📄 mpeg.c
字号:
int max_size, start_code; max_size = *size_ptr; pos_start = url_ftell(pb); /* in order to go faster, we fill the buffer */ pos = pos_start - 16386; if (pos < 0) pos = 0; url_fseek(pb, pos, SEEK_SET); get_byte(pb); pos = pos_start; for(;;) { pos--; if (pos < 0 || (pos_start - pos) >= max_size) { start_code = -1; goto the_end; } url_fseek(pb, pos, SEEK_SET); start_code = get_be32(pb); if ((start_code & 0xffffff00) == 0x100) break; } the_end: *size_ptr = pos_start - pos; return start_code;}#endif/** * Extracts stream types from a program stream map * According to ISO/IEC 13818-1 ('MPEG-2 Systems') table 2-35 * * @return number of bytes occupied by PSM in the bitstream */static long mpegps_psm_parse(MpegDemuxContext *m, ByteIOContext *pb){ int psm_length, ps_info_length, es_map_length; psm_length = get_be16(pb); get_byte(pb); get_byte(pb); ps_info_length = get_be16(pb); /* skip program_stream_info */ url_fskip(pb, ps_info_length); es_map_length = get_be16(pb); /* at least one es available? */ while (es_map_length >= 4){ unsigned char type = get_byte(pb); unsigned char es_id = get_byte(pb); uint16_t es_info_length = get_be16(pb); /* remember mapping from stream id to stream type */ m->psm_es_type[es_id] = type; /* skip program_stream_info */ url_fskip(pb, es_info_length); es_map_length -= 4 + es_info_length; } get_be32(pb); /* crc32 */ return 2 + psm_length;}/* read the next PES header. Return its position in ppos (if not NULL), and its start code, pts and dts. */static int mpegps_read_pes_header(AVFormatContext *s, int64_t *ppos, int *pstart_code, int64_t *ppts, int64_t *pdts){ MpegDemuxContext *m = s->priv_data; int len, size, startcode, c, flags, header_len; int64_t pts, dts, last_pos; last_pos = -1; redo: /* next start code (should be immediately after) */ m->header_state = 0xff; size = MAX_SYNC_SIZE; startcode = find_next_start_code(&s->pb, &size, &m->header_state); //printf("startcode=%x pos=0x%Lx\n", startcode, url_ftell(&s->pb)); if (startcode < 0) return AVERROR_IO; if (startcode == PACK_START_CODE) goto redo; if (startcode == SYSTEM_HEADER_START_CODE) goto redo; if (startcode == PADDING_STREAM || startcode == PRIVATE_STREAM_2) { /* skip them */ len = get_be16(&s->pb); url_fskip(&s->pb, len); goto redo; } if (startcode == PROGRAM_STREAM_MAP) { mpegps_psm_parse(m, &s->pb); goto redo; } /* find matching stream */ if (!((startcode >= 0x1c0 && startcode <= 0x1df) || (startcode >= 0x1e0 && startcode <= 0x1ef) || (startcode == 0x1bd))) goto redo; if (ppos) { *ppos = url_ftell(&s->pb) - 4; } len = get_be16(&s->pb); pts = AV_NOPTS_VALUE; dts = AV_NOPTS_VALUE; /* stuffing */ for(;;) { if (len < 1) goto redo; c = get_byte(&s->pb); len--; /* XXX: for mpeg1, should test only bit 7 */ if (c != 0xff) break; } if ((c & 0xc0) == 0x40) { /* buffer scale & size */ if (len < 2) goto redo; get_byte(&s->pb); c = get_byte(&s->pb); len -= 2; } if ((c & 0xf0) == 0x20) { if (len < 4) goto redo; dts = pts = get_pts(&s->pb, c); len -= 4; } else if ((c & 0xf0) == 0x30) { if (len < 9) goto redo; pts = get_pts(&s->pb, c); dts = get_pts(&s->pb, -1); len -= 9; } else if ((c & 0xc0) == 0x80) { /* mpeg 2 PES */ if ((c & 0x30) != 0) { /* Encrypted multiplex not handled */ goto redo; } flags = get_byte(&s->pb); header_len = get_byte(&s->pb); len -= 2; if (header_len > len) goto redo; if ((flags & 0xc0) == 0x80) { dts = pts = get_pts(&s->pb, -1); if (header_len < 5) goto redo; header_len -= 5; len -= 5; } if ((flags & 0xc0) == 0xc0) { pts = get_pts(&s->pb, -1); dts = get_pts(&s->pb, -1); if (header_len < 10) goto redo; header_len -= 10; len -= 10; } len -= header_len; while (header_len > 0) { get_byte(&s->pb); header_len--; } } else if( c!= 0xf ) goto redo; if (startcode == PRIVATE_STREAM_1 && !m->psm_es_type[startcode & 0xff]) { if (len < 1) goto redo; startcode = get_byte(&s->pb); len--; if (startcode >= 0x80 && startcode <= 0xbf) { /* audio: skip header */ if (len < 3) goto redo; get_byte(&s->pb); get_byte(&s->pb); get_byte(&s->pb); len -= 3; } } if(dts != AV_NOPTS_VALUE && ppos){ int i; for(i=0; i<s->nb_streams; i++){ if(startcode == s->streams[i]->id) { av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */); } } } *pstart_code = startcode; *ppts = pts; *pdts = dts; return len;}static int mpegps_read_packet(AVFormatContext *s, AVPacket *pkt){ MpegDemuxContext *m = s->priv_data; AVStream *st; int len, startcode, i, type, codec_id = 0, es_type; int64_t pts, dts, dummy_pos; //dummy_pos is needed for the index building to work redo: len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts); if (len < 0) return len; /* now find stream */ for(i=0;i<s->nb_streams;i++) { st = s->streams[i]; if (st->id == startcode) goto found; } es_type = m->psm_es_type[startcode & 0xff]; if(es_type > 0){ if(es_type == STREAM_TYPE_VIDEO_MPEG1){ codec_id = CODEC_ID_MPEG2VIDEO; type = CODEC_TYPE_VIDEO; } else if(es_type == STREAM_TYPE_VIDEO_MPEG2){ codec_id = CODEC_ID_MPEG2VIDEO; type = CODEC_TYPE_VIDEO; } else if(es_type == STREAM_TYPE_AUDIO_MPEG1 || es_type == STREAM_TYPE_AUDIO_MPEG2){ codec_id = CODEC_ID_MP3; type = CODEC_TYPE_AUDIO; } else if(es_type == STREAM_TYPE_AUDIO_AAC){ codec_id = CODEC_ID_AAC; type = CODEC_TYPE_AUDIO; } else if(es_type == STREAM_TYPE_VIDEO_MPEG4){ codec_id = CODEC_ID_MPEG4; type = CODEC_TYPE_VIDEO; } else if(es_type == STREAM_TYPE_VIDEO_H264){ codec_id = CODEC_ID_H264; type = CODEC_TYPE_VIDEO; } else if(es_type == STREAM_TYPE_AUDIO_AC3){ codec_id = CODEC_ID_AC3; type = CODEC_TYPE_AUDIO; } else { goto skip; } } else if (startcode >= 0x1e0 && startcode <= 0x1ef) { type = CODEC_TYPE_VIDEO; codec_id = CODEC_ID_MPEG2VIDEO; } else if (startcode >= 0x1c0 && startcode <= 0x1df) { type = CODEC_TYPE_AUDIO; codec_id = CODEC_ID_MP2; } else if (startcode >= 0x80 && startcode <= 0x87) { type = CODEC_TYPE_AUDIO; codec_id = CODEC_ID_AC3; } else if (startcode >= 0x88 && startcode <= 0x9f) { type = CODEC_TYPE_AUDIO; codec_id = CODEC_ID_DTS; } else if (startcode >= 0xa0 && startcode <= 0xbf) { type = CODEC_TYPE_AUDIO; codec_id = CODEC_ID_PCM_S16BE; } else if (startcode >= 0x20 && startcode <= 0x3f) { type = CODEC_TYPE_SUBTITLE; codec_id = CODEC_ID_DVD_SUBTITLE; } else { skip: /* skip packet */ url_fskip(&s->pb, len); goto redo; } /* no stream found: add a new stream */ st = av_new_stream(s, startcode); if (!st) goto skip; st->codec->codec_type = type; st->codec->codec_id = codec_id; if (codec_id != CODEC_ID_PCM_S16BE) st->need_parsing = 1; found: if(st->discard >= AVDISCARD_ALL) goto skip; if (startcode >= 0xa0 && startcode <= 0xbf) { int b1, freq; /* for LPCM, we just skip the header and consider it is raw audio data */ if (len <= 3) goto skip; get_byte(&s->pb); /* emphasis (1), muse(1), reserved(1), frame number(5) */ b1 = get_byte(&s->pb); /* quant (2), freq(2), reserved(1), channels(3) */ get_byte(&s->pb); /* dynamic range control (0x80 = off) */ len -= 3; freq = (b1 >> 4) & 3; st->codec->sample_rate = lpcm_freq_tab[freq]; st->codec->channels = 1 + (b1 & 7); st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 2; } av_new_packet(pkt, len); get_buffer(&s->pb, pkt->data, pkt->size); pkt->pts = pts; pkt->dts = dts; pkt->stream_index = st->index;#if 0 av_log(s, AV_LOG_DEBUG, "%d: pts=%0.3f dts=%0.3f size=%d\n", pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0, pkt->size);#endif return 0;}static int mpegps_read_close(AVFormatContext *s){ return 0;}static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit){ int len, startcode; int64_t pos, pts, dts; pos = *ppos;#ifdef DEBUG_SEEK printf("read_dts: pos=0x%llx next=%d -> ", pos, find_next);#endif url_fseek(&s->pb, pos, SEEK_SET); for(;;) { len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts); if (len < 0) {#ifdef DEBUG_SEEK printf("none (ret=%d)\n", len);#endif return AV_NOPTS_VALUE; } if (startcode == s->streams[stream_index]->id && dts != AV_NOPTS_VALUE) { break; } url_fskip(&s->pb, len); }#ifdef DEBUG_SEEK printf("pos=0x%llx dts=0x%llx %0.3f\n", pos, dts, dts / 90000.0);#endif *ppos = pos; return dts;}#ifdef CONFIG_MUXERSstatic AVOutputFormat mpeg1system_mux = { "mpeg", "MPEG1 System format", "video/mpeg", "mpg,mpeg", sizeof(MpegMuxContext), CODEC_ID_MP2, CODEC_ID_MPEG1VIDEO, mpeg_mux_init, mpeg_mux_write_packet, mpeg_mux_end,};static AVOutputFormat mpeg1vcd_mux = { "vcd", "MPEG1 System format (VCD)", "video/mpeg", NULL, sizeof(MpegMuxContext), CODEC_ID_MP2, CODEC_ID_MPEG1VIDEO, mpeg_mux_init, mpeg_mux_write_packet, mpeg_mux_end,};static AVOutputFormat mpeg2vob_mux = { "vob", "MPEG2 PS format (VOB)", "video/mpeg", "vob", sizeof(MpegMuxContext), CODEC_ID_MP2, CODEC_ID_MPEG2VIDEO, mpeg_mux_init, mpeg_mux_write_packet, mpeg_mux_end,};/* Same as mpeg2vob_mux except that the pack size is 2324 */static AVOutputFormat mpeg2svcd_mux = { "svcd", "MPEG2 PS format (VOB)", "video/mpeg", "vob", sizeof(MpegMuxContext), CODEC_ID_MP2, CODEC_ID_MPEG2VIDEO, mpeg_mux_init, mpeg_mux_write_packet, mpeg_mux_end,};/* Same as mpeg2vob_mux except the 'is_dvd' flag is set to produce NAV pkts */static AVOutputFormat mpeg2dvd_mux = { "dvd", "MPEG2 PS format (DVD VOB)", "video/mpeg", "dvd", sizeof(MpegMuxContext), CODEC_ID_MP2, CODEC_ID_MPEG2VIDEO, mpeg_mux_init, mpeg_mux_write_packet, mpeg_mux_end,};#endif //CONFIG_MUXERSAVInputFormat mpegps_demux = { "mpeg", "MPEG PS format", sizeof(MpegDemuxContext), mpegps_probe, mpegps_read_header, mpegps_read_packet, mpegps_read_close, NULL, //mpegps_read_seek, mpegps_read_dts, .flags = AVFMT_SHOW_IDS,};int mpegps_init(void){#ifdef CONFIG_MUXERS av_register_output_format(&mpeg1system_mux); av_register_output_format(&mpeg1vcd_mux); av_register_output_format(&mpeg2vob_mux); av_register_output_format(&mpeg2svcd_mux); av_register_output_format(&mpeg2dvd_mux);#endif //CONFIG_MUXERS av_register_input_format(&mpegps_demux); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -