...
|
...
|
@@ -191,7 +191,11 @@ typedef struct VideoState {
|
191
|
191
|
AVPacket audio_pkt_temp;
|
192
|
192
|
AVPacket audio_pkt;
|
193
|
193
|
int audio_pkt_temp_serial;
|
|
194
|
+ int audio_last_serial;
|
194
|
195
|
struct AudioParams audio_src;
|
|
196
|
+#if CONFIG_AVFILTER
|
|
197
|
+ struct AudioParams audio_filter_src;
|
|
198
|
+#endif
|
195
|
199
|
struct AudioParams audio_tgt;
|
196
|
200
|
struct SwrContext *swr_ctx;
|
197
|
201
|
double audio_current_pts;
|
...
|
...
|
@@ -253,6 +257,9 @@ typedef struct VideoState {
|
253
|
253
|
#if CONFIG_AVFILTER
|
254
|
254
|
AVFilterContext *in_video_filter; // the first filter in the video chain
|
255
|
255
|
AVFilterContext *out_video_filter; // the last filter in the video chain
|
|
256
|
+ AVFilterContext *in_audio_filter; // the first filter in the audio chain
|
|
257
|
+ AVFilterContext *out_audio_filter; // the last filter in the audio chain
|
|
258
|
+ AVFilterGraph *agraph; // audio filter graph
|
256
|
259
|
#endif
|
257
|
260
|
|
258
|
261
|
int last_video_stream, last_audio_stream, last_subtitle_stream;
|
...
|
...
|
@@ -309,6 +316,7 @@ static int64_t cursor_last_shown;
|
309
|
309
|
static int cursor_hidden = 0;
|
310
|
310
|
#if CONFIG_AVFILTER
|
311
|
311
|
static char *vfilters = NULL;
|
|
312
|
+static char *afilters = NULL;
|
312
|
313
|
#endif
|
313
|
314
|
|
314
|
315
|
/* current context */
|
...
|
...
|
@@ -322,6 +330,26 @@ static AVPacket flush_pkt;
|
322
|
322
|
|
323
|
323
|
static SDL_Surface *screen;
|
324
|
324
|
|
|
325
|
+static inline
|
|
326
|
+int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1,
|
|
327
|
+ enum AVSampleFormat fmt2, int64_t channel_count2)
|
|
328
|
+{
|
|
329
|
+ /* If channel count == 1, planar and non-planar formats are the same */
|
|
330
|
+ if (channel_count1 == 1 && channel_count2 == 1)
|
|
331
|
+ return av_get_packed_sample_fmt(fmt1) != av_get_packed_sample_fmt(fmt2);
|
|
332
|
+ else
|
|
333
|
+ return channel_count1 != channel_count2 || fmt1 != fmt2;
|
|
334
|
+}
|
|
335
|
+
|
|
336
|
+static inline
|
|
337
|
+int64_t get_valid_channel_layout(int64_t channel_layout, int channels)
|
|
338
|
+{
|
|
339
|
+ if (channel_layout && av_get_channel_layout_nb_channels(channel_layout) == channels)
|
|
340
|
+ return channel_layout;
|
|
341
|
+ else
|
|
342
|
+ return 0;
|
|
343
|
+}
|
|
344
|
+
|
325
|
345
|
static int packet_queue_put(PacketQueue *q, AVPacket *pkt);
|
326
|
346
|
|
327
|
347
|
static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
|
...
|
...
|
@@ -1781,6 +1809,71 @@ fail:
|
1781
|
1781
|
return ret;
|
1782
|
1782
|
}
|
1783
|
1783
|
|
|
1784
|
+static int configure_audio_filters(VideoState *is, const char *afilters, int force_output_format)
|
|
1785
|
+{
|
|
1786
|
+ static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, PIX_FMT_NONE };
|
|
1787
|
+ int sample_rates[2] = { 0, -1 };
|
|
1788
|
+ int64_t channel_layouts[2] = { 0, -1 };
|
|
1789
|
+ int channels[2] = { 0, -1 };
|
|
1790
|
+ AVFilterContext *filt_asrc = NULL, *filt_asink = NULL;
|
|
1791
|
+ char asrc_args[256];
|
|
1792
|
+ AVABufferSinkParams *asink_params = NULL;
|
|
1793
|
+ int ret;
|
|
1794
|
+
|
|
1795
|
+ avfilter_graph_free(&is->agraph);
|
|
1796
|
+ if (!(is->agraph = avfilter_graph_alloc()))
|
|
1797
|
+ return AVERROR(ENOMEM);
|
|
1798
|
+
|
|
1799
|
+ ret = snprintf(asrc_args, sizeof(asrc_args),
|
|
1800
|
+ "sample_rate=%d:sample_fmt=%s:channels=%d",
|
|
1801
|
+ is->audio_filter_src.freq, av_get_sample_fmt_name(is->audio_filter_src.fmt),
|
|
1802
|
+ is->audio_filter_src.channels);
|
|
1803
|
+ if (is->audio_filter_src.channel_layout)
|
|
1804
|
+ snprintf(asrc_args + ret, sizeof(asrc_args) - ret,
|
|
1805
|
+ ":channel_layout=0x%"PRIx64, is->audio_filter_src.channel_layout);
|
|
1806
|
+
|
|
1807
|
+ ret = avfilter_graph_create_filter(&filt_asrc,
|
|
1808
|
+ avfilter_get_by_name("abuffer"), "ffplay_abuffer",
|
|
1809
|
+ asrc_args, NULL, is->agraph);
|
|
1810
|
+ if (ret < 0)
|
|
1811
|
+ goto end;
|
|
1812
|
+
|
|
1813
|
+ if (!(asink_params = av_abuffersink_params_alloc())) {
|
|
1814
|
+ ret = AVERROR(ENOMEM);
|
|
1815
|
+ goto end;
|
|
1816
|
+ }
|
|
1817
|
+ asink_params->sample_fmts = sample_fmts;
|
|
1818
|
+
|
|
1819
|
+ asink_params->all_channel_counts = 1;
|
|
1820
|
+ if (force_output_format) {
|
|
1821
|
+ channel_layouts[0] = is->audio_tgt.channel_layout;
|
|
1822
|
+ asink_params->channel_layouts = channel_layouts;
|
|
1823
|
+ asink_params->all_channel_counts = 0;
|
|
1824
|
+ channels[0] = is->audio_tgt.channels;
|
|
1825
|
+ asink_params->channel_counts = channels;
|
|
1826
|
+ asink_params->all_channel_counts = 0;
|
|
1827
|
+ sample_rates[0] = is->audio_tgt.freq;
|
|
1828
|
+ asink_params->sample_rates = sample_rates;
|
|
1829
|
+ }
|
|
1830
|
+
|
|
1831
|
+ ret = avfilter_graph_create_filter(&filt_asink,
|
|
1832
|
+ avfilter_get_by_name("abuffersink"), "ffplay_abuffersink",
|
|
1833
|
+ NULL, asink_params, is->agraph);
|
|
1834
|
+ if (ret < 0)
|
|
1835
|
+ goto end;
|
|
1836
|
+
|
|
1837
|
+ if ((ret = configure_filtergraph(is->agraph, afilters, filt_asrc, filt_asink)) < 0)
|
|
1838
|
+ goto end;
|
|
1839
|
+
|
|
1840
|
+ is->in_audio_filter = filt_asrc;
|
|
1841
|
+ is->out_audio_filter = filt_asink;
|
|
1842
|
+
|
|
1843
|
+end:
|
|
1844
|
+ av_freep(&asink_params);
|
|
1845
|
+ if (ret < 0)
|
|
1846
|
+ avfilter_graph_free(&is->agraph);
|
|
1847
|
+ return ret;
|
|
1848
|
+}
|
1784
|
1849
|
#endif /* CONFIG_AVFILTER */
|
1785
|
1850
|
|
1786
|
1851
|
static int video_thread(void *arg)
|
...
|
...
|
@@ -2056,6 +2149,7 @@ static int audio_decode_frame(VideoState *is)
|
2056
|
2056
|
int new_packet = 0;
|
2057
|
2057
|
int flush_complete = 0;
|
2058
|
2058
|
int wanted_nb_samples;
|
|
2059
|
+ AVRational tb;
|
2059
|
2060
|
|
2060
|
2061
|
for (;;) {
|
2061
|
2062
|
/* NOTE: the audio packet can contain several frames */
|
...
|
...
|
@@ -2098,6 +2192,49 @@ static int audio_decode_frame(VideoState *is)
|
2098
|
2098
|
is->frame->pts = av_rescale_q(pkt_temp->pts, is->audio_st->time_base, dec->time_base);
|
2099
|
2099
|
if (pkt_temp->pts != AV_NOPTS_VALUE)
|
2100
|
2100
|
pkt_temp->pts += (double) is->frame->nb_samples / is->frame->sample_rate / av_q2d(is->audio_st->time_base);
|
|
2101
|
+ tb = dec->time_base;
|
|
2102
|
+
|
|
2103
|
+#if CONFIG_AVFILTER
|
|
2104
|
+ {
|
|
2105
|
+ int ret;
|
|
2106
|
+ int reconfigure;
|
|
2107
|
+
|
|
2108
|
+ dec_channel_layout = get_valid_channel_layout(is->frame->channel_layout, av_frame_get_channels(is->frame));
|
|
2109
|
+
|
|
2110
|
+ reconfigure =
|
|
2111
|
+ cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.channels,
|
|
2112
|
+ is->frame->format, av_frame_get_channels(is->frame)) ||
|
|
2113
|
+ is->audio_filter_src.channel_layout != dec_channel_layout ||
|
|
2114
|
+ is->audio_filter_src.freq != is->frame->sample_rate ||
|
|
2115
|
+ is->audio_pkt_temp_serial != is->audio_last_serial;
|
|
2116
|
+
|
|
2117
|
+ if (reconfigure) {
|
|
2118
|
+ char buf1[1024], buf2[1024];
|
|
2119
|
+ av_get_channel_layout_string(buf1, sizeof(buf1), -1, is->audio_filter_src.channel_layout);
|
|
2120
|
+ av_get_channel_layout_string(buf2, sizeof(buf2), -1, dec_channel_layout);
|
|
2121
|
+ av_log(NULL, AV_LOG_DEBUG,
|
|
2122
|
+ "Audio frame changed from rate:%d ch:%d fmt:%s layout:%s serial:%d to rate:%d ch:%d fmt:%s layout:%s serial:%d\n",
|
|
2123
|
+ is->audio_filter_src.freq, is->audio_filter_src.channels, av_get_sample_fmt_name(is->audio_filter_src.fmt), buf1, is->audio_last_serial,
|
|
2124
|
+ is->frame->sample_rate, av_frame_get_channels(is->frame), av_get_sample_fmt_name(is->frame->format), buf2, is->audio_pkt_temp_serial);
|
|
2125
|
+
|
|
2126
|
+ is->audio_filter_src.fmt = is->frame->format;
|
|
2127
|
+ is->audio_filter_src.channels = av_frame_get_channels(is->frame);
|
|
2128
|
+ is->audio_filter_src.channel_layout = dec_channel_layout;
|
|
2129
|
+ is->audio_filter_src.freq = is->frame->sample_rate;
|
|
2130
|
+ is->audio_last_serial = is->audio_pkt_temp_serial;
|
|
2131
|
+
|
|
2132
|
+ if ((ret = configure_audio_filters(is, afilters, 1)) < 0)
|
|
2133
|
+ return ret;
|
|
2134
|
+ }
|
|
2135
|
+
|
|
2136
|
+ if ((ret = av_buffersrc_add_frame(is->in_audio_filter, is->frame)) < 0)
|
|
2137
|
+ return ret;
|
|
2138
|
+ av_frame_unref(is->frame);
|
|
2139
|
+ if ((ret = av_buffersink_get_frame_flags(is->out_audio_filter, is->frame, 0)) < 0)
|
|
2140
|
+ return ret;
|
|
2141
|
+ tb = is->out_audio_filter->inputs[0]->time_base;
|
|
2142
|
+ }
|
|
2143
|
+#endif
|
2101
|
2144
|
|
2102
|
2145
|
data_size = av_samples_get_buffer_size(NULL, av_frame_get_channels(is->frame),
|
2103
|
2146
|
is->frame->nb_samples,
|
...
|
...
|
@@ -2164,7 +2301,7 @@ static int audio_decode_frame(VideoState *is)
|
2164
|
2164
|
audio_clock0 = is->audio_clock;
|
2165
|
2165
|
/* update the audio clock with the pts */
|
2166
|
2166
|
if (is->frame->pts != AV_NOPTS_VALUE) {
|
2167
|
|
- is->audio_clock = is->frame->pts * av_q2d(dec->time_base) + (double) is->frame->nb_samples / is->frame->sample_rate;
|
|
2167
|
+ is->audio_clock = is->frame->pts * av_q2d(tb) + (double) is->frame->nb_samples / is->frame->sample_rate;
|
2168
|
2168
|
is->audio_clock_serial = is->audio_pkt_temp_serial;
|
2169
|
2169
|
}
|
2170
|
2170
|
#ifdef DEBUG
|
...
|
...
|
@@ -2308,6 +2445,8 @@ static int stream_component_open(VideoState *is, int stream_index)
|
2308
|
2308
|
const char *forced_codec_name = NULL;
|
2309
|
2309
|
AVDictionary *opts;
|
2310
|
2310
|
AVDictionaryEntry *t = NULL;
|
|
2311
|
+ int sample_rate, nb_channels;
|
|
2312
|
+ int64_t channel_layout;
|
2311
|
2313
|
int ret;
|
2312
|
2314
|
|
2313
|
2315
|
if (stream_index < 0 || stream_index >= ic->nb_streams)
|
...
|
...
|
@@ -2363,8 +2502,29 @@ static int stream_component_open(VideoState *is, int stream_index)
|
2363
|
2363
|
ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
|
2364
|
2364
|
switch (avctx->codec_type) {
|
2365
|
2365
|
case AVMEDIA_TYPE_AUDIO:
|
|
2366
|
+#if CONFIG_AVFILTER
|
|
2367
|
+ {
|
|
2368
|
+ AVFilterLink *link;
|
|
2369
|
+
|
|
2370
|
+ is->audio_filter_src.freq = avctx->sample_rate;
|
|
2371
|
+ is->audio_filter_src.channels = avctx->channels;
|
|
2372
|
+ is->audio_filter_src.channel_layout = get_valid_channel_layout(avctx->channel_layout, avctx->channels);
|
|
2373
|
+ is->audio_filter_src.fmt = avctx->sample_fmt;
|
|
2374
|
+ if ((ret = configure_audio_filters(is, afilters, 0)) < 0)
|
|
2375
|
+ return ret;
|
|
2376
|
+ link = is->out_audio_filter->inputs[0];
|
|
2377
|
+ sample_rate = link->sample_rate;
|
|
2378
|
+ nb_channels = link->channels;
|
|
2379
|
+ channel_layout = link->channel_layout;
|
|
2380
|
+ }
|
|
2381
|
+#else
|
|
2382
|
+ sample_rate = avctx->sample_rate;
|
|
2383
|
+ nb_channels = avctx->channels;
|
|
2384
|
+ channel_layout = avctx->channel_layout;
|
|
2385
|
+#endif
|
|
2386
|
+
|
2366
|
2387
|
/* prepare audio output */
|
2367
|
|
- if ((ret = audio_open(is, avctx->channel_layout, avctx->channels, avctx->sample_rate, &is->audio_tgt)) < 0)
|
|
2388
|
+ if ((ret = audio_open(is, channel_layout, nb_channels, sample_rate, &is->audio_tgt)) < 0)
|
2368
|
2389
|
return ret;
|
2369
|
2390
|
is->audio_hw_buf_size = ret;
|
2370
|
2391
|
is->audio_src = is->audio_tgt;
|
...
|
...
|
@@ -2436,6 +2596,9 @@ static void stream_component_close(VideoState *is, int stream_index)
|
2436
|
2436
|
is->rdft = NULL;
|
2437
|
2437
|
is->rdft_bits = 0;
|
2438
|
2438
|
}
|
|
2439
|
+#if CONFIG_AVFILTER
|
|
2440
|
+ avfilter_graph_free(&is->agraph);
|
|
2441
|
+#endif
|
2439
|
2442
|
break;
|
2440
|
2443
|
case AVMEDIA_TYPE_VIDEO:
|
2441
|
2444
|
packet_queue_abort(&is->videoq);
|
...
|
...
|
@@ -2825,6 +2988,7 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
|
2825
|
2825
|
is->video_current_pts_drift = is->audio_current_pts_drift;
|
2826
|
2826
|
is->audio_clock_serial = -1;
|
2827
|
2827
|
is->video_clock_serial = -1;
|
|
2828
|
+ is->audio_last_serial = -1;
|
2828
|
2829
|
is->av_sync_type = av_sync_type;
|
2829
|
2830
|
is->read_tid = SDL_CreateThread(read_thread, is);
|
2830
|
2831
|
if (!is->read_tid) {
|
...
|
...
|
@@ -3233,6 +3397,7 @@ static const OptionDef options[] = {
|
3233
|
3233
|
{ "window_title", OPT_STRING | HAS_ARG, { &window_title }, "set window title", "window title" },
|
3234
|
3234
|
#if CONFIG_AVFILTER
|
3235
|
3235
|
{ "vf", OPT_STRING | HAS_ARG, { &vfilters }, "set video filters", "filter_graph" },
|
|
3236
|
+ { "af", OPT_STRING | HAS_ARG, { &afilters }, "set audio filters", "filter_graph" },
|
3236
|
3237
|
#endif
|
3237
|
3238
|
{ "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
|
3238
|
3239
|
{ "showmode", HAS_ARG, { .func_arg = opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" },
|