Merge commit '755cd4197d53946208e042f095b930dca18d9430'
[ffmpeg.git] / ffmpeg.c
index 6501bd3..a05d3c4 100644 (file)
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -35,6 +35,7 @@
 #include "libavformat/avformat.h"
 #include "libavdevice/avdevice.h"
 #include "libswscale/swscale.h"
+#include "libswresample/swresample.h"
 #include "libavutil/opt.h"
 #include "libavutil/audioconvert.h"
 #include "libavutil/parseutils.h"
 #include "libavutil/timestamp.h"
 #include "libavutil/bprint.h"
 #include "libavformat/os_support.h"
-#include "libswresample/swresample.h"
 
 #include "libavformat/ffm.h" // not public API
 
 # include "libavfilter/avcodec.h"
 # include "libavfilter/avfilter.h"
 # include "libavfilter/avfiltergraph.h"
-# include "libavfilter/buffersink.h"
 # include "libavfilter/buffersrc.h"
+# include "libavfilter/buffersink.h"
 
 #if HAVE_SYS_RESOURCE_H
 #include <sys/types.h>
@@ -97,7 +97,6 @@
 #define VSYNC_VFR         2
 #define VSYNC_DROP        0xff
 
-// #define SRCA
 #define SINKA
 
 const char program_name[] = "ffmpeg";
