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

📄 mpeg2_ps.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 4 页
字号:
      }    }    file_skip_bytes(ps->fd, pes_left);  }  if (ps->video_cnt == 0 && ps->audio_cnt == 0) {    return;  }  /*   * Now, we go to close to the end, and try to find the last    * dts that we can   */  //  printf("to end "X64"\n", end - orig_check);  file_seek_to(ps->fd, ps->end_loc - orig_check);  while (read_to_next_pes_header(ps->fd, &stream_id, &pes_len)) {    loc = file_location(ps->fd) - 6;    if (stream_id == 0xbd || (stream_id >= 0xc0 && stream_id < 0xf0)) {      if (read_pes_header_data(ps->fd, 			       pes_len, 			       &pes_left, 			       &have_ts, 			       &ts) == 0) {	return;      }      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))) {	  file_skip_bytes(ps->fd, pes_left);	  continue;	}      } else {	substream = 0;      }      sptr = find_stream_from_id(ps, stream_id, substream);      if (sptr == NULL) {	add_stream(ps, stream_id, substream, 0, NULL);	sptr = find_stream_from_id(ps, stream_id, substream);      }      if (sptr != NULL && have_ts) {	sptr->end_dts = ts.have_dts ? ts.dts : ts.pts;	sptr->end_dts_loc = loc;      }#if 0      printf("loc "X64" stream %x %x", loc, stream_id, substream);      if (ts.have_pts) printf(" pts "U64, ts.pts);      if (ts.have_dts) printf(" dts "U64, ts.dts);      printf("\n");#endif      file_skip_bytes(ps->fd, pes_left);    }  }  /*   * Now, get the info for all streams, so we can use it again   * we could do this before the above, I suppose   */  get_info_for_all_streams(ps);  ps->first_dts = (u64) -1;  /*   * we need to find the earliest start pts - we use that to calc   * the rest of the timing, so we're 0 based.   */  for (av_ix = 0; av_ix < 2; av_ix++) {    if (av_ix == 0) max_cnt = ps->video_cnt;    else max_cnt = ps->audio_cnt;    for (stream_ix = 0; stream_ix < max_cnt; stream_ix++) {      sptr = av_ix == 0 ? ps->video_streams[stream_ix] :	ps->audio_streams[stream_ix];      if (sptr != NULL && sptr->start_dts < ps->first_dts) {	ps->first_dts = sptr->start_dts;      }    }  }  /*   * Now, for each thread, we'll start at the last pts location, and   * read the number of frames.  This will give us a max time   */  for (av_ix = 0; av_ix < 2; av_ix++) {    if (av_ix == 0) max_cnt = ps->video_cnt;    else max_cnt = ps->audio_cnt;    for (stream_ix = 0; stream_ix < max_cnt; stream_ix++) {      u32 frame_cnt_since_last;	  sptr = av_ix == 0 ? ps->video_streams[stream_ix] :	ps->audio_streams[stream_ix];            // pick up here - find the final time...      if (sptr->end_dts_loc != 0) {	file_seek_to(ps->fd, sptr->end_dts_loc);	sptr->m_fd = ps->fd;	frame_cnt_since_last = 0;	clear_stream_buffer(sptr);	while (mpeg2ps_stream_read_frame(sptr,					 &buffer, 					 &buflen,					 1)) {	  frame_cnt_since_last++;	}	sptr->m_fd = FDNULL;	clear_stream_buffer(sptr);	ps->max_time = MAX(ps->max_time, 			   convert_ts(sptr, 				      TS_MSEC,				      sptr->end_dts,				      ps->first_dts, 				      frame_cnt_since_last));      }    }  }  ps->max_dts = (ps->max_time * 90) + ps->first_dts;  file_seek_to(ps->fd, 0);}/************************************************************************* * API routines *************************************************************************/u64 mpeg2ps_get_max_time_msec (mpeg2ps_t *ps) {  return ps->max_time;}u32 mpeg2ps_get_video_stream_count (mpeg2ps_t *ps){  return ps->video_cnt;}#define NUM_ELEMENTS_IN_ARRAY(name) ((sizeof((name))) / (sizeof(*(name))))// routine to check stream number passed.static Bool invalid_video_streamno (mpeg2ps_t *ps, u32 streamno){  if (streamno >= NUM_ELEMENTS_IN_ARRAY(ps->video_streams)) return 1;  if (ps->video_streams[streamno] == NULL) return 1;  return 0;}const char *mpeg2ps_get_video_stream_name (mpeg2ps_t *ps, u32 streamno){  if (invalid_video_streamno(ps, streamno)) {    return 0;  }  if (ps->video_streams[streamno]->have_mpeg2) {    return "Mpeg-2";  }  return "Mpeg-1";}mpeg2ps_video_type_t mpeg2ps_get_video_stream_type (mpeg2ps_t *ps, 						    u32 streamno){  if (invalid_video_streamno(ps, streamno)) {    return MPEG_VIDEO_UNKNOWN;  }  return ps->video_streams[streamno]->have_mpeg2 ? MPEG_VIDEO_MPEG2 : MPEG_VIDEO_MPEG1;}u32 mpeg2ps_get_video_stream_width (mpeg2ps_t *ps, u32 streamno){  if (invalid_video_streamno(ps, streamno)) {    return 0;  }  return ps->video_streams[streamno]->w;}u32 mpeg2ps_get_video_stream_height (mpeg2ps_t *ps, u32 streamno){  if (invalid_video_streamno(ps, streamno)) {    return 0;  }  return ps->video_streams[streamno]->h;}u32 mpeg2ps_get_video_stream_aspect_ratio (mpeg2ps_t *ps, u32 streamno){  if (invalid_video_streamno(ps, streamno)) {    return 0;  }  return ps->video_streams[streamno]->par;}Double mpeg2ps_get_video_stream_bitrate (mpeg2ps_t *ps, u32 streamno){  if (invalid_video_streamno(ps, streamno)) {    return 0;  }  return ps->video_streams[streamno]->bit_rate;}Double mpeg2ps_get_video_stream_framerate (mpeg2ps_t *ps, u32 streamno){  if (invalid_video_streamno(ps, streamno)) {    return 0;  }  return ps->video_streams[streamno]->frame_rate;}static Bool invalid_audio_streamno (mpeg2ps_t *ps, u32 streamno){  if (streamno >= NUM_ELEMENTS_IN_ARRAY(ps->audio_streams)) return 1;  if (ps->audio_streams[streamno] == NULL) return 1;  return 0;}u32 mpeg2ps_get_audio_stream_count (mpeg2ps_t *ps){  return ps->audio_cnt;}const char *mpeg2ps_get_audio_stream_name (mpeg2ps_t *ps, 					   u32 streamno){  if (invalid_audio_streamno(ps, streamno)) {    return "none";  }  if (ps->audio_streams[streamno]->m_stream_id >= 0xc0) {    switch (ps->audio_streams[streamno]->layer) {    case 1: return "MP1";    case 2: return "MP2";    case 3: return "MP3";    }    return "unknown mpeg layer";  }  if (ps->audio_streams[streamno]->m_substream_id >= 0x80 &&      ps->audio_streams[streamno]->m_substream_id < 0x90)    return "AC3";  return "LPCM";}mpeg2ps_audio_type_t mpeg2ps_get_audio_stream_type (mpeg2ps_t *ps, 						    u32 streamno){  if (invalid_audio_streamno(ps, streamno)) {    return MPEG_AUDIO_UNKNOWN;  }  if (ps->audio_streams[streamno]->m_stream_id >= 0xc0) {    return MPEG_AUDIO_MPEG;  }  if (ps->audio_streams[streamno]->m_substream_id >= 0x80 &&      ps->audio_streams[streamno]->m_substream_id < 0x90)    return MPEG_AUDIO_AC3;  return MPEG_AUDIO_LPCM;}u32 mpeg2ps_get_audio_stream_sample_freq (mpeg2ps_t *ps, u32 streamno){  if (invalid_audio_streamno(ps, streamno)) {    return 0;  }  return ps->audio_streams[streamno]->freq;}u32 mpeg2ps_get_audio_stream_channels (mpeg2ps_t *ps, u32 streamno){  if (invalid_audio_streamno(ps, streamno)) {    return 0;  }  return ps->audio_streams[streamno]->channels;}u32 mpeg2ps_get_audio_stream_bitrate (mpeg2ps_t *ps, u32 streamno){  if (invalid_audio_streamno(ps, streamno)) {    return 0;  }  return ps->audio_streams[streamno]->bitrate;}mpeg2ps_t *mpeg2ps_init (const char *filename){  mpeg2ps_t *ps;  GF_SAFEALLOC(ps, mpeg2ps_t);  if (ps == NULL) {    return NULL;  }  memset(ps, 0, sizeof(*ps));  ps->fd = file_open(filename);  if (file_okay(ps->fd) == 0) {    free(ps);    return NULL;  }    ps->filename = strdup(filename);  mpeg2ps_scan_file(ps);  if (ps->video_cnt == 0 && ps->audio_cnt == 0) {    mpeg2ps_close(ps);    return NULL;  }  return ps;}void mpeg2ps_close (mpeg2ps_t *ps){  u32 ix;  if (ps == NULL) return;  for (ix = 0; ix < ps->video_cnt; ix++) {    mpeg2ps_stream_destroy(ps->video_streams[ix]);    ps->video_streams[ix] = NULL;  }  for (ix = 0; ix < ps->audio_cnt; ix++) {    mpeg2ps_stream_destroy(ps->audio_streams[ix]);    ps->audio_streams[ix] = NULL;  }  if (ps->filename) free(ps->filename);  if (ps->fd) file_close(ps->fd);  free(ps);}/* * check_fd_for_stream will make sure we have a fd for the stream we're * trying to read - we use a different fd for each stream *//* * stream_convert_frame_ts_to_msec - given a "read" frame, we'll * calculate the msec and freq timestamps.  This can be called more * than 1 time, if needed, without changing any variables, such as * frames_since_last_ts, which gets updated in advance_frame */static u64 stream_convert_frame_ts_to_msec (mpeg2ps_stream_t *sptr, 						 mpeg2ps_ts_type_t ts_type,						 u64 base_dts,						 u32 *freq_ts){  u64 calc_ts;  u32 frames_since_last = 0;  u64 freq_conv;  calc_ts = sptr->last_ts;  if (sptr->frame_ts.have_dts) calc_ts = sptr->frame_ts.dts;  else if (sptr->frame_ts.have_pts) calc_ts = sptr->frame_ts.dts;  else frames_since_last = sptr->frames_since_last_ts + 1;  if (freq_ts != NULL) {    freq_conv = calc_ts - base_dts;    freq_conv *= sptr->freq;    freq_conv /= 90000;    freq_conv += frames_since_last * sptr->samples_per_frame;    *freq_ts = (u32) (freq_conv & 0xffffffff);  }  return convert_ts(sptr, ts_type, calc_ts, base_dts, frames_since_last);}/* * mpeg2ps_get_video_frame - gets the next frame */    Bool mpeg2ps_get_video_frame(mpeg2ps_t *ps, u32 streamno,			     u8 **buffer, 			     u32 *buflen,			     u8 *frame_type,			     mpeg2ps_ts_type_t ts_type,			     u64 *timestamp){  mpeg2ps_stream_t *sptr;  if (invalid_video_streamno(ps, streamno)) return 0;  sptr = ps->video_streams[streamno];  check_fd_for_stream(ps, sptr);  if (sptr->have_frame_loaded == 0) {    // if we don't have the frame in the buffer (like after a seek),     // read the next frame    if (mpeg2ps_stream_find_mpeg_video_frame(sptr) == 0) {      return 0;    }  }  *buffer = sptr->pes_buffer + sptr->pes_buffer_on;  *buflen = sptr->frame_len;  // determine frame type  if (frame_type != NULL) {    *frame_type = MPEG12_PictHdrType(sptr->pes_buffer + 					 sptr->pict_header_offset);  }  // and the timestamp  if (timestamp != NULL) {    *timestamp = stream_convert_frame_ts_to_msec(sptr, ts_type, 						 ps->first_dts, NULL);  }  // finally, indicate that we read this frame - get ready for the next one.  advance_frame(sptr);  return 1;}// see above comments      Bool mpeg2ps_get_audio_frame(mpeg2ps_t *ps, u32 streamno,			     u8 **buffer, 			     u32 *buflen,			     mpeg2ps_ts_type_t ts_type,			     u32 *freq_timestamp,			     u64 *timestamp){  mpeg2ps_stream_t *sptr;  u64 ts;  if (invalid_audio_streamno(ps, streamno)) return 0;  sptr = ps->audio_streams[streamno];  check_fd_for_stream(ps, sptr);  if (sptr->have_frame_loaded == 0) {    if (mpeg2ps_stream_read_frame(sptr, buffer, buflen, 0) == 0)       return 0;  }     if (timestamp != NULL || freq_timestamp != NULL) {    ts = stream_convert_frame_ts_to_msec(sptr, 					 ts_type,					 ps->first_dts,					 freq_timestamp);    if (timestamp != NULL) {      *timestamp = ts;    }  }  advance_frame(sptr);  return 1;}s64 mpeg2ps_get_ps_size(mpeg2ps_t *ps){	return file_size(ps->fd);}s64 mpeg2ps_get_video_pos(mpeg2ps_t *ps, u32 streamno){  if (invalid_video_streamno(ps, streamno)) return 0;  return gf_f64_tell(ps->video_streams[streamno]->m_fd);}s64 mpeg2ps_get_audio_pos(mpeg2ps_t *ps, u32 streamno){  if (invalid_audio_streamno(ps, streamno)) return 0;  return gf_f64_tell(ps->audio_streams[streamno]->m_fd);}#endif

⌨️ 快捷键说明

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