summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorMartin Herkt <lachs0r@srsfckn.biz>2016-04-11 17:42:55 +0200
committerMartin Herkt <lachs0r@srsfckn.biz>2016-04-11 17:42:55 +0200
commit0803f4ad21c195519209bae8d18840dd810191f8 (patch)
treef9a869011ba90c106cf5c05c3e346912a669f63a /audio
parent9d2980dab752280468620df49cabe7f4843f0551 (diff)
parentb968d779afb9114694976792e903b0591a71a816 (diff)
downloadmpv-0803f4ad21c195519209bae8d18840dd810191f8.tar.bz2
mpv-0803f4ad21c195519209bae8d18840dd810191f8.tar.xz
Merge branch 'master' into release/current
Diffstat (limited to 'audio')
-rw-r--r--audio/decode/ad_lavc.c24
-rw-r--r--audio/decode/ad_spdif.c4
-rw-r--r--audio/format.c31
-rw-r--r--audio/format.h1
-rw-r--r--audio/out/ao_coreaudio_exclusive.c2
-rw-r--r--audio/out/ao_lavc.c5
-rw-r--r--audio/out/ao_wasapi_utils.c14
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;
}