ffmpeg: move getutime to the start of the file.
[ffmpeg.git] / ffmpeg.c
index 0f70118..3990f4f 100644 (file)
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -272,11 +272,12 @@ typedef struct OutputStream {
 
     AVFilterContext *output_video_filter;
     AVFilterContext *input_video_filter;
-    AVFilterBufferRef *picref;
     char *avfilter;
     AVFilterGraph *graph;
 
     int64_t sws_flags;
+    int64_t swr_dither_method;
+    double swr_dither_scale;
     AVDictionary *opts;
     int is_past_recording_time;
     int stream_copy;
@@ -415,6 +416,24 @@ typedef struct OptionsContext {
     }\
 }
 
+static int64_t getutime(void)
+{
+#if HAVE_GETRUSAGE
+    struct rusage rusage;
+
+    getrusage(RUSAGE_SELF, &rusage);
+    return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
+#elif HAVE_GETPROCESSTIMES
+    HANDLE proc;
+    FILETIME c, e, k, u;
+    proc = GetCurrentProcess();
+    GetProcessTimes(proc, &c, &e, &k, &u);
+    return ((int64_t) u.dwHighDateTime << 32 | u.dwLowDateTime) / 10;
+#else
+    return av_gettime();
+#endif
+}
+
 static void reset_options(OptionsContext *o, int is_input)
 {
     const OptionDef *po = options;
@@ -1130,7 +1149,7 @@ static int alloc_audio_output_buf(AVCodecContext *dec, AVCodecContext *enc,
 
     audio_buf_size = av_samples_get_buffer_size(NULL, enc->channels,
                                                 audio_buf_samples,
-                                                enc->sample_fmt, 32);
+                                                enc->sample_fmt, 0);
     if (audio_buf_size < 0)
         return audio_buf_size;
 
@@ -1200,6 +1219,8 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
                                           enc->channel_layout, enc->sample_fmt, enc->sample_rate,
                                           dec->channel_layout, dec->sample_fmt, dec->sample_rate,
                                           0, NULL);
+            av_opt_set_int(ost->swr, "dither_method", ost->swr_dither_method,0);
+            av_opt_set_int(ost->swr, "dither_scale", ost->swr_dither_scale,0);
             if (ost->audio_channels_mapped)
                 swr_set_channel_mapping(ost->swr, ost->audio_channels_map);
             av_opt_set_double(ost->swr, "rmvol", ost->rematrix_volume, 0);
@@ -1283,7 +1304,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
                 swr_set_compensation(ost->swr, comp, enc->sample_rate);
             }
         }
-    } else
+    } else if (audio_sync_method == 0)
         ost->sync_opts = lrintf(get_sync_ipts(ost, ist->pts) * enc->sample_rate) -
                                 av_fifo_size(ost->fifo) / (enc->channels * osize); // FIXME wrong
 
@@ -2116,6 +2137,9 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
 
     rate_emu_sleep(ist);
 
+    if (ist->st->sample_aspect_ratio.num)
+        decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
+
     for (i = 0; i < nb_output_streams; i++) {
         OutputStream *ost = &output_streams[i];
 
@@ -2125,8 +2149,9 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
         while (av_buffersink_poll_frame(ost->output_video_filter)) {
             AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base;
             AVFrame *filtered_frame;
+            AVFilterBufferRef *picref;
 
-            if (av_buffersink_get_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0){
+            if (av_buffersink_get_buffer_ref(ost->output_video_filter, &picref, 0) < 0){
                 av_log(NULL, AV_LOG_WARNING, "AV Filter told us it has a frame available but failed to output one\n");
                 goto cont;
             }
@@ -2136,13 +2161,13 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
             }
             filtered_frame = ist->filtered_frame;
             *filtered_frame= *decoded_frame; //for me_threshold
-            avfilter_fill_frame_from_video_buffer_ref(filtered_frame, ost->picref);
-            filtered_frame->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
+            avfilter_fill_frame_from_video_buffer_ref(filtered_frame, picref);
+            filtered_frame->pts = av_rescale_q(picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
             if (!ost->frame_aspect_ratio)
-                ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio;
+                ost->st->codec->sample_aspect_ratio = picref->video->sample_aspect_ratio;
             do_video_out(output_files[ost->file_index].ctx, ost, ist, filtered_frame);
             cont:
-            avfilter_unref_buffer(ost->picref);
+            avfilter_unref_buffer(picref);
         }
     }
 
@@ -2325,10 +2350,57 @@ static void print_sdp(OutputFile *output_files, int n)
     av_freep(&avc);
 }
 
