1
mirror of https://github.com/mpv-player/mpv synced 2024-11-14 22:48:35 +01:00
mpv/test/chmap.c
Dudemanguy 9db818279a test: integrate unittests with meson
This reworks all of mpv's unit tests so they are compiled as separate
executables (optional) and run via meson test. Because most of the tests
are dependant on mpv's internals, existing compiled objects are
leveraged to create static libs and used when necessary. As an aside, a
function was moved into video/out/gpu/utils for sanity's sake (otherwise
most of vo would have been needed). As a plus, meson multithreads
running tests automatically and also the output no longer pollutes the
source directory. There are tests that can break due to ffmpeg changes,
so they require a specific minimum libavutil version to be built.
2023-03-02 15:45:27 +00:00

219 lines
7.5 KiB
C

#include "audio/chmap.h"
#include "audio/chmap_sel.h"
#include "config.h"
#include "test_utils.h"
#if HAVE_AV_CHANNEL_LAYOUT
#include "audio/chmap_avchannel.h"
#endif
#define LAYOUTS(...) (char*[]){__VA_ARGS__, NULL}
static void test_sel(const char *input, const char *expected_selection,
char **layouts)
{
struct mp_chmap_sel s = {0};
struct mp_chmap input_map;
struct mp_chmap expected_map;
assert_true(mp_chmap_from_str(&input_map, bstr0(input)));
assert_true(mp_chmap_from_str(&expected_map, bstr0(expected_selection)));
for (int n = 0; layouts[n]; n++) {
struct mp_chmap tmp;
assert_true(mp_chmap_from_str(&tmp, bstr0(layouts[n])));
int count = s.num_chmaps;
mp_chmap_sel_add_map(&s, &tmp);
assert_true(s.num_chmaps > count); // assure validity and max. count
}
assert_true(mp_chmap_sel_fallback(&s, &input_map));
// We convert expected_map to a chmap and then back to a string to avoid
// problems with ambiguous layouts.
assert_string_equal(mp_chmap_to_str(&input_map),
mp_chmap_to_str(&expected_map));
}
#if HAVE_AV_CHANNEL_LAYOUT
static bool layout_matches(const AVChannelLayout *av_layout,
const struct mp_chmap *mp_layout,
bool require_default_unspec)
{
if (!mp_chmap_is_valid(mp_layout) ||
!av_channel_layout_check(av_layout) ||
av_layout->nb_channels != mp_layout->num ||
mp_layout->num > MP_NUM_CHANNELS)
return false;
switch (av_layout->order) {
case AV_CHANNEL_ORDER_UNSPEC:
{
if (!require_default_unspec)
return true;
// mp_chmap essentially does not have a concept of "unspecified"
// so we check if the mp layout matches the default layout for such
// channel count.
struct mp_chmap default_layout = { 0 };
mp_chmap_from_channels(&default_layout, mp_layout->num);
return mp_chmap_equals(mp_layout, &default_layout);
}
case AV_CHANNEL_ORDER_NATIVE:
return av_layout->u.mask == mp_chmap_to_lavc(mp_layout);
default:
// TODO: handle custom layouts
return false;
}
return true;
}
static void test_mp_chmap_to_av_channel_layout(void)
{
mp_ch_layout_tuple *mapping_array = NULL;
void *iter = NULL;
bool anything_failed = false;
printf("Testing mp_chmap -> AVChannelLayout conversions\n");
while ((mapping_array = mp_iterate_builtin_layouts(&iter))) {
const char *mapping_name = (*mapping_array)[0];
const char *mapping_str = (*mapping_array)[1];
struct mp_chmap mp_layout = { 0 };
AVChannelLayout av_layout = { 0 };
char layout_desc[128] = {0};
assert_true(mp_chmap_from_str(&mp_layout, bstr0(mapping_str)));
mp_chmap_to_av_layout(&av_layout, &mp_layout);
assert_false(av_channel_layout_describe(&av_layout,
layout_desc, 128) < 0);
bool success =
(strcmp(layout_desc, mp_chmap_to_str(&mp_layout)) == 0 ||
layout_matches(&av_layout, &mp_layout, false));
if (!success)
anything_failed = true;
printf("%s: %s (%s) -> %s\n",
success ? "Success" : "Failure",
mapping_str, mapping_name, layout_desc);
av_channel_layout_uninit(&av_layout);
}
assert_false(anything_failed);
}
static void test_av_channel_layout_to_mp_chmap(void)
{
const AVChannelLayout *av_layout = NULL;
void *iter = NULL;
bool anything_failed = false;
printf("Testing AVChannelLayout -> mp_chmap conversions\n");
while ((av_layout = av_channel_layout_standard(&iter))) {
struct mp_chmap mp_layout = { 0 };
char layout_desc[128] = {0};
assert_false(av_channel_layout_describe(av_layout,
layout_desc, 128) < 0);
bool ret = mp_chmap_from_av_layout(&mp_layout, av_layout);
if (!ret) {
bool too_many_channels =
av_layout->nb_channels > MP_NUM_CHANNELS;
printf("Conversion from '%s' to mp_chmap failed (%s)!\n",
layout_desc,
too_many_channels ?
"channel count was over max, ignoring" :
"unexpected, failing");
// we should for now only fail with things such as 22.2
// due to mp_chmap being currently limited to 16 channels
assert_true(too_many_channels);
continue;
}
bool success =
(strcmp(layout_desc, mp_chmap_to_str(&mp_layout)) == 0 ||
layout_matches(av_layout, &mp_layout, true));
if (!success)
anything_failed = true;
printf("%s: %s -> %s\n",
success ? "Success" : "Failure",
layout_desc, mp_chmap_to_str(&mp_layout));
}
assert_false(anything_failed);
}
#endif
int main(void)
{
struct mp_chmap a;
struct mp_chmap b;
struct mp_chmap_sel s = {0};
test_sel("5.1", "7.1", LAYOUTS("7.1"));
test_sel("7.1", "5.1", LAYOUTS("5.1"));
test_sel("7.1(wide-side)", "7.1", LAYOUTS("7.1"));
test_sel("7.1(wide-side)", "5.1(side)", LAYOUTS("7.1", "5.1(side)"));
test_sel("3.1", "5.1", LAYOUTS("7.1", "5.1", "2.1", "stereo", "mono"));
test_sel("5.1", "7.1(rear)", LAYOUTS("7.1(rear)"));
test_sel("5.1(side)", "5.1", LAYOUTS("5.1", "7.1"));
test_sel("5.1", "7.1(alsa)", LAYOUTS("7.1(alsa)"));
test_sel("mono", "stereo", LAYOUTS("stereo", "5.1"));
test_sel("stereo", "stereo", LAYOUTS("stereo", "5.1"));
test_sel("5.1(side)", "7.1(rear)", LAYOUTS("stereo", "7.1(rear)"));
test_sel("7.1", "fl-fr-lfe-fc-bl-br-flc-frc",
LAYOUTS("fl-fr-lfe-fc-bl-br-flc-frc", "3.0(back)"));
mp_chmap_set_unknown(&a, 2);
mp_chmap_from_str(&b, bstr0("5.1"));
mp_chmap_sel_add_map(&s, &a);
assert_false(mp_chmap_sel_fallback(&s, &b));
assert_string_equal(mp_chmap_to_str(&b), "5.1");
test_sel("quad", "quad(side)", LAYOUTS("quad(side)", "stereo"));
test_sel("quad", "quad(side)", LAYOUTS("quad(side)", "7.0"));
test_sel("quad", "quad(side)", LAYOUTS("7.0", "quad(side)"));
test_sel("quad", "7.1(wide-side)", LAYOUTS("7.1(wide-side)", "stereo"));
test_sel("quad", "7.1(wide-side)", LAYOUTS("stereo", "7.1(wide-side)"));
test_sel("quad", "fl-fr-sl-sr",
LAYOUTS("fl-fr-fc-bl-br", "fl-fr-sl-sr"));
test_sel("quad", "fl-fr-bl-br-na-na-na-na",
LAYOUTS("fl-fr-bl-br-na-na-na-na", "quad(side)", "stereo"));
test_sel("quad", "fl-fr-bl-br-na-na-na-na",
LAYOUTS("stereo", "quad(side)", "fl-fr-bl-br-na-na-na-na"));
test_sel("fl-fr-fc-lfe-sl-sr", "fl-fr-lfe-fc-bl-br-na-na",
LAYOUTS("fl-fr-lfe-fc-bl-br-na-na", "fl-fr-lfe-fc-bl-br-sdl-sdr"));
test_sel("fl-fr-fc-lfe-sl-sr", "fl-fr-lfe-fc-bl-br-na-na",
LAYOUTS("fl-fr-lfe-fc-bl-br-sdl-sdr", "fl-fr-lfe-fc-bl-br-na-na"));
test_sel("na-fl-fr", "na-fl-fr", LAYOUTS("na-fl-fr-na", "fl-na-fr", "na-fl-fr",
"fl-fr-na-na", "na-na-fl-fr"));
mp_chmap_from_str(&a, bstr0("3.1"));
mp_chmap_from_str(&b, bstr0("2.1"));
assert_int_equal(mp_chmap_diffn(&a, &b), 1);
mp_chmap_from_str(&b, bstr0("6.1(back)"));
assert_int_equal(mp_chmap_diffn(&a, &b), 0);
assert_int_equal(mp_chmap_diffn(&b, &a), 3);
#if HAVE_AV_CHANNEL_LAYOUT
test_av_channel_layout_to_mp_chmap();
test_mp_chmap_to_av_channel_layout();
#endif
return 0;
}