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

📄 mpegenc.c

📁 ffmpeg的完整源代码和作者自己写的文档。不但有在Linux的工程哦
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * MPEG1/2 muxer
 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard.
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "avformat.h"
#include "bitstream.h"
#include "fifo.h"
#include "mpeg.h"

#define MAX_PAYLOAD_SIZE 4096
//#define DEBUG_SEEK

#undef NDEBUG
#include <assert.h>

typedef struct PacketDesc {
    int64_t pts;
    int64_t dts;
    int size;
    int unwritten_size;
    int flags;
    struct PacketDesc *next;
} PacketDesc;

typedef struct {
    AVFifoBuffer fifo;
    uint8_t id;
    int max_buffer_size; /* in bytes */
    int buffer_index;
    PacketDesc *predecode_packet;
    PacketDesc *premux_packet;
    PacketDesc **next_packet;
    int packet_number;
    uint8_t lpcm_header[3];
    int lpcm_align;
    int bytes_to_iframe;
    int align_iframe;
    int64_t vobu_start_pts;
} StreamInfo;

typedef struct {
    int packet_size; /* required packet size */
    int packet_number;
    int pack_header_freq;     /* frequency (in packets^-1) at which we send pack headers */
    int system_header_freq;
    int system_header_size;
    int mux_rate; /* bitrate in units of 50 bytes/s */
    /* stream info */
    int audio_bound;
    int video_bound;
    int is_mpeg2;
    int is_vcd;
    int is_svcd;
    int is_dvd;
    int64_t last_scr; /* current system clock */

    double vcd_padding_bitrate; //FIXME floats
    int64_t vcd_padding_bytes_written;

} MpegMuxContext;

extern AVOutputFormat mpeg1vcd_muxer;
extern AVOutputFormat mpeg2dvd_muxer;
extern AVOutputFormat mpeg2svcd_muxer;
extern AVOutputFormat mpeg2vob_muxer;

static int put_pack_header(AVFormatContext *ctx,
                           uint8_t *buf, int64_t timestamp)
{
    MpegMuxContext *s = ctx->priv_data;
    PutBitContext pb;

    init_put_bits(&pb, buf, 128);

    put_bits(&pb, 32, PACK_START_CODE);
    if (s->is_mpeg2) {
        put_bits(&pb, 2, 0x1);
    } else {
        put_bits(&pb, 4, 0x2);
    }
    put_bits(&pb, 3, (uint32_t)((timestamp >> 30) & 0x07));
    put_bits(&pb, 1, 1);
    put_bits(&pb, 15, (uint32_t)((timestamp >> 15) & 0x7fff));
    put_bits(&pb, 1, 1);
    put_bits(&pb, 15, (uint32_t)((timestamp) & 0x7fff));
    put_bits(&pb, 1, 1);
    if (s->is_mpeg2) {
        /* clock extension */
        put_bits(&pb, 9, 0);
    }
    put_bits(&pb, 1, 1);
    put_bits(&pb, 22, s->mux_rate);
    put_bits(&pb, 1, 1);
    if (s->is_mpeg2) {
        put_bits(&pb, 1, 1);
        put_bits(&pb, 5, 0x1f); /* reserved */
        put_bits(&pb, 3, 0); /* stuffing length */
    }
    flush_put_bits(&pb);
    return pbBufPtr(&pb) - pb.buf;
}

