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

📄 mpeg.c

📁 ffmpeg源码分析
💻 C
📖 第 1 页 / 共 4 页
字号:
    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           exactly 75 packs / second (the data rate of a single speed cdrom).           Since the video bitrate (probably 1150000 bits/sec) will be below           the theoretical maximum we have to add some padding packets           to make up for the lower data rate.           (cf. VCD standard p. IV-6 )*/        /* Add the header overhead to the data rate.           2279 data bytes per audio pack, 2294 data bytes per video pack*/        overhead_rate = ((audio_bitrate / 8.0) / 2279) * (2324 - 2279);        overhead_rate += ((video_bitrate / 8.0) / 2294) * (2324 - 2294);        overhead_rate *= 8;        /* Add padding so that the full bitrate is 2324*75 bytes/sec */        s->vcd_padding_bitrate = 2324 * 75 * 8 - (bitrate + overhead_rate);    }    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)        /* the standard mandates that there are only two system headers           in the whole file: one in the first packet of each stream.           (see standard p. IV-7 and IV-8) */        s->system_header_freq = 0x7fffffff;    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->packet_number = 0;    }    s->system_header_size = get_system_header_size(ctx);    s->last_scr = 0;    return 0; fail:    for(i=0;i<ctx->nb_streams;i++) {        av_free(ctx->streams[i]->priv_data);    }    return -ENOMEM;}static inline void put_timestamp(ByteIOContext *pb, int id, int64_t timestamp){    put_byte(pb,             (id << 4) |             (((timestamp >> 30) & 0x07) << 1) |             1);    put_be16(pb, (uint16_t)((((timestamp >> 15) & 0x7fff) << 1) | 1));    put_be16(pb, (uint16_t)((((timestamp) & 0x7fff) << 1) | 1));}/* return the number of padding bytes that should be inserted into   the multiplexed stream.*/static int get_vcd_padding_size(AVFormatContext *ctx, int64_t pts){    MpegMuxContext *s = ctx->priv_data;    int pad_bytes = 0;    if (s->vcd_padding_bitrate > 0 && pts!=AV_NOPTS_VALUE)    {        int64_t full_pad_bytes;        full_pad_bytes = (int64_t)((s->vcd_padding_bitrate * (pts / 90000.0)) / 8.0); //FIXME this is wrong        pad_bytes = (int) (full_pad_bytes - s->vcd_padding_bytes_written);        if (pad_bytes<0)            /* might happen if we have already padded to a later timestamp. This               can occur if another stream has already advanced further.*/            pad_bytes=0;    }    return pad_bytes;}#if 0 /* unused, remove? *//* return the exact available payload size for the next packet for   stream 'stream_index'. 'pts' and 'dts' are only used to know if   timestamps are needed in the packet header. */static int get_packet_payload_size(AVFormatContext *ctx, int stream_index,                                   int64_t pts, int64_t dts){    MpegMuxContext *s = ctx->priv_data;    int buf_index;    StreamInfo *stream;    stream = ctx->streams[stream_index]->priv_data;    buf_index = 0;    if (((s->packet_number % s->pack_header_freq) == 0)) {        /* pack header size */        if (s->is_mpeg2)            buf_index += 14;        else            buf_index += 12;        if (s->is_vcd) {            /* there is exactly one system header for each stream in a VCD MPEG,               One in the very first video packet and one in the very first               audio packet (see VCD standard p. IV-7 and IV-8).*/            if (stream->packet_number==0)                /* The system headers refer only to the stream they occur in,                   so they have a constant size.*/                buf_index += 15;        } else {            if ((s->packet_number % s->system_header_freq) == 0)                buf_index += s->system_header_size;        }    }    if ((s->is_vcd && stream->packet_number==0)        || (s->is_svcd && s->packet_number==0))        /* the first pack of each stream contains only the pack header,           the system header and some padding (see VCD standard p. IV-6)           Add the padding size, so that the actual payload becomes 0.*/        buf_index += s->packet_size - buf_index;    else {        /* packet header size */        buf_index += 6;        if (s->is_mpeg2) {            buf_index += 3;            if (stream->packet_number==0)                buf_index += 3; /* PES extension */            buf_index += 1;    /* obligatory stuffing byte */        }        if (pts != AV_NOPTS_VALUE) {            if (dts != pts)                buf_index += 5 + 5;            else                buf_index += 5;        } else {            if (!s->is_mpeg2)                buf_index++;        }        if (stream->id < 0xc0) {            /* AC3/LPCM private data header */            buf_index += 4;            if (stream->id >= 0xa0) {                int n;                buf_index += 3;                /* NOTE: we round the payload size to an integer number of                   LPCM samples */                n = (s->packet_size - buf_index) % stream->lpcm_align;                if (n)                    buf_index += (stream->lpcm_align - n);            }        }        if (s->is_vcd && stream->id == AUDIO_ID)            /* The VCD standard demands that 20 zero bytes follow               each audio packet (see standard p. IV-8).*/            buf_index+=20;    }    return s->packet_size - buf_index;}#endif/* Write an MPEG padding packet header. */static void put_padding_packet(AVFormatContext *ctx, ByteIOContext *pb,int packet_bytes){    MpegMuxContext *s = ctx->priv_data;    int i;    put_be32(pb, PADDING_STREAM);    put_be16(pb, packet_bytes - 6);    if (!s->is_mpeg2) {        put_byte(pb, 0x0f);        packet_bytes -= 7;    } else        packet_bytes -= 6;    for(i=0;i<packet_bytes;i++)        put_byte(pb, 0xff);}static int get_nb_frames(AVFormatContext *ctx, StreamInfo *stream, int len){    int nb_frames=0;    PacketDesc *pkt_desc= stream->premux_packet;    while(len>0){        if(pkt_desc->size == pkt_desc->unwritten_size)            nb_frames++;        len -= pkt_desc->unwritten_size;        pkt_desc= pkt_desc->next;    }    return nb_frames;}/* flush the packet on stream stream_index */static int flush_packet(AVFormatContext *ctx, int stream_index,                         int64_t pts, int64_t dts, int64_t scr, int trailer_size){    MpegMuxContext *s = ctx->priv_data;    StreamInfo *stream = ctx->streams[stream_index]->priv_data;    uint8_t *buf_ptr;    int size, payload_size, startcode, id, stuffing_size, i, header_len;    int packet_size;    uint8_t buffer[128];    int zero_trail_bytes = 0;    int pad_packet_bytes = 0;    int pes_flags;    int general_pack = 0;  /*"general" pack without data specific to one stream?*/    int nb_frames;    id = stream->id;#if 0    printf("packet ID=%2x PTS=%0.3f\n",           id, pts / 90000.0);#endif    buf_ptr = buffer;    if ((s->packet_number % s->pack_header_freq) == 0 || s->last_scr != scr) {        /* output pack and systems header if needed */        size = put_pack_header(ctx, buf_ptr, scr);        buf_ptr += size;        s->last_scr= scr;        if (s->is_vcd) {            /* there is exactly one system header for each stream in a VCD MPEG,               One in the very first video packet and one in the very first               audio packet (see VCD standard p. IV-7 and IV-8).*/            if (stream->packet_number==0) {                size = put_system_header(ctx, buf_ptr, id);                buf_ptr += size;            }        } else if (s->is_dvd) {            if (stream->align_iframe || s->packet_number == 0){                int bytes_to_iframe;                int PES_bytes_to_fill;                if (stream->fifo_iframe_ptr >= stream->fifo.rptr) {                    bytes_to_iframe = stream->fifo_iframe_ptr - stream->fifo.rptr;                } else {                    bytes_to_iframe = (stream->fifo.end - stream->fifo.rptr) + (stream->fifo_iframe_ptr - stream->fifo.buffer);                }                PES_bytes_to_fill = s->packet_size - size - 10;                if (pts != AV_NOPTS_VALUE) {                    if (dts != pts)                        PES_bytes_to_fill -= 5 + 5;                    else                        PES_bytes_to_fill -= 5;                }                if (bytes_to_iframe == 0 || s->packet_number == 0) {                    size = put_system_header(ctx, buf_ptr, 0);                    buf_ptr += size;                    size = buf_ptr - buffer;                    put_buffer(&ctx->pb, buffer, size);                    put_be32(&ctx->pb, PRIVATE_STREAM_2);                    put_be16(&ctx->pb, 0x03d4);         // length                    put_byte(&ctx->pb, 0x00);           // substream ID, 00=PCI                    for (i = 0; i < 979; i++)                        put_byte(&ctx->pb, 0x00);                    put_be32(&ctx->pb, PRIVATE_STREAM_2);                    put_be16(&ctx->pb, 0x03fa);         // length                    put_byte(&ctx->pb, 0x01);           // substream ID, 01=DSI                    for (i = 0; i < 1017; i++)                        put_byte(&ctx->pb, 0x00);                    memset(buffer, 0, 128);                    buf_ptr = buffer;                    s->packet_number++;                    stream->align_iframe = 0;                    scr += s->packet_size*90000LL / (s->mux_rate*50LL); //FIXME rounding and first few bytes of each packet                    size = put_pack_header(ctx, buf_ptr, scr);                    s->last_scr= scr;                    buf_ptr += size;                    /* GOP Start */                } else if (bytes_to_iframe < PES_bytes_to_fill) {                    pad_packet_bytes = PES_bytes_to_fill - bytes_to_iframe;                }            }        } else {            if ((s->packet_number % s->system_header_freq) == 0) {                size = put_system_header(ctx, buf_ptr, 0);                buf_ptr += size;            }        }    }    size = buf_ptr - buffer;    put_buffer(&ctx->pb, buffer, size);    packet_size = s->packet_size - size;    if (s->is_vcd && id == AUDIO_ID)        /* The VCD standard demands that 20 zero bytes follow           each audio pack (see standard p. IV-8).*/        zero_trail_bytes += 20;    if ((s->is_vcd && stream->packet_number==0)        || (s->is_svcd && s->packet_number==0)) {        /* for VCD the first pack of each stream contains only the pack header,           the system header and lots of padding (see VCD standard p. IV-6).           In the case of an audio pack, 20 zero bytes are also added at           the end.*/        /* For SVCD we fill the very first pack to increase compatibility with           some DVD players. Not mandated by the standard.*/        if (s->is_svcd)            general_pack = 1;    /* the system header refers to both streams and no stream data*/        pad_packet_bytes = packet_size - zero_trail_bytes;    }    packet_size -= pad_packet_bytes + zero_trail_bytes;    if (packet_size > 0) {        /* packet header size */        packet_size -= 6;        /* packet header */        if (s->is_mpeg2) {            header_len = 3;            if (stream->packet_number==0)                header_len += 3; /* PES extension */            header_len += 1; /* obligatory stuffing byte */        } else {            header_len = 0;        }        if (pts != AV_NOPTS_VALUE) {            if (dts != pts)                header_len += 5 + 5;            else                header_len += 5;        } else {            if (!s->is_mpeg2)                header_len++;        }        payload_size = packet_size - header_len;        if (id < 0xc0) {            startcode = PRIVATE_STREAM_1;            payload_size -= 1;            if (id >= 0x40) {                payload_size -= 3;                if (id >= 0xa0)                    payload_size -= 3;            }        } else {            startcode = 0x100 + id;        }        stuffing_size = payload_size - fifo_size(&stream->fifo, stream->fifo.rptr);        // first byte doesnt fit -> reset pts/dts + stuffing        if(payload_size <= trailer_size && pts != AV_NOPTS_VALUE){            int timestamp_len=0;            if(dts != pts)                timestamp_len += 5;            if(pts != AV_NOPTS_VALUE)                timestamp_len += s->is_mpeg2 ? 5 : 4;            pts=dts= AV_NOPTS_VALUE;            header_len -= timestamp_len;            if (s->is_dvd && stream->align_iframe) {                pad_packet_bytes += timestamp_len;                packet_size -= timestamp_len;            } else {                payload_size += timestamp_len;            }            stuffing_size += timestamp_len;            if(payload_size > trailer_size)                stuffing_size += payload_size - trailer_size;        }        if (pad_packet_bytes > 0 && pad_packet_bytes <= 7) { // can't use padding, so use stuffing            packet_size += pad_packet_bytes;            payload_size += pad_packet_bytes; // undo the previous adjustment            if (stuffing_size < 0) {                stuffing_size = pad_packet_bytes;            } else {                stuffing_size += pad_packet_bytes;            }            pad_packet_bytes = 0;        }        if (stuffing_size < 0)            stuffing_size = 0;        if (stuffing_size > 16) {    /*<=16 for MPEG-1, <=32 for MPEG-2*/            pad_packet_bytes += stuffing_size;            packet_size -= stuffing_size;            payload_size -= stuffing_size;            stuffing_size = 0;        }        nb_frames= get_nb_frames(ctx, stream, payload_size - stuffing_size);        put_be32(&ctx->pb, startcode);        put_be16(&ctx->pb, packet_size);        if (!s->is_mpeg2)            for(i=0;i<stuffing_size;i++)                put_byte(&ctx->pb, 0xff);        if (s->is_mpeg2) {            put_byte(&ctx->pb, 0x80); /* mpeg2 id */            pes_flags=0;            if (pts != AV_NOPTS_VALUE) {                pes_flags |= 0x80;                if (dts != pts)                    pes_flags |= 0x40;            }            /* Both the MPEG-2 and the SVCD standards demand that the               P-STD_buffer_size field be included in the first packet of               every stream. (see SVCD standard p. 26 V.2.3.1 and V.2.3.2               and MPEG-2 standard 2.7.7) */            if (stream->packet_number == 0)                pes_flags |= 0x01;            put_byte(&ctx->pb, pes_flags); /* flags */            put_byte(&ctx->pb, header_len - 3 + stuffing_size);            if (pes_flags & 0x80)  /*write pts*/

⌨️ 快捷键说明

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