[FFmpeg-soc] [soc]: r2417 - dvbmuxer/ffmpeg_svn.patch

bcoudurier subversion at mplayerhq.hu
Mon Jun 9 20:14:53 CEST 2008


Author: bcoudurier
Date: Mon Jun  9 20:14:53 2008
New Revision: 2417

Log:
update ffmpeg svn patch

Modified:
   dvbmuxer/ffmpeg_svn.patch

Modified: dvbmuxer/ffmpeg_svn.patch
==============================================================================
--- dvbmuxer/ffmpeg_svn.patch	(original)
+++ dvbmuxer/ffmpeg_svn.patch	Mon Jun  9 20:14:53 2008
@@ -1,12 +1,10 @@
-Index: libavformat/mpeg_pes_enc.c
+Index: libavformat/mpegpes.h
 ===================================================================
---- libavformat/mpeg_pes_enc.c	(revision 0)
-+++ libavformat/mpeg_pes_enc.c	(revision 0)
-@@ -0,0 +1,351 @@
+--- libavformat/mpegpes.h	(revision 0)
++++ libavformat/mpegpes.h	(revision 0)
+@@ -0,0 +1,139 @@
 +/*
-+ * MPEG PES muxer
 + * Copyright (c) 2000-2002 Fabrice Bellard
-+ * Copyright (c) 2007 Xiaohui Sun <sunxiaohui at dsp.ac.cn>
 + *
 + * This file is part of FFmpeg.
 + *
@@ -25,23 +23,162 @@ Index: libavformat/mpeg_pes_enc.c
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
-+#include "mpeg_pes.h"
-+#include "bytestream.h"
++/**
++ * @file mpegpes.h
++ * MPEG PES packetizer API header
++ */
++
++#ifndef FFMPEG_MPEGPES_H
++#define FFMPEG_MPEGPES_H
++
++#include "avformat.h"
++#include "libavutil/fifo.h"
++
++#define PES_FMT_MPEG2 0x01
++#define PES_FMT_VCD   0x02
++// formats below are all mpeg-2
++#define PES_FMT_SVCD  0x05
++#define PES_FMT_DVD   0x09
++#define PES_FMT_TS    0x11
++
++/**
++ * PES packet description
++ */
++typedef struct PacketDesc {
++    int64_t pts;
++    int64_t dts;
++    int size;
++    int unwritten_size;
++    int flags;
++    struct PacketDesc *next;
++} PacketDesc;
++
++/**
++ * PES stream structure
++ */
++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;
++    int format; ///< mux format (ts, svcd ...)
++} StreamInfo;
++
++#define PRIVATE_STREAM_1   0x1bd
++#define PADDING_STREAM     0x1be
 +
 +/**
 + * Initialization of PES muxer.
-+ * @param[in] ctx the AVFormatContext which contains streams
-+ * @return  On error a negative value is returned, on success zero.
++ * @param[in] ctx AVFormatContext
++ * @return        Negative value on error, zero on success
++ */
++int ff_pes_muxer_init(AVFormatContext *ctx);
++
++/**
++ * Finalization of PES muxer.
++ * @param [in] ctx AVFormatContext
 + */
++void ff_pes_muxer_end(AVFormatContext *ctx);
++
++/**
++ * Write packet into PES fifo.
++ * @param [in] ctx           AVFormatContext
++ * @param [in] pkt           Packet to write
++ * @param [in] packet_number Current muxer packet number
++ */
++void ff_pes_write_packet(AVFormatContext *ctx, AVPacket *pkt, int packet_number);
++
++/**
++ * Output PES packet to the output file.
++ * @param[in]  ctx          AVFormatContext
++ * @param[in]  packet_size  PES stream packet size
++ * @param[in]  flush        Wether flushing remaining data is needed
++ * @param[in]  scr          Last clock reference (SCR for PS, PCR for TS)
++ * @param[out] scr          Updated clock reference, bumped if needed
++ * @param[out] best_i       Index of the stream muxed
++ * @param[in]  flush_packet Function to call to actually write packet to file
++ * @return                  Negative on error, zero if no packet output,
++ *                          else Byte size of flushed data
++ */
++int ff_pes_output_packet(AVFormatContext *ctx, int packet_size,
++                         int64_t *scr, int *best_i, int flush,
++                         int (*flush_packet)(AVFormatContext *, int, int64_t,
++                                             int64_t, int64_t, int));
++
++/**
++ * Write PES data from PES Stream into supplied buffer.
++ * @param [in]  ctx               AVFormatContext
++ * @param [in]  stream_index      Stream index to write from
++ * @param [in]  buf               Buffer to write to
++ * @param [in]  pts               Packet pts
++ * @param [in]  dts               Packet dts
++ * @param [in]  trailer_size      Packet trailer size
++ * @param [in]  packet_size       Total packet size
++ * @param [in]  pad_packet_bytes  Packet padding size
++ * @param [out] payload_size      Packet payload size
++ * @param [out] stuffing_size     Packet stuffing size
++ * @return                        Bytes written to buffer
++ */
++int ff_pes_write_buf(AVFormatContext *ctx, int stream_index, uint8_t *buf,
++          int64_t *pts, int64_t *dts,
++          int trailer_size, int *packet_size, int *pad_packet_bytes,
++          int *payload_size, int *stuffing_size);
++
++/**
++ * Remove decoded packets of each stream.
++ * @param[in] ctx  the AVFormatContext
++ * @param[in] scr  Clock Reference (SCR for PS, PCR for TS)
++ * @return         Negative value on error, 0 on success
++ */
++int ff_pes_remove_decoded_packets(AVFormatContext *ctx, int64_t scr);
++
++#endif /* FFMPEG_MPEGPES_H */
+Index: libavformat/mpegpesenc.c
+===================================================================
+--- libavformat/mpegpesenc.c	(revision 0)
++++ libavformat/mpegpesenc.c	(revision 0)
+@@ -0,0 +1,450 @@
++/*
++ * MPEG PES muxer
++ * Copyright (c) 2000-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 "mpegpes.h"
++#include "mpeg.h"
++#include "libavcodec/bytestream.h"
++
 +int ff_pes_muxer_init(AVFormatContext *ctx)
 +{
-+    AVStream *st;
-+    PESStream *stream;
 +    int i;
 +
 +    for(i=0;i<ctx->nb_streams;i++) {
-+        st = ctx->streams[i];
-+        stream = st->priv_data;
++        AVStream *st = ctx->streams[i];
++        StreamInfo *stream = st->priv_data;
 +        av_set_pts_info(st, 64, 1, 90000);
 +
 +        switch(st->codec->codec_type) {
@@ -51,6 +188,10 @@ Index: libavformat/mpeg_pes_enc.c
 +            stream->max_buffer_size = 4 * 1024;
 +            break;
 +        case CODEC_TYPE_VIDEO:
++            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;
@@ -59,10 +200,6 @@ Index: libavformat/mpeg_pes_enc.c
 +                   Right now it is also used for everything else.*/
 +                stream->max_buffer_size = 230 * 1024;
 +#endif
-+            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
 +            break;
 +        case CODEC_TYPE_SUBTITLE:
 +            stream->max_buffer_size = 16 * 1024;
@@ -75,7 +212,7 @@ Index: libavformat/mpeg_pes_enc.c
 +    return 0;
 +}
 +
