[FFmpeg-devel] [PATCH 2/5] ffmpeg: use the write_uncoded_frame() API.

Nicolas George george at nsup.org
Wed Jan 15 23:30:01 CET 2014


Signed-off-by: Nicolas George <george at nsup.org>
---
 ffmpeg.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
 ffmpeg.h |  1 +
 2 files changed, 55 insertions(+), 9 deletions(-)


Fixed: the previous patch did call the non-interleaved version.

Change: use a different magic constant for the packet size.


diff --git a/ffmpeg.c b/ffmpeg.c
index 5ccbf10..f998808 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -163,6 +163,9 @@ static struct termios oldtty;
 static int restore_tty;
 #endif
 
+/* Use a different value than the library. */
+#define UNCODED_FRAME_PACKET_SIZE (INT_MIN / 3 * 2 - (int)sizeof(AVFrame))
+
 static void free_input_threads(void);
 
 
@@ -644,7 +647,23 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
               );
     }
 
-    ret = av_interleaved_write_frame(s, pkt);
+    if (ost->uncoded_frame) {
+        AVFrame *frame = av_frame_clone((AVFrame *)pkt->data);
+        av_assert0(!ost->encoding_needed);
+        av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE);
+        if (!frame) {
+            ret = AVERROR(ENOMEM);
+        } else {
+            frame->pts = frame->pkt_pts = pkt->pts;
+            frame->pkt_dts = pkt->dts;
+            av_frame_set_pkt_duration(frame, pkt->duration);
+            ret = av_interleaved_write_uncoded_frame(s, pkt->stream_index, frame);
+            pkt->size = 0;
+            pkt->data = NULL;
+        }
+    } else {
+        ret = av_interleaved_write_frame(s, pkt);
+    }
     if (ret < 0) {
         print_error("av_interleaved_write_frame()", ret);
         exit_program(1);
@@ -693,6 +712,8 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
         frame->pts = ost->sync_opts;
     ost->sync_opts = frame->pts + frame->nb_samples;
 
+    if (ost->encoding_needed) {
+        /* TODO reindent */
     av_assert0(pkt.size || !pkt.data);
     update_benchmark(NULL);
     if (avcodec_encode_audio2(enc, &pkt, frame, &got_packet) < 0) {
@@ -700,6 +721,13 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
         exit_program(1);
     }
     update_benchmark("encode_audio %d.%d", ost->file_index, ost->index);
+    } else {
+        av_assert0(ost->uncoded_frame);
+        pkt.pts = pkt.dts = frame->pts;
+        pkt.data = (void *)frame;
+        pkt.size = UNCODED_FRAME_PACKET_SIZE;
+        got_packet = 1;
+    }
 
     if (got_packet) {
         if (pkt.pts != AV_NOPTS_VALUE)
@@ -923,7 +951,7 @@ static void do_video_out(AVFormatContext *s,
             in_picture->top_field_first = !!ost->top_field_first;
 
         if (in_picture->interlaced_frame) {
-            if (enc->codec->id == AV_CODEC_ID_MJPEG)
+            if (enc->codec && enc->codec->id == AV_CODEC_ID_MJPEG)
                 enc->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB;
             else
                 enc->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT;
@@ -968,6 +996,8 @@ static void do_video_out(AVFormatContext *s,
             av_log(NULL, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time);
         }
 
+        if (ost->encoding_needed) {
+            /* TODO reindent */
         update_benchmark(NULL);
         ret = avcodec_encode_video2(enc, &pkt, in_picture, &got_packet);
         update_benchmark("encode_video %d.%d", ost->file_index, ost->index);
@@ -975,6 +1005,13 @@ static void do_video_out(AVFormatContext *s,
             av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
             exit_program(1);
         }
+        } else {
+            av_assert0(ost->uncoded_frame);
+            pkt.pts = pkt.dts = in_picture->pts;
+            pkt.data = (void *)in_picture;
+            pkt.size = UNCODED_FRAME_PACKET_SIZE;
+            got_packet = 1;
+        }
 
         if (got_packet) {
             if (pkt.pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & CODEC_CAP_DELAY))
@@ -1117,7 +1154,8 @@ static int reap_filters(void)
                 break;
             case AVMEDIA_TYPE_AUDIO:
                 filtered_frame->pts = frame_pts;
-                if (!(ost->st->codec->codec->capabilities & CODEC_CAP_PARAM_CHANGE) &&
+                if (!(ost->st->codec->codec &&
+                      (ost->st->codec->codec->capabilities & CODEC_CAP_PARAM_CHANGE)) &&
                     ost->st->codec->channels != av_frame_get_channels(filtered_frame)) {
                     av_log(NULL, AV_LOG_ERROR,
                            "Audio filter graph output is not normalized and encoder does not support parameter changes\n");
@@ -1978,7 +2016,8 @@ static int output_packet(InputStream *ist, const AVPacket *pkt)
     for (i = 0; pkt && i < nb_output_streams; i++) {
         OutputStream *ost = output_streams[i];
 
-        if (!check_output_constraints(ist, ost) || ost->encoding_needed)
+        if (!check_output_constraints(ist, ost) || ost->encoding_needed ||
+            ost->uncoded_frame)
             continue;
 
         do_streamcopy(ist, ost, pkt);
@@ -2411,6 +2450,9 @@ static int transcode_init(void)
                 abort();
             }
         } else {
+            ret = av_write_uncoded_frame_query(oc, ost->index);
+            if (ret < 0) {
+                /* TODO reindent */
             if (!ost->enc)
                 ost->enc = avcodec_find_encoder(codec->codec_id);
             if (!ost->enc) {
@@ -2420,10 +2462,15 @@ static int transcode_init(void)
                 ret = AVERROR(EINVAL);
                 goto dump_format;
             }
+                ost->encoding_needed = 1;
+            } else {
+                av_log(oc, AV_LOG_VERBOSE, "Using uncoded frame output "
+                       "for stream #%d\n", ost->index);
+                ost->uncoded_frame = 1;
+            }
 
             if (ist)
                 ist->decoding_needed++;
-            ost->encoding_needed = 1;
 
             if (!ost->filter &&
                 (codec->codec_type == AVMEDIA_TYPE_VIDEO ||
@@ -3400,10 +3447,8 @@ static int transcode(void)
     /* close each encoder */
     for (i = 0; i < nb_output_streams; i++) {
         ost = output_streams[i];
-        if (ost->encoding_needed) {
-            av_freep(&ost->st->codec->stats_in);
-            avcodec_close(ost->st->codec);
-        }
+        av_freep(&ost->st->codec->stats_in);
+        avcodec_close(ost->st->codec);
     }
 
     /* close each decoder */
diff --git a/ffmpeg.h b/ffmpeg.h
index 433baf8..55d7235 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -350,6 +350,7 @@ typedef struct OutputStream {
     int source_index;        /* InputStream index */
     AVStream *st;            /* stream in the output file */
     int encoding_needed;     /* true if encoding needed for this stream */
+    int uncoded_frame;       /* true if using the uncoded frame API */
     int frame_number;
     /* input pts and corresponding output pts
        for A/V sync */
-- 
1.8.5.2



More information about the ffmpeg-devel mailing list