⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg2_ps.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 4 页
字号:
    if (mpeg2ps_stream_read_next_pes_buffer(sptr) == 0) {      return 0;    }  }  sptr->frame_len = hdr.framesize;  sptr->pes_buffer_on += diff;  if (diff == 0 && started_new_pes) {    // we might have a new PTS - but it's not here  } else {    sptr->frame_ts = sptr->next_pes_ts;    sptr->next_pes_ts.have_dts = sptr->next_pes_ts.have_pts = 0;  }  while (sptr->pes_buffer_size - sptr->pes_buffer_on < sptr->frame_len) {#if 0    printf("don't have enough - on %u size %u %u %u\n", sptr->pes_buffer_on, 	   sptr->pes_buffer_size,	   sptr->pes_buffer_size - sptr->pes_buffer_on, 	   sptr->frame_len);#endif    if (mpeg2ps_stream_read_next_pes_buffer(sptr) == 0) {      return 0;    }  }  sptr->have_frame_loaded = 1;  return 1;}static Bool mpeg2ps_stream_find_mp3_frame (mpeg2ps_stream_t *sptr){  u32 diff, hdr;  Bool started_new_pes = 0;  sptr->frame_ts = sptr->next_pes_ts;  if (sptr->pes_buffer_size <= sptr->pes_buffer_on + 4) {    if (sptr->pes_buffer_size != sptr->pes_buffer_on)      started_new_pes = 1;    if (mpeg2ps_stream_read_next_pes_buffer(sptr) == 0) {      return 0;    }  }  while ((hdr=gf_mp3_get_next_header_mem((char*)sptr->pes_buffer + sptr->pes_buffer_on,			sptr->pes_buffer_size - sptr->pes_buffer_on,			&diff) ) == 0) {    // don't have frame    if (sptr->pes_buffer_size > 3) {      if (sptr->pes_buffer_on != sptr->pes_buffer_size) {	sptr->pes_buffer_on = sptr->pes_buffer_size - 3;      }      started_new_pes = 1; // we have left over bytes...    } else {      sptr->pes_buffer_on = sptr->pes_buffer_size;    }    if (mpeg2ps_stream_read_next_pes_buffer(sptr) == 0) {      return 0;    }  }  // have frame.  sptr->frame_len = gf_mp3_frame_size(hdr);  sptr->pes_buffer_on += diff;  if (diff == 0 && started_new_pes) {  } else {    sptr->frame_ts = sptr->next_pes_ts;    sptr->next_pes_ts.have_dts = sptr->next_pes_ts.have_pts = 0;  }  while (sptr->pes_buffer_size - sptr->pes_buffer_on < sptr->frame_len) {#if 0    printf("don't have enough - on %u size %u %u %u\n", sptr->pes_buffer_on, 	   sptr->pes_buffer_size,	   sptr->pes_buffer_size - sptr->pes_buffer_on, 	   sptr->frame_len);#endif    if (mpeg2ps_stream_read_next_pes_buffer(sptr) == 0) {      return 0;    }  }  sptr->have_frame_loaded = 1;  return 1;}/* * mpeg2ps_stream_read_frame.  read the correct frame based on stream type. * advance_pointers is 0 when we want to use the data */static Bool mpeg2ps_stream_read_frame (mpeg2ps_stream_t *sptr,				       u8 **buffer, 				       u32 *buflen,				       Bool advance_pointers){  //  Bool done = 0;  if (sptr->is_video) {    if (mpeg2ps_stream_find_mpeg_video_frame(sptr)) {      *buffer = sptr->pes_buffer + sptr->pes_buffer_on;      *buflen = sptr->frame_len;      if (advance_pointers) {	sptr->pes_buffer_on += sptr->frame_len;      }      return 1;    }    return 0;  } else if (sptr->m_stream_id == 0xbd) {    // would need to handle LPCM here    if (mpeg2ps_stream_find_ac3_frame(sptr)) {      *buffer = sptr->pes_buffer + sptr->pes_buffer_on;      *buflen = sptr->frame_len;      if (advance_pointers)	sptr->pes_buffer_on += sptr->frame_len;      return 1;    }    return 0;  } else if (mpeg2ps_stream_find_mp3_frame(sptr)) {    *buffer = sptr->pes_buffer + sptr->pes_buffer_on;    *buflen = sptr->frame_len;    if (advance_pointers)      sptr->pes_buffer_on += sptr->frame_len;    return 1;  }  return 0;}/* * get_info_from_frame - we have a frame, get the info from it. */static void get_info_from_frame (mpeg2ps_stream_t *sptr, 				 u8 *buffer, 				 u32 buflen){  if (sptr->is_video) {    if (MPEG12_ParseSeqHdr(buffer, buflen,			       &sptr->have_mpeg2,			       &sptr->h,			       &sptr->w,			       &sptr->frame_rate,			       &sptr->bit_rate,			       &sptr->par) < 0) {      sptr->m_stream_id = 0;      sptr->m_fd = FDNULL;    }    sptr->ticks_per_frame = (u64)(90000.0 / sptr->frame_rate);    return;  }  if (sptr->m_stream_id >= 0xc0) {    // mpeg audio    u32 hdr = GF_4CC(buffer[0],buffer[1],buffer[2],buffer[3]);    sptr->channels = gf_mp3_num_channels(hdr);    sptr->freq = gf_mp3_sampling_rate(hdr);    sptr->samples_per_frame = gf_mp3_window_size(hdr);    sptr->bitrate = gf_mp3_bit_rate(hdr) * 1000; // give bps, not kbps    sptr->layer = gf_mp3_layer(hdr);  } else if (sptr->m_stream_id == 0xbd) {    if (sptr->m_substream_id >= 0xa0) {      // PCM - ???    } else if (sptr->m_substream_id >= 0x80) {		u32 pos;		GF_AC3Header hdr;      gf_ac3_parser(buffer, buflen, &pos, &hdr);	  sptr->bitrate = hdr.bitrate;	  sptr->freq = hdr.sample_rate;	  sptr->channels = hdr.channels;      sptr->samples_per_frame = 256 * 6;    } else {      return;    }  } else {    return;  }}/* * clear_stream_buffer - called when we seek to clear out any data in  * the buffers */static void clear_stream_buffer (mpeg2ps_stream_t *sptr){  sptr->pes_buffer_on = sptr->pes_buffer_size = 0;  sptr->frame_len = 0;  sptr->have_frame_loaded = 0;  sptr->next_pes_ts.have_dts = sptr->next_pes_ts.have_pts = 0;  sptr->frame_ts.have_dts = sptr->frame_ts.have_pts = 0;}/* * convert_to_msec - convert ts (at 90000) to msec, based on base_ts and * frames_since_last_ts. */static u64 convert_ts (mpeg2ps_stream_t *sptr,			    mpeg2ps_ts_type_t ts_type,			    u64 ts,			    u64 base_ts,			    u32 frames_since_ts){  u64 ret, calc;  ret = ts - base_ts;  if (sptr->is_video) {    // video    ret += frames_since_ts * sptr->ticks_per_frame;  } else {    // audio    calc = (frames_since_ts * 90000 * sptr->samples_per_frame) / sptr->freq;    ret += calc;  }  if (ts_type == TS_MSEC)    ret /= (u64) (90); // * 1000 / 90000  return ret;}/* * find_stream_from_id - given the stream, get the sptr. * only used in inital set up, really.  APIs use index into  * video_streams and audio_streams arrays. */static mpeg2ps_stream_t *find_stream_from_id (mpeg2ps_t *ps, 					      u8 stream_id, 					      u8 substream){  u8 ix;  if (stream_id >= 0xe0) {    for (ix = 0; ix < ps->video_cnt; ix++) {      if (ps->video_streams[ix]->m_stream_id == stream_id) {	return ps->video_streams[ix];      }    }  } else {    for (ix = 0; ix < ps->audio_cnt; ix++) {      if (ps->audio_streams[ix]->m_stream_id == stream_id &&	  (stream_id != 0xbd ||	   substream == ps->audio_streams[ix]->m_substream_id)) {	return ps->audio_streams[ix];      }    }  }  return NULL;}/* * add_stream - add a new stream */static Bool add_stream (mpeg2ps_t *ps,			u8 stream_id,			u8 substream,			s64 first_loc,			mpeg2ps_ts_t *ts){  mpeg2ps_stream_t *sptr;    sptr = find_stream_from_id(ps, stream_id, substream);  if (sptr != NULL) return 0;  // need to add  sptr = mpeg2ps_stream_create(stream_id, substream);  sptr->first_pes_loc = first_loc;  if (ts == NULL ||      (ts->have_dts == 0 && ts->have_pts == 0)) {    sptr->first_pes_has_dts = 0;  } else {    sptr->start_dts = ts->have_dts ? ts->dts : ts->pts;    sptr->first_pes_has_dts = 1;  }  if (sptr->is_video) {    // can't be more than 16 - e0 to ef...    ps->video_streams[ps->video_cnt] = sptr;    ps->video_cnt++;  } else {    if (ps->audio_cnt >= 32) {      mpeg2ps_stream_destroy(sptr);      return 0;    }    ps->audio_streams[ps->audio_cnt] = sptr;    ps->audio_cnt++;  }  return 1;}static void check_fd_for_stream (mpeg2ps_t *ps, 			  mpeg2ps_stream_t *sptr){  if (sptr->m_fd != FDNULL) return;  sptr->m_fd = file_open(ps->filename);}/* * advance_frame - when we're reading frames, this indicates that we're * done.  We will call this when we read a frame, but not when we * seek.  It allows us to leave the last frame we're seeking in the * buffer */static void advance_frame (mpeg2ps_stream_t *sptr){  sptr->pes_buffer_on += sptr->frame_len;  sptr->have_frame_loaded = 0;  if (sptr->frame_ts.have_dts || sptr->frame_ts.have_pts) {    if (sptr->frame_ts.have_dts)       sptr->last_ts = sptr->frame_ts.dts;    else      sptr->last_ts = sptr->frame_ts.pts;    sptr->frames_since_last_ts = 0;  } else {    sptr->frames_since_last_ts++;  }}/* * get_info_for_all_streams - loop through found streams - read an * figure out the info */static void get_info_for_all_streams (mpeg2ps_t *ps){  u8 stream_ix, max_ix, av;  mpeg2ps_stream_t *sptr;  u8 *buffer;  u32 buflen;	file_seek_to(ps->fd, 0);  // av will be 0 for video streams, 1 for audio streams  // av is just so I don't have to dup a lot of code that does the  // same thing.  for (av = 0; av < 2; av++) {    if (av == 0) max_ix = ps->video_cnt;    else max_ix = ps->audio_cnt;    for (stream_ix = 0; stream_ix < max_ix; stream_ix++) {      if (av == 0) sptr = ps->video_streams[stream_ix];      else sptr = ps->audio_streams[stream_ix];      // we don't open a seperate file descriptor yet (only when they      // start reading or seeking).  Use the one from the ps.      sptr->m_fd = ps->fd; // for now      clear_stream_buffer(sptr);      if (mpeg2ps_stream_read_frame(sptr,				    &buffer, 				    &buflen,				    0) == 0) {	sptr->m_stream_id = 0;	sptr->m_fd = FDNULL;	continue;      }      get_info_from_frame(sptr, buffer, buflen);      // here - if (sptr->first_pes_has_dts == 0) should be processed      if (sptr->first_pes_has_dts == 0) {	u32 frames_from_beg = 0;	Bool have_frame;	do {	  advance_frame(sptr);	  have_frame = 	    mpeg2ps_stream_read_frame(sptr, &buffer, &buflen, 0);	  frames_from_beg++;	} while (have_frame && 		 sptr->frame_ts.have_dts == 0 && 		 sptr->frame_ts.have_pts == 0 && 		 frames_from_beg < 1000);	if (have_frame == 0 ||	    (sptr->frame_ts.have_dts == 0 &&	     sptr->frame_ts.have_pts == 0)) {	} else {	  sptr->start_dts = sptr->frame_ts.have_dts ? sptr->frame_ts.dts : 	    sptr->frame_ts.pts;	  if (sptr->is_video) {	    sptr->start_dts -= frames_from_beg * sptr->ticks_per_frame;	  } else {	    u64 conv;	    conv = sptr->samples_per_frame * 90000;	    conv /= (u64)sptr->freq;	    sptr->start_dts -= conv;	  }	}      }      clear_stream_buffer(sptr);      sptr->m_fd = FDNULL;    }  }}/* * mpeg2ps_scan_file - read file, grabbing all the information that * we can out of it (what streams exist, timing, etc). */static void mpeg2ps_scan_file (mpeg2ps_t *ps){  u8 stream_id, stream_ix, substream, av_ix, max_cnt;  u16 pes_len, pes_left;  mpeg2ps_ts_t ts;  s64 loc, first_video_loc = 0, first_audio_loc = 0;  s64 check, orig_check;  mpeg2ps_stream_t *sptr;  Bool valid_stream;  u8 *buffer;  u32 buflen;  Bool have_ts;  ps->end_loc = file_size(ps->fd);  orig_check = check = MAX(ps->end_loc / 50, 200 * 1024);  /*   * This part reads and finds the streams.  We check up until we   * find audio and video plus a little, with a max of either 200K or   * the file size / 50   */  loc = 0;  while (read_to_next_pes_header(ps->fd, &stream_id, &pes_len) && 	 loc < check) {    pes_left = pes_len;    if (stream_id >= 0xbd && stream_id < 0xf0) {      loc = file_location(ps->fd) - 6;      if (read_pes_header_data(ps->fd, 			       pes_len, 			       &pes_left, 			       &have_ts, 			       &ts) == 0) {	return;      }      valid_stream = 0;      substream = 0;      if (stream_id == 0xbd) {	if (file_read_bytes(ps->fd, &substream, 1) == 0) {	  return;	}	pes_left--; // remove byte we just read	if ((substream >= 0x80 && substream < 0x90) ||	    (substream >= 0xa0 && substream < 0xb0)){	  valid_stream = 1;	}      } else if (stream_id >= 0xc0 &&		 stream_id <= 0xef) {	// audio and video	valid_stream = 1;      }      if (valid_stream) {	if (add_stream(ps, stream_id, substream, loc, &ts)) {	  // added	  if (stream_id >= 0xe0) {	    if (ps->video_cnt == 1) {	      first_video_loc = loc;	    }	  } else if (ps->audio_cnt == 1) {	    first_audio_loc = loc;	  }	  if (ps->audio_cnt > 0 && ps->video_cnt > 0) {	    s64 diff;	    if (first_audio_loc > first_video_loc) 	      diff = first_audio_loc - first_video_loc;	    else 	      diff = first_video_loc - first_audio_loc;	    diff *= 2;	    diff += first_video_loc;	    if (diff < check) {	      check = diff;	    }	  }	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -