[FFmpeg-devel] [PATCH] Added queueing for OutputStreams to sidestep DVB subtitle encoding bug.

Wim Vander Schelden wim at fixnum.org
Fri Nov 15 16:50:09 CET 2013


Hi,

I've got a possible solution for http://trac.ffmpeg.org/ticket/2024. It's
not the prettiest or most elegant solution, but it "works for my
samples"™.I'm open to feedback on how to improve this, I'd love to get
this fix
merged.

Kind regards,

Wim Vander Schelden
http://fixnum.org

From: Wim Vander Schelden <wim at fixnum.org>
Date: Fri, 15 Nov 2013 16:40:32 +0100
Subject: [PATCH] Added queueing for OutputStreams to sidestep DVB subtitle
 encoding bug.


Signed-off-by: Wim Vander Schelden <wim at fixnum.org>
---
 ffmpeg.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 ffmpeg.h |  9 +++++++++
 2 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/ffmpeg.c b/ffmpeg.c
index 2a88535..2177784 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -543,6 +543,51 @@ static void update_benchmark(const char *fmt, ...)
     }
 }

+#define STAMP(pkt) ( ((pkt)->dts == AV_NOPTS_VALUE) ? (pkt)->pts :
(pkt)->dts)
+
+static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream
*ost);
+static void queue_frame(AVFormatContext *s, AVPacket *pkt, OutputStream
*ost)
+{
+    PacketQueue *last = ost->queue, *new;
+    new = av_mallocz(sizeof(PacketQueue));
+    new->s   = s;
+    new->pkt = av_memdup(pkt, sizeof(AVPacket));
+    new->ost = ost;
+
+    if(STAMP(pkt) == AV_NOPTS_VALUE) {
+       write_frame(s, pkt, ost);
+       return;
+    }
+
+    if(!last) {
+       ost->queue = new;
+       return;
+    }
+
+    while(last && last->next && STAMP(last->next->pkt) < STAMP(pkt)) {
+       last = last->next;
+    }
+
+    new->next  = last->next;
+    last->next = new;
+}
+
+static void flush_queue(OutputStream *ost, int64_t ts)
+{
+    PacketQueue *last;
+
+    if(ts == AV_NOPTS_VALUE)
+       return;
+
+    while(ost->queue && STAMP(ost->queue->pkt) <= ts) {
+       last = ost->queue;
+       ost->queue = ost->queue->next;
+       write_frame(last->s, last->pkt, last->ost);
+       av_free(last->pkt);
+       av_free(last);
+    }
+}
+
 static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream
*ost)
 {
     AVBitStreamFilterContext *bsfc = ost->bitstream_filters;
@@ -604,6 +649,8 @@ static void write_frame(AVFormatContext *s, AVPacket
*pkt, OutputStream *ost)
         bsfc = bsfc->next;
     }

+    flush_queue(ost, STAMP(pkt));
+
     if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS) &&
         (avctx->codec_type == AVMEDIA_TYPE_AUDIO || avctx->codec_type ==
AVMEDIA_TYPE_VIDEO) &&
         pkt->dts != AV_NOPTS_VALUE &&
@@ -651,6 +698,8 @@ static void close_output_stream(OutputStream *ost)
 {
     OutputFile *of = output_files[ost->file_index];

+    flush_queue(ost, INT64_MAX);
+
     ost->finished = 1;
     if (of->shortest) {
         int64_t end = av_rescale_q(ost->sync_opts - ost->first_pts,
ost->st->codec->time_base, AV_TIME_BASE_Q);
@@ -788,7 +837,10 @@ static void do_subtitle_out(AVFormatContext *s,
                 pkt.pts += 90 * sub->end_display_time;
         }
         subtitle_size += pkt.size;
-        write_frame(s, &pkt, ost);
+       if(i == 0)
+           write_frame(s, &pkt, ost);
+       else
+           queue_frame(s, &pkt, ost);
     }
 }

diff --git a/ffmpeg.h b/ffmpeg.h
index 409525c..6968135 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -312,6 +312,14 @@ enum forced_keyframes_const {

 extern const char *const forced_keyframes_const_names[];

+struct OutputStream;
+typedef struct PacketQueue {
+    AVFormatContext *s;
+    AVPacket *pkt;
+    struct OutputStream *ost;
+    struct PacketQueue *next;
+} PacketQueue;
+
 typedef struct OutputStream {
     int file_index;          /* file index */
     int index;               /* stream index in the output file */
@@ -375,6 +383,7 @@ typedef struct OutputStream {
     int keep_pix_fmt;

     AVCodecParserContext *parser;
+    PacketQueue *queue;
 } OutputStream;

 typedef struct OutputFile {
-- 
1.8.1.4


More information about the ffmpeg-devel mailing list