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

📄 mpeg.c

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.10平台上编译为嵌入式图形界面操作系统。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * MPEG1/2 mux/demux * Copyright (c) 2000, 2001, 2002 Fabrice Bellard. * * This library 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 of the License, or (at your option) any later version. * * This library 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 this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "avformat.h"#define MAX_PAYLOAD_SIZE 4096#define NB_STREAMS 2typedef struct {    uint8_t buffer[MAX_PAYLOAD_SIZE];    int buffer_ptr;    uint8_t id;    int max_buffer_size; /* in bytes */    int packet_number;    int64_t start_pts;} StreamInfo;typedef struct {    int packet_size; /* required packet size */    int packet_data_max_size; /* maximum data size inside a packet */    int packet_number;    int pack_header_freq;     /* frequency (in packets^-1) at which we send pack headers */    int system_header_freq;    int mux_rate; /* bitrate in units of 50 bytes/s */    /* stream info */    int audio_bound;    int video_bound;    int is_mpeg2;    int is_vcd;} MpegMuxContext;#define PACK_START_CODE             ((unsigned int)0x000001ba)#define SYSTEM_HEADER_START_CODE    ((unsigned int)0x000001bb)#define SEQUENCE_END_CODE           ((unsigned int)0x000001b7)#define PACKET_START_CODE_MASK      ((unsigned int)0xffffff00)#define PACKET_START_CODE_PREFIX    ((unsigned int)0x00000100)#define ISO_11172_END_CODE          ((unsigned int)0x000001b9)  /* mpeg2 */#define PROGRAM_STREAM_MAP 0x1bc#define PRIVATE_STREAM_1   0x1bd#define PADDING_STREAM     0x1be#define PRIVATE_STREAM_2   0x1bf#define AUDIO_ID 0xc0#define VIDEO_ID 0xe0#ifdef CONFIG_ENCODERSextern AVOutputFormat mpeg1system_mux;extern AVOutputFormat mpeg1vcd_mux;extern AVOutputFormat mpeg2vob_mux;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, 1, 1);    put_bits(&pb, 22, s->mux_rate);    put_bits(&pb, 1, 1);    if (s->is_mpeg2) {        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){    MpegMuxContext *s = ctx->priv_data;    int size, rate_bound, 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);        rate_bound = s->mux_rate; /* maximum bit rate of the multiplexed stream */    put_bits(&pb, 22, rate_bound);    put_bits(&pb, 1, 1); /* marker */    put_bits(&pb, 6, s->audio_bound);    put_bits(&pb, 1, 1); /* variable bitrate */    put_bits(&pb, 1, 1); /* non constrainted bit stream */        put_bits(&pb, 1, 0); /* audio locked */    put_bits(&pb, 1, 0); /* video locked */    put_bits(&pb, 1, 1); /* marker */    put_bits(&pb, 5, s->video_bound);    put_bits(&pb, 8, 0xff); /* reserved byte */        /* audio stream info */    private_stream_coded = 0;    for(i=0;i<ctx->nb_streams;i++) {        StreamInfo *stream = ctx->streams[i]->priv_data;        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 mpeg_mux_init(AVFormatContext *ctx){    MpegMuxContext *s = ctx->priv_data;    int bitrate, i, mpa_id, mpv_id, ac3_id;    AVStream *st;    StreamInfo *stream;    s->packet_number = 0;    s->is_vcd = (ctx->oformat == &mpeg1vcd_mux);    s->is_mpeg2 = (ctx->oformat == &mpeg2vob_mux);        if (s->is_vcd)        s->packet_size = 2324; /* VCD packet size */    else        s->packet_size = 2048;            /* startcode(4) + length(2) + flags(1) */    s->packet_data_max_size = s->packet_size - 7;    s->audio_bound = 0;    s->video_bound = 0;    mpa_id = AUDIO_ID;    ac3_id = 0x80;    mpv_id = VIDEO_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;        switch(st->codec.codec_type) {        case CODEC_TYPE_AUDIO:            if (st->codec.codec_id == CODEC_ID_AC3)                stream->id = ac3_id++;            else                stream->id = mpa_id++;            stream->max_buffer_size = 4 * 1024;             s->audio_bound++;            break;        case CODEC_TYPE_VIDEO:            stream->id = mpv_id++;            stream->max_buffer_size = 46 * 1024;             s->video_bound++;            break;        default:            av_abort();        }    }    /* we increase slightly the bitrate to take into account the       headers. XXX: compute it exactly */    bitrate = 2000;    for(i=0;i<ctx->nb_streams;i++) {        st = ctx->streams[i];        bitrate += st->codec.bit_rate;    }    s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50);        if (s->is_vcd || s->is_mpeg2)        /* every packet */        s->pack_header_freq = 1;    else        /* every 2 seconds */        s->pack_header_freq = 2 * bitrate / s->packet_size / 8;    /* the above seems to make pack_header_freq zero sometimes */    if (s->pack_header_freq == 0)       s->pack_header_freq = 1;        if (s->is_mpeg2)        /* every 200 packets. Need to look at the spec.  */        s->system_header_freq = s->pack_header_freq * 40;    else if (s->is_vcd)        /* every 40 packets, this is my invention */        s->system_header_freq = s->pack_header_freq * 40;    else        s->system_header_freq = s->pack_header_freq * 5;        for(i=0;i<ctx->nb_streams;i++) {        stream = ctx->streams[i]->priv_data;        stream->buffer_ptr = 0;        stream->packet_number = 0;        stream->start_pts = -1;    }    return 0; fail:    for(i=0;i<ctx->nb_streams;i++) {        av_free(ctx->streams[i]->priv_data);    }    return -ENOMEM;}/* flush the packet on stream stream_index */static void flush_packet(AVFormatContext *ctx, int stream_index){    MpegMuxContext *s = ctx->priv_data;    StreamInfo *stream = ctx->streams[stream_index]->priv_data;    uint8_t *buf_ptr;    int size, payload_size, startcode, id, len, stuffing_size, i, header_len;    int64_t timestamp;    uint8_t buffer[128];        id = stream->id;    timestamp = stream->start_pts;#if 0    printf("packet ID=%2x PTS=%0.3f\n",            id, timestamp / 90000.0);#endif    buf_ptr = buffer;    if (((s->packet_number % s->pack_header_freq) == 0)) {        /* output pack and systems header if needed */        size = put_pack_header(ctx, buf_ptr, timestamp);        buf_ptr += size;        if ((s->packet_number % s->system_header_freq) == 0) {            size = put_system_header(ctx, buf_ptr);            buf_ptr += size;        }    }    size = buf_ptr - buffer;    put_buffer(&ctx->pb, buffer, size);    /* packet header */    if (s->is_mpeg2) {        header_len = 8;    } else {        header_len = 5;    }    payload_size = s->packet_size - (size + 6 + header_len);    if (id < 0xc0) {        startcode = PRIVATE_STREAM_1;        payload_size -= 4;    } else {        startcode = 0x100 + id;    }    stuffing_size = payload_size - stream->buffer_ptr;    if (stuffing_size < 0)        stuffing_size = 0;    put_be32(&ctx->pb, startcode);    put_be16(&ctx->pb, payload_size + header_len);    /* stuffing */    for(i=0;i<stuffing_size;i++)        put_byte(&ctx->pb, 0xff);    if (s->is_mpeg2) {        put_byte(&ctx->pb, 0x80); /* mpeg2 id */        put_byte(&ctx->pb, 0x80); /* flags */        put_byte(&ctx->pb, 0x05); /* header len (only pts is included) */    }    put_byte(&ctx->pb,              (0x02 << 4) |              (((timestamp >> 30) & 0x07) << 1) |              1);    put_be16(&ctx->pb, (uint16_t)((((timestamp >> 15) & 0x7fff) << 1) | 1));    put_be16(&ctx->pb, (uint16_t)((((timestamp) & 0x7fff) << 1) | 1));    if (startcode == PRIVATE_STREAM_1) {        put_byte(&ctx->pb, id);        if (id >= 0x80 && id <= 0xbf) {            /* XXX: need to check AC3 spec */            put_byte(&ctx->pb, 1);            put_byte(&ctx->pb, 0);            put_byte(&ctx->pb, 2);        }    }    /* output data */    put_buffer(&ctx->pb, stream->buffer, payload_size - stuffing_size);    put_flush_packet(&ctx->pb);        /* preserve remaining data */    len = stream->buffer_ptr - payload_size;    if (len < 0)         len = 0;    memmove(stream->buffer, stream->buffer + stream->buffer_ptr - len, len);    stream->buffer_ptr = len;    s->packet_number++;    stream->packet_number++;    stream->start_pts = -1;}static int mpeg_mux_write_packet(AVFormatContext *ctx, int stream_index,                                 const uint8_t *buf, int size, int64_t pts){    MpegMuxContext *s = ctx->priv_data;    AVStream *st = ctx->streams[stream_index];    StreamInfo *stream = st->priv_data;    int len;        while (size > 0) {        /* set pts */        if (stream->start_pts == -1) {            stream->start_pts = pts;

⌨️ 快捷键说明

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