-+static inline void insert_timestamp(uint8_t** p, int id, int64_t timestamp)
++static inline void put_timestamp(uint8_t** p, int id, int64_t timestamp)
 +{
 +    bytestream_put_byte(p,
 +        (id << 4) |
@@ -85,14 +222,7 @@ Index: libavformat/mpeg_pes_enc.c
 +    bytestream_put_be16(p, (uint16_t)((((timestamp) & 0x7fff) << 1) | 1));
 +}
 +
-+/**
-+ * Get total number of frames that have been muxed.
-+ * @param[in] ctx    the AVFormatContext
-+ * @param[in] stream the PES stream
-+ * @param[in] len    PES packet size
-+ * @return  the number of frames have been muxed.
-+ */
-+int ff_pes_get_nb_frames(AVFormatContext *ctx, PESStream *stream, int len){
++static int get_nb_frames(AVFormatContext *ctx, StreamInfo *stream, int len){
 +    int nb_frames=0;
 +    PacketDesc *pkt_desc= stream->premux_packet;
 +
@@ -106,99 +236,193 @@ Index: libavformat/mpeg_pes_enc.c
 +    return nb_frames;
 +}
 +
-+/**
-+ * Mux one stream into PES stream.
-+ * @param [in]      ctx            the AVFormatContext which contains streams
-+ * @param [in]      stream_index   the stream index to write
-+ * @param [in]      pes_buffer     PES payload data
-+ * @param [in]      pts            packet presentation timestamp
-+ * @param [in]      dts            packet decoding timestamp
-+ * @param [in]      id             stream ID
-+ * @param [in]      start_code     PES packet start code
-+ * @param [in]      header_len     PES header size
-+ * @param [in]      packet_size    total packet size
-+ * @param [in]      payload_size   packet payload size
-+ * @param [in]      stuffing_size  packet stuffing size
-+ * @return   bytes written to PES stream.
-+ */
-+int ff_pes_muxer_write(AVFormatContext *ctx, int stream_index, uint8_t* pes_buffer,
-+    int64_t pts,int64_t dts, int  id, int startcode,
-+    uint8_t* pes_content, int pes_content_len,
-+    int header_len, int packet_size, int payload_size, int stuffing_size)
++int ff_pes_write_buf(AVFormatContext *ctx, int stream_index, uint8_t *buf,
++                     int64_t *pts, int64_t *dts,
++                     int trailer_size, int *packet_size, int *pad_packet_bytes,
++                     int *payload_size, int *stuffing_size)
 +{
-+    PESStream *stream = ctx->streams[stream_index]->priv_data;
-+    PESContext *context = ctx->priv_data;
-+    int pes_flags, i;
-+    int data_size = payload_size - stuffing_size;
-+    uint8_t *q = pes_buffer;
++    StreamInfo *stream = ctx->streams[stream_index]->priv_data;
++    int startcode, i, header_len;
++    int pes_flags = 0;
++    uint8_t *p = buf;
++    int nb_frames;
 +
-+    bytestream_put_be32(&q, startcode);
++    /* packet header size */
++    *packet_size -= 6;
 +
-+    bytestream_put_be16(&q, packet_size);
-+    bytestream_put_byte(&q, 0x80); /* mpeg2 id */
++    /* packet header */
++    if (stream->format & PES_FMT_MPEG2) {
++        header_len = 3;
++        if (stream->packet_number==0)
++            header_len += 3; /* PES extension */
++        header_len += 1; /* obligatory stuffing byte */
++    } else {
++        header_len = 0;
++    }
 +
-+    pes_flags=0;
++    if (*pts != AV_NOPTS_VALUE) {
++        if (*dts != *pts)
++            header_len += 5 + 5;
++        else
++            header_len += 5;
++    } else {
++        if (!(stream->format & PES_FMT_MPEG2))
++            header_len++;
++    }
 +
-+    if (pts != AV_NOPTS_VALUE) {
-+        pes_flags |= 0x80;
-+        if (dts != pts)
-+           pes_flags |= 0x40;
++    *payload_size = *packet_size - header_len;
++    if (stream->id < 0xc0) {
++        startcode = PRIVATE_STREAM_1;
++        *payload_size -= 1;
++        if (stream->id >= 0x40) {
++            *payload_size -= 3;
++            if (stream->id >= 0xa0)
++                *payload_size -= 3;
++        }
++    } else {
++        startcode = 0x100 + stream->id;
 +    }
 +
-+    /* 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 (context->packet_number == 0 && context->muxer_type == PESMUXER_PS)
-+        pes_flags |= 0x01;
++    *stuffing_size = *payload_size - av_fifo_size(&stream->fifo);
 +
-+    bytestream_put_byte(&q, pes_flags); /* flags */
-+    bytestream_put_byte(&q, header_len - 3 + stuffing_size);
++    // first byte does not 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 += stream->format & PES_FMT_MPEG2 ? 5 : 4;
++        *pts=*dts= AV_NOPTS_VALUE;
++        header_len -= timestamp_len;
++        if (stream->format == PES_FMT_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 (pes_flags & 0x80)  /*write pts*/
-+        insert_timestamp(&q, (pes_flags & 0x40) ? 0x03 : 0x02, pts);
-+    if (pes_flags & 0x40)  /*write dts*/
-+        insert_timestamp(&q, 0x01, dts);
++    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 (pes_flags & 0x01) {  /*write pes extension*/
-+        bytestream_put_byte(&q, 0x10); /* flags */
++    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;
++    }
 +
-+        /* P-STD buffer info */
-+        if (id == AUDIO_ID)
-+            bytestream_put_be16(&q, 0x4000 | stream->max_buffer_size/128);
-+        else
-+            bytestream_put_be16(&q, 0x6000 | stream->max_buffer_size/1024);
++    nb_frames= get_nb_frames(ctx, stream, *payload_size - *stuffing_size);
++
++    bytestream_put_be32(&p, startcode);
++
++    bytestream_put_be16(&p, *packet_size);
++
++    if (!(stream->format & PES_FMT_MPEG2))
++        for(i=0;i<*stuffing_size;i++)
++            bytestream_put_byte(&p, 0xff);
++
++    if (stream->format & PES_FMT_MPEG2) {
++        bytestream_put_byte(&p, 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;
++
++        bytestream_put_byte(&p, pes_flags); /* flags */
++        bytestream_put_byte(&p, header_len - 3 + *stuffing_size);
++
++        if (pes_flags & 0x80)  /*write pts*/
++            put_timestamp(&p, (pes_flags & 0x40) ? 0x03 : 0x02, *pts);
++        if (pes_flags & 0x40)  /*write dts*/
++            put_timestamp(&p, 0x01, *dts);
++
++        if (pes_flags & 0x01) {  /*write pes extension*/
++            bytestream_put_byte(&p, 0x10); /* flags */
++
++            /* P-STD buffer info */
++            if (stream->id == AUDIO_ID)
++                bytestream_put_be16(&p, 0x4000 | stream->max_buffer_size/128);
++            else
++                bytestream_put_be16(&p, 0x6000 | stream->max_buffer_size/1024);
++        }
++
++    } else {
++        if (*pts != AV_NOPTS_VALUE) {
++            if (*dts != *pts) {
++                put_timestamp(&p, 0x03, *pts);
++                put_timestamp(&p, 0x01, *dts);
++            } else {
++                put_timestamp(&p, 0x02, *pts);
++            }
++        } else {
++            bytestream_put_byte(&p, 0x0f);
++        }
 +    }
 +
-+    /* special stuffing byte that is always written
-+       to prevent accidental generation of startcodes. */
-+    bytestream_put_byte(&q, 0xff);
++    if (stream->format & PES_FMT_MPEG2) {
++        /* special stuffing byte that is always written
++           to prevent accidental generation of start codes. */
++        bytestream_put_byte(&p, 0xff);
 +
-+    for(i=0;i<stuffing_size;i++)
-+        bytestream_put_byte(&q, 0xff);
++        for(i=0;i<*stuffing_size;i++)
++            bytestream_put_byte(&p, 0xff);
++    }
 +
-+    if(pes_content != NULL)
-+        bytestream_put_buffer(&q, pes_content, pes_content_len);
++    if (startcode == PRIVATE_STREAM_1) {
++        bytestream_put_byte(&p, stream->id);
++        if (stream->id >= 0xa0) {
++            /* LPCM (XXX: check nb_frames) */
++            bytestream_put_byte(&p, 7);
++            bytestream_put_be16(&p, 4); /* skip 3 header bytes */
++            bytestream_put_byte(&p, stream->lpcm_header[0]);
++            bytestream_put_byte(&p, stream->lpcm_header[1]);
++            bytestream_put_byte(&p, stream->lpcm_header[2]);
++        } else if (stream->id >= 0x40) {
++            /* AC3 */
++            bytestream_put_byte(&p, nb_frames);
++            bytestream_put_be16(&p, trailer_size+1);
++        }
++    }
 +
 +    /* output data */
-+    if(av_fifo_read(&stream->fifo, q, data_size) < 0)
++    assert(*payload_size - *stuffing_size <= av_fifo_size(&stream->fifo));
++    if(av_fifo_read(&stream->fifo, p, *payload_size - *stuffing_size) < 0)
 +        return -1;
-+    return (q - pes_buffer + data_size);
++    return p - buf + *payload_size - *stuffing_size;
 +}
 +
-+/**
-+ * Remove decoded packets of each stream.
-+ * @param[in] ctx  the AVFormatContext
-+ * @param[in] scr  System Clock Reference of PES stream
-+ * @return  On error a negative or zero value is returned, on success 1 is returned.
-+ */
 +int ff_pes_remove_decoded_packets(AVFormatContext *ctx, int64_t scr)
 +{
 +    int i;
 +
 +    for(i=0; i<ctx->nb_streams; i++){
 +        AVStream *st = ctx->streams[i];
-+        PESStream  *stream = st->priv_data;
++        StreamInfo *stream = st->priv_data;
 +        PacketDesc *pkt_desc;
 +
 +        while((pkt_desc= stream->predecode_packet)
@@ -220,26 +444,66 @@ Index: libavformat/mpeg_pes_enc.c
 +    return 0;
 +}
 +
-+/**
-+ * Find the stream to mux into the PES stream.
-+ * @param[in] ctx          the AVFormatContext
-+ * @param[in] packet_size  PES stream packet size
-+ * @param[in] flush        Flush after every single subtitle packet.
-+ * @param[out] best_i      index of stream to be muxed
-+ * @return  On error a negative or zero value is returned, on success 1 is returned.
-+ */
-+int ff_pes_find_beststream(AVFormatContext *ctx, int packet_size, int flush, int64_t *scr, int* best_i)
++void ff_pes_write_packet(AVFormatContext *ctx, AVPacket *pkt, int packet_number)
 +{
-+    int i, avail_space;
++    int stream_index= pkt->stream_index;
++    int size= pkt->size;
++    uint8_t *buf= pkt->data;
++    AVStream *st= ctx->streams[stream_index];
++    StreamInfo *stream= st->priv_data;
++    int64_t pts, dts;
++    PacketDesc *pkt_desc;
++    const int preload= av_rescale(ctx->preload, 90000, AV_TIME_BASE);
++    const int is_iframe = st->codec->codec_type == CODEC_TYPE_VIDEO && (pkt->flags & PKT_FLAG_KEY);
++
++    pts= pkt->pts;
++    dts= pkt->dts;
++
++    if(pts != AV_NOPTS_VALUE) pts += preload;
++    if(dts != AV_NOPTS_VALUE) dts += preload;
++
++//av_log(ctx, AV_LOG_DEBUG, "dts:%f pts:%f flags:%d stream:%d nopts:%d\n", dts/90000.0, pts/90000.0, pkt->flags, pkt->stream_index, pts != AV_NOPTS_VALUE);
++    if (!stream->premux_packet)
++        stream->next_packet = &stream->premux_packet;
++    *stream->next_packet=
++    pkt_desc= av_mallocz(sizeof(PacketDesc));
++    pkt_desc->pts= pts;
++    pkt_desc->dts= dts;
++    pkt_desc->unwritten_size=
++    pkt_desc->size= size;
++    if(!stream->predecode_packet)
++        stream->predecode_packet= pkt_desc;
++    stream->next_packet= &pkt_desc->next;
++
++    av_fifo_realloc(&stream->fifo, av_fifo_size(&stream->fifo) + size);
++
++    if (stream->format == PES_FMT_DVD){
++        if (is_iframe && (packet_number == 0 || (pts - stream->vobu_start_pts >= 36000))) { // min VOBU length 0.4 seconds (mpucoder)
++            stream->bytes_to_iframe = av_fifo_size(&stream->fifo);
++            stream->align_iframe = 1;
++            stream->vobu_start_pts = pts;
++        }
++    }
++
++    av_fifo_generic_write(&stream->fifo, buf, size, NULL);
++}
++
++int ff_pes_output_packet(AVFormatContext *ctx, int packet_size, int64_t *scr,
++                         int *best_i, int flush, int (*flush_packet)())
++{
++    AVStream *st;
++    StreamInfo *stream;
++    int i, avail_space=0, trailer_size;
 +    int best_score= INT_MIN;
 +    int ignore_constraints=0;
++    PacketDesc *timestamp_packet;
 +    const int64_t max_delay= av_rescale(ctx->max_delay, 90000, AV_TIME_BASE);
 +
 +retry:
 +    for(i=0; i<ctx->nb_streams; i++){
-+        AVStream *st = ctx->streams[i];
-+        PESStream*stream = st->priv_data;
-+        const int avail_data=  av_fifo_size(&stream->fifo);
++        AVStream *st= ctx->streams[i];
++        StreamInfo *stream= st->priv_data;
++        const int avail_data= av_fifo_size(&stream->fifo);
 +        const int space= stream->max_buffer_size - stream->buffer_index;
 +        int rel_space= 1024*space / stream->max_buffer_size;
 +        PacketDesc *next_pkt= stream->premux_packet;
@@ -271,7 +535,7 @@ Index: libavformat/mpeg_pes_enc.c
 +
 +        for(i=0; i<ctx->nb_streams; i++){
 +            AVStream *st = ctx->streams[i];
-+            PESStream *stream = st->priv_data;
++            StreamInfo *stream = st->priv_data;
 +            PacketDesc *pkt_desc= stream->predecode_packet;
 +            if(pkt_desc && pkt_desc->dts < best_dts)
 +                best_dts= pkt_desc->dts;
@@ -293,58 +557,37 @@ Index: libavformat/mpeg_pes_enc.c
 +            return -1;
 +        goto retry;
 +    }
-+    assert(avail_space >= packet_size || ignore_constraints);
-+    return 1;
-+}
 +
-+/**
-+ * Write packet into PES FIFO.
-+ * @param [in] ctx  the AVFormatContext which contains streams.
-+ * @param [in] pkt  the packet to write.
-+ * @return  NULL
-+ */
-+void ff_pes_write_packet(AVFormatContext *ctx, AVPacket *pkt)
-+{
-+    int stream_index= pkt->stream_index;
-+    int size= pkt->size;
-+    uint8_t *buf= pkt->data;
-+    AVStream *st = ctx->streams[stream_index];
-+    PESStream *stream = st->priv_data;
-+    int64_t pts, dts;
-+    PacketDesc *pkt_desc;
-+    const int preload= av_rescale(ctx->preload, 90000, AV_TIME_BASE);
++    assert(*best_i >= 0);
 +
-+    pts= pkt->pts;
-+    dts= pkt->dts;
++    st = ctx->streams[*best_i];
++    stream = st->priv_data;
 +
-+    if(pts != AV_NOPTS_VALUE) pts += preload;
-+    if(dts != AV_NOPTS_VALUE) dts += preload;
++    assert(av_fifo_size(&stream->fifo) > 0);
 +
-+//av_log(ctx, AV_LOG_DEBUG, "dts:%f pts:%f flags:%d stream:%d nopts:%d\n", dts/90000.0, pts/90000.0, pkt->flags, pkt->stream_index, pts != AV_NOPTS_VALUE);
-+    if (!stream->premux_packet)
-+        stream->next_packet = &stream->premux_packet;
-+    *stream->next_packet=
-+    pkt_desc= av_mallocz(sizeof(PacketDesc));
-+    pkt_desc->pts= pts;
-+    pkt_desc->dts= dts;
-+    pkt_desc->unwritten_size=
-+    pkt_desc->size= size;
-+    if(!stream->predecode_packet)
-+        stream->predecode_packet= pkt_desc;
-+    stream->next_packet= &pkt_desc->next;
++    assert(avail_space >= packet_size || ignore_constraints);
 +
-+    av_fifo_realloc(&stream->fifo, av_fifo_size(&stream->fifo) + size + 1);
-+    av_fifo_write(&stream->fifo, buf, size);
++    timestamp_packet= stream->premux_packet;
++    if(timestamp_packet->unwritten_size == timestamp_packet->size){
++        trailer_size= 0;
++    }else{
++        trailer_size= timestamp_packet->unwritten_size;
++        timestamp_packet= timestamp_packet->next;
++    }
++
++    if(timestamp_packet){
++//av_log(ctx, AV_LOG_DEBUG, "dts:%f pts:%f pcr:%f stream:%d\n", timestamp_packet->dts/90000.0, timestamp_packet->pts/90000.0, pcr/90000.0, best_i);
++        return flush_packet(ctx, *best_i, timestamp_packet->pts, timestamp_packet->dts, *scr, trailer_size);
++    }else{
++        assert(av_fifo_size(&stream->fifo) == trailer_size);
++        return flush_packet(ctx, *best_i, AV_NOPTS_VALUE, AV_NOPTS_VALUE, *scr, trailer_size);
++    }
 +}
 +
-+/**
-+ * Finalization of PES muxer.
-+ * @param [in] ctx the AVFormatContext which contains streams.
-+ * @return  NULL
-+ */
++
 +void ff_pes_muxer_end(AVFormatContext *ctx)
 +{
-+    PESStream *stream;
++    StreamInfo *stream;
 +    int i;
 +
 +    for(i=0;i<ctx->nb_streams;i++) {
@@ -356,190 +599,662 @@ Index: libavformat/mpeg_pes_enc.c
 +}
 Index: libavformat/Makefile
 ===================================================================
---- libavformat/Makefile	(revision 11662)
+--- libavformat/Makefile	(revision 13661)
 +++ libavformat/Makefile	(working copy)
-@@ -97,7 +97,7 @@
+@@ -102,7 +102,7 @@
  OBJS-$(CONFIG_MPEGPS_DEMUXER)            += mpeg.o
  OBJS-$(CONFIG_MPEGTS_DEMUXER)            += mpegts.o
  OBJS-$(CONFIG_MPEGTSRAW_DEMUXER)         += mpegts.o
 -OBJS-$(CONFIG_MPEGTS_MUXER)              += mpegtsenc.o
-+OBJS-$(CONFIG_MPEGTS_MUXER)              += mpegtsenc.o mpeg_pes_enc.o
++OBJS-$(CONFIG_MPEGTS_MUXER)              += mpegtsenc.o mpegpesenc.o
  OBJS-$(CONFIG_MPEGVIDEO_DEMUXER)         += raw.o
  OBJS-$(CONFIG_MPJPEG_MUXER)              += mpjpeg.o
- OBJS-$(CONFIG_MTV_DEMUXER)               += mtv.o
+ OBJS-$(CONFIG_MSNWC_TCP_DEMUXER)         += msnwc_tcp.o
+Index: libavformat/mpegenc.c
+===================================================================
+--- libavformat/mpegenc.c	(revision 13661)
++++ libavformat/mpegenc.c	(working copy)
+@@ -23,6 +23,7 @@
+ #include "libavcodec/bitstream.h"
+ #include "avformat.h"
+ #include "mpeg.h"
++#include "mpegpes.h"
+ 
+ #define MAX_PAYLOAD_SIZE 4096
+ //#define DEBUG_SEEK
+@@ -30,32 +31,7 @@
+ #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 */
+@@ -73,7 +49,7 @@
+ 
+     double vcd_padding_bitrate; //FIXME floats
+     int64_t vcd_padding_bytes_written;
+-
++    uint8_t *payload; ///< PES packet buffer
+ } MpegMuxContext;
+ 
+ extern AVOutputFormat mpeg1vcd_muxer;
+@@ -308,7 +284,9 @@
+         s->packet_size = ctx->packet_size;
+     else
+         s->packet_size = 2048;
+-
++    s->payload = av_mallocz(s->packet_size);
++    if (!s->payload)
++        return AVERROR(ENOMEM);
+     s->vcd_padding_bytes_written = 0;
+     s->vcd_padding_bitrate=0;
+ 
+@@ -327,6 +305,11 @@
+             goto fail;
+         st->priv_data = stream;
+ 
++        /* set StreamInfo format */
++        if (s->is_dvd)   stream->format = PES_FMT_DVD;
++        if (s->is_svcd)  stream->format = PES_FMT_SVCD;
++        if (s->is_mpeg2) stream->format = PES_FMT_MPEG2;
++        if (s->is_vcd)   stream->format = PES_FMT_VCD;
+         av_set_pts_info(st, 64, 1, 90000);
+ 
+         switch(st->codec->codec_type) {
+@@ -482,17 +465,6 @@
+     return AVERROR(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)
+@@ -621,20 +593,6 @@
+         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)
+@@ -642,14 +600,12 @@
+     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 size, payload_size, id, stuffing_size, i;
+     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;
+ 
+@@ -750,171 +706,14 @@
+     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 - av_fifo_size(&stream->fifo);
+-
+-        // first byte does not 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*/
+-                put_timestamp(ctx->pb, (pes_flags & 0x40) ? 0x03 : 0x02, pts);
+-            if (pes_flags & 0x40)  /*write dts*/
+-                put_timestamp(ctx->pb, 0x01, dts);
+-
+-            if (pes_flags & 0x01) {  /*write pes extension*/
+-                put_byte(ctx->pb, 0x10); /* flags */
+-
+-                /* P-STD buffer info */
+-                if (id == AUDIO_ID)
+-                    put_be16(ctx->pb, 0x4000 | stream->max_buffer_size/128);
+-                else
+-                    put_be16(ctx->pb, 0x6000 | stream->max_buffer_size/1024);
+-            }
+-
+-        } else {
+-            if (pts != AV_NOPTS_VALUE) {
+-                if (dts != pts) {
+-                    put_timestamp(ctx->pb, 0x03, pts);
+-                    put_timestamp(ctx->pb, 0x01, dts);
+-                } else {
+-                    put_timestamp(ctx->pb, 0x02, pts);
+-                }
+-            } else {
+-                put_byte(ctx->pb, 0x0f);
+-            }
+-        }
+-
+-        if (s->is_mpeg2) {
+-            /* special stuffing byte that is always written
+-               to prevent accidental generation of start codes. */
+-            put_byte(ctx->pb, 0xff);
+-
+-            for(i=0;i<stuffing_size;i++)
+-                put_byte(ctx->pb, 0xff);
+-        }
+-
+-        if (startcode == PRIVATE_STREAM_1) {
+-            put_byte(ctx->pb, id);
+-            if (id >= 0xa0) {
+-                /* LPCM (XXX: check nb_frames) */
+-                put_byte(ctx->pb, 7);
+-                put_be16(ctx->pb, 4); /* skip 3 header bytes */
+-                put_byte(ctx->pb, stream->lpcm_header[0]);
+-                put_byte(ctx->pb, stream->lpcm_header[1]);
+-                put_byte(ctx->pb, stream->lpcm_header[2]);
+-            } else if (id >= 0x40) {
+-                /* AC3 */
+-                put_byte(ctx->pb, nb_frames);
+-                put_be16(ctx->pb, trailer_size+1);
+-            }
+-        }
+-
++        int pes_size = ff_pes_write_buf(ctx, stream_index, s->payload,
++                                        &pts, &dts, trailer_size,
++                                        &packet_size, &pad_packet_bytes,
++                                        &payload_size, &stuffing_size);
++        if(pes_size < 0)
++            return -1;
+         /* output data */
+-        assert(payload_size - stuffing_size <= av_fifo_size(&stream->fifo));
+-        av_fifo_generic_read(&stream->fifo, payload_size - stuffing_size, &put_buffer, ctx->pb);
++        put_buffer(ctx->pb, s->payload, pes_size);
+         stream->bytes_to_iframe -= payload_size - stuffing_size;
+     }else{
+         payload_size=
+@@ -987,130 +786,18 @@
+ }
+ #endif
+ 
+-static int remove_decoded_packets(AVFormatContext *ctx, int64_t scr){
+-//    MpegMuxContext *s = ctx->priv_data;
+-    int i;
+-
+-    for(i=0; i<ctx->nb_streams; i++){
+-        AVStream *st = ctx->streams[i];
+-        StreamInfo *stream = st->priv_data;
+-        PacketDesc *pkt_desc;
+-
+-        while((pkt_desc= stream->predecode_packet)
+-              && scr > pkt_desc->dts){ //FIXME > vs >=
+-            if(stream->buffer_index < pkt_desc->size ||
+-               stream->predecode_packet == stream->premux_packet){
+-                av_log(ctx, AV_LOG_ERROR,
+-                       "buffer underflow i=%d bufi=%d size=%d\n",
+-                       i, stream->buffer_index, pkt_desc->size);
+-                break;
+-            }
+-            stream->buffer_index -= pkt_desc->size;
+-
+-            stream->predecode_packet= pkt_desc->next;
+-            av_freep(&pkt_desc);
+-        }
+-    }
+-
+-    return 0;
+-}
+-
+ static int output_packet(AVFormatContext *ctx, int flush){
+     MpegMuxContext *s = ctx->priv_data;
+-    AVStream *st;
+     StreamInfo *stream;
+-    int i, avail_space=0, es_size, trailer_size;
++    int es_size;
+     int best_i= -1;
+-    int best_score= INT_MIN;
+-    int ignore_constraints=0;
+     int64_t scr= s->last_scr;
+-    PacketDesc *timestamp_packet;
+-    const int64_t max_delay= av_rescale(ctx->max_delay, 90000, AV_TIME_BASE);
+ 
+-retry:
+-    for(i=0; i<ctx->nb_streams; i++){
+-        AVStream *st = ctx->streams[i];
+-        StreamInfo *stream = st->priv_data;
+-        const int avail_data=  av_fifo_size(&stream->fifo);
+-        const int space= stream->max_buffer_size - stream->buffer_index;
+-        int rel_space= 1024*space / stream->max_buffer_size;
+-        PacketDesc *next_pkt= stream->premux_packet;
++    if ((es_size = ff_pes_output_packet(ctx, s->packet_size, &scr, &best_i,
++                                        flush, flush_packet)) <= 0)
++        return es_size;
++    stream= ctx->streams[best_i]->priv_data;
+ 
+-        /* for subtitle, a single PES packet must be generated,
+-           so we flush after every single subtitle packet */
+-        if(s->packet_size > avail_data && !flush
+-           && st->codec->codec_type != CODEC_TYPE_SUBTITLE)
+-            return 0;
+-        if(avail_data==0)
+-            continue;
+-        assert(avail_data>0);
+-
+-        if(space < s->packet_size && !ignore_constraints)
+-            continue;
+-
+-        if(next_pkt && next_pkt->dts - scr > max_delay)
+-            continue;
+-
+-        if(rel_space > best_score){
+-            best_score= rel_space;
+-            best_i = i;
+-            avail_space= space;
+-        }
+-    }
+-
+-    if(best_i < 0){
+-        int64_t best_dts= INT64_MAX;
+-
+-        for(i=0; i<ctx->nb_streams; i++){
+-            AVStream *st = ctx->streams[i];
+-            StreamInfo *stream = st->priv_data;
+-            PacketDesc *pkt_desc= stream->predecode_packet;
+-            if(pkt_desc && pkt_desc->dts < best_dts)
+-                best_dts= pkt_desc->dts;
+-        }
+-
+-#if 0
+-        av_log(ctx, AV_LOG_DEBUG, "bumping scr, scr:%f, dts:%f\n",
+-               scr/90000.0, best_dts/90000.0);
+-#endif
+-        if(best_dts == INT64_MAX)
+-            return 0;
+-
+-        if(scr >= best_dts+1 && !ignore_constraints){
+-            av_log(ctx, AV_LOG_ERROR, "packet too large, ignoring buffer limits to mux it\n");
+-            ignore_constraints= 1;
+-        }
+-        scr= FFMAX(best_dts+1, scr);
+-        if(remove_decoded_packets(ctx, scr) < 0)
+-            return -1;
+-        goto retry;
+-    }
+-
+-    assert(best_i >= 0);
+-
+-    st = ctx->streams[best_i];
+-    stream = st->priv_data;
+-
+-    assert(av_fifo_size(&stream->fifo) > 0);
+-
+-    assert(avail_space >= s->packet_size || ignore_constraints);
+-
+-    timestamp_packet= stream->premux_packet;
+-    if(timestamp_packet->unwritten_size == timestamp_packet->size){
+-        trailer_size= 0;
+-    }else{
+-        trailer_size= timestamp_packet->unwritten_size;
+-        timestamp_packet= timestamp_packet->next;
+-    }
+-
+-    if(timestamp_packet){
+-//av_log(ctx, AV_LOG_DEBUG, "dts:%f pts:%f scr:%f stream:%d\n", timestamp_packet->dts/90000.0, timestamp_packet->pts/90000.0, scr/90000.0, best_i);
+-        es_size= flush_packet(ctx, best_i, timestamp_packet->pts, timestamp_packet->dts, scr, trailer_size);
+-    }else{
+-        assert(av_fifo_size(&stream->fifo) == trailer_size);
+-        es_size= flush_packet(ctx, best_i, AV_NOPTS_VALUE, AV_NOPTS_VALUE, scr, trailer_size);
+-    }
+-
+     if (s->is_vcd) {
+         /* Write one or more padding sectors, if necessary, to reach
+            the constant overall bitrate.*/
+@@ -1132,7 +819,7 @@
+     if(es_size)
+         stream->premux_packet->unwritten_size -= es_size;
+ 
+-    if(remove_decoded_packets(ctx, s->last_scr) < 0)
++    if(ff_pes_remove_decoded_packets(ctx, s->last_scr) < 0)
+         return -1;
+ 
+     return 1;
+@@ -1141,47 +828,7 @@
+ static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt)
+ {
+     MpegMuxContext *s = ctx->priv_data;
+-    int stream_index= pkt->stream_index;
+-    int size= pkt->size;
+-    uint8_t *buf= pkt->data;
+-    AVStream *st = ctx->streams[stream_index];
+-    StreamInfo *stream = st->priv_data;
+-    int64_t pts, dts;
+-    PacketDesc *pkt_desc;
+-    const int preload= av_rescale(ctx->preload, 90000, AV_TIME_BASE);
+-    const int is_iframe = st->codec->codec_type == CODEC_TYPE_VIDEO && (pkt->flags & PKT_FLAG_KEY);
+-
+-    pts= pkt->pts;
+-    dts= pkt->dts;
+-
+-    if(pts != AV_NOPTS_VALUE) pts += preload;
+-    if(dts != AV_NOPTS_VALUE) dts += preload;
+-
+-//av_log(ctx, AV_LOG_DEBUG, "dts:%f pts:%f flags:%d stream:%d nopts:%d\n", dts/90000.0, pts/90000.0, pkt->flags, pkt->stream_index, pts != AV_NOPTS_VALUE);
+-    if (!stream->premux_packet)
+-        stream->next_packet = &stream->premux_packet;
+-    *stream->next_packet=
+-    pkt_desc= av_mallocz(sizeof(PacketDesc));
+-    pkt_desc->pts= pts;
+-    pkt_desc->dts= dts;
+-    pkt_desc->unwritten_size=
+-    pkt_desc->size= size;
+-    if(!stream->predecode_packet)
+-        stream->predecode_packet= pkt_desc;
+-    stream->next_packet= &pkt_desc->next;
+-
+-    av_fifo_realloc(&stream->fifo, av_fifo_size(&stream->fifo) + size);
+-
+-    if (s->is_dvd){
+-        if (is_iframe && (s->packet_number == 0 || (pts - stream->vobu_start_pts >= 36000))) { // min VOBU length 0.4 seconds (mpucoder)
+-            stream->bytes_to_iframe = av_fifo_size(&stream->fifo);
+-            stream->align_iframe = 1;
+-            stream->vobu_start_pts = pts;
+-        }
+-    }
+-
+-    av_fifo_generic_write(&stream->fifo, buf, size, NULL);
+-
++    ff_pes_write_packet(ctx, pkt, s->packet_number);
+     for(;;){
+         int ret= output_packet(ctx, 0);
+         if(ret<=0)
+@@ -1191,9 +838,7 @@
+ 
+ static int mpeg_mux_end(AVFormatContext *ctx)
+ {
+-//    MpegMuxContext *s = ctx->priv_data;
+-    StreamInfo *stream;
+-    int i;
++    MpegMuxContext *s = ctx->priv_data;
+ 
+     for(;;){
+         int ret= output_packet(ctx, 1);
+@@ -1209,12 +854,9 @@
+     //put_be32(ctx->pb, ISO_11172_END_CODE);
+     //put_flush_packet(ctx->pb);
+ 
+-    for(i=0;i<ctx->nb_streams;i++) {
+-        stream = ctx->streams[i]->priv_data;
++    ff_pes_muxer_end(ctx);
+ 
+-        assert(av_fifo_size(&stream->fifo) == 0);
+-        av_fifo_free(&stream->fifo);
+-    }
++    av_free(s->payload);
+     return 0;
+ }
+ 
 Index: libavformat/mpegtsenc.c
 ===================================================================
---- libavformat/mpegtsenc.c	(revision 11662)
+--- libavformat/mpegtsenc.c	(revision 13661)
 +++ libavformat/mpegtsenc.c	(working copy)
-@@ -21,6 +21,8 @@
+@@ -22,6 +22,8 @@
+ #include "libavutil/crc.h"
  #include "avformat.h"
- #include "crc.h"
  #include "mpegts.h"
-+#include "bytestream.h"
-+#include "mpeg_pes.h"
++#include "libavcodec/bytestream.h"
++#include "mpegpes.h"
  
  /* write DVB SI sections */
  
-@@ -60,8 +62,9 @@
-             b |= 0x40;
-         *q++ = b;
-         *q++ = s->pid;
--        s->cc = (s->cc + 1) & 0xf;
-+        s->cc = (s->cc) & 0xf;
-         *q++ = 0x10 | s->cc;
-+        s->cc++;
-         if (first)
-             *q++ = 0; /* 0 offset */
-         len1 = TS_PACKET_SIZE - (q - packet);
-@@ -136,8 +139,26 @@
+@@ -136,9 +138,10 @@
+ /* we retransmit the SI info at this rate */
  #define SDT_RETRANS_TIME 500
  #define PAT_RETRANS_TIME 100
- #define PCR_RETRANS_TIME 20
-+#define MAX_DELTA_PCR 4500 /**< 90000 / PCR_RETRANS_TIME */
+-#define PCR_RETRANS_TIME 20
++#define MAX_DELTA_PCR 9000 /**< 0.1s according to ISO 13818-1 */
  
-+
-+/**
-+ *  lookup table from codec id to pes stream id
-+ */
-+static int pes_streamid[5] = {
-+   0xe0,        /**< CODEC_TYPE_VIDEO    */
-+   0xc0,        /**< CODEC_TYPE_AUDIO    */
-+   0xbd,        /**< CODEC_TYPE_DATA     */
-+   0xbd,        /**< CODEC_TYPE_SUBTITLE */
-+   0xbd         /**< CODEC_TYPE_NB       */
-+};
-+
  typedef struct MpegTSWriteStream {
-+    PESStream pes_stream;
-+    int packet_size;
-+    int packet_number;
-+    int startcode;  /**< PES header start code */
-+    uint8_t id;
++    StreamInfo pes;
      struct MpegTSService *service;
      int pid; /* stream associated pid */
      int cc;
-@@ -158,6 +179,7 @@
+@@ -154,8 +157,6 @@
+     char *name;
+     char *provider_name;
+     int pcr_pid;
+-    int pcr_packet_count;
+-    int pcr_packet_freq;
  } MpegTSService;
  
  typedef struct MpegTSWrite {
-+    PESContext pes_context;
-     MpegTSSection pat; /* MPEG2 pat table */
-     MpegTSSection sdt; /* MPEG2 sdt table context */
-     MpegTSService **services;
-@@ -168,6 +190,11 @@
+@@ -169,6 +170,9 @@
      int nb_services;
      int onid;
      int tsid;
-+    int packet_number;
-+    int64_t last_pcr; /* last programme clock reference */
-+    int64_t cur_pcr; /* current programme clock reference */
++    int64_t last_pcr; ///< last program clock reference */
++    int64_t cur_pcr;  ///< last program clock reference */
 +    int mux_rate;
-+    int packet_size;
  } MpegTSWrite;
  
  static void mpegts_write_pat(AVFormatContext *s)
-@@ -362,7 +389,8 @@
-     MpegTSWriteStream *ts_st;
-     MpegTSService *service;
-     AVStream *st;
--    int i, total_bit_rate;
-+    int bitrate;
-+    int i;
-     const char *service_name;
- 
-     ts->tsid = DEFAULT_TSID;
-@@ -376,6 +404,14 @@
-     service->pmt.write_packet = section_write_packet;
-     service->pmt.opaque = s;
- 
-+    ts->packet_number = 0;
-+
-+    if(s->packet_size)
-+        ts->packet_size = s->packet_size;
-+    else
-+        ts->packet_size = DEFAULT_PES_PAYLOAD_SIZE;
-+
-+
-     ts->pat.pid = PAT_PID;
-     ts->pat.cc = 0;
-     ts->pat.write_packet = section_write_packet;
-@@ -387,7 +423,6 @@
-     ts->sdt.opaque = s;
- 
+@@ -390,6 +394,7 @@
      /* assign pids to each stream */
--    total_bit_rate = 0;
+     total_bit_rate = 0;
      for(i = 0;i < s->nb_streams; i++) {
++        int codec_rate;
          st = s->streams[i];
          ts_st = av_mallocz(sizeof(MpegTSWriteStream));
-@@ -402,7 +437,13 @@
+         if (!ts_st)
+@@ -403,7 +408,29 @@
          if (st->codec->codec_type == CODEC_TYPE_VIDEO &&
              service->pcr_pid == 0x1fff)
              service->pcr_pid = ts_st->pid;
 -        total_bit_rate += st->codec->bit_rate;
 +
-+        ts_st->id = pes_streamid[st->codec->codec_type];
++        if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
++            ts_st->pes.id = 0xe0;
++        } else if (st->codec->codec_type == CODEC_TYPE_AUDIO &&
++                   (st->codec->codec_id == CODEC_ID_MP2 ||
++                    st->codec->codec_id == CODEC_ID_MP3)) {
++            ts_st->pes.id = 0xc0;
++        } else {
++            ts_st->pes.id = 0xbd;
++            if (st->codec->codec_type == CODEC_TYPE_SUBTITLE) {
++                //private_code = 0x20;
++            }
++        }
 +
-+        if(ts_st->id < 0xc0)
-+            ts_st->startcode = PRIVATE_STREAM_1;
++        ts_st->pes.format = PES_FMT_TS;
++
++        if(st->codec->rc_max_rate)
++            codec_rate= st->codec->rc_max_rate;
 +        else
-+            ts_st->startcode = 0x100 + ts_st->id;
++            codec_rate= st->codec->bit_rate;
++        if(!codec_rate)
++            codec_rate= (1<<21)*8/s->nb_streams;
++        total_bit_rate += codec_rate;
      }
  
      /* if no video stream, use the first stream as PCR */
-@@ -411,13 +452,40 @@
+@@ -412,10 +439,20 @@
          service->pcr_pid = ts_st->pid;
      }
  
 -    if (total_bit_rate <= 8 * 1024)
 -        total_bit_rate = 8 * 1024;
 -    service->pcr_packet_freq = (total_bit_rate * PCR_RETRANS_TIME) /
+-        (TS_PACKET_SIZE * 8 * 1000);
 +    if(ff_pes_muxer_init(s) != 0)
 +        goto fail;
 +
-+    bitrate = 0;
-+    for(i=0;i<s->nb_streams;i++) {
-+        int codec_rate;
-+        st = s->streams[i];
-+        ts_st = (MpegTSWriteStream*) st->priv_data;
-+        if(st->codec->rc_max_rate)
-+            codec_rate= st->codec->rc_max_rate;
-+        else
-+            codec_rate= st->codec->bit_rate;
-+
-+        if(!codec_rate)
-+            bitrate= (1<<21) * 8/s->nb_streams;
-+        bitrate += codec_rate;
-+    }
-+
 +    if(s->mux_rate) {
 +        ts->mux_rate= s->mux_rate;
 +    } else {
-+        bitrate += bitrate * 25 / (8 *  DEFAULT_PES_PAYLOAD_SIZE) +  /* PES header size */
-+                   bitrate * 4 / (8 * TS_PACKET_SIZE) +             /* TS  header size */
-+                   500 * 12 +                                       /* SDT size */
-+                   100 * 16;                                        /* PAT size */
-+        ts->mux_rate = bitrate;
++        total_bit_rate +=
++            total_bit_rate * 25 / (8 * DEFAULT_PES_PAYLOAD_SIZE) + /* PES header size */
++            total_bit_rate * 4 / (8 * TS_PACKET_SIZE) +            /* TS  header size */
++            SDT_RETRANS_TIME * 12 +                                /* SDT size */
++            PAT_RETRANS_TIME * 16;                                 /* PAT size */
++        ts->mux_rate = total_bit_rate;
 +    }
-+    ts->last_pcr = ts->cur_pcr = 0;
 +
-+    service->pcr_packet_freq = (ts->mux_rate * PCR_RETRANS_TIME) /
-         (TS_PACKET_SIZE * 8 * 1000);
--    ts->sdt_packet_freq = (total_bit_rate * SDT_RETRANS_TIME) /
-+    ts->sdt_packet_freq = (ts->mux_rate * SDT_RETRANS_TIME) /
-         (TS_PACKET_SIZE * 8 * 1000);
--    ts->pat_packet_freq = (total_bit_rate * PAT_RETRANS_TIME) /
-+    ts->pat_packet_freq = (ts->mux_rate * PAT_RETRANS_TIME) /
+     ts->sdt_packet_freq = (total_bit_rate * SDT_RETRANS_TIME) /
          (TS_PACKET_SIZE * 8 * 1000);
- #if 0
-     printf("%d %d %d\n",
-@@ -462,46 +530,32 @@
+     ts->pat_packet_freq = (total_bit_rate * PAT_RETRANS_TIME) /
+@@ -463,60 +500,44 @@
      }
  }
  
 -static void write_pts(uint8_t *q, int fourbits, int64_t pts)
-+static void mpegts_write_pes(AVFormatContext *s, MpegTSWriteStream *ts_st,
-+                             const uint8_t *payload, int payload_size)
- {
+-{
 -    int val;
 -
 -    val = fourbits << 4 | (((pts >> 30) & 0x07) << 1) | 1;
@@ -552,45 +1267,43 @@ Index: libavformat/mpegtsenc.c
 -    *q++ = val;
 -}
 -
--/* NOTE: pes_data contains all the PES packet */
--static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
+ /* NOTE: pes_data contains all the PES packet */
+ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
 -                             const uint8_t *payload, int payload_size,
 -                             int64_t pts, int64_t dts)
--{
--    MpegTSWriteStream *ts_st = st->priv_data;
++                             int64_t pcr, const uint8_t *payload, int payload_size)
+ {
+     MpegTSWriteStream *ts_st = st->priv_data;
 +    MpegTSWrite *ts = s->priv_data;
      uint8_t buf[TS_PACKET_SIZE];
      uint8_t *q;
 -    int val, is_start, len, header_len, write_pcr, private_code, flags;
 +    int val, is_start, len, header_len, write_pcr;
      int afc_len, stuffing_len;
-     int64_t pcr = -1; /* avoid warning */
-+    int64_t delta_pcr;
+-    int64_t pcr = -1; /* avoid warning */
  
-+    int offset = 0;
      is_start = 1;
++    ts->cur_pcr = pcr;
      while (payload_size > 0) {
          retransmit_si_info(s);
--
-         write_pcr = 0;
+ 
+-        write_pcr = 0;
++        write_pcr = !ts->cur_pcr;
          if (ts_st->pid == ts_st->service->pcr_pid) {
-             ts_st->service->pcr_packet_count++;
-+            delta_pcr = ts->cur_pcr - ts->last_pcr;
-             if (ts_st->service->pcr_packet_count >=
+-            ts_st->service->pcr_packet_count++;
+-            if (ts_st->service->pcr_packet_count >=
 -                ts_st->service->pcr_packet_freq) {
-+                ts_st->service->pcr_packet_freq || delta_pcr > MAX_DELTA_PCR) {
-+                pcr = delta_pcr > MAX_DELTA_PCR ? ts->last_pcr + MAX_DELTA_PCR : ts->cur_pcr;
-+                pcr += offset* 8*90000LL / ts->mux_rate;
-                 ts_st->service->pcr_packet_count = 0;
+-                ts_st->service->pcr_packet_count = 0;
++            pcr = ts->cur_pcr + (TS_PACKET_SIZE+4+7)*8*90000LL / ts->mux_rate;
++            if (pcr - ts->last_pcr > MAX_DELTA_PCR)
                  write_pcr = 1;
 -                /* XXX: this is incorrect, but at least we have a PCR
 -                   value */
 -                pcr = pts;
-+                ts->last_pcr = pcr;
-             }
+-            }
          }
  
-@@ -509,8 +563,10 @@
+         /* prepare packet header */
          q = buf;
          *q++ = 0x47;
          val = (ts_st->pid >> 8);
@@ -602,9 +1315,18 @@ Index: libavformat/mpegtsenc.c
          *q++ = val;
          *q++ = ts_st->pid;
          *q++ = 0x10 | ts_st->cc | (write_pcr ? 0x20 : 0);
-@@ -525,58 +581,6 @@
+         ts_st->cc = (ts_st->cc + 1) & 0xf;
+         if (write_pcr) {
++            /* add header and pcr bytes to pcr according to specs */
++            pcr = ts->cur_pcr + (4+7)*8*90000LL / ts->mux_rate;
+             *q++ = 7; /* AFC length */
+             *q++ = 0x10; /* flags: PCR present */
+             *q++ = pcr >> 25;
+@@ -525,59 +546,8 @@
+             *q++ = pcr >> 1;
              *q++ = (pcr & 1) << 7;
              *q++ = 0;
++            ts->last_pcr = pcr;
          }
 -        if (is_start) {
 -            /* write PES header */
@@ -661,25 +1383,17 @@ Index: libavformat/mpegtsenc.c
          /* header size */
          header_len = q - buf;
          /* data len */
-@@ -605,71 +609,217 @@
-                 }
-             }
-         }
--        memcpy(buf + TS_PACKET_SIZE - len, payload, len);
--        payload += len;
-+        memcpy(buf + TS_PACKET_SIZE - len, payload + offset, len);
-+        offset += len;
+@@ -610,67 +580,113 @@
+         payload += len;
          payload_size -= len;
          put_buffer(s->pb, buf, TS_PACKET_SIZE);
++        ts->cur_pcr += (TS_PACKET_SIZE+write_pcr)*8*90000LL / ts->mux_rate;
      }
-+    if(pcr != -1)
-+        ts->cur_pcr = pcr;
      put_flush_packet(s->pb);
  }
  
 -static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt)
-+/* Write an MPEG padding packet header. */
-+static void put_padding_packet(uint8_t** pes_payload, int packet_bytes)
++static void put_padding_packet(uint8_t **pes_payload, int packet_bytes)
  {
 -    AVStream *st = s->streams[pkt->stream_index];
 -    int size= pkt->size;
@@ -692,10 +1406,39 @@ Index: libavformat/mpegtsenc.c
 -        /* for subtitle, a single PES packet must be generated */
 -        mpegts_write_pes(s, st, buf, size, pkt->pts, AV_NOPTS_VALUE);
 -        return 0;
--    }
 +    bytestream_put_be32(pes_payload, PADDING_STREAM);
 +    bytestream_put_be16(pes_payload, packet_bytes - 6);
 +    packet_bytes -= 6;
++
++    for(i=0;i<packet_bytes;i++)
++        bytestream_put_byte(pes_payload, 0xff);
++}
++
++/* flush the packet on stream stream_index */
++static int flush_packet(AVFormatContext *ctx, int stream_index,
++                        int64_t pts, int64_t dts, int64_t pcr, int trailer_size)
++{
++    MpegTSWriteStream *stream = ctx->streams[stream_index]->priv_data;
++    int payload_size, stuffing_size, i;
++    int packet_size;
++    int zero_trail_bytes = 0;
++    int pad_packet_bytes = 0;
++    uint8_t *q = stream->payload;
++
++    packet_size = DEFAULT_PES_PAYLOAD_SIZE;
++
++    if (packet_size > 0) {
++        int pes_size = ff_pes_write_buf(ctx, stream_index, stream->payload,
++                                        &pts, &dts, trailer_size,
++                                        &packet_size, &pad_packet_bytes,
++                                        &payload_size, &stuffing_size);
++        if(pes_size < 0)
++            return -1;
++        q += pes_size;
++    }else{
++        payload_size=
++        stuffing_size= 0;
+     }
  
 -    max_payload_size = DEFAULT_PES_PAYLOAD_SIZE;
 -    while (size > 0) {
@@ -716,177 +1459,50 @@ Index: libavformat/mpegtsenc.c
 -            ts_st->payload_pts = AV_NOPTS_VALUE;
 -            ts_st->payload_dts = AV_NOPTS_VALUE;
 -            ts_st->payload_index = 0;
-+    for(i=0;i<packet_bytes;i++)
-+        bytestream_put_byte(pes_payload, 0xff);
-+}
-+/* flush the packet on stream stream_index */
-+static int flush_packet(AVFormatContext *ctx, int stream_index,
-+                         int64_t pts, int64_t dts, int64_t pcr, int trailer_size)
-+{
-+    MpegTSWrite *s = ctx->priv_data;
-+    MpegTSWriteStream *stream = ctx->streams[stream_index]->priv_data;
-+    PESContext* pes_context = &s->pes_context;
-+    PESStream *pes_stream = &stream->pes_stream;
-+    int payload_size, id, stuffing_size, i, header_len;
-+    int packet_size, es_size;
-+    int zero_trail_bytes = 0;
-+    int pad_packet_bytes = 0;
-+    int general_pack = 0;  /*"general" pack without data specific to one stream?*/
-+    int pes_size;
-+    uint8_t* q = stream->payload;
-+
-+    id = stream->id;
-+    packet_size = s->packet_size;
-+
-+    if (packet_size > 0) {
-+
-+        /* packet header size */
-+        packet_size -= 6;
-+
-+        /* packet header */
-+        header_len = 3;
-+        header_len += 1; /* obligatory stuffing byte */
-+        if (pts != AV_NOPTS_VALUE) {
-+            if (dts != pts)
-+                header_len += 5 + 5;
-+            else
-+                header_len += 5;
-         }
-+        payload_size = packet_size - header_len;
-+
-+        stuffing_size = payload_size - av_fifo_size(&pes_stream->fifo);
-+
-+        // first byte does not 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 += 5;
-+            pts=dts= AV_NOPTS_VALUE;
-+            header_len -= timestamp_len;
-+            payload_size += timestamp_len;
-+            stuffing_size += timestamp_len;
-+            if(payload_size > trailer_size)
-+                stuffing_size += payload_size - trailer_size;
-+        }
-+
-+        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;
-+        }
-+        pes_context->packet_number = s->packet_number;
-+        pes_context->muxer_type = PESMUXER_TS;
-+        pes_size = ff_pes_muxer_write(ctx, stream_index, stream->payload, pts, dts, id, stream->startcode, NULL, 0,
-+                 header_len, packet_size, payload_size, stuffing_size);
-+        if(pes_size < 0)
-+            return -1;
-+        q += pes_size;
-+    }else{
-+        payload_size=
-+        stuffing_size= 0;
-     }
--    return 0;
-+
+-        }
 +    if (pad_packet_bytes > 0)
 +        put_padding_packet(&q, pad_packet_bytes);
 +
 +    for(i=0;i<zero_trail_bytes;i++)
 +        bytestream_put_byte(&q, 0x00);
 +
-+    mpegts_write_pes(ctx, stream, stream->payload, q - stream->payload);
-+    put_flush_packet(ctx->pb);
-+
-+    s->packet_number++;
-+
-+    /* only increase the stream packet number if this pack actually contains
-+       something that is specific to this stream! I.e. a dedicated header
-+       or some data.*/
-+    if (!general_pack)
-+        stream->packet_number++;
-+
-+    es_size = payload_size - stuffing_size;
-+    pes_stream->buffer_index += payload_size - stuffing_size;
-+    while(pes_stream->premux_packet && pes_stream->premux_packet->unwritten_size <= es_size){
-+        es_size -= pes_stream->premux_packet->unwritten_size;
-+        pes_stream->premux_packet= pes_stream->premux_packet->next;
-+    }
-+
-+    if(es_size)
-+        pes_stream->premux_packet->unwritten_size -= es_size;
++    mpegts_write_pes(ctx, ctx->streams[stream_index], pcr,
++                     stream->payload, q - stream->payload);
 +
 +    return payload_size - stuffing_size;
- }
- 
++}
++
 +static int output_packet(AVFormatContext *ctx, int flush){
 +    MpegTSWrite *s = ctx->priv_data;
-+    AVStream *st;
-+    PESStream *stream;
-+    int es_size, trailer_size;
-+    int result;
++    StreamInfo *stream;
++    int es_size;
 +    int best_i= -1;
-+    int64_t pcr = s->cur_pcr;
-+    MpegTSWriteStream *ts_st;
-+    PacketDesc *timestamp_packet;
-+
-+    if((result = ff_pes_find_beststream(ctx, s->packet_size, flush, &pcr, &best_i)) <= 0)
-+        return result;
-+
-+    ts_st = ctx->streams[best_i]->priv_data;
-+    if (ts_st->pid == ts_st->service->pcr_pid) {
-+        s->cur_pcr = pcr;
-+    }
-+    assert(best_i >= 0);
-+
-+    st = ctx->streams[best_i];
-+    stream = st->priv_data;
-+
-+    assert(av_fifo_size(&stream->fifo) > 0);
-+
-+    timestamp_packet= stream->premux_packet;
-+    if(s->cur_pcr == 0)
-+        s->cur_pcr = timestamp_packet->dts;
-+    if(timestamp_packet->unwritten_size == timestamp_packet->size){
-+        trailer_size= 0;
-+    }else{
-+        trailer_size= timestamp_packet->unwritten_size;
-+        timestamp_packet= timestamp_packet->next;
-+    }
++    int64_t pcr= s->last_pcr;
 +
-+    if(timestamp_packet){
-+//av_log(ctx, AV_LOG_DEBUG, "dts:%f pts:%f pcr:%f stream:%d\n", timestamp_packet->dts/90000.0, timestamp_packet->pts/90000.0, pcr/90000.0, best_i);
-+        es_size= flush_packet(ctx, best_i, timestamp_packet->pts, timestamp_packet->dts, pcr, trailer_size);
-+    }else{
-+        assert(av_fifo_size(&stream->fifo) == trailer_size);
-+        es_size= flush_packet(ctx, best_i, AV_NOPTS_VALUE, AV_NOPTS_VALUE, pcr, trailer_size);
-+    }
++    if ((es_size = ff_pes_output_packet(ctx, DEFAULT_PES_PAYLOAD_SIZE,
++                                        &pcr, &best_i, flush, flush_packet)) <= 0)
++        return es_size;
++    stream= ctx->streams[best_i]->priv_data;
 +
++    stream->buffer_index += es_size;
++    while(stream->premux_packet && stream->premux_packet->unwritten_size <= es_size){
++        es_size -= stream->premux_packet->unwritten_size;
++        stream->premux_packet= stream->premux_packet->next;
+     }
+-    return 0;
++    if(es_size)
++        stream->premux_packet->unwritten_size -= es_size;
 +
 +    if(ff_pes_remove_decoded_packets(ctx, s->last_pcr) < 0)
 +        return -1;
 +
 +    return 1;
-+}
-+
+ }
+ 
 +
 +static int mpegts_write_packet(AVFormatContext *ctx, AVPacket *pkt)
 +{
-+    int stream_index= pkt->stream_index;
-+    int size = pkt->size;
-+    static int total_size = 0;
-+    AVStream *st = ctx->streams[stream_index];
-+    MpegTSWriteStream *stream = st->priv_data;
-+    PESStream *pes_stream = &stream->pes_stream;
-+    int64_t pts;
-+
-+    total_size += size;
-+    ff_pes_write_packet(ctx, pkt);
-+    pts= pes_stream->predecode_packet->pts;
-+
++    ff_pes_write_packet(ctx, pkt, 0);
 +    for(;;){
 +        int ret = output_packet(ctx, 0);
 +        if(ret<=0)
@@ -923,166 +1539,3 @@ Index: libavformat/mpegtsenc.c
      for(i = 0; i < ts->nb_services; i++) {
          service = ts->services[i];
          av_freep(&service->provider_name);
-Index: libavformat/mpeg_pes.h
-===================================================================
---- libavformat/mpeg_pes.h	(revision 0)
-+++ libavformat/mpeg_pes.h	(revision 0)
-@@ -0,0 +1,158 @@
-+/*
-+ * Copyright (c) 2000-2002 Fabrice Bellard
-+ * Copyright (c) 2007 Xiaohui Sun <sunxiaohui at dsp.ac.cn>
-+ *
-+ * 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
-+ */
-+
-+/**
-+ * @file mpeg_pes.h
-+ * MPEG PES packetizer API header
-+ */
-+
-+#ifndef AVFORMAT_MPEG_PES_H
-+#define AVFORMAT_MPEG_PES_H
-+
-+#include "avformat.h"
-+#include "fifo.h"
-+
-+/**
-+ * PES packet description
-+ */
-+typedef struct PacketDesc {
-+    int64_t pts;
-+    int64_t dts;
-+    int size;
-+    int unwritten_size;
-+    int flags;
-+    struct PacketDesc *next;
-+} PacketDesc;
-+
-+/**
-+ * muxer type for PES
-+ */
-+typedef enum {
-+    PESMUXER_PS,
-+    PESMUXER_TS,
-+    PESMUXER_PES
-+} PESMuxerType;
-+
-+/**
-+ * PES context
-+ */
-+typedef struct {
-+    PESMuxerType muxer_type;
-+    int packet_number;
-+} PESContext;
-+
-+/**
-+ * PES stream structure
-+ */
-+typedef struct {
-+    AVFifoBuffer fifo;
-+    int max_buffer_size; /**< in bytes */
-+    int buffer_index;
-+    PacketDesc *predecode_packet;
-+    PacketDesc *premux_packet;
-+    PacketDesc **next_packet;
-+} PESStream;
-+
-+
-+#define AUDIO_ID 0xc0
-+#define VIDEO_ID 0xe0
-+#define AC3_ID   0x80
-+#define DTS_ID   0x8a
-+#define LPCM_ID  0xa0
-+#define SUB_ID   0x20
-+
-+#define PROGRAM_STREAM_MAP 0x1bc
-+#define PRIVATE_STREAM_1   0x1bd
-+#define PADDING_STREAM     0x1be
-+#define PRIVATE_STREAM_2   0x1bf
-+
-+
-+
-+/**
-+ * Initialization of PES muxer.
-+ * @param[in] ctx the AVFormatContext which contains streams
-+ * @return  On error a negative value is returned, on success zero.
-+ */
-+int ff_pes_muxer_init(AVFormatContext *ctx);
-+
-+/**
-+ * Finalization of PES muxer.
-+ * @param [in] ctx the AVFormatContext which contains streams.
-+ * @return  NULL
-+ */
-+void ff_pes_muxer_end(AVFormatContext *ctx);
-+
-+/**
-+ * Write packet into PES FIFO.
-+ * @param [in] ctx  the AVFormatContext which contains streams.
-+ * @param [in] pkt  the packet to write.
-+ * @return  NULL
-+ */
-+void ff_pes_write_packet(AVFormatContext *ctx, AVPacket *pkt);
-+
-+/**
-+ * Find the stream to mux into the PES stream.
-+ * @param[in] ctx          the AVFormatContext
-+ * @param[in] packet_size  PES stream packet size
-+ * @param[in] flush        Flush after every single subtitle packet.
-+ * @param[out] best_i      index of stream to be muxed
-+ * @return  On error a negative or zero value is returned, on success 1 is returned.
-+ */
-+int ff_pes_find_beststream(AVFormatContext *ctx, int packet_size, int flush, int64_t *scr, int* best_i);
-+
-+/**
-+ * Get total number of frames that have been muxed.
-+ * @param[in] ctx    the AVFormatContext
-+ * @param[in] stream the PES stream
-+ * @param[in] len    PES packet size
-+ * @return  the number of frames have been muxed.
-+ */
-+int ff_pes_get_nb_frames(AVFormatContext *ctx, PESStream *stream, int len);
-+
-+/**
-+ * Mux one stream into PES stream.
-+ * @param [in]      ctx            the AVFormatContext which contains streams
-+ * @param [in]      stream_index   the stream index to write
-+ * @param [in]      pes_buffer     PES payload data
-+ * @param [in]      pts            packet presentation timestamp
-+ * @param [in]      dts            packet decoding timestamp
-+ * @param [in]      id             stream ID
-+ * @param [in]      start_code     PES packet start code
-+ * @param [in]      header_len     PES header size
-+ * @param [in]      packet_size    total packet size
-+ * @param [in]      payload_size   packet payload size
-+ * @param [in]      stuffing_size  packet stuffing size
-+ * @return   bytes written to PES stream.
-+ */
-+int ff_pes_muxer_write(AVFormatContext *ctx, int stream_index, uint8_t *pes_buffer,
-+          int64_t pts,int64_t dts, int  id, int startcode,
-+          uint8_t* pes_content, int pes_content_len,
-+          int header_len, int packet_size, int payload_size, int stuffing_size);
-+
-+/**
-+ * Remove decoded packets of each stream.
-+ * @param[in] ctx  the AVFormatContext
-+ * @param[in] scr  System Clock Reference of PES stream
-+ * @return  On error a negative or zero value is returned, on success 1 is returned.
-+ */
-+int ff_pes_remove_decoded_packets(AVFormatContext *ctx, int64_t scr);
-+
-+#endif/* AVFORMAT_MPEG_PES_H */



More information about the FFmpeg-soc mailing list