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

📄 mpeg.c

📁 ffmpeg源码分析
💻 C
📖 第 1 页 / 共 4 页
字号:
    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 + -