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

📄 mpeg2_ps.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 4 页
字号:
  }  file_skip_bytes(fd, 13 - read_from_start);  file_read_bytes(fd, &readbyte, 1);  stuffed = readbyte & 0x7;  file_skip_bytes(fd, stuffed);}/* * find_pack_start * look for the pack start code in the file - read 512 bytes at a time,  * searching for that code. * Note: we may also be okay looking for >= 00 00 01 bb */static Bool find_pack_start (FILE *fd, 			     u8 *saved,			     u32 len){  u8 buffer[512];  u32 buffer_on = 0, new_offset, scode;  memcpy(buffer, saved, len);  if (file_read_bytes(fd, buffer + len, sizeof(buffer) - len) == 0) {    return 0;  }  while (1) {    if (MPEG12_FindNextStartCode(buffer + buffer_on,				 sizeof(buffer) - buffer_on, 				 &new_offset, 				 &scode) >= 0) {      buffer_on += new_offset;      if (scode == MPEG2_PS_PACKSTART) {	file_skip_bytes(fd, buffer_on - 512); // go back to header	return 1;      }      buffer_on += 1;    } else {      len = 0;      if (buffer[sizeof(buffer) - 3] == 0 &&	  buffer[sizeof(buffer) - 2] == 0 &&	  buffer[sizeof(buffer) - 1] == 1) {	buffer[0] = 0;	buffer[1] = 0;	buffer[2] = 1;	len = 3;      } else if (*(u16 *)(buffer + sizeof(buffer) - 2) == 0) {	buffer[0] = 0;	buffer[1] = 0;	len = 2;      } else if (buffer[sizeof(buffer) - 1] == 0) {	buffer[0] = 0;	len = 1;      }      if (file_read_bytes(fd, buffer + len, sizeof(buffer) - len) == 0) {	return 0;      }      buffer_on = 0;    }  }  return 0;}/* * copy_bytes_to_pes_buffer - read pes_len bytes into the buffer,  * adjusting it if we need it */static void copy_bytes_to_pes_buffer (mpeg2ps_stream_t *sptr, 			       u16 pes_len){  u32 to_move;  if (sptr->pes_buffer_size + pes_len > sptr->pes_buffer_size_max) {    // if no room in the buffer, we'll move it - otherwise, just fill    // note - we might want a better strategy about moving the buffer -     // right now, we might be moving a number of bytes if we have a large    // followed by large frame.    to_move = sptr->pes_buffer_size - sptr->pes_buffer_on;    memmove(sptr->pes_buffer,	    sptr->pes_buffer + sptr->pes_buffer_on,	    to_move);    sptr->pes_buffer_size = to_move;    sptr->pes_buffer_on = 0;    //printf("moving %d bytes\n", to_move);    if (to_move + pes_len > sptr->pes_buffer_size_max) {      sptr->pes_buffer = (u8 *)realloc(sptr->pes_buffer, 					    to_move + pes_len + 2048);      sptr->pes_buffer_size_max = to_move + pes_len + 2048;    }  }  file_read_bytes(sptr->m_fd, sptr->pes_buffer + sptr->pes_buffer_size, pes_len);  sptr->pes_buffer_size += pes_len;#if 0  printf("copying %u bytes - on %u size %u\n",	 pes_len, sptr->pes_buffer_on, sptr->pes_buffer_size);#endif}/* * read_to_next_pes_header - read the file, look for the next valid * pes header.  We will skip over PACK headers, but not over any of the * headers listed in 13818-1, table 2-18 - basically, anything with the * 00 00 01 and the next byte > 0xbb. * We return the pes len to read, and the "next byte" */static Bool read_to_next_pes_header (FILE *fd, 				     u8 *stream_id,				     u16 *pes_len){  u32 hdr;  u8 local[6];  while (1) {    // read the pes header    if (file_read_bytes(fd, local, 6) == 0) {      return 0;    }    hdr = convert32(local);    // if we're not a 00 00 01, read until we get the next pack start    // we might want to also read until next PES - look into that.    if (((hdr & MPEG2_PS_START_MASK) != MPEG2_PS_START) ||	(hdr < MPEG2_PS_END)) {      if (find_pack_start(fd, local, 6) == 0) {	return 0;      }      continue;    }    if (hdr == MPEG2_PS_PACKSTART) {      // pack start code - we can skip down      adv_past_pack_hdr(fd, local, 6);      continue;    }    if (hdr == MPEG2_PS_END) {      file_skip_bytes(fd, -2);      continue;    }    // we should have a valid stream and pes_len here...    *stream_id = hdr & 0xff;    *pes_len = convert16(local + 4);#if 0    printf("loc: "X64" %x len %u\n", file_location(fd) - 6,	   local[3],	   *pes_len);#endif    return 1;  }  return 0;}/* * read_pes_header_data * this should read past the pes header for the audio and video streams * it will store the timestamps if it reads them */static Bool read_pes_header_data (FILE *fd, 				  u16 orig_pes_len,				  u16 *pes_left,				  Bool *have_ts,				  mpeg2ps_ts_t *ts){  u16 pes_len = orig_pes_len;  u8 local[10];  u32 hdr_len;  ts->have_pts = 0;  ts->have_dts = 0;  *have_ts = 0;  if (file_read_bytes(fd, local, 1) == 0) {    return 0;  }  pes_len--; // remove this first byte from length  while (*local == 0xff) {    if (file_read_bytes(fd, local, 1) == 0) {      return 0;    }    pes_len--;    if (pes_len == 0) {      *pes_left = 0;      return 1;    }  }  if ((*local & 0xc0) == 0x40) {     // buffer scale & size    file_skip_bytes(fd, 1);    if (file_read_bytes(fd, local, 1) == 0) {      return 0;    }    pes_len -= 2;  }  if ((*local & 0xf0) == 0x20) {    // mpeg-1 with pts    if (file_read_bytes(fd, local + 1, 4) == 0) {      return 0;    }    ts->have_pts = 1;    ts->pts = ts->dts = read_pts(local);    //printf("mpeg1 pts "U64"\n", ts->pts);    *have_ts = 1;    pes_len -= 4;  } else if ((*local & 0xf0) == 0x30) {    // have mpeg 1 pts and dts    if (file_read_bytes(fd, local + 1, 9) == 0) {      return 0;    }    ts->have_pts = 1;    ts->have_dts = 1;    *have_ts = 1;    ts->pts = read_pts(local);    ts->dts = read_pts(local + 5);    pes_len -= 9;  } else if ((*local & 0xc0) == 0x80) {    // mpeg2 pes header  - we're pointing at the flags field now    if (file_read_bytes(fd, local + 1, 2) == 0) {      return 0;    }    hdr_len = local[2];    pes_len -= hdr_len + 2; // first byte removed already    if ((local[1] & 0xc0) == 0x80) {      // just pts      ts->have_pts = 1;      file_read_bytes(fd, local, 5);      ts->pts = ts->dts = read_pts(local);      *have_ts = 1;      hdr_len -= 5;    } else if ((local[1] & 0xc0) == 0xc0) {      // pts and dts      ts->have_pts = 1;      ts->have_dts = 1;      *have_ts = 1;      file_read_bytes(fd, local, 10);      ts->pts = read_pts(local);      ts->dts = read_pts(local  + 5);          hdr_len -= 10;    }    file_skip_bytes(fd, hdr_len);  } else if (*local != 0xf) {    file_skip_bytes(fd, pes_len);    pes_len = 0;  }   *pes_left = pes_len;  return 1;}static Bool search_for_next_pes_header (mpeg2ps_stream_t *sptr, 					u16 *pes_len,					Bool *have_ts, 					s64 *found_loc){  u8 stream_id;  u8 local;  s64 loc;  while (1) {    // this will read until we find the next pes.  We don't know if the    // stream matches - this will read over pack headers    if (read_to_next_pes_header(sptr->m_fd, &stream_id, pes_len) == 0) {      return 0;    }    if (stream_id != sptr->m_stream_id) {      file_skip_bytes(sptr->m_fd, *pes_len);      continue;    }    loc = file_location(sptr->m_fd) - 6;     // advance past header, reading pts    if (read_pes_header_data(sptr->m_fd, 			     *pes_len, 			     pes_len, 			     have_ts, 			     &sptr->next_pes_ts) == 0) {      return 0;    }    // If we're looking at a private stream, make sure that the sub-stream    // matches.    if (sptr->m_stream_id == 0xbd) {      // ac3 or pcm      file_read_bytes(sptr->m_fd, &local, 1);      *pes_len -= 1;      if (local != sptr->m_substream_id) {	file_skip_bytes(sptr->m_fd, *pes_len);	continue; // skip to the next one      }      *pes_len -= 3;      file_skip_bytes(sptr->m_fd, 3); // 4 bytes - we don't need now...      // we need more here...    }    if (have_ts) {      mpeg2ps_record_pts(sptr, loc, &sptr->next_pes_ts);    }    if (found_loc != NULL) *found_loc = loc;    return 1;  }  return 0;}/* * mpeg2ps_stream_read_next_pes_buffer - for the given stream,  * go forward in the file until the next PES for the stream is read.  Read * the header (pts, dts), and read the data into the pes_buffer pointer */static Bool mpeg2ps_stream_read_next_pes_buffer (mpeg2ps_stream_t *sptr){  u16 pes_len;  Bool have_ts;  if (search_for_next_pes_header(sptr, &pes_len, &have_ts, NULL) == 0) {    return 0;  }  copy_bytes_to_pes_buffer(sptr, pes_len);  return 1;}/*************************************************************************** * Frame reading routine.  For each stream, the fd's should be different. * we will read from the pes stream, and save it in the stream's pes buffer. * This will give us raw data that we can search through for frame headers,  * and the like.  We shouldn't read more than we need - when we need to read,  * we'll put the whole next pes buffer in the buffer * * Audio routines are of the format: *   look for header *   determine length *   make sure length is in buffer * * Video routines *   look for start header (GOP, SEQ, Picture) *   look for pict header *   look for next start (END, GOP, SEQ, Picture) *    ***************************************************************************/#define IS_MPEG_START(a) ((a) == 0xb3 || (a) == 0x00 || (a) == 0xb8)static Bool mpeg2ps_stream_find_mpeg_video_frame (mpeg2ps_stream_t *sptr){  u32 offset, scode;  Bool have_pict;  Bool started_new_pes = 0;  u32 start;  /*   * First thing - determine if we have enough bytes to read the header.   * if we do, we have the correct timestamp.  If not, we read the new   * pes, so we'd want to use the timestamp we read.   */  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 (MPEG12_FindNextStartCode(sptr->pes_buffer + sptr->pes_buffer_on, 				  sptr->pes_buffer_size - sptr->pes_buffer_on,				  &offset,				  &scode) < 0 ||	 (!IS_MPEG_START(scode & 0xff))) {    if (sptr->pes_buffer_size > 3)      sptr->pes_buffer_on = sptr->pes_buffer_size - 3;    else {      sptr->pes_buffer_on = sptr->pes_buffer_size;      started_new_pes = 1;    }    if (mpeg2ps_stream_read_next_pes_buffer(sptr) == 0) {      return 0;    }  }  sptr->pes_buffer_on += offset;  if (offset == 0 && started_new_pes) {    // nothing...  we've copied the timestamp already.  } else {    // we found the new start, but we pulled in a new pes header before    // starting.  So, we want to use the header that we read.    sptr->frame_ts = sptr->next_pes_ts; // set timestamp after searching    // clear timestamp indication    sptr->next_pes_ts.have_pts = sptr->next_pes_ts.have_dts = 0;  }#if 0  printf("header %x at %d\n", scode, sptr->pes_buffer_on);#endif  if (scode == MPEG12_PICTURE_START_CODE) {    sptr->pict_header_offset = sptr->pes_buffer_on;    have_pict = 1;  } else have_pict = 0;  start = 4 + sptr->pes_buffer_on;  while (1) {        if (MPEG12_FindNextStartCode(sptr->pes_buffer + start, 				 sptr->pes_buffer_size - start,				 &offset,				 &scode) < 0) {      start = sptr->pes_buffer_size - 3;      start -= sptr->pes_buffer_on;      sptr->pict_header_offset -= sptr->pes_buffer_on;      if (mpeg2ps_stream_read_next_pes_buffer(sptr) == 0) {	return 0;      }      start += sptr->pes_buffer_on;      sptr->pict_header_offset += sptr->pes_buffer_on;    } else {#if 0      printf("2header %x at %d\n", scode, start);#endif      start += offset;      if (have_pict == 0) {	if (scode == MPEG12_PICTURE_START_CODE) {	  have_pict = 1;	  sptr->pict_header_offset = start;	}      } else {	if (IS_MPEG_START(scode & 0xff) ||	    scode == MPEG12_SEQUENCE_END_START_CODE) {	  sptr->frame_len = start - sptr->pes_buffer_on;	  sptr->have_frame_loaded = 1;	  return 1;	}      }      start += 4;    }  }  return 0;}static Bool mpeg2ps_stream_find_ac3_frame (mpeg2ps_stream_t *sptr){  u32 diff;  GF_AC3Header hdr;  Bool started_new_pes = 0;  sptr->frame_ts = sptr->next_pes_ts; // set timestamp after searching  if (sptr->pes_buffer_size <= sptr->pes_buffer_on + 6) {    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 (gf_ac3_parser(sptr->pes_buffer + sptr->pes_buffer_on,			      sptr->pes_buffer_size - sptr->pes_buffer_on,			       &diff, 			      &hdr) <= 0) {    // don't have frame    if (sptr->pes_buffer_size > 6) {      sptr->pes_buffer_on = sptr->pes_buffer_size - 6;      started_new_pes = 1;    } else {      sptr->pes_buffer_on = sptr->pes_buffer_size;    }

⌨️ 快捷键说明

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