+static void get_default_channel_layouts(OutputStream *ost, InputStream *ist)
+{
+    char layout_name[256];
+    AVCodecContext *enc = ost->st->codec;
+    AVCodecContext *dec = ist->st->codec;
+
+    if (!dec->channel_layout) {
+        if (enc->channel_layout && dec->channels == enc->channels) {
+            dec->channel_layout = enc->channel_layout;
+        } else {
+            dec->channel_layout = av_get_default_channel_layout(dec->channels);
+
+            if (!dec->channel_layout) {
+                av_log(NULL, AV_LOG_FATAL, "Unable to find default channel "
+                       "layout for Input Stream #%d.%d\n", ist->file_index,
+                       ist->st->index);
+                exit_program(1);
+            }
+        }
+        av_get_channel_layout_string(layout_name, sizeof(layout_name),
+                                     dec->channels, dec->channel_layout);
+        av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for  Input Stream "
+               "#%d.%d : %s\n", ist->file_index, ist->st->index, layout_name);
+    }
+    if (!enc->channel_layout) {
+        if (dec->channels == enc->channels) {
+            enc->channel_layout = dec->channel_layout;
+            return;
+        } else {
+            enc->channel_layout = av_get_default_channel_layout(enc->channels);
+        }
+        if (!enc->channel_layout) {
+            av_log(NULL, AV_LOG_FATAL, "Unable to find default channel layout "
+                   "for Output Stream #%d.%d\n", ost->file_index,
+                   ost->st->index);
+            exit_program(1);
+        }
+        av_get_channel_layout_string(layout_name, sizeof(layout_name),
+                                     enc->channels, enc->channel_layout);
+        av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for Output Stream "
+               "#%d.%d : %s\n", ost->file_index, ost->st->index, layout_name);
+    }
+}
+
+
 static int init_input_stream(int ist_index, OutputStream *output_streams, int nb_output_streams,
                              char *error, int error_len)
 {
     InputStream *ist = &input_streams[ist_index];
+    int i;
+
     if (ist->decoding_needed) {
         AVCodec *codec = ist->dec;
         if (!codec) {
@@ -2353,6 +2425,17 @@ static int init_input_stream(int ist_index, OutputStream *output_streams, int nb
         }
         assert_codec_experimental(ist->st->codec, 0);
         assert_avoptions(ist->opts);
+
+        if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+            for (i = 0; i < nb_output_streams; i++) {
+                OutputStream *ost = &output_streams[i];
+                if (ost->source_index == ist_index) {
+                    if (!ist->st->codec->channel_layout || !ost->st->codec->channel_layout)
+                        get_default_channel_layouts(ost, ist);
+                    break;
+                }
+            }
+        }
     }
 
     ist->dts = ist->st->avg_frame_rate.num ? - ist->st->codec->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;
@@ -3904,6 +3987,8 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
         st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
 
     av_opt_get_int(sws_opts, "sws_flags", 0, &ost->sws_flags);
+    av_opt_get_int   (swr_opts, "dither_method", 0, &ost->swr_dither_method);
+    av_opt_get_double(swr_opts, "dither_scale" , 0, &ost->swr_dither_scale);
 
     ost->source_index = source_index;
     if (source_index >= 0) {
@@ -4556,24 +4641,6 @@ static int opt_pass(const char *opt, const char *arg)
     return 0;
 }
 
-static int64_t getutime(void)
-{
-#if HAVE_GETRUSAGE
-    struct rusage rusage;
-
-    getrusage(RUSAGE_SELF, &rusage);
-    return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
-#elif HAVE_GETPROCESSTIMES
-    HANDLE proc;
-    FILETIME c, e, k, u;
-    proc = GetCurrentProcess();
-    GetProcessTimes(proc, &c, &e, &k, &u);
-    return ((int64_t) u.dwHighDateTime << 32 | u.dwLowDateTime) / 10;
-#else
-    return av_gettime();
-#endif
-}
-
 static int64_t getmaxrss(void)
 {
 #if HAVE_GETRUSAGE && HAVE_STRUCT_RUSAGE_RU_MAXRSS
@@ -4940,6 +5007,41 @@ static void parse_cpuflags(int argc, char **argv, const OptionDef *options)
         opt_cpuflags("cpuflags", argv[idx + 1]);
 }
 
+static int opt_channel_layout(OptionsContext *o, const char *opt, const char *arg)
+{
+    char layout_str[32];
+    char *stream_str;
+    char *ac_str;
+    int ret, channels, ac_str_size;
+    uint64_t layout;
+
+    layout = av_get_channel_layout(arg);
+    if (!layout) {
+        av_log(NULL, AV_LOG_ERROR, "Unknown channel layout: %s\n", arg);
+        return AVERROR(EINVAL);
+    }
+    snprintf(layout_str, sizeof(layout_str), "%"PRIu64, layout);
+    ret = opt_default(opt, layout_str);
+    if (ret < 0)
+        return ret;
+
+    /* set 'ac' option based on channel layout */
+    channels = av_get_channel_layout_nb_channels(layout);
+    snprintf(layout_str, sizeof(layout_str), "%d", channels);
+    stream_str = strchr(opt, ':');
+    ac_str_size = 3 + (stream_str ? strlen(stream_str) : 0);
+    ac_str = av_mallocz(ac_str_size);
+    if (!ac_str)
+        return AVERROR(ENOMEM);
+    av_strlcpy(ac_str, "ac", 3);
+    if (stream_str)
+        av_strlcat(ac_str, stream_str, ac_str_size);
+    ret = parse_option(o, ac_str, layout_str, options);
+    av_free(ac_str);
+
+    return ret;
+}
+
 #define OFFSET(x) offsetof(OptionsContext, x)
 static const OptionDef options[] = {
     /* main options */
@@ -5048,6 +5150,7 @@ static const OptionDef options[] = {
     { "vol", OPT_INT | HAS_ARG | OPT_AUDIO, {(void*)&audio_volume}, "change audio volume (256=normal)" , "volume" }, //
     { "sample_fmt", HAS_ARG | OPT_EXPERT | OPT_AUDIO | OPT_SPEC | OPT_STRING, {.off = OFFSET(sample_fmts)}, "set sample format", "format" },
     { "rmvol", HAS_ARG | OPT_AUDIO | OPT_FLOAT | OPT_SPEC, {.off = OFFSET(rematrix_volume)}, "rematrix volume (as factor)", "volume" },
+    { "channel_layout", HAS_ARG | OPT_EXPERT | OPT_AUDIO | OPT_FUNC2, {(void*)opt_channel_layout}, "set channel layout", "layout" },
 
     /* subtitle options */
     { "sn", OPT_BOOL | OPT_SUBTITLE | OPT_OFFSET, {.off = OFFSET(subtitle_disable)}, "disable subtitle" },