[libav-devel] [PATCH 1/8] avconv: split off streamcopy handling into a separate loop.

Anton Khirnov anton at khirnov.net
Mon Nov 21 18:32:45 CET 2011


This is easier to understand and is less likely to break horribly when a
stream is to be both decoded and copied.
---
 avconv.c |  162 ++++++++++++++++++++++++++++++++++---------------------------
 1 files changed, 90 insertions(+), 72 deletions(-)

diff --git a/avconv.c b/avconv.c
index c962b2b..0537e8c 100644
--- a/avconv.c
+++ b/avconv.c
@@ -1528,6 +1528,83 @@ static void flush_encoders(OutputStream *ost_table, int nb_ostreams)
     }
 }
 
+/*
+ * Check whether a packet from ist should be written into ost at this time
+ */
+static int check_output_constraints(InputStream *ist, OutputStream *ost)
+{
+    OutputFile *of = &output_files[ost->file_index];
+    int ist_index  = ist - input_streams;
+
+    if (ost->source_index != ist_index)
+        return 0;
+
+    if (of->start_time && ist->pts < of->start_time)
+        return 0;
+
+    if (of->recording_time != INT64_MAX &&
+        av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + of->start_time,
+                      (AVRational){1, 1000000}) >= 0) {
+        ost->is_past_recording_time = 1;
+        return 0;
+    }
+
+    return 1;
+}
+
+static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt)
+{
+    OutputFile *of = &output_files[ost->file_index];
+    int64_t ost_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base);
+    AVPacket opkt;
+
+    av_init_packet(&opkt);
+
+    if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) &&
+        !ost->copy_initial_nonkeyframes)
+        return;
+
+    /* force the input stream PTS */
+    if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+        audio_size += pkt->size;
+    else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        video_size += pkt->size;
+        ost->sync_opts++;
+    }
+
+    opkt.stream_index = ost->index;
+    if (pkt->pts != AV_NOPTS_VALUE)
+        opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time;
+    else
+        opkt.pts = AV_NOPTS_VALUE;
+
+    if (pkt->dts == AV_NOPTS_VALUE)
+        opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base);
+    else
+        opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base);
+    opkt.dts -= ost_tb_start_time;
+
+    opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base);
+    opkt.flags    = pkt->flags;
+
+    //FIXME remove the following 2 lines they shall be replaced by the bitstream filters
+    if(   ost->st->codec->codec_id != CODEC_ID_H264
+       && ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO
+       && ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO
+       ) {
+        if (av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, pkt->data, pkt->size, pkt->flags & AV_PKT_FLAG_KEY))
+            opkt.destruct = av_destruct_packet;
+    } else {
+        opkt.data = pkt->data;
+        opkt.size = pkt->size;
+    }
+
+    write_frame(of->ctx, &opkt, ost->st->codec, ost->bitstream_filters);
+    ost->st->codec->frame_number++;
+    ost->frame_number++;
+    av_free_packet(&opkt);
+}
+
 /* pkt = NULL means EOF (needed to flush decoder buffers) */
 static int output_packet(InputStream *ist, int ist_index,
                          OutputStream *ost_table, int nb_ostreams,
@@ -1569,8 +1646,8 @@ static int output_packet(InputStream *ist, int ist_index,
 
     //while we have more to decode or while the decoder did output something on EOF
     while (avpkt.size > 0 || (!pkt && got_output)) {
-        uint8_t *data_buf, *decoded_data_buf;
-        int data_size, decoded_data_size;
+        uint8_t *decoded_data_buf;
+        int decoded_data_size;
         AVFrame *decoded_frame, *filtered_frame;
     handle_eof:
         ist->pts= ist->next_pts;
@@ -1584,8 +1661,6 @@ static int output_packet(InputStream *ist, int ist_index,
         decoded_frame    = filtered_frame = NULL;
         decoded_data_buf = NULL; /* fail safe */
         decoded_data_size= 0;
-        data_buf  = avpkt.data;
-        data_size = avpkt.size;
         subtitle_to_free = NULL;
         if (ist->decoding_needed) {
             switch(ist->st->codec->codec_type) {
@@ -1604,7 +1679,6 @@ static int output_packet(InputStream *ist, int ist_index,
                     return ret;
                 avpkt.data += ret;
                 avpkt.size -= ret;
-                data_size   = ret;
                 got_output  = decoded_data_size > 0;
                 /* Some bug in mpeg audio decoder gives */
                 /* decoded_data_size < 0, it seems they are overflows */
@@ -1745,23 +1819,13 @@ static int output_packet(InputStream *ist, int ist_index,
         /* if output time reached then transcode raw format,
            encode packets and output them */
         for (i = 0; i < nb_ostreams; i++) {
-            OutputFile *of = &output_files[ost_table[i].file_index];
             int frame_size;
 
             ost = &ost_table[i];
-            if (ost->source_index != ist_index)
-                continue;
 
-            if (of->start_time && ist->pts < of->start_time)
+            if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
                 continue;
 
-            if (of->recording_time != INT64_MAX &&
-                av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + of->start_time,
-                              (AVRational){1, 1000000}) >= 0) {
-                ost->is_past_recording_time = 1;
-                continue;
-            }
-
 #if CONFIG_AVFILTER
             if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
                 ost->input_video_filter) {
@@ -1815,64 +1879,8 @@ static int output_packet(InputStream *ist, int ist_index,
                     default:
                         abort();
                     }
-                } else {
-                    AVPacket opkt;
-                    int64_t ost_tb_start_time= av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base);
-
-                    av_init_packet(&opkt);
-
-                    if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) &&
-                        !ost->copy_initial_nonkeyframes)
-#if !CONFIG_AVFILTER
-                        continue;
-#else
-                        goto cont;
-#endif
-
-                    /* no reencoding needed : output the packet directly */
-                    /* force the input stream PTS */
-
-                    if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
-                        audio_size += data_size;
-                    else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-                        video_size += data_size;
-                        ost->sync_opts++;
-                    }
-
-                    opkt.stream_index= ost->index;
-                    if(pkt->pts != AV_NOPTS_VALUE)
-                        opkt.pts= av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time;
-                    else
-                        opkt.pts= AV_NOPTS_VALUE;
-
-                    if (pkt->dts == AV_NOPTS_VALUE)
-                        opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base);
-                    else
-                        opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base);
-                    opkt.dts -= ost_tb_start_time;
-
-                    opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base);
-                    opkt.flags= pkt->flags;
-
-                    //FIXME remove the following 2 lines they shall be replaced by the bitstream filters
-                    if(   ost->st->codec->codec_id != CODEC_ID_H264
-                       && ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO
-                       && ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO
-                       ) {
-                        if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & AV_PKT_FLAG_KEY))
-                            opkt.destruct= av_destruct_packet;
-                    } else {
-                        opkt.data = data_buf;
-                        opkt.size = data_size;
-                    }
-
-                    write_frame(os, &opkt, ost->st->codec, ost->bitstream_filters);
-                    ost->st->codec->frame_number++;
-                    ost->frame_number++;
-                    av_free_packet(&opkt);
                 }
 #if CONFIG_AVFILTER
-                cont:
                 frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
                                    ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]);
                 if (ost->picref)
@@ -1895,6 +1903,16 @@ fail:
     }
  discard_packet:
 
+    /* handle stream copy */
+    for (i = 0; pkt && i < nb_ostreams; i++) {
+        ost = &ost_table[i];
+
+        if (!check_output_constraints(ist, ost) || ost->encoding_needed)
+            continue;
+
+        do_streamcopy(ist, ost, pkt);
+    }
+
     return 0;
 }
 
-- 
1.7.7



More information about the libav-devel mailing list