diff options
author | Martin Herkt <lachs0r@srsfckn.biz> | 2016-04-11 17:42:55 +0200 |
---|---|---|
committer | Martin Herkt <lachs0r@srsfckn.biz> | 2016-04-11 17:42:55 +0200 |
commit | 0803f4ad21c195519209bae8d18840dd810191f8 (patch) | |
tree | f9a869011ba90c106cf5c05c3e346912a669f63a /audio | |
parent | 9d2980dab752280468620df49cabe7f4843f0551 (diff) | |
parent | b968d779afb9114694976792e903b0591a71a816 (diff) | |
download | mpv-0803f4ad21c195519209bae8d18840dd810191f8.tar.bz2 mpv-0803f4ad21c195519209bae8d18840dd810191f8.tar.xz |
Merge branch 'master' into release/current
Diffstat (limited to 'audio')
-rw-r--r-- | audio/decode/ad_lavc.c | 24 | ||||
-rw-r--r-- | audio/decode/ad_spdif.c | 4 | ||||
-rw-r--r-- | audio/format.c | 31 | ||||
-rw-r--r-- | audio/format.h | 1 | ||||
-rw-r--r-- | audio/out/ao_coreaudio_exclusive.c | 2 | ||||
-rw-r--r-- | audio/out/ao_lavc.c | 5 | ||||
-rw-r--r-- | audio/out/ao_wasapi_utils.c | 14 |
7 files changed, 65 insertions, 16 deletions
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index c30aff7fd5..8a6bb4061b 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -45,6 +45,7 @@ struct priv { uint32_t skip_samples, trim_samples; bool preroll_done; double next_pts; + AVRational codec_timebase; }; static void uninit(struct dec_audio *da); @@ -84,6 +85,8 @@ static int init(struct dec_audio *da, const char *decoder) struct priv *ctx = talloc_zero(NULL, struct priv); da->priv = ctx; + ctx->codec_timebase = (AVRational){0}; + ctx->force_channel_map = c->force_channels; lavc_codec = avcodec_find_decoder_by_name(decoder); @@ -128,8 +131,7 @@ static int init(struct dec_audio *da, const char *decoder) // demux_mkv mp_lavc_set_extradata(lavc_context, c->extradata, c->extradata_size); - if (c->lav_headers) - mp_copy_lav_codec_headers(lavc_context, c->lav_headers); + mp_set_lav_codec_headers(lavc_context, c); mp_set_avcodec_threads(da->log, lavc_context, opts->threads); @@ -185,10 +187,23 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, int in_len = mpkt ? mpkt->len : 0; AVPacket pkt; - mp_set_av_packet(&pkt, mpkt, NULL); + mp_set_av_packet(&pkt, mpkt, &priv->codec_timebase); int got_frame = 0; av_frame_unref(priv->avframe); + +#if HAVE_AVCODEC_NEW_CODEC_API + int ret = avcodec_send_packet(avctx, &pkt); + if (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + if (ret >= 0 && mpkt) + mpkt->len = 0; + ret = avcodec_receive_frame(avctx, priv->avframe); + if (ret >= 0) + got_frame = 1; + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + ret = 0; + } +#else int ret = avcodec_decode_audio4(avctx, priv->avframe, &got_frame, &pkt); if (mpkt) { // At least "shorten" decodes sub-frames, instead of the whole packet. @@ -205,6 +220,7 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, return 0; } } +#endif if (ret < 0) { MP_ERR(da, "Error decoding audio.\n"); return -1; @@ -212,7 +228,7 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, if (!got_frame) return 0; - double out_pts = mp_pts_from_av(priv->avframe->pkt_pts, NULL); + double out_pts = mp_pts_from_av(priv->avframe->pkt_pts, &priv->codec_timebase); struct mp_audio *mpframe = mp_audio_from_avframe(priv->avframe); if (!mpframe) diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index 7298d9e7d7..eb2e2bb0a9 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -171,7 +171,11 @@ static int init_filter(struct dec_audio *da, AVPacket *pkt) if (!stream) goto fail; +#if HAVE_AVCODEC_HAS_CODECPAR + stream->codecpar->codec_id = spdif_ctx->codec_id; +#else stream->codec->codec_id = spdif_ctx->codec_id; +#endif AVDictionary *format_opts = NULL; diff --git a/audio/format.c b/audio/format.c index 06360b884b..bbe0cec9bb 100644 --- a/audio/format.c +++ b/audio/format.c @@ -245,6 +245,37 @@ void af_get_best_sample_formats(int src_format, int out_formats[AF_FORMAT_COUNT] out_formats[num] = 0; } +// Return the best match to src_samplerate from the list provided in the array +// *available, which must be terminated by 0, or itself NULL. If *available is +// empty or NULL, return a negative value. Exact match to src_samplerate is +// most preferred, followed by the lowest integer multiple, followed by the +// maximum of *available. +int af_select_best_samplerate(int src_samplerate, const int *available) +{ + if (!available) + return -1; + + int min_mult_rate = INT_MAX; + int max_rate = INT_MIN; + for (int i = 0; available[i]; i++) { + if (available[i] == src_samplerate) + return available[i]; + + if (!(available[i] % src_samplerate)) + min_mult_rate = MPMIN(min_mult_rate, available[i]); + + max_rate = MPMAX(max_rate, available[i]); + } + + if (min_mult_rate < INT_MAX) + return min_mult_rate; + + if (max_rate > INT_MIN) + return max_rate; + + return -1; +} + // Return the number of samples that make up one frame in this format. // You get the byte size by multiplying them with sample size and channel count. int af_format_sample_alignment(int format) diff --git a/audio/format.h b/audio/format.h index de1ff1a30d..3d5cc1024b 100644 --- a/audio/format.h +++ b/audio/format.h @@ -76,6 +76,7 @@ int af_fmt_seconds_to_bytes(int format, float seconds, int channels, int sampler void af_fill_silence(void *dst, size_t bytes, int format); void af_get_best_sample_formats(int src_format, int out_formats[AF_FORMAT_COUNT]); +int af_select_best_samplerate(int src_sampelrate, const int *available); int af_format_sample_alignment(int format); diff --git a/audio/out/ao_coreaudio_exclusive.c b/audio/out/ao_coreaudio_exclusive.c index af07fe0f3e..510fa3a529 100644 --- a/audio/out/ao_coreaudio_exclusive.c +++ b/audio/out/ao_coreaudio_exclusive.c @@ -367,7 +367,7 @@ static void uninit(struct ao *ao) CHECK_CA_WARN("failed to remove device render callback"); if (!ca_change_physical_format_sync(ao, p->stream, p->original_asbd)) - MP_WARN(ao, "can't revert to original device format"); + MP_WARN(ao, "can't revert to original device format\n"); err = ca_enable_mixing(ao, p->device, p->changed_mixing); CHECK_CA_WARN("can't re-enable mixing"); diff --git a/audio/out/ao_lavc.c b/audio/out/ao_lavc.c index b671301922..bf1728682a 100644 --- a/audio/out/ao_lavc.c +++ b/audio/out/ao_lavc.c @@ -108,6 +108,11 @@ static int init(struct ao *ao) codec = encode_lavc_get_codec(ao->encode_lavc_ctx, ac->stream); + int samplerate = af_select_best_samplerate(ao->samplerate, + codec->supported_samplerates); + if (samplerate > 0) + ao->samplerate = samplerate; + // TODO: Remove this redundancy with encode_lavc_alloc_stream also // setting the time base. // Using codec->time_bvase is deprecated, but needed for older lavf. diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c index 8d0ea30bd7..0e7dec885a 100644 --- a/audio/out/ao_wasapi_utils.c +++ b/audio/out/ao_wasapi_utils.c @@ -364,17 +364,9 @@ static bool search_samplerates(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat, } } - for (int i = 0; supported[i]; i++) { - // first choose the lowest integer multiple of the sample rate - if (!(supported[i] % ao->samplerate)) { - change_waveformat_samplerate(wformat, supported[i]); - return true; - } - } - - // then choose the highest supported (if any) - if (n) { - change_waveformat_samplerate(wformat, supported[n-1]); + int samplerate = af_select_best_samplerate(ao->samplerate, supported); + if (samplerate > 0) { + change_waveformat_samplerate(wformat, samplerate); return true; } |