static int put_system_header(AVFormatContext *ctx, uint8_t *buf,int only_for_stream_id)
{
    MpegMuxContext *s = ctx->priv_data;
    int size, i, private_stream_coded, id;
    PutBitContext pb;

    init_put_bits(&pb, buf, 128);

    put_bits(&pb, 32, SYSTEM_HEADER_START_CODE);
    put_bits(&pb, 16, 0);
    put_bits(&pb, 1, 1);

    put_bits(&pb, 22, s->mux_rate); /* maximum bit rate of the multiplexed stream */
    put_bits(&pb, 1, 1); /* marker */
    if (s->is_vcd && only_for_stream_id==VIDEO_ID) {
        /* This header applies only to the video stream (see VCD standard p. IV-7)*/
        put_bits(&pb, 6, 0);
    } else
        put_bits(&pb, 6, s->audio_bound);

    if (s->is_vcd) {
        /* see VCD standard, p. IV-7*/
        put_bits(&pb, 1, 0);
        put_bits(&pb, 1, 1);
    } else {
        put_bits(&pb, 1, 0); /* variable bitrate*/
        put_bits(&pb, 1, 0); /* non constrainted bit stream */
    }

    if (s->is_vcd || s->is_dvd) {
        /* see VCD standard p IV-7 */
        put_bits(&pb, 1, 1); /* audio locked */
        put_bits(&pb, 1, 1); /* video locked */
    } else {
        put_bits(&pb, 1, 0); /* audio locked */
        put_bits(&pb, 1, 0); /* video locked */
    }

    put_bits(&pb, 1, 1); /* marker */

    if (s->is_vcd && only_for_stream_id==AUDIO_ID) {
        /* This header applies only to the audio stream (see VCD standard p. IV-7)*/
        put_bits(&pb, 5, 0);
    } else
        put_bits(&pb, 5, s->video_bound);

    if (s->is_dvd) {
        put_bits(&pb, 1, 0);    /* packet_rate_restriction_flag */
        put_bits(&pb, 7, 0x7f); /* reserved byte */
    } else
        put_bits(&pb, 8, 0xff); /* reserved byte */

    /* DVD-Video Stream_bound entries
    id (0xB9) video, maximum P-STD for stream 0xE0. (P-STD_buffer_bound_scale = 1)
    id (0xB8) audio, maximum P-STD for any MPEG audio (0xC0 to 0xC7) streams. If there are none set to 4096 (32x128). (P-STD_buffer_bound_scale = 0)
    id (0xBD) private stream 1 (audio other than MPEG and subpictures). (P-STD_buffer_bound_scale = 1)
    id (0xBF) private stream 2, NAV packs, set to 2x1024. */
    if (s->is_dvd) {

        int P_STD_max_video = 0;
        int P_STD_max_mpeg_audio = 0;
        int P_STD_max_mpeg_PS1 = 0;

        for(i=0;i<ctx->nb_streams;i++) {
            StreamInfo *stream = ctx->streams[i]->priv_data;

            id = stream->id;
            if (id == 0xbd && stream->max_buffer_size > P_STD_max_mpeg_PS1) {
                P_STD_max_mpeg_PS1 = stream->max_buffer_size;
            } else if (id >= 0xc0 && id <= 0xc7 && stream->max_buffer_size > P_STD_max_mpeg_audio) {
                P_STD_max_mpeg_audio = stream->max_buffer_size;
            } else if (id == 0xe0 && stream->max_buffer_size > P_STD_max_video) {
                P_STD_max_video = stream->max_buffer_size;
            }
        }

        /* video */
        put_bits(&pb, 8, 0xb9); /* stream ID */
        put_bits(&pb, 2, 3);
        put_bits(&pb, 1, 1);
        put_bits(&pb, 13, P_STD_max_video / 1024);

        /* audio */
        if (P_STD_max_mpeg_audio == 0)
            P_STD_max_mpeg_audio = 4096;
        put_bits(&pb, 8, 0xb8); /* stream ID */
        put_bits(&pb, 2, 3);
        put_bits(&pb, 1, 0);
        put_bits(&pb, 13, P_STD_max_mpeg_audio / 128);

        /* private stream 1 */
        put_bits(&pb, 8, 0xbd); /* stream ID */
        put_bits(&pb, 2, 3);
        put_bits(&pb, 1, 0);
        put_bits(&pb, 13, P_STD_max_mpeg_PS1 / 128);

        /* private stream 2 */
        put_bits(&pb, 8, 0xbf); /* stream ID */
        put_bits(&pb, 2, 3);
        put_bits(&pb, 1, 1);
        put_bits(&pb, 13, 2);
    }
    else {
        /* audio stream info */
        private_stream_coded = 0;
        for(i=0;i<ctx->nb_streams;i++) {
            StreamInfo *stream = ctx->streams[i]->priv_data;


            /* For VCDs, only include the stream info for the stream
            that the pack which contains this system belongs to.
            (see VCD standard p. IV-7) */
            if ( !s->is_vcd || stream->id==only_for_stream_id
                || only_for_stream_id==0) {

                id = stream->id;
                if (id < 0xc0) {
                    /* special case for private streams (AC3 use that) */
                    if (private_stream_coded)
                        continue;
                    private_stream_coded = 1;
                    id = 0xbd;
                }
                put_bits(&pb, 8, id); /* stream ID */
                put_bits(&pb, 2, 3);
                if (id < 0xe0) {
                    /* audio */
                    put_bits(&pb, 1, 0);
                    put_bits(&pb, 13, stream->max_buffer_size / 128);
                } else {
                    /* video */
                    put_bits(&pb, 1, 1);
                    put_bits(&pb, 13, stream->max_buffer_size / 1024);
                }
            }
        }
    }

    flush_put_bits(&pb);
    size = pbBufPtr(&pb) - pb.buf;
    /* patch packet size */
    buf[4] = (size - 6) >> 8;
    buf[5] = (size - 6) & 0xff;

    return size;
}

