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

📄 mpeg.c

📁 linux下的MPEG1
💻 C
📖 第 1 页 / 共 2 页
字号:
        }      switch (vcd_bitvec_read_bits (buf, &bitpos, 2)) /* layer */        {        case 3: /* %11 */          state->stream.ahdr[aud_idx].layer = 1;          break;        case 2: /* %10 */          state->stream.ahdr[aud_idx].layer = 2;          break;        case 1: /* %01 */          state->stream.ahdr[aud_idx].layer = 3;          break;        case 0: /* %00 */          state->stream.ahdr[aud_idx].layer = 0;          break;        }      bitpos++; /* protection_bit */      {        const int bits = vcd_bitvec_read_bits (buf, &bitpos, 4);        const unsigned bit_rates[4][16] = {           {0, },          {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0},          {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0},          {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}        };        vcd_assert (IN(state->stream.ahdr[aud_idx].layer, 0, 3));        vcd_assert (IN(bits, 0, 15));        state->stream.ahdr[aud_idx].bitrate = 1024 * bit_rates[state->stream.ahdr[aud_idx].layer][bits];      }      switch (vcd_bitvec_read_bits (buf, &bitpos, 2)) /* sampling_frequency */        {        case 0: /* %00 */          state->stream.ahdr[aud_idx].sampfreq = 44100;          break;        case 1: /* %01 */          state->stream.ahdr[aud_idx].sampfreq = 48000;          break;        case 2: /* %10 */          state->stream.ahdr[aud_idx].sampfreq = 32000;          break;        case 3: /* %11 */          state->stream.ahdr[aud_idx].sampfreq = 0;          break;        }            bitpos++; /* padding_bit */      bitpos++; /* private_bit */      state->stream.ahdr[aud_idx].mode = 1 + vcd_bitvec_read_bits (buf, &bitpos, 2); /* mode */            state->stream.ahdr[aud_idx].seen = true;            /* we got the info, let's jump outta here */      break;    }}static void_analyze_video_pes (uint8_t streamid, const uint8_t *buf, int len, bool only_pts,		    VcdMpegStreamCtx *state){  const int vid_idx = _vid_streamid_idx (streamid);  int pos, pes_header;  int sequence_header_pos = -1;  int gop_header_pos = -1;  int ipicture_header_pos = -1;  vcd_assert (vid_idx != -1);  pes_header = pos = _analyze_pes_header (buf, len, state);  /* if only pts extraction was needed, we are done here... */  if (only_pts)    return;    while (pos + 4 <= len)    {      uint32_t code = vcd_bitvec_peek_bits32 (buf, pos << 3);      if (!_start_code_p (code))	{	  pos++;	  continue;	}      switch (code)	{	case MPEG_PICTURE_CODE:	  pos += 4;	            if (vcd_bitvec_peek_bits (buf, (pos << 3) + 10, 3) == 1)            ipicture_header_pos = pos;	  break;	  	case MPEG_SEQUENCE_CODE:	  pos += 4;	  sequence_header_pos = pos;          _parse_sequence_header (streamid, buf + pos, state);	  break;	case MPEG_GOP_CODE:	  pos += 4;          if (pos + 4 > len)            break;	  gop_header_pos = pos;	  _parse_gop_header (streamid, buf + pos, state);	  state->packet.gop = true;	  break;	case MPEG_USER_CODE:	  pos += 4;          if (pos + 4 > len)            break;          _parse_user_data (streamid, buf + pos, len - pos, pos, state);	  break;	case MPEG_EXT_CODE:	default:	  pos += 4;	  break;	}    }  /* decide whether this packet qualifies as access point */  state->packet.aps = APS_NONE; /* paranoia */  if (state->packet.has_pts       && ipicture_header_pos != -1)    {      enum aps_t _aps_type = APS_NONE;      switch (state->stream.version)        {        case MPEG_VERS_MPEG1:        case MPEG_VERS_MPEG2:          if (sequence_header_pos != -1              && sequence_header_pos < gop_header_pos              && gop_header_pos < ipicture_header_pos)            _aps_type = (sequence_header_pos - 4 == pes_header) ? APS_ASGI : APS_SGI;          else if (gop_header_pos != 1                    && gop_header_pos < ipicture_header_pos)            _aps_type = APS_GI;          else            _aps_type = APS_I;          break;        default:          break;        }      if (_aps_type)         {          const double pts2 = state->packet.pts;          if (state->stream.shdr[vid_idx].last_aps_pts > pts2)            vcd_warn ("APS' pts seems out of order (actual pts %f, last seen pts %f) "                      "-- ignoring this aps",                      pts2, state->stream.shdr[vid_idx].last_aps_pts);          else            {              state->packet.aps_idx = vid_idx;              state->packet.aps = _aps_type;              state->packet.aps_pts = pts2;              state->stream.shdr[vid_idx].last_aps_pts = pts2;            }        }    }}static void_register_streamid (uint8_t streamid, VcdMpegStreamCtx *state){  const uint32_t code = MPEG_START_CODE_PATTERN | streamid;  switch (code)    {    case MPEG_VIDEO_E0_CODE:    case MPEG_VIDEO_E1_CODE:     case MPEG_VIDEO_E2_CODE:       state->packet.video[_vid_streamid_idx (streamid)] = true;      break;    case MPEG_AUDIO_C0_CODE:    case MPEG_AUDIO_C1_CODE:    case MPEG_AUDIO_C2_CODE:      state->packet.audio[_aud_streamid_idx (streamid)] = true;      break;    case MPEG_PAD_CODE:      state->packet.padding = true;      break;    case MPEG_SYSTEM_HEADER_CODE:       state->packet.system_header = true;      break;    }}static void_analyze_system_header (const uint8_t *buf, int len,                         VcdMpegStreamCtx *state){  unsigned bitpos = 0;  MARKER (buf, &bitpos);  bitpos += 22; /* rate_bound */  MARKER (buf, &bitpos);  bitpos += 6; /* audio_bound */   bitpos++; /* fixed_flag */  bitpos++; /* CSPS_flag */  bitpos++; /* system_audio_lock_flag */  bitpos++; /* system_video_lock_flag */  MARKER (buf, &bitpos);  bitpos += 5; /* video_bound */   bitpos += 1; /* packet_rate_restriction_flag -- only ISO 13818-1 */  bitpos += 7; /* reserved */  while (vcd_bitvec_peek_bits (buf, bitpos, 1) == 1          && bitpos <= (len << 3))    {      const uint8_t stream_id = vcd_bitvec_read_bits (buf, &bitpos, 8);      bitpos += 2; /* %11 */      bitpos++; /* P-STD_buffer_bound_scale */      bitpos += 13; /* P-STD_buffer_size_bound */      _register_streamid (stream_id, state);    }  vcd_assert (bitpos <= (len << 3));}static void_analyze_private_1_stream (const uint8_t *buf, int len,                            VcdMpegStreamCtx *state){  unsigned bitpos = _analyze_pes_header (buf, len, state);  int ogt_idx = -1;  uint8_t private_data_id;  bitpos <<= 3;  private_data_id = vcd_bitvec_read_bits (buf, &bitpos, 8);  switch (private_data_id)     {      uint8_t sub_stream_id;    case 0x00:    case 0x01:    case 0x02:    case 0x03:      /* CVD subs */      ogt_idx = private_data_id;      if (!state->stream.ogt[ogt_idx])        vcd_debug ("Assuming CVD-style subtitles for data_id 0x%.2x in private stream 1", ogt_idx);      break;    case 0x70:      /* SVCD OGT */      sub_stream_id = vcd_bitvec_read_bits (buf, &bitpos, 8);      if (sub_stream_id < 4)        {          ogt_idx = sub_stream_id;          if (!state->stream.ogt[ogt_idx])            vcd_debug ("subtitles detect for channel 0x%.2x", ogt_idx);        }      else        vcd_warn ("sub_stream_id out of range (0x%.2x)", sub_stream_id);      break;    default:      vcd_warn ("unknown private_data_id for private stream 1 seen (0x%.2x)",                private_data_id);      return;      break;    }  if (ogt_idx >= 0)    state->stream.ogt[ogt_idx] = state->packet.ogt[ogt_idx] = true;}intvcd_mpeg_parse_packet (const void *_buf, unsigned buflen, bool parse_pes,                       VcdMpegStreamCtx *ctx){  const uint8_t *buf = _buf;  int pos;  vcd_assert (buf != NULL);  vcd_assert (ctx != NULL);    /* clear packet info */  memset (&(ctx->packet), 0, sizeof (ctx->packet));  ctx->stream.packets++;  for (pos = 0; pos < buflen && !buf[pos]; pos++);  if (pos == buflen)    {      ctx->packet.zero = true;      return buflen;    }  /* verify the packet begins with a pack header */  if (vcd_bitvec_peek_bits32 (buf, 0) != MPEG_PACK_HEADER_CODE)    {      const uint32_t _code = vcd_bitvec_peek_bits32 (buf, 0);      vcd_warn ("mpeg scan: pack header code (0x%8.8x) expected, "                "but 0x%8.8x found (buflen = %d)",                (unsigned int) MPEG_PACK_HEADER_CODE,                 (unsigned int) _code, buflen);      ctx->stream.packets--;      if (!ctx->stream.packets)        {          if (_code == MPEG_SEQUENCE_CODE)            vcd_warn ("...this looks like a elementary video stream"                      " but a multiplexed program stream was required.");          if ((0xfff00000 & _code) == 0xfff00000)            vcd_warn ("...this looks like a elementary audio stream"                      " but a multiplexed program stream was required.");          if (_code == 0x52494646)            vcd_warn ("...this looks like a RIFF header"                      " but a plain multiplexed program stream was required.");        }      else if (_code == MPEG_PROGRAM_END_CODE)        vcd_warn ("...PEM (program end marker) found instead of pack header;"                  " should be in last 4 bytes of pack");      return 0;    }  /* take a look at the pack header */  pos = 0;  while (pos + 4 <= buflen)    {      uint32_t code = vcd_bitvec_peek_bits32 (buf, pos << 3);      /* skip zero bytes... */      if (!code)	{	  pos += (pos + 4 == buflen) ? 4 : 2;	  continue;	}      /* continue until start code seen */      if (!_start_code_p (code))	{	  pos++;	  continue;	}      switch (code)	{	  uint16_t size;          int bits;          unsigned bitpos;          	case MPEG_PACK_HEADER_CODE:	  if (pos)	    return pos;	  pos += 4;          bitpos = pos << 3;          bits = vcd_bitvec_peek_bits (buf, bitpos, 4);          if (bits == 0x2) /* %0010 ISO11172-1 */            {              uint64_t _scr;              uint32_t _muxrate;              bitpos += 4;              if (!ctx->stream.version)                ctx->stream.version = MPEG_VERS_MPEG1;              if (ctx->stream.version != MPEG_VERS_MPEG1)                vcd_warn ("mixed mpeg versions?");              _scr = _parse_timecode (buf, &bitpos);              MARKER (buf, &bitpos);              _muxrate = vcd_bitvec_read_bits (buf, &bitpos, 22);              MARKER (buf, &bitpos);              vcd_assert (bitpos % 8 == 0);              pos = bitpos >> 3;              ctx->packet.scr = _scr;              ctx->stream.muxrate = ctx->packet.muxrate = _muxrate * 50 * 8;            }          else if (bits >> 2 == 0x1) /* %01xx ISO13818-1 */            {              uint64_t _scr;              uint32_t _muxrate;              int tmp;              bitpos += 2;              if (!ctx->stream.version)                ctx->stream.version = MPEG_VERS_MPEG2;              if (ctx->stream.version != MPEG_VERS_MPEG2)                vcd_warn ("mixed mpeg versions?");              _scr = _parse_timecode (buf, &bitpos);              _scr *= 300;              _scr += vcd_bitvec_read_bits (buf, &bitpos, 9); /* SCR ext */              MARKER (buf, &bitpos);                            _muxrate = vcd_bitvec_read_bits (buf, &bitpos, 22);                            MARKER (buf, &bitpos);              MARKER (buf, &bitpos);              bitpos += 5; /* reserved */              tmp = vcd_bitvec_read_bits (buf, &bitpos, 3) << 3;              bitpos += tmp;              vcd_assert (bitpos % 8 == 0);              pos = bitpos >> 3;              ctx->packet.scr = _scr;              ctx->stream.muxrate = ctx->packet.muxrate = _muxrate * 50 * 8;            }          else            {              vcd_warn ("packet not recognized as either version 1 or 2 (%d)"                         " -- assuming v1", bits);            }	  break;	case MPEG_SYSTEM_HEADER_CODE:	case MPEG_PAD_CODE:	case MPEG_PRIVATE_1_CODE:	case MPEG_VIDEO_E0_CODE:	case MPEG_VIDEO_E1_CODE:	case MPEG_VIDEO_E2_CODE:        case MPEG_AUDIO_C0_CODE:        case MPEG_AUDIO_C1_CODE:        case MPEG_AUDIO_C2_CODE:	  pos += 4;	  size = vcd_bitvec_peek_bits16 (buf, pos << 3);	  pos += 2;	  	  if (pos + size > buflen)	              {              vcd_warn ("packet length beyond buffer"                         " (pos = %d + size = %d > buflen = %d) "                        "-- stream may be truncated or packet length > 2324 bytes!",                        pos, size, buflen);              ctx->stream.packets--;              return 0;            }          _register_streamid (code & 0xff, ctx);	  switch (code)	    {	    case MPEG_SYSTEM_HEADER_CODE:               _analyze_system_header (buf + pos, size, ctx);              break;	    case MPEG_VIDEO_E0_CODE:	    case MPEG_VIDEO_E1_CODE: 	    case MPEG_VIDEO_E2_CODE:               _analyze_video_pes (code & 0xff, buf + pos, size, !parse_pes, ctx);              break;            case MPEG_AUDIO_C0_CODE:            case MPEG_AUDIO_C1_CODE:            case MPEG_AUDIO_C2_CODE:              _analyze_audio_pes (code & 0xff, buf + pos, size, !parse_pes, ctx);              break;            case MPEG_PRIVATE_1_CODE:              _analyze_private_1_stream (buf + pos, size, ctx);              break;	    }	  pos += size;	  break;	  	case MPEG_PROGRAM_END_CODE:	  ctx->packet.pem = true;	  pos += 4;	  break;	case MPEG_PICTURE_CODE:	  pos += 3;	  break;	default:	  vcd_debug ("unexpected start code 0x%8.8x", (unsigned int) code);	  pos += 4;	  break;	}    }  if (pos != buflen)    vcd_debug ("pos != buflen (%d != %d)", pos, buflen); /* fixme? */  return buflen;}mpeg_norm_t vcd_mpeg_get_norm (const struct vcd_mpeg_stream_vid_info *_info){  int i;          for (i = 0; norm_table[i].norm != MPEG_NORM_OTHER;i++)    if (norm_table[i].hsize == _info->hsize        && norm_table[i].vsize == _info->vsize        && frame_rates[norm_table[i].frate_idx] == _info->frate)      break;  return norm_table[i].norm;}enum vcd_mpeg_packet_typevcd_mpeg_packet_get_type (const struct vcd_mpeg_packet_info *_info){  if (_info->video[0]       || _info->video[1]      || _info->video[2])    return PKT_TYPE_VIDEO;  else if (_info->audio[0]            || _info->audio[1]           || _info->audio[2])    return PKT_TYPE_AUDIO;  else if (_info->zero)    return PKT_TYPE_ZERO;  else if (_info->ogt[0]            || _info->ogt[1]            || _info->ogt[2]           || _info->ogt[3])    return PKT_TYPE_OGT;   else if (_info->system_header || _info->padding)    return PKT_TYPE_EMPTY;  return PKT_TYPE_INVALID;}/*  * Local variables: *  c-file-style: "gnu" *  tab-width: 8 *  indent-tabs-mode: nil * End: */

⌨️ 快捷键说明

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