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

📄 mpeg2_ps.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is MPEG4IP. *  * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2004.  All Rights Reserved. *  * Contributor(s):  *		Bill May wmay@cisco.com *//* * mpeg2ps.c - parse program stream and vob files */#include "mpeg2_ps.h"static GFINLINE u16 convert16 (u8 *p){#ifdef GPAC_BIG_ENDIAN  return *(u16 *)p;#else  u16 val = p[0];  val <<= 8;  return (val | p[1]);#endif}static GFINLINE u32 convert32 (u8 *p){#ifdef GPAC_BIG_ENDIAN  return *(u32 *)p;#else  u32 val;  val = p[0]; val <<= 8;  val |= p[1]; val <<= 8;  val |= p[2]; val <<= 8;  val |= p[3];  return val;#endif}#define FDNULL 0/* * structure for passing timestamps around */typedef struct mpeg2ps_ts_t{  Bool have_pts;  Bool have_dts;  u64 pts;  u64 dts;} mpeg2ps_ts_t;typedef struct mpeg2ps_record_pes_t{  struct mpeg2ps_record_pes_t *next_rec;  u64 dts;  u64 location;} mpeg2ps_record_pes_t;s32 MPEG12_FindNextStartCode(unsigned char *pbuffer, u32 buflen, u32 *optr, u32 *scode){  u32 value;  u32 offset;  if (buflen < 4) return -1;  for (offset = 0; offset < buflen - 3; offset++, pbuffer++) {#ifdef GPAC_BIG_ENDIAN    value = *(u32 *)pbuffer >> 8;#else    value = (pbuffer[0] << 16) | (pbuffer[1] << 8) | (pbuffer[2] << 0); #endif    if (value == MPEG12_START_CODE_PREFIX) {      *optr = offset;      *scode = (value << 8) | pbuffer[3];      return 0;    }  }  return -1;}s32 MPEG12_FindNextSliceStart(unsigned char *pbuffer, u32 startoffset, u32 buflen, u32 *slice_offset){	u32 slicestart, code;	while (MPEG12_FindNextStartCode(pbuffer + startoffset, buflen - startoffset, &slicestart, &code) >= 0) {		if ((code >= MPEG12_SLICE_MIN_START) && (code <= MPEG12_SLICE_MAX_START)) {			*slice_offset = slicestart + startoffset;			return 0;		}		startoffset += slicestart + 4;	}	return -1;}#ifndef GPAC_READ_ONLY/* * information about reading a stream */typedef struct mpeg2ps_stream_t {  mpeg2ps_record_pes_t *record_first, *record_last;  FILE *m_fd;  Bool is_video;  u8 m_stream_id;    // program stream id  u8 m_substream_id; // substream, for program stream id == 0xbd  mpeg2ps_ts_t next_pes_ts, frame_ts;  u32 frames_since_last_ts;  u64 last_ts;  Bool have_frame_loaded;  /*   * pes_buffer processing.  this contains the raw elementary stream data   */  u8 *pes_buffer;  u32 pes_buffer_size;  u32 pes_buffer_size_max;  u32 pes_buffer_on;  u32 frame_len;  u32 pict_header_offset; // for mpeg video  // timing information and locations.  s64 first_pes_loc;  u64 start_dts;  Bool first_pes_has_dts;  s64    end_dts_loc;  u64 end_dts;  // audio stuff  u32 freq;  u32 channels;  u32 bitrate;  u32 samples_per_frame;  u32 layer;  // video stuff  u32 h, w, par;  Double frame_rate;  s32 have_mpeg2;  Double bit_rate;  u64 ticks_per_frame;} mpeg2ps_stream_t;/* * main interface structure - contains stream pointers and other * information */struct mpeg2ps_ {  mpeg2ps_stream_t *video_streams[16];  mpeg2ps_stream_t *audio_streams[32];  char *filename;  FILE *fd;  u64 first_dts;  u32 audio_cnt, video_cnt;  s64 end_loc;  u64 max_dts;  u64 max_time;  // time is in msec.};/************************************************************************* * File access routines.  Could all be inlined *************************************************************************/static FILE *file_open (const char *name){  return gf_f64_open(name, "rb");}static Bool file_okay (FILE *fd){	return (fd!=NULL) ? 1 : 0;}static void file_close (FILE *fd){  fclose(fd);}static Bool file_read_bytes(FILE *fd,			     u8 *buffer, 			     u32 len){  u32 readval = fread(buffer, 1, len, fd);  return readval == len;}// note: len could be negative.static void file_skip_bytes (FILE *fd, s32 len){  gf_f64_seek(fd, len, SEEK_CUR);}#define file_location(__f) gf_f64_tell(__f)#define file_seek_to(__f, __off) gf_f64_seek(__f, __off, SEEK_SET)static s64 file_size(FILE *fd){	s64 ret;  gf_f64_seek(fd, 0, SEEK_END);  ret = gf_f64_tell(fd);  gf_f64_seek(fd, 0, SEEK_SET);  return ret;}static mpeg2ps_record_pes_t *create_record (s64 loc, u64 ts){  mpeg2ps_record_pes_t *ret;  GF_SAFEALLOC(ret, mpeg2ps_record_pes_t);  ret->next_rec = NULL;  ret->dts = ts;  ret->location = loc;  return ret;}#define MPEG2PS_RECORD_TIME ((u64) (5 * 90000))void mpeg2ps_record_pts (mpeg2ps_stream_t *sptr, s64 location, mpeg2ps_ts_t *pTs){  u64 ts;  mpeg2ps_record_pes_t *p, *q;  if (sptr->is_video) {    if (pTs->have_dts == 0) return;    ts = pTs->dts;  } else {    if (pTs->have_pts == 0) return;    ts = pTs->pts;  }  if (sptr->record_first == NULL) {    sptr->record_first = sptr->record_last = create_record(location, ts);    return;  }   if (ts > sptr->record_last->dts) {    if (ts < MPEG2PS_RECORD_TIME + sptr->record_last->dts) return;    sptr->record_last->next_rec = create_record(location, ts);	sptr->record_last = sptr->record_last->next_rec;    return;  }  if (ts < sptr->record_first->dts) {    if (ts < MPEG2PS_RECORD_TIME + sptr->record_first->dts) return;    p = create_record(location, ts);    p->next_rec = sptr->record_first;    sptr->record_first = p;    return;  }  p = sptr->record_first;  q = p->next_rec;  while (q != NULL && q->dts < ts) {    p = q;    q = q->next_rec;  }  if (p->dts + MPEG2PS_RECORD_TIME <= ts &&      ts + MPEG2PS_RECORD_TIME <= q->dts) {    p->next_rec = create_record(location, ts);    p->next_rec->next_rec = q;  }}static Double mpeg12_frame_rate_table[16] ={  0.0,   /* Pad */  24000.0/1001.0,       /* Official frame rates */  24.0,  25.0,  30000.0/1001.0,  30.0,  50.0,  ((60.0*1000.0)/1001.0),  60.0,  1,                    /* Unofficial economy rates */  5,   10,  12,  15,  0,  0,};#define SEQ_ID 1int MPEG12_ParseSeqHdr(unsigned char *pbuffer, u32 buflen, s32 *have_mpeg2, u32 *height, u32 *width, 								  Double *frame_rate, Double *bitrate, u32 *aspect_ratio){  u32 aspect_code;  u32 framerate_code;  u32 bitrate_int;  u32 bitrate_ext;  u32 scode, ix;  s32 found = -1;  *have_mpeg2 = 0;  buflen -= 6;  bitrate_int = 0;  for (ix = 0; ix < buflen; ix++, pbuffer++) {    scode = (pbuffer[0] << 24) | (pbuffer[1] << 16) | (pbuffer[2] << 8) |       pbuffer[3];    if (scode == MPEG12_SEQUENCE_START_CODE) {      pbuffer += sizeof(u32);      *width = (pbuffer[0]);      *width <<= 4;      *width |= ((pbuffer[1] >> 4) &0xf);      *height = (pbuffer[1] & 0xf);      *height <<= 8;      *height |= pbuffer[2];      aspect_code = (pbuffer[3] >> 4) & 0xf;      if (aspect_ratio != NULL) {		  u32 par = 0;			switch (aspect_code) {			default: *aspect_ratio = 0; break;			case 2: par = 4; par<<=16; par |= 3; break;			case 3: par = 16; par<<=16; par |= 9; break;			case 4: par = 2; par<<=16; par |= 21; break;			}			*aspect_ratio = par;      }	  	      framerate_code = pbuffer[3] & 0xf;      *frame_rate = mpeg12_frame_rate_table[framerate_code];      // 18 bits      bitrate_int = (pbuffer[4] << 10) | 	(pbuffer[5] << 2) | 	((pbuffer[6] >> 6) & 0x3);      *bitrate = bitrate_int;      *bitrate *= 400.0;      ix += sizeof(u32) + 7;      pbuffer += 7;      found = 0;    } else if (found == 0) {      if (scode == MPEG12_EXT_START_CODE) {	pbuffer += sizeof(u32);	ix += sizeof(u32);	switch ((pbuffer[0] >> 4) & 0xf) {	case SEQ_ID:	  *have_mpeg2 = 1;	  *height = ((pbuffer[1] & 0x1) << 13) | 	    ((pbuffer[2] & 0x80) << 5) |	    (*height & 0x0fff);	  *width = (((pbuffer[2] >> 5) & 0x3) << 12) | (*width & 0x0fff);	  bitrate_ext = (pbuffer[2] & 0x1f) << 7;	  bitrate_ext |= (pbuffer[3] >> 1) & 0x7f;	  bitrate_int |= (bitrate_ext << 18);	  *bitrate = bitrate_int;	  *bitrate *= 400.0;	  break;	default:	  break;	}	pbuffer++;	ix++;      } else if (scode == MPEG12_PICTURE_START_CODE) {	return found;      }    }  }  return found;}s32 MPEG12_PictHdrType (unsigned char *pbuffer){  pbuffer += sizeof(u32);  return ((pbuffer[1] >> 3) & 0x7);}u16 MPEG12_PictHdrTempRef(unsigned char *pbuffer){  pbuffer += sizeof(u32);  return ((pbuffer[0] << 2) | ((pbuffer[1] >> 6) & 0x3));}static u64 read_pts (u8 *pak){  u64 pts;  u16 temp;    pts = ((pak[0] >> 1) & 0x7);  pts <<= 15;  temp = convert16(&pak[1]) >> 1;  pts |= temp;  pts <<= 15;  temp = convert16(&pak[3]) >> 1;  pts |= temp;  return pts;}static mpeg2ps_stream_t *mpeg2ps_stream_create (u8 stream_id,						u8 substream){  mpeg2ps_stream_t *ptr;  GF_SAFEALLOC(ptr, mpeg2ps_stream_t);  ptr->m_stream_id = stream_id;  ptr->m_substream_id = substream;  ptr->is_video = stream_id >= 0xe0;  ptr->pes_buffer = (u8 *)malloc(4*4096);  ptr->pes_buffer_size_max = 4 * 4096;  return ptr;}static void mpeg2ps_stream_destroy (mpeg2ps_stream_t *sptr){  mpeg2ps_record_pes_t *p;  while (sptr->record_first != NULL) {    p = sptr->record_first;    sptr->record_first = p->next_rec;    free(p);  }  if (sptr->m_fd != FDNULL) {    file_close(sptr->m_fd);    sptr->m_fd = FDNULL;  }  if (sptr->pes_buffer) free(sptr->pes_buffer);  free(sptr);}/* * adv_past_pack_hdr - read the pack header, advance past it * we don't do anything with the data */static void adv_past_pack_hdr (FILE *fd, 			       u8 *pak,			       u32 read_from_start){  u8 stuffed;  u8 readbyte;  u8 val;  if (read_from_start < 5) {    file_skip_bytes(fd, 5 - read_from_start);    file_read_bytes(fd, &readbyte, 1);    val = readbyte;  } else {    val = pak[4];  }      // we've read 6 bytes  if ((val & 0xc0) != 0x40) {    // mpeg1    file_skip_bytes(fd, 12 - read_from_start); // skip 6 more bytes    return;

⌨️ 快捷键说明

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