@@ -228,8 +227,8 @@ typedef struct InputStream {
     /* dts of the last packet read for this stream */
     int64_t       dts;
 
-    int64_t       next_pts;  ///< synthetic pts for the next decode frame
-    int64_t       pts;       ///< current pts of the decoded frame
+    int64_t       next_pts;  /* synthetic pts for the next decode frame */
+    int64_t       pts;       /* current pts of the decoded frame */
     double ts_scale;
     int is_start;            /* is 1 at the start and after a discontinuity */
     int saw_first_ts;
@@ -250,7 +249,7 @@ typedef struct InputStream {
     int dr1;
 
     /* decoded data from this stream goes into all those filters
-     * currently video only */
+     * currently video and audio only */
     InputFilter **filters;
     int        nb_filters;
 } InputStream;
@@ -376,8 +375,8 @@ typedef struct OptionsContext {
     /* output options */
     StreamMap *stream_maps;
     int     nb_stream_maps;
-    AudioChannelMap *audio_channel_maps; ///< one info entry per -map_channel
-    int           nb_audio_channel_maps; ///< number of (valid) -map_channel settings
+    AudioChannelMap *audio_channel_maps; /* one info entry per -map_channel */
+    int           nb_audio_channel_maps; /* number of (valid) -map_channel settings */
     int metadata_global_manual;
     int metadata_streams_manual;
     int metadata_chapters_manual;
@@ -810,13 +809,8 @@ static int configure_audio_filters(FilterGraph *fg, AVFilterContext **in_filter,
     if (!(fg->graph = avfilter_graph_alloc()))
         return AVERROR(ENOMEM);
 
-#ifdef SRCA
     snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:"
              "channel_layout=0x%"PRIx64, ist->st->time_base.num,
-#else
-    snprintf(args, sizeof(args), "%d/%d:%d:%s:"
-             "0x%"PRIx64, ist->st->time_base.num,
-#endif
              ist->st->time_base.den, icodec->sample_rate,
              av_get_sample_fmt_name(icodec->sample_fmt), icodec->channel_layout);
     ret = avfilter_graph_create_filter(&fg->inputs[0]->filter,
@@ -873,6 +867,29 @@ static int configure_audio_filters(FilterGraph *fg, AVFilterContext **in_filter,
         *out_filter = format;
     }
 
+    if (audio_sync_method > 0) {
+        AVFilterContext *aswr;
+        char args[256] = {0};
+
+        av_strlcatf(args, sizeof(args), "min_comp=0.001:min_hard_comp=%f", audio_drift_threshold);
+
+        if (audio_sync_method > 1)
+            av_strlcatf(args, sizeof(args), ":max_soft_comp=%f", audio_sync_method/(double)icodec->sample_rate);
+
+        av_log(NULL, AV_LOG_INFO, "-async %d is forwarded to lavfi similarly to -af aresample=%s\n", audio_sync_method, args);
+
+        ret = avfilter_graph_create_filter(&aswr, avfilter_get_by_name("aresample"),
+                                           "aresample", args, NULL, fg->graph);
+        if (ret < 0)
+            return ret;
+
+        ret = avfilter_link(*in_filter, 0, aswr, 0);
+        if (ret < 0)
+            return ret;
+
+        *in_filter = aswr;
+    }
+
 #define AUTO_INSERT_FILTER(opt_name, filter_name, arg) do {                 \
     AVFilterContext *filt_ctx;                                              \
                                                                             \
@@ -936,8 +953,10 @@ static int configure_video_filters(FilterGraph *fg, AVFilterContext **in_filter,
         sample_aspect_ratio = ist->st->codec->sample_aspect_ratio;
 
     snprintf(args, 255, "%d:%d:%d:%d:%d:%d:%d:flags=%d", ist->st->codec->width,
-             ist->st->codec->height, ist->st->codec->pix_fmt, 1, AV_TIME_BASE,
-             sample_aspect_ratio.num, sample_aspect_ratio.den, SWS_BILINEAR + ((ist->st->codec->flags&CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0));
+             ist->st->codec->height, ist->st->codec->pix_fmt,
+             1, AV_TIME_BASE,
+             sample_aspect_ratio.num, sample_aspect_ratio.den,
+             SWS_BILINEAR + ((ist->st->codec->flags&CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0));
 
     ret = avfilter_graph_create_filter(&fg->inputs[0]->filter,
                                        avfilter_get_by_name("buffer"),
@@ -1090,8 +1109,9 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
     int i;
 
     // TODO: support other filter types
-    if (type != AVMEDIA_TYPE_VIDEO) {
-        av_log(NULL, AV_LOG_FATAL, "Only video filters supported currently.\n");
+    if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) {
+        av_log(NULL, AV_LOG_FATAL, "Only video and audio filters supported "
+               "currently.\n");
         exit_program(1);
     }
 
@@ -1152,7 +1172,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
     ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1];
 }
 
-static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
+static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
 {
     char *pix_fmts;
     AVCodecContext *codec = ofilter->ost->st->codec;
@@ -1214,6 +1234,104 @@ static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFil
     return 0;
 }
 
+static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
+{
+    OutputStream *ost = ofilter->ost;
+    AVCodecContext *codec  = ost->st->codec;
+    AVFilterContext *last_filter = out->filter_ctx;
+    int pad_idx = out->pad_idx;
+    char *sample_fmts, *sample_rates, *channel_layouts;
+    int ret;
+
+    ret = avfilter_graph_create_filter(&ofilter->filter,
+                                       avfilter_get_by_name("abuffersink"),
+                                       "out", NULL, NULL, fg->graph);
+    if (ret < 0)
+        return ret;
+
+    if (codec->channels && !codec->channel_layout)
+        codec->channel_layout = av_get_default_channel_layout(codec->channels);
+
+    sample_fmts     = choose_sample_fmts(ost);
+    sample_rates    = choose_sample_rates(ost);
+    channel_layouts = choose_channel_layouts(ost);
+    if (sample_fmts || sample_rates || channel_layouts) {
+        AVFilterContext *format;
+        char args[256];
+        int len = 0;
+
+        if (sample_fmts)
+            len += snprintf(args + len, sizeof(args) - len, "sample_fmts=%s:",
+                            sample_fmts);
+        if (sample_rates)
+            len += snprintf(args + len, sizeof(args) - len, "sample_rates=%s:",
+                            sample_rates);
+        if (channel_layouts)
+            len += snprintf(args + len, sizeof(args) - len, "channel_layouts=%s:",
+                            channel_layouts);
+        args[len - 1] = 0;
+
+        av_freep(&sample_fmts);
+        av_freep(&sample_rates);
+        av_freep(&channel_layouts);
+
+        ret = avfilter_graph_create_filter(&format,
+                                           avfilter_get_by_name("aformat"),
+                                           "aformat", args, NULL, fg->graph);
+        if (ret < 0)
+            return ret;
+
+        ret = avfilter_link(last_filter, pad_idx, format, 0);
+        if (ret < 0)
+            return ret;
+
+        last_filter = format;
+        pad_idx = 0;
+    }
+
+    if (audio_sync_method > 0) {
+        AVFilterContext *async;
+        char args[256];
+        int  len = 0;
+
+        av_log(NULL, AV_LOG_WARNING, "-async has been deprecated. Used the "
+               "asyncts audio filter instead.\n");
+
+        if (audio_sync_method > 1)
+            len += snprintf(args + len, sizeof(args) - len, "compensate=1:"
+                            "max_comp=%d:", audio_sync_method);
+        snprintf(args + len, sizeof(args) - len, "min_delta=%f",
+                 audio_drift_threshold);
+
+        ret = avfilter_graph_create_filter(&async,
+                                           avfilter_get_by_name("asyncts"),
+                                           "async", args, NULL, fg->graph);
+        if (ret < 0)
+            return ret;
+
+        ret = avfilter_link(last_filter, pad_idx, async, 0);
+        if (ret < 0)
+            return ret;
+
+        last_filter = async;
+        pad_idx = 0;
+    }
+
+    if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
+        return ret;
+
+    return 0;
+}
+
+static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
+{
+    switch (out->filter_ctx->output_pads[out->pad_idx].type) {
+    case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, ofilter, out);
+    case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, ofilter, out);
+    default: av_assert0(0);
+    }
+}
+
 static int configure_complex_filter(FilterGraph *fg)
 {
     AVFilterInOut *inputs, *outputs, *cur;
@@ -1233,16 +1351,34 @@ static int configure_complex_filter(FilterGraph *fg)
         InputFilter *ifilter = fg->inputs[i];
         InputStream     *ist = ifilter->ist;
         AVRational       sar;
+        AVFilter     *filter;
         char            args[255];
 
-        sar = ist->st->sample_aspect_ratio.num ? ist->st->sample_aspect_ratio :
-                                                 ist->st->codec->sample_aspect_ratio;
-        snprintf(args, sizeof(args), "%d:%d:%d:%d:%d:%d:%d", ist->st->codec->width,
-                 ist->st->codec->height, ist->st->codec->pix_fmt, 1, AV_TIME_BASE,
-                 sar.num, sar.den);
+        switch (cur->filter_ctx->input_pads[cur->pad_idx].type) {
+        case AVMEDIA_TYPE_VIDEO:
+            sar = ist->st->sample_aspect_ratio.num ?
+                  ist->st->sample_aspect_ratio :
+                  ist->st->codec->sample_aspect_ratio;
+            snprintf(args, sizeof(args), "%d:%d:%d:%d:%d:%d:%d", ist->st->codec->width,
+                     ist->st->codec->height, ist->st->codec->pix_fmt, 1, AV_TIME_BASE,
+                     sar.num, sar.den);
+            filter = avfilter_get_by_name("buffer");
+            break;
+        case AVMEDIA_TYPE_AUDIO:
+            snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:"
+                     "sample_fmt=%s:channel_layout=0x%"PRIx64,
+                     ist->st->time_base.num, ist->st->time_base.den,
+                     ist->st->codec->sample_rate,
+                     av_get_sample_fmt_name(ist->st->codec->sample_fmt),
+                     ist->st->codec->channel_layout);
+            filter = avfilter_get_by_name("abuffer");
+            break;
+        default:
+            av_assert0(0);
+        }
 
         if ((ret = avfilter_graph_create_filter(&ifilter->filter,
-                                                avfilter_get_by_name("buffer"), cur->name,
+                                                filter, cur->name,
                                                 args, NULL, fg->graph)) < 0)
             return ret;
         if ((ret = avfilter_link(ifilter->filter, 0,
@@ -1487,7 +1623,7 @@ void av_noreturn exit_program(int ret)
         exit (255);
     }
 
-    exit(ret); /* not all OS-es handle main() return value */
+    exit(ret);
 }
 
 static void assert_avoptions(AVDictionary *m)
@@ -1650,9 +1786,8 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
     if (got_packet) {
         if (pkt.pts != AV_NOPTS_VALUE)
             pkt.pts      = av_rescale_q(pkt.pts,      enc->time_base, ost->st->time_base);
-        if (pkt.dts != AV_NOPTS_VALUE) {
+        if (pkt.dts != AV_NOPTS_VALUE)
             pkt.dts      = av_rescale_q(pkt.dts,      enc->time_base, ost->st->time_base);
-        }
         if (pkt.duration > 0)
             pkt.duration = av_rescale_q(pkt.duration, enc->time_base, ost->st->time_base);
 
@@ -2028,8 +2163,10 @@ static int poll_filters(void)
                 //if (ost->source_index >= 0)
                 //    *filtered_frame= *input_streams[ost->source_index]->decoded_frame; //for me_threshold
 
-                if (of->start_time && filtered_frame->pts < of->start_time)
-                    return 0;
+                if (of->start_time && filtered_frame->pts < of->start_time) {
+                    avfilter_unref_buffer(picref);
+                    continue;
+                }
 
                 switch (ost->filter->filter->inputs[0]->type) {
                 case AVMEDIA_TYPE_VIDEO:
@@ -2424,11 +2561,8 @@ static int transcode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
         /* no audio frame */
         if (!pkt->size)
             for (i = 0; i < ist->nb_filters; i++)
-#ifdef SRCA
-                av_buffersrc_buffer(ist->filters[i]->filter, NULL);
-#else
-                av_buffersrc_add_ref(ist->filters[i]->filter, NULL, 0);
-#endif
+                av_buffersrc_add_ref(ist->filters[i]->filter, NULL,
+                                     AV_BUFFERSRC_FLAG_NO_COPY);
         return ret;
     }
 
@@ -2495,13 +2629,8 @@ static int transcode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
             }
     }
 
-    for (i = 0; i < ist->nb_filters; i++) {
-#ifdef SRCA
-        av_buffersrc_write_frame(ist->filters[i]->filter, decoded_frame);
-#else
+    for (i = 0; i < ist->nb_filters; i++)
         av_buffersrc_add_frame(ist->filters[i]->filter, decoded_frame, 0);
-#endif
-    }
 
     return ret;
 }
@@ -2536,11 +2665,7 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
         /* no picture yet */
         if (!pkt->size)
             for (i = 0; i < ist->nb_filters; i++)
-#ifdef SRCA
-                av_buffersrc_buffer(ist->filters[i]->filter, NULL);
-#else
-                av_buffersrc_add_ref(ist->filters[i]->filter, NULL, 0);
-#endif
+                av_buffersrc_add_ref(ist->filters[i]->filter, NULL, AV_BUFFERSRC_FLAG_NO_COPY);
         return ret;
     }
 
@@ -2549,7 +2674,6 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
         ist->next_pts = ist->pts = decoded_frame->pts = best_effort_timestamp;
 
     pkt->size = 0;
-
     pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free);
 
     rate_emu_sleep(ist);
