From 54aea7d5de13735bad291c0f1d9ba93b17a6321e Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 28 Dec 2014 09:38:22 +0100 Subject: chmap_sel: add multichannel fallback heuristic Instead of just failing during channel map selection, try to select a close layout that makes most sense and upmix/downmix to that instead of failing AO initialization. The heuristic is rather simple, and uses the following steps: 1) If mono is required always prefer stereo to a multichannel upmix. 2) Search for an upmix that is an exact superset of the required channel map. 3) Search for a downmix that is the exact subset of the required channel map. 4) Search for either an upmix or downmix that is the closest (minimum difference of channels) to the required channel map. --- audio/chmap.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'audio/chmap.c') diff --git a/audio/chmap.c b/audio/chmap.c index 64b56b93b2..497b910cff 100644 --- a/audio/chmap.c +++ b/audio/chmap.c @@ -375,6 +375,29 @@ void mp_chmap_get_reorder(int dst[MP_NUM_CHANNELS], const struct mp_chmap *from, assert(to->speaker[dst[n]] == from->speaker[n]); } +// Performs the difference between a and b, and store it in diff. If b has +// channels that do not appear in a, those will not appear in the difference. +// To get to those the argument ordering in the function call has to be +// inverted. For the same reason, the diff with a superset will return no +// speakers. +void mp_chmap_diff(const struct mp_chmap *a, const struct mp_chmap *b, + struct mp_chmap *diff) +{ + uint64_t a_mask = mp_chmap_to_lavc_unchecked(a); + uint64_t b_mask = mp_chmap_to_lavc_unchecked(b); + mp_chmap_from_lavc(diff, (a_mask ^ b_mask) & a_mask); +} + +// Checks whether a contains all the speakers in b +bool mp_chmap_contains(const struct mp_chmap *a, const struct mp_chmap *b) +{ + struct mp_chmap d1; + struct mp_chmap d2; + mp_chmap_diff(a, b, &d1); + mp_chmap_diff(b, a, &d2); + return a->num >= b->num && d1.num >= 0 && d2.num == 0; +} + // Returns something like "fl-fr-fc". If there's a standard layout in lavc // order, return that, e.g. "3.0" instead of "fl-fr-fc". // Unassigned but valid speakers get names like "sp28". -- cgit v1.2.3