summaryrefslogtreecommitdiffstats
path: root/audio/out
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-05-05 21:46:17 +0200
committerwm4 <wm4@nowhere>2015-05-05 21:46:17 +0200
commitfd6809f98a546c2abe87b378bb1fe0bbec40a4ef (patch)
tree5e41e8dd8d0ab862ee3d133ca2dd57bcae02d87a /audio/out
parent66f4e7cce497f24e5b693b95fa222382da649f86 (diff)
downloadmpv-fd6809f98a546c2abe87b378bb1fe0bbec40a4ef.tar.bz2
mpv-fd6809f98a546c2abe87b378bb1fe0bbec40a4ef.tar.xz
ao_coreaudio_utils: refine format selection
Instead of always picking a somehow better format over the previous one, select a format that is equal to or better the requested format, but is also reasonably close. Drop the mFormatID comparison - checking the sample format handles this already. Make sure to exclude channel counts that can't be used.
Diffstat (limited to 'audio/out')
-rw-r--r--audio/out/ao_coreaudio_utils.c44
1 files changed, 25 insertions, 19 deletions
diff --git a/audio/out/ao_coreaudio_utils.c b/audio/out/ao_coreaudio_utils.c
index 79189380ab..fbb336149d 100644
--- a/audio/out/ao_coreaudio_utils.c
+++ b/audio/out/ao_coreaudio_utils.c
@@ -268,36 +268,42 @@ void ca_print_asbd(struct ao *ao, const char *description,
talloc_free(format);
}
+// Return whether new is an improvement over old. Assume a higher value means
+// better quality, and we always prefer the value closest to the requested one,
+// which is still larger than the requested one.
+// Equal values prefer the new one (so ca_asbd_is_better() checks other params).
+static bool value_is_better(double req, double old, double new)
+{
+ if (new >= req) {
+ return old < req || new <= old;
+ } else {
+ return old < req && new >= old;
+ }
+}
+
// Return whether new is an improvement over old (req is the requested format).
bool ca_asbd_is_better(AudioStreamBasicDescription *req,
AudioStreamBasicDescription *old,
AudioStreamBasicDescription *new)
{
- if (req->mFormatID != new->mFormatID)
+ if (new->mChannelsPerFrame > MP_NUM_CHANNELS)
return false;
+ if (old->mChannelsPerFrame > MP_NUM_CHANNELS)
+ return true;
- int mpfmt_req = ca_asbd_to_mp_format(old);
+ int mpfmt_req = ca_asbd_to_mp_format(req);
+ int mpfmt_old = ca_asbd_to_mp_format(old);
int mpfmt_new = ca_asbd_to_mp_format(new);
- if (!mpfmt_new)
+ if (af_format_conversion_score(mpfmt_req, mpfmt_old) >
+ af_format_conversion_score(mpfmt_req, mpfmt_new))
return false;
- if (mpfmt_req != mpfmt_new) {
- int mpfmt_old = ca_asbd_to_mp_format(old);
- if (af_format_conversion_score(mpfmt_req, mpfmt_old) >
- af_format_conversion_score(mpfmt_req, mpfmt_new))
- return false;
- }
-
- if (req->mSampleRate != new->mSampleRate) {
- if (old->mSampleRate > new->mSampleRate)
- return false;
- }
+ if (!value_is_better(req->mSampleRate, old->mSampleRate, new->mSampleRate))
+ return false;
- if (req->mChannelsPerFrame != new->mChannelsPerFrame) {
- if (old->mChannelsPerFrame > new->mChannelsPerFrame ||
- new->mChannelsPerFrame > MP_NUM_CHANNELS)
- return false;
- }
+ if (!value_is_better(req->mChannelsPerFrame, old->mChannelsPerFrame,
+ new->mChannelsPerFrame))
+ return false;
return true;
}