static int get_system_header_size(AVFormatContext *ctx)
{
    int buf_index, i, private_stream_coded;
    StreamInfo *stream;
    MpegMuxContext *s = ctx->priv_data;

    if (s->is_dvd)
       return 18; // DVD-Video system headers are 18 bytes fixed length.

    buf_index = 12;
    private_stream_coded = 0;
    for(i=0;i<ctx->nb_streams;i++) {
        stream = ctx->streams[i]->priv_data;
        if (stream->id < 0xc0) {
            if (private_stream_coded)
                continue;
            private_stream_coded = 1;
        }
        buf_index += 3;
    }
    return buf_index;
}

static int mpeg_mux_init(AVFormatContext *ctx)
{
    MpegMuxContext *s = ctx->priv_data;
    int bitrate, i, mpa_id, mpv_id, mps_id, ac3_id, dts_id, lpcm_id, j;
    AVStream *st;
    StreamInfo *stream;
    int audio_bitrate;
    int video_bitrate;

    s->packet_number = 0;
    s->is_vcd =   (ENABLE_MPEG1VCD_MUXER  && ctx->oformat == &mpeg1vcd_muxer);
    s->is_svcd =  (ENABLE_MPEG2SVCD_MUXER && ctx->oformat == &mpeg2svcd_muxer);
    s->is_mpeg2 = (ENABLE_MPEG2VOB_MUXER  && ctx->oformat == &mpeg2vob_muxer ||
                   ENABLE_MPEG2DVD_MUXER  && ctx->oformat == &mpeg2dvd_muxer ||
                   ENABLE_MPEG2SVCD_MUXER && ctx->oformat == &mpeg2svcd_muxer);
    s->is_dvd =   (ENABLE_MPEG2DVD_MUXER  && ctx->oformat == &mpeg2dvd_muxer);

    if(ctx->packet_size)
        s->packet_size = ctx->packet_size;
    else
        s->packet_size = 2048;

    s->vcd_padding_bytes_written = 0;
    s->vcd_padding_bitrate=0;

    s->audio_bound = 0;
    s->video_bound = 0;
    mpa_id = AUDIO_ID;
    ac3_id = AC3_ID;
    dts_id = DTS_ID;
    mpv_id = VIDEO_ID;
    mps_id = SUB_ID;
    lpcm_id = LPCM_ID;
    for(i=0;i<ctx->nb_streams;i++) {
        st = ctx->streams[i];
        stream = av_mallocz(sizeof(StreamInfo));
        if (!stream)
            goto fail;
        st->priv_data = stream;

        av_set_pts_info(st, 64, 1, 90000);

        switch(st->codec->codec_type) {
        case CODEC_TYPE_AUDIO:
            if (st->codec->codec_id == CODEC_ID_AC3) {
                stream->id = ac3_id++;
            } else if (st->codec->codec_id == CODEC_ID_DTS) {
                stream->id = dts_id++;
            } else if (st->codec->codec_id == CODEC_ID_PCM_S16BE) {
                stream->id = lpcm_id++;
                for(j = 0; j < 4; j++) {
                    if (lpcm_freq_tab[j] == st->codec->sample_rate)
                        break;
                }
                if (j == 4)
                    goto fail;
                if (st->codec->channels > 8)
                    return -1;
                stream->lpcm_header[0] = 0x0c;
                stream->lpcm_header[1] = (st->codec->channels - 1) | (j << 4);
                stream->lpcm_header[2] = 0x80;
                stream->lpcm_align = st->codec->channels * 2;
            } else {
                stream->id = mpa_id++;
            }

            /* This value HAS to be used for VCD (see VCD standard, p. IV-7).
               Right now it is also used for everything else.*/
            stream->max_buffer_size = 4 * 1024;
            s->audio_bound++;
            break;
        case CODEC_TYPE_VIDEO:
            stream->id = mpv_id++;
            if (st->codec->rc_buffer_size)
                stream->max_buffer_size = 6*1024 + st->codec->rc_buffer_size/8;
            else
                stream->max_buffer_size = 230*1024; //FIXME this is probably too small as default
#if 0
                /* see VCD standard, p. IV-7*/
                stream->max_buffer_size = 46 * 1024;
            else
                /* This value HAS to be used for SVCD (see SVCD standard, p. 26 V.2.3.2).
                   Right now it is also used for everything else.*/
                stream->max_buffer_size = 230 * 1024;
#endif
            s->video_bound++;
            break;
        case CODEC_TYPE_SUBTITLE:
            stream->id = mps_id++;
            stream->max_buffer_size = 16 * 1024;
            break;
        default:
            return -1;
        }
        av_fifo_init(&stream->fifo, 16);
    }
    bitrate = 0;
    audio_bitrate = 0;
    video_bitrate = 0;
    for(i=0;i<ctx->nb_streams;i++) {
        int codec_rate;
        st = ctx->streams[i];
        stream = (StreamInfo*) st->priv_data;

        if(st->codec->rc_max_rate || stream->id==VIDEO_ID)
            codec_rate= st->codec->rc_max_rate;
        else
            codec_rate= st->codec->bit_rate;

        if(!codec_rate)
            codec_rate= (1<<21)*8*50/ctx->nb_streams;

        bitrate += codec_rate;

        if (stream->id==AUDIO_ID)
            audio_bitrate += codec_rate;
        else if (stream->id==VIDEO_ID)
            video_bitrate += codec_rate;
    }

    if(ctx->mux_rate){
        s->mux_rate= (ctx->mux_rate + (8 * 50) - 1) / (8 * 50);
    } else {
        /* we increase slightly the bitrate to take into account the
           headers. XXX: compute it exactly */
        bitrate += bitrate*5/100;
        bitrate += 10000;
        s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50);
    }

    if (s->is_vcd) {
        double overhead_rate;

        /* The VCD standard mandates that the mux_rate field is 3528
           (see standard p. IV-6).
           The value is actually "wrong", i.e. if you calculate
           it using the normal formula and the 75 sectors per second transfer
           rate you get a different value because the real pack size is 2324,
           not 2352. But the standard explicitly specifies that the mux_rate
           field in the header must have this value.*/
//        s->mux_rate=2352 * 75 / 50;    /* = 3528*/

        /* The VCD standard states that the muxed stream must be

⌨️ 快捷键说明

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