@@ -2604,17 +2728,11 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
 
             av_assert0(buf->refcount>0);
             buf->refcount++;
-#ifdef SRCA
-            av_buffersrc_buffer(ist->filters[i]->filter, fb);
-        } else
-        if(av_buffersrc_write_frame(ist->filters[i]->filter, decoded_frame)<0) {
-#else
             av_buffersrc_add_ref(ist->filters[i]->filter, fb,
                                  AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT |
                                  AV_BUFFERSRC_FLAG_NO_COPY);
         } else
         if(av_buffersrc_add_frame(ist->filters[i]->filter, decoded_frame, 0)<0) {
-#endif
             av_log(NULL, AV_LOG_FATAL, "Failed to inject frame into filter network\n");
             exit_program(1);
         }
@@ -3106,7 +3224,7 @@ static int transcode_init(void)
                         size_t logbuffer_size;
                         if (cmdutils_read_file(logfilename, &logbuffer, &logbuffer_size) < 0) {
                             av_log(NULL, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n",
-                                logfilename);
+                                   logfilename);
                             exit_program(1);
                         }
                         codec->stats_in = logbuffer;
@@ -4813,12 +4931,15 @@ static void init_output_filter(OutputFilter *ofilter, OptionsContext *o,
 {
     OutputStream *ost;
 
-    if (ofilter->out_tmp->filter_ctx->output_pads[ofilter->out_tmp->pad_idx].type != AVMEDIA_TYPE_VIDEO) {
-        av_log(NULL, AV_LOG_FATAL, "Only video filters are supported currently.\n");
+    switch (ofilter->out_tmp->filter_ctx->output_pads[ofilter->out_tmp->pad_idx].type) {
+    case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(o, oc, -1); break;
+    case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc, -1); break;
+    default:
+        av_log(NULL, AV_LOG_FATAL, "Only video and audio filters are supported "
+               "currently.\n");
         exit_program(1);
     }
 
-    ost               = new_video_stream(o, oc, -1);
     ost->source_index = -1;
     ost->filter       = ofilter;
 
@@ -4999,7 +5120,7 @@ loop_end:
                 case AVMEDIA_TYPE_ATTACHMENT: ost = new_attachment_stream(o, oc, src_idx); break;
                 default:
                     av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d:%d - unsupported type.\n",
-                        map->file_index, map->stream_index);
+                           map->file_index, map->stream_index);
                     exit_program(1);
                 }
             }