mp_chmap_is_valid:
  126|  3.81k|{
  127|  3.81k|    bool mapped[MP_SPEAKER_ID_COUNT] = {0};
  128|  38.5k|    for (int n = 0; n < src->num; n++) {
  ------------------
  |  Branch (128:21): [True: 34.7k, False: 3.81k]
  ------------------
  129|  34.7k|        int sp = src->speaker[n];
  130|  34.7k|        if (sp >= MP_SPEAKER_ID_COUNT || mapped[sp])
  ------------------
  |  Branch (130:13): [True: 0, False: 34.7k]
  |  Branch (130:42): [True: 2, False: 34.7k]
  ------------------
  131|      2|            return false;
  132|  34.7k|        if (sp != MP_SPEAKER_ID_NA)
  ------------------
  |  Branch (132:13): [True: 12.6k, False: 22.0k]
  ------------------
  133|  12.6k|            mapped[sp] = true;
  134|  34.7k|    }
  135|  3.81k|    return src->num > 0;
  136|  3.81k|}
mp_chmap_is_unknown:
  146|     57|{
  147|     57|    for (int n = 0; n < src->num; n++) {
  ------------------
  |  Branch (147:21): [True: 57, False: 0]
  ------------------
  148|     57|        if (src->speaker[n] != MP_SPEAKER_ID_NA)
  ------------------
  |  Branch (148:13): [True: 57, False: 0]
  ------------------
  149|     57|            return false;
  150|     57|    }
  151|      0|    return mp_chmap_is_valid(src);
  152|     57|}
mp_chmap_equals:
  156|  1.18k|{
  157|  1.18k|    if (a->num != b->num)
  ------------------
  |  Branch (157:9): [True: 246, False: 935]
  ------------------
  158|    246|        return false;
  159|  5.40k|    for (int n = 0; n < a->num; n++) {
  ------------------
  |  Branch (159:21): [True: 4.61k, False: 790]
  ------------------
  160|  4.61k|        if (a->speaker[n] != b->speaker[n])
  ------------------
  |  Branch (160:13): [True: 145, False: 4.46k]
  ------------------
  161|    145|            return false;
  162|  4.61k|    }
  163|    790|    return true;
  164|    935|}
mp_chmap_from_channels:
  218|  1.46k|{
  219|  1.46k|    *dst = (struct mp_chmap) {0};
  220|  1.46k|    if (num_channels >= 0 && num_channels < MP_ARRAY_SIZE(default_layouts))
  ------------------
  |  |   48|  1.42k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (220:9): [True: 1.42k, False: 36]
  |  Branch (220:30): [True: 1.15k, False: 271]
  ------------------
  221|  1.15k|        *dst = default_layouts[num_channels];
  222|  1.46k|    if (!dst->num)
  ------------------
  |  Branch (222:9): [True: 309, False: 1.15k]
  ------------------
  223|    309|        mp_chmap_set_unknown(dst, num_channels);
  224|  1.46k|}
mp_chmap_set_unknown:
  232|    455|{
  233|    455|    if (num_channels < 0 || num_channels > MP_NUM_CHANNELS) {
  ------------------
  |  |   25|    394|#define MP_NUM_CHANNELS 64
  ------------------
  |  Branch (233:9): [True: 61, False: 394]
  |  Branch (233:29): [True: 42, False: 352]
  ------------------
  234|    103|        *dst = (struct mp_chmap) {0};
  235|    352|    } else {
  236|    352|        dst->num = num_channels;
  237|  11.3k|        for (int n = 0; n < dst->num; n++)
  ------------------
  |  Branch (237:25): [True: 11.0k, False: 352]
  ------------------
  238|  11.0k|            dst->speaker[n] = MP_SPEAKER_ID_NA;
  239|    352|    }
  240|    455|}
mp_chmap_to_str_buf:
  368|     57|{
  369|     57|    buf[0] = '\0';
  370|       |
  371|     57|    if (mp_chmap_is_unknown(src)) {
  ------------------
  |  Branch (371:9): [True: 0, False: 57]
  ------------------
  372|      0|        snprintf(buf, buf_size, "unknown%d", src->num);
  373|      0|        return buf;
  374|      0|    }
  375|       |
  376|    171|    for (int n = 0; n < src->num; n++) {
  ------------------
  |  Branch (376:21): [True: 114, False: 57]
  ------------------
  377|    114|        int sp = src->speaker[n];
  378|    114|        const char *s = sp < MP_SPEAKER_ID_COUNT ? speaker_names[sp][0] : NULL;
  ------------------
  |  Branch (378:25): [True: 114, False: 0]
  ------------------
  379|    114|        char sp_buf[10];
  380|    114|        if (!s) {
  ------------------
  |  Branch (380:13): [True: 0, False: 114]
  ------------------
  381|      0|            snprintf(sp_buf, sizeof(sp_buf), "sp%d", sp);
  382|      0|            s = sp_buf;
  383|      0|        }
  384|    114|        mp_snprintf_cat(buf, buf_size, "%s%s", n > 0 ? "-" : "", s);
  ------------------
  |  Branch (384:48): [True: 57, False: 57]
  ------------------
  385|    114|    }
  386|       |
  387|       |    // To standard layout name
  388|    228|    for (int n = 0; std_layout_names[n][0]; n++) {
  ------------------
  |  Branch (388:21): [True: 228, False: 0]
  ------------------
  389|    228|        if (strcmp(buf, std_layout_names[n][1]) == 0) {
  ------------------
  |  Branch (389:13): [True: 57, False: 171]
  ------------------
  390|     57|            snprintf(buf, buf_size, "%s", std_layout_names[n][0]);
  391|     57|            break;
  392|     57|        }
  393|    228|    }
  394|       |
  395|     57|    return buf;
  396|     57|}
mp_chmap_from_str:
  403|  2.43k|{
  404|       |    // Single number corresponds to mp_chmap_from_channels()
  405|  2.43k|    if (src.len > 0) {
  ------------------
  |  Branch (405:9): [True: 2.43k, False: 1]
  ------------------
  406|  2.43k|        bstr t = src;
  407|  2.43k|        bool unknown = bstr_eatstart0(&t, "unknown");
  408|  2.43k|        bstr rest;
  409|  2.43k|        long long count = bstrtoll(t, &rest, 10);
  410|  2.43k|        if (rest.len == 0) {
  ------------------
  |  Branch (410:13): [True: 1.60k, False: 822]
  ------------------
  411|  1.60k|            struct mp_chmap res;
  412|  1.60k|            if (unknown) {
  ------------------
  |  Branch (412:17): [True: 146, False: 1.46k]
  ------------------
  413|    146|                mp_chmap_set_unknown(&res, count);
  414|  1.46k|            } else {
  415|  1.46k|                mp_chmap_from_channels(&res, count);
  416|  1.46k|            }
  417|  1.60k|            if (mp_chmap_is_valid(&res)) {
  ------------------
  |  Branch (417:17): [True: 1.50k, False: 106]
  ------------------
  418|  1.50k|                *dst = res;
  419|  1.50k|                return true;
  420|  1.50k|            }
  421|  1.60k|        }
  422|  2.43k|    }
  423|       |
  424|       |    // From standard layout name
  425|  33.4k|    for (int n = 0; std_layout_names[n][0]; n++) {
  ------------------
  |  Branch (425:21): [True: 32.7k, False: 674]
  ------------------
  426|  32.7k|        if (bstr_equals0(src, std_layout_names[n][0])) {
  ------------------
  |  Branch (426:13): [True: 255, False: 32.4k]
  ------------------
  427|    255|            src = bstr0(std_layout_names[n][1]);
  428|    255|            break;
  429|    255|        }
  430|  32.7k|    }
  431|       |
  432|       |    // Explicit speaker list (separated by "-")
  433|    929|    struct mp_chmap res = {0};
  434|  2.66k|    while (src.len) {
  ------------------
  |  Branch (434:12): [True: 1.96k, False: 703]
  ------------------
  435|  1.96k|        bstr s;
  436|  1.96k|        bstr_split_tok(src, "-", &s, &src);
  437|  1.96k|        int speaker = -1;
  438|  46.0k|        for (int n = 0; n < MP_SPEAKER_ID_COUNT; n++) {
  ------------------
  |  Branch (438:25): [True: 45.5k, False: 553]
  ------------------
  439|  45.5k|            const char *name = speaker_names[n][0];
  440|  45.5k|            if (name && bstr_equals0(s, name)) {
  ------------------
  |  Branch (440:17): [True: 25.4k, False: 20.1k]
  |  Branch (440:25): [True: 1.40k, False: 24.0k]
  ------------------
  441|  1.40k|                speaker = n;
  442|  1.40k|                break;
  443|  1.40k|            }
  444|  45.5k|        }
  445|  1.96k|        if (speaker < 0) {
  ------------------
  |  Branch (445:13): [True: 553, False: 1.40k]
  ------------------
  446|    553|            if (bstr_eatstart0(&s, "sp")) {
  ------------------
  |  Branch (446:17): [True: 404, False: 149]
  ------------------
  447|    404|                long long sp = bstrtoll(s, &s, 0);
  448|    404|                if (s.len == 0 && sp >= 0 && sp < MP_SPEAKER_ID_COUNT)
  ------------------
  |  Branch (448:21): [True: 395, False: 9]
  |  Branch (448:35): [True: 395, False: 0]
  |  Branch (448:46): [True: 328, False: 67]
  ------------------
  449|    328|                    speaker = sp;
  450|    404|            }
  451|    553|            if (speaker < 0)
  ------------------
  |  Branch (451:17): [True: 225, False: 328]
  ------------------
  452|    225|                return false;
  453|    553|        }
  454|  1.73k|        if (res.num >= MP_NUM_CHANNELS)
  ------------------
  |  |   25|  1.73k|#define MP_NUM_CHANNELS 64
  ------------------
  |  Branch (454:13): [True: 1, False: 1.73k]
  ------------------
  455|      1|            return false;
  456|  1.73k|        res.speaker[res.num] = speaker;
  457|  1.73k|        res.num++;
  458|  1.73k|    }
  459|       |
  460|    703|    *dst = res;
  461|    703|    return true;
  462|    929|}
mp_chmap_print_help:
  501|      1|{
  502|      1|    mp_info(log, "Speakers:\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  503|     66|    for (int n = 0; n < MP_SPEAKER_ID_COUNT; n++) {
  ------------------
  |  Branch (503:21): [True: 65, False: 1]
  ------------------
  504|     65|        if (speaker_names[n][0])
  ------------------
  |  Branch (504:13): [True: 31, False: 34]
  ------------------
  505|     31|            mp_info(log, "    %-16s (%s)\n",
  ------------------
  |  |   74|     31|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  506|     65|                    speaker_names[n][0], speaker_names[n][1]);
  507|     65|    }
  508|      1|    mp_info(log, "Standard layouts:\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  509|     44|    for (int n = 0; std_layout_names[n][0]; n++) {
  ------------------
  |  Branch (509:21): [True: 43, False: 1]
  ------------------
  510|     43|        mp_info(log, "    %-16s (%s)\n",
  ------------------
  |  |   74|     43|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  511|     43|                 std_layout_names[n][0], std_layout_names[n][1]);
  512|     43|    }
  513|     65|    for (int n = 0; n < MP_NUM_CHANNELS; n++)
  ------------------
  |  |   25|     65|#define MP_NUM_CHANNELS 64
  ------------------
  |  Branch (513:21): [True: 64, False: 1]
  ------------------
  514|     64|        mp_info(log, "    unknown%d\n", n + 1);
  ------------------
  |  |   74|     64|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  515|      1|}

ad_lavc.c:add_decoders:
  321|  2.58k|{
  322|  2.58k|    mp_add_lavc_decoders(list, AVMEDIA_TYPE_AUDIO);
  323|  2.58k|}

af_fmt_to_str:
  117|  9.61k|{
  118|  9.61k|    switch (format) {
  ------------------
  |  Branch (118:13): [True: 0, False: 9.61k]
  ------------------
  119|    506|    case AF_FORMAT_U8:          return "u8";
  ------------------
  |  Branch (119:5): [True: 506, False: 9.10k]
  ------------------
  120|    506|    case AF_FORMAT_S16:         return "s16";
  ------------------
  |  Branch (120:5): [True: 506, False: 9.10k]
  ------------------
  121|    506|    case AF_FORMAT_S32:         return "s32";
  ------------------
  |  Branch (121:5): [True: 506, False: 9.10k]
  ------------------
  122|    506|    case AF_FORMAT_S64:         return "s64";
  ------------------
  |  Branch (122:5): [True: 506, False: 9.10k]
  ------------------
  123|    506|    case AF_FORMAT_FLOAT:       return "float";
  ------------------
  |  Branch (123:5): [True: 506, False: 9.10k]
  ------------------
  124|    506|    case AF_FORMAT_DOUBLE:      return "double";
  ------------------
  |  Branch (124:5): [True: 506, False: 9.10k]
  ------------------
  125|    506|    case AF_FORMAT_U8P:         return "u8p";
  ------------------
  |  Branch (125:5): [True: 506, False: 9.10k]
  ------------------
  126|    506|    case AF_FORMAT_S16P:        return "s16p";
  ------------------
  |  Branch (126:5): [True: 506, False: 9.10k]
  ------------------
  127|    506|    case AF_FORMAT_S32P:        return "s32p";
  ------------------
  |  Branch (127:5): [True: 506, False: 9.10k]
  ------------------
  128|    506|    case AF_FORMAT_S64P:        return "s64p";
  ------------------
  |  Branch (128:5): [True: 506, False: 9.10k]
  ------------------
  129|    506|    case AF_FORMAT_FLOATP:      return "floatp";
  ------------------
  |  Branch (129:5): [True: 506, False: 9.10k]
  ------------------
  130|    506|    case AF_FORMAT_DOUBLEP:     return "doublep";
  ------------------
  |  Branch (130:5): [True: 506, False: 9.10k]
  ------------------
  131|    506|    case AF_FORMAT_S_AAC:       return "spdif-aac";
  ------------------
  |  Branch (131:5): [True: 506, False: 9.10k]
  ------------------
  132|    506|    case AF_FORMAT_S_AC3:       return "spdif-ac3";
  ------------------
  |  Branch (132:5): [True: 506, False: 9.10k]
  ------------------
  133|    506|    case AF_FORMAT_S_DTS:       return "spdif-dts";
  ------------------
  |  Branch (133:5): [True: 506, False: 9.10k]
  ------------------
  134|    506|    case AF_FORMAT_S_DTSHD:     return "spdif-dtshd";
  ------------------
  |  Branch (134:5): [True: 506, False: 9.10k]
  ------------------
  135|    506|    case AF_FORMAT_S_EAC3:      return "spdif-eac3";
  ------------------
  |  Branch (135:5): [True: 506, False: 9.10k]
  ------------------
  136|    506|    case AF_FORMAT_S_MP3:       return "spdif-mp3";
  ------------------
  |  Branch (136:5): [True: 506, False: 9.10k]
  ------------------
  137|    506|    case AF_FORMAT_S_TRUEHD:    return "spdif-truehd";
  ------------------
  |  Branch (137:5): [True: 506, False: 9.10k]
  ------------------
  138|  9.61k|    }
  139|      0|    return "??";
  140|  9.61k|}

ao_hotplug_create:
  471|     21|{
  472|     21|    struct ao_hotplug *hp = talloc_ptrtype(NULL, hp);
  ------------------
  |  |   34|     21|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|     21|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     21|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  473|     21|    *hp = (struct ao_hotplug){
  474|     21|        .global = global,
  475|     21|        .wakeup_cb = wakeup_cb,
  476|     21|        .wakeup_ctx = wakeup_ctx,
  477|     21|        .needs_update = true,
  478|     21|    };
  479|     21|    return hp;
  480|     21|}
ao_hotplug_check_update:
  492|      3|{
  493|      3|    if (hp->ao && ao_query_and_reset_events(hp->ao, AO_EVENT_HOTPLUG)) {
  ------------------
  |  Branch (493:9): [True: 0, False: 3]
  |  Branch (493:19): [True: 0, False: 0]
  ------------------
  494|      0|        hp->needs_update = true;
  495|      0|        return true;
  496|      0|    }
  497|      3|    return false;
  498|      3|}
ao_hotplug_get_device_list:
  503|    148|{
  504|    148|    if (hp->list && !hp->needs_update)
  ------------------
  |  Branch (504:9): [True: 127, False: 21]
  |  Branch (504:21): [True: 127, False: 0]
  ------------------
  505|    127|        return hp->list;
  506|       |
  507|     21|    talloc_free(hp->list);
  ------------------
  |  |   47|     21|#define talloc_free                     ta_free
  ------------------
  508|     21|    struct ao_device_list *list = talloc_zero(hp, struct ao_device_list);
  ------------------
  |  |   27|     21|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|     21|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     21|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  509|     21|    hp->list = list;
  510|       |
  511|     21|    MP_TARRAY_APPEND(list, list->devices, list->num_devices,
  ------------------
  |  |  105|     21|    do {                                            \
  |  |  106|     21|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|     21|    do {                                            \
  |  |  |  |   97|     21|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|     21|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|     21|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|     21|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 21, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|     21|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|     21|    do {                                                        \
  |  |  |  |  |  |   89|     21|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|     21|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|     21|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|     21|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|     21|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|     21|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|     21|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|     21|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|     21|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|     21|        (idxvar)++;                                 \
  |  |  109|     21|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  512|     21|        (struct ao_device_desc){"auto", "Autoselect device"});
  513|       |
  514|       |    // Try to use the same AO for hotplug handling as for playback.
  515|       |    // Different AOs may not agree and the playback one is the only one the
  516|       |    // user knows about and may even have configured explicitly.
  517|     21|    if (!hp->ao && playback_ao && playback_ao->driver->hotplug_init) {
  ------------------
  |  Branch (517:9): [True: 21, False: 0]
  |  Branch (517:20): [True: 0, False: 21]
  |  Branch (517:35): [True: 0, False: 0]
  ------------------
  518|      0|        struct ao *ao = ao_alloc(true, hp->global, hp->wakeup_cb, hp->wakeup_ctx,
  519|      0|                                 (char *)playback_ao->driver->name);
  520|      0|        if (playback_ao->driver->hotplug_init(ao) >= 0) {
  ------------------
  |  Branch (520:13): [True: 0, False: 0]
  ------------------
  521|      0|            hp->ao = ao;
  522|      0|        } else {
  523|      0|            talloc_free(ao);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  524|      0|        }
  525|      0|    }
  526|       |
  527|     21|    for (int n = 0; n < MP_ARRAY_SIZE(audio_out_drivers); n++) {
  ------------------
  |  |   48|     21|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (527:21): [True: 21, False: 0]
  ------------------
  528|     21|        const struct ao_driver *d = audio_out_drivers[n];
  529|     21|        if (d == &audio_out_null)
  ------------------
  |  Branch (529:13): [True: 21, False: 0]
  ------------------
  530|     21|            break; // don't add unsafe/special entries
  531|       |
  532|      0|        struct ao *ao = ao_alloc(true, hp->global, hp->wakeup_cb, hp->wakeup_ctx,
  533|      0|                                 (char *)d->name);
  534|      0|        if (!ao)
  ------------------
  |  Branch (534:13): [True: 0, False: 0]
  ------------------
  535|      0|            continue;
  536|       |
  537|      0|        if (ao->driver->hotplug_init) {
  ------------------
  |  Branch (537:13): [True: 0, False: 0]
  ------------------
  538|      0|            if (ao->driver->hotplug_init(ao) >= 0) {
  ------------------
  |  Branch (538:17): [True: 0, False: 0]
  ------------------
  539|      0|                get_devices(ao, list);
  540|      0|                if (hp->ao)
  ------------------
  |  Branch (540:21): [True: 0, False: 0]
  ------------------
  541|      0|                    ao->driver->hotplug_uninit(ao);
  542|      0|                else
  543|      0|                    hp->ao = ao; // keep this one
  544|      0|            }
  545|      0|        } else {
  546|      0|            get_devices(ao, list);
  547|      0|        }
  548|      0|        if (ao != hp->ao)
  ------------------
  |  Branch (548:13): [True: 0, False: 0]
  ------------------
  549|      0|            talloc_free(ao);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  550|      0|    }
  551|     21|    hp->needs_update = false;
  552|     21|    return list;
  553|    148|}
ao_hotplug_destroy:
  580|  17.0k|{
  581|  17.0k|    if (!hp)
  ------------------
  |  Branch (581:9): [True: 17.0k, False: 21]
  ------------------
  582|  17.0k|        return;
  583|     21|    if (hp->ao && hp->ao->driver->hotplug_uninit)
  ------------------
  |  Branch (583:9): [True: 0, False: 21]
  |  Branch (583:19): [True: 0, False: 0]
  ------------------
  584|      0|        hp->ao->driver->hotplug_uninit(hp->ao);
  585|     21|    talloc_free(hp->ao);
  ------------------
  |  |   47|     21|#define talloc_free                     ta_free
  ------------------
  586|     21|    talloc_free(hp);
  ------------------
  |  |   47|     21|#define talloc_free                     ta_free
  ------------------
  587|     21|}
ao.c:get_desc:
  112|   124k|{
  113|   124k|    if (index >= MP_ARRAY_SIZE(audio_out_drivers))
  ------------------
  |  |   48|   124k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (113:9): [True: 18.1k, False: 106k]
  ------------------
  114|  18.1k|        return false;
  115|   106k|    const struct ao_driver *ao = audio_out_drivers[index];
  116|   106k|    *dst = (struct m_obj_desc) {
  117|   106k|        .name = ao->name,
  118|   106k|        .description = ao->description,
  119|   106k|        .priv_size = ao->priv_size,
  120|   106k|        .priv_defaults = ao->priv_defaults,
  121|   106k|        .options = ao->options,
  122|   106k|        .options_prefix = ao->options_prefix,
  123|   106k|        .global_opts = ao->global_opts,
  124|   106k|        .hidden = ao->encode,
  125|   106k|        .p = ao,
  126|   106k|    };
  127|   106k|    return true;
  128|   124k|}

mp_add_lavc_decoders:
  243|  5.16k|{
  244|  5.16k|    add_codecs(list, type, true);
  245|  5.16k|}
mp_get_lavf_demuxers:
  254|  8.17k|{
  255|  8.17k|    char **list = NULL;
  256|  8.17k|    void *iter = NULL;
  257|  8.17k|    int num = 0;
  258|  2.91M|    for (;;) {
  259|  2.91M|        const AVInputFormat *cur = av_demuxer_iterate(&iter);
  260|  2.91M|        if (!cur)
  ------------------
  |  Branch (260:13): [True: 8.17k, False: 2.90M]
  ------------------
  261|  8.17k|            break;
  262|  2.90M|        MP_TARRAY_APPEND(NULL, list, num, talloc_strdup(list, cur->name));
  ------------------
  |  |  105|  2.90M|    do {                                            \
  |  |  106|  2.90M|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  2.90M|    do {                                            \
  |  |  |  |   97|  2.90M|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  2.90M|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  2.90M|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  2.90M|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 65.4k, False: 2.83M]
  |  |  |  |  ------------------
  |  |  |  |   99|  2.90M|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  65.4k|    do {                                                        \
  |  |  |  |  |  |   89|  65.4k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  65.4k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  65.4k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  65.4k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  65.4k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  65.4k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  65.4k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  2.90M|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  2.90M|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  2.90M|        (idxvar)++;                                 \
  |  |  109|  2.90M|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  263|  2.90M|    }
  264|  8.17k|    MP_TARRAY_APPEND(NULL, list, num, NULL);
  ------------------
  |  |  105|  8.17k|    do {                                            \
  |  |  106|  8.17k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  8.17k|    do {                                            \
  |  |  |  |   97|  8.17k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  8.17k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  8.17k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  8.17k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 8.17k]
  |  |  |  |  ------------------
  |  |  |  |   99|  8.17k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  8.17k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  8.17k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  8.17k|        (idxvar)++;                                 \
  |  |  109|  8.17k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  265|  8.17k|    return list;
  266|  8.17k|}
mp_get_lavf_protocols:
  269|  11.9k|{
  270|  11.9k|    char **list = NULL;
  271|  11.9k|    int num = 0;
  272|  11.9k|    void *opaque = NULL;
  273|  11.9k|    const char *name;
  274|   143k|    while ((name = avio_enum_protocols(&opaque, 0)))
  ------------------
  |  Branch (274:12): [True: 131k, False: 11.9k]
  ------------------
  275|   131k|        MP_TARRAY_APPEND(NULL, list, num, talloc_strdup(list, name));
  ------------------
  |  |  105|   131k|    do {                                            \
  |  |  106|   131k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|   131k|    do {                                            \
  |  |  |  |   97|   131k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|   131k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|   131k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|   131k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 35.8k, False: 95.5k]
  |  |  |  |  ------------------
  |  |  |  |   99|   131k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  35.8k|    do {                                                        \
  |  |  |  |  |  |   89|  35.8k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  35.8k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  35.8k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  35.8k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  35.8k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  35.8k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  35.8k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|   131k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|   131k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|   131k|        (idxvar)++;                                 \
  |  |  109|   131k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  276|  11.9k|    MP_TARRAY_APPEND(NULL, list, num, NULL);
  ------------------
  |  |  105|  11.9k|    do {                                            \
  |  |  106|  11.9k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  11.9k|    do {                                            \
  |  |  |  |   97|  11.9k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  11.9k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  11.9k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  11.9k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 11.9k]
  |  |  |  |  ------------------
  |  |  |  |   99|  11.9k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  11.9k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  11.9k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  11.9k|        (idxvar)++;                                 \
  |  |  109|  11.9k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  277|  11.9k|    return list;
  278|  11.9k|}
mp_codec_from_av_codec_id:
  297|  1.19M|{
  298|  1.19M|    const char *name = NULL;
  299|  1.19M|    const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id);
  300|  1.19M|    if (desc)
  ------------------
  |  Branch (300:9): [True: 1.19M, False: 0]
  ------------------
  301|  1.19M|        name = desc->name;
  302|  1.19M|    if (!name) {
  ------------------
  |  Branch (302:9): [True: 0, False: 1.19M]
  ------------------
  303|      0|        const AVCodec *avcodec = avcodec_find_decoder(codec_id);
  304|      0|        if (avcodec)
  ------------------
  |  Branch (304:13): [True: 0, False: 0]
  ------------------
  305|      0|            name = avcodec->name;
  306|      0|    }
  307|  1.19M|    return name;
  308|  1.19M|}
mp_set_avdict:
  320|  2.17k|{
  321|  2.17k|    for (int n = 0; kv && kv[n * 2]; n++)
  ------------------
  |  Branch (321:21): [True: 0, False: 2.17k]
  |  Branch (321:27): [True: 0, False: 0]
  ------------------
  322|      0|        av_dict_set(dict, kv[n * 2 + 0], kv[n * 2 + 1], 0);
  323|  2.17k|}
mp_avdict_print_unset:
  328|    680|{
  329|    680|    AVDictionaryEntry *t = NULL;
  330|  4.22k|    while ((t = av_dict_get(dict, "", t, AV_DICT_IGNORE_SUFFIX)))
  ------------------
  |  Branch (330:12): [True: 3.54k, False: 680]
  ------------------
  331|  3.54k|        mp_msg(log, msgl, "Could not set AVOption %s='%s'\n", t->key, t->value);
  332|    680|}
av_common.c:add_codecs:
  227|  5.16k|{
  228|  5.16k|    void *iter = NULL;
  229|  2.51M|    for (;;) {
  230|  2.51M|        const AVCodec *cur = av_codec_iterate(&iter);
  231|  2.51M|        if (!cur)
  ------------------
  |  Branch (231:13): [True: 5.16k, False: 2.50M]
  ------------------
  232|  5.16k|            break;
  233|  2.50M|        if (av_codec_is_decoder(cur) == decoders &&
  ------------------
  |  Branch (233:13): [True: 2.50M, False: 0]
  ------------------
  234|  2.50M|            (type == AVMEDIA_TYPE_UNKNOWN || cur->type == type))
  ------------------
  |  Branch (234:14): [True: 0, False: 2.50M]
  |  Branch (234:46): [True: 1.19M, False: 1.31M]
  ------------------
  235|  1.19M|        {
  236|  1.19M|            mp_add_decoder(list, mp_codec_from_av_codec_id(cur->id),
  237|  1.19M|                           cur->name, cur->long_name);
  238|  1.19M|        }
  239|  2.50M|    }
  240|  5.16k|}

init_libav:
  154|  17.0k|{
  155|  17.0k|    mp_mutex_lock(&log_lock);
  ------------------
  |  |  131|  17.0k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  156|  17.0k|    if (!log_mpv_instance) {
  ------------------
  |  Branch (156:9): [True: 17.0k, False: 0]
  ------------------
  157|  17.0k|        log_mpv_instance = global;
  158|  17.0k|        log_root = mp_log_new(NULL, global->log, "ffmpeg");
  159|  17.0k|        log_decaudio = mp_log_new(log_root, log_root, "audio");
  160|  17.0k|        log_decvideo = mp_log_new(log_root, log_root, "video");
  161|  17.0k|        log_demuxer = mp_log_new(log_root, log_root, "demuxer");
  162|  17.0k|        log_buffer = (bstr){0};
  163|  17.0k|        av_log_set_callback(mp_msg_av_log_callback);
  164|  17.0k|    }
  165|  17.0k|    mp_mutex_unlock(&log_lock);
  ------------------
  |  |  133|  17.0k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  166|       |
  167|  17.0k|    avformat_network_init();
  168|       |
  169|  17.0k|#if HAVE_LIBAVDEVICE
  170|  17.0k|    avdevice_register_all();
  171|  17.0k|#endif
  172|  17.0k|}
uninit_libav:
  175|  17.0k|{
  176|  17.0k|    mp_mutex_lock(&log_lock);
  ------------------
  |  |  131|  17.0k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  177|  17.0k|    if (log_mpv_instance == global) {
  ------------------
  |  Branch (177:9): [True: 17.0k, False: 0]
  ------------------
  178|  17.0k|        av_log_set_callback(av_log_default_callback);
  179|  17.0k|        log_mpv_instance = NULL;
  180|  17.0k|        talloc_free(log_root);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  181|  17.0k|    }
  182|  17.0k|    mp_mutex_unlock(&log_lock);
  ------------------
  |  |  133|  17.0k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  183|  17.0k|}
check_library_versions:
  196|  30.1k|{
  197|  30.1k|    const struct lib libs[] = {
  198|  30.1k|        {"libavcodec",    LIBAVCODEC_VERSION_INT,    avcodec_version()},
  199|  30.1k|#if HAVE_LIBAVDEVICE
  200|  30.1k|        {"libavdevice",   LIBAVDEVICE_VERSION_INT,   avdevice_version()},
  201|  30.1k|#endif
  202|  30.1k|        {"libavfilter",   LIBAVFILTER_VERSION_INT,   avfilter_version()},
  203|  30.1k|        {"libavformat",   LIBAVFORMAT_VERSION_INT,   avformat_version()},
  204|  30.1k|        {"libavutil",     LIBAVUTIL_VERSION_INT,     avutil_version()},
  205|  30.1k|        {"libswresample", LIBSWRESAMPLE_VERSION_INT, swresample_version()},
  206|  30.1k|        {"libswscale",    LIBSWSCALE_VERSION_INT,    swscale_version()},
  207|  30.1k|    };
  208|       |
  209|  30.1k|    const char *runtime_version = av_version_info();
  210|  30.1k|    mp_msg(log, v, "FFmpeg version: %s", FFMPEG_VERSION);
  211|  30.1k|    if (strcmp(runtime_version, FFMPEG_VERSION))
  ------------------
  |  Branch (211:9): [True: 0, False: 30.1k]
  ------------------
  212|      0|        mp_msg(log, v, " (runtime %s)", runtime_version);
  213|  30.1k|    mp_msg(log, v, "\n");
  214|  30.1k|    mp_msg(log, v, "FFmpeg library versions:\n");
  215|       |
  216|   240k|    for (int n = 0; n < MP_ARRAY_SIZE(libs); n++) {
  ------------------
  |  |   48|   240k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (216:21): [True: 210k, False: 30.1k]
  ------------------
  217|   210k|        const struct lib *l = &libs[n];
  218|   210k|        mp_msg(log, v, "   %-15s %d.%d.%d", l->name, V(l->buildv));
  ------------------
  |  |  185|   210k|#define V(x) AV_VERSION_MAJOR(x), \
  |  |  186|   210k|             AV_VERSION_MINOR(x), \
  |  |  187|   210k|             AV_VERSION_MICRO(x)
  ------------------
  219|   210k|        if (l->buildv != l->runv)
  ------------------
  |  Branch (219:13): [True: 0, False: 210k]
  ------------------
  220|      0|            mp_msg(log, v, " (runtime %d.%d.%d)", V(l->runv));
  ------------------
  |  |  185|      0|#define V(x) AV_VERSION_MAJOR(x), \
  |  |  186|      0|             AV_VERSION_MINOR(x), \
  |  |  187|      0|             AV_VERSION_MICRO(x)
  ------------------
  221|   210k|        mp_msg(log, v, "\n");
  222|   210k|        if (l->buildv > l->runv ||
  ------------------
  |  Branch (222:13): [True: 0, False: 210k]
  ------------------
  223|   210k|            AV_VERSION_MAJOR(l->buildv) != AV_VERSION_MAJOR(l->runv))
  ------------------
  |  Branch (223:13): [True: 0, False: 210k]
  ------------------
  224|      0|        {
  225|      0|            mp_fatal(log, "%s: build version %d.%d.%d incompatible with runtime version %d.%d.%d\n",
  ------------------
  |  |   71|      0|#define mp_fatal(log, ...)      mp_msg(log, MSGL_FATAL, __VA_ARGS__)
  ------------------
  226|      0|                     l->name, V(l->buildv), V(l->runv));
  227|      0|            exit(1);
  228|      0|        }
  229|   210k|    }
  230|  30.1k|}
av_log.c:mp_msg_av_log_callback:
  119|  7.61k|{
  120|  7.61k|    AVClass *avc = ptr ? *(AVClass **)ptr : NULL;
  ------------------
  |  Branch (120:20): [True: 7.00k, False: 612]
  ------------------
  121|  7.61k|    int mp_level = av_log_level_to_mp_level(level);
  122|       |
  123|       |    // Note: mp_log is thread-safe, but destruction of the log instances is not.
  124|  7.61k|    mp_mutex_lock(&log_lock);
  ------------------
  |  |  131|  7.61k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  125|       |
  126|  7.61k|    if (!log_mpv_instance) {
  ------------------
  |  Branch (126:9): [True: 0, False: 7.61k]
  ------------------
  127|      0|        mp_mutex_unlock(&log_lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  128|       |        // Fallback to stderr
  129|      0|        vfprintf(stderr, fmt, vl);
  130|      0|        return;
  131|      0|    }
  132|       |
  133|  7.61k|    struct mp_log *log = get_av_log(ptr);
  134|       |
  135|  7.61k|    if (mp_msg_test(log, mp_level)) {
  ------------------
  |  Branch (135:9): [True: 4.35k, False: 3.26k]
  ------------------
  136|  4.35k|        log_buffer.len = 0;
  137|  4.35k|        bstr_xappend_vasprintf(log_root, &log_buffer, fmt, vl);
  138|  4.35k|        if (!log_buffer.len)
  ------------------
  |  Branch (138:13): [True: 0, False: 4.35k]
  ------------------
  139|      0|            goto done;
  140|  4.35k|        const char *prefix = avc ? avclass_item_name(ptr, avc) : NULL;
  ------------------
  |  Branch (140:30): [True: 4.13k, False: 219]
  ------------------
  141|  4.35k|        if (log_print_prefix && prefix) {
  ------------------
  |  Branch (141:13): [True: 4.30k, False: 50]
  |  Branch (141:33): [True: 4.08k, False: 219]
  ------------------
  142|  4.08k|            mp_msg(log, mp_level, "%s: %.*s", prefix, BSTR_P(log_buffer));
  ------------------
  |  |  283|  4.08k|#define BSTR_P(bstr) (int)((bstr).len), ((bstr).start ? (char*)(bstr).start : "")
  |  |  ------------------
  |  |  |  Branch (283:42): [True: 4.08k, False: 0]
  |  |  ------------------
  ------------------
  143|  4.08k|        } else {
  144|    269|            mp_msg(log, mp_level, "%.*s", BSTR_P(log_buffer));
  ------------------
  |  |  283|    269|#define BSTR_P(bstr) (int)((bstr).len), ((bstr).start ? (char*)(bstr).start : "")
  |  |  ------------------
  |  |  |  Branch (283:42): [True: 269, False: 0]
  |  |  ------------------
  ------------------
  145|    269|        }
  146|  4.35k|        log_print_prefix = log_buffer.start[log_buffer.len - 1] == '\n';
  147|  4.35k|    }
  148|       |
  149|  7.61k|done:
  150|  7.61k|    mp_mutex_unlock(&log_lock);
  ------------------
  |  |  133|  7.61k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  151|  7.61k|}
av_log.c:av_log_level_to_mp_level:
   63|  7.61k|{
   64|  7.61k|    if (av_level > AV_LOG_VERBOSE)
  ------------------
  |  Branch (64:9): [True: 3.45k, False: 4.15k]
  ------------------
   65|  3.45k|        return MSGL_TRACE;
   66|  4.15k|    if (av_level > AV_LOG_INFO)
  ------------------
  |  Branch (66:9): [True: 2.51k, False: 1.64k]
  ------------------
   67|  2.51k|        return MSGL_DEBUG;
   68|  1.64k|    if (av_level > AV_LOG_WARNING)
  ------------------
  |  Branch (68:9): [True: 79, False: 1.56k]
  ------------------
   69|     79|        return MSGL_V;
   70|  1.56k|    if (av_level > AV_LOG_ERROR)
  ------------------
  |  Branch (70:9): [True: 129, False: 1.43k]
  ------------------
   71|    129|        return MSGL_WARN;
   72|  1.43k|    if (av_level > AV_LOG_FATAL)
  ------------------
  |  Branch (72:9): [True: 1.43k, False: 0]
  ------------------
   73|  1.43k|        return MSGL_ERR;
   74|      0|    return MSGL_FATAL;
   75|  1.43k|}
av_log.c:get_av_log:
   78|  7.61k|{
   79|  7.61k|    if (!ptr)
  ------------------
  |  Branch (79:9): [True: 612, False: 7.00k]
  ------------------
   80|    612|        return log_root;
   81|       |
   82|  7.00k|    AVClass *avc = *(AVClass **)ptr;
   83|  7.00k|    if (!avc) {
  ------------------
  |  Branch (83:9): [True: 0, False: 7.00k]
  ------------------
   84|      0|        mp_warn(log_root,
  ------------------
  |  |   73|      0|#define mp_warn(log, ...)       mp_msg(log, MSGL_WARN, __VA_ARGS__)
  ------------------
   85|      0|               "av_log callback called with bad parameters (NULL AVClass).\n"
   86|      0|               "This is a bug in one of FFmpeg libraries used.\n");
   87|      0|        return log_root;
   88|      0|    }
   89|       |
   90|  7.00k|    if (!strcmp(avc->class_name, "AVCodecContext")) {
  ------------------
  |  Branch (90:9): [True: 0, False: 7.00k]
  ------------------
   91|      0|        AVCodecContext *s = ptr;
   92|      0|        if (s->codec) {
  ------------------
  |  Branch (92:13): [True: 0, False: 0]
  ------------------
   93|      0|            if (s->codec->type == AVMEDIA_TYPE_AUDIO) {
  ------------------
  |  Branch (93:17): [True: 0, False: 0]
  ------------------
   94|      0|                if (av_codec_is_decoder(s->codec))
  ------------------
  |  Branch (94:21): [True: 0, False: 0]
  ------------------
   95|      0|                    return log_decaudio;
   96|      0|            } else if (s->codec->type == AVMEDIA_TYPE_VIDEO) {
  ------------------
  |  Branch (96:24): [True: 0, False: 0]
  ------------------
   97|      0|                if (av_codec_is_decoder(s->codec))
  ------------------
  |  Branch (97:21): [True: 0, False: 0]
  ------------------
   98|      0|                    return log_decvideo;
   99|      0|            }
  100|      0|        }
  101|      0|    }
  102|       |
  103|  7.00k|    if (!strcmp(avc->class_name, "AVFormatContext")) {
  ------------------
  |  Branch (103:9): [True: 1.06k, False: 5.94k]
  ------------------
  104|  1.06k|        AVFormatContext *s = ptr;
  105|  1.06k|        if (s->iformat)
  ------------------
  |  Branch (105:13): [True: 1.06k, False: 0]
  ------------------
  106|  1.06k|            return log_demuxer;
  107|  1.06k|    }
  108|       |
  109|  5.94k|    return log_root;
  110|  7.00k|}
av_log.c:avclass_item_name:
  113|  4.13k|{
  114|  4.13k|    return (avc->item_name ? avc->item_name : av_default_item_name)(obj);
  ------------------
  |  Branch (114:13): [True: 4.13k, False: 0]
  ------------------
  115|  4.13k|}

mp_add_decoder:
   26|  2.39M|{
   27|  2.39M|    struct mp_decoder_entry entry = {
   28|  2.39M|        .codec = talloc_strdup(list, codec),
  ------------------
  |  |   50|  2.39M|#define talloc_strdup                   ta_xstrdup
  ------------------
   29|  2.39M|        .decoder = talloc_strdup(list, decoder),
  ------------------
  |  |   50|  2.39M|#define talloc_strdup                   ta_xstrdup
  ------------------
   30|  2.39M|        .desc = talloc_strdup(list, desc),
  ------------------
  |  |   50|  2.39M|#define talloc_strdup                   ta_xstrdup
  ------------------
   31|  2.39M|    };
   32|  2.39M|    MP_TARRAY_APPEND(list, list->entries, list->num_entries, entry);
  ------------------
  |  |  105|  2.39M|    do {                                            \
  |  |  106|  2.39M|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  2.39M|    do {                                            \
  |  |  |  |   97|  2.39M|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  2.39M|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  2.39M|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  2.39M|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 59.2k, False: 2.33M]
  |  |  |  |  ------------------
  |  |  |  |   99|  2.39M|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  59.2k|    do {                                                        \
  |  |  |  |  |  |   89|  59.2k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  59.2k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  59.2k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  59.2k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  59.2k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  59.2k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  59.2k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  2.39M|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  2.39M|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  2.39M|        (idxvar)++;                                 \
  |  |  109|  2.39M|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
   33|  2.39M|}
mp_append_decoders:
   89|  5.14k|{
   90|  1.19M|    for (int n = 0; n < a->num_entries; n++)
  ------------------
  |  Branch (90:21): [True: 1.19M, False: 5.14k]
  ------------------
   91|  1.19M|        add_new(list, &a->entries[n], NULL);
   92|  5.14k|}
mp_print_decoders:
   96|     13|{
   97|     13|    mp_msg(log, msgl, "%s\n", header);
   98|  2.77k|    for (int n = 0; n < list->num_entries; n++) {
  ------------------
  |  Branch (98:21): [True: 2.76k, False: 13]
  ------------------
   99|  2.76k|        struct mp_decoder_entry *entry = &list->entries[n];
  100|  2.76k|        mp_msg(log, msgl, "    %s", entry->decoder);
  101|  2.76k|        if (strcmp(entry->decoder, entry->codec) != 0)
  ------------------
  |  Branch (101:13): [True: 301, False: 2.46k]
  ------------------
  102|    301|            mp_msg(log, msgl, " (%s)", entry->codec);
  103|  2.76k|        mp_msg(log, msgl, " - %s\n", entry->desc);
  104|  2.76k|    }
  105|     13|    if (list->num_entries == 0)
  ------------------
  |  Branch (105:9): [True: 0, False: 13]
  ------------------
  106|      0|        mp_msg(log, msgl, "    (no decoders)\n");
  107|     13|}
codecs.c:add_new:
   39|  1.19M|{
   40|  1.19M|    if (!entry || (codec && strcmp(entry->codec, codec) != 0))
  ------------------
  |  Branch (40:9): [True: 0, False: 1.19M]
  |  Branch (40:20): [True: 0, False: 1.19M]
  |  Branch (40:29): [True: 0, False: 0]
  ------------------
   41|      0|        return;
   42|  1.19M|    mp_add_decoder(to, entry->codec, entry->decoder, entry->desc);
   43|  1.19M|}

mp_format_time_fmt:
   46|     39|{
   47|     39|    if (time == MP_NOPTS_VALUE)
  ------------------
  |  |   38|     39|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (47:9): [True: 3, False: 36]
  ------------------
   48|      3|        return talloc_strdup(NULL, "unknown");
  ------------------
  |  |   50|      3|#define talloc_strdup                   ta_xstrdup
  ------------------
   49|     36|    char *sign = time < 0 ? "-" : "";
  ------------------
  |  Branch (49:18): [True: 18, False: 18]
  ------------------
   50|     36|    time = time < 0 ? -time : time;
  ------------------
  |  Branch (50:12): [True: 18, False: 18]
  ------------------
   51|     36|    long long int itime = time;
   52|     36|    long long int h, m, tm, s;
   53|     36|    int ms = lrint((time - itime) * 1000);
   54|     36|    if (ms >= 1000) {
  ------------------
  |  Branch (54:9): [True: 0, False: 36]
  ------------------
   55|      0|        ms -= 1000;
   56|      0|        itime += 1;
   57|      0|    }
   58|     36|    s = itime;
   59|     36|    tm = s / 60;
   60|     36|    h = s / 3600;
   61|     36|    s -= h * 3600;
   62|     36|    m = s / 60;
   63|     36|    s -= m * 60;
   64|     36|    char *res = talloc_strdup(NULL, "");
  ------------------
  |  |   50|     36|#define talloc_strdup                   ta_xstrdup
  ------------------
   65|    216|    while (*fmt) {
  ------------------
  |  Branch (65:12): [True: 180, False: 36]
  ------------------
   66|    180|        if (fmt[0] == '%') {
  ------------------
  |  Branch (66:13): [True: 108, False: 72]
  ------------------
   67|    108|            fmt++;
   68|    108|            switch (fmt[0]) {
   69|      0|            case 'h': appendf(&res, "%s%lld", sign, h); break;
  ------------------
  |  |   33|      0|    do {(*(ptr)) = talloc_asprintf_append_buffer(*(ptr), __VA_ARGS__);} while(0)
  |  |  ------------------
  |  |  |  |   64|      0|#define talloc_asprintf_append_buffer   ta_talloc_asprintf_append_buffer
  |  |  ------------------
  |  |  |  Branch (33:79): [Folded - Ignored]
  |  |  ------------------
  ------------------
  |  Branch (69:13): [True: 0, False: 108]
  ------------------
   70|     36|            case 'H': appendf(&res, "%s%02lld", sign, h); break;
  ------------------
  |  |   33|     36|    do {(*(ptr)) = talloc_asprintf_append_buffer(*(ptr), __VA_ARGS__);} while(0)
  |  |  ------------------
  |  |  |  |   64|     36|#define talloc_asprintf_append_buffer   ta_talloc_asprintf_append_buffer
  |  |  ------------------
  |  |  |  Branch (33:79): [Folded - Ignored]
  |  |  ------------------
  ------------------
  |  Branch (70:13): [True: 36, False: 72]
  ------------------
   71|      0|            case 'm': appendf(&res, "%s%lld", sign, tm); break;
  ------------------
  |  |   33|      0|    do {(*(ptr)) = talloc_asprintf_append_buffer(*(ptr), __VA_ARGS__);} while(0)
  |  |  ------------------
  |  |  |  |   64|      0|#define talloc_asprintf_append_buffer   ta_talloc_asprintf_append_buffer
  |  |  ------------------
  |  |  |  Branch (33:79): [Folded - Ignored]
  |  |  ------------------
  ------------------
  |  Branch (71:13): [True: 0, False: 108]
  ------------------
   72|     36|            case 'M': appendf(&res, "%02lld", m); break;
  ------------------
  |  |   33|     36|    do {(*(ptr)) = talloc_asprintf_append_buffer(*(ptr), __VA_ARGS__);} while(0)
  |  |  ------------------
  |  |  |  |   64|     36|#define talloc_asprintf_append_buffer   ta_talloc_asprintf_append_buffer
  |  |  ------------------
  |  |  |  Branch (33:79): [Folded - Ignored]
  |  |  ------------------
  ------------------
  |  Branch (72:13): [True: 36, False: 72]
  ------------------
   73|      0|            case 's': appendf(&res, "%s%lld", sign, itime); break;
  ------------------
  |  |   33|      0|    do {(*(ptr)) = talloc_asprintf_append_buffer(*(ptr), __VA_ARGS__);} while(0)
  |  |  ------------------
  |  |  |  |   64|      0|#define talloc_asprintf_append_buffer   ta_talloc_asprintf_append_buffer
  |  |  ------------------
  |  |  |  Branch (33:79): [Folded - Ignored]
  |  |  ------------------
  ------------------
  |  Branch (73:13): [True: 0, False: 108]
  ------------------
   74|     36|            case 'S': appendf(&res, "%02lld", s); break;
  ------------------
  |  |   33|     36|    do {(*(ptr)) = talloc_asprintf_append_buffer(*(ptr), __VA_ARGS__);} while(0)
  |  |  ------------------
  |  |  |  |   64|     36|#define talloc_asprintf_append_buffer   ta_talloc_asprintf_append_buffer
  |  |  ------------------
  |  |  |  Branch (33:79): [Folded - Ignored]
  |  |  ------------------
  ------------------
  |  Branch (74:13): [True: 36, False: 72]
  ------------------
   75|      0|            case 'T': appendf(&res, "%03d", ms); break;
  ------------------
  |  |   33|      0|    do {(*(ptr)) = talloc_asprintf_append_buffer(*(ptr), __VA_ARGS__);} while(0)
  |  |  ------------------
  |  |  |  |   64|      0|#define talloc_asprintf_append_buffer   ta_talloc_asprintf_append_buffer
  |  |  ------------------
  |  |  |  Branch (33:79): [Folded - Ignored]
  |  |  ------------------
  ------------------
  |  Branch (75:13): [True: 0, False: 108]
  ------------------
   76|      0|            case 'f': appendf(&res, "%f", time); break;
  ------------------
  |  |   33|      0|    do {(*(ptr)) = talloc_asprintf_append_buffer(*(ptr), __VA_ARGS__);} while(0)
  |  |  ------------------
  |  |  |  |   64|      0|#define talloc_asprintf_append_buffer   ta_talloc_asprintf_append_buffer
  |  |  ------------------
  |  |  |  Branch (33:79): [Folded - Ignored]
  |  |  ------------------
  ------------------
  |  Branch (76:13): [True: 0, False: 108]
  ------------------
   77|      0|            case '%': appendf(&res, "%s", "%"); break;
  ------------------
  |  |   33|      0|    do {(*(ptr)) = talloc_asprintf_append_buffer(*(ptr), __VA_ARGS__);} while(0)
  |  |  ------------------
  |  |  |  |   64|      0|#define talloc_asprintf_append_buffer   ta_talloc_asprintf_append_buffer
  |  |  ------------------
  |  |  |  Branch (33:79): [Folded - Ignored]
  |  |  ------------------
  ------------------
  |  Branch (77:13): [True: 0, False: 108]
  ------------------
   78|      0|            default: goto error;
  ------------------
  |  Branch (78:13): [True: 0, False: 108]
  ------------------
   79|    108|            }
   80|    108|            fmt++;
   81|    108|        } else {
   82|     72|            appendf(&res, "%c", *fmt);
  ------------------
  |  |   33|     72|    do {(*(ptr)) = talloc_asprintf_append_buffer(*(ptr), __VA_ARGS__);} while(0)
  |  |  ------------------
  |  |  |  |   64|     72|#define talloc_asprintf_append_buffer   ta_talloc_asprintf_append_buffer
  |  |  ------------------
  |  |  |  Branch (33:79): [Folded - Ignored]
  |  |  ------------------
  ------------------
   83|     72|            fmt++;
   84|     72|        }
   85|    180|    }
   86|     36|    return res;
   87|      0|error:
   88|      0|    talloc_free(res);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
   89|      0|    return NULL;
   90|     36|}
mp_format_time:
   93|     39|{
   94|     39|    return mp_format_time_fmt(fractions ? "%H:%M:%S.%T" : "%H:%M:%S", time);
  ------------------
  |  Branch (94:31): [True: 0, False: 39]
  ------------------
   95|     39|}
mp_format_double:
   99|  5.36k|{
  100|  5.36k|    bstr str = {0};
  101|  5.36k|    const char *fmt = plus_sign ? "%+.*f" : "%.*f";
  ------------------
  |  Branch (101:23): [True: 0, False: 5.36k]
  ------------------
  102|  5.36k|    bstr_xappend_asprintf(talloc_ctx, &str, fmt, precision, val);
  103|  5.36k|    size_t pos = str.len;
  104|  5.36k|    if (trim) {
  ------------------
  |  Branch (104:9): [True: 5.28k, False: 79]
  ------------------
  105|  25.3k|        while (--pos && str.start[pos] == '0')
  ------------------
  |  Branch (105:16): [True: 25.3k, False: 0]
  |  Branch (105:25): [True: 20.0k, False: 5.28k]
  ------------------
  106|  20.0k|            str.len--;
  107|  5.28k|        if (str.start[pos] == '.')
  ------------------
  |  Branch (107:13): [True: 4.68k, False: 604]
  ------------------
  108|  4.68k|            str.len--;
  109|  5.28k|    }
  110|  5.36k|    if (percent_sign)
  ------------------
  |  Branch (110:9): [True: 39, False: 5.32k]
  ------------------
  111|     39|        bstr_xappend(talloc_ctx, &str, bstr0("%"));
  112|  5.36k|    str.start[str.len] = '\0';
  113|  5.36k|    return str.start;
  114|  5.36k|}
mp_snprintf_cat:
  214|  4.73k|{
  215|  4.73k|    size_t len = strnlen(str, size);
  216|  4.73k|    mp_assert(!size || len < size); // str with no 0-termination is not allowed
  ------------------
  |  |   41|  4.73k|#define mp_assert assert
  ------------------
  217|  4.73k|    int r;
  218|  4.73k|    va_list ap;
  219|  4.73k|    va_start(ap, format);
  220|  4.73k|    r = vsnprintf(str + len, size - len, format, ap);
  221|  4.73k|    va_end(ap);
  222|  4.73k|    return r;
  223|  4.73k|}
mp_append_utf8_bstr:
  229|  1.31M|{
  230|  1.31M|    char data[8];
  231|  1.31M|    uint8_t tmp;
  232|  1.31M|    char *output = data;
  233|  1.31M|    PUT_UTF8(codepoint, tmp, *output++ = tmp;);
  234|  1.31M|    bstr_xappend(talloc_ctx, buf, (bstr){data, output - data});
  235|  1.31M|}
mp_append_escaped_string_noalloc:
  300|   128k|{
  301|   128k|    bstr t = *src;
  302|   128k|    int cur = 0;
  303|   899k|    while (1) {
  ------------------
  |  Branch (303:12): [Folded - Ignored]
  ------------------
  304|   899k|        if (cur >= t.len || t.start[cur] == '"') {
  ------------------
  |  Branch (304:13): [True: 4.86k, False: 894k]
  |  Branch (304:29): [True: 123k, False: 771k]
  ------------------
  305|   127k|            *src = bstr_cut(t, cur);
  306|   127k|            t = bstr_splice(t, 0, cur);
  307|   127k|            if (dst->start == NULL) {
  ------------------
  |  Branch (307:17): [True: 126k, False: 1.71k]
  ------------------
  308|   126k|                *dst = t;
  309|   126k|            } else {
  310|  1.71k|                bstr_xappend(talloc_ctx, dst, t);
  311|  1.71k|            }
  312|   127k|            return true;
  313|   771k|        } else if (t.start[cur] == '\\') {
  ------------------
  |  Branch (313:20): [True: 3.30k, False: 768k]
  ------------------
  314|  3.30k|            bstr_xappend(talloc_ctx, dst, bstr_splice(t, 0, cur));
  315|  3.30k|            t = bstr_cut(t, cur + 1);
  316|  3.30k|            cur = 0;
  317|  3.30k|            if (!mp_parse_escape(talloc_ctx, dst, &t))
  ------------------
  |  Branch (317:17): [True: 137, False: 3.16k]
  ------------------
  318|    137|                goto error;
  319|   768k|        } else {
  320|   768k|            cur++;
  321|   768k|        }
  322|   899k|    }
  323|    137|error:
  324|    137|    return false;
  325|   128k|}
mp_append_escaped_string:
  338|  6.46k|{
  339|  6.46k|    if (mp_append_escaped_string_noalloc(talloc_ctx, dst, src)) {
  ------------------
  |  Branch (339:9): [True: 6.36k, False: 101]
  ------------------
  340|       |        // Guarantee copy (or allocation).
  341|  6.36k|        if (!dst->start || dst->start == src->start) {
  ------------------
  |  Branch (341:13): [True: 0, False: 6.36k]
  |  Branch (341:28): [True: 303, False: 6.06k]
  ------------------
  342|    303|            bstr res = *dst;
  343|    303|            *dst = (bstr){0};
  344|    303|            bstr_xappend(talloc_ctx, dst, res);
  345|    303|        }
  346|  6.36k|        return true;
  347|  6.36k|    }
  348|    101|    return false;
  349|  6.46k|}
mp_strerror_buf:
  353|    407|{
  354|       |    // This handles the nasty details of calling the right function for us.
  355|    407|    av_strerror(AVERROR(errnum), buf, buf_size);
  356|    407|    return buf;
  357|    407|}
mp_tprintf_buf:
  376|  6.33k|{
  377|  6.33k|    va_list ap;
  378|  6.33k|    va_start(ap, format);
  379|  6.33k|    vsnprintf(buf, buf_size, format, ap);
  380|  6.33k|    va_end(ap);
  381|  6.33k|    return buf;
  382|  6.33k|}
mp_log2:
  401|   142k|{
  402|   142k|#if (defined(__GNUC__) && __GNUC__ >= 4) || defined(__clang__)
  403|   142k|    return v ? 31 - __builtin_clz(v) : 0;
  ------------------
  |  Branch (403:12): [True: 135k, False: 6.66k]
  ------------------
  404|       |#else
  405|       |    for (int x = 31; x >= 0; x--) {
  406|       |        if (v & (((uint32_t)1) << x))
  407|       |            return x;
  408|       |    }
  409|       |    return 0;
  410|       |#endif
  411|   142k|}
mp_round_next_power_of_2:
  419|  80.6k|{
  420|  80.6k|    if (!v)
  ------------------
  |  Branch (420:9): [True: 0, False: 80.6k]
  ------------------
  421|      0|        return 1;
  422|  80.6k|    if (!(v & (v - 1)))
  ------------------
  |  Branch (422:9): [True: 50.7k, False: 29.9k]
  ------------------
  423|  50.7k|        return v;
  424|  29.9k|    int l = mp_log2(v) + 1;
  425|  29.9k|    return l == 32 ? 0 : (uint32_t)1 << l;
  ------------------
  |  Branch (425:12): [True: 0, False: 29.9k]
  ------------------
  426|  80.6k|}
common.c:mp_parse_escape:
  243|  3.30k|{
  244|  3.30k|    if (code->len < 1)
  ------------------
  |  Branch (244:9): [True: 8, False: 3.29k]
  ------------------
  245|      8|        return false;
  246|  3.29k|    char replace = 0;
  247|  3.29k|    switch (code->start[0]) {
  ------------------
  |  Branch (247:13): [True: 998, False: 2.29k]
  ------------------
  248|    194|    case '"':  replace = '"';  break;
  ------------------
  |  Branch (248:5): [True: 194, False: 3.10k]
  ------------------
  249|    261|    case '\\': replace = '\\'; break;
  ------------------
  |  Branch (249:5): [True: 261, False: 3.03k]
  ------------------
  250|    215|    case '/':  replace = '/'; break;
  ------------------
  |  Branch (250:5): [True: 215, False: 3.07k]
  ------------------
  251|    196|    case 'b':  replace = '\b'; break;
  ------------------
  |  Branch (251:5): [True: 196, False: 3.09k]
  ------------------
  252|    236|    case 'f':  replace = '\f'; break;
  ------------------
  |  Branch (252:5): [True: 236, False: 3.05k]
  ------------------
  253|    282|    case 'n':  replace = '\n'; break;
  ------------------
  |  Branch (253:5): [True: 282, False: 3.01k]
  ------------------
  254|    304|    case 'r':  replace = '\r'; break;
  ------------------
  |  Branch (254:5): [True: 304, False: 2.99k]
  ------------------
  255|    196|    case 't':  replace = '\t'; break;
  ------------------
  |  Branch (255:5): [True: 196, False: 3.09k]
  ------------------
  256|    200|    case 'e':  replace = '\x1b'; break;
  ------------------
  |  Branch (256:5): [True: 200, False: 3.09k]
  ------------------
  257|    212|    case '\'': replace = '\''; break;
  ------------------
  |  Branch (257:5): [True: 212, False: 3.08k]
  ------------------
  258|  3.29k|    }
  259|  3.29k|    if (replace) {
  ------------------
  |  Branch (259:9): [True: 2.29k, False: 998]
  ------------------
  260|  2.29k|        bstr_xappend(talloc_ctx, dst, (bstr){&replace, 1});
  261|  2.29k|        *code = bstr_cut(*code, 1);
  262|  2.29k|        return true;
  263|  2.29k|    }
  264|    998|    if (code->start[0] == 'x' && code->len >= 3) {
  ------------------
  |  Branch (264:9): [True: 367, False: 631]
  |  Branch (264:34): [True: 363, False: 4]
  ------------------
  265|    363|        bstr num = bstr_splice(*code, 1, 3);
  266|    363|        char c = bstrtoll(num, &num, 16);
  267|    363|        if (num.len)
  ------------------
  |  Branch (267:13): [True: 9, False: 354]
  ------------------
  268|      9|            return false;
  269|    354|        bstr_xappend(talloc_ctx, dst, (bstr){&c, 1});
  270|    354|        *code = bstr_cut(*code, 3);
  271|    354|        return true;
  272|    363|    }
  273|    635|    if (code->start[0] == 'u' && code->len >= 5) {
  ------------------
  |  Branch (273:9): [True: 577, False: 58]
  |  Branch (273:34): [True: 573, False: 4]
  ------------------
  274|    573|        bstr num = bstr_splice(*code, 1, 5);
  275|    573|        uint32_t c = bstrtoll(num, &num, 16);
  276|    573|        if (num.len || c > 0x10FFFF)
  ------------------
  |  Branch (276:13): [True: 11, False: 562]
  |  Branch (276:24): [True: 11, False: 551]
  ------------------
  277|     22|            return false;
  278|    551|        if (c >= 0xd800 && c <= 0xdbff) {
  ------------------
  |  Branch (278:13): [True: 193, False: 358]
  |  Branch (278:28): [True: 76, False: 117]
  ------------------
  279|     76|            if (code->len < 5 + 6 // udddd + \udddd
  ------------------
  |  Branch (279:17): [True: 3, False: 73]
  ------------------
  280|     76|                || code->start[5] != '\\' || code->start[6] != 'u')
  ------------------
  |  Branch (280:20): [True: 9, False: 64]
  |  Branch (280:46): [True: 2, False: 62]
  ------------------
  281|     14|                return false;
  282|     62|            *code = bstr_cut(*code, 5 + 1);
  283|     62|            bstr num2 = bstr_splice(*code, 1, 5);
  284|     62|            uint32_t c2 = bstrtoll(num2, &num2, 16);
  285|     62|            if (num2.len || c2 < 0xdc00 || c2 > 0xdfff)
  ------------------
  |  Branch (285:17): [True: 1, False: 61]
  |  Branch (285:29): [True: 12, False: 49]
  |  Branch (285:44): [True: 9, False: 40]
  ------------------
  286|     22|                return false;
  287|     40|            c = ((c - 0xd800) << 10) + 0x10000 + (c2 - 0xdc00);
  288|     40|        }
  289|    515|        mp_append_utf8_bstr(talloc_ctx, dst, c);
  290|    515|        *code = bstr_cut(*code, 5);
  291|    515|        return true;
  292|    551|    }
  293|     62|    return false;
  294|    635|}

encode_lavc_init:
  100|    309|{
  101|    309|    struct encode_lavc_context *ctx = talloc_ptrtype(NULL, ctx);
  ------------------
  |  |   34|    309|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|    309|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    309|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  102|    309|    *ctx = (struct encode_lavc_context){
  103|    309|        .global = global,
  104|    309|        .options = mp_get_config_group(ctx, global, &encode_config),
  105|    309|        .priv = talloc_zero(ctx, struct encode_priv),
  ------------------
  |  |   27|    309|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    309|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    309|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  106|    309|        .log = mp_log_new(ctx, global->log, "encode"),
  107|    309|    };
  108|    309|    mp_mutex_init(&ctx->lock);
  109|       |
  110|    309|    struct encode_priv *p = ctx->priv;
  111|    309|    p->log = ctx->log;
  112|       |
  113|    309|    const char *filename = ctx->options->file;
  114|       |
  115|       |    // STUPID STUPID STUPID STUPID avio
  116|       |    // does not support "-" as file name to mean stdin/stdout
  117|       |    // ffmpeg.c works around this too, the same way
  118|    309|    if (!strcmp(filename, "-"))
  ------------------
  |  Branch (118:9): [True: 28, False: 281]
  ------------------
  119|     28|        filename = "pipe:1";
  120|       |
  121|    309|    encode_lavc_discontinuity(ctx);
  122|       |
  123|    309|    p->muxer = avformat_alloc_context();
  124|    309|    MP_HANDLE_OOM(p->muxer);
  ------------------
  |  |  176|    309|#define MP_HANDLE_OOM(x) do {   \
  |  |  177|    309|        void *oom_p_ = (x);     \
  |  |  178|    309|        if (!oom_p_)            \
  |  |  ------------------
  |  |  |  Branch (178:13): [True: 0, False: 309]
  |  |  ------------------
  |  |  179|    309|            abort();            \
  |  |  180|    309|    } while (0)
  |  |  ------------------
  |  |  |  Branch (180:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  125|       |
  126|    309|    if (ctx->options->format && ctx->options->format[0]) {
  ------------------
  |  Branch (126:9): [True: 36, False: 273]
  |  Branch (126:33): [True: 35, False: 1]
  ------------------
  127|     35|        ctx->oformat = av_guess_format(ctx->options->format, filename, NULL);
  128|    274|    } else {
  129|    274|        ctx->oformat = av_guess_format(NULL, filename, NULL);
  130|    274|    }
  131|       |
  132|    309|    if (!ctx->oformat) {
  ------------------
  |  Branch (132:9): [True: 288, False: 21]
  ------------------
  133|    288|        MP_FATAL(ctx, "format not found\n");
  ------------------
  |  |   84|    288|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    288|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  134|    288|        goto fail;
  135|    288|    }
  136|       |
  137|     21|    p->muxer->oformat = ctx->oformat;
  138|       |
  139|     21|    char *path = mp_get_user_path(NULL, global, filename);
  140|     21|    p->muxer->url = av_strdup(path);
  141|     21|    talloc_free(path);
  ------------------
  |  |   47|     21|#define talloc_free                     ta_free
  ------------------
  142|     21|    MP_HANDLE_OOM(p->muxer->url);
  ------------------
  |  |  176|     21|#define MP_HANDLE_OOM(x) do {   \
  |  |  177|     21|        void *oom_p_ = (x);     \
  |  |  178|     21|        if (!oom_p_)            \
  |  |  ------------------
  |  |  |  Branch (178:13): [True: 0, False: 21]
  |  |  ------------------
  |  |  179|     21|            abort();            \
  |  |  180|     21|    } while (0)
  |  |  ------------------
  |  |  |  Branch (180:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  143|       |
  144|     21|    return ctx;
  145|       |
  146|    288|fail:
  147|    288|    p->failed = true;
  148|    288|    encode_lavc_free(ctx);
  149|    288|    return NULL;
  150|     21|}
encode_lavc_free:
  188|  17.3k|{
  189|  17.3k|    bool res = true;
  190|  17.3k|    if (!ctx)
  ------------------
  |  Branch (190:9): [True: 17.0k, False: 309]
  ------------------
  191|  17.0k|        return res;
  192|       |
  193|    309|    struct encode_priv *p = ctx->priv;
  194|       |
  195|    309|    if (!p->failed && !p->header_written) {
  ------------------
  |  Branch (195:9): [True: 21, False: 288]
  |  Branch (195:23): [True: 21, False: 0]
  ------------------
  196|     21|        MP_FATAL(p, "no data written to target file\n");
  ------------------
  |  |   84|     21|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     21|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  197|     21|        p->failed = true;
  198|     21|    }
  199|       |
  200|    309|    if (!p->failed && p->header_written) {
  ------------------
  |  Branch (200:9): [True: 0, False: 309]
  |  Branch (200:23): [True: 0, False: 0]
  ------------------
  201|      0|        if (av_write_trailer(p->muxer) < 0)
  ------------------
  |  Branch (201:13): [True: 0, False: 0]
  ------------------
  202|      0|            MP_ERR(p, "error writing trailer\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  203|       |
  204|      0|        MP_INFO(p, "video: encoded %lld bytes\n", p->vbytes);
  ------------------
  |  |   87|      0|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  205|      0|        MP_INFO(p, "audio: encoded %lld bytes\n", p->abytes);
  ------------------
  |  |   87|      0|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  206|       |
  207|      0|        MP_INFO(p, "muxing overhead %lld bytes\n",
  ------------------
  |  |   87|      0|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  208|      0|                (long long)(avio_size(p->muxer->pb) - p->vbytes - p->abytes));
  209|      0|    }
  210|       |
  211|    309|    if (avio_closep(&p->muxer->pb) < 0 && !p->failed) {
  ------------------
  |  Branch (211:9): [True: 0, False: 309]
  |  Branch (211:43): [True: 0, False: 0]
  ------------------
  212|      0|        MP_ERR(p, "Closing file failed\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  213|      0|        p->failed = true;
  214|      0|    }
  215|       |
  216|    309|    avformat_free_context(p->muxer);
  217|       |
  218|    309|    res = !p->failed;
  219|       |
  220|    309|    mp_mutex_destroy(&ctx->lock);
  ------------------
  |  |  130|    309|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
  221|    309|    talloc_free(ctx);
  ------------------
  |  |   47|    309|#define talloc_free                     ta_free
  ------------------
  222|       |
  223|    309|    return res;
  224|  17.3k|}
encode_lavc_discontinuity:
  446|  4.24k|{
  447|  4.24k|    if (!ctx)
  ------------------
  |  Branch (447:9): [True: 3.42k, False: 813]
  ------------------
  448|  3.42k|        return;
  449|       |
  450|    813|    mp_mutex_lock(&ctx->lock);
  ------------------
  |  |  131|    813|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  451|    813|    ctx->discontinuity_pts_offset = MP_NOPTS_VALUE;
  ------------------
  |  |   38|    813|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  452|    813|    mp_mutex_unlock(&ctx->lock);
  ------------------
  |  |  133|    813|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  453|    813|}
encode_lavc_showhelp:
  530|  12.1k|{
  531|  12.1k|    bool help_output = false;
  532|  12.1k|#define CHECKS(str) ((str) && \
  533|  12.1k|                     strcmp((str), "help") == 0 ? (help_output |= 1) : 0)
  534|  12.1k|#define CHECKV(strv) ((strv) && (strv)[0] && \
  535|  12.1k|                      strcmp((strv)[0], "help") == 0 ? (help_output |= 1) : 0)
  536|  12.1k|    if (CHECKS(opts->format)) {
  ------------------
  |  |  532|  12.1k|#define CHECKS(str) ((str) && \
  |  |  ------------------
  |  |  |  Branch (532:21): [True: 4, False: 12.1k]
  |  |  |  Branch (532:22): [True: 67, False: 12.0k]
  |  |  ------------------
  |  |  533|  12.1k|                     strcmp((str), "help") == 0 ? (help_output |= 1) : 0)
  |  |  ------------------
  |  |  |  Branch (533:22): [True: 4, False: 63]
  |  |  ------------------
  ------------------
  537|      4|        const AVOutputFormat *c = NULL;
  538|      4|        void *iter = NULL;
  539|      4|        mp_info(log, "Available output formats:\n");
  ------------------
  |  |   74|      4|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  540|     16|        while ((c = av_muxer_iterate(&iter))) {
  ------------------
  |  Branch (540:16): [True: 12, False: 4]
  ------------------
  541|     12|            mp_info(log, "  --of=%-13s %s\n", c->name,
  ------------------
  |  |   74|     24|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (74:56): [True: 12, False: 0]
  |  |  ------------------
  ------------------
  542|     12|                   c->long_name ? c->long_name : "");
  543|     12|        }
  544|      4|    }
  545|  12.1k|    if (CHECKV(opts->fopts)) {
  ------------------
  |  |  534|  12.1k|#define CHECKV(strv) ((strv) && (strv)[0] && \
  |  |  ------------------
  |  |  |  Branch (534:22): [True: 3, False: 12.1k]
  |  |  |  Branch (534:23): [True: 140, False: 12.0k]
  |  |  |  Branch (534:33): [True: 136, False: 4]
  |  |  ------------------
  |  |  535|  12.1k|                      strcmp((strv)[0], "help") == 0 ? (help_output |= 1) : 0)
  |  |  ------------------
  |  |  |  Branch (535:23): [True: 3, False: 133]
  |  |  ------------------
  ------------------
  546|      3|        AVFormatContext *c = avformat_alloc_context();
  547|      3|        const AVOutputFormat *format = NULL;
  548|      3|        mp_info(log, "Available output format ctx->options:\n");
  ------------------
  |  |   74|      3|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  549|      3|        encode_lavc_printoptions(log, c, "  --ofopts=", "           ", NULL,
  550|      3|                                 AV_OPT_FLAG_ENCODING_PARAM,
  551|      3|                                 AV_OPT_FLAG_ENCODING_PARAM);
  552|      3|        avformat_free_context(c);
  553|      3|        void *iter = NULL;
  554|     12|        while ((format = av_muxer_iterate(&iter))) {
  ------------------
  |  Branch (554:16): [True: 9, False: 3]
  ------------------
  555|      9|            if (format->priv_class) {
  ------------------
  |  Branch (555:17): [True: 9, False: 0]
  ------------------
  556|      9|                mp_info(log, "Additionally, for --of=%s:\n",
  ------------------
  |  |   74|      9|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  557|      9|                       format->name);
  558|      9|                encode_lavc_printoptions(log, &format->priv_class, "  --ofopts=",
  559|      9|                                         "           ", NULL,
  560|      9|                                         AV_OPT_FLAG_ENCODING_PARAM,
  561|      9|                                         AV_OPT_FLAG_ENCODING_PARAM);
  562|      9|            }
  563|      9|        }
  564|      3|    }
  565|  12.1k|    if (CHECKV(opts->vopts)) {
  ------------------
  |  |  534|  12.1k|#define CHECKV(strv) ((strv) && (strv)[0] && \
  |  |  ------------------
  |  |  |  Branch (534:22): [True: 7, False: 12.1k]
  |  |  |  Branch (534:23): [True: 38, False: 12.1k]
  |  |  |  Branch (534:33): [True: 38, False: 0]
  |  |  ------------------
  |  |  535|  12.1k|                      strcmp((strv)[0], "help") == 0 ? (help_output |= 1) : 0)
  |  |  ------------------
  |  |  |  Branch (535:23): [True: 7, False: 31]
  |  |  ------------------
  ------------------
  566|      7|        AVCodecContext *c = avcodec_alloc_context3(NULL);
  567|      7|        const AVCodec *codec = NULL;
  568|      7|        mp_info(log, "Available output video codec ctx->options:\n");
  ------------------
  |  |   74|      7|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  569|      7|        encode_lavc_printoptions(log,
  570|      7|            c, "  --ovcopts=", "            ", NULL,
  571|      7|            AV_OPT_FLAG_ENCODING_PARAM |
  572|      7|            AV_OPT_FLAG_VIDEO_PARAM,
  573|      7|            AV_OPT_FLAG_ENCODING_PARAM |
  574|      7|            AV_OPT_FLAG_VIDEO_PARAM);
  575|      7|        av_free(c);
  576|      7|        void *iter = NULL;
  577|  3.40k|        while ((codec = av_codec_iterate(&iter))) {
  ------------------
  |  Branch (577:16): [True: 3.40k, False: 7]
  ------------------
  578|  3.40k|            if (!av_codec_is_encoder(codec))
  ------------------
  |  Branch (578:17): [True: 3.40k, False: 0]
  ------------------
  579|  3.40k|                continue;
  580|      0|            if (codec->type != AVMEDIA_TYPE_VIDEO)
  ------------------
  |  Branch (580:17): [True: 0, False: 0]
  ------------------
  581|      0|                continue;
  582|      0|            if (opts->vcodec && opts->vcodec[0] &&
  ------------------
  |  Branch (582:17): [True: 0, False: 0]
  |  Branch (582:33): [True: 0, False: 0]
  ------------------
  583|      0|                strcmp(opts->vcodec, codec->name) != 0)
  ------------------
  |  Branch (583:17): [True: 0, False: 0]
  ------------------
  584|      0|                continue;
  585|      0|            if (codec->priv_class) {
  ------------------
  |  Branch (585:17): [True: 0, False: 0]
  ------------------
  586|      0|                mp_info(log, "Additionally, for --ovc=%s:\n",
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  587|      0|                       codec->name);
  588|      0|                encode_lavc_printoptions(log,
  589|      0|                    &codec->priv_class, "  --ovcopts=",
  590|      0|                    "            ", NULL,
  591|      0|                    AV_OPT_FLAG_ENCODING_PARAM |
  592|      0|                    AV_OPT_FLAG_VIDEO_PARAM,
  593|      0|                    AV_OPT_FLAG_ENCODING_PARAM |
  594|      0|                    AV_OPT_FLAG_VIDEO_PARAM);
  595|      0|            }
  596|      0|        }
  597|      7|    }
  598|  12.1k|    if (CHECKV(opts->aopts)) {
  ------------------
  |  |  534|  12.1k|#define CHECKV(strv) ((strv) && (strv)[0] && \
  |  |  ------------------
  |  |  |  Branch (534:22): [True: 7, False: 12.1k]
  |  |  |  Branch (534:23): [True: 58, False: 12.0k]
  |  |  |  Branch (534:33): [True: 57, False: 1]
  |  |  ------------------
  |  |  535|  12.1k|                      strcmp((strv)[0], "help") == 0 ? (help_output |= 1) : 0)
  |  |  ------------------
  |  |  |  Branch (535:23): [True: 7, False: 50]
  |  |  ------------------
  ------------------
  599|      7|        AVCodecContext *c = avcodec_alloc_context3(NULL);
  600|      7|        const AVCodec *codec = NULL;
  601|      7|        mp_info(log, "Available output audio codec ctx->options:\n");
  ------------------
  |  |   74|      7|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  602|      7|        encode_lavc_printoptions(log,
  603|      7|            c, "  --oacopts=", "            ", NULL,
  604|      7|            AV_OPT_FLAG_ENCODING_PARAM |
  605|      7|            AV_OPT_FLAG_AUDIO_PARAM,
  606|      7|            AV_OPT_FLAG_ENCODING_PARAM |
  607|      7|            AV_OPT_FLAG_AUDIO_PARAM);
  608|      7|        av_free(c);
  609|      7|        void *iter = NULL;
  610|  3.40k|        while ((codec = av_codec_iterate(&iter))) {
  ------------------
  |  Branch (610:16): [True: 3.40k, False: 7]
  ------------------
  611|  3.40k|            if (!av_codec_is_encoder(codec))
  ------------------
  |  Branch (611:17): [True: 3.40k, False: 0]
  ------------------
  612|  3.40k|                continue;
  613|      0|            if (codec->type != AVMEDIA_TYPE_AUDIO)
  ------------------
  |  Branch (613:17): [True: 0, False: 0]
  ------------------
  614|      0|                continue;
  615|      0|            if (opts->acodec && opts->acodec[0] &&
  ------------------
  |  Branch (615:17): [True: 0, False: 0]
  |  Branch (615:33): [True: 0, False: 0]
  ------------------
  616|      0|                strcmp(opts->acodec, codec->name) != 0)
  ------------------
  |  Branch (616:17): [True: 0, False: 0]
  ------------------
  617|      0|                continue;
  618|      0|            if (codec->priv_class) {
  ------------------
  |  Branch (618:17): [True: 0, False: 0]
  ------------------
  619|      0|                mp_info(log, "Additionally, for --oac=%s:\n",
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  620|      0|                       codec->name);
  621|      0|                encode_lavc_printoptions(log,
  622|      0|                    &codec->priv_class, "  --oacopts=",
  623|      0|                    "           ", NULL,
  624|      0|                    AV_OPT_FLAG_ENCODING_PARAM |
  625|      0|                    AV_OPT_FLAG_AUDIO_PARAM,
  626|      0|                    AV_OPT_FLAG_ENCODING_PARAM |
  627|      0|                    AV_OPT_FLAG_AUDIO_PARAM);
  628|      0|            }
  629|      0|        }
  630|      7|    }
  631|  12.1k|    if (CHECKS(opts->vcodec)) {
  ------------------
  |  |  532|  12.1k|#define CHECKS(str) ((str) && \
  |  |  ------------------
  |  |  |  Branch (532:21): [True: 1, False: 12.1k]
  |  |  |  Branch (532:22): [True: 39, False: 12.1k]
  |  |  ------------------
  |  |  533|  12.1k|                     strcmp((str), "help") == 0 ? (help_output |= 1) : 0)
  |  |  ------------------
  |  |  |  Branch (533:22): [True: 1, False: 38]
  |  |  ------------------
  ------------------
  632|      1|        const AVCodec *c = NULL;
  633|      1|        void *iter = NULL;
  634|      1|        mp_info(log, "Available output video codecs:\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  635|    487|        while ((c = av_codec_iterate(&iter))) {
  ------------------
  |  Branch (635:16): [True: 486, False: 1]
  ------------------
  636|    486|            if (!av_codec_is_encoder(c))
  ------------------
  |  Branch (636:17): [True: 486, False: 0]
  ------------------
  637|    486|                continue;
  638|      0|            if (c->type != AVMEDIA_TYPE_VIDEO)
  ------------------
  |  Branch (638:17): [True: 0, False: 0]
  ------------------
  639|      0|                continue;
  640|      0|            mp_info(log, "  --ovc=%-12s %s\n", c->name,
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (74:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  641|      0|                   c->long_name ? c->long_name : "");
  642|      0|        }
  643|      1|    }
  644|  12.1k|    if (CHECKS(opts->acodec)) {
  ------------------
  |  |  532|  12.1k|#define CHECKS(str) ((str) && \
  |  |  ------------------
  |  |  |  Branch (532:21): [True: 1, False: 12.1k]
  |  |  |  Branch (532:22): [True: 11, False: 12.1k]
  |  |  ------------------
  |  |  533|  12.1k|                     strcmp((str), "help") == 0 ? (help_output |= 1) : 0)
  |  |  ------------------
  |  |  |  Branch (533:22): [True: 1, False: 10]
  |  |  ------------------
  ------------------
  645|      1|        const AVCodec *c = NULL;
  646|      1|        void *iter = NULL;
  647|      1|        mp_info(log, "Available output audio codecs:\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  648|    487|        while ((c = av_codec_iterate(&iter))) {
  ------------------
  |  Branch (648:16): [True: 486, False: 1]
  ------------------
  649|    486|            if (!av_codec_is_encoder(c))
  ------------------
  |  Branch (649:17): [True: 486, False: 0]
  ------------------
  650|    486|                continue;
  651|      0|            if (c->type != AVMEDIA_TYPE_AUDIO)
  ------------------
  |  Branch (651:17): [True: 0, False: 0]
  ------------------
  652|      0|                continue;
  653|      0|            mp_info(log, "  --oac=%-12s %s\n", c->name,
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (74:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  654|      0|                   c->long_name ? c->long_name : "");
  655|      0|        }
  656|      1|    }
  657|  12.1k|    return help_output;
  658|  12.1k|}
encode_lavc_didfail:
  702|  3.93k|{
  703|  3.93k|    if (!ctx)
  ------------------
  |  Branch (703:9): [True: 3.42k, False: 504]
  ------------------
  704|  3.42k|        return false;
  705|    504|    mp_mutex_lock(&ctx->lock);
  ------------------
  |  |  131|    504|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  706|    504|    bool fail = ctx->priv->failed;
  707|    504|    mp_mutex_unlock(&ctx->lock);
  ------------------
  |  |  133|    504|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  708|    504|    return fail;
  709|  3.93k|}
encoder_update_log:
  947|  6.00k|{
  948|  6.00k|    struct encode_opts *options = mp_get_config_group(NULL, global, &encode_config);
  949|  6.00k|    if (options->file && (!strcmp(options->file, "-") ||
  ------------------
  |  Branch (949:9): [True: 277, False: 5.73k]
  |  Branch (949:27): [True: 25, False: 252]
  ------------------
  950|    277|                          !strcmp(options->file, "/dev/stdout") ||
  ------------------
  |  Branch (950:27): [True: 3, False: 249]
  ------------------
  951|    277|                          !strcmp(options->file, "pipe:") ||
  ------------------
  |  Branch (951:27): [True: 3, False: 246]
  ------------------
  952|    277|                          !strcmp(options->file, "pipe:1")))
  ------------------
  |  Branch (952:27): [True: 3, False: 243]
  ------------------
  953|     34|    {
  954|     34|        mp_msg_force_stderr(global, true);
  955|     34|    }
  956|  6.00k|    talloc_free(options);
  ------------------
  |  |   47|  6.00k|#define talloc_free                     ta_free
  ------------------
  957|  6.00k|}
encode_lavc.c:encode_lavc_printoptions:
  459|    296|{
  460|    296|    const AVOption *opt = NULL;
  461|    296|    char optbuf[32];
  462|  94.3k|    while ((opt = av_opt_next(obj, opt))) {
  ------------------
  |  Branch (462:12): [True: 94.0k, False: 296]
  ------------------
  463|       |        // if flags are 0, it simply hasn't been filled in yet and may be
  464|       |        // potentially useful
  465|  94.0k|        if (opt->flags)
  ------------------
  |  Branch (465:13): [True: 88.7k, False: 5.32k]
  ------------------
  466|  88.7k|            if ((opt->flags & filter_and) != filter_eq)
  ------------------
  |  Branch (466:17): [True: 43.6k, False: 45.1k]
  ------------------
  467|  43.6k|                continue;
  468|       |        /* Don't print CONST's on level one.
  469|       |         * Don't print anything but CONST's on level two.
  470|       |         * Only print items from the requested unit.
  471|       |         */
  472|  50.4k|        if (!unit && opt->type == AV_OPT_TYPE_CONST) {
  ------------------
  |  Branch (472:13): [True: 2.33k, False: 48.1k]
  |  Branch (472:22): [True: 1.41k, False: 925]
  ------------------
  473|  1.41k|            continue;
  474|  49.0k|        } else if (unit && opt->type != AV_OPT_TYPE_CONST) {
  ------------------
  |  Branch (474:20): [True: 48.1k, False: 925]
  |  Branch (474:28): [True: 17.6k, False: 30.4k]
  ------------------
  475|  17.6k|            continue;
  476|  31.3k|        } else if (unit && opt->type == AV_OPT_TYPE_CONST
  ------------------
  |  Branch (476:20): [True: 30.4k, False: 925]
  |  Branch (476:28): [True: 30.4k, False: 0]
  ------------------
  477|  31.3k|                 && strcmp(unit, opt->unit))
  ------------------
  |  Branch (477:21): [True: 28.5k, False: 1.82k]
  ------------------
  478|  28.5k|        {
  479|  28.5k|            continue;
  480|  28.5k|        } else if (unit && opt->type == AV_OPT_TYPE_CONST) {
  ------------------
  |  Branch (480:20): [True: 1.82k, False: 925]
  |  Branch (480:28): [True: 1.82k, False: 0]
  ------------------
  481|  1.82k|            mp_info(log, "%s", subindent);
  ------------------
  |  |   74|  1.82k|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  482|  1.82k|        } else {
  483|    925|            mp_info(log, "%s", indent);
  ------------------
  |  |   74|    925|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  484|    925|        }
  485|       |
  486|  2.74k|        switch (opt->type) {
  487|     93|        case AV_OPT_TYPE_FLAGS:
  ------------------
  |  Branch (487:9): [True: 93, False: 2.65k]
  ------------------
  488|     93|            snprintf(optbuf, sizeof(optbuf), "%s=<flags>", opt->name);
  489|     93|            break;
  490|    554|        case AV_OPT_TYPE_INT:
  ------------------
  |  Branch (490:9): [True: 554, False: 2.19k]
  ------------------
  491|    554|            snprintf(optbuf, sizeof(optbuf), "%s=<int>", opt->name);
  492|    554|            break;
  493|     90|        case AV_OPT_TYPE_INT64:
  ------------------
  |  Branch (493:9): [True: 90, False: 2.65k]
  ------------------
  494|     90|            snprintf(optbuf, sizeof(optbuf), "%s=<int64>", opt->name);
  495|     90|            break;
  496|      0|        case AV_OPT_TYPE_DOUBLE:
  ------------------
  |  Branch (496:9): [True: 0, False: 2.74k]
  ------------------
  497|      0|            snprintf(optbuf, sizeof(optbuf), "%s=<double>", opt->name);
  498|      0|            break;
  499|     91|        case AV_OPT_TYPE_FLOAT:
  ------------------
  |  Branch (499:9): [True: 91, False: 2.65k]
  ------------------
  500|     91|            snprintf(optbuf, sizeof(optbuf), "%s=<float>", opt->name);
  501|     91|            break;
  502|     17|        case AV_OPT_TYPE_STRING:
  ------------------
  |  Branch (502:9): [True: 17, False: 2.72k]
  ------------------
  503|     17|            snprintf(optbuf, sizeof(optbuf), "%s=<string>", opt->name);
  504|     17|            break;
  505|     42|        case AV_OPT_TYPE_RATIONAL:
  ------------------
  |  Branch (505:9): [True: 42, False: 2.70k]
  ------------------
  506|     42|            snprintf(optbuf, sizeof(optbuf), "%s=<rational>", opt->name);
  507|     42|            break;
  508|      0|        case AV_OPT_TYPE_BINARY:
  ------------------
  |  Branch (508:9): [True: 0, False: 2.74k]
  ------------------
  509|      0|            snprintf(optbuf, sizeof(optbuf), "%s=<binary>", opt->name);
  510|      0|            break;
  511|  1.82k|        case AV_OPT_TYPE_CONST:
  ------------------
  |  Branch (511:9): [True: 1.82k, False: 925]
  ------------------
  512|  1.82k|            snprintf(optbuf, sizeof(optbuf), "  [+-]%s", opt->name);
  513|  1.82k|            break;
  514|     38|        default:
  ------------------
  |  Branch (514:9): [True: 38, False: 2.70k]
  ------------------
  515|     38|            snprintf(optbuf, sizeof(optbuf), "%s", opt->name);
  516|     38|            break;
  517|  2.74k|        }
  518|  2.74k|        optbuf[sizeof(optbuf) - 1] = 0;
  519|  2.74k|        mp_info(log, "%-32s ", optbuf);
  ------------------
  |  |   74|  2.74k|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  520|  2.74k|        if (opt->help)
  ------------------
  |  Branch (520:13): [True: 2.19k, False: 547]
  ------------------
  521|  2.19k|            mp_info(log, " %s", opt->help);
  ------------------
  |  |   74|  2.19k|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  522|  2.74k|        mp_info(log, "\n");
  ------------------
  |  |   74|  2.74k|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  523|  2.74k|        if (opt->unit && opt->type != AV_OPT_TYPE_CONST)
  ------------------
  |  Branch (523:13): [True: 2.09k, False: 655]
  |  Branch (523:26): [True: 270, False: 1.82k]
  ------------------
  524|    270|            encode_lavc_printoptions(log, obj, indent, subindent, opt->unit,
  525|    270|                                     filter_and, filter_eq);
  526|  2.74k|    }
  527|    296|}

mp_msg_level:
  182|  7.20M|{
  183|  7.20M|    struct mp_log_root *root = log->root;
  184|  7.20M|    if (!root)
  ------------------
  |  Branch (184:9): [True: 208k, False: 6.99M]
  ------------------
  185|   208k|        return -1;
  186|  6.99M|    if (atomic_load_explicit(&log->reload_counter, memory_order_relaxed) !=
  ------------------
  |  Branch (186:9): [True: 155k, False: 6.84M]
  ------------------
  187|  6.99M|        atomic_load_explicit(&root->reload_counter, memory_order_relaxed))
  188|   155k|    {
  189|   155k|        update_loglevel(log);
  190|   155k|    }
  191|  6.99M|    return log->level;
  192|  7.20M|}
mp_msg_flush_status_line:
  289|  21.0k|{
  290|  21.0k|    if (!log->root)
  ------------------
  |  Branch (290:9): [True: 0, False: 21.0k]
  ------------------
  291|      0|        return;
  292|       |
  293|  21.0k|    mp_mutex_lock(&log->root->lock);
  ------------------
  |  |  131|  21.0k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  294|  21.0k|    msg_flush_status_line(log->root, clear);
  295|  21.0k|    mp_mutex_unlock(&log->root->lock);
  ------------------
  |  |  133|  21.0k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  296|  21.0k|}
mp_msg_set_term_title:
  299|     15|{
  300|     15|    if (log->root && title) {
  ------------------
  |  Branch (300:9): [True: 15, False: 0]
  |  Branch (300:22): [True: 15, False: 0]
  ------------------
  301|       |        // Lock because printf to terminal is not necessarily atomic.
  302|     15|        mp_mutex_lock(&log->root->lock);
  ------------------
  |  |  131|     15|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  303|     15|        fprintf(term_msg_fp(log->root, MSGL_STATUS), "\033]0;%s\007", title);
  304|     15|        mp_mutex_unlock(&log->root->lock);
  ------------------
  |  |  133|     15|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  305|     15|    }
  306|     15|}
mp_msg_has_status_line:
  309|  3.49k|{
  310|  3.49k|    struct mp_log_root *root = global->log->root;
  311|  3.49k|    mp_mutex_lock(&root->lock);
  ------------------
  |  |  131|  3.49k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  312|  3.49k|    bool r = root->status_lines > 0;
  313|  3.49k|    mp_mutex_unlock(&root->lock);
  ------------------
  |  |  133|  3.49k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  314|  3.49k|    return r;
  315|  3.49k|}
mp_msg_va:
  563|  4.83M|{
  564|  4.83M|    if (!mp_msg_test(log, lev))
  ------------------
  |  Branch (564:9): [True: 2.79M, False: 2.04M]
  ------------------
  565|  2.79M|        return; // do not display
  566|       |
  567|  2.04M|    struct mp_log_root *root = log->root;
  568|       |
  569|  2.04M|    mp_mutex_lock(&root->lock);
  ------------------
  |  |  131|  2.04M|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  570|       |
  571|  2.04M|    root->buffer.len = 0;
  572|       |
  573|  2.04M|    if (log->partial[lev].len)
  ------------------
  |  Branch (573:9): [True: 763k, False: 1.27M]
  ------------------
  574|   763k|        bstr_xappend(root, &root->buffer, log->partial[lev]);
  575|  2.04M|    log->partial[lev].len = 0;
  576|       |
  577|  2.04M|    if (bstr_xappend_vasprintf(root, &root->buffer, format, va) < 0) {
  ------------------
  |  Branch (577:9): [True: 0, False: 2.04M]
  ------------------
  578|      0|        bstr_xappend(root, &root->buffer, bstr0("format error: "));
  579|      0|        bstr_xappend(root, &root->buffer, bstr0(format));
  580|      0|    }
  581|       |
  582|       |    // Remember last status message and restore it to ensure that it is
  583|       |    // always displayed
  584|  2.04M|    if (lev == MSGL_STATUS) {
  ------------------
  |  Branch (584:9): [True: 3.49k, False: 2.03M]
  ------------------
  585|  3.49k|        root->status_log = log;
  586|  3.49k|        root->status_line.len = 0;
  587|       |        // Use bstr_xappend instead bstrdup to reuse allocated memory
  588|  3.49k|        if (root->buffer.len)
  ------------------
  |  Branch (588:13): [True: 0, False: 3.49k]
  ------------------
  589|      0|            bstr_xappend(root, &root->status_line, root->buffer);
  590|  3.49k|    }
  591|       |
  592|  2.04M|    if (lev == MSGL_STATS) {
  ------------------
  |  Branch (592:9): [True: 599, False: 2.03M]
  ------------------
  593|    599|        dump_stats(log, lev, root->buffer);
  594|  2.03M|    } else if (lev == MSGL_STATUS && !test_terminal_level(log, lev)) {
  ------------------
  |  Branch (594:16): [True: 3.49k, False: 2.03M]
  |  Branch (594:38): [True: 7, False: 3.48k]
  ------------------
  595|       |        /* discard */
  596|  2.03M|    } else {
  597|  2.03M|        write_term_msg(log, lev, root->buffer, &root->term_msg);
  598|       |
  599|  2.03M|        FILE *stream = term_msg_fp(root, lev);
  600|  2.03M|        if (root->term_msg.len) {
  ------------------
  |  Branch (600:13): [True: 264k, False: 1.77M]
  ------------------
  601|   264k|            root->term_status_msg.len = 0;
  602|   264k|            if (lev != MSGL_STATUS && root->status_line.len && root->status_log &&
  ------------------
  |  Branch (602:17): [True: 264k, False: 0]
  |  Branch (602:39): [True: 0, False: 264k]
  |  Branch (602:64): [True: 0, False: 0]
  ------------------
  603|   264k|                is_status_output(root, lev) && test_terminal_level(root->status_log, MSGL_STATUS))
  ------------------
  |  Branch (603:17): [True: 0, False: 0]
  |  Branch (603:48): [True: 0, False: 0]
  ------------------
  604|      0|            {
  605|      0|                write_term_msg(root->status_log, MSGL_STATUS, root->status_line,
  606|      0|                               &root->term_status_msg);
  607|      0|            }
  608|   264k|            fwrite(root->term_msg.start, root->term_msg.len, 1, stream);
  609|   264k|            if (root->term_status_msg.len)
  ------------------
  |  Branch (609:17): [True: 0, False: 264k]
  ------------------
  610|      0|                fwrite(root->term_status_msg.start, root->term_status_msg.len, 1, stream);
  611|   264k|            fflush(stream);
  612|   264k|        }
  613|  2.03M|    }
  614|       |
  615|  2.04M|    mp_mutex_unlock(&root->lock);
  ------------------
  |  |  133|  2.04M|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  616|  2.04M|}
mp_log_new:
  638|   249k|{
  639|   249k|    mp_assert(parent);
  ------------------
  |  |   41|   249k|#define mp_assert assert
  ------------------
  640|   249k|    struct mp_log *log = talloc_zero(talloc_ctx, struct mp_log);
  ------------------
  |  |   27|   249k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|   249k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|   249k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  641|   249k|    if (!parent->root)
  ------------------
  |  Branch (641:9): [True: 0, False: 249k]
  ------------------
  642|      0|        return log; // same as null_log
  643|   249k|    talloc_set_destructor(log, destroy_log);
  ------------------
  |  |   41|   249k|#define talloc_set_destructor           ta_set_destructor
  ------------------
  644|   249k|    log->root = parent->root;
  645|   249k|    log->max_level = MSGL_MAX;
  646|   249k|    if (name) {
  ------------------
  |  Branch (646:9): [True: 244k, False: 4.32k]
  ------------------
  647|   244k|        if (name[0] == '!') {
  ------------------
  |  Branch (647:13): [True: 40.6k, False: 204k]
  ------------------
  648|  40.6k|            name = &name[1];
  649|   204k|        } else if (name[0] == '/') {
  ------------------
  |  Branch (649:20): [True: 0, False: 204k]
  ------------------
  650|      0|            name = &name[1];
  651|      0|            log->prefix = talloc_strdup(log, name);
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  652|   204k|        } else {
  653|   204k|            log->prefix = parent->prefix
  ------------------
  |  Branch (653:27): [True: 63.4k, False: 140k]
  ------------------
  654|   204k|                    ? talloc_asprintf(log, "%s/%s", parent->prefix, name)
  ------------------
  |  |   52|  63.4k|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|  63.4k|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  655|   204k|                    : talloc_strdup(log, name);
  ------------------
  |  |   50|   140k|#define talloc_strdup                   ta_xstrdup
  ------------------
  656|   204k|        }
  657|   244k|        log->verbose_prefix = parent->prefix
  ------------------
  |  Branch (657:31): [True: 63.4k, False: 181k]
  ------------------
  658|   244k|                ? talloc_asprintf(log, "%s/%s", parent->prefix, name)
  ------------------
  |  |   52|  63.4k|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|  63.4k|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  659|   244k|                : talloc_strdup(log, name);
  ------------------
  |  |   50|   181k|#define talloc_strdup                   ta_xstrdup
  ------------------
  660|   244k|        if (log->prefix && !log->prefix[0])
  ------------------
  |  Branch (660:13): [True: 204k, False: 40.6k]
  |  Branch (660:28): [True: 17.0k, False: 187k]
  ------------------
  661|  17.0k|            log->prefix = NULL;
  662|   244k|        if (!log->verbose_prefix[0])
  ------------------
  |  Branch (662:13): [True: 17.0k, False: 227k]
  ------------------
  663|  17.0k|            log->verbose_prefix = "global";
  664|   244k|    } else {
  665|  4.32k|        log->prefix = talloc_strdup(log, parent->prefix);
  ------------------
  |  |   50|  4.32k|#define talloc_strdup                   ta_xstrdup
  ------------------
  666|  4.32k|        log->verbose_prefix = talloc_strdup(log, parent->verbose_prefix);
  ------------------
  |  |   50|  4.32k|#define talloc_strdup                   ta_xstrdup
  ------------------
  667|  4.32k|    }
  668|   249k|    return log;
  669|   249k|}
mp_msg_init:
  672|  17.0k|{
  673|  17.0k|    mp_assert(!global->log);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  674|       |
  675|  17.0k|    struct mp_log_root *root = talloc_zero(NULL, struct mp_log_root);
  ------------------
  |  |   27|  17.0k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  17.0k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  676|  17.0k|    *root = (struct mp_log_root){
  677|  17.0k|        .global = global,
  678|  17.0k|        .reload_counter = 1,
  679|  17.0k|    };
  680|       |
  681|  17.0k|    mp_mutex_init(&root->lock);
  682|  17.0k|    mp_mutex_init(&root->log_file_lock);
  683|  17.0k|    mp_cond_init(&root->log_file_wakeup);
  684|       |
  685|  17.0k|    struct mp_log dummy = { .root = root };
  686|  17.0k|    struct mp_log *log = mp_log_new(root, &dummy, "");
  687|       |
  688|  17.0k|    global->log = log;
  689|  17.0k|}
mp_msg_update_msglevels:
  782|  29.2k|{
  783|  29.2k|    struct mp_log_root *root = global->log->root;
  784|       |
  785|  29.2k|    mp_mutex_lock(&root->lock);
  ------------------
  |  |  131|  29.2k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  786|       |
  787|  29.2k|    root->verbose = opts->verbose;
  788|  29.2k|    root->really_quiet = opts->msg_really_quiet;
  789|  29.2k|    root->module = opts->msg_module;
  790|  29.2k|    root->use_terminal = opts->use_terminal;
  791|  29.2k|    root->show_time = opts->msg_time;
  792|       |
  793|  29.2k|    if (root->really_quiet)
  ------------------
  |  Branch (793:9): [True: 13, False: 29.2k]
  ------------------
  794|     13|        root->status_lines = 0;
  795|       |
  796|  41.2k|    for (int i = STDOUT_FILENO; i <= STDERR_FILENO && root->use_terminal; ++i) {
  ------------------
  |  Branch (796:33): [True: 35.2k, False: 6.00k]
  |  Branch (796:55): [True: 12.0k, False: 23.2k]
  ------------------
  797|  12.0k|        root->isatty[i] = isatty(i);
  798|  12.0k|        root->color[i] = opts->msg_color && root->isatty[i];
  ------------------
  |  Branch (798:26): [True: 12.0k, False: 0]
  |  Branch (798:45): [True: 0, False: 12.0k]
  ------------------
  799|  12.0k|    }
  800|       |
  801|  29.2k|    m_option_type_msglevels.free(&root->msg_levels);
  802|  29.2k|    m_option_type_msglevels.copy(NULL, &root->msg_levels, &opts->msg_levels);
  803|       |
  804|  29.2k|    atomic_fetch_add(&root->reload_counter, 1);
  805|  29.2k|    mp_mutex_unlock(&root->lock);
  ------------------
  |  |  133|  29.2k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  806|       |
  807|  29.2k|    if (check_new_path(global, opts->log_file, &root->log_path)) {
  ------------------
  |  Branch (807:9): [True: 0, False: 29.2k]
  ------------------
  808|      0|        terminate_log_file_thread(root);
  809|      0|        if (root->log_path) {
  ------------------
  |  Branch (809:13): [True: 0, False: 0]
  ------------------
  810|      0|            root->log_file = fopen(root->log_path, "wb");
  811|      0|            if (root->log_file) {
  ------------------
  |  Branch (811:17): [True: 0, False: 0]
  ------------------
  812|       |
  813|       |                // if a logfile is created and the early filebuf still exists,
  814|       |                // flush and destroy the early buffer
  815|      0|                mp_mutex_lock(&root->lock);
  ------------------
  |  |  131|      0|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  816|      0|                struct mp_log_buffer *earlybuf = root->early_filebuffer;
  817|      0|                if (earlybuf)
  ------------------
  |  Branch (817:21): [True: 0, False: 0]
  ------------------
  818|      0|                    root->early_filebuffer = NULL;  // but it still logs msgs
  819|      0|                mp_mutex_unlock(&root->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  820|       |
  821|      0|                if (earlybuf) {
  ------------------
  |  Branch (821:21): [True: 0, False: 0]
  ------------------
  822|       |                    // flush, destroy before creating the normal logfile buf,
  823|       |                    // as once the new one is created (specifically, its write
  824|       |                    // thread), then MSGL_LOGFILE messages become blocking, but
  825|       |                    // the early logfile buf is without dequeue - can deadlock.
  826|       |                    // note: timestamp is unknown, we use 0.000 as indication.
  827|       |                    // note: new messages while iterating are still flushed.
  828|      0|                    struct mp_log_buffer_entry *e;
  829|      0|                    while ((e = mp_msg_log_buffer_read(earlybuf))) {
  ------------------
  |  Branch (829:28): [True: 0, False: 0]
  ------------------
  830|      0|                        fprintf(root->log_file, "[%8.3f][%c][%s] %s", 0.0,
  831|      0|                                mp_log_levels[e->level][0], e->prefix, e->text);
  832|      0|                        talloc_free(e);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  833|      0|                    }
  834|      0|                    mp_msg_log_buffer_destroy(earlybuf);  // + remove from root
  835|      0|                }
  836|       |
  837|      0|                root->log_file_buffer =
  838|      0|                    mp_msg_log_buffer_new(global, FILE_BUF, MP_LOG_BUFFER_MSGL_LOGFILE,
  ------------------
  |  |   44|      0|#define FILE_BUF 100
  ------------------
                                  mp_msg_log_buffer_new(global, FILE_BUF, MP_LOG_BUFFER_MSGL_LOGFILE,
  ------------------
  |  |   29|      0|#define MP_LOG_BUFFER_MSGL_LOGFILE (MSGL_MAX + 2)
  ------------------
  839|      0|                                          wakeup_log_file, root);
  840|      0|                root->log_file_thread_active = true;
  841|      0|                if (mp_thread_create(&root->log_file_thread, log_file_thread,
  ------------------
  |  |  211|      0|#define mp_thread_create(t, f, a) pthread_create(t, NULL, f, a)
  |  |  ------------------
  |  |  |  Branch (211:35): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  842|      0|                                   root))
  843|      0|                {
  844|      0|                    root->log_file_thread_active = false;
  845|      0|                    terminate_log_file_thread(root);
  846|      0|                }
  847|      0|            } else {
  848|      0|                mp_err(global->log, "Failed to open log file '%s'\n",
  ------------------
  |  |   72|      0|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  849|      0|                       root->log_path);
  850|      0|            }
  851|      0|        }
  852|      0|    }
  853|       |
  854|  29.2k|    if (check_new_path(global, opts->dump_stats, &root->stats_path)) {
  ------------------
  |  Branch (854:9): [True: 21, False: 29.1k]
  ------------------
  855|     21|        bool open_error = false;
  856|       |
  857|     21|        mp_mutex_lock(&root->lock);
  ------------------
  |  |  131|     21|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  858|     21|        if (root->stats_file)
  ------------------
  |  Branch (858:13): [True: 0, False: 21]
  ------------------
  859|      0|            fclose(root->stats_file);
  860|     21|        root->stats_file = NULL;
  861|     21|        if (root->stats_path) {
  ------------------
  |  Branch (861:13): [True: 21, False: 0]
  ------------------
  862|     21|            root->stats_file = fopen(root->stats_path, "wb");
  863|     21|            open_error = !root->stats_file;
  864|     21|        }
  865|     21|        mp_mutex_unlock(&root->lock);
  ------------------
  |  |  133|     21|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  866|       |
  867|     21|        if (open_error) {
  ------------------
  |  Branch (867:13): [True: 2, False: 19]
  ------------------
  868|      2|            mp_err(global->log, "Failed to open stats file '%s'\n",
  ------------------
  |  |   72|      2|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  869|      2|                   root->stats_path);
  870|      2|        }
  871|     21|    }
  872|  29.2k|}
mp_msg_force_stderr:
  875|     34|{
  876|     34|    struct mp_log_root *root = global->log->root;
  877|       |
  878|     34|    mp_mutex_lock(&root->lock);
  ------------------
  |  |  131|     34|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  879|     34|    root->force_stderr = force_stderr;
  880|     34|    mp_mutex_unlock(&root->lock);
  ------------------
  |  |  133|     34|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  881|     34|}
mp_msg_has_log_file:
  885|  58.4k|{
  886|  58.4k|    struct mp_log_root *root = global->log->root;
  887|       |
  888|  58.4k|    return !!root->log_file;
  889|  58.4k|}
mp_msg_uninit:
  892|  17.0k|{
  893|  17.0k|    struct mp_log_root *root = global->log->root;
  894|  17.0k|    mp_msg_flush_status_line(global->log, true);
  895|  17.0k|    if (root->really_quiet && root->isatty[term_msg_fileno(root, MSGL_STATUS)])
  ------------------
  |  Branch (895:9): [True: 7, False: 17.0k]
  |  Branch (895:31): [True: 0, False: 7]
  ------------------
  896|      0|        fprintf(term_msg_fp(root, MSGL_STATUS), TERM_ESC_RESTORE_CURSOR);
  ------------------
  |  |   30|      0|#define TERM_ESC_RESTORE_CURSOR     "\033[?25h"
  ------------------
  897|  17.0k|    terminate_log_file_thread(root);
  898|  17.0k|    mp_msg_log_buffer_destroy(root->early_buffer);
  899|  17.0k|    mp_msg_log_buffer_destroy(root->early_filebuffer);
  900|  17.0k|    mp_assert(root->num_buffers == 0);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  901|  17.0k|    if (root->stats_file)
  ------------------
  |  Branch (901:9): [True: 19, False: 17.0k]
  ------------------
  902|     19|        fclose(root->stats_file);
  903|  17.0k|    talloc_free(root->stats_path);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  904|  17.0k|    talloc_free(root->log_path);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  905|  17.0k|    m_option_type_msglevels.free(&root->msg_levels);
  906|  17.0k|    mp_mutex_destroy(&root->lock);
  ------------------
  |  |  130|  17.0k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
  907|  17.0k|    mp_mutex_destroy(&root->log_file_lock);
  ------------------
  |  |  130|  17.0k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
  908|  17.0k|    mp_cond_destroy(&root->log_file_wakeup);
  909|  17.0k|    talloc_free(root);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  910|  17.0k|    global->log = NULL;
  911|  17.0k|}
mp_msg_set_early_logging:
  959|  29.2k|{
  960|  29.2k|    struct mp_log_root *root = global->log->root;
  961|       |
  962|  29.2k|    mp_msg_set_early_logging_raw(global, enable, &root->early_buffer,
  963|  29.2k|                                 EARLY_TERM_BUF, MP_LOG_BUFFER_MSGL_TERM);
  ------------------
  |  |   47|  29.2k|#define EARLY_TERM_BUF 100
  ------------------
                                               EARLY_TERM_BUF, MP_LOG_BUFFER_MSGL_TERM);
  ------------------
  |  |   27|  29.2k|#define MP_LOG_BUFFER_MSGL_TERM (MSGL_MAX + 1)
  ------------------
  964|       |
  965|       |    // normally MSGL_LOGFILE buffer gets a write thread, but not the early buf
  966|  29.2k|    mp_msg_set_early_logging_raw(global, enable, &root->early_filebuffer,
  967|  29.2k|                                 EARLY_FILE_BUF, MP_LOG_BUFFER_MSGL_LOGFILE);
  ------------------
  |  |   53|  29.2k|#define EARLY_FILE_BUF 5000
  ------------------
                                               EARLY_FILE_BUF, MP_LOG_BUFFER_MSGL_LOGFILE);
  ------------------
  |  |   29|  29.2k|#define MP_LOG_BUFFER_MSGL_LOGFILE (MSGL_MAX + 2)
  ------------------
  968|  29.2k|}
mp_msg_log_buffer_new:
  974|  34.1k|{
  975|  34.1k|    struct mp_log_root *root = global->log->root;
  976|       |
  977|  34.1k|    mp_mutex_lock(&root->lock);
  ------------------
  |  |  131|  34.1k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  978|       |
  979|  34.1k|    if (level == MP_LOG_BUFFER_MSGL_TERM) {
  ------------------
  |  |   27|  34.1k|#define MP_LOG_BUFFER_MSGL_TERM (MSGL_MAX + 1)
  ------------------
  |  Branch (979:9): [True: 17.0k, False: 17.0k]
  ------------------
  980|       |        // The first thing which creates a terminal-level log buffer gets the
  981|       |        // early log buffer, if it exists. This is supposed to enable a script
  982|       |        // to grab log messages from before it was initialized. It's OK that
  983|       |        // this works only for 1 script and only once.
  984|  17.0k|        if (root->early_buffer) {
  ------------------
  |  Branch (984:13): [True: 0, False: 17.0k]
  ------------------
  985|      0|            struct mp_log_buffer *buffer = root->early_buffer;
  986|      0|            root->early_buffer = NULL;
  987|      0|            mp_msg_log_buffer_resize(buffer, size);
  988|      0|            buffer->wakeup_cb = wakeup_cb;
  989|      0|            buffer->wakeup_cb_ctx = wakeup_cb_ctx;
  990|      0|            mp_mutex_unlock(&root->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  991|      0|            return buffer;
  992|      0|        }
  993|  17.0k|    }
  994|       |
  995|  34.1k|    mp_assert(size > 0);
  ------------------
  |  |   41|  34.1k|#define mp_assert assert
  ------------------
  996|       |
  997|  34.1k|    struct mp_log_buffer *buffer = talloc_ptrtype(NULL, buffer);
  ------------------
  |  |   34|  34.1k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  34.1k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  34.1k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  998|  34.1k|    *buffer = (struct mp_log_buffer) {
  999|  34.1k|        .root = root,
 1000|  34.1k|        .level = level,
 1001|  34.1k|        .entries = talloc_array(buffer, struct mp_log_buffer_entry *, size),
  ------------------
  |  |   29|  34.1k|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|  34.1k|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  34.1k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1002|  34.1k|        .capacity = size,
 1003|  34.1k|        .wakeup_cb = wakeup_cb,
 1004|  34.1k|        .wakeup_cb_ctx = wakeup_cb_ctx,
 1005|  34.1k|    };
 1006|       |
 1007|  34.1k|    mp_mutex_init(&buffer->lock);
 1008|       |
 1009|  34.1k|    MP_TARRAY_APPEND(root, root->buffers, root->num_buffers, buffer);
  ------------------
  |  |  105|  34.1k|    do {                                            \
  |  |  106|  34.1k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  34.1k|    do {                                            \
  |  |  |  |   97|  34.1k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  34.1k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  34.1k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  34.1k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 17.0k, False: 17.0k]
  |  |  |  |  ------------------
  |  |  |  |   99|  34.1k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  17.0k|    do {                                                        \
  |  |  |  |  |  |   89|  17.0k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  17.0k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  17.0k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  17.0k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  17.0k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  17.0k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  17.0k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  34.1k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  34.1k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  34.1k|        (idxvar)++;                                 \
  |  |  109|  34.1k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1010|       |
 1011|  34.1k|    atomic_fetch_add(&root->reload_counter, 1);
 1012|  34.1k|    mp_mutex_unlock(&root->lock);
  ------------------
  |  |  133|  34.1k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1013|       |
 1014|  34.1k|    return buffer;
 1015|  34.1k|}
mp_msg_log_buffer_destroy:
 1059|  97.8k|{
 1060|  97.8k|    if (!buffer)
  ------------------
  |  Branch (1060:9): [True: 63.6k, False: 34.1k]
  ------------------
 1061|  63.6k|        return;
 1062|       |
 1063|  34.1k|    struct mp_log_root *root = buffer->root;
 1064|       |
 1065|  34.1k|    mp_mutex_lock(&root->lock);
  ------------------
  |  |  131|  34.1k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1066|       |
 1067|  34.1k|    for (int n = 0; n < root->num_buffers; n++) {
  ------------------
  |  Branch (1067:21): [True: 34.1k, False: 0]
  ------------------
 1068|  34.1k|        if (root->buffers[n] == buffer) {
  ------------------
  |  Branch (1068:13): [True: 34.1k, False: 0]
  ------------------
 1069|  34.1k|            MP_TARRAY_REMOVE_AT(root->buffers, root->num_buffers, n);
  ------------------
  |  |  143|  34.1k|    do {                                            \
  |  |  144|  34.1k|        size_t at_ = (at);                          \
  |  |  145|  34.1k|        assert(at_ <= (idxvar));                    \
  |  |  146|  34.1k|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|  34.1k|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|  34.1k|        (idxvar)--;                                 \
  |  |  149|  34.1k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1070|  34.1k|            goto found;
 1071|  34.1k|        }
 1072|  34.1k|    }
 1073|       |
 1074|      0|    MP_ASSERT_UNREACHABLE();
  ------------------
  |  |   42|      0|#define MP_ASSERT_UNREACHABLE() (assert(!"unreachable"), __builtin_unreachable())
  ------------------
 1075|       |
 1076|  34.1k|found:
 1077|       |
 1078|  1.14M|    while (buffer->num_entries)
  ------------------
  |  Branch (1078:12): [True: 1.11M, False: 34.1k]
  ------------------
 1079|  1.11M|        talloc_free(log_buffer_read(buffer));
  ------------------
  |  |   47|  1.11M|#define talloc_free                     ta_free
  ------------------
 1080|       |
 1081|  34.1k|    mp_mutex_destroy(&buffer->lock);
  ------------------
  |  |  130|  34.1k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
 1082|  34.1k|    talloc_free(buffer);
  ------------------
  |  |   47|  34.1k|#define talloc_free                     ta_free
  ------------------
 1083|       |
 1084|  34.1k|    atomic_fetch_add(&root->reload_counter, 1);
 1085|  34.1k|    mp_mutex_unlock(&root->lock);
  ------------------
  |  |  133|  34.1k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1086|  34.1k|}
mp_msg:
 1121|  4.82M|{
 1122|  4.82M|    va_list va;
 1123|  4.82M|    va_start(va, format);
 1124|  4.82M|    mp_msg_va(log, lev, format, va);
 1125|  4.82M|    va_end(va);
 1126|  4.82M|}
mp_msg_find_level:
 1153|  1.23k|{
 1154|  6.91k|    for (int n = 0; n < MP_ARRAY_SIZE(mp_log_levels); n++) {
  ------------------
  |  |   48|  6.91k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (1154:21): [True: 6.33k, False: 580]
  ------------------
 1155|  6.33k|        if (mp_log_levels[n] && !strcasecmp(s, mp_log_levels[n]))
  ------------------
  |  Branch (1155:13): [True: 6.33k, False: 0]
  |  Branch (1155:33): [True: 655, False: 5.67k]
  ------------------
 1156|    655|            return n;
 1157|  6.33k|    }
 1158|    580|    return -1;
 1159|  1.23k|}
msg.c:update_loglevel:
  140|   155k|{
  141|   155k|    struct mp_log_root *root = log->root;
  142|   155k|    mp_mutex_lock(&root->lock);
  ------------------
  |  |  131|   155k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  143|   155k|    log->level = MSGL_STATUS + root->verbose; // default log level
  144|   155k|    if (root->really_quiet)
  ------------------
  |  Branch (144:9): [True: 82, False: 155k]
  ------------------
  145|     82|        log->level = -1;
  146|   156k|    for (int n = 0; root->msg_levels && root->msg_levels[n * 2 + 0]; n++) {
  ------------------
  |  Branch (146:21): [True: 1.78k, False: 154k]
  |  Branch (146:41): [True: 896, False: 887]
  ------------------
  147|    896|        if (match_mod(log->verbose_prefix, root->msg_levels[n * 2 + 0]))
  ------------------
  |  Branch (147:13): [True: 130, False: 766]
  ------------------
  148|    130|            log->level = mp_msg_find_level(root->msg_levels[n * 2 + 1]);
  149|    896|    }
  150|   155k|    log->terminal_level = log->level;
  151|   374k|    for (int n = 0; n < log->root->num_buffers; n++) {
  ------------------
  |  Branch (151:21): [True: 219k, False: 155k]
  ------------------
  152|   219k|        int buffer_level = log->root->buffers[n]->level;
  153|   219k|        if (buffer_level == MP_LOG_BUFFER_MSGL_LOGFILE)
  ------------------
  |  |   29|   219k|#define MP_LOG_BUFFER_MSGL_LOGFILE (MSGL_MAX + 2)
  ------------------
  |  Branch (153:13): [True: 109k, False: 109k]
  ------------------
  154|   109k|            buffer_level = MSGL_DEBUG;
  155|   219k|        if (buffer_level != MP_LOG_BUFFER_MSGL_TERM)
  ------------------
  |  |   27|   219k|#define MP_LOG_BUFFER_MSGL_TERM (MSGL_MAX + 1)
  ------------------
  |  Branch (155:13): [True: 109k, False: 109k]
  ------------------
  156|   109k|            log->level = MPMAX(log->level, buffer_level);
  ------------------
  |  |   43|   109k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 4.47k, False: 105k]
  |  |  ------------------
  ------------------
  157|   219k|    }
  158|   155k|    if (log->root->log_file)
  ------------------
  |  Branch (158:9): [True: 0, False: 155k]
  ------------------
  159|      0|        log->level = MPMAX(log->level, MSGL_DEBUG);
  ------------------
  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  160|   155k|    if (log->root->stats_file)
  ------------------
  |  Branch (160:9): [True: 312, False: 154k]
  ------------------
  161|    312|        log->level = MPMAX(log->level, MSGL_STATS);
  ------------------
  |  |   43|    312|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 175, False: 137]
  |  |  ------------------
  ------------------
  162|   155k|    log->level = MPMIN(log->level, log->max_level);
  ------------------
  |  |   44|   155k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 1.14k, False: 154k]
  |  |  ------------------
  ------------------
  163|   155k|    atomic_store(&log->reload_counter, atomic_load(&log->root->reload_counter));
  164|   155k|    mp_mutex_unlock(&root->lock);
  ------------------
  |  |  133|   155k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  165|   155k|}
msg.c:match_mod:
  131|    896|{
  132|    896|    if (!strcmp(mod, "all"))
  ------------------
  |  Branch (132:9): [True: 119, False: 777]
  ------------------
  133|    119|        return true;
  134|       |    // Path prefix matches
  135|    777|    bstr b = bstr0(name);
  136|    777|    return bstr_eatstart0(&b, mod) && (bstr_eatstart0(&b, "/") || !b.len);
  ------------------
  |  Branch (136:12): [True: 440, False: 337]
  |  Branch (136:40): [True: 0, False: 440]
  |  Branch (136:67): [True: 11, False: 429]
  ------------------
  137|    896|}
msg.c:msg_flush_status_line:
  263|  21.0k|{
  264|  21.0k|    if (!root->status_lines)
  ------------------
  |  Branch (264:9): [True: 21.0k, False: 0]
  ------------------
  265|  21.0k|        goto done;
  266|       |
  267|      0|    FILE *fp = term_msg_fp(root, MSGL_STATUS);
  268|      0|    if (!clear) {
  ------------------
  |  Branch (268:9): [True: 0, False: 0]
  ------------------
  269|      0|        if (root->isatty[term_msg_fileno(root, MSGL_STATUS)])
  ------------------
  |  Branch (269:13): [True: 0, False: 0]
  ------------------
  270|      0|            fprintf(fp, TERM_ESC_RESTORE_CURSOR);
  ------------------
  |  |   30|      0|#define TERM_ESC_RESTORE_CURSOR     "\033[?25h"
  ------------------
  271|      0|        fprintf(fp, "\n");
  272|      0|        root->blank_lines = 0;
  273|      0|        root->status_lines = 0;
  274|      0|        goto done;
  275|      0|    }
  276|       |
  277|      0|    bstr term_msg = {0};
  278|      0|    prepare_prefix(root, &term_msg, MSGL_STATUS, 0);
  279|      0|    if (term_msg.len) {
  ------------------
  |  Branch (279:9): [True: 0, False: 0]
  ------------------
  280|      0|        fprintf(fp, "%.*s", BSTR_P(term_msg));
  ------------------
  |  |  283|      0|#define BSTR_P(bstr) (int)((bstr).len), ((bstr).start ? (char*)(bstr).start : "")
  |  |  ------------------
  |  |  |  Branch (283:42): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  281|      0|        talloc_free(term_msg.start);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  282|      0|    }
  283|       |
  284|  21.0k|done:
  285|  21.0k|    root->status_line.len = 0;
  286|  21.0k|}
msg.c:prepare_prefix:
  219|   267k|{
  220|   267k|    int new_lines = lev == MSGL_STATUS ? term_lines : 0;
  ------------------
  |  Branch (220:21): [True: 3.48k, False: 264k]
  ------------------
  221|   267k|    out->len = 0;
  222|       |
  223|   267k|    if (!is_status_output(root, lev))
  ------------------
  |  Branch (223:9): [True: 0, False: 267k]
  ------------------
  224|      0|        return;
  225|       |
  226|   267k|    if (!root->isatty[term_msg_fileno(root, lev)]) {
  ------------------
  |  Branch (226:9): [True: 267k, False: 0]
  ------------------
  227|   267k|        if (root->status_lines)
  ------------------
  |  Branch (227:13): [True: 0, False: 267k]
  ------------------
  228|      0|            bstr_xappend(root, out, bstr0("\n"));
  229|   267k|        root->status_lines = new_lines;
  230|   267k|        return;
  231|   267k|    }
  232|       |
  233|       |    // Set cursor state
  234|      0|    if (new_lines && !root->status_lines) {
  ------------------
  |  Branch (234:9): [True: 0, False: 0]
  |  Branch (234:22): [True: 0, False: 0]
  ------------------
  235|      0|        bstr_xappend(root, out, bstr0(TERM_ESC_HIDE_CURSOR));
  ------------------
  |  |   29|      0|#define TERM_ESC_HIDE_CURSOR        "\033[?25l"
  ------------------
  236|      0|    } else if (!new_lines && root->status_lines) {
  ------------------
  |  Branch (236:16): [True: 0, False: 0]
  |  Branch (236:30): [True: 0, False: 0]
  ------------------
  237|      0|        bstr_xappend(root, out, bstr0(TERM_ESC_RESTORE_CURSOR));
  ------------------
  |  |   30|      0|#define TERM_ESC_RESTORE_CURSOR     "\033[?25h"
  ------------------
  238|      0|    }
  239|       |
  240|      0|    int line_skip = 0;
  241|      0|    if (root->status_lines) {
  ------------------
  |  Branch (241:9): [True: 0, False: 0]
  ------------------
  242|       |        // Clear previous status line
  243|      0|        bstr_xappend(root, out, bstr0("\033[1K\r"));
  244|      0|        bstr up_clear = bstr0("\033[A\033[K");
  245|      0|        for (int i = 1; i < root->status_lines; ++i)
  ------------------
  |  Branch (245:25): [True: 0, False: 0]
  ------------------
  246|      0|            bstr_xappend(root, out, up_clear);
  247|      0|        mp_assert(root->status_lines > 0 && root->blank_lines >= root->status_lines);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  248|      0|        line_skip = root->blank_lines - root->status_lines;
  249|      0|    }
  250|       |
  251|      0|    if (new_lines)
  ------------------
  |  Branch (251:9): [True: 0, False: 0]
  ------------------
  252|      0|        line_skip -= MPMAX(0, root->blank_lines - new_lines);
  ------------------
  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  253|       |
  254|      0|    if (line_skip)
  ------------------
  |  Branch (254:9): [True: 0, False: 0]
  ------------------
  255|      0|        bstr_xappend_asprintf(root, out, line_skip > 0 ? "\033[%dA" : "\033[%dB", abs(line_skip));
  ------------------
  |  Branch (255:42): [True: 0, False: 0]
  ------------------
  256|       |
  257|      0|    root->blank_lines = MPMAX(0, root->blank_lines - term_lines);
  ------------------
  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  258|      0|    root->status_lines = new_lines;
  259|      0|    root->blank_lines += root->status_lines;
  260|      0|}
msg.c:term_msg_fp:
  200|  2.03M|{
  201|  2.03M|    return term_msg_fileno(root, lev) == STDERR_FILENO ? stderr : stdout;
  ------------------
  |  Branch (201:12): [True: 4.85k, False: 2.03M]
  ------------------
  202|  2.03M|}
msg.c:dump_stats:
  498|    599|{
  499|    599|    struct mp_log_root *root = log->root;
  500|    599|    if (lev == MSGL_STATS && root->stats_file)
  ------------------
  |  Branch (500:9): [True: 599, False: 0]
  |  Branch (500:30): [True: 53, False: 546]
  ------------------
  501|     53|        fprintf(root->stats_file, "%"PRId64" %.*s\n", mp_time_ns(), BSTR_P(text));
  ------------------
  |  |  283|     53|#define BSTR_P(bstr) (int)((bstr).len), ((bstr).start ? (char*)(bstr).start : "")
  |  |  ------------------
  |  |  |  Branch (283:42): [True: 53, False: 0]
  |  |  ------------------
  ------------------
  502|    599|}
msg.c:test_terminal_level:
  371|  2.04M|{
  372|  2.04M|    return lev <= log->terminal_level && log->root->use_terminal &&
  ------------------
  |  Branch (372:12): [True: 1.21M, False: 832k]
  |  Branch (372:42): [True: 432k, False: 777k]
  ------------------
  373|  2.04M|           !(lev == MSGL_STATUS && terminal_in_background());
  ------------------
  |  Branch (373:14): [True: 6.97k, False: 425k]
  |  Branch (373:36): [True: 0, False: 6.97k]
  ------------------
  374|  2.04M|}
msg.c:write_term_msg:
  505|  2.03M|{
  506|  2.03M|    struct mp_log_root *root = log->root;
  507|  2.03M|    bool print_term = test_terminal_level(log, lev);
  508|  2.03M|    int fileno = term_msg_fileno(root, lev);
  509|  2.03M|    int term_w = 0, term_h = 0;
  510|  2.03M|    if (print_term && root->isatty[fileno])
  ------------------
  |  Branch (510:9): [True: 429k, False: 1.61M]
  |  Branch (510:23): [True: 0, False: 429k]
  ------------------
  511|      0|        terminal_get_size(&term_w, &term_h);
  512|       |
  513|  2.03M|    out->len = 0;
  514|       |
  515|       |    // Split away each line. Normally we require full lines; buffer partial
  516|       |    // lines if they happen.
  517|  2.03M|    root->term_msg_tmp.len = 0;
  518|  2.03M|    int term_msg_lines = 0;
  519|       |
  520|  2.03M|    bstr str = text;
  521|  3.31M|    while (str.len) {
  ------------------
  |  Branch (521:12): [True: 2.04M, False: 1.27M]
  ------------------
  522|  2.04M|        bstr line = bstr_getline(str, &str);
  523|  2.04M|        if (line.start[line.len - 1] != '\n') {
  ------------------
  |  Branch (523:13): [True: 763k, False: 1.27M]
  ------------------
  524|   763k|            mp_assert(str.len == 0);
  ------------------
  |  |   41|   763k|#define mp_assert assert
  ------------------
  525|   763k|            str = line;
  526|   763k|            break;
  527|   763k|        }
  528|       |
  529|  1.27M|        bool clip = bstr_eatstart0(&line, TERM_MSG_0);
  ------------------
  |  |   30|  1.27M|#define TERM_MSG_0 TERM_MSG_ESCAPE "0"
  |  |  ------------------
  |  |  |  |   29|  1.27M|#define TERM_MSG_ESCAPE "\xC2\x92" "t"
  |  |  ------------------
  ------------------
  530|  1.27M|        if (print_term) {
  ------------------
  |  Branch (530:13): [True: 264k, False: 1.01M]
  ------------------
  531|   264k|            int line_w;
  532|   264k|            append_terminal_line(log, lev, line, &root->term_msg_tmp, &line_w,
  533|   264k|                                 clip && term_w ? term_w : INT_MAX);
  ------------------
  |  Branch (533:34): [True: 0, False: 264k]
  |  Branch (533:42): [True: 0, False: 0]
  ------------------
  534|   264k|            term_msg_lines += (!line_w || !term_w)
  ------------------
  |  Branch (534:32): [True: 264k, False: 0]
  |  Branch (534:43): [True: 0, False: 0]
  ------------------
  535|   264k|                                ? 1 : (line_w + term_w - 1) / term_w;
  536|   264k|        }
  537|  1.27M|        write_msg_to_buffers(log, lev, line);
  538|  1.27M|    }
  539|       |
  540|  2.03M|    if (lev == MSGL_STATUS) {
  ------------------
  |  Branch (540:9): [True: 3.48k, False: 2.03M]
  ------------------
  541|  3.48k|        int line_w = 0;
  542|  3.48k|        bool clip = bstr_eatstart0(&str, TERM_MSG_0);
  ------------------
  |  |   30|  3.48k|#define TERM_MSG_0 TERM_MSG_ESCAPE "0"
  |  |  ------------------
  |  |  |  |   29|  3.48k|#define TERM_MSG_ESCAPE "\xC2\x92" "t"
  |  |  ------------------
  ------------------
  543|  3.48k|        if (str.len && print_term)
  ------------------
  |  Branch (543:13): [True: 0, False: 3.48k]
  |  Branch (543:24): [True: 0, False: 0]
  ------------------
  544|      0|            append_terminal_line(log, lev, str, &root->term_msg_tmp, &line_w,
  545|      0|                                 clip && term_w ? term_w : INT_MAX);
  ------------------
  |  Branch (545:34): [True: 0, False: 0]
  |  Branch (545:42): [True: 0, False: 0]
  ------------------
  546|  3.48k|        term_msg_lines += !term_w ? (str.len ? 1 : 0)
  ------------------
  |  Branch (546:27): [True: 3.48k, False: 0]
  |  Branch (546:38): [True: 0, False: 3.48k]
  ------------------
  547|  3.48k|                                  : (line_w + term_w - 1) / term_w;
  548|  2.03M|    } else if (str.len) {
  ------------------
  |  Branch (548:16): [True: 763k, False: 1.27M]
  ------------------
  549|   763k|        bstr_xappend(NULL, &log->partial[lev], str);
  550|   763k|    }
  551|       |
  552|  2.03M|    if (print_term && (root->term_msg_tmp.len || lev == MSGL_STATUS)) {
  ------------------
  |  Branch (552:9): [True: 429k, False: 1.61M]
  |  Branch (552:24): [True: 264k, False: 165k]
  |  Branch (552:50): [True: 3.48k, False: 161k]
  ------------------
  553|   267k|        prepare_prefix(root, out, lev, term_msg_lines);
  554|   267k|        if (root->color[fileno] && root->term_msg_tmp.len) {
  ------------------
  |  Branch (554:13): [True: 0, False: 267k]
  |  Branch (554:36): [True: 0, False: 0]
  ------------------
  555|      0|            set_msg_color(root, out, lev);
  556|      0|            set_term_color(root, &root->term_msg_tmp, -1);
  557|      0|        }
  558|   267k|        bstr_xappend(root, out, root->term_msg_tmp);
  559|   267k|    }
  560|  2.03M|}
msg.c:append_terminal_line:
  378|   264k|{
  379|   264k|    struct mp_log_root *root = log->root;
  380|       |
  381|   264k|    size_t start = term_msg->len;
  382|       |
  383|   264k|    if (root->show_time)
  ------------------
  |  Branch (383:9): [True: 1.11k, False: 263k]
  ------------------
  384|  1.11k|        bstr_xappend_asprintf(root, term_msg, "[%10.6f] ", mp_time_sec());
  385|       |
  386|   264k|    const char *log_prefix = (lev >= MSGL_V) || root->verbose || root->module
  ------------------
  |  Branch (386:30): [True: 234k, False: 30.3k]
  |  Branch (386:49): [True: 21.9k, False: 8.38k]
  |  Branch (386:66): [True: 501, False: 7.88k]
  ------------------
  387|   264k|                                ? log->verbose_prefix : log->prefix;
  388|   264k|    if (log_prefix) {
  ------------------
  |  Branch (388:9): [True: 257k, False: 6.55k]
  ------------------
  389|   257k|        if (root->module) {
  ------------------
  |  Branch (389:13): [True: 2.49k, False: 255k]
  ------------------
  390|  2.49k|            pretty_print_module(root, term_msg, log_prefix, lev);
  391|   255k|        } else {
  392|   255k|            bstr_xappend_asprintf(root, term_msg, "[%s] ", log_prefix);
  393|   255k|        }
  394|   257k|    }
  395|       |
  396|   264k|    bstr_xappend(root, term_msg, text);
  397|       |
  398|   264k|    const unsigned char *cut_pos = NULL;
  399|   264k|    int ellipsis_width = 2;
  400|   264k|    int width = term_disp_width(bstr_splice(*term_msg, start, term_msg->len),
  401|   264k|                                term_w - ellipsis_width, &cut_pos);
  402|   264k|    if (cut_pos) {
  ------------------
  |  Branch (402:9): [True: 0, False: 264k]
  ------------------
  403|      0|        int new_len = cut_pos - term_msg->start;
  404|      0|        bstr rem = bstrdup(NULL, (bstr){(unsigned char *)cut_pos, term_msg->len - new_len});
  405|      0|        void *ptr = rem.start;
  406|      0|        term_msg->len = new_len;
  407|       |
  408|      0|        bstr_xappend(root, term_msg, bstr0(".."));
  409|       |
  410|      0|        while (rem.len) {
  ------------------
  |  Branch (410:16): [True: 0, False: 0]
  ------------------
  411|      0|            if (bstr_eatstart0(&rem, "\n")) {
  ------------------
  |  Branch (411:17): [True: 0, False: 0]
  ------------------
  412|      0|                bstr_xappend(root, term_msg, bstr0("\n"));
  413|      0|                continue;
  414|      0|            }
  415|      0|            if (bstr_eatstart0(&rem, "\033[")) {
  ------------------
  |  Branch (415:17): [True: 0, False: 0]
  ------------------
  416|      0|                bstr_xappend(root, term_msg, bstr0("\033["));
  417|       |
  418|      0|                while (rem.len && !((*rem.start >= '@' && *rem.start <= '~') || *rem.start == 'm')) {
  ------------------
  |  Branch (418:24): [True: 0, False: 0]
  |  Branch (418:38): [True: 0, False: 0]
  |  Branch (418:59): [True: 0, False: 0]
  |  Branch (418:81): [True: 0, False: 0]
  ------------------
  419|      0|                    bstr_xappend(root, term_msg, bstr_splice(rem, 0, 1));
  420|      0|                    rem = bstr_cut(rem, 1);
  421|      0|                }
  422|      0|                bstr_xappend(root, term_msg, bstr_splice(rem, 0, 1));
  423|      0|            }
  424|      0|            rem = bstr_cut(rem, 1);
  425|      0|        }
  426|      0|        talloc_free(ptr);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  427|       |
  428|      0|        width += ellipsis_width;
  429|      0|    }
  430|   264k|    *line_w = root->isatty[term_msg_fileno(root, lev)] ? width : 0;
  ------------------
  |  Branch (430:15): [True: 0, False: 264k]
  ------------------
  431|   264k|}
msg.c:pretty_print_module:
  349|  2.49k|{
  350|  2.49k|    size_t prefix_len = strlen(prefix);
  351|  2.49k|    root->module_indent = MPMAX(10, MPMAX(root->module_indent, prefix_len));
  ------------------
  |  |   43|  4.99k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 29, False: 2.46k]
  |  |  |  Branch (43:29): [True: 2.28k, False: 208]
  |  |  |  Branch (43:41): [True: 2.28k, False: 179]
  |  |  ------------------
  ------------------
  352|  2.49k|    bool color = root->color[term_msg_fileno(root, lev)];
  353|       |
  354|       |    // Use random color based on the name of the module
  355|  2.49k|    if (color) {
  ------------------
  |  Branch (355:9): [True: 0, False: 2.49k]
  ------------------
  356|      0|        unsigned int mod = 0;
  357|      0|        for (int i = 0; i < prefix_len; ++i)
  ------------------
  |  Branch (357:25): [True: 0, False: 0]
  ------------------
  358|      0|            mod = mod * 33 + prefix[i];
  359|      0|        set_term_color(root, text, (mod + 1) % 15 + 1);
  360|      0|    }
  361|       |
  362|  2.49k|    bstr_xappend_asprintf(root, text, "%*s", root->module_indent, prefix);
  363|  2.49k|    if (color)
  ------------------
  |  Branch (363:9): [True: 0, False: 2.49k]
  ------------------
  364|      0|        set_term_color(root, text, -1);
  365|  2.49k|    bstr_xappend(root, text, bstr0(": "));
  366|  2.49k|    if (color)
  ------------------
  |  Branch (366:9): [True: 0, False: 2.49k]
  ------------------
  367|      0|        set_msg_color(root, text, lev);
  368|  2.49k|}
msg.c:write_msg_to_buffers:
  443|  1.27M|{
  444|  1.27M|    struct mp_log_root *root = log->root;
  445|  3.04M|    for (int n = 0; n < root->num_buffers; n++) {
  ------------------
  |  Branch (445:21): [True: 1.76M, False: 1.27M]
  ------------------
  446|  1.76M|        struct mp_log_buffer *buffer = root->buffers[n];
  447|  1.76M|        bool wakeup = false;
  448|  1.76M|        mp_mutex_lock(&buffer->lock);
  ------------------
  |  |  131|  1.76M|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  449|  1.76M|        int buffer_level = buffer->level;
  450|  1.76M|        if (buffer_level == MP_LOG_BUFFER_MSGL_TERM)
  ------------------
  |  |   27|  1.76M|#define MP_LOG_BUFFER_MSGL_TERM (MSGL_MAX + 1)
  ------------------
  |  Branch (450:13): [True: 883k, False: 883k]
  ------------------
  451|   883k|            buffer_level = log->terminal_level;
  452|  1.76M|        if (buffer_level == MP_LOG_BUFFER_MSGL_LOGFILE)
  ------------------
  |  |   29|  1.76M|#define MP_LOG_BUFFER_MSGL_LOGFILE (MSGL_MAX + 2)
  ------------------
  |  Branch (452:13): [True: 886k, False: 880k]
  ------------------
  453|   886k|            buffer_level = MPMAX(log->terminal_level, MSGL_DEBUG);
  ------------------
  |  |   43|   886k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 111k, False: 774k]
  |  |  ------------------
  ------------------
  454|  1.76M|        if (lev <= buffer_level && lev != MSGL_STATUS) {
  ------------------
  |  Branch (454:13): [True: 1.24M, False: 522k]
  |  Branch (454:36): [True: 1.24M, False: 0]
  ------------------
  455|  1.24M|            if (buffer->level == MP_LOG_BUFFER_MSGL_LOGFILE) {
  ------------------
  |  |   29|  1.24M|#define MP_LOG_BUFFER_MSGL_LOGFILE (MSGL_MAX + 2)
  ------------------
  |  Branch (455:17): [True: 882k, False: 362k]
  ------------------
  456|       |                // If the buffer is full, block until we can write again,
  457|       |                // unless there's no write thread (died, or early filebuffer)
  458|   882k|                bool dead = false;
  459|   883k|                while (buffer->num_entries == buffer->capacity && !dead) {
  ------------------
  |  Branch (459:24): [True: 2.85k, False: 880k]
  |  Branch (459:67): [True: 1.42k, False: 1.42k]
  ------------------
  460|       |                    // Temporary unlock is OK; buffer->level is immutable, and
  461|       |                    // buffer can't go away because the global log lock is held.
  462|  1.42k|                    mp_mutex_unlock(&buffer->lock);
  ------------------
  |  |  133|  1.42k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  463|  1.42k|                    mp_mutex_lock(&root->log_file_lock);
  ------------------
  |  |  131|  1.42k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  464|  1.42k|                    if (root->log_file_thread_active) {
  ------------------
  |  Branch (464:25): [True: 0, False: 1.42k]
  ------------------
  465|      0|                        mp_cond_wait(&root->log_file_wakeup,
  466|      0|                                          &root->log_file_lock);
  467|  1.42k|                    } else {
  468|  1.42k|                        dead = true;
  469|  1.42k|                    }
  470|  1.42k|                    mp_mutex_unlock(&root->log_file_lock);
  ------------------
  |  |  133|  1.42k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  471|  1.42k|                    mp_mutex_lock(&buffer->lock);
  ------------------
  |  |  131|  1.42k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  472|  1.42k|                }
  473|   882k|            }
  474|  1.24M|            if (buffer->num_entries == buffer->capacity) {
  ------------------
  |  Branch (474:17): [True: 128k, False: 1.11M]
  ------------------
  475|   128k|                struct mp_log_buffer_entry *skip = log_buffer_read(buffer);
  476|   128k|                talloc_free(skip);
  ------------------
  |  |   47|   128k|#define talloc_free                     ta_free
  ------------------
  477|   128k|                buffer->dropped += 1;
  478|   128k|            }
  479|  1.24M|            struct mp_log_buffer_entry *entry = talloc_ptrtype(NULL, entry);
  ------------------
  |  |   34|  1.24M|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  1.24M|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  1.24M|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  480|  1.24M|            *entry = (struct mp_log_buffer_entry) {
  481|  1.24M|                .prefix = talloc_strdup(entry, log->verbose_prefix),
  ------------------
  |  |   50|  1.24M|#define talloc_strdup                   ta_xstrdup
  ------------------
  482|  1.24M|                .level = lev,
  483|  1.24M|                .text = bstrdup0(entry, text),
  484|  1.24M|            };
  485|  1.24M|            int pos = (buffer->entry0 + buffer->num_entries) % buffer->capacity;
  486|  1.24M|            buffer->entries[pos] = entry;
  487|  1.24M|            buffer->num_entries += 1;
  488|  1.24M|            if (buffer->wakeup_cb && !buffer->silent)
  ------------------
  |  Branch (488:17): [True: 0, False: 1.24M]
  |  Branch (488:38): [True: 0, False: 0]
  ------------------
  489|      0|                wakeup = true;
  490|  1.24M|        }
  491|  1.76M|        mp_mutex_unlock(&buffer->lock);
  ------------------
  |  |  133|  1.76M|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  492|  1.76M|        if (wakeup)
  ------------------
  |  Branch (492:13): [True: 0, False: 1.76M]
  ------------------
  493|      0|            buffer->wakeup_cb(buffer->wakeup_cb_ctx);
  494|  1.76M|    }
  495|  1.27M|}
msg.c:is_status_output:
  205|   267k|{
  206|   267k|    if (lev == MSGL_STATUS)
  ------------------
  |  Branch (206:9): [True: 3.48k, False: 264k]
  ------------------
  207|  3.48k|        return true;
  208|   264k|    int msg_out = term_msg_fileno(root, lev);
  209|   264k|    int status_out = term_msg_fileno(root, MSGL_STATUS);
  210|   264k|    if (msg_out != status_out && root->isatty[msg_out] != root->isatty[status_out])
  ------------------
  |  Branch (210:9): [True: 0, False: 264k]
  |  Branch (210:34): [True: 0, False: 0]
  ------------------
  211|      0|        return false;
  212|   264k|    return true;
  213|   264k|}
msg.c:destroy_log:
  619|   249k|{
  620|   249k|    struct mp_log *log = ptr;
  621|       |    // This is not managed via talloc itself, because mp_msg calls must be
  622|       |    // thread-safe, while talloc is not thread-safe.
  623|  2.49M|    for (int lvl = 0; lvl <= MSGL_MAX; ++lvl)
  ------------------
  |  Branch (623:23): [True: 2.24M, False: 249k]
  ------------------
  624|  2.24M|        talloc_free(log->partial[lvl].start);
  ------------------
  |  |   47|  2.24M|#define talloc_free                     ta_free
  ------------------
  625|   249k|}
msg.c:check_new_path:
  759|  58.4k|{
  760|  58.4k|    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|  58.4k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  58.4k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  761|  58.4k|    bool res = false;
  762|       |
  763|  58.4k|    char *new_path = mp_get_user_path(tmp, global, opt);
  764|  58.4k|    if (!new_path)
  ------------------
  |  Branch (764:9): [True: 58.3k, False: 39]
  ------------------
  765|  58.3k|        new_path = "";
  766|       |
  767|  58.4k|    char *old_path = *current_path ? *current_path : "";
  ------------------
  |  Branch (767:22): [True: 16, False: 58.4k]
  ------------------
  768|  58.4k|    if (strcmp(old_path, new_path) != 0) {
  ------------------
  |  Branch (768:9): [True: 21, False: 58.4k]
  ------------------
  769|     21|        talloc_free(*current_path);
  ------------------
  |  |   47|     21|#define talloc_free                     ta_free
  ------------------
  770|     21|        *current_path = NULL;
  771|     21|        if (new_path[0])
  ------------------
  |  Branch (771:13): [True: 21, False: 0]
  ------------------
  772|     21|            *current_path = talloc_strdup(NULL, new_path);
  ------------------
  |  |   50|     21|#define talloc_strdup                   ta_xstrdup
  ------------------
  773|     21|        res = true;
  774|     21|    }
  775|       |
  776|  58.4k|    talloc_free(tmp);
  ------------------
  |  |   47|  58.4k|#define talloc_free                     ta_free
  ------------------
  777|       |
  778|  58.4k|    return res;
  779|  58.4k|}
msg.c:terminate_log_file_thread:
  733|  17.0k|{
  734|  17.0k|    bool wait_terminate = false;
  735|       |
  736|  17.0k|    mp_mutex_lock(&root->log_file_lock);
  ------------------
  |  |  131|  17.0k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  737|  17.0k|    if (root->log_file_thread_active) {
  ------------------
  |  Branch (737:9): [True: 0, False: 17.0k]
  ------------------
  738|      0|        root->log_file_thread_active = false;
  739|      0|        mp_cond_broadcast(&root->log_file_wakeup);
  740|      0|        wait_terminate = true;
  741|      0|    }
  742|  17.0k|    mp_mutex_unlock(&root->log_file_lock);
  ------------------
  |  |  133|  17.0k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  743|       |
  744|  17.0k|    if (wait_terminate)
  ------------------
  |  Branch (744:9): [True: 0, False: 17.0k]
  ------------------
  745|      0|        mp_thread_join(root->log_file_thread);
  ------------------
  |  |  212|      0|#define mp_thread_join(t)         pthread_join(t, NULL)
  ------------------
  746|       |
  747|  17.0k|    mp_msg_log_buffer_destroy(root->log_file_buffer);
  748|  17.0k|    root->log_file_buffer = NULL;
  749|       |
  750|  17.0k|    if (root->log_file)
  ------------------
  |  Branch (750:9): [True: 0, False: 17.0k]
  ------------------
  751|      0|        fclose(root->log_file);
  752|  17.0k|    root->log_file = NULL;
  753|  17.0k|}
msg.c:term_msg_fileno:
  195|  5.14M|{
  196|  5.14M|    return root->force_stderr ? STDERR_FILENO : STDOUT_FILENO;
  ------------------
  |  Branch (196:12): [True: 17.8k, False: 5.12M]
  ------------------
  197|  5.14M|}
msg.c:mp_msg_set_early_logging_raw:
  934|  58.4k|{
  935|  58.4k|    struct mp_log_root *root = global->log->root;
  936|  58.4k|    mp_mutex_lock(&root->lock);
  ------------------
  |  |  131|  58.4k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  937|       |
  938|  58.4k|    if (enable != !!*root_logbuf) {
  ------------------
  |  Branch (938:9): [True: 58.4k, False: 0]
  ------------------
  939|  58.4k|        if (enable) {
  ------------------
  |  Branch (939:13): [True: 34.1k, False: 24.2k]
  ------------------
  940|  34.1k|            mp_mutex_unlock(&root->lock);
  ------------------
  |  |  133|  34.1k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  941|  34.1k|            struct mp_log_buffer *buf =
  942|  34.1k|                mp_msg_log_buffer_new(global, size, level, NULL, NULL);
  943|  34.1k|            mp_mutex_lock(&root->lock);
  ------------------
  |  |  131|  34.1k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  944|  34.1k|            mp_assert(!*root_logbuf); // no concurrent calls to this function
  ------------------
  |  |   41|  34.1k|#define mp_assert assert
  ------------------
  945|  34.1k|            *root_logbuf = buf;
  946|  34.1k|        } else {
  947|  24.2k|            struct mp_log_buffer *buf = *root_logbuf;
  948|  24.2k|            *root_logbuf = NULL;
  949|  24.2k|            mp_mutex_unlock(&root->lock);
  ------------------
  |  |  133|  24.2k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  950|  24.2k|            mp_msg_log_buffer_destroy(buf);
  951|  24.2k|            return;
  952|  24.2k|        }
  953|  58.4k|    }
  954|       |
  955|  34.1k|    mp_mutex_unlock(&root->lock);
  ------------------
  |  |  133|  34.1k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  956|  34.1k|}
msg.c:log_buffer_read:
  434|  1.24M|{
  435|  1.24M|    mp_assert(buffer->num_entries);
  ------------------
  |  |   41|  1.24M|#define mp_assert assert
  ------------------
  436|  1.24M|    struct mp_log_buffer_entry *res = buffer->entries[buffer->entry0];
  437|  1.24M|    buffer->entry0 = (buffer->entry0 + 1) % buffer->capacity;
  438|  1.24M|    buffer->num_entries -= 1;
  439|  1.24M|    return res;
  440|  1.24M|}

av_log.c:mp_msg_test:
   64|  7.61k|{
   65|  7.61k|    return lev <= mp_msg_level(log);
   66|  7.61k|}
msg.c:mp_msg_test:
   64|  4.83M|{
   65|  4.83M|    return lev <= mp_msg_level(log);
   66|  4.83M|}
cmd.c:mp_msg_test:
   64|  12.1k|{
   65|  12.1k|    return lev <= mp_msg_level(log);
   66|  12.1k|}
input.c:mp_msg_test:
   64|  2.34M|{
   65|  2.34M|    return lev <= mp_msg_level(log);
   66|  2.34M|}
command.c:mp_msg_test:
   64|    370|{
   65|    370|    return lev <= mp_msg_level(log);
   66|    370|}

playlist_entry_new:
   31|  96.3k|{
   32|  96.3k|    struct playlist_entry *e = talloc_zero(NULL, struct playlist_entry);
  ------------------
  |  |   27|  96.3k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  96.3k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  96.3k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   33|  96.3k|    char *local_filename = mp_file_url_to_filename(e, bstr0(filename));
   34|  96.3k|    e->filename = local_filename ? local_filename : talloc_strdup(e, filename);
  ------------------
  |  |   50|  95.5k|#define talloc_strdup                   ta_xstrdup
  ------------------
  |  Branch (34:19): [True: 813, False: 95.5k]
  ------------------
   35|  96.3k|    e->stream_flags = STREAM_ORIGIN_DIRECT;
  ------------------
  |  |   47|  96.3k|#define STREAM_ORIGIN_DIRECT      (1 << 2) // passed from cmdline or loadfile
  ------------------
   36|  96.3k|    e->original_index = -1;
   37|  96.3k|    return e;
   38|  96.3k|}
playlist_entry_add_param:
   41|  23.2k|{
   42|  23.2k|    struct playlist_param p = {bstrdup(e, name), bstrdup(e, value)};
   43|  23.2k|    MP_TARRAY_APPEND(e, e->params, e->num_params, p);
  ------------------
  |  |  105|  23.2k|    do {                                            \
  |  |  106|  23.2k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  23.2k|    do {                                            \
  |  |  |  |   97|  23.2k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  23.2k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  23.2k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  23.2k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 3.03k, False: 20.2k]
  |  |  |  |  ------------------
  |  |  |  |   99|  23.2k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  3.03k|    do {                                                        \
  |  |  |  |  |  |   89|  3.03k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  3.03k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  3.03k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  3.03k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  3.03k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  3.03k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  3.03k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  23.2k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  23.2k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  23.2k|        (idxvar)++;                                 \
  |  |  109|  23.2k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
   44|  23.2k|}
playlist_entry_add_params:
   49|  1.81k|{
   50|  25.0k|    for (int n = 0; n < num_params; n++)
  ------------------
  |  Branch (50:21): [True: 23.2k, False: 1.81k]
  ------------------
   51|  23.2k|        playlist_entry_add_param(e, params[n].name, params[n].value);
   52|  1.81k|}
playlist_insert_at:
   67|  96.3k|{
   68|  96.3k|    mp_assert(add->filename);
  ------------------
  |  |   41|  96.3k|#define mp_assert assert
  ------------------
   69|  96.3k|    mp_assert(!at || at->pl == pl);
  ------------------
  |  |   41|  96.3k|#define mp_assert assert
  ------------------
   70|       |
   71|  96.3k|    int index = at ? at->pl_index : pl->num_entries;
  ------------------
  |  Branch (71:17): [True: 0, False: 96.3k]
  ------------------
   72|  96.3k|    MP_TARRAY_INSERT_AT(pl, pl->entries, pl->num_entries, index, add);
  ------------------
  |  |  115|  96.3k|    do {                                            \
  |  |  116|  96.3k|        size_t at_ = (at);                          \
  |  |  117|  96.3k|        assert(at_ <= (idxvar));                    \
  |  |  118|  96.3k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  96.3k|    do {                                            \
  |  |  |  |   97|  96.3k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  96.3k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  96.3k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  96.3k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 17.5k, False: 78.7k]
  |  |  |  |  ------------------
  |  |  |  |   99|  96.3k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  17.5k|    do {                                                        \
  |  |  |  |  |  |   89|  17.5k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  17.5k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  17.5k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  17.5k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  17.5k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  17.5k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  17.5k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  96.3k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  119|  96.3k|        memmove((p) + at_ + 1, (p) + at_,           \
  |  |  120|  96.3k|                ((idxvar) - at_) * sizeof((p)[0])); \
  |  |  121|  96.3k|        (idxvar)++;                                 \
  |  |  122|  96.3k|        (p)[at_] = (__VA_ARGS__);                   \
  |  |  123|  96.3k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (123:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
   73|       |
   74|  96.3k|    add->pl = pl;
   75|  96.3k|    add->pl_index = index;
   76|  96.3k|    add->id = ++pl->id_alloc;
   77|       |
   78|  96.3k|    playlist_update_indexes(pl, index, pl->num_entries);
   79|       |
   80|  96.3k|    talloc_steal(pl, add);
  ------------------
  |  |   38|  96.3k|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|  96.3k|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
   81|  96.3k|}
playlist_entry_unref:
   84|  17.0k|{
   85|  17.0k|    e->reserved--;
   86|  17.0k|    if (e->reserved < 0) {
  ------------------
  |  Branch (86:9): [True: 16.6k, False: 405]
  ------------------
   87|  16.6k|        mp_assert(!e->pl);
  ------------------
  |  |   41|  16.6k|#define mp_assert assert
  ------------------
   88|  16.6k|        talloc_free(e);
  ------------------
  |  |   47|  16.6k|#define talloc_free                     ta_free
  ------------------
   89|  16.6k|    }
   90|  17.0k|}
playlist_remove:
   93|  16.6k|{
   94|  16.6k|    mp_assert(pl && entry->pl == pl);
  ------------------
  |  |   41|  16.6k|#define mp_assert assert
  ------------------
   95|       |
   96|  16.6k|    if (pl->current == entry) {
  ------------------
  |  Branch (96:9): [True: 1, False: 16.6k]
  ------------------
   97|      1|        pl->current = playlist_entry_get_rel(entry, 1);
   98|      1|        pl->current_was_replaced = true;
   99|      1|    }
  100|       |
  101|  16.6k|    MP_TARRAY_REMOVE_AT(pl->entries, pl->num_entries, entry->pl_index);
  ------------------
  |  |  143|  16.6k|    do {                                            \
  |  |  144|  16.6k|        size_t at_ = (at);                          \
  |  |  145|  16.6k|        assert(at_ <= (idxvar));                    \
  |  |  146|  16.6k|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|  16.6k|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|  16.6k|        (idxvar)--;                                 \
  |  |  149|  16.6k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  102|  16.6k|    playlist_update_indexes(pl, entry->pl_index, -1);
  103|       |
  104|  16.6k|    entry->pl = NULL;
  105|  16.6k|    entry->pl_index = -1;
  106|  16.6k|    ta_set_parent(entry, NULL);
  107|       |
  108|  16.6k|    entry->removed = true;
  109|  16.6k|    playlist_entry_unref(entry);
  110|  16.6k|}
playlist_clear:
  113|  1.22k|{
  114|  17.8k|    for (int n = pl->num_entries - 1; n >= 0; n--)
  ------------------
  |  Branch (114:39): [True: 16.6k, False: 1.22k]
  ------------------
  115|  16.6k|        playlist_remove(pl, pl->entries[n]);
  116|  1.22k|    mp_assert(!pl->current);
  ------------------
  |  |   41|  1.22k|#define mp_assert assert
  ------------------
  117|  1.22k|    pl->current_was_replaced = false;
  118|  1.22k|    pl->playlist_completed = false;
  119|  1.22k|    pl->playlist_started = false;
  120|  1.22k|    TA_FREEP(&pl->playlist_dir);
  ------------------
  |  |   81|  1.22k|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|  1.22k|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  121|  1.22k|}
playlist_append_file:
  156|  96.3k|{
  157|  96.3k|    playlist_insert_at(pl, playlist_entry_new(filename), NULL);
  158|  96.3k|}
playlist_shuffle:
  170|    173|{
  171|  19.3k|    for (int n = 0; n < pl->num_entries; n++)
  ------------------
  |  Branch (171:21): [True: 19.2k, False: 173]
  ------------------
  172|  19.2k|        pl->entries[n]->original_index = n;
  173|    173|    mp_rand_state s = mp_rand_seed(0);
  174|  19.2k|    for (int n = 0; n < pl->num_entries - 1; n++) {
  ------------------
  |  Branch (174:21): [True: 19.0k, False: 173]
  ------------------
  175|  19.0k|        size_t j = mp_rand_in_range32(&s, n, pl->num_entries);
  176|  19.0k|        MPSWAP(struct playlist_entry *, pl->entries[n], pl->entries[j]);
  ------------------
  |  |   47|  19.0k|    do { type SWAP_tmp = b; b = a; a = SWAP_tmp; } while (0)
  |  |  ------------------
  |  |  |  Branch (47:59): [Folded - Ignored]
  |  |  ------------------
  ------------------
  177|  19.0k|    }
  178|    173|    playlist_update_indexes(pl, 0, -1);
  179|    173|}
playlist_get_first:
  202|  12.2k|{
  203|  12.2k|    return pl->num_entries ? pl->entries[0] : NULL;
  ------------------
  |  Branch (203:12): [True: 7.22k, False: 5.07k]
  ------------------
  204|  12.2k|}
playlist_get_last:
  208|  1.08k|{
  209|  1.08k|    return pl->num_entries ? pl->entries[pl->num_entries - 1] : NULL;
  ------------------
  |  Branch (209:12): [True: 386, False: 697]
  ------------------
  210|  1.08k|}
playlist_get_next:
  213|  3.52k|{
  214|  3.52k|    mp_assert(direction == -1 || direction == +1);
  ------------------
  |  |   41|  3.52k|#define mp_assert assert
  ------------------
  215|  3.52k|    if (!pl->current && pl->playlist_completed && direction < 0) {
  ------------------
  |  Branch (215:9): [True: 0, False: 3.52k]
  |  Branch (215:25): [True: 0, False: 0]
  |  Branch (215:51): [True: 0, False: 0]
  ------------------
  216|      0|        return playlist_entry_from_index(pl, pl->num_entries - 1);
  217|  3.52k|    } else if (!pl->current && !pl->playlist_started && direction > 0) {
  ------------------
  |  Branch (217:16): [True: 0, False: 3.52k]
  |  Branch (217:32): [True: 0, False: 0]
  |  Branch (217:57): [True: 0, False: 0]
  ------------------
  218|      0|        return playlist_entry_from_index(pl, 0);
  219|  3.52k|    } else if (!pl->current) {
  ------------------
  |  Branch (219:16): [True: 0, False: 3.52k]
  ------------------
  220|      0|        return NULL;
  221|      0|    }
  222|  3.52k|    mp_assert(pl->current->pl == pl);
  ------------------
  |  |   41|  3.52k|#define mp_assert assert
  ------------------
  223|  3.52k|    if (direction < 0)
  ------------------
  |  Branch (223:9): [True: 0, False: 3.52k]
  ------------------
  224|      0|        return playlist_entry_get_rel(pl->current, -1);
  225|  3.52k|    return pl->current_was_replaced ? pl->current :
  ------------------
  |  Branch (225:12): [True: 0, False: 3.52k]
  ------------------
  226|  3.52k|           playlist_entry_get_rel(pl->current, 1);
  227|  3.52k|}
playlist_entry_get_rel:
  232|  5.48k|{
  233|  5.48k|    mp_assert(direction == -1 || direction == +1);
  ------------------
  |  |   41|  5.48k|#define mp_assert assert
  ------------------
  234|  5.48k|    if (!e->pl)
  ------------------
  |  Branch (234:9): [True: 0, False: 5.48k]
  ------------------
  235|      0|        return NULL;
  236|  5.48k|    return playlist_entry_from_index(e->pl, e->pl_index + direction);
  237|  5.48k|}
playlist_set_stream_flags:
  322|     86|{
  323|    172|    for (int n = 0; n < pl->num_entries; n++)
  ------------------
  |  Branch (323:21): [True: 86, False: 86]
  ------------------
  324|     86|        pl->entries[n]->stream_flags = flags;
  325|     86|}
playlist_entry_to_index:
  383|    205|{
  384|    205|    if (!e || e->pl != pl)
  ------------------
  |  Branch (384:9): [True: 202, False: 3]
  |  Branch (384:15): [True: 0, False: 3]
  ------------------
  385|    202|        return -1;
  386|      3|    return e->pl_index;
  387|    205|}
playlist_entry_count:
  390|  2.14k|{
  391|  2.14k|    return pl->num_entries;
  392|  2.14k|}
playlist_entry_from_index:
  397|  60.4k|{
  398|  60.4k|    return index >= 0 && index < pl->num_entries ? pl->entries[index] : NULL;
  ------------------
  |  Branch (398:12): [True: 60.4k, False: 0]
  |  Branch (398:26): [True: 60.1k, False: 284]
  ------------------
  399|  60.4k|}
playlist.c:playlist_update_indexes:
   55|   113k|{
   56|   113k|    start = MPMAX(start, 0);
  ------------------
  |  |   43|   113k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 102k, False: 10.2k]
  |  |  ------------------
  ------------------
   57|   113k|    end = end < 0 ? pl->num_entries : MPMIN(end, pl->num_entries);
  ------------------
  |  |   44|   209k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 96.3k]
  |  |  ------------------
  ------------------
  |  Branch (57:11): [True: 16.8k, False: 96.3k]
  ------------------
   58|       |
   59|   228k|    for (int n = start; n < end; n++)
  ------------------
  |  Branch (59:25): [True: 115k, False: 113k]
  ------------------
   60|   115k|        pl->entries[n]->pl_index = n;
   61|   113k|}

stats_global_init:
   81|  17.0k|{
   82|  17.0k|    mp_assert(!global->stats);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
   83|  17.0k|    struct stats_base *stats = talloc_zero(global, struct stats_base);
  ------------------
  |  |   27|  17.0k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  17.0k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   84|  17.0k|    ta_set_destructor(stats, stats_destroy);
   85|  17.0k|    mp_mutex_init(&stats->lock);
   86|       |
   87|  17.0k|    global->stats = stats;
   88|  17.0k|    stats->global = global;
   89|  17.0k|}
stats_ctx_create:
  224|  37.0k|{
  225|  37.0k|    struct stats_base *base = global->stats;
  226|  37.0k|    mp_assert(base);
  ------------------
  |  |   41|  37.0k|#define mp_assert assert
  ------------------
  227|       |
  228|  37.0k|    struct stats_ctx *ctx = talloc_zero(ta_parent, struct stats_ctx);
  ------------------
  |  |   27|  37.0k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  37.0k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  37.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  229|  37.0k|    ctx->base = base;
  230|  37.0k|    ctx->prefix = talloc_strdup(ctx, prefix);
  ------------------
  |  |   50|  37.0k|#define talloc_strdup                   ta_xstrdup
  ------------------
  231|  37.0k|    ta_set_destructor(ctx, stats_ctx_destroy);
  232|       |
  233|  37.0k|    mp_mutex_lock(&base->lock);
  ------------------
  |  |  131|  37.0k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  234|  37.0k|    LL_APPEND(list, &base->list, ctx);
  ------------------
  |  |   44|  37.0k|#define LL_APPEND(field, list, item)  do {                              \
  |  |   45|  37.0k|    (item)->field.prev = (list)->tail;                                  \
  |  |   46|  37.0k|    (item)->field.next = NULL;                                          \
  |  |   47|  37.0k|    LL_RELINK_(field, list, item)                                       \
  |  |  ------------------
  |  |  |  |   98|  37.0k|    if ((item)->field.prev) {                                           \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:9): [True: 19.9k, False: 17.0k]
  |  |  |  |  ------------------
  |  |  |  |   99|  19.9k|        (item)->field.prev->field.next = (item);                        \
  |  |  |  |  100|  19.9k|    } else {                                                            \
  |  |  |  |  101|  17.0k|        (list)->head = (item);                                          \
  |  |  |  |  102|  17.0k|    }                                                                   \
  |  |  |  |  103|  37.0k|    if ((item)->field.next) {                                           \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (103:9): [True: 0, False: 37.0k]
  |  |  |  |  ------------------
  |  |  |  |  104|      0|        (item)->field.next->field.prev = (item);                        \
  |  |  |  |  105|  37.0k|    } else {                                                            \
  |  |  |  |  106|  37.0k|        (list)->tail = (item);                                          \
  |  |  |  |  107|  37.0k|    }
  |  |  ------------------
  |  |   48|  37.0k|} while (0)
  |  |  ------------------
  |  |  |  Branch (48:10): [Folded - Ignored]
  |  |  ------------------
  ------------------
  235|  37.0k|    base->num_entries = 0; // invalidate
  236|  37.0k|    mp_mutex_unlock(&base->lock);
  ------------------
  |  |  133|  37.0k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  237|       |
  238|  37.0k|    return ctx;
  239|  37.0k|}
stats_time_start:
  283|    450|{
  284|    450|    MP_STATS(ctx->base->global, "start %s", name);
  ------------------
  |  |   95|    450|#define MP_STATS(obj, ...)      MP_MSG(obj, MSGL_STATS, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    450|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  285|    450|    if (!IS_ACTIVE(ctx))
  ------------------
  |  |   68|    450|    (atomic_load_explicit(&(ctx)->base->active, memory_order_relaxed))
  ------------------
  |  Branch (285:9): [True: 450, False: 0]
  ------------------
  286|    450|        return;
  287|      0|    mp_mutex_lock(&ctx->base->lock);
  ------------------
  |  |  131|      0|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  288|      0|    struct stat_entry *e = find_entry(ctx, name);
  289|      0|    e->type = VAL_TIME;
  290|      0|    e->thread_id = mp_thread_current_id();
  ------------------
  |  |  214|      0|#define mp_thread_current_id      pthread_self
  ------------------
  291|      0|    e->cpu_start_ns = mp_thread_cpu_time_ns(e->thread_id);
  292|      0|    e->time_start_ns = mp_time_ns();
  293|      0|    mp_mutex_unlock(&ctx->base->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  294|      0|}
stats_time_end:
  297|    450|{
  298|    450|    MP_STATS(ctx->base->global, "end %s", name);
  ------------------
  |  |   95|    450|#define MP_STATS(obj, ...)      MP_MSG(obj, MSGL_STATS, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    450|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  299|    450|    if (!IS_ACTIVE(ctx))
  ------------------
  |  |   68|    450|    (atomic_load_explicit(&(ctx)->base->active, memory_order_relaxed))
  ------------------
  |  Branch (299:9): [True: 450, False: 0]
  ------------------
  300|    450|        return;
  301|      0|    mp_mutex_lock(&ctx->base->lock);
  ------------------
  |  |  131|      0|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  302|      0|    struct stat_entry *e = find_entry(ctx, name);
  303|      0|    if (e->type == VAL_TIME && e->time_start_ns) {
  ------------------
  |  Branch (303:9): [True: 0, False: 0]
  |  Branch (303:32): [True: 0, False: 0]
  ------------------
  304|      0|        e->val_th += mp_thread_cpu_time_ns(e->thread_id) - e->cpu_start_ns;
  305|      0|        e->val_rt += mp_time_ns() - e->time_start_ns;
  306|      0|        e->time_start_ns = 0;
  307|      0|    }
  308|      0|    mp_mutex_unlock(&ctx->base->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  309|      0|}
stats_event:
  312|  19.4k|{
  313|  19.4k|    if (!IS_ACTIVE(ctx))
  ------------------
  |  |   68|  19.4k|    (atomic_load_explicit(&(ctx)->base->active, memory_order_relaxed))
  ------------------
  |  Branch (313:9): [True: 19.4k, False: 0]
  ------------------
  314|  19.4k|        return;
  315|      0|    mp_mutex_lock(&ctx->base->lock);
  ------------------
  |  |  131|      0|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  316|      0|    struct stat_entry *e = find_entry(ctx, name);
  317|      0|    e->val_d += 1;
  318|      0|    e->type = VAL_INC;
  319|      0|    mp_mutex_unlock(&ctx->base->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  320|      0|}
stats_register_thread_cputime:
  333|  12.1k|{
  334|  12.1k|    register_thread(ctx, name, VAL_THREAD_CPU_TIME);
  335|  12.1k|}
stats.c:stats_destroy:
   71|  17.0k|{
   72|  17.0k|    struct stats_base *stats = p;
   73|       |
   74|       |    // All entries must have been destroyed before this.
   75|  17.0k|    mp_assert(!stats->list.head);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
   76|       |
   77|  17.0k|    mp_mutex_destroy(&stats->lock);
  ------------------
  |  |  130|  17.0k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
   78|  17.0k|}
stats.c:stats_ctx_destroy:
  213|  37.0k|{
  214|  37.0k|    struct stats_ctx *ctx = p;
  215|       |
  216|  37.0k|    mp_mutex_lock(&ctx->base->lock);
  ------------------
  |  |  131|  37.0k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  217|  37.0k|    LL_REMOVE(list, &ctx->base->list, ctx);
  ------------------
  |  |   78|  37.0k|#define LL_REMOVE(field, list, item) do {                               \
  |  |   79|  37.0k|    if ((item)->field.prev) {                                           \
  |  |  ------------------
  |  |  |  Branch (79:9): [True: 19.9k, False: 17.0k]
  |  |  ------------------
  |  |   80|  19.9k|        (item)->field.prev->field.next = (item)->field.next;            \
  |  |   81|  19.9k|    } else {                                                            \
  |  |   82|  17.0k|        (list)->head = (item)->field.next;                              \
  |  |   83|  17.0k|    }                                                                   \
  |  |   84|  37.0k|    if ((item)->field.next) {                                           \
  |  |  ------------------
  |  |  |  Branch (84:9): [True: 116, False: 36.9k]
  |  |  ------------------
  |  |   85|    116|        (item)->field.next->field.prev = (item)->field.prev;            \
  |  |   86|  36.9k|    } else {                                                            \
  |  |   87|  36.9k|        (list)->tail = (item)->field.prev;                              \
  |  |   88|  36.9k|    }                                                                   \
  |  |   89|  37.0k|} while (0)
  |  |  ------------------
  |  |  |  Branch (89:10): [Folded - Ignored]
  |  |  ------------------
  ------------------
  218|  37.0k|    ctx->base->num_entries = 0; // invalidate
  219|  37.0k|    mp_mutex_unlock(&ctx->base->lock);
  ------------------
  |  |  133|  37.0k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  220|  37.0k|}
stats.c:find_entry:
  242|  12.1k|{
  243|  12.1k|    for (int n = 0; n < ctx->num_entries; n++) {
  ------------------
  |  Branch (243:21): [True: 0, False: 12.1k]
  ------------------
  244|      0|        if (strcmp(ctx->entries[n]->name, name) == 0)
  ------------------
  |  Branch (244:13): [True: 0, False: 0]
  ------------------
  245|      0|            return ctx->entries[n];
  246|      0|    }
  247|       |
  248|  12.1k|    struct stat_entry *e = talloc_zero(ctx, struct stat_entry);
  ------------------
  |  |   27|  12.1k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  12.1k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  12.1k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  249|  12.1k|    snprintf(e->name, sizeof(e->name), "%s", name);
  250|  12.1k|    mp_assert(strcmp(e->name, name) == 0); // make e->name larger and don't complain
  ------------------
  |  |   41|  12.1k|#define mp_assert assert
  ------------------
  251|       |
  252|  12.1k|    e->full_name = talloc_asprintf(e, "%s/%s", ctx->prefix, e->name);
  ------------------
  |  |   52|  12.1k|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|  12.1k|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  253|       |
  254|  12.1k|    MP_TARRAY_APPEND(ctx, ctx->entries, ctx->num_entries, e);
  ------------------
  |  |  105|  12.1k|    do {                                            \
  |  |  106|  12.1k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  12.1k|    do {                                            \
  |  |  |  |   97|  12.1k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  12.1k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  12.1k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  12.1k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 12.1k, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|  12.1k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  12.1k|    do {                                                        \
  |  |  |  |  |  |   89|  12.1k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  12.1k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  12.1k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  12.1k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  12.1k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  12.1k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  12.1k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  12.1k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  12.1k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  12.1k|        (idxvar)++;                                 \
  |  |  109|  12.1k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  255|  12.1k|    ctx->base->num_entries = 0; // invalidate
  256|       |
  257|  12.1k|    return e;
  258|  12.1k|}
stats.c:register_thread:
  324|  12.1k|{
  325|  12.1k|    mp_mutex_lock(&ctx->base->lock);
  ------------------
  |  |  131|  12.1k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  326|  12.1k|    struct stat_entry *e = find_entry(ctx, name);
  327|  12.1k|    e->type = type;
  328|  12.1k|    e->thread_id = mp_thread_current_id();
  ------------------
  |  |  214|  12.1k|#define mp_thread_current_id      pthread_self
  ------------------
  329|  12.1k|    mp_mutex_unlock(&ctx->base->lock);
  ------------------
  |  |  133|  12.1k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  330|  12.1k|}

mp_tags_set_str:
   27|    162|{
   28|    162|    mp_tags_set_bstr(tags, bstr0(key), bstr0(value));
   29|    162|}
mp_tags_set_bstr:
   32|    162|{
   33|    162|    for (int n = 0; n < tags->num_keys; n++) {
  ------------------
  |  Branch (33:21): [True: 0, False: 162]
  ------------------
   34|      0|        if (bstrcasecmp0(key, tags->keys[n]) == 0) {
  ------------------
  |  Branch (34:13): [True: 0, False: 0]
  ------------------
   35|      0|            talloc_free(tags->values[n]);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
   36|      0|            tags->values[n] = bstrto0(tags, value);
   37|      0|            return;
   38|      0|        }
   39|      0|    }
   40|       |
   41|    162|    MP_RESIZE_ARRAY(tags, tags->keys,   tags->num_keys + 1);
  ------------------
  |  |   88|    162|    do {                                                        \
  |  |   89|    162|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  ------------------
  |  |  |  |  158|    162|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|    162|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|    162|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|    162|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   90|    162|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |   91|    162|    } while (0)
  |  |  ------------------
  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
   42|    162|    MP_RESIZE_ARRAY(tags, tags->values, tags->num_keys + 1);
  ------------------
  |  |   88|    162|    do {                                                        \
  |  |   89|    162|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  ------------------
  |  |  |  |  158|    162|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|    162|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|    162|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|    162|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   90|    162|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |   91|    162|    } while (0)
  |  |  ------------------
  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
   43|    162|    tags->keys[tags->num_keys]   = bstrto0(tags, key);
   44|    162|    tags->values[tags->num_keys] = bstrto0(tags, value);
   45|    162|    tags->num_keys++;
   46|    162|}
mp_tags_get_str:
   67|    378|{
   68|    378|    return mp_tags_get_bstr(tags, bstr0(key));
   69|    378|}
mp_tags_get_bstr:
   72|    378|{
   73|    385|    for (int n = 0; n < tags->num_keys; n++) {
  ------------------
  |  Branch (73:21): [True: 7, False: 378]
  ------------------
   74|      7|        if (bstrcasecmp0(key, tags->keys[n]) == 0)
  ------------------
  |  Branch (74:13): [True: 0, False: 7]
  ------------------
   75|      0|            return tags->values[n];
   76|      7|    }
   77|    378|    return NULL;
   78|    378|}
mp_tags_clear:
   81|    321|{
   82|    321|    *tags = (struct mp_tags){0};
   83|    321|    talloc_free_children(tags);
  ------------------
  |  |   46|    321|#define talloc_free_children            ta_free_children
  ------------------
   84|    321|}
mp_tags_dup:
   89|    321|{
   90|    321|    struct mp_tags *new = talloc_zero(tparent, struct mp_tags);
  ------------------
  |  |   27|    321|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    321|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    321|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   91|    321|    mp_tags_replace(new, tags);
   92|    321|    return new;
   93|    321|}
mp_tags_replace:
   96|    321|{
   97|    321|    mp_tags_clear(dst);
   98|    321|    MP_RESIZE_ARRAY(dst, dst->keys,   src->num_keys);
  ------------------
  |  |   88|    321|    do {                                                        \
  |  |   89|    321|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  ------------------
  |  |  |  |  158|    321|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|    321|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|    321|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|    321|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   90|    321|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |   91|    321|    } while (0)
  |  |  ------------------
  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
   99|    321|    MP_RESIZE_ARRAY(dst, dst->values, src->num_keys);
  ------------------
  |  |   88|    321|    do {                                                        \
  |  |   89|    321|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  ------------------
  |  |  |  |  158|    321|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|    321|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|    321|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|    321|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   90|    321|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |   91|    321|    } while (0)
  |  |  ------------------
  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  100|    321|    dst->num_keys = src->num_keys;
  101|    328|    for (int n = 0; n < src->num_keys; n++) {
  ------------------
  |  Branch (101:21): [True: 7, False: 321]
  ------------------
  102|      7|        dst->keys[n] = talloc_strdup(dst, src->keys[n]);
  ------------------
  |  |   50|      7|#define talloc_strdup                   ta_xstrdup
  ------------------
  103|      7|        dst->values[n] = talloc_strdup(dst, src->values[n]);
  ------------------
  |  |   50|      7|#define talloc_strdup                   ta_xstrdup
  ------------------
  104|      7|    }
  105|    321|}
mp_tags_merge:
  133|     21|{
  134|     21|    for (int n = 0; n < src->num_keys; n++)
  ------------------
  |  Branch (134:21): [True: 0, False: 21]
  ------------------
  135|      0|        mp_tags_set_str(tags, src->keys[n], src->values[n]);
  136|     21|}
mp_tags_copy_from_av_dictionary:
  140|    155|{
  141|    155|    AVDictionaryEntry *entry = NULL;
  142|    162|    while ((entry = av_dict_get(av_dict, "", entry, AV_DICT_IGNORE_SUFFIX)))
  ------------------
  |  Branch (142:12): [True: 7, False: 155]
  ------------------
  143|      7|        mp_tags_set_str(tags, entry->key, entry->value);
  144|    155|}
mp_tags_move_from_av_dictionary:
  148|    155|{
  149|    155|    mp_tags_copy_from_av_dictionary(tags, *av_dict_ptr);
  150|    155|    av_dict_free(av_dict_ptr);
  151|    155|}

mp_map_mimetype_to_video_codec:
  197|     48|{
  198|     48|    if (mimetype) {
  ------------------
  |  Branch (198:9): [True: 0, False: 48]
  ------------------
  199|      0|        for (int n = 0; mimetype_to_codec[n][0]; n++) {
  ------------------
  |  Branch (199:25): [True: 0, False: 0]
  ------------------
  200|      0|            if (strcasecmp(mimetype_to_codec[n][0], mimetype) == 0)
  ------------------
  |  Branch (200:17): [True: 0, False: 0]
  ------------------
  201|      0|                return mimetype_to_codec[n][1];
  202|      0|        }
  203|      0|    }
  204|     48|    return NULL;
  205|     48|}

mp_probe_cue:
  180|    295|{
  181|    295|    bool valid = false;
  182|    295|    data = skip_utf8_bom(data);
  183|    295|    for (;;) {
  184|    295|        enum cue_command cmd = read_cmd(&data, NULL);
  185|       |        // End reached. Since the line was most likely cut off, don't use the
  186|       |        // result of the last parsing call.
  187|    295|        if (data.len == 0)
  ------------------
  |  Branch (187:13): [True: 295, False: 0]
  ------------------
  188|    295|            break;
  189|      0|        if (cmd == CUE_ERROR)
  ------------------
  |  Branch (189:13): [True: 0, False: 0]
  ------------------
  190|      0|            return false;
  191|      0|        if (cmd != CUE_EMPTY)
  ------------------
  |  Branch (191:13): [True: 0, False: 0]
  ------------------
  192|      0|            valid = true;
  193|      0|    }
  194|    295|    return valid;
  195|    295|}
cue.c:skip_utf8_bom:
  172|    295|{
  173|    295|    return bstr_startswith0(data, "\xEF\xBB\xBF") ? bstr_cut(data, 3) : data;
  ------------------
  |  Branch (173:12): [True: 1, False: 294]
  ------------------
  174|    295|}
cue.c:read_cmd:
   91|    295|{
   92|    295|    struct bstr line = bstr_strip_linebreaks(bstr_getline(*data, data));
   93|    295|    line = lstrip_whitespace(line);
   94|    295|    if (line.len == 0)
  ------------------
  |  Branch (94:9): [True: 1, False: 294]
  ------------------
   95|      1|        return CUE_EMPTY;
   96|  4.41k|    for (int n = 0; cue_command_strings[n].command != -1; n++) {
  ------------------
  |  Branch (96:21): [True: 4.11k, False: 294]
  ------------------
   97|  4.11k|        struct bstr name = bstr0(cue_command_strings[n].text);
   98|  4.11k|        if (bstr_case_startswith(line, name)) {
  ------------------
  |  Branch (98:13): [True: 0, False: 4.11k]
  ------------------
   99|      0|            struct bstr rest = bstr_cut(line, name.len);
  100|      0|            struct bstr par = lstrip_whitespace(rest);
  101|      0|            if (rest.len && par.len == rest.len)
  ------------------
  |  Branch (101:17): [True: 0, False: 0]
  |  Branch (101:29): [True: 0, False: 0]
  ------------------
  102|      0|                continue;
  103|      0|            if (out_params)
  ------------------
  |  Branch (103:17): [True: 0, False: 0]
  ------------------
  104|      0|                *out_params = par;
  105|      0|            return cue_command_strings[n].command;
  106|      0|        }
  107|  4.11k|    }
  108|    294|    return CUE_ERROR;
  109|    294|}
cue.c:lstrip_whitespace:
   68|    295|{
   69|    295|    while (data.len) {
  ------------------
  |  Branch (69:12): [True: 294, False: 1]
  ------------------
   70|    294|        bstr rest = data;
   71|    294|        int code = bstr_decode_utf8(data, &rest);
   72|    294|        if (code < 0) {
  ------------------
  |  Branch (72:13): [True: 41, False: 253]
  ------------------
   73|       |            // Tolerate Latin1 => probing works (which doesn't convert charsets).
   74|     41|            code = data.start[0];
   75|     41|            rest.start += 1;
   76|     41|            rest.len -= 1;
   77|     41|        }
   78|  2.35k|        for (size_t n = 0; n < MP_ARRAY_SIZE(spaces); n++) {
  ------------------
  |  |   48|  2.35k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (78:28): [True: 2.05k, False: 294]
  ------------------
   79|  2.05k|            if (spaces[n] == code) {
  ------------------
  |  Branch (79:17): [True: 0, False: 2.05k]
  ------------------
   80|      0|                data = rest;
   81|      0|                goto next;
   82|      0|            }
   83|  2.05k|        }
   84|    294|        break;
   85|    294|    next: ;
   86|      0|    }
   87|    295|    return data;
   88|    295|}

demux_alloc_sh_stream:
  950|     81|{
  951|     81|    struct sh_stream *sh = talloc_ptrtype(NULL, sh);
  ------------------
  |  |   34|     81|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|     81|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     81|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  952|     81|    *sh = (struct sh_stream) {
  953|     81|        .type = type,
  954|     81|        .index = -1,
  955|     81|        .ff_index = -1,     // may be overwritten by demuxer
  956|     81|        .demuxer_id = -1,   // ... same
  957|     81|        .program_id = -1,   // ... same
  958|     81|        .codec = talloc_zero(sh, struct mp_codec_params),
  ------------------
  |  |   27|     81|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|     81|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     81|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  959|     81|        .tags = talloc_zero(sh, struct mp_tags),
  ------------------
  |  |   27|     81|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|     81|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     81|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  960|     81|    };
  961|     81|    sh->codec->type = type;
  962|     81|    return sh;
  963|     81|}
demux_add_sh_stream:
 1036|     81|{
 1037|     81|    struct demux_internal *in = demuxer->in;
 1038|     81|    mp_assert(demuxer == in->d_thread);
  ------------------
  |  |   41|     81|#define mp_assert assert
  ------------------
 1039|     81|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|     81|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1040|     81|    demux_add_sh_stream_locked(in, sh);
 1041|     81|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|     81|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1042|     81|}
demux_get_stream:
 1049|     40|{
 1050|     40|    struct demux_internal *in = demuxer->in;
 1051|     40|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|     40|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1052|     40|    mp_assert(index >= 0 && index < in->num_streams);
  ------------------
  |  |   41|     40|#define mp_assert assert
  ------------------
 1053|     40|    struct sh_stream *r = in->streams[index];
 1054|     40|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|     40|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1055|     40|    return r;
 1056|     40|}
demux_get_num_stream:
 1060|    148|{
 1061|    148|    struct demux_internal *in = demuxer->in;
 1062|    148|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|    148|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1063|    148|    int r = in->num_streams;
 1064|    148|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|    148|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1065|    148|    return r;
 1066|    148|}
demux_free:
 1109|  3.12k|{
 1110|  3.12k|    if (!demuxer)
  ------------------
  |  Branch (1110:9): [True: 304, False: 2.81k]
  ------------------
 1111|    304|        return;
 1112|  2.81k|    struct demux_internal *in = demuxer->in;
 1113|  2.81k|    mp_assert(demuxer == in->d_user);
  ------------------
  |  |   41|  2.81k|#define mp_assert assert
  ------------------
 1114|       |
 1115|  2.81k|    demux_stop_thread(demuxer);
 1116|  2.81k|    demux_shutdown(in);
 1117|  2.81k|    demux_dealloc(in);
 1118|  2.81k|}
demux_cancel_and_free:
 1179|    161|{
 1180|    161|    if (!demuxer)
  ------------------
  |  Branch (1180:9): [True: 0, False: 161]
  ------------------
 1181|      0|        return;
 1182|    161|    mp_cancel_trigger(demuxer->cancel);
 1183|    161|    demux_free(demuxer);
 1184|    161|}
demux_stop_thread:
 1200|  2.81k|{
 1201|  2.81k|    struct demux_internal *in = demuxer->in;
 1202|  2.81k|    mp_assert(demuxer == in->d_user);
  ------------------
  |  |   41|  2.81k|#define mp_assert assert
  ------------------
 1203|       |
 1204|  2.81k|    if (in->threading) {
  ------------------
  |  Branch (1204:9): [True: 0, False: 2.81k]
  ------------------
 1205|      0|        mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|      0|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1206|      0|        in->thread_terminate = true;
 1207|      0|        mp_cond_signal(&in->wakeup);
 1208|      0|        mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1209|      0|        mp_thread_join(in->thread);
  ------------------
  |  |  212|      0|#define mp_thread_join(t)         pthread_join(t, NULL)
  ------------------
 1210|      0|        in->threading = false;
 1211|      0|        in->thread_terminate = false;
 1212|      0|    }
 1213|  2.81k|}
stream_type_name:
 1237|      1|{
 1238|      1|    switch (type) {
 1239|      1|    case STREAM_VIDEO:  return "video";
  ------------------
  |  Branch (1239:5): [True: 1, False: 0]
  ------------------
 1240|      0|    case STREAM_AUDIO:  return "audio";
  ------------------
  |  Branch (1240:5): [True: 0, False: 1]
  ------------------
 1241|      0|    case STREAM_SUB:    return "sub";
  ------------------
  |  Branch (1241:5): [True: 0, False: 1]
  ------------------
 1242|      0|    default:            return "unknown";
  ------------------
  |  Branch (1242:5): [True: 0, False: 1]
  ------------------
 1243|      1|    }
 1244|      1|}
demuxer_help:
 2829|      1|{
 2830|      1|    int i;
 2831|       |
 2832|      1|    mp_info(log, "Available demuxers:\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2833|      1|    mp_info(log, " demuxer:   info:\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2834|     13|    for (i = 0; demuxer_list[i]; i++) {
  ------------------
  |  Branch (2834:17): [True: 12, False: 1]
  ------------------
 2835|     12|        mp_info(log, "%10s  %s\n",
  ------------------
  |  |   74|     12|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2836|     12|                demuxer_list[i]->name, demuxer_list[i]->desc);
 2837|     12|    }
 2838|      1|    mp_info(log, "\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2839|       |
 2840|      1|    return M_OPT_EXIT;
  ------------------
  |  |  533|      1|#define M_OPT_EXIT              -6
  ------------------
 2841|      1|}
demux_update:
 3142|    321|{
 3143|    321|    mp_assert(demuxer == demuxer->in->d_user);
  ------------------
  |  |   41|    321|#define mp_assert assert
  ------------------
 3144|    321|    struct demux_internal *in = demuxer->in;
 3145|       |
 3146|    321|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|    321|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 3147|       |
 3148|    321|    if (!in->threading)
  ------------------
  |  Branch (3148:9): [True: 321, False: 0]
  ------------------
 3149|    321|        update_cache(in);
 3150|       |
 3151|       |    // This implies this function is actually called from "the" user thread.
 3152|    321|    in->d_user->filesize = in->stream_size;
 3153|       |
 3154|    321|    pts = MP_ADD_PTS(pts, -in->ts_offset);
  ------------------
  |  |   66|    321|#define MP_ADD_PTS(a, b) ((a) == MP_NOPTS_VALUE ? (a) : ((a) + (b)))
  |  |  ------------------
  |  |  |  |   38|    321|#define MP_NOPTS_VALUE (-0x1p+63)
  |  |  ------------------
  |  |  |  Branch (66:27): [True: 321, False: 0]
  |  |  ------------------
  ------------------
 3155|       |
 3156|    321|    struct timed_metadata *prev = lookup_timed_metadata(in, in->last_playback_pts);
 3157|    321|    struct timed_metadata *cur = lookup_timed_metadata(in, pts);
 3158|    321|    if (prev != cur || in->force_metadata_update) {
  ------------------
  |  Branch (3158:9): [True: 0, False: 321]
  |  Branch (3158:24): [True: 321, False: 0]
  ------------------
 3159|    321|        in->force_metadata_update = false;
 3160|    321|        update_final_metadata(demuxer, cur);
 3161|    321|        demuxer->events |= DEMUX_EVENT_METADATA;
 3162|    321|    }
 3163|       |
 3164|    321|    in->last_playback_pts = pts;
 3165|       |
 3166|    321|    demuxer->events |= in->events;
 3167|    321|    in->events = 0;
 3168|    321|    if (demuxer->events & (DEMUX_EVENT_METADATA | DEMUX_EVENT_STREAMS))
  ------------------
  |  Branch (3168:9): [True: 321, False: 0]
  ------------------
 3169|    321|        demux_update_replaygain(demuxer);
 3170|    321|    if (demuxer->events & DEMUX_EVENT_DURATION)
  ------------------
  |  Branch (3170:9): [True: 321, False: 0]
  ------------------
 3171|    321|        demuxer->duration = in->duration;
 3172|       |
 3173|    321|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|    321|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 3174|    321|}
demux_close_stream:
 3211|    114|{
 3212|    114|    struct demux_internal *in = demuxer->in;
 3213|    114|    mp_assert(!in->threading && demuxer == in->d_thread);
  ------------------
  |  |   41|    114|#define mp_assert assert
  ------------------
 3214|       |
 3215|    114|    if (!demuxer->stream || !in->owns_stream)
  ------------------
  |  Branch (3215:9): [True: 0, False: 114]
  |  Branch (3215:29): [True: 0, False: 114]
  ------------------
 3216|      0|        return;
 3217|       |
 3218|    114|    MP_VERBOSE(demuxer, "demuxer read all data; closing stream\n");
  ------------------
  |  |   88|    114|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    114|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 3219|    114|    free_stream(demuxer->stream);
 3220|    114|    demuxer->stream = NULL;
 3221|    114|    in->d_user->stream = NULL;
 3222|    114|}
demux_open_url:
 3482|    653|{
 3483|    653|    if (!params)
  ------------------
  |  Branch (3483:9): [True: 0, False: 653]
  ------------------
 3484|      0|        return NULL;
 3485|    653|    struct mp_cancel *priv_cancel = mp_cancel_new(NULL);
 3486|    653|    if (cancel)
  ------------------
  |  Branch (3486:9): [True: 653, False: 0]
  ------------------
 3487|    653|        mp_cancel_set_parent(priv_cancel, cancel);
 3488|    653|    struct stream *s = params->external_stream;
 3489|    653|    if (!s) {
  ------------------
  |  Branch (3489:9): [True: 653, False: 0]
  ------------------
 3490|    653|        s = stream_create(url, STREAM_READ | params->stream_flags,
  ------------------
  |  |   41|    653|#define STREAM_READ               0
  ------------------
 3491|    653|                          priv_cancel, global);
 3492|    653|        if (s && params->init_fragment.len) {
  ------------------
  |  Branch (3492:13): [True: 609, False: 44]
  |  Branch (3492:18): [True: 0, False: 609]
  ------------------
 3493|      0|            s = create_webshit_concat_stream(global, priv_cancel,
 3494|      0|                                             params->init_fragment, s);
 3495|      0|        }
 3496|    653|    }
 3497|    653|    if (!s) {
  ------------------
  |  Branch (3497:9): [True: 44, False: 609]
  ------------------
 3498|     44|        talloc_free(priv_cancel);
  ------------------
  |  |   47|     44|#define talloc_free                     ta_free
  ------------------
 3499|     44|        return NULL;
 3500|     44|    }
 3501|    609|    struct demuxer *d = demux_open(s, priv_cancel, params, global);
 3502|    609|    if (d) {
  ------------------
  |  Branch (3502:9): [True: 303, False: 306]
  ------------------
 3503|    303|        talloc_steal(d->in, priv_cancel);
  ------------------
  |  |   38|    303|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|    303|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 3504|    303|        mp_assert(d->cancel);
  ------------------
  |  |   41|    303|#define mp_assert assert
  ------------------
 3505|    306|    } else {
 3506|    306|        params->demuxer_failed = true;
 3507|    306|        if (!params->external_stream)
  ------------------
  |  Branch (3507:13): [True: 306, False: 0]
  ------------------
 3508|    306|            free_stream(s);
 3509|    306|        talloc_free(priv_cancel);
  ------------------
  |  |   47|    306|#define talloc_free                     ta_free
  ------------------
 3510|    306|    }
 3511|    609|    return d;
 3512|    609|}
demux_flush:
 3516|  2.81k|{
 3517|  2.81k|    struct demux_internal *in = demuxer->in;
 3518|  2.81k|    mp_assert(demuxer == in->d_user);
  ------------------
  |  |   41|  2.81k|#define mp_assert assert
  ------------------
 3519|       |
 3520|  2.81k|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|  2.81k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 3521|  2.81k|    clear_reader_state(in, true);
 3522|  3.13k|    for (int n = 0; n < in->num_ranges; n++)
  ------------------
  |  Branch (3522:21): [True: 321, False: 2.81k]
  ------------------
 3523|    321|        clear_cached_range(in, in->ranges[n]);
 3524|  2.81k|    free_empty_cached_ranges(in);
 3525|  2.89k|    for (int n = 0; n < in->num_streams; n++) {
  ------------------
  |  Branch (3525:21): [True: 81, False: 2.81k]
  ------------------
 3526|     81|        struct demux_stream *ds = in->streams[n]->ds;
 3527|     81|        ds->refreshing = false;
 3528|     81|        ds->eof = false;
 3529|     81|    }
 3530|  2.81k|    in->eof = false;
 3531|  2.81k|    in->seeking = false;
 3532|  2.81k|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|  2.81k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 3533|  2.81k|}
demuxer_select_track:
 4008|     14|{
 4009|     14|    struct demux_internal *in = demuxer->in;
 4010|     14|    struct demux_stream *ds = stream->ds;
 4011|     14|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|     14|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 4012|       |    // don't flush buffers if stream is already selected / unselected
 4013|     14|    if (ds->selected != selected) {
  ------------------
  |  Branch (4013:9): [True: 0, False: 14]
  ------------------
 4014|      0|        MP_VERBOSE(in, "%sselect track %d\n", selected ? "" : "de", stream->index);
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4015|      0|        ds->selected = selected;
 4016|      0|        update_stream_selection_state(in, ds);
 4017|      0|        in->tracks_switched = true;
 4018|      0|        if (ds->selected)
  ------------------
  |  Branch (4018:13): [True: 0, False: 0]
  ------------------
 4019|      0|            refresh_track(in, stream, ref_pts);
 4020|      0|        if (in->threading) {
  ------------------
  |  Branch (4020:13): [True: 0, False: 0]
  ------------------
 4021|      0|            mp_cond_signal(&in->wakeup);
 4022|      0|        } else {
 4023|      0|            execute_trackswitch(in);
 4024|      0|        }
 4025|      0|    }
 4026|     14|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|     14|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 4027|     14|}
demux_stream_is_selected:
 4049|     78|{
 4050|     78|    if (!stream)
  ------------------
  |  Branch (4050:9): [True: 0, False: 78]
  ------------------
 4051|      0|        return false;
 4052|     78|    bool r = false;
 4053|     78|    mp_mutex_lock(&stream->ds->in->lock);
  ------------------
  |  |  131|     78|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 4054|     78|    r = stream->ds->selected;
 4055|     78|    mp_mutex_unlock(&stream->ds->in->lock);
  ------------------
  |  |  133|     78|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 4056|     78|    return r;
 4057|     78|}
demux_report_unbuffered_read_bytes:
 4464|     14|{
 4465|     14|    struct demux_internal *in = demuxer->in;
 4466|     14|    mp_assert(demuxer == in->d_thread);
  ------------------
  |  |   41|     14|#define mp_assert assert
  ------------------
 4467|       |
 4468|     14|    in->slave_unbuffered_read_bytes += new;
 4469|     14|}
demux_get_bytes_read_hack:
 4474|     14|{
 4475|     14|    struct demux_internal *in = demuxer->in;
 4476|       |
 4477|       |    // Required because demuxer==in->d_user, and we access in->d_thread.
 4478|       |    // Locking won't solve this, because we also need to access struct stream.
 4479|     14|    mp_assert(!in->threading);
  ------------------
  |  |   41|     14|#define mp_assert assert
  ------------------
 4480|       |
 4481|     14|    update_bytes_read(in);
 4482|       |
 4483|     14|    int64_t res = in->hack_unbuffered_read_bytes;
 4484|     14|    in->hack_unbuffered_read_bytes = 0;
 4485|     14|    return res;
 4486|     14|}
demux_cancel_test:
 4595|    161|{
 4596|    161|    return mp_cancel_test(demuxer->cancel);
 4597|    161|}
demux.c:demux_add_sh_stream_locked:
  970|     81|{
  971|     81|    mp_assert(!sh->ds); // must not be added yet
  ------------------
  |  |   41|     81|#define mp_assert assert
  ------------------
  972|       |
  973|     81|    sh->index = in->num_streams;
  974|       |
  975|     81|    sh->ds = talloc(sh, struct demux_stream);
  ------------------
  |  |   26|     81|#define talloc                          ta_xnew
  |  |  ------------------
  |  |  |  |  133|     81|#define ta_xnew(...)                    ta_oom_g(ta_new(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     81|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  976|     81|    *sh->ds = (struct demux_stream) {
  977|     81|        .in = in,
  978|     81|        .sh = sh,
  979|     81|        .type = sh->type,
  980|     81|        .index = sh->index,
  981|     81|        .global_correct_dts = true,
  982|     81|        .global_correct_pos = true,
  983|     81|    };
  984|       |
  985|     81|    struct demux_stream *ds = sh->ds;
  986|       |
  987|     81|    if (!sh->codec->codec)
  ------------------
  |  Branch (987:9): [True: 0, False: 81]
  ------------------
  988|      0|        sh->codec->codec = "";
  989|       |
  990|     81|    if (sh->ff_index < 0)
  ------------------
  |  Branch (990:9): [True: 9, False: 72]
  ------------------
  991|      9|        sh->ff_index = sh->index;
  992|       |
  993|     81|    MP_TARRAY_APPEND(in, in->streams, in->num_streams, sh);
  ------------------
  |  |  105|     81|    do {                                            \
  |  |  106|     81|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|     81|    do {                                            \
  |  |  |  |   97|     81|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|     81|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|     81|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|     81|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 81, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|     81|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|     81|    do {                                                        \
  |  |  |  |  |  |   89|     81|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|     81|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|     81|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|     81|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|     81|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|     81|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|     81|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|     81|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|     81|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|     81|        (idxvar)++;                                 \
  |  |  109|     81|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  994|     81|    mp_assert(in->streams[sh->index] == sh);
  ------------------
  |  |   41|     81|#define mp_assert assert
  ------------------
  995|       |
  996|     81|    if (in->current_range) {
  ------------------
  |  Branch (996:9): [True: 0, False: 81]
  ------------------
  997|      0|        for (int n = 0; n < in->num_ranges; n++)
  ------------------
  |  Branch (997:25): [True: 0, False: 0]
  ------------------
  998|      0|            add_missing_streams(in, in->ranges[n]);
  999|       |
 1000|      0|        sh->ds->queue = in->current_range->streams[sh->ds->index];
 1001|      0|    }
 1002|       |
 1003|     81|    update_stream_selection_state(in, sh->ds);
 1004|       |
 1005|     81|    switch (ds->type) {
  ------------------
  |  Branch (1005:13): [True: 29, False: 52]
  ------------------
 1006|      0|    case STREAM_AUDIO:
  ------------------
  |  Branch (1006:5): [True: 0, False: 81]
  ------------------
 1007|      0|        ds->back_preroll = in->d_user->opts->audio_back_preroll;
 1008|      0|        if (ds->back_preroll < 0) { // auto
  ------------------
  |  Branch (1008:13): [True: 0, False: 0]
  ------------------
 1009|      0|            ds->back_preroll = mp_codec_is_lossless(sh->codec->codec) ? 0 : 1;
  ------------------
  |  Branch (1009:32): [True: 0, False: 0]
  ------------------
 1010|      0|            if (sh->codec->codec && (strcmp(sh->codec->codec, "opus") == 0 ||
  ------------------
  |  Branch (1010:17): [True: 0, False: 0]
  |  Branch (1010:38): [True: 0, False: 0]
  ------------------
 1011|      0|                                     strcmp(sh->codec->codec, "vorbis") == 0 ||
  ------------------
  |  Branch (1011:38): [True: 0, False: 0]
  ------------------
 1012|      0|                                     strcmp(sh->codec->codec, "mp3") == 0))
  ------------------
  |  Branch (1012:38): [True: 0, False: 0]
  ------------------
 1013|      0|                ds->back_preroll = 2;
 1014|      0|        }
 1015|      0|        break;
 1016|     52|    case STREAM_VIDEO:
  ------------------
  |  Branch (1016:5): [True: 52, False: 29]
  ------------------
 1017|     52|        ds->back_preroll = in->d_user->opts->video_back_preroll;
 1018|     52|        if (ds->back_preroll < 0)
  ------------------
  |  Branch (1018:13): [True: 52, False: 0]
  ------------------
 1019|     52|            ds->back_preroll = 0; // auto
 1020|     52|        break;
 1021|     81|    }
 1022|       |
 1023|     81|    if (!ds->sh->attached_picture) {
  ------------------
  |  Branch (1023:9): [True: 81, False: 0]
  ------------------
 1024|       |        // Typically this is used for webradio, so any stream will do.
 1025|     81|        if (!in->metadata_stream)
  ------------------
  |  Branch (1025:13): [True: 81, False: 0]
  ------------------
 1026|     81|            in->metadata_stream = sh;
 1027|     81|    }
 1028|       |
 1029|     81|    in->events |= DEMUX_EVENT_STREAMS;
 1030|     81|    if (in->wakeup_cb)
  ------------------
  |  Branch (1030:9): [True: 0, False: 81]
  ------------------
 1031|      0|        in->wakeup_cb(in->wakeup_cb_ctx);
 1032|     81|}
demux.c:add_missing_streams:
  930|    321|{
  931|    402|    for (int n = range->num_streams; n < in->num_streams; n++) {
  ------------------
  |  Branch (931:38): [True: 81, False: 321]
  ------------------
  932|     81|        struct demux_stream *ds = in->streams[n]->ds;
  933|       |
  934|     81|        struct demux_queue *queue = talloc_ptrtype(NULL, queue);
  ------------------
  |  |   34|     81|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|     81|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     81|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  935|     81|        *queue = (struct demux_queue){
  936|     81|            .ds = ds,
  937|     81|            .range = range,
  938|     81|        };
  939|     81|        clear_queue(queue);
  940|     81|        MP_TARRAY_APPEND(range, range->streams, range->num_streams, queue);
  ------------------
  |  |  105|     81|    do {                                            \
  |  |  106|     81|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|     81|    do {                                            \
  |  |  |  |   97|     81|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|     81|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|     81|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|     81|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 81, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|     81|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|     81|    do {                                                        \
  |  |  |  |  |  |   89|     81|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|     81|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|     81|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|     81|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|     81|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|     81|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|     81|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|     81|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|     81|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|     81|        (idxvar)++;                                 \
  |  |  109|     81|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  941|     81|        mp_assert(range->streams[ds->index] == queue);
  ------------------
  |  |   41|     81|#define mp_assert assert
  ------------------
  942|     81|    }
  943|    321|}
demux.c:clear_queue:
  724|    243|{
  725|    243|    struct demux_stream *ds = queue->ds;
  726|    243|    struct demux_internal *in = ds->in;
  727|       |
  728|    243|    if (queue->head)
  ------------------
  |  Branch (728:9): [True: 0, False: 243]
  ------------------
  729|      0|        in->total_bytes -= queue->tail_cum_pos - queue->head->cum_pos;
  730|       |
  731|    243|    free_index(queue);
  732|       |
  733|    243|    demux_packet_pool_prepend(in->packet_pool, queue->head, queue->tail);
  734|    243|    queue->head = queue->tail = NULL;
  735|    243|    queue->keyframe_first = NULL;
  736|    243|    queue->keyframe_latest = NULL;
  737|    243|    queue->seek_start = queue->seek_end = queue->last_pruned = MP_NOPTS_VALUE;
  ------------------
  |  |   38|    243|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  738|       |
  739|    243|    queue->correct_dts = queue->correct_pos = true;
  740|    243|    queue->last_pos = -1;
  741|    243|    queue->last_ts = queue->last_dts = MP_NOPTS_VALUE;
  ------------------
  |  |   38|    243|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  742|    243|    queue->last_pos_fixup = -1;
  743|       |
  744|    243|    queue->is_eof = false;
  745|    243|    queue->is_bof = false;
  746|    243|}
demux.c:free_index:
  712|    243|{
  713|    243|    struct demux_stream *ds = queue->ds;
  714|    243|    struct demux_internal *in = ds->in;
  715|       |
  716|    243|    in->total_bytes -= queue->index_size * sizeof(queue->index[0]);
  717|    243|    queue->index_size = 0;
  718|    243|    queue->index0 = 0;
  719|    243|    queue->num_index = 0;
  720|    243|    TA_FREEP(&queue->index);
  ------------------
  |  |   81|    243|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|    243|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  721|    243|}
demux.c:demux_shutdown:
 1070|  2.81k|{
 1071|  2.81k|    struct demuxer *demuxer = in->d_user;
 1072|       |
 1073|  2.81k|    if (in->recorder) {
  ------------------
  |  Branch (1073:9): [True: 0, False: 2.81k]
  ------------------
 1074|      0|        mp_recorder_destroy(in->recorder);
 1075|      0|        in->recorder = NULL;
 1076|      0|    }
 1077|       |
 1078|  2.81k|    dumper_close(in);
 1079|       |
 1080|  2.81k|    if (demuxer->desc->close)
  ------------------
  |  Branch (1080:9): [True: 930, False: 1.88k]
  ------------------
 1081|    930|        demuxer->desc->close(in->d_thread);
 1082|  2.81k|    demuxer->priv = NULL;
 1083|  2.81k|    in->d_thread->priv = NULL;
 1084|       |
 1085|  2.81k|    demux_flush(demuxer);
 1086|  2.81k|    mp_assert(in->total_bytes == 0);
  ------------------
  |  |   41|  2.81k|#define mp_assert assert
  ------------------
 1087|       |
 1088|  2.81k|    in->current_range = NULL;
 1089|  2.81k|    free_empty_cached_ranges(in);
 1090|       |
 1091|  2.81k|    talloc_free(in->cache);
  ------------------
  |  |   47|  2.81k|#define talloc_free                     ta_free
  ------------------
 1092|  2.81k|    in->cache = NULL;
 1093|       |
 1094|  2.81k|    if (in->owns_stream)
  ------------------
  |  Branch (1094:9): [True: 2.81k, False: 0]
  ------------------
 1095|  2.81k|        free_stream(demuxer->stream);
 1096|  2.81k|    demuxer->stream = NULL;
 1097|  2.81k|}
demux.c:demux_dealloc:
 1100|  2.81k|{
 1101|  2.89k|    for (int n = 0; n < in->num_streams; n++)
  ------------------
  |  Branch (1101:21): [True: 81, False: 2.81k]
  ------------------
 1102|     81|        talloc_free(in->streams[n]);
  ------------------
  |  |   47|     81|#define talloc_free                     ta_free
  ------------------
 1103|  2.81k|    mp_mutex_destroy(&in->lock);
  ------------------
  |  |  130|  2.81k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
 1104|  2.81k|    mp_cond_destroy(&in->wakeup);
 1105|  2.81k|    talloc_free(in->d_user);
  ------------------
  |  |   47|  2.81k|#define talloc_free                     ta_free
  ------------------
 1106|  2.81k|}
demux.c:update_seek_ranges:
  595|    642|{
  596|    642|    range->seek_start = range->seek_end = MP_NOPTS_VALUE;
  ------------------
  |  |   38|    642|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  597|    642|    range->is_bof = true;
  598|    642|    range->is_eof = true;
  599|       |
  600|    642|    double min_start_pts = MP_NOPTS_VALUE;
  ------------------
  |  |   38|    642|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  601|    642|    double max_end_pts = MP_NOPTS_VALUE;
  ------------------
  |  |   38|    642|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  602|       |
  603|    804|    for (int n = 0; n < range->num_streams; n++) {
  ------------------
  |  Branch (603:21): [True: 162, False: 642]
  ------------------
  604|    162|        struct demux_queue *queue = range->streams[n];
  605|       |
  606|    162|        if (queue->ds->selected && queue->ds->eager) {
  ------------------
  |  Branch (606:13): [True: 0, False: 162]
  |  Branch (606:36): [True: 0, False: 0]
  ------------------
  607|      0|            if (queue->is_bof) {
  ------------------
  |  Branch (607:17): [True: 0, False: 0]
  ------------------
  608|      0|                min_start_pts = MP_PTS_MIN(min_start_pts, queue->seek_start);
  ------------------
  |  |   63|      0|#define MP_PTS_MIN(a, b) MPMIN(MP_PTS_OR_DEF(a, b), MP_PTS_OR_DEF(b, a))
  |  |  ------------------
  |  |  |  |   44|      0|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (44:22): [True: 0, False: 0]
  |  |  |  |  |  Branch (44:23): [True: 0, False: 0]
  |  |  |  |  |  Branch (44:29): [True: 0, False: 0]
  |  |  |  |  |  Branch (44:35): [True: 0, False: 0]
  |  |  |  |  |  Branch (44:41): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  609|      0|            } else {
  610|      0|                range->seek_start =
  611|      0|                    MP_PTS_MAX(range->seek_start, queue->seek_start);
  ------------------
  |  |   64|      0|#define MP_PTS_MAX(a, b) MPMAX(MP_PTS_OR_DEF(a, b), MP_PTS_OR_DEF(b, a))
  |  |  ------------------
  |  |  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  |  |  |  Branch (43:23): [True: 0, False: 0]
  |  |  |  |  |  Branch (43:29): [True: 0, False: 0]
  |  |  |  |  |  Branch (43:35): [True: 0, False: 0]
  |  |  |  |  |  Branch (43:41): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  612|      0|            }
  613|       |
  614|      0|            if (queue->is_eof) {
  ------------------
  |  Branch (614:17): [True: 0, False: 0]
  ------------------
  615|      0|                max_end_pts = MP_PTS_MAX(max_end_pts, queue->seek_end);
  ------------------
  |  |   64|      0|#define MP_PTS_MAX(a, b) MPMAX(MP_PTS_OR_DEF(a, b), MP_PTS_OR_DEF(b, a))
  |  |  ------------------
  |  |  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  |  |  |  Branch (43:23): [True: 0, False: 0]
  |  |  |  |  |  Branch (43:29): [True: 0, False: 0]
  |  |  |  |  |  Branch (43:35): [True: 0, False: 0]
  |  |  |  |  |  Branch (43:41): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  616|      0|            } else {
  617|      0|                range->seek_end = MP_PTS_MIN(range->seek_end, queue->seek_end);
  ------------------
  |  |   63|      0|#define MP_PTS_MIN(a, b) MPMIN(MP_PTS_OR_DEF(a, b), MP_PTS_OR_DEF(b, a))
  |  |  ------------------
  |  |  |  |   44|      0|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (44:22): [True: 0, False: 0]
  |  |  |  |  |  Branch (44:23): [True: 0, False: 0]
  |  |  |  |  |  Branch (44:29): [True: 0, False: 0]
  |  |  |  |  |  Branch (44:35): [True: 0, False: 0]
  |  |  |  |  |  Branch (44:41): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  618|      0|            }
  619|       |
  620|      0|            range->is_eof &= queue->is_eof;
  621|      0|            range->is_bof &= queue->is_bof;
  622|       |
  623|      0|            bool empty = queue->is_eof && !queue->head;
  ------------------
  |  Branch (623:26): [True: 0, False: 0]
  |  Branch (623:43): [True: 0, False: 0]
  ------------------
  624|      0|            if (queue->seek_start >= queue->seek_end && !empty &&
  ------------------
  |  Branch (624:17): [True: 0, False: 0]
  |  Branch (624:57): [True: 0, False: 0]
  ------------------
  625|      0|                !(queue->seek_start == queue->seek_end &&
  ------------------
  |  Branch (625:19): [True: 0, False: 0]
  ------------------
  626|      0|                  queue->seek_start != MP_NOPTS_VALUE))
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (626:19): [True: 0, False: 0]
  ------------------
  627|      0|                goto broken;
  628|      0|        }
  629|    162|    }
  630|       |
  631|    642|    if (range->is_eof)
  ------------------
  |  Branch (631:9): [True: 642, False: 0]
  ------------------
  632|    642|        range->seek_end = max_end_pts;
  633|    642|    if (range->is_bof)
  ------------------
  |  Branch (633:9): [True: 642, False: 0]
  ------------------
  634|    642|        range->seek_start = min_start_pts;
  635|       |
  636|       |    // Sparse (subtitle) stream behavior is not very clearly defined, but
  637|       |    // usually we don't want it to restrict the range of other streams. For
  638|       |    // example, if there are subtitle packets at position 5 and 10 seconds, and
  639|       |    // the demuxer demuxed the other streams until position 7 seconds, the seek
  640|       |    // range end position is 7.
  641|       |    // Assume that reading a non-sparse (audio/video) packet gets all sparse
  642|       |    // packets that are needed before that non-sparse packet.
  643|       |    // This is incorrect in any of these cases:
  644|       |    //  - sparse streams only (it's unknown how to determine an accurate range)
  645|       |    //  - if sparse streams have non-keyframe packets (we set queue->last_pruned
  646|       |    //    to the start of the pruned keyframe range - we'd need the end or so)
  647|       |    // We also assume that ds->eager equals to a stream not being sparse
  648|       |    // (usually true, except if only sparse streams are selected).
  649|       |    // We also rely on the fact that the demuxer position will always be ahead
  650|       |    // of the seek_end for audio/video, because they need to prefetch at least
  651|       |    // 1 packet to detect the end of a keyframe range. This means that there's
  652|       |    // a relatively high guarantee to have all sparse (subtitle) packets within
  653|       |    // the seekable range.
  654|       |    // As a consequence, the code _never_ checks queue->seek_end for a sparse
  655|       |    // queue, as the end of it is implied by the highest PTS of a non-sparse
  656|       |    // stream (i.e. the latest demuxer position).
  657|       |    // On the other hand, if a sparse packet was pruned, and that packet has
  658|       |    // a higher PTS than seek_start for non-sparse queues, that packet is
  659|       |    // missing. So the range's seek_start needs to be adjusted accordingly.
  660|    804|    for (int n = 0; n < range->num_streams; n++) {
  ------------------
  |  Branch (660:21): [True: 162, False: 642]
  ------------------
  661|    162|        struct demux_queue *queue = range->streams[n];
  662|    162|        if (queue->ds->selected && !queue->ds->eager &&
  ------------------
  |  Branch (662:13): [True: 0, False: 162]
  |  Branch (662:36): [True: 0, False: 0]
  ------------------
  663|    162|            queue->last_pruned != MP_NOPTS_VALUE &&
  ------------------
  |  |   38|    162|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (663:13): [True: 0, False: 0]
  ------------------
  664|    162|            range->seek_start != MP_NOPTS_VALUE)
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (664:13): [True: 0, False: 0]
  ------------------
  665|      0|        {
  666|       |            // (last_pruned is _exclusive_ to the seekable range, so add a small
  667|       |            // value to exclude it from the valid range.)
  668|      0|            range->seek_start =
  669|      0|                MP_PTS_MAX(range->seek_start, queue->last_pruned + 0.1);
  ------------------
  |  |   64|      0|#define MP_PTS_MAX(a, b) MPMAX(MP_PTS_OR_DEF(a, b), MP_PTS_OR_DEF(b, a))
  |  |  ------------------
  |  |  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  |  |  |  Branch (43:23): [True: 0, False: 0]
  |  |  |  |  |  Branch (43:29): [True: 0, False: 0]
  |  |  |  |  |  Branch (43:35): [True: 0, False: 0]
  |  |  |  |  |  Branch (43:41): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  670|      0|        }
  671|    162|    }
  672|       |
  673|    642|    if (range->seek_start >= range->seek_end && !(range->is_bof && range->is_eof))
  ------------------
  |  Branch (673:9): [True: 642, False: 0]
  |  Branch (673:51): [True: 642, False: 0]
  |  Branch (673:68): [True: 642, False: 0]
  ------------------
  674|      0|        goto broken;
  675|       |
  676|    642|    prune_metadata(range);
  677|    642|    return;
  678|       |
  679|      0|broken:
  680|      0|    range->seek_start = range->seek_end = MP_NOPTS_VALUE;
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  681|      0|    prune_metadata(range);
  682|      0|}
demux.c:prune_metadata:
  569|    642|{
  570|    642|    int first_needed = 0;
  571|       |
  572|    642|    if (range->seek_start == MP_NOPTS_VALUE) {
  ------------------
  |  |   38|    642|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (572:9): [True: 642, False: 0]
  ------------------
  573|    642|        first_needed = range->num_metadata;
  574|    642|    } else {
  575|      0|        for (int n = 0; n < range->num_metadata ; n++) {
  ------------------
  |  Branch (575:25): [True: 0, False: 0]
  ------------------
  576|      0|            if (range->metadata[n]->pts > range->seek_start)
  ------------------
  |  Branch (576:17): [True: 0, False: 0]
  ------------------
  577|      0|                break;
  578|      0|            first_needed = n;
  579|      0|        }
  580|      0|    }
  581|       |
  582|       |    // Always preserve the last entry.
  583|    642|    first_needed = MPMIN(first_needed, range->num_metadata - 1);
  ------------------
  |  |   44|    642|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 642, False: 0]
  |  |  ------------------
  ------------------
  584|       |
  585|       |    // (Could make this significantly more efficient for large first_needed,
  586|       |    // however that might be very rare and even then it might not matter.)
  587|    642|    for (int n = 0; n < first_needed; n++) {
  ------------------
  |  Branch (587:21): [True: 0, False: 642]
  ------------------
  588|      0|        talloc_free(range->metadata[0]);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  589|      0|        MP_TARRAY_REMOVE_AT(range->metadata, range->num_metadata, 0);
  ------------------
  |  |  143|      0|    do {                                            \
  |  |  144|      0|        size_t at_ = (at);                          \
  |  |  145|      0|        assert(at_ <= (idxvar));                    \
  |  |  146|      0|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|      0|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|      0|        (idxvar)--;                                 \
  |  |  149|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  590|      0|    }
  591|    642|}
demux.c:prune_old_packets:
 2293|    321|{
 2294|    321|    mp_assert(in->current_range == in->ranges[in->num_ranges - 1]);
  ------------------
  |  |   41|    321|#define mp_assert assert
  ------------------
 2295|       |
 2296|       |    // It's not clear what the ideal way to prune old packets is. For now, we
 2297|       |    // prune the oldest packet runs, as long as the total cache amount is too
 2298|       |    // big.
 2299|    321|    while (1) {
  ------------------
  |  Branch (2299:12): [Folded - Ignored]
  ------------------
 2300|    321|        uint64_t fw_bytes = 0;
 2301|    402|        for (int n = 0; n < in->num_streams; n++) {
  ------------------
  |  Branch (2301:25): [True: 81, False: 321]
  ------------------
 2302|     81|            struct demux_stream *ds = in->streams[n]->ds;
 2303|     81|            fw_bytes += get_forward_buffered_bytes(ds);
 2304|     81|        }
 2305|    321|        uint64_t max_avail = in->max_bytes_bw;
 2306|       |        // Backward cache (if enabled at all) can use unused forward cache.
 2307|       |        // Still leave 1 byte free, so the read_packet logic doesn't get stuck.
 2308|    321|        if (max_avail && in->max_bytes > (fw_bytes + 1) && in->d_user->opts->donate_fw)
  ------------------
  |  Branch (2308:13): [True: 37, False: 284]
  |  Branch (2308:26): [True: 37, False: 0]
  |  Branch (2308:60): [True: 37, False: 0]
  ------------------
 2309|     37|            max_avail += in->max_bytes - (fw_bytes + 1);
 2310|    321|        if (in->total_bytes - fw_bytes <= max_avail)
  ------------------
  |  Branch (2310:13): [True: 321, False: 0]
  ------------------
 2311|    321|            break;
 2312|       |
 2313|       |        // (Start from least recently used range.)
 2314|      0|        struct demux_cached_range *range = in->ranges[0];
 2315|      0|        double earliest_ts = MP_NOPTS_VALUE;
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
 2316|      0|        struct demux_stream *earliest_stream = NULL;
 2317|       |
 2318|      0|        for (int n = 0; n < range->num_streams; n++) {
  ------------------
  |  Branch (2318:25): [True: 0, False: 0]
  ------------------
 2319|      0|            struct demux_queue *queue = range->streams[n];
 2320|      0|            struct demux_stream *ds = queue->ds;
 2321|       |
 2322|      0|            if (queue->head && queue->head != ds->reader_head) {
  ------------------
  |  Branch (2322:17): [True: 0, False: 0]
  |  Branch (2322:32): [True: 0, False: 0]
  ------------------
 2323|      0|                struct demux_packet *dp = queue->head;
 2324|      0|                double ts = queue->seek_start;
 2325|       |                // If the ts is NOPTS, the queue has no retainable packets, so
 2326|       |                // delete them all. This code is not run when there's enough
 2327|       |                // free space, so normally the queue gets the chance to build up.
 2328|      0|                bool prune_always =
 2329|      0|                    !in->seekable_cache || ts == MP_NOPTS_VALUE || !dp->keyframe;
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (2329:21): [True: 0, False: 0]
  |  Branch (2329:44): [True: 0, False: 0]
  |  Branch (2329:68): [True: 0, False: 0]
  ------------------
 2330|      0|                if (prune_always || !earliest_stream || ts < earliest_ts) {
  ------------------
  |  Branch (2330:21): [True: 0, False: 0]
  |  Branch (2330:37): [True: 0, False: 0]
  |  Branch (2330:57): [True: 0, False: 0]
  ------------------
 2331|      0|                    earliest_ts = ts;
 2332|      0|                    earliest_stream = ds;
 2333|      0|                    if (prune_always)
  ------------------
  |  Branch (2333:25): [True: 0, False: 0]
  ------------------
 2334|      0|                        break;
 2335|      0|                }
 2336|      0|            }
 2337|      0|        }
 2338|       |
 2339|       |        // In some cases (like when the seek index became huge), there aren't
 2340|       |        // any backwards packets, even if the total cache size is exceeded.
 2341|      0|        if (!earliest_stream)
  ------------------
  |  Branch (2341:13): [True: 0, False: 0]
  ------------------
 2342|      0|            break;
 2343|       |
 2344|      0|        struct demux_stream *ds = earliest_stream;
 2345|      0|        struct demux_queue *queue = range->streams[ds->index];
 2346|       |
 2347|      0|        bool non_kf_prune = queue->head && !queue->head->keyframe;
  ------------------
  |  Branch (2347:29): [True: 0, False: 0]
  |  Branch (2347:44): [True: 0, False: 0]
  ------------------
 2348|      0|        bool kf_was_pruned = false;
 2349|       |
 2350|      0|        while (queue->head && queue->head != ds->reader_head) {
  ------------------
  |  Branch (2350:16): [True: 0, False: 0]
  |  Branch (2350:31): [True: 0, False: 0]
  ------------------
 2351|      0|            if (queue->head->keyframe) {
  ------------------
  |  Branch (2351:17): [True: 0, False: 0]
  ------------------
 2352|       |                // If the cache is seekable, only delete until up the next
 2353|       |                // keyframe. This is not always efficient, but ensures we
 2354|       |                // prune all streams fairly.
 2355|       |                // Also, if the first packet was _not_ a keyframe, we want it
 2356|       |                // to remove all preceding non-keyframe packets first, before
 2357|       |                // re-evaluating what to prune next.
 2358|      0|                if ((kf_was_pruned || non_kf_prune) && in->seekable_cache)
  ------------------
  |  Branch (2358:22): [True: 0, False: 0]
  |  Branch (2358:39): [True: 0, False: 0]
  |  Branch (2358:56): [True: 0, False: 0]
  ------------------
 2359|      0|                    break;
 2360|      0|                kf_was_pruned = true;
 2361|      0|            }
 2362|       |
 2363|      0|            remove_head_packet(queue);
 2364|      0|        }
 2365|       |
 2366|       |        // Need to update the seekable time range.
 2367|      0|        if (kf_was_pruned) {
  ------------------
  |  Branch (2367:13): [True: 0, False: 0]
  ------------------
 2368|      0|            mp_assert(!queue->keyframe_first); // it was just deleted, supposedly
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
 2369|       |
 2370|      0|            queue->keyframe_first = queue->head;
 2371|       |            // (May happen if reader_head stopped pruning the range, and there's
 2372|       |            // no next range.)
 2373|      0|            while (queue->keyframe_first && !queue->keyframe_first->keyframe)
  ------------------
  |  Branch (2373:20): [True: 0, False: 0]
  |  Branch (2373:45): [True: 0, False: 0]
  ------------------
 2374|      0|                queue->keyframe_first = queue->keyframe_first->next;
 2375|       |
 2376|      0|            if (queue->seek_start != MP_NOPTS_VALUE)
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (2376:17): [True: 0, False: 0]
  ------------------
 2377|      0|                queue->last_pruned = queue->seek_start;
 2378|       |
 2379|      0|            double kf_min;
 2380|      0|            compute_keyframe_times(queue->keyframe_first, &kf_min, NULL);
 2381|       |
 2382|      0|            bool update_range = true;
 2383|       |
 2384|      0|            queue->seek_start = kf_min;
 2385|       |
 2386|      0|            if (queue->seek_start != MP_NOPTS_VALUE) {
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (2386:17): [True: 0, False: 0]
  ------------------
 2387|      0|                queue->seek_start += ds->sh->seek_preroll;
 2388|       |
 2389|       |                // Don't need to update if the new start is still before the
 2390|       |                // range's start (or if the range was undefined anyway).
 2391|      0|                if (range->seek_start == MP_NOPTS_VALUE ||
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (2391:21): [True: 0, False: 0]
  ------------------
 2392|      0|                    queue->seek_start <= range->seek_start)
  ------------------
  |  Branch (2392:21): [True: 0, False: 0]
  ------------------
 2393|      0|                {
 2394|      0|                    update_range = false;
 2395|      0|                }
 2396|      0|            }
 2397|       |
 2398|      0|            if (update_range)
  ------------------
  |  Branch (2398:17): [True: 0, False: 0]
  ------------------
 2399|      0|                update_seek_ranges(range);
 2400|      0|        }
 2401|       |
 2402|      0|        if (range != in->current_range && range->seek_start == MP_NOPTS_VALUE)
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (2402:13): [True: 0, False: 0]
  |  Branch (2402:43): [True: 0, False: 0]
  ------------------
 2403|      0|            free_empty_cached_ranges(in);
 2404|      0|    }
 2405|    321|}
demux.c:ds_clear_reader_state:
  808|    162|{
  809|    162|    ds_clear_reader_queue_state(ds);
  810|       |
  811|    162|    ds->base_ts = ds->last_br_ts = MP_NOPTS_VALUE;
  ------------------
  |  |   38|    162|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  812|    162|    ds->last_br_bytes = 0;
  813|    162|    ds->bitrate = -1;
  814|    162|    ds->skip_to_keyframe = false;
  815|    162|    ds->attached_picture_added = false;
  816|    162|    ds->last_ret_pos = -1;
  817|    162|    ds->last_ret_dts = MP_NOPTS_VALUE;
  ------------------
  |  |   38|    162|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  818|    162|    ds->force_read_until = MP_NOPTS_VALUE;
  ------------------
  |  |   38|    162|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  819|       |
  820|    162|    if (clear_back_state) {
  ------------------
  |  Branch (820:9): [True: 162, False: 0]
  ------------------
  821|    162|        ds->back_restart_pos = -1;
  822|    162|        ds->back_restart_dts = MP_NOPTS_VALUE;
  ------------------
  |  |   38|    162|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  823|    162|        ds->back_restart_eof = false;
  824|    162|        ds->back_restart_next = ds->in->back_demuxing;
  825|    162|        ds->back_restarting = ds->in->back_demuxing && ds->eager;
  ------------------
  |  Branch (825:31): [True: 0, False: 162]
  |  Branch (825:56): [True: 0, False: 0]
  ------------------
  826|    162|        ds->back_seek_pos = MP_NOPTS_VALUE;
  ------------------
  |  |   38|    162|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  827|    162|        ds->back_resume_pos = -1;
  828|    162|        ds->back_resume_dts = MP_NOPTS_VALUE;
  ------------------
  |  |   38|    162|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  829|    162|        ds->back_resuming = false;
  830|    162|        ds->back_range_started = false;
  831|    162|        ds->back_range_count = 0;
  832|    162|        ds->back_range_preroll = 0;
  833|    162|    }
  834|    162|}
demux.c:ds_clear_reader_queue_state:
  800|    162|{
  801|    162|    ds->reader_head = NULL;
  802|    162|    ds->eof = false;
  803|    162|    ds->need_wakeup = true;
  804|    162|}
demux.c:update_opts:
 2454|    321|{
 2455|    321|    struct demux_opts *opts = demuxer->opts;
 2456|    321|    struct demux_internal *in = demuxer->in;
 2457|       |
 2458|    321|    in->min_secs = opts->min_secs;
 2459|    321|    in->hyst_secs = opts->hyst_secs;
 2460|    321|    in->max_bytes = opts->max_bytes;
 2461|    321|    in->max_bytes_bw = opts->max_bytes_bw;
 2462|       |
 2463|    321|    int seekable = opts->seekable_cache;
 2464|    321|    bool is_streaming = in->d_thread->is_streaming;
 2465|    321|    bool use_cache = is_streaming;
 2466|    321|    if (opts->enable_cache >= 0)
  ------------------
  |  Branch (2466:9): [True: 0, False: 321]
  ------------------
 2467|      0|        use_cache = opts->enable_cache == 1;
 2468|       |
 2469|    321|    if (use_cache) {
  ------------------
  |  Branch (2469:9): [True: 94, False: 227]
  ------------------
 2470|     94|        in->min_secs = MPMAX(in->min_secs, opts->min_secs_cache);
  ------------------
  |  |   43|     94|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 94]
  |  |  ------------------
  ------------------
 2471|     94|        if (seekable < 0)
  ------------------
  |  Branch (2471:13): [True: 94, False: 0]
  ------------------
 2472|     94|            seekable = 1;
 2473|     94|    }
 2474|    321|    in->seekable_cache = seekable == 1;
 2475|    321|    in->using_network_cache_opts = is_streaming && use_cache;
  ------------------
  |  Branch (2475:36): [True: 94, False: 227]
  |  Branch (2475:52): [True: 94, False: 0]
  ------------------
 2476|       |
 2477|    321|    if (!in->seekable_cache)
  ------------------
  |  Branch (2477:9): [True: 227, False: 94]
  ------------------
 2478|    227|        in->max_bytes_bw = 0;
 2479|       |
 2480|    321|    if (!in->can_cache) {
  ------------------
  |  Branch (2480:9): [True: 160, False: 161]
  ------------------
 2481|    160|        in->seekable_cache = false;
 2482|    160|        in->min_secs = 0;
 2483|    160|        in->max_bytes = 1;
 2484|    160|        in->max_bytes_bw = 0;
 2485|    160|        in->using_network_cache_opts = false;
 2486|    160|    }
 2487|       |
 2488|    321|    if (in->seekable_cache && opts->disk_cache && !in->cache) {
  ------------------
  |  Branch (2488:9): [True: 37, False: 284]
  |  Branch (2488:31): [True: 0, False: 37]
  |  Branch (2488:51): [True: 0, False: 0]
  ------------------
 2489|      0|        in->cache = demux_cache_create(in->global, in->log);
 2490|      0|        if (!in->cache)
  ------------------
  |  Branch (2490:13): [True: 0, False: 0]
  ------------------
 2491|      0|            MP_ERR(in, "Failed to create file cache.\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2492|      0|    }
 2493|       |
 2494|       |    // The filename option really decides whether recording should be active.
 2495|       |    // So if the filename changes, act upon it.
 2496|    321|    char *old = in->record_filename ? in->record_filename : "";
  ------------------
  |  Branch (2496:17): [True: 0, False: 321]
  ------------------
 2497|    321|    char *new = opts->record_file ? opts->record_file : "";
  ------------------
  |  Branch (2497:17): [True: 0, False: 321]
  ------------------
 2498|    321|    if (strcmp(old, new) != 0) {
  ------------------
  |  Branch (2498:9): [True: 0, False: 321]
  ------------------
 2499|      0|        if (in->recorder) {
  ------------------
  |  Branch (2499:13): [True: 0, False: 0]
  ------------------
 2500|      0|            MP_WARN(in, "Stopping recording.\n");
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2501|      0|            mp_recorder_destroy(in->recorder);
 2502|      0|            in->recorder = NULL;
 2503|      0|        }
 2504|      0|        talloc_free(in->record_filename);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 2505|      0|        in->record_filename = talloc_strdup(in, opts->record_file);
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
 2506|       |        // Note: actual recording only starts once packets are read. It may be
 2507|       |        // important to delay creating in->recorder to that point, because the
 2508|       |        // demuxer might detect more streams until finding the first packet.
 2509|      0|        in->enable_recording = in->can_record;
 2510|      0|    }
 2511|       |
 2512|       |    // In case the cache was reduced in size.
 2513|    321|    prune_old_packets(in);
 2514|       |
 2515|       |    // In case the seekable cache was disabled.
 2516|    321|    free_empty_cached_ranges(in);
 2517|    321|}
demux.c:lookup_timed_metadata:
 3116|    642|{
 3117|    642|    struct demux_cached_range *r = in->current_range;
 3118|       |
 3119|    642|    if (!r || !r->num_metadata || pts == MP_NOPTS_VALUE)
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (3119:9): [True: 0, False: 642]
  |  Branch (3119:15): [True: 642, False: 0]
  |  Branch (3119:35): [True: 0, False: 0]
  ------------------
 3120|    642|        return NULL;
 3121|       |
 3122|      0|    int start = 1;
 3123|      0|    int i = in->cached_metadata_index;
 3124|      0|    if (i >= 0 &&  i < r->num_metadata && r->metadata[i]->pts <= pts)
  ------------------
  |  Branch (3124:9): [True: 0, False: 0]
  |  Branch (3124:20): [True: 0, False: 0]
  |  Branch (3124:43): [True: 0, False: 0]
  ------------------
 3125|      0|        start = i + 1;
 3126|       |
 3127|      0|    in->cached_metadata_index = r->num_metadata - 1;
 3128|      0|    for (int n = start; n < r->num_metadata; n++) {
  ------------------
  |  Branch (3128:25): [True: 0, False: 0]
  ------------------
 3129|      0|        if (r->metadata[n]->pts >= pts) {
  ------------------
  |  Branch (3129:13): [True: 0, False: 0]
  ------------------
 3130|      0|            in->cached_metadata_index = n - 1;
 3131|      0|            break;
 3132|      0|        }
 3133|      0|    }
 3134|       |
 3135|      0|    return r->metadata[in->cached_metadata_index];
 3136|    642|}
demux.c:update_final_metadata:
 3073|    321|{
 3074|    321|    mp_assert(demuxer == demuxer->in->d_user);
  ------------------
  |  |   41|    321|#define mp_assert assert
  ------------------
 3075|    321|    struct demux_internal *in = demuxer->in;
 3076|       |
 3077|    321|    struct mp_tags *dyn_tags = NULL;
 3078|       |
 3079|       |    // Often useful for audio-only files, which have metadata in the audio track
 3080|       |    // metadata instead of the main metadata, but can also have cover art
 3081|       |    // metadata (which libavformat likes to treat as video streams).
 3082|    321|    int astreams = 0;
 3083|    321|    int astream_id = -1;
 3084|    321|    int vstreams = 0;
 3085|    402|    for (int n = 0; n < in->num_streams; n++) {
  ------------------
  |  Branch (3085:21): [True: 81, False: 321]
  ------------------
 3086|     81|        struct sh_stream *sh = in->streams[n];
 3087|     81|        if (sh->type == STREAM_VIDEO && !sh->attached_picture)
  ------------------
  |  Branch (3087:13): [True: 52, False: 29]
  |  Branch (3087:41): [True: 52, False: 0]
  ------------------
 3088|     52|            vstreams += 1;
 3089|     81|        if (sh->type == STREAM_AUDIO) {
  ------------------
  |  Branch (3089:13): [True: 0, False: 81]
  ------------------
 3090|      0|            astreams += 1;
 3091|      0|            astream_id = n;
 3092|      0|        }
 3093|     81|    }
 3094|       |
 3095|       |    // Use the metadata_stream tags only if this really seems to be an audio-
 3096|       |    // only stream. Otherwise it will happen too often that "uninteresting"
 3097|       |    // stream metadata will trash the actual file tags.
 3098|    321|    if (vstreams == 0 && astreams == 1 &&
  ------------------
  |  Branch (3098:9): [True: 269, False: 52]
  |  Branch (3098:26): [True: 0, False: 269]
  ------------------
 3099|    321|        in->streams[astream_id] == in->metadata_stream)
  ------------------
  |  Branch (3099:9): [True: 0, False: 0]
  ------------------
 3100|      0|    {
 3101|      0|        dyn_tags = in->metadata_stream->tags;
 3102|      0|        if (tm && tm->from_stream)
  ------------------
  |  Branch (3102:13): [True: 0, False: 0]
  |  Branch (3102:19): [True: 0, False: 0]
  ------------------
 3103|      0|            dyn_tags = tm->tags;
 3104|      0|    }
 3105|       |
 3106|       |    // Global metadata updates.
 3107|    321|    if (tm && !tm->from_stream)
  ------------------
  |  Branch (3107:9): [True: 0, False: 321]
  |  Branch (3107:15): [True: 0, False: 0]
  ------------------
 3108|      0|        dyn_tags = tm->tags;
 3109|       |
 3110|    321|    if (dyn_tags)
  ------------------
  |  Branch (3110:9): [True: 0, False: 321]
  ------------------
 3111|      0|        mp_tags_merge(demuxer->metadata, dyn_tags);
 3112|    321|}
demux.c:demux_update_replaygain:
 2957|    321|{
 2958|    321|    struct demux_internal *in = demuxer->in;
 2959|    402|    for (int n = 0; n < in->num_streams; n++) {
  ------------------
  |  Branch (2959:21): [True: 81, False: 321]
  ------------------
 2960|     81|        struct sh_stream *sh = in->streams[n];
 2961|     81|        if (sh->type == STREAM_AUDIO && !sh->codec->replaygain_data) {
  ------------------
  |  Branch (2961:13): [True: 0, False: 81]
  |  Branch (2961:41): [True: 0, False: 0]
  ------------------
 2962|      0|            struct replaygain_data *rg = decode_rgain(demuxer->log, sh->tags);
 2963|      0|            if (!rg)
  ------------------
  |  Branch (2963:17): [True: 0, False: 0]
  ------------------
 2964|      0|                rg = decode_rgain(demuxer->log, demuxer->metadata);
 2965|      0|            if (rg)
  ------------------
  |  Branch (2965:17): [True: 0, False: 0]
  ------------------
 2966|      0|                sh->codec->replaygain_data = talloc_steal(in, rg);
  ------------------
  |  |   38|      0|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 2967|      0|        }
 2968|     81|    }
 2969|    321|}
demux.c:demux_open:
 3395|    609|{
 3396|    609|    const int *check_levels = d_normal;
 3397|    609|    const struct demuxer_desc *check_desc = NULL;
 3398|    609|    struct mp_log *log = mp_log_new(NULL, global->log, "!demux");
 3399|    609|    struct demuxer *demuxer = NULL;
 3400|    609|    char *force_format = params ? params->force_format : NULL;
  ------------------
  |  Branch (3400:26): [True: 609, False: 0]
  ------------------
 3401|       |
 3402|    609|    struct parent_stream_info sinfo = {
 3403|    609|        .seekable = stream->seekable,
 3404|    609|        .is_network = stream->is_network,
 3405|    609|        .is_streaming = stream->streaming,
 3406|    609|        .stream_origin = stream->stream_origin,
 3407|    609|        .cancel = cancel,
 3408|    609|        .filename = talloc_strdup(NULL, stream->url),
  ------------------
  |  |   50|    609|#define talloc_strdup                   ta_xstrdup
  ------------------
 3409|    609|    };
 3410|       |
 3411|    609|    if (!force_format)
  ------------------
  |  Branch (3411:9): [True: 608, False: 1]
  ------------------
 3412|    608|        force_format = stream->demuxer;
 3413|       |
 3414|    609|    if (force_format && force_format[0] && !stream->is_directory) {
  ------------------
  |  Branch (3414:9): [True: 227, False: 382]
  |  Branch (3414:25): [True: 227, False: 0]
  |  Branch (3414:44): [True: 227, False: 0]
  ------------------
 3415|    227|        check_levels = d_request;
 3416|    227|        if (force_format[0] == '+') {
  ------------------
  |  Branch (3416:13): [True: 0, False: 227]
  ------------------
 3417|      0|            force_format += 1;
 3418|      0|            check_levels = d_force;
 3419|      0|        }
 3420|  1.47k|        for (int n = 0; demuxer_list[n]; n++) {
  ------------------
  |  Branch (3420:25): [True: 1.47k, False: 1]
  ------------------
 3421|  1.47k|            if (strcmp(demuxer_list[n]->name, force_format) == 0) {
  ------------------
  |  Branch (3421:17): [True: 226, False: 1.24k]
  ------------------
 3422|    226|                check_desc = demuxer_list[n];
 3423|    226|                break;
 3424|    226|            }
 3425|  1.47k|        }
 3426|    227|        if (!check_desc) {
  ------------------
  |  Branch (3426:13): [True: 1, False: 226]
  ------------------
 3427|      1|            mp_err(log, "Demuxer %s does not exist.\n", force_format);
  ------------------
  |  |   72|      1|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
 3428|      1|            goto done;
 3429|      1|        }
 3430|    227|    }
 3431|       |
 3432|       |    // Test demuxers from first to last, one pass for each check_levels[] entry
 3433|  1.21k|    for (int pass = 0; check_levels[pass] != -1; pass++) {
  ------------------
  |  Branch (3433:24): [True: 906, False: 305]
  ------------------
 3434|    906|        enum demux_check level = check_levels[pass];
 3435|    906|        mp_verbose(log, "Trying demuxers for level=%s.\n", d_level(level));
  ------------------
  |  |   75|    906|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
 3436|  9.95k|        for (int n = 0; demuxer_list[n]; n++) {
  ------------------
  |  Branch (3436:25): [True: 9.35k, False: 603]
  ------------------
 3437|  9.35k|            const struct demuxer_desc *desc = demuxer_list[n];
 3438|  9.35k|            if (!check_desc || desc == check_desc) {
  ------------------
  |  Branch (3438:17): [True: 7.81k, False: 1.54k]
  |  Branch (3438:32): [True: 226, False: 1.31k]
  ------------------
 3439|  8.03k|                demuxer = open_given_type(global, log, desc, stream, &sinfo,
 3440|  8.03k|                                          params, level);
 3441|  8.03k|                if (demuxer) {
  ------------------
  |  Branch (3441:21): [True: 303, False: 7.73k]
  ------------------
 3442|    303|                    talloc_steal(demuxer, log);
  ------------------
  |  |   38|    303|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|    303|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 3443|    303|                    log = NULL;
 3444|    303|                    goto done;
 3445|    303|                }
 3446|  8.03k|            }
 3447|  9.35k|        }
 3448|    906|    }
 3449|       |
 3450|    609|done:
 3451|    609|    talloc_free(sinfo.filename);
  ------------------
  |  |   47|    609|#define talloc_free                     ta_free
  ------------------
 3452|    609|    talloc_free(log);
  ------------------
  |  |   47|    609|#define talloc_free                     ta_free
  ------------------
 3453|    609|    return demuxer;
 3454|    608|}
demux.c:d_level:
 2844|  3.72k|{
 2845|  3.72k|    switch (level) {
  ------------------
  |  Branch (2845:13): [True: 0, False: 3.72k]
  ------------------
 2846|     18|    case DEMUX_CHECK_FORCE:  return "force";
  ------------------
  |  Branch (2846:5): [True: 18, False: 3.70k]
  ------------------
 2847|    548|    case DEMUX_CHECK_UNSAFE: return "unsafe";
  ------------------
  |  Branch (2847:5): [True: 548, False: 3.17k]
  ------------------
 2848|    443|    case DEMUX_CHECK_REQUEST:return "request";
  ------------------
  |  Branch (2848:5): [True: 443, False: 3.28k]
  ------------------
 2849|  2.71k|    case DEMUX_CHECK_NORMAL: return "normal";
  ------------------
  |  Branch (2849:5): [True: 2.71k, False: 1.00k]
  ------------------
 2850|  3.72k|    }
 2851|      0|    MP_ASSERT_UNREACHABLE();
  ------------------
  |  |   42|      0|#define MP_ASSERT_UNREACHABLE() (assert(!"unreachable"), __builtin_unreachable())
  ------------------
 2852|      0|}
demux.c:open_given_type:
 3267|  8.05k|{
 3268|  8.05k|    if (mp_cancel_test(sinfo->cancel))
  ------------------
  |  Branch (3268:9): [True: 5.24k, False: 2.81k]
  ------------------
 3269|  5.24k|        return NULL;
 3270|       |
 3271|  2.81k|    struct demuxer *demuxer = talloc_ptrtype(NULL, demuxer);
  ------------------
  |  |   34|  2.81k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  2.81k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  2.81k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3272|  2.81k|    struct m_config_cache *opts_cache =
 3273|  2.81k|        m_config_cache_alloc(demuxer, global, &demux_conf);
 3274|  2.81k|    struct demux_opts *opts = opts_cache->opts;
 3275|  2.81k|    *demuxer = (struct demuxer) {
 3276|  2.81k|        .desc = desc,
 3277|  2.81k|        .stream = stream,
 3278|  2.81k|        .cancel = sinfo->cancel,
 3279|  2.81k|        .seekable = sinfo->seekable,
 3280|  2.81k|        .filepos = -1,
 3281|  2.81k|        .global = global,
 3282|  2.81k|        .log = mp_log_new(demuxer, log, desc->name),
 3283|  2.81k|        .packet_pool = demux_packet_pool_get(global),
 3284|  2.81k|        .glog = log,
 3285|  2.81k|        .filename = talloc_strdup(demuxer, sinfo->filename),
  ------------------
  |  |   50|  2.81k|#define talloc_strdup                   ta_xstrdup
  ------------------
 3286|  2.81k|        .is_network = sinfo->is_network,
 3287|  2.81k|        .is_streaming = sinfo->is_streaming,
 3288|  2.81k|        .stream_origin = sinfo->stream_origin,
 3289|  2.81k|        .access_references = opts->access_references,
 3290|  2.81k|        .opts = opts,
 3291|  2.81k|        .opts_cache = opts_cache,
 3292|  2.81k|        .events = DEMUX_EVENT_ALL,
 3293|  2.81k|        .duration = -1,
 3294|  2.81k|    };
 3295|       |
 3296|  2.81k|    struct demux_internal *in = demuxer->in = talloc_ptrtype(demuxer, in);
  ------------------
  |  |   34|  2.81k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  2.81k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  2.81k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3297|  2.81k|    *in = (struct demux_internal){
 3298|  2.81k|        .global = global,
 3299|  2.81k|        .log = demuxer->log,
 3300|  2.81k|        .packet_pool = demux_packet_pool_get(global),
 3301|  2.81k|        .stats = stats_ctx_create(in, global, "demuxer"),
 3302|  2.81k|        .can_cache = params && params->is_top_level,
  ------------------
  |  Branch (3302:22): [True: 2.81k, False: 0]
  |  Branch (3302:32): [True: 1.53k, False: 1.27k]
  ------------------
 3303|  2.81k|        .can_record = params && params->stream_record,
  ------------------
  |  Branch (3303:23): [True: 2.81k, False: 0]
  |  Branch (3303:33): [True: 1.53k, False: 1.27k]
  ------------------
 3304|  2.81k|        .d_thread = talloc(demuxer, struct demuxer),
  ------------------
  |  |   26|  2.81k|#define talloc                          ta_xnew
  |  |  ------------------
  |  |  |  |  133|  2.81k|#define ta_xnew(...)                    ta_oom_g(ta_new(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  2.81k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3305|  2.81k|        .d_user = demuxer,
 3306|  2.81k|        .after_seek = true, // (assumed identical to initial demuxer state)
 3307|  2.81k|        .after_seek_to_start = true,
 3308|  2.81k|        .highest_av_pts = MP_NOPTS_VALUE,
  ------------------
  |  |   38|  2.81k|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
 3309|  2.81k|        .seeking_in_progress = MP_NOPTS_VALUE,
  ------------------
  |  |   38|  2.81k|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
 3310|  2.81k|        .demux_ts = MP_NOPTS_VALUE,
  ------------------
  |  |   38|  2.81k|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
 3311|  2.81k|        .owns_stream = !params->external_stream,
 3312|  2.81k|    };
 3313|  2.81k|    mp_mutex_init(&in->lock);
 3314|  2.81k|    mp_cond_init(&in->wakeup);
 3315|       |
 3316|  2.81k|    *in->d_thread = *demuxer;
 3317|       |
 3318|  2.81k|    in->d_thread->metadata = talloc_zero(in->d_thread, struct mp_tags);
  ------------------
  |  |   27|  2.81k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  2.81k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  2.81k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3319|       |
 3320|  2.81k|    mp_dbg(log, "Trying demuxer: %s (force-level: %s)\n",
  ------------------
  |  |   76|  2.81k|#define mp_dbg(log, ...)        mp_msg(log, MSGL_DEBUG, __VA_ARGS__)
  ------------------
 3321|  2.81k|           desc->name, d_level(check));
 3322|       |
 3323|  2.81k|    if (stream)
  ------------------
  |  Branch (3323:9): [True: 2.79k, False: 18]
  ------------------
 3324|  2.79k|        stream_seek(stream, 0);
 3325|       |
 3326|  2.81k|    in->d_thread->params = params; // temporary during open()
 3327|  2.81k|    int ret = demuxer->desc->open(in->d_thread, check);
 3328|  2.81k|    if (ret >= 0) {
  ------------------
  |  Branch (3328:9): [True: 321, False: 2.49k]
  ------------------
 3329|    321|        in->d_thread->params = NULL;
 3330|    321|        if (in->d_thread->filetype)
  ------------------
  |  Branch (3330:13): [True: 105, False: 216]
  ------------------
 3331|    105|            mp_verbose(log, "Detected file format: %s (%s)\n",
  ------------------
  |  |   75|    105|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
 3332|    321|                       in->d_thread->filetype, desc->desc);
 3333|    216|        else
 3334|    216|            mp_verbose(log, "Detected file format: %s\n", desc->desc);
  ------------------
  |  |   75|    216|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
 3335|    321|        if (!in->d_thread->seekable)
  ------------------
  |  Branch (3335:13): [True: 212, False: 109]
  ------------------
 3336|    212|            mp_verbose(log, "Stream is not seekable.\n");
  ------------------
  |  |   75|    212|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
 3337|    321|        if (!in->d_thread->seekable && opts->force_seekable) {
  ------------------
  |  Branch (3337:13): [True: 212, False: 109]
  |  Branch (3337:40): [True: 0, False: 212]
  ------------------
 3338|      0|            mp_warn(log, "Not seekable, but enabling seeking on user request.\n");
  ------------------
  |  |   73|      0|#define mp_warn(log, ...)       mp_msg(log, MSGL_WARN, __VA_ARGS__)
  ------------------
 3339|      0|            in->d_thread->seekable = true;
 3340|      0|            in->d_thread->partially_seekable = true;
 3341|      0|        }
 3342|    321|        demux_init_cuesheet(in->d_thread);
 3343|    321|        demux_init_ccs(demuxer, opts);
 3344|    321|        demux_convert_tags_charset(in->d_thread);
 3345|    321|        demux_copy(in->d_user, in->d_thread);
 3346|    321|        in->duration = in->d_thread->duration;
 3347|    321|        demuxer_sort_chapters(demuxer);
 3348|    321|        in->events = DEMUX_EVENT_ALL;
 3349|       |
 3350|    321|        struct demuxer *sub = NULL;
 3351|    321|        if (!(params && params->disable_timeline)) {
  ------------------
  |  Branch (3351:15): [True: 321, False: 0]
  |  Branch (3351:25): [True: 0, False: 321]
  ------------------
 3352|    321|            struct timeline *tl = timeline_load(global, log, demuxer);
 3353|    321|            if (tl) {
  ------------------
  |  Branch (3353:17): [True: 21, False: 300]
  ------------------
 3354|     21|                struct demuxer_params params2 = {0};
 3355|     21|                params2.timeline = tl;
 3356|     21|                params2.is_top_level = params && params->is_top_level;
  ------------------
  |  Branch (3356:40): [True: 21, False: 0]
  |  Branch (3356:50): [True: 21, False: 0]
  ------------------
 3357|     21|                params2.stream_record = params && params->stream_record;
  ------------------
  |  Branch (3357:41): [True: 21, False: 0]
  |  Branch (3357:51): [True: 21, False: 0]
  ------------------
 3358|     21|                sub =
 3359|     21|                    open_given_type(global, log, &demuxer_desc_timeline,
 3360|     21|                                    NULL, sinfo, &params2, DEMUX_CHECK_FORCE);
 3361|     21|                if (sub) {
  ------------------
  |  Branch (3361:21): [True: 18, False: 3]
  ------------------
 3362|     18|                    in->can_cache = false;
 3363|     18|                    in->can_record = false;
 3364|     18|                } else {
 3365|      3|                    timeline_destroy(tl);
 3366|      3|                }
 3367|     21|            }
 3368|    321|        }
 3369|       |
 3370|    321|        switch_to_fresh_cache_range(in);
 3371|       |
 3372|    321|        update_opts(demuxer);
 3373|       |
 3374|    321|        demux_update(demuxer, MP_NOPTS_VALUE);
  ------------------
  |  |   38|    321|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
 3375|       |
 3376|    321|        demuxer = sub ? sub : demuxer;
  ------------------
  |  Branch (3376:19): [True: 18, False: 303]
  ------------------
 3377|    321|        return demuxer;
 3378|    321|    }
 3379|       |
 3380|  2.49k|    demuxer->stream = NULL;
 3381|  2.49k|    demux_free(demuxer);
 3382|  2.49k|    return NULL;
 3383|  2.81k|}
demux.c:demux_init_cuesheet:
 3177|    321|{
 3178|    321|    if (demuxer->num_chapters)
  ------------------
  |  Branch (3178:9): [True: 18, False: 303]
  ------------------
 3179|     18|        return;
 3180|       |
 3181|    303|    struct sh_stream *sh = demuxer->in->metadata_stream;
 3182|    303|    char *cue = mp_tags_get_str(demuxer->metadata, "cuesheet");
 3183|    303|    if (!cue && sh)
  ------------------
  |  Branch (3183:9): [True: 303, False: 0]
  |  Branch (3183:17): [True: 75, False: 228]
  ------------------
 3184|     75|        cue = mp_tags_get_str(sh->tags, "cuesheet");
 3185|    303|    if (!cue)
  ------------------
  |  Branch (3185:9): [True: 303, False: 0]
  ------------------
 3186|    303|        return;
 3187|       |
 3188|      0|    struct cue_file *f = mp_parse_cue(bstr0(cue));
 3189|      0|    if (f) {
  ------------------
  |  Branch (3189:9): [True: 0, False: 0]
  ------------------
 3190|      0|        if (mp_check_embedded_cue(f) < 0) {
  ------------------
  |  Branch (3190:13): [True: 0, False: 0]
  ------------------
 3191|      0|            MP_WARN(demuxer, "Embedded cue sheet references more than one file. "
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 3192|      0|                    "Ignoring it.\n");
 3193|      0|        } else {
 3194|      0|            for (int n = 0; n < f->num_tracks; n++) {
  ------------------
  |  Branch (3194:29): [True: 0, False: 0]
  ------------------
 3195|      0|                struct cue_track *t = &f->tracks[n];
 3196|      0|                int idx = demuxer_add_chapter(demuxer, "", t->start, -1);
 3197|      0|                mp_tags_merge(demuxer->chapters[idx].metadata, t->tags);
 3198|      0|            }
 3199|      0|        }
 3200|      0|        talloc_free(f);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 3201|      0|    }
 3202|      0|}
demux.c:demux_init_ccs:
 3225|    321|{
 3226|    321|    struct demux_internal *in = demuxer->in;
 3227|    321|    if (!opts->create_ccs)
  ------------------
  |  Branch (3227:9): [True: 321, False: 0]
  ------------------
 3228|    321|        return;
 3229|      0|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|      0|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 3230|      0|    for (int n = 0; n < in->num_streams; n++) {
  ------------------
  |  Branch (3230:21): [True: 0, False: 0]
  ------------------
 3231|      0|        struct sh_stream *sh = in->streams[n];
 3232|      0|        if (sh->type == STREAM_VIDEO && !sh->attached_picture)
  ------------------
  |  Branch (3232:13): [True: 0, False: 0]
  |  Branch (3232:41): [True: 0, False: 0]
  ------------------
 3233|      0|            demuxer_get_cc_track_locked(sh);
 3234|      0|    }
 3235|      0|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 3236|      0|}
demux.c:demux_convert_tags_charset:
 4664|    321|{
 4665|    321|    struct demux_internal *in = demuxer->in;
 4666|       |
 4667|    321|    char *cp = demuxer->opts->meta_cp;
 4668|    321|    if (!cp || mp_charset_is_utf8(cp))
  ------------------
  |  Branch (4668:9): [True: 0, False: 321]
  |  Branch (4668:16): [True: 0, False: 321]
  ------------------
 4669|      0|        return;
 4670|       |
 4671|    321|    char *data = talloc_strdup(NULL, "");
  ------------------
  |  |   50|    321|#define talloc_strdup                   ta_xstrdup
  ------------------
 4672|    321|    visit_meta(demuxer, &data, visit_detect);
 4673|       |
 4674|    321|    in->meta_charset = (char *)mp_charset_guess(in, in->log, bstr0(data), cp, 0);
 4675|    321|    if (in->meta_charset && !mp_charset_is_utf8(in->meta_charset)) {
  ------------------
  |  Branch (4675:9): [True: 321, False: 0]
  |  Branch (4675:29): [True: 24, False: 297]
  ------------------
 4676|     24|        MP_INFO(demuxer, "Using tag charset: %s\n", in->meta_charset);
  ------------------
  |  |   87|     24|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     24|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 4677|     24|        visit_meta(demuxer, demuxer, visit_convert);
 4678|     24|    }
 4679|       |
 4680|    321|    talloc_free(data);
  ------------------
  |  |   47|    321|#define talloc_free                     ta_free
  ------------------
 4681|    321|}
demux.c:visit_meta:
 4618|    345|{
 4619|    345|    struct demux_internal *in = demuxer->in;
 4620|       |
 4621|    432|    for (int n = 0; n < in->num_streams; n++) {
  ------------------
  |  Branch (4621:21): [True: 87, False: 345]
  ------------------
 4622|     87|        struct sh_stream *sh = in->streams[n];
 4623|       |
 4624|     87|        visit(ctx, sh, &sh->title);
 4625|     87|        visit_tags(ctx, visit, sh->tags);
 4626|     87|    }
 4627|       |
 4628|    449|    for (int n = 0; n < demuxer->num_chapters; n++)
  ------------------
  |  Branch (4628:21): [True: 104, False: 345]
  ------------------
 4629|    104|        visit_tags(ctx, visit, demuxer->chapters[n].metadata);
 4630|       |
 4631|    345|    visit_tags(ctx, visit, demuxer->metadata);
 4632|    345|}
demux.c:visit_tags:
 4611|    536|{
 4612|    653|    for (int n = 0; n < (tags ? tags->num_keys : 0); n++)
  ------------------
  |  Branch (4612:21): [True: 117, False: 536]
  |  Branch (4612:26): [True: 653, False: 0]
  ------------------
 4613|    117|        visit(ctx, tags, &tags->values[n]);
 4614|    536|}
demux.c:visit_detect:
 4636|    140|{
 4637|    140|    char **all = ctx;
 4638|       |
 4639|    140|    if (*s)
  ------------------
  |  Branch (4639:9): [True: 59, False: 81]
  ------------------
 4640|     59|        *all = talloc_asprintf_append_buffer(*all, "%s\n", *s);
  ------------------
  |  |   64|     59|#define talloc_asprintf_append_buffer   ta_talloc_asprintf_append_buffer
  ------------------
 4641|    140|}
demux.c:visit_convert:
 4644|     64|{
 4645|     64|    struct demuxer *demuxer = ctx;
 4646|     64|    struct demux_internal *in = demuxer->in;
 4647|       |
 4648|     64|    if (!*s)
  ------------------
  |  Branch (4648:9): [True: 6, False: 58]
  ------------------
 4649|      6|        return;
 4650|       |
 4651|     58|    bstr data = bstr0(*s);
 4652|     58|    bstr conv = mp_iconv_to_utf8(in->log, data, in->meta_charset,
 4653|     58|                                 MP_ICONV_VERBOSE);
 4654|     58|    if (conv.start && conv.start != data.start) {
  ------------------
  |  Branch (4654:9): [True: 58, False: 0]
  |  Branch (4654:23): [True: 58, False: 0]
  ------------------
 4655|     58|        char *ns = conv.start; // 0-termination is guaranteed
 4656|       |        // (The old string might not be an alloc, but if it is, it's a talloc
 4657|       |        // child, and will not leak, even if it stays allocated uselessly.)
 4658|     58|        *s = ns;
 4659|     58|        talloc_steal(ta, *s);
  ------------------
  |  |   38|     58|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     58|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 4660|     58|    }
 4661|     58|}
demux.c:demux_copy:
 2973|    321|{
 2974|       |    // Note that we do as shallow copies as possible. We expect the data
 2975|       |    // that is not-copied (only referenced) to be immutable.
 2976|       |    // This implies e.g. that no chapters are added after initialization.
 2977|    321|    dst->chapters = src->chapters;
 2978|    321|    dst->num_chapters = src->num_chapters;
 2979|    321|    dst->editions = src->editions;
 2980|    321|    dst->num_editions = src->num_editions;
 2981|    321|    dst->edition = src->edition;
 2982|    321|    dst->attachments = src->attachments;
 2983|    321|    dst->num_attachments = src->num_attachments;
 2984|    321|    dst->matroska_data = src->matroska_data;
 2985|    321|    dst->playlist = src->playlist;
 2986|    321|    dst->seekable = src->seekable;
 2987|    321|    dst->partially_seekable = src->partially_seekable;
 2988|    321|    dst->filetype = src->filetype;
 2989|    321|    dst->ts_resets_possible = src->ts_resets_possible;
 2990|    321|    dst->fully_read = src->fully_read;
 2991|    321|    dst->start_time = src->start_time;
 2992|    321|    dst->duration = src->duration;
 2993|    321|    dst->is_network = src->is_network;
 2994|    321|    dst->is_streaming = src->is_streaming;
 2995|    321|    dst->stream_origin = src->stream_origin;
 2996|    321|    dst->priv = src->priv;
 2997|    321|    dst->metadata = mp_tags_dup(dst, src->metadata);
 2998|    321|}
demux.c:demuxer_sort_chapters:
 4099|    321|{
 4100|    321|    if (demuxer->num_chapters) {
  ------------------
  |  Branch (4100:9): [True: 18, False: 303]
  ------------------
 4101|     18|        qsort(demuxer->chapters, demuxer->num_chapters,
 4102|     18|            sizeof(struct demux_chapter), chapter_compare);
 4103|     18|    }
 4104|    321|}
demux.c:chapter_compare:
 4087|     45|{
 4088|     45|    struct demux_chapter *c1 = (void *)p1;
 4089|     45|    struct demux_chapter *c2 = (void *)p2;
 4090|       |
 4091|     45|    if (c1->pts > c2->pts)
  ------------------
  |  Branch (4091:9): [True: 0, False: 45]
  ------------------
 4092|      0|        return 1;
 4093|     45|    else if (c1->pts < c2->pts)
  ------------------
  |  Branch (4093:14): [True: 45, False: 0]
  ------------------
 4094|     45|        return -1;
 4095|      0|    return c1->original_index > c2->original_index ? 1 :-1; // never equal
  ------------------
  |  Branch (4095:12): [True: 0, False: 0]
  ------------------
 4096|     45|}
demux.c:switch_to_fresh_cache_range:
 3774|    321|{
 3775|    321|    if (!in->seekable_cache && in->current_range) {
  ------------------
  |  Branch (3775:9): [True: 321, False: 0]
  |  Branch (3775:32): [True: 0, False: 321]
  ------------------
 3776|      0|        clear_cached_range(in, in->current_range);
 3777|      0|        return;
 3778|      0|    }
 3779|       |
 3780|    321|    struct demux_cached_range *range = talloc_ptrtype(NULL, range);
  ------------------
  |  |   34|    321|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|    321|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    321|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3781|    321|    *range = (struct demux_cached_range){
 3782|    321|        .seek_start = MP_NOPTS_VALUE,
  ------------------
  |  |   38|    321|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
 3783|    321|        .seek_end = MP_NOPTS_VALUE,
  ------------------
  |  |   38|    321|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
 3784|    321|    };
 3785|    321|    MP_TARRAY_APPEND(in, in->ranges, in->num_ranges, range);
  ------------------
  |  |  105|    321|    do {                                            \
  |  |  106|    321|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|    321|    do {                                            \
  |  |  |  |   97|    321|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|    321|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|    321|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|    321|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 321, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|    321|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|    321|    do {                                                        \
  |  |  |  |  |  |   89|    321|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|    321|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|    321|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|    321|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|    321|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|    321|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|    321|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|    321|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|    321|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|    321|        (idxvar)++;                                 \
  |  |  109|    321|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 3786|    321|    add_missing_streams(in, range);
 3787|       |
 3788|    321|    switch_current_range(in, range);
 3789|    321|}
demux.c:switch_current_range:
 3538|    321|{
 3539|    321|    struct demux_cached_range *old = in->current_range;
 3540|    321|    mp_assert(old != range);
  ------------------
  |  |   41|    321|#define mp_assert assert
  ------------------
 3541|       |
 3542|    321|    set_current_range(in, range);
 3543|       |
 3544|    321|    if (old) {
  ------------------
  |  Branch (3544:9): [True: 0, False: 321]
  ------------------
 3545|       |        // Remove packets which can't be used when seeking back to the range.
 3546|      0|        for (int n = 0; n < in->num_streams; n++) {
  ------------------
  |  Branch (3546:25): [True: 0, False: 0]
  ------------------
 3547|      0|            struct demux_queue *queue = old->streams[n];
 3548|       |
 3549|       |            // Remove all packets which cannot be involved in seeking.
 3550|      0|            while (queue->head && !queue->head->keyframe)
  ------------------
  |  Branch (3550:20): [True: 0, False: 0]
  |  Branch (3550:35): [True: 0, False: 0]
  ------------------
 3551|      0|                remove_head_packet(queue);
 3552|      0|        }
 3553|       |
 3554|       |        // Exclude weird corner cases that break resuming.
 3555|      0|        for (int n = 0; n < in->num_streams; n++) {
  ------------------
  |  Branch (3555:25): [True: 0, False: 0]
  ------------------
 3556|      0|            struct demux_stream *ds = in->streams[n]->ds;
 3557|       |            // This is needed to resume or join the range at all.
 3558|      0|            if (ds->selected && !(ds->global_correct_dts ||
  ------------------
  |  Branch (3558:17): [True: 0, False: 0]
  |  Branch (3558:35): [True: 0, False: 0]
  ------------------
 3559|      0|                                  ds->global_correct_pos))
  ------------------
  |  Branch (3559:35): [True: 0, False: 0]
  ------------------
 3560|      0|            {
 3561|      0|                MP_VERBOSE(in, "discarding unseekable range due to stream %d\n", n);
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 3562|      0|                clear_cached_range(in, old);
 3563|      0|                break;
 3564|      0|            }
 3565|      0|        }
 3566|      0|    }
 3567|       |
 3568|       |    // Set up reading from new range (as well as writing to it).
 3569|    402|    for (int n = 0; n < in->num_streams; n++) {
  ------------------
  |  Branch (3569:21): [True: 81, False: 321]
  ------------------
 3570|     81|        struct demux_stream *ds = in->streams[n]->ds;
 3571|       |
 3572|     81|        ds->queue = range->streams[n];
 3573|     81|        ds->refreshing = false;
 3574|     81|        ds->eof = false;
 3575|     81|    }
 3576|       |
 3577|       |    // No point in keeping any junk (especially if old current_range is empty).
 3578|    321|    free_empty_cached_ranges(in);
 3579|       |
 3580|       |    // The change detection doesn't work across ranges.
 3581|    321|    in->force_metadata_update = true;
 3582|    321|}
demux.c:set_current_range:
  555|    321|{
  556|    321|    in->current_range = range;
  557|       |
  558|       |    // Move to in->ranges[in->num_ranges-1] (for LRU sorting/invariant)
  559|    321|    for (int n = 0; n < in->num_ranges; n++) {
  ------------------
  |  Branch (559:21): [True: 321, False: 0]
  ------------------
  560|    321|        if (in->ranges[n] == range) {
  ------------------
  |  Branch (560:13): [True: 321, False: 0]
  ------------------
  561|    321|            MP_TARRAY_REMOVE_AT(in->ranges, in->num_ranges, n);
  ------------------
  |  |  143|    321|    do {                                            \
  |  |  144|    321|        size_t at_ = (at);                          \
  |  |  145|    321|        assert(at_ <= (idxvar));                    \
  |  |  146|    321|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|    321|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|    321|        (idxvar)--;                                 \
  |  |  149|    321|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  562|    321|            break;
  563|    321|        }
  564|    321|    }
  565|    321|    MP_TARRAY_APPEND(in, in->ranges, in->num_ranges, range);
  ------------------
  |  |  105|    321|    do {                                            \
  |  |  106|    321|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|    321|    do {                                            \
  |  |  |  |   97|    321|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|    321|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|    321|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|    321|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 321]
  |  |  |  |  ------------------
  |  |  |  |   99|    321|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|    321|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|    321|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|    321|        (idxvar)++;                                 \
  |  |  109|    321|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  566|    321|}
demux.c:clear_reader_state:
  839|  2.81k|{
  840|  2.89k|    for (int n = 0; n < in->num_streams; n++)
  ------------------
  |  Branch (840:21): [True: 81, False: 2.81k]
  ------------------
  841|     81|        ds_clear_reader_state(in->streams[n]->ds, clear_back_state);
  842|  2.81k|    in->warned_queue_overflow = false;
  843|  2.81k|    in->d_user->filepos = -1; // implicitly synchronized
  844|  2.81k|    in->blocked = false;
  845|  2.81k|    in->need_back_seek = false;
  846|  2.81k|}
demux.c:clear_cached_range:
  750|    642|{
  751|    804|    for (int n = 0; n < range->num_streams; n++)
  ------------------
  |  Branch (751:21): [True: 162, False: 642]
  ------------------
  752|    162|        clear_queue(range->streams[n]);
  753|       |
  754|    642|    for (int n = 0; n < range->num_metadata; n++)
  ------------------
  |  Branch (754:21): [True: 0, False: 642]
  ------------------
  755|      0|        talloc_free(range->metadata[n]);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  756|    642|    range->num_metadata = 0;
  757|       |
  758|    642|    update_seek_ranges(range);
  759|    642|}
demux.c:free_empty_cached_ranges:
  764|  6.35k|{
  765|  6.35k|    while (1) {
  ------------------
  |  Branch (765:12): [Folded - Ignored]
  ------------------
  766|  6.35k|        struct demux_cached_range *worst = NULL;
  767|       |
  768|  6.35k|        int end = in->num_ranges - 1;
  769|       |
  770|       |        // (Not set during early init or late destruction.)
  771|  6.35k|        if (in->current_range) {
  ------------------
  |  Branch (771:13): [True: 963, False: 5.39k]
  ------------------
  772|    963|            mp_assert(in->current_range && in->num_ranges > 0);
  ------------------
  |  |   41|    963|#define mp_assert assert
  ------------------
  773|    963|            mp_assert(in->current_range == in->ranges[in->num_ranges - 1]);
  ------------------
  |  |   41|    963|#define mp_assert assert
  ------------------
  774|    963|            end -= 1;
  775|    963|        }
  776|       |
  777|  6.67k|        for (int n = end; n >= 0; n--) {
  ------------------
  |  Branch (777:27): [True: 321, False: 6.35k]
  ------------------
  778|    321|            struct demux_cached_range *range = in->ranges[n];
  779|    321|            if (range->seek_start == MP_NOPTS_VALUE || !in->seekable_cache) {
  ------------------
  |  |   38|    642|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (779:17): [True: 321, False: 0]
  |  Branch (779:56): [True: 0, False: 0]
  ------------------
  780|    321|                clear_cached_range(in, range);
  781|    321|                MP_TARRAY_REMOVE_AT(in->ranges, in->num_ranges, n);
  ------------------
  |  |  143|    321|    do {                                            \
  |  |  144|    321|        size_t at_ = (at);                          \
  |  |  145|    321|        assert(at_ <= (idxvar));                    \
  |  |  146|    321|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|    321|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|    321|        (idxvar)--;                                 \
  |  |  149|    321|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  782|    402|                for (int i = 0; i < range->num_streams; i++)
  ------------------
  |  Branch (782:33): [True: 81, False: 321]
  ------------------
  783|     81|                    talloc_free(range->streams[i]);
  ------------------
  |  |   47|     81|#define talloc_free                     ta_free
  ------------------
  784|    321|                talloc_free(range);
  ------------------
  |  |   47|    321|#define talloc_free                     ta_free
  ------------------
  785|    321|            } else {
  786|      0|                if (!worst || (range->seek_end - range->seek_start <
  ------------------
  |  Branch (786:21): [True: 0, False: 0]
  |  Branch (786:31): [True: 0, False: 0]
  ------------------
  787|      0|                               worst->seek_end - worst->seek_start))
  788|      0|                    worst = range;
  789|      0|            }
  790|    321|        }
  791|       |
  792|  6.35k|        if (in->num_ranges <= MAX_SEEK_RANGES || !worst)
  ------------------
  |  |   33|  12.7k|#define MAX_SEEK_RANGES 10
  ------------------
  |  Branch (792:13): [True: 6.35k, False: 0]
  |  Branch (792:50): [True: 0, False: 0]
  ------------------
  793|  6.35k|            break;
  794|       |
  795|      0|        clear_cached_range(in, worst);
  796|      0|    }
  797|  6.35k|}
demux.c:update_stream_selection_state:
  866|     81|{
  867|     81|    ds->eof = false;
  868|     81|    ds->refreshing = false;
  869|       |
  870|       |    // We still have to go over the whole stream list to update ds->eager for
  871|       |    // other streams too, because they depend on other stream's selections.
  872|       |
  873|     81|    bool any_av_streams = false;
  874|     81|    bool any_streams = false;
  875|       |
  876|    162|    for (int n = 0; n < in->num_streams; n++) {
  ------------------
  |  Branch (876:21): [True: 81, False: 81]
  ------------------
  877|     81|        struct demux_stream *s = in->streams[n]->ds;
  878|       |
  879|     81|        s->still_image = s->sh->still_image;
  880|     81|        s->eager = s->selected && !s->sh->attached_picture;
  ------------------
  |  Branch (880:20): [True: 0, False: 81]
  |  Branch (880:35): [True: 0, False: 0]
  ------------------
  881|     81|        if (s->eager && !s->still_image)
  ------------------
  |  Branch (881:13): [True: 0, False: 81]
  |  Branch (881:25): [True: 0, False: 0]
  ------------------
  882|      0|            any_av_streams |= s->type != STREAM_SUB;
  883|     81|        any_streams |= s->selected;
  884|     81|    }
  885|       |
  886|       |    // Subtitles are only eagerly read if there are no other eagerly read
  887|       |    // streams.
  888|     81|    if (any_av_streams) {
  ------------------
  |  Branch (888:9): [True: 0, False: 81]
  ------------------
  889|      0|        for (int n = 0; n < in->num_streams; n++) {
  ------------------
  |  Branch (889:25): [True: 0, False: 0]
  ------------------
  890|      0|            struct demux_stream *s = in->streams[n]->ds;
  891|       |
  892|      0|            if (s->type == STREAM_SUB)
  ------------------
  |  Branch (892:17): [True: 0, False: 0]
  ------------------
  893|      0|                s->eager = false;
  894|      0|        }
  895|      0|    }
  896|       |
  897|     81|    if (!any_streams)
  ------------------
  |  Branch (897:9): [True: 81, False: 0]
  ------------------
  898|     81|        in->blocked = false;
  899|       |
  900|     81|    ds_clear_reader_state(ds, true);
  901|       |
  902|       |    // Make sure any stream reselection or addition is reflected in the seek
  903|       |    // ranges, and also get rid of data that is not needed anymore (or
  904|       |    // rather, which can't be kept consistent). This has to happen after we've
  905|       |    // updated all the subtle state (like s->eager).
  906|     81|    for (int n = 0; n < in->num_ranges; n++) {
  ------------------
  |  Branch (906:21): [True: 0, False: 81]
  ------------------
  907|      0|        struct demux_cached_range *range = in->ranges[n];
  908|       |
  909|      0|        if (!ds->selected)
  ------------------
  |  Branch (909:13): [True: 0, False: 0]
  ------------------
  910|      0|            clear_queue(range->streams[ds->index]);
  911|       |
  912|      0|        update_seek_ranges(range);
  913|      0|    }
  914|       |
  915|     81|    free_empty_cached_ranges(in);
  916|       |
  917|     81|    wakeup_ds(ds);
  918|     81|}
demux.c:wakeup_ds:
  852|     81|{
  853|     81|    if (ds->need_wakeup) {
  ------------------
  |  Branch (853:9): [True: 81, False: 0]
  ------------------
  854|     81|        if (ds->wakeup_cb) {
  ------------------
  |  Branch (854:13): [True: 0, False: 81]
  ------------------
  855|      0|            ds->wakeup_cb(ds->wakeup_cb_ctx);
  856|     81|        } else if (ds->in->wakeup_cb) {
  ------------------
  |  Branch (856:20): [True: 0, False: 81]
  ------------------
  857|      0|            ds->in->wakeup_cb(ds->in->wakeup_cb_ctx);
  858|      0|        }
  859|     81|        ds->need_wakeup = false;
  860|     81|        mp_cond_signal(&ds->in->wakeup);
  861|     81|    }
  862|     81|}
demux.c:update_cache:
 4161|    321|{
 4162|    321|    struct demuxer *demuxer = in->d_thread;
 4163|    321|    struct stream *stream = demuxer->stream;
 4164|       |
 4165|    321|    int64_t now = mp_time_ns();
 4166|    321|    int64_t diff = now - in->last_speed_query;
 4167|    321|    bool do_update = diff >= MP_TIME_S_TO_NS(1) || !in->last_speed_query;
  ------------------
  |  |   59|    642|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  |  Branch (4167:22): [True: 321, False: 0]
  |  Branch (4167:52): [True: 0, False: 0]
  ------------------
 4168|       |
 4169|       |    // Don't lock while querying the stream.
 4170|    321|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|    321|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 4171|       |
 4172|    321|    int64_t stream_size = -1;
 4173|    321|    struct mp_tags *stream_metadata = NULL;
 4174|    321|    if (stream) {
  ------------------
  |  Branch (4174:9): [True: 189, False: 132]
  ------------------
 4175|    189|        if (do_update)
  ------------------
  |  Branch (4175:13): [True: 189, False: 0]
  ------------------
 4176|    189|            stream_size = stream_get_size(stream);
 4177|    189|        stream_control(stream, STREAM_CTRL_GET_METADATA, &stream_metadata);
 4178|    189|    }
 4179|       |
 4180|    321|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|    321|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 4181|       |
 4182|    321|    update_bytes_read(in);
 4183|       |
 4184|    321|    if (do_update)
  ------------------
  |  Branch (4184:9): [True: 321, False: 0]
  ------------------
 4185|    321|        in->stream_size = stream_size;
 4186|    321|    if (stream_metadata) {
  ------------------
  |  Branch (4186:9): [True: 0, False: 321]
  ------------------
 4187|      0|        add_timed_metadata(in, stream_metadata, NULL, MP_NOPTS_VALUE);
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
 4188|      0|        talloc_free(stream_metadata);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 4189|      0|    }
 4190|       |
 4191|    321|    in->next_cache_update = INT64_MAX;
 4192|       |
 4193|    321|    if (do_update) {
  ------------------
  |  Branch (4193:9): [True: 321, False: 0]
  ------------------
 4194|    321|        uint64_t bytes = in->cache_unbuffered_read_bytes;
 4195|    321|        in->cache_unbuffered_read_bytes = 0;
 4196|    321|        in->last_speed_query = now;
 4197|    321|        double speed = bytes / (diff / (double)MP_TIME_S_TO_NS(1));
  ------------------
  |  |   59|    321|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
 4198|    321|        in->bytes_per_second = 0.5 * in->speed_query_prev_sample +
 4199|    321|                               0.5 * speed;
 4200|    321|        in->speed_query_prev_sample = speed;
 4201|    321|    }
 4202|       |    // The idea is to update as long as there is "activity".
 4203|    321|    if (in->bytes_per_second)
  ------------------
  |  Branch (4203:9): [True: 29, False: 292]
  ------------------
 4204|     29|        in->next_cache_update = now + MP_TIME_S_TO_NS(1) + MP_TIME_US_TO_NS(1);
  ------------------
  |  |   59|     29|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
                      in->next_cache_update = now + MP_TIME_S_TO_NS(1) + MP_TIME_US_TO_NS(1);
  ------------------
  |  |   61|     29|#define MP_TIME_US_TO_NS(us) ((us) * INT64_C(1000))
  ------------------
 4205|    321|}
demux.c:dumper_close:
 4208|  2.81k|{
 4209|  2.81k|    if (in->dumper)
  ------------------
  |  Branch (4209:9): [True: 0, False: 2.81k]
  ------------------
 4210|      0|        mp_recorder_destroy(in->dumper);
 4211|  2.81k|    in->dumper = NULL;
 4212|  2.81k|    if (in->dumper_status == CONTROL_TRUE)
  ------------------
  |  |   69|  2.81k|#define CONTROL_TRUE 1
  ------------------
  |  Branch (4212:9): [True: 0, False: 2.81k]
  ------------------
 4213|      0|        in->dumper_status = CONTROL_FALSE; // make abort equal to success
  ------------------
  |  |   70|      0|#define CONTROL_FALSE 0
  ------------------
 4214|  2.81k|}
demux.c:update_bytes_read:
 4138|    335|{
 4139|    335|    struct demuxer *demuxer = in->d_thread;
 4140|       |
 4141|    335|    int64_t new = in->slave_unbuffered_read_bytes;
 4142|    335|    in->slave_unbuffered_read_bytes = 0;
 4143|       |
 4144|    335|    int64_t new_seeks = 0;
 4145|       |
 4146|    335|    struct stream *stream = demuxer->stream;
 4147|    335|    if (stream) {
  ------------------
  |  Branch (4147:9): [True: 202, False: 133]
  ------------------
 4148|    202|        new += stream->total_unbuffered_read_bytes;
 4149|    202|        stream->total_unbuffered_read_bytes = 0;
 4150|    202|        new_seeks += stream->total_stream_seeks;
 4151|    202|        stream->total_stream_seeks = 0;
 4152|    202|    }
 4153|       |
 4154|    335|    in->cache_unbuffered_read_bytes += new;
 4155|    335|    in->hack_unbuffered_read_bytes += new;
 4156|    335|    in->byte_level_seeks += new_seeks;
 4157|    335|}
demux.c:get_forward_buffered_bytes:
  457|     81|{
  458|     81|    if (!ds->reader_head)
  ------------------
  |  Branch (458:9): [True: 81, False: 0]
  ------------------
  459|     81|        return 0;
  460|      0|    return ds->queue->tail_cum_pos - ds->reader_head->cum_pos;
  461|     81|}
demux.c:get_demux_sub_opts:
 4684|   221k|{
 4685|   221k|    if (!demuxer_list[index])
  ------------------
  |  Branch (4685:9): [True: 17.0k, False: 204k]
  ------------------
 4686|  17.0k|        return false;
 4687|   204k|    *sub = demuxer_list[index]->options;
 4688|   204k|    return true;
 4689|   221k|}

demux_cue.c:try_open_file:
  248|    296|{
  249|    296|    if (!demuxer->access_references)
  ------------------
  |  Branch (249:9): [True: 0, False: 296]
  ------------------
  250|      0|        return -1;
  251|       |
  252|    296|    struct stream *s = demuxer->stream;
  253|    296|    if (check >= DEMUX_CHECK_UNSAFE) {
  ------------------
  |  Branch (253:9): [True: 296, False: 0]
  ------------------
  254|    296|        char probe[PROBE_SIZE];
  255|    296|        int len = stream_read_peek(s, probe, sizeof(probe));
  256|    296|        if (len < 1 || !mp_probe_cue((bstr){probe, len}))
  ------------------
  |  Branch (256:13): [True: 1, False: 295]
  |  Branch (256:24): [True: 295, False: 0]
  ------------------
  257|    296|            return -1;
  258|    296|    }
  259|      0|    struct priv *p = talloc_zero(demuxer, struct priv);
  ------------------
  |  |   27|      0|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|      0|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  260|      0|    demuxer->priv = p;
  261|      0|    demuxer->fully_read = true;
  262|      0|    bstr data = stream_read_complete(s, p, 1000000);
  263|      0|    if (data.start == NULL)
  ------------------
  |  Branch (263:9): [True: 0, False: 0]
  ------------------
  264|      0|        return -1;
  265|       |
  266|      0|    struct demux_opts *opts = mp_get_config_group(p, demuxer->global, &demux_conf);
  267|      0|    const char *charset = mp_charset_guess(p, demuxer->log, data, opts->meta_cp, 0);
  268|      0|    if (charset && !mp_charset_is_utf8(charset)) {
  ------------------
  |  Branch (268:9): [True: 0, False: 0]
  |  Branch (268:20): [True: 0, False: 0]
  ------------------
  269|      0|        MP_INFO(demuxer, "Using CUE charset: %s\n", charset);
  ------------------
  |  |   87|      0|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  270|      0|        bstr utf8 = mp_iconv_to_utf8(demuxer->log, data, charset, MP_ICONV_VERBOSE);
  271|      0|        if (utf8.start && utf8.start != data.start) {
  ------------------
  |  Branch (271:13): [True: 0, False: 0]
  |  Branch (271:27): [True: 0, False: 0]
  ------------------
  272|      0|            ta_steal(data.start, utf8.start);
  ------------------
  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  ------------------
  273|      0|            data = utf8;
  274|      0|        }
  275|      0|    }
  276|      0|    talloc_free(opts);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  277|       |
  278|      0|    p->f = mp_parse_cue(data);
  279|      0|    talloc_steal(p, p->f);
  ------------------
  |  |   38|      0|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  280|      0|    if (!p->f) {
  ------------------
  |  Branch (280:9): [True: 0, False: 0]
  ------------------
  281|      0|        MP_ERR(demuxer, "error parsing input file!\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  282|      0|        return -1;
  283|      0|    }
  284|       |
  285|      0|    demux_close_stream(demuxer);
  286|       |
  287|      0|    mp_tags_merge(demuxer->metadata, p->f->tags);
  288|      0|    return 0;
  289|      0|}

demux_disc.c:d_open:
  313|    304|{
  314|    304|    struct priv *p = demuxer->priv = talloc_zero(demuxer, struct priv);
  ------------------
  |  |   27|    304|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    304|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    304|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  315|       |
  316|    304|    if (check != DEMUX_CHECK_FORCE)
  ------------------
  |  Branch (316:9): [True: 304, False: 0]
  ------------------
  317|    304|        return -1;
  318|       |
  319|      0|    struct demuxer_params params = {
  320|      0|        .force_format = "+lavf",
  321|      0|        .external_stream = demuxer->stream,
  322|      0|        .stream_flags = demuxer->stream_origin,
  323|      0|    };
  324|       |
  325|      0|    struct stream *cur = demuxer->stream;
  326|      0|    const char *sname = "";
  327|      0|    if (cur->info)
  ------------------
  |  Branch (327:9): [True: 0, False: 0]
  ------------------
  328|      0|        sname = cur->info->name;
  329|       |
  330|      0|    p->is_cdda = strcmp(sname, "cdda") == 0;
  331|      0|    p->is_dvd = strcmp(sname, "dvdnav") == 0 ||
  ------------------
  |  Branch (331:17): [True: 0, False: 0]
  ------------------
  332|      0|                strcmp(sname, "ifo_dvdnav") == 0;
  ------------------
  |  Branch (332:17): [True: 0, False: 0]
  ------------------
  333|       |
  334|      0|    if (p->is_cdda)
  ------------------
  |  Branch (334:9): [True: 0, False: 0]
  ------------------
  335|      0|        params.force_format = "+rawaudio";
  336|       |
  337|      0|    char *t = NULL;
  338|      0|    stream_control(demuxer->stream, STREAM_CTRL_GET_DISC_NAME, &t);
  339|      0|    if (t) {
  ------------------
  |  Branch (339:9): [True: 0, False: 0]
  ------------------
  340|      0|        mp_tags_set_str(demuxer->metadata, "TITLE", t);
  341|      0|        talloc_free(t);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  342|      0|    }
  343|       |
  344|       |    // Initialize the playback time. We need to read _some_ data to get the
  345|       |    // correct stream-layer time (at least with libdvdnav).
  346|      0|    stream_read_peek(demuxer->stream, &(char){0}, 1);
  347|      0|    reset_pts(demuxer);
  348|       |
  349|      0|    p->slave = demux_open_url("-", &params, demuxer->cancel, demuxer->global);
  350|      0|    if (!p->slave)
  ------------------
  |  Branch (350:9): [True: 0, False: 0]
  ------------------
  351|      0|        return -1;
  352|       |
  353|       |    // Can be seekable even if the stream isn't.
  354|      0|    demuxer->seekable = true;
  355|       |
  356|      0|    add_dvd_streams(demuxer);
  357|      0|    add_streams(demuxer);
  358|      0|    add_stream_chapters(demuxer);
  359|      0|    add_stream_editions(demuxer);
  360|       |
  361|      0|    double len;
  362|      0|    if (stream_control(demuxer->stream, STREAM_CTRL_GET_TIME_LENGTH, &len) >= 1)
  ------------------
  |  Branch (362:9): [True: 0, False: 0]
  ------------------
  363|      0|        demuxer->duration = len;
  364|       |
  365|      0|    unsigned title;
  366|      0|    if (stream_control(demuxer->stream, STREAM_CTRL_GET_CURRENT_TITLE, &title) >= 1)
  ------------------
  |  Branch (366:9): [True: 0, False: 0]
  ------------------
  367|      0|        demuxer->edition = title;
  368|       |
  369|      0|    return 0;
  370|      0|}
demux_disc.c:d_close:
  373|    304|{
  374|    304|    struct priv *p = demuxer->priv;
  375|    304|    demux_free(p->slave);
  376|    304|}

demux_edl.c:try_open_file:
  624|    429|{
  625|    429|    if (!demuxer->access_references)
  ------------------
  |  Branch (625:9): [True: 0, False: 429]
  ------------------
  626|      0|        return -1;
  627|       |
  628|    429|    struct priv *p = talloc_zero(demuxer, struct priv);
  ------------------
  |  |   27|    429|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    429|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    429|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  629|    429|    demuxer->priv = p;
  630|    429|    demuxer->fully_read = true;
  631|       |
  632|    429|    struct stream *s = demuxer->stream;
  633|    429|    if (s->info && strcmp(s->info->name, "edl") == 0) {
  ------------------
  |  Branch (633:9): [True: 429, False: 0]
  |  Branch (633:20): [True: 130, False: 299]
  ------------------
  634|    130|        p->data = bstr0(s->path);
  635|    130|        return 0;
  636|    130|    }
  637|    299|    if (check >= DEMUX_CHECK_UNSAFE) {
  ------------------
  |  Branch (637:9): [True: 299, False: 0]
  ------------------
  638|    299|        char header[sizeof(HEADER) - 1];
  639|    299|        int len = stream_read_peek(s, header, sizeof(header));
  640|    299|        if (len != strlen(HEADER) || memcmp(header, HEADER, len) != 0)
  ------------------
  |  |   38|    299|#define HEADER "# mpv EDL v0\n"
  ------------------
                      if (len != strlen(HEADER) || memcmp(header, HEADER, len) != 0)
  ------------------
  |  |   38|    281|#define HEADER "# mpv EDL v0\n"
  ------------------
  |  Branch (640:13): [True: 18, False: 281]
  |  Branch (640:38): [True: 281, False: 0]
  ------------------
  641|    299|            return -1;
  642|    299|    }
  643|      0|    p->data = stream_read_complete(s, demuxer, 1000000);
  644|      0|    if (p->data.start == NULL)
  ------------------
  |  Branch (644:9): [True: 0, False: 0]
  ------------------
  645|      0|        return -1;
  646|      0|    bstr_eatstart0(&p->data, HEADER);
  ------------------
  |  |   38|      0|#define HEADER "# mpv EDL v0\n"
  ------------------
  647|      0|    demux_close_stream(demuxer);
  648|      0|    return 0;
  649|      0|}
demux_edl.c:build_mpv_edl_timeline:
  588|    130|{
  589|    130|    struct priv *p = tl->demuxer->priv;
  590|       |
  591|    130|    struct tl_root *root = parse_edl(p->data, tl->log);
  592|    130|    if (!root) {
  ------------------
  |  Branch (592:9): [True: 3, False: 127]
  ------------------
  593|      3|        MP_ERR(tl, "Error in EDL.\n");
  ------------------
  |  |   85|      3|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      3|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  594|      3|        return;
  595|      3|    }
  596|       |
  597|    127|    bool all_dash = true;
  598|    127|    bool all_no_clip = true;
  599|    127|    bool all_single = true;
  600|       |
  601|    148|    for (int n = 0; n < root->num_pars; n++) {
  ------------------
  |  Branch (601:21): [True: 127, False: 21]
  ------------------
  602|    127|        struct tl_parts *parts = root->pars[n];
  603|    127|        fix_filenames(parts, tl->demuxer->filename);
  604|    127|        struct timeline_par *par = build_timeline(tl, root, parts);
  605|    127|        if (!par)
  ------------------
  |  Branch (605:13): [True: 106, False: 21]
  ------------------
  606|    106|            break;
  607|     21|        all_dash &= par->dash;
  608|     21|        all_no_clip &= par->no_clip;
  609|     21|        all_single &= par->num_parts == 1;
  610|     21|    }
  611|       |
  612|    127|    if (all_dash) {
  ------------------
  |  Branch (612:9): [True: 106, False: 21]
  ------------------
  613|    106|        tl->format = "dash";
  614|    106|    } else if (all_no_clip && all_single) {
  ------------------
  |  Branch (614:16): [True: 0, False: 21]
  |  Branch (614:31): [True: 0, False: 0]
  ------------------
  615|      0|        tl->format = "multi";
  616|     21|    } else {
  617|     21|        tl->format = "edl";
  618|     21|    }
  619|       |
  620|    127|    talloc_free(root);
  ------------------
  |  |   47|    127|#define talloc_free                     ta_free
  ------------------
  621|    127|}
demux_edl.c:parse_edl:
  174|    130|{
  175|    130|    struct tl_root *root = talloc_zero(NULL, struct tl_root);
  ------------------
  |  |   27|    130|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    130|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    130|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  176|    130|    root->tags = talloc_zero(root, struct mp_tags);
  ------------------
  |  |   27|    130|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    130|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    130|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  177|    130|    struct tl_parts *tl = add_part(root);
  178|  4.00k|    while (str.len) {
  ------------------
  |  Branch (178:12): [True: 3.87k, False: 128]
  ------------------
  179|  3.87k|        if (bstr_eatstart0(&str, "#")) {
  ------------------
  |  Branch (179:13): [True: 42, False: 3.83k]
  ------------------
  180|     42|            bstr_split_tok(str, "\n", &(bstr){0}, &str);
  181|     42|            continue;
  182|     42|        }
  183|  3.83k|        if (bstr_eatstart0(&str, "\n") || bstr_eatstart0(&str, ";"))
  ------------------
  |  Branch (183:13): [True: 0, False: 3.83k]
  |  Branch (183:43): [True: 1.87k, False: 1.96k]
  ------------------
  184|  1.87k|            continue;
  185|  1.96k|        bool is_header = bstr_eatstart0(&str, "!");
  186|  1.96k|        struct parse_ctx ctx = { .log = log };
  187|  1.96k|        int nparam = 0;
  188|  1.96k|        while (1) {
  ------------------
  |  Branch (188:16): [Folded - Ignored]
  ------------------
  189|  1.96k|            bstr name, val;
  190|       |            // Check if it's of the form "name=..."
  191|  1.96k|            int next = bstrcspn(str, "=%,;\n");
  192|  1.96k|            if (next > 0 && next < str.len && str.start[next] == '=') {
  ------------------
  |  Branch (192:17): [True: 1.38k, False: 575]
  |  Branch (192:29): [True: 1.35k, False: 27]
  |  Branch (192:47): [True: 0, False: 1.35k]
  ------------------
  193|      0|                name = bstr_splice(str, 0, next);
  194|      0|                str = bstr_cut(str, next + 1);
  195|  1.96k|            } else if (is_header) {
  ------------------
  |  Branch (195:24): [True: 47, False: 1.91k]
  ------------------
  196|     47|                const char *names[] = {"type"}; // implied name
  197|     47|                name = bstr0(nparam < 1 ? names[nparam] : "-");
  ------------------
  |  Branch (197:30): [True: 47, False: 0]
  ------------------
  198|  1.91k|            } else {
  199|  1.91k|                const char *names[] = {"file", "start", "length"}; // implied name
  200|  1.91k|                name = bstr0(nparam < 3 ? names[nparam] : "-");
  ------------------
  |  Branch (200:30): [True: 1.91k, False: 0]
  ------------------
  201|  1.91k|            }
  202|  1.96k|            if (bstr_eatstart0(&str, "%")) {
  ------------------
  |  Branch (202:17): [True: 575, False: 1.38k]
  ------------------
  203|    575|                int len = bstrtoll(str, &str, 0);
  204|    575|                if (!bstr_startswith0(str, "%") || (len > str.len - 1))
  ------------------
  |  Branch (204:21): [True: 0, False: 575]
  |  Branch (204:52): [True: 0, False: 575]
  ------------------
  205|      0|                    goto error;
  206|    575|                val = bstr_splice(str, 1, len + 1);
  207|    575|                str = bstr_cut(str, len + 1);
  208|  1.38k|            } else {
  209|  1.38k|                next = bstrcspn(str, ",;\n");
  210|  1.38k|                val = bstr_splice(str, 0, next);
  211|  1.38k|                str = bstr_cut(str, next);
  212|  1.38k|            }
  213|  1.96k|            if (ctx.num_params >= NUM_MAX_PARAMS) {
  ------------------
  |  |   72|  1.96k|#define NUM_MAX_PARAMS 20
  ------------------
  |  Branch (213:17): [True: 0, False: 1.96k]
  ------------------
  214|      0|                mp_err(log, "Too many parameters, ignoring '%.*s'.\n",
  ------------------
  |  |   72|      0|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  215|      0|                       BSTR_P(name));
  216|  1.96k|            } else {
  217|  1.96k|                ctx.param_names[ctx.num_params] = name;
  218|  1.96k|                ctx.param_vals[ctx.num_params] = val;
  219|  1.96k|                ctx.num_params += 1;
  220|  1.96k|            }
  221|  1.96k|            nparam++;
  222|  1.96k|            if (!bstr_eatstart0(&str, ","))
  ------------------
  |  Branch (222:17): [True: 1.96k, False: 0]
  ------------------
  223|  1.96k|                break;
  224|  1.96k|        }
  225|  1.96k|        if (is_header) {
  ------------------
  |  Branch (225:13): [True: 47, False: 1.91k]
  ------------------
  226|     47|            bstr f_type = get_param(&ctx, "type");
  227|     47|            if (bstr_equals0(f_type, "mp4_dash")) {
  ------------------
  |  Branch (227:17): [True: 0, False: 47]
  ------------------
  228|      0|                tl->dash = true;
  229|      0|                tl->init_fragment_url = get_param0(&ctx, tl, "init");
  230|     47|            } else if (bstr_equals0(f_type, "no_clip")) {
  ------------------
  |  Branch (230:24): [True: 0, False: 47]
  ------------------
  231|      0|                tl->no_clip = true;
  232|     47|            } else if (bstr_equals0(f_type, "new_stream")) {
  ------------------
  |  Branch (232:24): [True: 45, False: 2]
  ------------------
  233|       |                // (Special case: ignore "redundant" headers at the start for
  234|       |                // general symmetry.)
  235|     45|                if (root->num_pars > 1 || tl->num_parts)
  ------------------
  |  Branch (235:21): [True: 39, False: 6]
  |  Branch (235:43): [True: 5, False: 1]
  ------------------
  236|     44|                    tl = add_part(root);
  237|     45|            } else if (bstr_equals0(f_type, "no_chapters")) {
  ------------------
  |  Branch (237:24): [True: 0, False: 2]
  ------------------
  238|      0|                tl->disable_chapters = true;
  239|      2|            } else if (bstr_equals0(f_type, "track_meta")) {
  ------------------
  |  Branch (239:24): [True: 0, False: 2]
  ------------------
  240|      0|                int index = get_param_int(&ctx, "index", -1);
  241|      0|                struct sh_stream *sh = index < 0 && tl->num_sh_meta
  ------------------
  |  Branch (241:40): [True: 0, False: 0]
  |  Branch (241:53): [True: 0, False: 0]
  ------------------
  242|      0|                    ? tl->sh_meta[tl->num_sh_meta - 1]
  243|      0|                    : get_meta(tl, index);
  244|      0|                sh->lang = get_param0(&ctx, sh, "lang");
  245|      0|                sh->title = get_param0(&ctx, sh, "title");
  246|      0|                sh->hls_bitrate = get_param_int(&ctx, "byterate", 0) * 8;
  247|      0|                bstr flags = get_param(&ctx, "flags");
  248|      0|                bstr flag;
  249|      0|                while (bstr_split_tok(flags, "+", &flag, &flags) || flag.len) {
  ------------------
  |  Branch (249:24): [True: 0, False: 0]
  |  Branch (249:69): [True: 0, False: 0]
  ------------------
  250|      0|                    if (bstr_equals0(flag, "default")) {
  ------------------
  |  Branch (250:25): [True: 0, False: 0]
  ------------------
  251|      0|                        sh->default_track = true;
  252|      0|                    } else if (bstr_equals0(flag, "forced")) {
  ------------------
  |  Branch (252:32): [True: 0, False: 0]
  ------------------
  253|      0|                        sh->forced_track = true;
  254|      0|                    } else {
  255|      0|                        mp_warn(log, "Unknown flag: '%.*s'\n", BSTR_P(flag));
  ------------------
  |  |   73|      0|#define mp_warn(log, ...)       mp_msg(log, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (73:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  256|      0|                    }
  257|      0|                }
  258|      2|            } else if (bstr_equals0(f_type, "delay_open")) {
  ------------------
  |  Branch (258:24): [True: 0, False: 2]
  ------------------
  259|      0|                struct sh_stream *sh = get_meta(tl, tl->num_sh_meta);
  260|      0|                bstr mt = get_param(&ctx, "media_type");
  261|      0|                if (bstr_equals0(mt, "video")) {
  ------------------
  |  Branch (261:21): [True: 0, False: 0]
  ------------------
  262|      0|                    sh->type = sh->codec->type = STREAM_VIDEO;
  263|      0|                } else if (bstr_equals0(mt, "audio")) {
  ------------------
  |  Branch (263:28): [True: 0, False: 0]
  ------------------
  264|      0|                    sh->type = sh->codec->type = STREAM_AUDIO;
  265|      0|                } else if (bstr_equals0(mt, "sub")) {
  ------------------
  |  Branch (265:28): [True: 0, False: 0]
  ------------------
  266|      0|                    sh->type = sh->codec->type = STREAM_SUB;
  267|      0|                } else {
  268|      0|                    mp_err(log, "Invalid or missing !delay_open media type.\n");
  ------------------
  |  |   72|      0|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  269|      0|                    goto error;
  270|      0|                }
  271|      0|                sh->codec->codec = get_param0(&ctx, sh, "codec");
  272|      0|                if (!sh->codec->codec)
  ------------------
  |  Branch (272:21): [True: 0, False: 0]
  ------------------
  273|      0|                    sh->codec->codec = "null";
  274|      0|                sh->codec->disp_w = get_param_int(&ctx, "w", 0);
  275|      0|                sh->codec->disp_h = get_param_int(&ctx, "h", 0);
  276|      0|                sh->codec->fps = get_param_int(&ctx, "fps", 0);
  277|      0|                sh->codec->samplerate = get_param_int(&ctx, "samplerate", 0);
  278|      0|                tl->delay_open = true;
  279|      2|            } else if (bstr_equals0(f_type, "global_tags")) {
  ------------------
  |  Branch (279:24): [True: 0, False: 2]
  ------------------
  280|      0|                for (int n = 0; n < ctx.num_params; n++) {
  ------------------
  |  Branch (280:33): [True: 0, False: 0]
  ------------------
  281|      0|                    mp_tags_set_bstr(root->tags, ctx.param_names[n],
  282|      0|                                     ctx.param_vals[n]);
  283|      0|                }
  284|      0|                ctx.num_params = 0;
  285|      2|            } else {
  286|      2|                mp_err(log, "Unknown header: '%.*s'\n", BSTR_P(f_type));
  ------------------
  |  |   72|      4|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 2, False: 0]
  |  |  ------------------
  ------------------
  287|      2|                goto error;
  288|      2|            }
  289|  1.91k|        } else {
  290|  1.91k|            struct tl_part p = { .length = -1 };
  291|  1.91k|            p.filename = get_param0(&ctx, tl, "file");
  292|  1.91k|            if (!p.filename || !p.filename[0]) {
  ------------------
  |  Branch (292:17): [True: 0, False: 1.91k]
  |  Branch (292:32): [True: 0, False: 1.91k]
  ------------------
  293|      0|                mp_err(log, "Missing filename in segment.'\n");
  ------------------
  |  |   72|      0|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  294|      0|                goto error;
  295|      0|            }
  296|  1.91k|            p.offset_set = get_param_time(&ctx, "start", &p.offset);
  297|  1.91k|            get_param_time(&ctx, "length", &p.length);
  298|  1.91k|            bstr ts = get_param(&ctx, "timestamps");
  299|  1.91k|            if (bstr_equals0(ts, "chapters")) {
  ------------------
  |  Branch (299:17): [True: 0, False: 1.91k]
  ------------------
  300|      0|                p.chapter_ts = true;
  301|  1.91k|            } else if (ts.start && !bstr_equals0(ts, "seconds")) {
  ------------------
  |  Branch (301:24): [True: 0, False: 1.91k]
  |  Branch (301:36): [True: 0, False: 0]
  ------------------
  302|      0|                mp_warn(log, "Unknown timestamp type: '%.*s'\n", BSTR_P(ts));
  ------------------
  |  |   73|      0|#define mp_warn(log, ...)       mp_msg(log, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (73:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  303|      0|            }
  304|  1.91k|            p.title = get_param0(&ctx, tl, "title");
  305|  1.91k|            bstr layout = get_param(&ctx, "layout");
  306|  1.91k|            if (layout.start) {
  ------------------
  |  Branch (306:17): [True: 0, False: 1.91k]
  ------------------
  307|      0|                if (bstr_equals0(layout, "this")) {
  ------------------
  |  Branch (307:21): [True: 0, False: 0]
  ------------------
  308|      0|                    p.is_layout = true;
  309|      0|                } else {
  310|      0|                    mp_warn(log, "Unknown layout param: '%.*s'\n", BSTR_P(layout));
  ------------------
  |  |   73|      0|#define mp_warn(log, ...)       mp_msg(log, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (73:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  311|      0|                }
  312|      0|            }
  313|  1.91k|            MP_TARRAY_APPEND(tl, tl->parts, tl->num_parts, p);
  ------------------
  |  |  105|  1.91k|    do {                                            \
  |  |  106|  1.91k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  1.91k|    do {                                            \
  |  |  |  |   97|  1.91k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  1.91k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  1.91k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  1.91k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 425, False: 1.48k]
  |  |  |  |  ------------------
  |  |  |  |   99|  1.91k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|    425|    do {                                                        \
  |  |  |  |  |  |   89|    425|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|    425|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|    425|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|    425|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|    425|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|    425|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|    425|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  1.91k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  1.91k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  1.91k|        (idxvar)++;                                 \
  |  |  109|  1.91k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  314|  1.91k|        }
  315|  1.95k|        if (ctx.error)
  ------------------
  |  Branch (315:13): [True: 0, False: 1.95k]
  ------------------
  316|      0|            goto error;
  317|  1.95k|        for (int n = 0; n < ctx.num_params; n++) {
  ------------------
  |  Branch (317:25): [True: 0, False: 1.95k]
  ------------------
  318|      0|            mp_warn(log, "Unknown or duplicate parameter: '%.*s'\n",
  ------------------
  |  |   73|      0|#define mp_warn(log, ...)       mp_msg(log, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (73:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  319|      0|                    BSTR_P(ctx.param_names[n]));
  320|      0|        }
  321|  1.95k|    }
  322|    128|    mp_assert(root->num_pars);
  ------------------
  |  |   41|    128|#define mp_assert assert
  ------------------
  323|    287|    for (int n = 0; n < root->num_pars; n++) {
  ------------------
  |  Branch (323:21): [True: 160, False: 127]
  ------------------
  324|    160|        if (root->pars[n]->num_parts < 1) {
  ------------------
  |  Branch (324:13): [True: 1, False: 159]
  ------------------
  325|      1|            mp_err(log, "EDL specifies no segments.'\n");
  ------------------
  |  |   72|      1|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  326|      1|            goto error;
  327|      1|        }
  328|    160|    }
  329|    127|    return root;
  330|      3|error:
  331|      3|    mp_err(log, "EDL parsing failed.\n");
  ------------------
  |  |   72|      3|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  332|      3|    talloc_free(root);
  ------------------
  |  |   47|      3|#define talloc_free                     ta_free
  ------------------
  333|      3|    return NULL;
  334|    128|}
demux_edl.c:add_part:
  149|    174|{
  150|    174|    struct tl_parts *tl = talloc_zero(root, struct tl_parts);
  ------------------
  |  |   27|    174|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    174|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    174|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  151|    174|    MP_TARRAY_APPEND(root, root->pars, root->num_pars, tl);
  ------------------
  |  |  105|    174|    do {                                            \
  |  |  106|    174|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|    174|    do {                                            \
  |  |  |  |   97|    174|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|    174|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|    174|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|    174|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 140, False: 34]
  |  |  |  |  ------------------
  |  |  |  |   99|    174|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|    140|    do {                                                        \
  |  |  |  |  |  |   89|    140|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|    140|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|    140|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|    140|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|    140|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|    140|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|    140|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|    174|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|    174|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|    174|        (idxvar)++;                                 \
  |  |  109|    174|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  152|    174|    return tl;
  153|    174|}
demux_edl.c:get_param:
   86|  11.5k|{
   87|  11.5k|    bstr bname = bstr0(name);
   88|  11.5k|    for (int n = 0; n < ctx->num_params; n++) {
  ------------------
  |  Branch (88:21): [True: 1.96k, False: 9.57k]
  ------------------
   89|  1.96k|        if (bstr_equals(ctx->param_names[n], bname)) {
  ------------------
  |  Branch (89:13): [True: 1.96k, False: 0]
  ------------------
   90|  1.96k|            bstr res = ctx->param_vals[n];
   91|  1.96k|            int count = ctx->num_params;
   92|  1.96k|            MP_TARRAY_REMOVE_AT(ctx->param_names, count, n);
  ------------------
  |  |  143|  1.96k|    do {                                            \
  |  |  144|  1.96k|        size_t at_ = (at);                          \
  |  |  145|  1.96k|        assert(at_ <= (idxvar));                    \
  |  |  146|  1.96k|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|  1.96k|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|  1.96k|        (idxvar)--;                                 \
  |  |  149|  1.96k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
   93|  1.96k|            count = ctx->num_params;
   94|  1.96k|            MP_TARRAY_REMOVE_AT(ctx->param_vals, count, n);
  ------------------
  |  |  143|  1.96k|    do {                                            \
  |  |  144|  1.96k|        size_t at_ = (at);                          \
  |  |  145|  1.96k|        assert(at_ <= (idxvar));                    \
  |  |  146|  1.96k|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|  1.96k|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|  1.96k|        (idxvar)--;                                 \
  |  |  149|  1.96k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
   95|  1.96k|            ctx->num_params -= 1;
   96|  1.96k|            if (!res.start)
  ------------------
  |  Branch (96:17): [True: 0, False: 1.96k]
  ------------------
   97|      0|                res = bstr0("");  // keep guarantees
   98|  1.96k|            return res;
   99|  1.96k|        }
  100|  1.96k|    }
  101|  9.57k|    return (bstr){0};
  102|  11.5k|}
demux_edl.c:get_param0:
  106|  3.82k|{
  107|  3.82k|    return bstrdup0(ta_ctx, get_param(ctx, name));
  108|  3.82k|}
demux_edl.c:get_param_time:
  132|  3.82k|{
  133|  3.82k|    bstr val = get_param(ctx, name);
  134|  3.82k|    if (val.start) {
  ------------------
  |  Branch (134:9): [True: 0, False: 3.82k]
  ------------------
  135|      0|        bstr rest;
  136|      0|        double time = bstrtod(val, &rest);
  137|      0|        if (!val.len || rest.len || !isfinite(time)) {
  ------------------
  |  Branch (137:13): [True: 0, False: 0]
  |  Branch (137:25): [True: 0, False: 0]
  |  Branch (137:37): [True: 0, False: 0]
  ------------------
  138|      0|            MP_ERR(ctx, "Invalid time string: '%.*s'\n", BSTR_P(val));
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  139|      0|            ctx->error = true;
  140|      0|            return false;
  141|      0|        }
  142|      0|        *t = time;
  143|      0|        return true;
  144|      0|    }
  145|  3.82k|    return false;
  146|  3.82k|}
demux_edl.c:fix_filenames:
  569|    127|{
  570|    127|    bstr proto = mp_split_proto(bstr0(source_path), NULL);
  571|       |    // Don't adjust self-expanding protocols
  572|    127|    if (!bstrcasecmp0(proto, "memory") || !bstrcasecmp0(proto, "lavf") ||
  ------------------
  |  Branch (572:9): [True: 0, False: 127]
  |  Branch (572:43): [True: 0, False: 127]
  ------------------
  573|    127|        !bstrcasecmp0(proto, "hex") || !bstrcasecmp0(proto, "edl"))
  ------------------
  |  Branch (573:9): [True: 0, False: 127]
  |  Branch (573:40): [True: 127, False: 0]
  ------------------
  574|    127|    {
  575|    127|        return;
  576|    127|    }
  577|      0|    struct bstr dirname = mp_dirname(source_path);
  578|      0|    for (int n = 0; n < parts->num_parts; n++) {
  ------------------
  |  Branch (578:21): [True: 0, False: 0]
  ------------------
  579|      0|        struct tl_part *part = &parts->parts[n];
  580|      0|        if (!mp_is_url(bstr0(part->filename))) {
  ------------------
  |  Branch (580:13): [True: 0, False: 0]
  ------------------
  581|      0|            part->filename =
  582|      0|                mp_path_join_bstr(parts, dirname, bstr0(part->filename));
  583|      0|        }
  584|      0|    }
  585|      0|}
demux_edl.c:build_timeline:
  403|    127|{
  404|    127|    struct timeline_par *tl = talloc_zero(root, struct timeline_par);
  ------------------
  |  |   27|    127|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    127|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    127|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  405|    127|    MP_TARRAY_APPEND(root, root->pars, root->num_pars, tl);
  ------------------
  |  |  105|    127|    do {                                            \
  |  |  106|    127|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|    127|    do {                                            \
  |  |  |  |   97|    127|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|    127|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|    127|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|    127|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 127, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|    127|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|    127|    do {                                                        \
  |  |  |  |  |  |   89|    127|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|    127|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|    127|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|    127|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|    127|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|    127|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|    127|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|    127|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|    127|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|    127|        (idxvar)++;                                 \
  |  |  109|    127|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  406|       |
  407|    127|    tl->track_layout = NULL;
  408|    127|    tl->dash = parts->dash;
  409|    127|    tl->no_clip = parts->no_clip;
  410|    127|    tl->delay_open = parts->delay_open;
  411|       |
  412|       |    // There is no copy function for sh_stream, so just steal it.
  413|    127|    for (int n = 0; n < parts->num_sh_meta; n++) {
  ------------------
  |  Branch (413:21): [True: 0, False: 127]
  ------------------
  414|      0|        MP_TARRAY_APPEND(tl, tl->sh_meta, tl->num_sh_meta,
  ------------------
  |  |  105|      0|    do {                                            \
  |  |  106|      0|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      0|    do {                                            \
  |  |  |  |   97|      0|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      0|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      0|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      0|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      0|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      0|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      0|        (idxvar)++;                                 \
  |  |  109|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  415|      0|                         talloc_steal(tl, parts->sh_meta[n]));
  416|      0|        parts->sh_meta[n] = NULL;
  417|      0|    }
  418|    127|    parts->num_sh_meta = 0;
  419|       |
  420|    127|    if (parts->init_fragment_url && parts->init_fragment_url[0]) {
  ------------------
  |  Branch (420:9): [True: 0, False: 127]
  |  Branch (420:37): [True: 0, False: 0]
  ------------------
  421|      0|        MP_VERBOSE(root, "Opening init fragment...\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  422|      0|        stream_t *s = stream_create(parts->init_fragment_url,
  423|      0|                                    STREAM_READ | root->stream_origin,
  ------------------
  |  |   41|      0|#define STREAM_READ               0
  ------------------
  424|      0|                                    root->cancel, root->global);
  425|      0|        if (s) {
  ------------------
  |  Branch (425:13): [True: 0, False: 0]
  ------------------
  426|      0|            root->is_network |= s->is_network;
  427|      0|            root->is_streaming |= s->streaming;
  428|      0|            tl->init_fragment = stream_read_complete(s, tl, 1000000);
  429|      0|        }
  430|      0|        free_stream(s);
  431|      0|        if (!tl->init_fragment.len) {
  ------------------
  |  Branch (431:13): [True: 0, False: 0]
  ------------------
  432|      0|            MP_ERR(root, "Could not read init fragment.\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  433|      0|            goto error;
  434|      0|        }
  435|      0|        struct demuxer_params params = {
  436|      0|            .init_fragment = tl->init_fragment,
  437|      0|            .stream_flags = root->stream_origin,
  438|      0|        };
  439|      0|        tl->track_layout = demux_open_url("memory://", &params, root->cancel,
  440|      0|                                          root->global);
  441|      0|        if (!tl->track_layout) {
  ------------------
  |  Branch (441:13): [True: 0, False: 0]
  ------------------
  442|      0|            MP_ERR(root, "Could not demux init fragment.\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  443|      0|            goto error;
  444|      0|        }
  445|      0|        MP_TARRAY_APPEND(root, root->sources, root->num_sources, tl->track_layout);
  ------------------
  |  |  105|      0|    do {                                            \
  |  |  106|      0|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      0|    do {                                            \
  |  |  |  |   97|      0|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      0|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      0|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      0|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      0|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      0|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      0|        (idxvar)++;                                 \
  |  |  109|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  446|      0|    }
  447|       |
  448|    127|    tl->parts = talloc_array_ptrtype(tl, tl->parts, parts->num_parts);
  ------------------
  |  |   36|    127|#define talloc_array_ptrtype            ta_xnew_array_ptrtype
  |  |  ------------------
  |  |  |  |  140|    127|#define ta_xnew_array_ptrtype(...)      ta_oom_g(ta_new_array_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    127|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  449|    127|    double starttime = 0;
  450|    282|    for (int n = 0; n < parts->num_parts; n++) {
  ------------------
  |  Branch (450:21): [True: 261, False: 21]
  ------------------
  451|    261|        struct tl_part *part = &parts->parts[n];
  452|    261|        struct demuxer *source = NULL;
  453|       |
  454|    261|        if (tl->dash) {
  ------------------
  |  Branch (454:13): [True: 0, False: 261]
  ------------------
  455|      0|            part->offset = starttime;
  456|      0|            if (part->length <= 0)
  ------------------
  |  Branch (456:17): [True: 0, False: 0]
  ------------------
  457|      0|                MP_WARN(root, "Segment %d has unknown duration.\n", n);
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  458|      0|            if (part->offset_set)
  ------------------
  |  Branch (458:17): [True: 0, False: 0]
  ------------------
  459|      0|                MP_WARN(root, "Offsets are ignored.\n");
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  460|       |
  461|      0|            if (!tl->track_layout)
  ------------------
  |  Branch (461:17): [True: 0, False: 0]
  ------------------
  462|      0|                tl->track_layout = open_source(root, tl, part->filename);
  463|    261|        } else if (tl->delay_open) {
  ------------------
  |  Branch (463:20): [True: 0, False: 261]
  ------------------
  464|      0|            if (n == 0 && !part->offset_set) {
  ------------------
  |  Branch (464:17): [True: 0, False: 0]
  |  Branch (464:27): [True: 0, False: 0]
  ------------------
  465|      0|                part->offset = starttime;
  466|      0|                part->offset_set = true;
  467|      0|            }
  468|      0|            if (part->chapter_ts || (part->length < 0 && !tl->no_clip)) {
  ------------------
  |  Branch (468:17): [True: 0, False: 0]
  |  Branch (468:38): [True: 0, False: 0]
  |  Branch (468:58): [True: 0, False: 0]
  ------------------
  469|      0|                MP_ERR(root, "Invalid specification for delay_open stream.\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  470|      0|                goto error;
  471|      0|            }
  472|    261|        } else {
  473|    261|            MP_VERBOSE(root, "Opening segment %d...\n", n);
  ------------------
  |  |   88|    261|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    261|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  474|       |
  475|    261|            source = open_source(root, tl, part->filename);
  476|    261|            if (!source)
  ------------------
  |  Branch (476:17): [True: 106, False: 155]
  ------------------
  477|    106|                goto error;
  478|       |
  479|    155|            resolve_timestamps(part, source);
  480|       |
  481|    155|            double end_time = source->duration;
  482|    155|            if (end_time >= 0)
  ------------------
  |  Branch (482:17): [True: 3, False: 152]
  ------------------
  483|      3|                end_time += source->start_time;
  484|       |
  485|       |            // Unknown length => use rest of the file. If duration is unknown, make
  486|       |            // something up.
  487|    155|            if (part->length < 0) {
  ------------------
  |  Branch (487:17): [True: 155, False: 0]
  ------------------
  488|    155|                if (end_time < 0) {
  ------------------
  |  Branch (488:21): [True: 152, False: 3]
  ------------------
  489|    152|                    MP_WARN(root, "EDL: source file '%s' has unknown duration.\n",
  ------------------
  |  |   86|    152|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    152|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  490|    152|                            part->filename);
  491|    152|                    end_time = 1;
  492|    152|                }
  493|    155|                part->length = end_time - part->offset;
  494|    155|            } else if (end_time >= 0) {
  ------------------
  |  Branch (494:24): [True: 0, False: 0]
  ------------------
  495|      0|                double end_part = part->offset + part->length;
  496|      0|                if (end_part > end_time) {
  ------------------
  |  Branch (496:21): [True: 0, False: 0]
  ------------------
  497|      0|                    MP_WARN(root, "EDL: entry %d uses %f "
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  498|      0|                            "seconds, but file has only %f seconds.\n",
  499|      0|                            n, end_part, end_time);
  500|      0|                }
  501|      0|            }
  502|       |
  503|    155|            if (!parts->disable_chapters) {
  ------------------
  |  Branch (503:17): [True: 155, False: 0]
  ------------------
  504|       |                // Add a chapter between each file.
  505|    155|                struct demux_chapter ch = {
  506|    155|                    .pts = starttime,
  507|    155|                    .metadata = talloc_zero(tl, struct mp_tags),
  ------------------
  |  |   27|    155|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    155|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    155|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  508|    155|                };
  509|    155|                mp_tags_set_str(ch.metadata, "title",
  510|    155|                                part->title ? part->title : part->filename);
  ------------------
  |  Branch (510:33): [True: 0, False: 155]
  ------------------
  511|    155|                MP_TARRAY_APPEND(root, root->chapters, root->num_chapters, ch);
  ------------------
  |  |  105|    155|    do {                                            \
  |  |  106|    155|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|    155|    do {                                            \
  |  |  |  |   97|    155|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|    155|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|    155|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|    155|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 88, False: 67]
  |  |  |  |  ------------------
  |  |  |  |   99|    155|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|     88|    do {                                                        \
  |  |  |  |  |  |   89|     88|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|     88|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|     88|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|     88|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|     88|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|     88|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|     88|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|    155|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|    155|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|    155|        (idxvar)++;                                 \
  |  |  109|    155|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  512|       |
  513|       |                // Also copy the source file's chapters for the relevant parts
  514|    155|                copy_chapters(&root->chapters, &root->num_chapters, source,
  515|    155|                              part->offset, part->length, starttime);
  516|    155|            }
  517|    155|        }
  518|       |
  519|    155|        tl->parts[n] = (struct timeline_part) {
  520|    155|            .start = starttime,
  521|    155|            .end = starttime + part->length,
  522|    155|            .source_start = part->offset,
  523|    155|            .source = source,
  524|    155|            .url = talloc_strdup(tl, part->filename),
  ------------------
  |  |   50|    155|#define talloc_strdup                   ta_xstrdup
  ------------------
  525|    155|        };
  526|       |
  527|    155|        starttime = tl->parts[n].end;
  528|       |
  529|    155|        if (source && !tl->track_layout && part->is_layout)
  ------------------
  |  Branch (529:13): [True: 155, False: 0]
  |  Branch (529:23): [True: 155, False: 0]
  |  Branch (529:44): [True: 0, False: 155]
  ------------------
  530|      0|            tl->track_layout = source;
  531|       |
  532|    155|        tl->num_parts++;
  533|    155|    }
  534|       |
  535|     21|    if (tl->no_clip && tl->num_parts > 1)
  ------------------
  |  Branch (535:9): [True: 0, False: 21]
  |  Branch (535:24): [True: 0, False: 0]
  ------------------
  536|     21|        MP_WARN(root, "Multiple parts with no_clip. Undefined behavior ahead.\n");
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  537|       |
  538|     21|    if (!tl->track_layout) {
  ------------------
  |  Branch (538:9): [True: 21, False: 0]
  ------------------
  539|       |        // Use a heuristic to select the "broadest" part as layout.
  540|     81|        for (int n = 0; n < parts->num_parts; n++) {
  ------------------
  |  Branch (540:25): [True: 60, False: 21]
  ------------------
  541|     60|            struct demuxer *s = tl->parts[n].source;
  542|     60|            if (!s)
  ------------------
  |  Branch (542:17): [True: 0, False: 60]
  ------------------
  543|      0|                continue;
  544|     60|            if (!tl->track_layout ||
  ------------------
  |  Branch (544:17): [True: 21, False: 39]
  ------------------
  545|     60|                demux_get_num_stream(s) > demux_get_num_stream(tl->track_layout))
  ------------------
  |  Branch (545:17): [True: 1, False: 38]
  ------------------
  546|     22|                tl->track_layout = s;
  547|     60|        }
  548|     21|    }
  549|       |
  550|     21|    if (!tl->track_layout && !tl->delay_open)
  ------------------
  |  Branch (550:9): [True: 0, False: 21]
  |  Branch (550:30): [True: 0, False: 0]
  ------------------
  551|      0|        goto error;
  552|     21|    if (!root->meta)
  ------------------
  |  Branch (552:9): [True: 21, False: 0]
  ------------------
  553|     21|        root->meta = tl->track_layout;
  554|       |
  555|       |    // Not very sane, since demuxer fields are supposed to be treated read-only
  556|       |    // from outside, but happens to work in this case, so who cares.
  557|     21|    if (root->meta)
  ------------------
  |  Branch (557:9): [True: 21, False: 0]
  ------------------
  558|     21|        mp_tags_merge(root->meta->metadata, edl_root->tags);
  559|       |
  560|     21|    mp_assert(tl->num_parts == parts->num_parts);
  ------------------
  |  |   41|     21|#define mp_assert assert
  ------------------
  561|     21|    return tl;
  562|       |
  563|    106|error:
  564|    106|    root->num_pars = 0;
  565|    106|    return NULL;
  566|     21|}
demux_edl.c:open_source:
  338|    261|{
  339|    631|    for (int n = 0; n < tl->num_parts; n++) {
  ------------------
  |  Branch (339:21): [True: 383, False: 248]
  ------------------
  340|    383|        struct demuxer *d = tl->parts[n].source;
  341|    383|        if (d && d->filename && strcmp(d->filename, filename) == 0)
  ------------------
  |  Branch (341:13): [True: 383, False: 0]
  |  Branch (341:18): [True: 383, False: 0]
  |  Branch (341:33): [True: 13, False: 370]
  ------------------
  342|     13|            return d;
  343|    383|    }
  344|    248|    struct demuxer_params params = {
  345|    248|        .init_fragment = tl->init_fragment,
  346|    248|        .stream_flags = root->stream_origin,
  347|    248|    };
  348|    248|    struct demuxer *d = demux_open_url(filename, &params, root->cancel,
  349|    248|                                       root->global);
  350|    248|    if (d) {
  ------------------
  |  Branch (350:9): [True: 142, False: 106]
  ------------------
  351|    142|        MP_TARRAY_APPEND(root, root->sources, root->num_sources, d);
  ------------------
  |  |  105|    142|    do {                                            \
  |  |  106|    142|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|    142|    do {                                            \
  |  |  |  |   97|    142|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|    142|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|    142|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|    142|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 84, False: 58]
  |  |  |  |  ------------------
  |  |  |  |   99|    142|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|     84|    do {                                                        \
  |  |  |  |  |  |   89|     84|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|     84|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|     84|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|     84|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|     84|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|     84|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|     84|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|    142|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|    142|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|    142|        (idxvar)++;                                 \
  |  |  109|    142|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  352|    142|    } else {
  353|    106|        MP_ERR(root, "EDL: Could not open source file '%s'.\n", filename);
  ------------------
  |  |   85|    106|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    106|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  354|    106|    }
  355|    248|    return d;
  356|    261|}
demux_edl.c:resolve_timestamps:
  384|    155|{
  385|    155|    if (part->chapter_ts) {
  ------------------
  |  Branch (385:9): [True: 0, False: 155]
  ------------------
  386|      0|        double start = demuxer_chapter_time(demuxer, part->offset);
  387|      0|        double length = part->length;
  388|      0|        double end = length;
  389|      0|        if (end >= 0)
  ------------------
  |  Branch (389:13): [True: 0, False: 0]
  ------------------
  390|      0|            end = demuxer_chapter_time(demuxer, part->offset + part->length);
  391|      0|        if (end >= 0 && start >= 0)
  ------------------
  |  Branch (391:13): [True: 0, False: 0]
  |  Branch (391:25): [True: 0, False: 0]
  ------------------
  392|      0|            length = end - start;
  393|      0|        part->offset = start;
  394|      0|        part->length = length;
  395|      0|    }
  396|    155|    if (!part->offset_set)
  ------------------
  |  Branch (396:9): [True: 155, False: 0]
  ------------------
  397|    155|        part->offset = demuxer->start_time;
  398|    155|}
demux_edl.c:copy_chapters:
  370|    155|{
  371|    155|    for (int n = 0; n < src->num_chapters; n++) {
  ------------------
  |  Branch (371:21): [True: 0, False: 155]
  ------------------
  372|      0|        double time = demuxer_chapter_time(src, n);
  373|      0|        if (time >= start && time <= start + len) {
  ------------------
  |  Branch (373:13): [True: 0, False: 0]
  |  Branch (373:30): [True: 0, False: 0]
  ------------------
  374|      0|            struct demux_chapter ch = {
  375|      0|                .pts = dest_offset + time - start,
  376|      0|                .metadata = mp_tags_dup(*chapters, src->chapters[n].metadata),
  377|      0|            };
  378|      0|            MP_TARRAY_APPEND(NULL, *chapters, *num_chapters, ch);
  ------------------
  |  |  105|      0|    do {                                            \
  |  |  106|      0|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      0|    do {                                            \
  |  |  |  |   97|      0|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      0|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      0|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      0|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      0|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      0|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      0|        (idxvar)++;                                 \
  |  |  109|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  379|      0|        }
  380|      0|    }
  381|    155|}

demux_lavf.c:demux_open_lavf:
  972|    276|{
  973|    276|    AVFormatContext *avfc = NULL;
  974|    276|    AVDictionaryEntry *t = NULL;
  975|    276|    float analyze_duration = 0;
  976|    276|    lavf_priv_t *priv = talloc_zero(NULL, lavf_priv_t);
  ------------------
  |  |   27|    276|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    276|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    276|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  977|    276|    AVDictionary *dopts = NULL;
  978|       |
  979|    276|    demuxer->priv = priv;
  980|    276|    priv->stream = demuxer->stream;
  981|       |
  982|    276|    priv->opts = mp_get_config_group(priv, demuxer->global, &demux_lavf_conf);
  983|    276|    struct demux_lavf_opts *lavfdopts = priv->opts;
  984|       |
  985|    276|    if (lavf_check_file(demuxer, check) < 0)
  ------------------
  |  Branch (985:9): [True: 146, False: 130]
  ------------------
  986|    146|        goto fail;
  987|       |
  988|    130|    avfc = avformat_alloc_context();
  989|    130|    if (!avfc)
  ------------------
  |  Branch (989:9): [True: 0, False: 130]
  ------------------
  990|      0|        goto fail;
  991|       |
  992|    130|    if (demuxer->opts->index_mode != 1)
  ------------------
  |  Branch (992:9): [True: 0, False: 130]
  ------------------
  993|      0|        avfc->flags |= AVFMT_FLAG_IGNIDX;
  994|       |
  995|    130|    if (lavfdopts->probesize) {
  ------------------
  |  Branch (995:9): [True: 0, False: 130]
  ------------------
  996|      0|        if (av_opt_set_int(avfc, "probesize", lavfdopts->probesize, 0) < 0)
  ------------------
  |  Branch (996:13): [True: 0, False: 0]
  ------------------
  997|      0|            MP_ERR(demuxer, "couldn't set option probesize to %u\n",
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  998|      0|                   lavfdopts->probesize);
  999|      0|    }
 1000|       |
 1001|    130|    if (priv->format_hack.analyzeduration)
  ------------------
  |  Branch (1001:9): [True: 0, False: 130]
  ------------------
 1002|      0|        analyze_duration = priv->format_hack.analyzeduration;
 1003|    130|    if (lavfdopts->analyzeduration)
  ------------------
  |  Branch (1003:9): [True: 0, False: 130]
  ------------------
 1004|      0|        analyze_duration = lavfdopts->analyzeduration;
 1005|    130|    if (analyze_duration > 0) {
  ------------------
  |  Branch (1005:9): [True: 0, False: 130]
  ------------------
 1006|      0|        if (av_opt_set_int(avfc, "analyzeduration",
  ------------------
  |  Branch (1006:13): [True: 0, False: 0]
  ------------------
 1007|      0|                           analyze_duration * AV_TIME_BASE, 0) < 0)
 1008|      0|            MP_ERR(demuxer, "demux_lavf, couldn't set option "
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1009|      0|                   "analyzeduration to %f\n", analyze_duration);
 1010|      0|    }
 1011|       |
 1012|    130|    if (priv->format_hack.no_ext_picky) {
  ------------------
  |  Branch (1012:9): [True: 0, False: 130]
  ------------------
 1013|      0|        bool user_set_ext_picky = false;
 1014|      0|        for (int i = 0; lavfdopts->avopts && lavfdopts->avopts[i * 2]; i++) {
  ------------------
  |  Branch (1014:25): [True: 0, False: 0]
  |  Branch (1014:46): [True: 0, False: 0]
  ------------------
 1015|      0|            if (bstr_startswith0(bstr0(lavfdopts->avopts[i * 2]), "extension_picky")) {
  ------------------
  |  Branch (1015:17): [True: 0, False: 0]
  ------------------
 1016|      0|                user_set_ext_picky = true;
 1017|      0|                break;
 1018|      0|            }
 1019|      0|        }
 1020|      0|        if (!user_set_ext_picky && av_dict_set(&dopts, "extension_picky", "0", 0) >= 0)
  ------------------
  |  Branch (1020:13): [True: 0, False: 0]
  |  Branch (1020:36): [True: 0, False: 0]
  ------------------
 1021|      0|            MP_VERBOSE(demuxer, "Option extension_picky=0 was set due to known FFmpeg bugs\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1022|      0|    }
 1023|       |
 1024|    130|    if ((priv->avif_flags & AVFMT_NOFILE) || priv->format_hack.no_stream) {
  ------------------
  |  Branch (1024:9): [True: 0, False: 130]
  |  Branch (1024:46): [True: 0, False: 130]
  ------------------
 1025|      0|        mp_setup_av_network_options(&dopts, priv->avif->name,
 1026|      0|                                    demuxer->global, demuxer->log);
 1027|       |        // This might be incorrect.
 1028|      0|        demuxer->seekable = true;
 1029|    130|    } else {
 1030|    130|        void *buffer = av_malloc(lavfdopts->buffersize);
 1031|    130|        if (!buffer)
  ------------------
  |  Branch (1031:13): [True: 0, False: 130]
  ------------------
 1032|      0|            goto fail;
 1033|    130|        priv->pb = avio_alloc_context(buffer, lavfdopts->buffersize, 0,
 1034|    130|                                      demuxer, mp_read, NULL, mp_seek);
 1035|    130|        if (!priv->pb) {
  ------------------
  |  Branch (1035:13): [True: 0, False: 130]
  ------------------
 1036|      0|            av_free(buffer);
 1037|      0|            goto fail;
 1038|      0|        }
 1039|    130|        priv->pb->read_seek = mp_read_seek;
 1040|    130|        priv->pb->seekable = demuxer->seekable ? AVIO_SEEKABLE_NORMAL : 0;
  ------------------
  |  Branch (1040:30): [True: 130, False: 0]
  ------------------
 1041|    130|        avfc->pb = priv->pb;
 1042|    130|        if (stream_control(priv->stream, STREAM_CTRL_HAS_AVSEEK, NULL) > 0)
  ------------------
  |  Branch (1042:13): [True: 0, False: 130]
  ------------------
 1043|      0|            demuxer->seekable = true;
 1044|    130|        demuxer->seekable |= priv->format_hack.fully_read;
 1045|    130|    }
 1046|       |
 1047|    130|    if (matches_avinputformat_name(priv, "rtsp")) {
  ------------------
  |  Branch (1047:9): [True: 0, False: 130]
  ------------------
 1048|      0|        const char *transport = NULL;
 1049|      0|        switch (lavfdopts->rtsp_transport) {
  ------------------
  |  Branch (1049:17): [True: 0, False: 0]
  ------------------
 1050|      0|        case 1: transport = "udp";  break;
  ------------------
  |  Branch (1050:9): [True: 0, False: 0]
  ------------------
 1051|      0|        case 2: transport = "tcp";  break;
  ------------------
  |  Branch (1051:9): [True: 0, False: 0]
  ------------------
 1052|      0|        case 3: transport = "http"; break;
  ------------------
  |  Branch (1052:9): [True: 0, False: 0]
  ------------------
 1053|      0|        case 4: transport = "udp_multicast"; break;
  ------------------
  |  Branch (1053:9): [True: 0, False: 0]
  ------------------
 1054|      0|        }
 1055|      0|        if (transport)
  ------------------
  |  Branch (1055:13): [True: 0, False: 0]
  ------------------
 1056|      0|            av_dict_set(&dopts, "rtsp_transport", transport, 0);
 1057|      0|    }
 1058|       |
 1059|    130|    guess_and_set_vobsub_name(demuxer, &dopts);
 1060|       |
 1061|    130|    avfc->interrupt_callback = (AVIOInterruptCB){
 1062|    130|        .callback = interrupt_cb,
 1063|    130|        .opaque = demuxer,
 1064|    130|    };
 1065|       |
 1066|    130|    avfc->opaque = demuxer;
 1067|    130|    if (demuxer->access_references) {
  ------------------
  |  Branch (1067:9): [True: 130, False: 0]
  ------------------
 1068|    130|        priv->default_io_open = avfc->io_open;
 1069|    130|        avfc->io_open = nested_io_open;
 1070|    130|        priv->default_io_close2 = avfc->io_close2;
 1071|    130|        avfc->io_close2 = nested_io_close2;
 1072|    130|    } else {
 1073|      0|        avfc->io_open = block_io_open;
 1074|      0|    }
 1075|       |
 1076|    130|    mp_set_avdict(&dopts, lavfdopts->avopts);
 1077|       |
 1078|    130|    if (av_dict_copy(&priv->av_opts, dopts, 0) < 0) {
  ------------------
  |  Branch (1078:9): [True: 0, False: 130]
  ------------------
 1079|      0|        MP_ERR(demuxer, "av_dict_copy() failed\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1080|      0|        goto fail;
 1081|      0|    }
 1082|       |
 1083|    130|    if (priv->format_hack.readall_on_no_streamseek && priv->pb &&
  ------------------
  |  Branch (1083:9): [True: 33, False: 97]
  |  Branch (1083:55): [True: 33, False: 0]
  ------------------
 1084|    130|        !priv->pb->seekable)
  ------------------
  |  Branch (1084:9): [True: 0, False: 33]
  ------------------
 1085|      0|    {
 1086|      0|        MP_VERBOSE(demuxer, "Non-seekable demuxer pre-read hack...\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1087|       |        // Read incremental to avoid unnecessary large buffer sizes.
 1088|      0|        int r = 0;
 1089|      0|        for (int n = 16; n < 29; n++) {
  ------------------
  |  Branch (1089:26): [True: 0, False: 0]
  ------------------
 1090|      0|            r = stream_peek(priv->stream, 1 << n);
 1091|      0|            if (r < (1 << n))
  ------------------
  |  Branch (1091:17): [True: 0, False: 0]
  ------------------
 1092|      0|                break;
 1093|      0|        }
 1094|      0|        MP_VERBOSE(demuxer, "...did read %d bytes.\n", r);
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1095|      0|    }
 1096|       |
 1097|    130|    if (avformat_open_input(&avfc, priv->filename, priv->avif, &dopts) < 0) {
  ------------------
  |  Branch (1097:9): [True: 40, False: 90]
  ------------------
 1098|     40|        MP_ERR(demuxer, "avformat_open_input() failed\n");
  ------------------
  |  |   85|     40|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     40|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1099|     40|        goto fail;
 1100|     40|    }
 1101|       |
 1102|     90|    mp_avdict_print_unset(demuxer->log, MSGL_V, dopts);
 1103|     90|    av_dict_free(&dopts);
 1104|       |
 1105|     90|    priv->avfc = avfc;
 1106|       |
 1107|     90|    bool probeinfo = lavfdopts->probeinfo != 0;
 1108|     90|    switch (lavfdopts->probeinfo) {
  ------------------
  |  Branch (1108:13): [True: 0, False: 90]
  ------------------
 1109|      0|    case -2: probeinfo = priv->avfc->nb_streams == 0; break;
  ------------------
  |  Branch (1109:5): [True: 0, False: 90]
  ------------------
 1110|     90|    case -1: probeinfo = !priv->format_hack.skipinfo; break;
  ------------------
  |  Branch (1110:5): [True: 90, False: 0]
  ------------------
 1111|     90|    }
 1112|     90|    if (demuxer->params && demuxer->params->skip_lavf_probing)
  ------------------
  |  Branch (1112:9): [True: 90, False: 0]
  |  Branch (1112:28): [True: 0, False: 90]
  ------------------
 1113|      0|        probeinfo = false;
 1114|     90|    if (probeinfo) {
  ------------------
  |  Branch (1114:9): [True: 90, False: 0]
  ------------------
 1115|     90|        if (avformat_find_stream_info(avfc, NULL) < 0) {
  ------------------
  |  Branch (1115:13): [True: 7, False: 83]
  ------------------
 1116|      7|            MP_ERR(demuxer, "av_find_stream_info() failed\n");
  ------------------
  |  |   85|      7|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      7|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1117|      7|            goto fail;
 1118|      7|        }
 1119|       |
 1120|     83|        MP_VERBOSE(demuxer, "avformat_find_stream_info() finished after %"PRId64
  ------------------
  |  |   88|     83|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     83|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1121|     83|                   " bytes.\n", stream_tell(priv->stream));
 1122|     83|    }
 1123|       |
 1124|     83|    for (int i = 0; i < avfc->nb_chapters; i++) {
  ------------------
  |  Branch (1124:21): [True: 0, False: 83]
  ------------------
 1125|      0|        AVChapter *c = avfc->chapters[i];
 1126|      0|        t = av_dict_get(c->metadata, "title", NULL, 0);
 1127|      0|        int index = demuxer_add_chapter(demuxer, t ? t->value : "",
  ------------------
  |  Branch (1127:50): [True: 0, False: 0]
  ------------------
 1128|      0|                                        c->start * av_q2d(c->time_base), i);
 1129|      0|        mp_tags_move_from_av_dictionary(demuxer->chapters[index].metadata, &c->metadata);
 1130|      0|    }
 1131|       |
 1132|     83|    add_new_streams(demuxer);
 1133|       |
 1134|     83|    mp_tags_move_from_av_dictionary(demuxer->metadata, &avfc->metadata);
 1135|       |
 1136|     83|    demuxer->ts_resets_possible =
 1137|     83|        priv->avif_flags & (AVFMT_TS_DISCONT | AVFMT_NOTIMESTAMPS);
 1138|       |
 1139|     83|    if (avfc->start_time != AV_NOPTS_VALUE)
  ------------------
  |  Branch (1139:9): [True: 44, False: 39]
  ------------------
 1140|     44|        demuxer->start_time = avfc->start_time / (double)AV_TIME_BASE;
 1141|       |
 1142|     83|    demuxer->fully_read = priv->format_hack.fully_read;
 1143|       |
 1144|     83|#ifdef AVFMTCTX_UNSEEKABLE
 1145|     83|    if (avfc->ctx_flags & AVFMTCTX_UNSEEKABLE)
  ------------------
  |  Branch (1145:9): [True: 0, False: 83]
  ------------------
 1146|      0|        demuxer->seekable = false;
 1147|     83|#endif
 1148|       |
 1149|     83|    demuxer->is_network |= priv->format_hack.is_network;
 1150|     83|    demuxer->seekable &= !priv->format_hack.no_seek;
 1151|       |
 1152|       |    // We initially prefer track durations over container durations because they
 1153|       |    // have a higher degree of precision over the container duration which are
 1154|       |    // only accurate to the 6th decimal place. This is probably a lavf bug.
 1155|     83|    double total_duration = -1;
 1156|     83|    double av_duration = -1;
 1157|    155|    for (int n = 0; n < priv->avfc->nb_streams; n++) {
  ------------------
  |  Branch (1157:21): [True: 72, False: 83]
  ------------------
 1158|     72|        AVStream *st = priv->avfc->streams[n];
 1159|     72|        if (st->duration <= 0)
  ------------------
  |  Branch (1159:13): [True: 72, False: 0]
  ------------------
 1160|     72|            continue;
 1161|      0|        double f_duration = st->duration * av_q2d(st->time_base);
 1162|      0|        total_duration = MPMAX(total_duration, f_duration);
  ------------------
  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1163|      0|        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ||
  ------------------
  |  Branch (1163:13): [True: 0, False: 0]
  ------------------
 1164|      0|            st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
  ------------------
  |  Branch (1164:13): [True: 0, False: 0]
  ------------------
 1165|      0|            av_duration = MPMAX(av_duration, f_duration);
  ------------------
  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1166|      0|    }
 1167|     83|    double duration = av_duration > 0 ? av_duration : total_duration;
  ------------------
  |  Branch (1167:23): [True: 0, False: 83]
  ------------------
 1168|     83|    if (duration <= 0 && priv->avfc->duration > 0)
  ------------------
  |  Branch (1168:9): [True: 83, False: 0]
  |  Branch (1168:26): [True: 0, False: 83]
  ------------------
 1169|      0|        duration = (double)priv->avfc->duration / AV_TIME_BASE;
 1170|     83|    demuxer->duration = duration;
 1171|       |
 1172|     83|    if (demuxer->duration < 0 && priv->format_hack.no_seek_on_no_duration)
  ------------------
  |  Branch (1172:9): [True: 83, False: 0]
  |  Branch (1172:34): [True: 0, False: 83]
  ------------------
 1173|      0|        demuxer->seekable = false;
 1174|       |
 1175|       |    // In some cases, libavformat will export bogus bullshit timestamps anyway,
 1176|       |    // such as with mjpeg.
 1177|     83|    if (priv->avif_flags & AVFMT_NOTIMESTAMPS) {
  ------------------
  |  Branch (1177:9): [True: 0, False: 83]
  ------------------
 1178|      0|        MP_WARN(demuxer,
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1179|      0|                "This format is marked by FFmpeg as having no timestamps!\n"
 1180|      0|                "FFmpeg will likely make up its own broken timestamps. For\n"
 1181|      0|                "video streams you can correct this with:\n"
 1182|      0|                "    --no-correct-pts --container-fps-override=VALUE\n"
 1183|      0|                "with VALUE being the real framerate of the stream. You can\n"
 1184|      0|                "expect seeking and buffering estimation to be generally\n"
 1185|      0|                "broken as well.\n");
 1186|      0|    }
 1187|       |
 1188|     83|    if (demuxer->fully_read) {
  ------------------
  |  Branch (1188:9): [True: 28, False: 55]
  ------------------
 1189|     28|        demux_close_stream(demuxer);
 1190|     28|        if (priv->own_stream)
  ------------------
  |  Branch (1190:13): [True: 28, False: 0]
  ------------------
 1191|     28|            free_stream(priv->stream);
 1192|     28|        priv->own_stream = false;
 1193|     28|        priv->stream = NULL;
 1194|     28|    }
 1195|       |
 1196|     83|    if (priv->stream) {
  ------------------
  |  Branch (1196:9): [True: 55, False: 28]
  ------------------
 1197|     55|        const char *sname = priv->stream->info->name;
 1198|     55|        priv->is_dvd_bd = strcmp(sname, "dvdnav") == 0 ||
  ------------------
  |  Branch (1198:27): [True: 0, False: 55]
  ------------------
 1199|     55|                          strcmp(sname, "ifo_dvdnav") == 0 ||
  ------------------
  |  Branch (1199:27): [True: 0, False: 55]
  ------------------
 1200|     55|                          strcmp(sname, "bd") == 0 ||
  ------------------
  |  Branch (1200:27): [True: 0, False: 55]
  ------------------
 1201|     55|                          strcmp(sname, "bdnav") == 0 ||
  ------------------
  |  Branch (1201:27): [True: 0, False: 55]
  ------------------
 1202|     55|                          strcmp(sname, "bdmv/bluray") == 0;
  ------------------
  |  Branch (1202:27): [True: 0, False: 55]
  ------------------
 1203|     55|    }
 1204|       |
 1205|     83|    return 0;
 1206|       |
 1207|    193|fail:
 1208|    193|    if (!priv->avfc)
  ------------------
  |  Branch (1208:9): [True: 186, False: 7]
  ------------------
 1209|    186|        avformat_free_context(avfc);
 1210|    193|    av_dict_free(&dopts);
 1211|       |
 1212|    193|    return -1;
 1213|     90|}
demux_lavf.c:lavf_check_file:
  422|    276|{
  423|    276|    lavf_priv_t *priv = demuxer->priv;
  424|    276|    struct demux_lavf_opts *lavfdopts = priv->opts;
  425|    276|    struct stream *s = priv->stream;
  426|       |
  427|    276|    priv->filename = remove_prefix(s->url, prefixes);
  428|       |
  429|    276|    char *avdevice_format = NULL;
  430|    276|    if (s->info && strcmp(s->info->name, "avdevice") == 0) {
  ------------------
  |  Branch (430:9): [True: 276, False: 0]
  |  Branch (430:20): [True: 1, False: 275]
  ------------------
  431|       |        // always require filename in the form "format:filename"
  432|      1|        char *sep = strchr(priv->filename, ':');
  433|      1|        if (!sep) {
  ------------------
  |  Branch (433:13): [True: 1, False: 0]
  ------------------
  434|      1|            MP_FATAL(demuxer, "Must specify filename in 'format:filename' form\n");
  ------------------
  |  |   84|      1|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      1|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  435|      1|            return -1;
  436|      1|        }
  437|      0|        avdevice_format = talloc_strndup(priv, priv->filename,
  ------------------
  |  |   51|      0|#define talloc_strndup                  ta_xstrndup
  ------------------
  438|      0|                                         sep - priv->filename);
  439|      0|        priv->filename = sep + 1;
  440|      0|    }
  441|       |
  442|    275|    char *mime_type = s->mime_type;
  443|    275|    if (!lavfdopts->allow_mimetype || !mime_type)
  ------------------
  |  Branch (443:9): [True: 0, False: 275]
  |  Branch (443:39): [True: 275, False: 0]
  ------------------
  444|    275|        mime_type = "";
  445|       |
  446|    275|    const AVInputFormat *forced_format = NULL;
  447|    275|    const char *format = lavfdopts->format;
  448|    275|    if (!format || !format[0])
  ------------------
  |  Branch (448:9): [True: 275, False: 0]
  |  Branch (448:20): [True: 0, False: 0]
  ------------------
  449|    275|        format = s->lavf_type;
  450|    275|    if (!format)
  ------------------
  |  Branch (450:9): [True: 275, False: 0]
  ------------------
  451|    275|        format = avdevice_format;
  452|    275|    if (format) {
  ------------------
  |  Branch (452:9): [True: 0, False: 275]
  ------------------
  453|      0|        if (strcmp(format, "help") == 0) {
  ------------------
  |  Branch (453:13): [True: 0, False: 0]
  ------------------
  454|      0|            list_formats(demuxer);
  455|      0|            return -1;
  456|      0|        }
  457|      0|        forced_format = av_find_input_format(format);
  458|      0|        if (!forced_format) {
  ------------------
  |  Branch (458:13): [True: 0, False: 0]
  ------------------
  459|      0|            MP_FATAL(demuxer, "Unknown lavf format %s\n", format);
  ------------------
  |  |   84|      0|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  460|      0|            return -1;
  461|      0|        }
  462|      0|    }
  463|       |
  464|       |    // HLS streams seems to be not well tagged, so matching mime type is not
  465|       |    // enough. Strip URL parameters and match extension.
  466|    275|    bstr ext = bstr_get_ext(bstr_split(bstr0(priv->filename), "?#", NULL));
  467|    275|    AVProbeData avpd = {
  468|       |        // Disable file-extension matching with normal checks, except for HLS
  469|    275|        .filename = !bstrcasecmp0(ext, "m3u8") || !bstrcasecmp0(ext, "m3u") ||
  ------------------
  |  Branch (469:21): [True: 0, False: 275]
  |  Branch (469:51): [True: 4, False: 271]
  ------------------
  470|    275|                    check <= DEMUX_CHECK_REQUEST ? priv->filename : "",
  ------------------
  |  Branch (470:21): [True: 23, False: 248]
  ------------------
  471|    275|        .buf_size = 0,
  472|    275|        .buf = av_mallocz(PROBE_BUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE),
  ------------------
  |  |   59|    275|#define PROBE_BUF_SIZE (10 * 1024 * 1024)
  ------------------
  473|    275|        .mime_type = lavfdopts->allow_mimetype ? mime_type : NULL,
  ------------------
  |  Branch (473:22): [True: 275, False: 0]
  ------------------
  474|    275|    };
  475|    275|    if (!avpd.buf)
  ------------------
  |  Branch (475:9): [True: 0, False: 275]
  ------------------
  476|      0|        return -1;
  477|       |
  478|    275|    bool final_probe = false;
  479|    414|    do {
  480|    414|        int score = 0;
  481|       |
  482|    414|        if (forced_format) {
  ------------------
  |  Branch (482:13): [True: 0, False: 414]
  ------------------
  483|      0|            priv->avif = forced_format;
  484|      0|            score = AVPROBE_SCORE_MAX;
  485|    414|        } else {
  486|    414|            int nsize = av_clip(avpd.buf_size * 2, INITIAL_PROBE_SIZE,
  ------------------
  |  |   58|    414|#define INITIAL_PROBE_SIZE STREAM_BUFFER_SIZE
  |  |  ------------------
  |  |  |  |   33|    414|#define STREAM_BUFFER_SIZE 2048
  |  |  ------------------
  ------------------
  487|    414|                                PROBE_BUF_SIZE);
  ------------------
  |  |   59|    414|#define PROBE_BUF_SIZE (10 * 1024 * 1024)
  ------------------
  488|    414|            nsize = stream_read_peek(s, avpd.buf, nsize);
  489|    414|            if (nsize <= avpd.buf_size)
  ------------------
  |  Branch (489:17): [True: 140, False: 274]
  ------------------
  490|    140|                final_probe = true;
  491|    414|            avpd.buf_size = nsize;
  492|       |
  493|    414|            priv->avif = av_probe_input_format2(&avpd, avpd.buf_size > 0, &score);
  494|    414|        }
  495|       |
  496|    414|        if (priv->avif) {
  ------------------
  |  Branch (496:13): [True: 285, False: 129]
  ------------------
  497|    285|            MP_VERBOSE(demuxer, "Found '%s' at score=%d size=%d%s.\n",
  ------------------
  |  |   88|    285|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    570|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 0, False: 285]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  498|    285|                       priv->avif->name, score, avpd.buf_size,
  499|    285|                       forced_format ? " (forced)" : "");
  500|       |
  501|  5.32k|            for (int n = 0; lavfdopts->hacks && format_hacks[n].ff_name; n++) {
  ------------------
  |  Branch (501:29): [True: 5.32k, False: 0]
  |  Branch (501:49): [True: 5.25k, False: 68]
  ------------------
  502|  5.25k|                const struct format_hack *entry = &format_hacks[n];
  503|  5.25k|                if (!matches_avinputformat_name(priv, entry->ff_name))
  ------------------
  |  Branch (503:21): [True: 4.90k, False: 353]
  ------------------
  504|  4.90k|                    continue;
  505|    353|                if (entry->mime_type && strcasecmp(entry->mime_type, mime_type) != 0)
  ------------------
  |  Branch (505:21): [True: 136, False: 217]
  |  Branch (505:41): [True: 136, False: 0]
  ------------------
  506|    136|                    continue;
  507|    217|                priv->format_hack = *entry;
  508|    217|                break;
  509|    353|            }
  510|       |
  511|       |            // AVIF always needs to find stream info
  512|    285|            if (bstrcasecmp0(ext, "avif") == 0)
  ------------------
  |  Branch (512:17): [True: 0, False: 285]
  ------------------
  513|      0|                priv->format_hack.skipinfo = false;
  514|       |
  515|    285|            if (score >= lavfdopts->probescore)
  ------------------
  |  Branch (515:17): [True: 135, False: 150]
  ------------------
  516|    135|                break;
  517|       |
  518|    150|            if (priv->format_hack.probescore &&
  ------------------
  |  Branch (518:17): [True: 132, False: 18]
  ------------------
  519|    150|                score >= priv->format_hack.probescore &&
  ------------------
  |  Branch (519:17): [True: 0, False: 132]
  ------------------
  520|    150|                (!priv->format_hack.max_probe || final_probe))
  ------------------
  |  Branch (520:18): [True: 0, False: 0]
  |  Branch (520:50): [True: 0, False: 0]
  ------------------
  521|      0|                break;
  522|    150|        }
  523|       |
  524|    279|        priv->avif = NULL;
  525|    279|        priv->format_hack = (struct format_hack){0};
  526|    279|    } while (!final_probe);
  ------------------
  |  Branch (526:14): [True: 139, False: 140]
  ------------------
  527|       |
  528|      0|    av_free(avpd.buf);
  529|       |
  530|    275|    if (priv->avif && !forced_format && priv->format_hack.ignore) {
  ------------------
  |  Branch (530:9): [True: 135, False: 140]
  |  Branch (530:23): [True: 135, False: 0]
  |  Branch (530:41): [True: 5, False: 130]
  ------------------
  531|      5|        MP_VERBOSE(demuxer, "Format blacklisted.\n");
  ------------------
  |  |   88|      5|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      5|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  532|      5|        priv->avif = NULL;
  533|      5|    }
  534|       |
  535|    275|    if (!priv->avif) {
  ------------------
  |  Branch (535:9): [True: 145, False: 130]
  ------------------
  536|    145|        MP_VERBOSE(demuxer, "No format found, try lowering probescore or forcing the format.\n");
  ------------------
  |  |   88|    145|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    145|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  537|    145|        return -1;
  538|    145|    }
  539|       |
  540|    130|    if (lavfdopts->hacks)
  ------------------
  |  Branch (540:9): [True: 130, False: 0]
  ------------------
  541|    130|        priv->avif_flags = priv->avif->flags | priv->format_hack.if_flags;
  542|       |
  543|    130|    priv->linearize_ts = lavfdopts->linearize_ts;
  544|    130|    if (priv->linearize_ts < 0 && !priv->format_hack.linearize_audio_ts)
  ------------------
  |  Branch (544:9): [True: 130, False: 0]
  |  Branch (544:35): [True: 130, False: 0]
  ------------------
  545|    130|        priv->linearize_ts = 0;
  546|       |
  547|    130|    demuxer->filetype = priv->avif->name;
  548|       |
  549|    130|    if (priv->format_hack.detect_charset)
  ------------------
  |  Branch (549:9): [True: 28, False: 102]
  ------------------
  550|     28|        convert_charset(demuxer);
  551|       |
  552|    130|    return 0;
  553|    275|}
demux_lavf.c:remove_prefix:
  409|    276|{
  410|  1.37k|    for (int n = 0; prefixes[n]; n++) {
  ------------------
  |  Branch (410:21): [True: 1.10k, False: 275]
  ------------------
  411|  1.10k|        int len = strlen(prefixes[n]);
  412|  1.10k|        if (strncmp(s, prefixes[n], len) == 0)
  ------------------
  |  Branch (412:13): [True: 1, False: 1.10k]
  ------------------
  413|      1|            return s + len;
  414|  1.10k|    }
  415|    275|    return s;
  416|    276|}
demux_lavf.c:convert_charset:
  379|     28|{
  380|     28|    lavf_priv_t *priv = demuxer->priv;
  381|     28|    char *cp = priv->opts->sub_cp;
  382|     28|    if (!cp || !cp[0] || mp_charset_is_utf8(cp))
  ------------------
  |  Branch (382:9): [True: 0, False: 28]
  |  Branch (382:16): [True: 0, False: 28]
  |  Branch (382:26): [True: 0, False: 28]
  ------------------
  383|      0|        return;
  384|     28|    bstr data = stream_read_complete(priv->stream, NULL, 128 * 1024 * 1024);
  385|     28|    if (!data.start) {
  ------------------
  |  Branch (385:9): [True: 0, False: 28]
  ------------------
  386|      0|        MP_WARN(demuxer, "File too big (or error reading) - skip charset probing.\n");
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  387|      0|        return;
  388|      0|    }
  389|     28|    void *alloc = data.start;
  390|     28|    cp = (char *)mp_charset_guess(priv, demuxer->log, data, cp, 0);
  391|     28|    if (cp && !mp_charset_is_utf8(cp))
  ------------------
  |  Branch (391:9): [True: 28, False: 0]
  |  Branch (391:15): [True: 28, False: 0]
  ------------------
  392|     28|        MP_INFO(demuxer, "Using subtitle charset: %s\n", cp);
  ------------------
  |  |   87|     28|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     28|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  393|       |    // libavformat transparently converts UTF-16 to UTF-8
  394|     28|    if (!mp_charset_is_utf16(cp) && !mp_charset_is_utf8(cp)) {
  ------------------
  |  Branch (394:9): [True: 28, False: 0]
  |  Branch (394:37): [True: 28, False: 0]
  ------------------
  395|     28|        bstr conv = mp_iconv_to_utf8(demuxer->log, data, cp, MP_ICONV_VERBOSE);
  396|     28|        if (conv.start && conv.start != data.start)
  ------------------
  |  Branch (396:13): [True: 28, False: 0]
  |  Branch (396:27): [True: 28, False: 0]
  ------------------
  397|     28|            talloc_steal(alloc, conv.start);
  ------------------
  |  |   38|     28|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     28|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  398|     28|        if (conv.start)
  ------------------
  |  Branch (398:13): [True: 28, False: 0]
  ------------------
  399|     28|            data = conv;
  400|     28|    }
  401|     28|    if (data.start) {
  ------------------
  |  Branch (401:9): [True: 28, False: 0]
  ------------------
  402|     28|        priv->stream = stream_memory_open(demuxer->global, data.start, data.len);
  403|     28|        priv->own_stream = true;
  404|     28|    }
  405|     28|    talloc_free(alloc);
  ------------------
  |  |   47|     28|#define talloc_free                     ta_free
  ------------------
  406|     28|}
demux_lavf.c:mp_read:
  294|    463|{
  295|    463|    struct demuxer *demuxer = opaque;
  296|    463|    lavf_priv_t *priv = demuxer->priv;
  297|    463|    struct stream *stream = priv->stream;
  298|    463|    if (!stream)
  ------------------
  |  Branch (298:9): [True: 0, False: 463]
  ------------------
  299|      0|        return 0;
  300|       |
  301|    463|    int ret = stream_read_partial(stream, buf, size);
  302|       |
  303|    463|    MP_TRACE(demuxer, "%d=mp_read(%p, %p, %d), pos: %"PRId64", eof:%d\n",
  ------------------
  |  |   90|    463|#define MP_TRACE(obj, ...)      MP_MSG(obj, MSGL_TRACE, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    463|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  304|    463|             ret, stream, buf, size, stream_tell(stream), stream->eof);
  305|    463|    return ret ? ret : AVERROR_EOF;
  ------------------
  |  Branch (305:12): [True: 130, False: 333]
  ------------------
  306|    463|}
demux_lavf.c:mp_seek:
  309|    930|{
  310|    930|    struct demuxer *demuxer = opaque;
  311|    930|    lavf_priv_t *priv = demuxer->priv;
  312|    930|    struct stream *stream = priv->stream;
  313|    930|    if (!stream)
  ------------------
  |  Branch (313:9): [True: 0, False: 930]
  ------------------
  314|      0|        return -1;
  315|       |
  316|    930|    MP_TRACE(demuxer, "mp_seek(%p, %"PRId64", %s)\n", stream, pos,
  ------------------
  |  |   90|    930|#define MP_TRACE(obj, ...)      MP_MSG(obj, MSGL_TRACE, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  4.88k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 528, False: 229]
  |  |  |  |  |  Branch (82:57): [True: 0, False: 757]
  |  |  |  |  |  Branch (82:57): [True: 173, False: 757]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  317|    930|             whence == SEEK_END ? "end" :
  318|    930|             whence == SEEK_CUR ? "cur" :
  319|    930|             whence == SEEK_SET ? "set" : "size");
  320|    930|    if (whence == SEEK_END || whence == AVSEEK_SIZE) {
  ------------------
  |  Branch (320:9): [True: 173, False: 757]
  |  Branch (320:31): [True: 229, False: 528]
  ------------------
  321|    402|        int64_t end = stream_get_size(stream);
  322|    402|        if (end < 0)
  ------------------
  |  Branch (322:13): [True: 346, False: 56]
  ------------------
  323|    346|            return -1;
  324|     56|        if (whence == AVSEEK_SIZE)
  ------------------
  |  Branch (324:13): [True: 56, False: 0]
  ------------------
  325|     56|            return end;
  326|      0|        pos += end;
  327|    528|    } else if (whence == SEEK_CUR) {
  ------------------
  |  Branch (327:16): [True: 0, False: 528]
  ------------------
  328|      0|        pos += stream_tell(stream);
  329|    528|    } else if (whence != SEEK_SET) {
  ------------------
  |  Branch (329:16): [True: 0, False: 528]
  ------------------
  330|      0|        return -1;
  331|      0|    }
  332|       |
  333|    528|    if (pos < 0)
  ------------------
  |  Branch (333:9): [True: 0, False: 528]
  ------------------
  334|      0|        return -1;
  335|       |
  336|    528|    int64_t current_pos = stream_tell(stream);
  337|    528|    if (!priv->is_dvd_bd) {
  ------------------
  |  Branch (337:9): [True: 528, False: 0]
  ------------------
  338|    528|        if (stream_seek(stream, pos) == 0) {
  ------------------
  |  Branch (338:13): [True: 528, False: 0]
  ------------------
  339|    528|            stream_seek(stream, current_pos);
  340|    528|            return -1;
  341|    528|        }
  342|    528|    } else {
  343|      0|        stream_drop_buffers(stream);
  344|      0|        stream->pos = current_pos;
  345|      0|    }
  346|       |
  347|      0|    return pos;
  348|    528|}
demux_lavf.c:matches_avinputformat_name:
  280|  5.58k|{
  281|  5.58k|    const char *avifname = priv->avif->name;
  282|  6.36k|    while (1) {
  ------------------
  |  Branch (282:12): [Folded - Ignored]
  ------------------
  283|  6.36k|        const char *next = strchr(avifname, ',');
  284|  6.36k|        if (!next)
  ------------------
  |  Branch (284:13): [True: 5.57k, False: 792]
  ------------------
  285|  5.57k|            return !strcmp(avifname, name);
  286|    792|        int len = next - avifname;
  287|    792|        if (len == strlen(name) && !memcmp(avifname, name, len))
  ------------------
  |  Branch (287:13): [True: 517, False: 275]
  |  Branch (287:36): [True: 11, False: 506]
  ------------------
  288|     11|            return true;
  289|    781|        avifname = next + 1;
  290|    781|    }
  291|  5.58k|}
demux_lavf.c:guess_and_set_vobsub_name:
  564|    130|{
  565|    130|    lavf_priv_t *priv = demuxer->priv;
  566|    130|    if (!matches_avinputformat_name(priv, "vobsub"))
  ------------------
  |  Branch (566:9): [True: 130, False: 0]
  ------------------
  567|    130|        return;
  568|       |
  569|      0|    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|      0|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|      0|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  570|      0|    bstr bfilename = bstr0(priv->filename);
  571|      0|    char *subname = NULL;
  572|      0|    if (mp_is_url(bfilename)) {
  ------------------
  |  Branch (572:9): [True: 0, False: 0]
  ------------------
  573|       |        // It might be a http URL, which has additional parameters after the
  574|       |        // end of the actual file path.
  575|      0|        bstr start, end;
  576|      0|        if (bstr_split_tok(bfilename, "?", &start, &end)) {
  ------------------
  |  Branch (576:13): [True: 0, False: 0]
  ------------------
  577|      0|            subname = replace_idx_ext(tmp, start);
  578|      0|            if (subname)
  ------------------
  |  Branch (578:17): [True: 0, False: 0]
  ------------------
  579|      0|                subname = talloc_asprintf(tmp, "%s?%.*s", subname, BSTR_P(end));
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (127:62): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  580|      0|        }
  581|      0|    }
  582|      0|    if (!subname)
  ------------------
  |  Branch (582:9): [True: 0, False: 0]
  ------------------
  583|      0|        subname = replace_idx_ext(tmp, bfilename);
  584|      0|    if (!subname)
  ------------------
  |  Branch (584:9): [True: 0, False: 0]
  ------------------
  585|      0|        subname = talloc_asprintf(tmp, "%.*s.sub", BSTR_P(bfilename));
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (127:62): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  586|       |
  587|      0|    MP_VERBOSE(demuxer, "Assuming associated .sub file: %s\n", subname);
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  588|      0|    av_dict_set(d, "sub_name", subname, 0);
  589|      0|    talloc_free(tmp);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  590|      0|}
demux_lavf.c:interrupt_cb:
  905|    110|{
  906|    110|    struct demuxer *demuxer = ctx;
  907|    110|    return mp_cancel_test(demuxer->cancel);
  908|    110|}
demux_lavf.c:add_new_streams:
  888|     83|{
  889|     83|    lavf_priv_t *priv = demuxer->priv;
  890|    155|    while (priv->num_streams < priv->avfc->nb_streams)
  ------------------
  |  Branch (890:12): [True: 72, False: 83]
  ------------------
  891|     72|        handle_new_stream(demuxer, priv->num_streams);
  892|     83|}
demux_lavf.c:handle_new_stream:
  686|     72|{
  687|     72|    lavf_priv_t *priv = demuxer->priv;
  688|     72|    AVFormatContext *avfc = priv->avfc;
  689|     72|    AVStream *st = avfc->streams[i];
  690|     72|    struct sh_stream *sh = NULL;
  691|     72|    AVCodecParameters *codec = st->codecpar;
  692|     72|    int lavc_delay = codec->initial_padding;
  693|       |
  694|     72|    switch (codec->codec_type) {
  695|      0|    case AVMEDIA_TYPE_AUDIO: {
  ------------------
  |  Branch (695:5): [True: 0, False: 72]
  ------------------
  696|      0|        sh = demux_alloc_sh_stream(STREAM_AUDIO);
  697|      0|        if (!mp_chmap_from_av_layout(&sh->codec->channels, &codec->ch_layout)) {
  ------------------
  |  Branch (697:13): [True: 0, False: 0]
  ------------------
  698|      0|            char layout[128] = {0};
  699|      0|            MP_WARN(demuxer,
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  700|      0|                    "Failed to convert channel layout %s to mpv one!\n",
  701|      0|                    av_channel_layout_describe(&codec->ch_layout,
  702|      0|                                               layout, 128) < 0 ?
  703|      0|                    "undefined" : layout);
  704|      0|        }
  705|       |
  706|      0|        sh->codec->samplerate = codec->sample_rate;
  707|      0|        sh->codec->bitrate = codec->bit_rate;
  708|      0|        sh->codec->format_name = talloc_strdup(sh, av_get_sample_fmt_name(codec->format));
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  709|       |
  710|      0|        double delay = 0;
  711|      0|        if (codec->sample_rate > 0)
  ------------------
  |  Branch (711:13): [True: 0, False: 0]
  ------------------
  712|      0|            delay = lavc_delay / (double)codec->sample_rate;
  713|      0|        priv->seek_delay = MPMAX(priv->seek_delay, delay);
  ------------------
  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  714|       |
  715|      0|        export_replaygain(demuxer, sh, st);
  716|       |
  717|      0|        sh->seek_preroll = delay;
  718|       |
  719|      0|        break;
  720|      0|    }
  721|     44|    case AVMEDIA_TYPE_VIDEO: {
  ------------------
  |  Branch (721:5): [True: 44, False: 28]
  ------------------
  722|     44|        sh = demux_alloc_sh_stream(STREAM_VIDEO);
  723|       |
  724|     44|        if ((st->disposition & AV_DISPOSITION_ATTACHED_PIC) &&
  ------------------
  |  Branch (724:13): [True: 0, False: 44]
  ------------------
  725|     44|            !(st->disposition & AV_DISPOSITION_TIMED_THUMBNAILS))
  ------------------
  |  Branch (725:13): [True: 0, False: 0]
  ------------------
  726|      0|        {
  727|      0|            sh->attached_picture =
  728|      0|                new_demux_packet_from_avpacket(demuxer->packet_pool, &st->attached_pic);
  729|      0|            if (sh->attached_picture) {
  ------------------
  |  Branch (729:17): [True: 0, False: 0]
  ------------------
  730|      0|                sh->attached_picture->pts = 0;
  731|      0|                talloc_steal(sh, sh->attached_picture);
  ------------------
  |  |   38|      0|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  732|      0|                sh->attached_picture->keyframe = true;
  733|      0|            }
  734|      0|        }
  735|       |
  736|     44|        if (!sh->attached_picture) {
  ------------------
  |  Branch (736:13): [True: 44, False: 0]
  ------------------
  737|       |            // A real video stream probably means it's a packet based format.
  738|     44|            priv->pcm_seek_hack_disabled = true;
  739|     44|            priv->pcm_seek_hack = NULL;
  740|       |            // Also, we don't want to do this shit for ogv videos.
  741|     44|            if (priv->linearize_ts < 0)
  ------------------
  |  Branch (741:17): [True: 0, False: 44]
  ------------------
  742|      0|                priv->linearize_ts = 0;
  743|     44|        }
  744|       |
  745|     44|        sh->codec->disp_w = codec->width;
  746|     44|        sh->codec->disp_h = codec->height;
  747|     44|        sh->codec->format_name = talloc_strdup(sh, av_get_pix_fmt_name(codec->format));
  ------------------
  |  |   50|     44|#define talloc_strdup                   ta_xstrdup
  ------------------
  748|     44|        if (st->avg_frame_rate.num)
  ------------------
  |  Branch (748:13): [True: 8, False: 36]
  ------------------
  749|      8|            sh->codec->fps = av_q2d(st->avg_frame_rate);
  750|     44|        if (is_image(st, sh->attached_picture, priv->avif)) {
  ------------------
  |  Branch (750:13): [True: 41, False: 3]
  ------------------
  751|     41|            MP_VERBOSE(demuxer, "Assuming this is an image format.\n");
  ------------------
  |  |   88|     41|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     41|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  752|     41|            sh->image = true;
  753|     41|            sh->codec->fps = demuxer->opts->mf_fps;
  754|     41|        }
  755|     44|        sh->codec->par_w = st->sample_aspect_ratio.num;
  756|     44|        sh->codec->par_h = st->sample_aspect_ratio.den;
  757|       |
  758|     44|        const uint8_t *sd = mp_av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX);
  759|     44|        if (sd) {
  ------------------
  |  Branch (759:13): [True: 0, False: 44]
  ------------------
  760|      0|            double r = av_display_rotation_get((int32_t *)sd);
  761|      0|            if (!isnan(r))
  ------------------
  |  Branch (761:17): [True: 0, False: 0]
  ------------------
  762|      0|                sh->codec->rotate = (((int)(-r) % 360) + 360) % 360;
  763|      0|        }
  764|       |
  765|     44|        if ((sd = mp_av_stream_get_side_data(st, AV_PKT_DATA_DOVI_CONF))) {
  ------------------
  |  Branch (765:13): [True: 0, False: 44]
  ------------------
  766|      0|            const AVDOVIDecoderConfigurationRecord *cfg = (void *) sd;
  767|      0|            MP_VERBOSE(demuxer, "Found Dolby Vision config record: profile "
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  768|      0|                       "%d level %d\n", cfg->dv_profile, cfg->dv_level);
  769|      0|            sh->codec->dovi = true;
  770|      0|            sh->codec->dv_profile = cfg->dv_profile;
  771|      0|            sh->codec->dv_level = cfg->dv_level;
  772|      0|        }
  773|       |
  774|       |        // This also applies to vfw-muxed mkv, but we can't detect these easily.
  775|     44|        sh->codec->avi_dts = matches_avinputformat_name(priv, "avi");
  776|       |
  777|     44|        break;
  778|      0|    }
  779|     28|    case AVMEDIA_TYPE_SUBTITLE: {
  ------------------
  |  Branch (779:5): [True: 28, False: 44]
  ------------------
  780|     28|        sh = demux_alloc_sh_stream(STREAM_SUB);
  781|       |
  782|     28|        if (codec->extradata_size) {
  ------------------
  |  Branch (782:13): [True: 25, False: 3]
  ------------------
  783|     25|            sh->codec->extradata = talloc_size(sh, codec->extradata_size);
  ------------------
  |  |   43|     25|#define talloc_size                     ta_xalloc_size
  |  |  ------------------
  |  |  |  |  120|     25|#define ta_xalloc_size(...)             ta_oom_p(ta_alloc_size(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  153|     25|#define ta_alloc_size(...)      ta_dbg_set_loc(ta_alloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|     25|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|     25|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|     25|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  784|     25|            memcpy(sh->codec->extradata, codec->extradata, codec->extradata_size);
  785|     25|            sh->codec->extradata_size = codec->extradata_size;
  786|     25|        }
  787|       |
  788|     28|        if (matches_avinputformat_name(priv, "microdvd")) {
  ------------------
  |  Branch (788:13): [True: 0, False: 28]
  ------------------
  789|      0|            AVRational r;
  790|      0|            if (av_opt_get_q(avfc, "subfps", AV_OPT_SEARCH_CHILDREN, &r) >= 0) {
  ------------------
  |  Branch (790:17): [True: 0, False: 0]
  ------------------
  791|       |                // File headers don't have a FPS set.
  792|      0|                if (r.num < 1 || r.den < 1)
  ------------------
  |  Branch (792:21): [True: 0, False: 0]
  |  Branch (792:34): [True: 0, False: 0]
  ------------------
  793|      0|                    sh->codec->frame_based = 23.976; // default timebase
  794|      0|            }
  795|      0|        }
  796|     28|        break;
  797|      0|    }
  798|      0|    case AVMEDIA_TYPE_ATTACHMENT: {
  ------------------
  |  Branch (798:5): [True: 0, False: 72]
  ------------------
  799|      0|        AVDictionaryEntry *ftag = av_dict_get(st->metadata, "filename", NULL, 0);
  800|      0|        char *filename = ftag ? ftag->value : NULL;
  ------------------
  |  Branch (800:26): [True: 0, False: 0]
  ------------------
  801|      0|        AVDictionaryEntry *mt = av_dict_get(st->metadata, "mimetype", NULL, 0);
  802|      0|        char *mimetype = mt ? mt->value : NULL;
  ------------------
  |  Branch (802:26): [True: 0, False: 0]
  ------------------
  803|      0|        if (mimetype) {
  ------------------
  |  Branch (803:13): [True: 0, False: 0]
  ------------------
  804|      0|            demuxer_add_attachment(demuxer, filename, mimetype,
  805|      0|                                   codec->extradata, codec->extradata_size);
  806|      0|        }
  807|      0|        break;
  808|      0|    }
  809|      0|    default: ;
  ------------------
  |  Branch (809:5): [True: 0, False: 72]
  ------------------
  810|     72|    }
  811|       |
  812|     72|    struct stream_info *info = talloc_zero(priv, struct stream_info);
  ------------------
  |  |   27|     72|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|     72|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     72|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  813|     72|    *info = (struct stream_info){
  814|     72|        .sh = sh,
  815|     72|        .last_key_pts = MP_NOPTS_VALUE,
  ------------------
  |  |   38|     72|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  816|     72|        .highest_pts = MP_NOPTS_VALUE,
  ------------------
  |  |   38|     72|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  817|     72|    };
  818|     72|    mp_assert(priv->num_streams == i); // directly mapped
  ------------------
  |  |   41|     72|#define mp_assert assert
  ------------------
  819|     72|    MP_TARRAY_APPEND(priv, priv->streams, priv->num_streams, info);
  ------------------
  |  |  105|     72|    do {                                            \
  |  |  106|     72|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|     72|    do {                                            \
  |  |  |  |   97|     72|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|     72|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|     72|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|     72|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 72, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|     72|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|     72|    do {                                                        \
  |  |  |  |  |  |   89|     72|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|     72|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|     72|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|     72|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|     72|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|     72|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|     72|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|     72|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|     72|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|     72|        (idxvar)++;                                 \
  |  |  109|     72|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  820|       |
  821|     72|    if (sh) {
  ------------------
  |  Branch (821:9): [True: 72, False: 0]
  ------------------
  822|     72|        sh->ff_index = st->index;
  823|     72|        sh->codec->codec = mp_codec_from_av_codec_id(codec->codec_id);
  824|     72|        sh->codec->codec_tag = codec->codec_tag;
  825|     72|        sh->codec->lav_codecpar = avcodec_parameters_alloc();
  826|     72|        if (sh->codec->lav_codecpar)
  ------------------
  |  Branch (826:13): [True: 72, False: 0]
  ------------------
  827|     72|            avcodec_parameters_copy(sh->codec->lav_codecpar, codec);
  828|     72|        sh->codec->native_tb_num = st->time_base.num;
  829|     72|        sh->codec->native_tb_den = st->time_base.den;
  830|       |
  831|     72|        if (st->disposition & AV_DISPOSITION_DEFAULT)
  ------------------
  |  Branch (831:13): [True: 0, False: 72]
  ------------------
  832|      0|            sh->default_track = true;
  833|     72|        if (st->disposition & AV_DISPOSITION_FORCED)
  ------------------
  |  Branch (833:13): [True: 0, False: 72]
  ------------------
  834|      0|            sh->forced_track = true;
  835|     72|        if (st->disposition & AV_DISPOSITION_DEPENDENT)
  ------------------
  |  Branch (835:13): [True: 0, False: 72]
  ------------------
  836|      0|            sh->dependent_track = true;
  837|     72|        if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
  ------------------
  |  Branch (837:13): [True: 0, False: 72]
  ------------------
  838|      0|            sh->visual_impaired_track = true;
  839|     72|        if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
  ------------------
  |  Branch (839:13): [True: 0, False: 72]
  ------------------
  840|      0|            sh->hearing_impaired_track = true;
  841|     72|        if (st->disposition & AV_DISPOSITION_STILL_IMAGE)
  ------------------
  |  Branch (841:13): [True: 0, False: 72]
  ------------------
  842|      0|            sh->still_image = true;
  843|     72|        if (priv->format_hack.use_stream_ids)
  ------------------
  |  Branch (843:13): [True: 0, False: 72]
  ------------------
  844|      0|            sh->demuxer_id = st->id;
  845|     72|        AVDictionaryEntry *title = av_dict_get(st->metadata, "title", NULL, 0);
  846|     72|        if (title && title->value)
  ------------------
  |  Branch (846:13): [True: 0, False: 72]
  |  Branch (846:22): [True: 0, False: 0]
  ------------------
  847|      0|            sh->title = talloc_strdup(sh, title->value);
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  848|     72|        if (!sh->title && st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
  ------------------
  |  Branch (848:13): [True: 72, False: 0]
  |  Branch (848:27): [True: 0, False: 72]
  ------------------
  849|      0|            sh->title = talloc_asprintf(sh, "visual impaired");
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  850|     72|        if (!sh->title && st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
  ------------------
  |  Branch (850:13): [True: 72, False: 0]
  |  Branch (850:27): [True: 0, False: 72]
  ------------------
  851|      0|            sh->title = talloc_asprintf(sh, "hearing impaired");
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  852|     72|        AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0);
  853|     72|        if (lang && lang->value && strcmp(lang->value, "und") != 0)
  ------------------
  |  Branch (853:13): [True: 0, False: 72]
  |  Branch (853:21): [True: 0, False: 0]
  |  Branch (853:36): [True: 0, False: 0]
  ------------------
  854|      0|            sh->lang = talloc_strdup(sh, lang->value);
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  855|     72|        sh->hls_bitrate = dict_get_decimal(st->metadata, "variant_bitrate", 0);
  856|     72|        AVProgram *prog = av_find_program_from_stream(avfc, NULL, i);
  857|     72|        if (prog)
  ------------------
  |  Branch (857:13): [True: 0, False: 72]
  ------------------
  858|      0|            sh->program_id = prog->id;
  859|     72|        sh->missing_timestamps = !!(priv->avif_flags & AVFMT_NOTIMESTAMPS);
  860|     72|        mp_tags_move_from_av_dictionary(sh->tags, &st->metadata);
  861|     72|        demux_add_sh_stream(demuxer, sh);
  862|       |
  863|       |        // Unfortunately, there is no better way to detect PCM codecs, other
  864|       |        // than listing them all manually. (Or other "frameless" codecs. Or
  865|       |        // rather, codecs with frames so small libavformat will put multiple of
  866|       |        // them into a single packet, but not preserve these artificial packet
  867|       |        // boundaries on seeking.)
  868|     72|        if (sh->codec->codec && strncmp(sh->codec->codec, "pcm_", 4) == 0 &&
  ------------------
  |  Branch (868:13): [True: 72, False: 0]
  |  Branch (868:33): [True: 0, False: 72]
  ------------------
  869|     72|            codec->block_align && !priv->pcm_seek_hack_disabled &&
  ------------------
  |  Branch (869:13): [True: 0, False: 0]
  |  Branch (869:35): [True: 0, False: 0]
  ------------------
  870|     72|            priv->opts->hacks && !priv->format_hack.no_pcm_seek &&
  ------------------
  |  Branch (870:13): [True: 0, False: 0]
  |  Branch (870:34): [True: 0, False: 0]
  ------------------
  871|     72|            st->time_base.num == 1 && st->time_base.den == codec->sample_rate)
  ------------------
  |  Branch (871:13): [True: 0, False: 0]
  |  Branch (871:39): [True: 0, False: 0]
  ------------------
  872|      0|        {
  873|      0|            if (priv->pcm_seek_hack) {
  ------------------
  |  Branch (873:17): [True: 0, False: 0]
  ------------------
  874|       |                // More than 1 audio stream => usually doesn't apply.
  875|      0|                priv->pcm_seek_hack_disabled = true;
  876|      0|                priv->pcm_seek_hack = NULL;
  877|      0|            } else {
  878|      0|                priv->pcm_seek_hack = st;
  879|      0|            }
  880|      0|        }
  881|     72|    }
  882|       |
  883|     72|    select_tracks(demuxer, i);
  884|     72|}
demux_lavf.c:is_image:
  671|     44|{
  672|     44|    return st->nb_frames <= 1 && (
  ------------------
  |  Branch (672:12): [True: 43, False: 1]
  ------------------
  673|     43|        attached_picture ||
  ------------------
  |  Branch (673:9): [True: 0, False: 43]
  ------------------
  674|     43|        bstr_endswith0(bstr0(avif->name), "_pipe") ||
  ------------------
  |  Branch (674:9): [True: 8, False: 35]
  ------------------
  675|     43|        strcmp(avif->name, "alias_pix") == 0 ||
  ------------------
  |  Branch (675:9): [True: 0, False: 35]
  ------------------
  676|     43|        strcmp(avif->name, "gif") == 0 ||
  ------------------
  |  Branch (676:9): [True: 33, False: 2]
  ------------------
  677|     43|        strcmp(avif->name, "ico") == 0 ||
  ------------------
  |  Branch (677:9): [True: 0, False: 2]
  ------------------
  678|     43|        strcmp(avif->name, "image2pipe") == 0 ||
  ------------------
  |  Branch (678:9): [True: 0, False: 2]
  ------------------
  679|     43|        ((st->codecpar->codec_id == AV_CODEC_ID_HEVC ||
  ------------------
  |  Branch (679:11): [True: 0, False: 2]
  ------------------
  680|      2|          st->codecpar->codec_id == AV_CODEC_ID_AV1)
  ------------------
  |  Branch (680:11): [True: 0, False: 2]
  ------------------
  681|      2|         && st->nb_frames == 1)
  ------------------
  |  Branch (681:13): [True: 0, False: 0]
  ------------------
  682|     43|    );
  683|     44|}
demux_lavf.c:mp_av_stream_get_side_data:
  606|     88|{
  607|     88|    const AVPacketSideData *sd;
  608|     88|    sd = av_packet_side_data_get(st->codecpar->coded_side_data,
  609|     88|                                 st->codecpar->nb_coded_side_data,
  610|     88|                                 type);
  611|     88|    return sd ? sd->data : NULL;
  ------------------
  |  Branch (611:12): [True: 0, False: 88]
  ------------------
  612|     88|}
demux_lavf.c:dict_get_decimal:
  659|     72|{
  660|     72|    AVDictionaryEntry *e = av_dict_get(dict, entry, NULL, 0);
  661|     72|    if (e && e->value) {
  ------------------
  |  Branch (661:9): [True: 0, False: 72]
  |  Branch (661:14): [True: 0, False: 0]
  ------------------
  662|      0|        char *end = NULL;
  663|      0|        long int r = strtol(e->value, &end, 10);
  664|      0|        if (end && !end[0] && r >= INT_MIN && r <= INT_MAX)
  ------------------
  |  Branch (664:13): [True: 0, False: 0]
  |  Branch (664:20): [True: 0, False: 0]
  |  Branch (664:31): [True: 0, False: 0]
  |  Branch (664:47): [True: 0, False: 0]
  ------------------
  665|      0|            return r;
  666|      0|    }
  667|     72|    return def;
  668|     72|}
demux_lavf.c:select_tracks:
  593|     72|{
  594|     72|    lavf_priv_t *priv = demuxer->priv;
  595|    144|    for (int n = start; n < priv->num_streams; n++) {
  ------------------
  |  Branch (595:25): [True: 72, False: 72]
  ------------------
  596|     72|        struct sh_stream *stream = priv->streams[n]->sh;
  597|     72|        AVStream *st = priv->avfc->streams[n];
  598|     72|        bool selected = stream && demux_stream_is_selected(stream) &&
  ------------------
  |  Branch (598:25): [True: 72, False: 0]
  |  Branch (598:35): [True: 0, False: 72]
  ------------------
  599|     72|                        !stream->attached_picture;
  ------------------
  |  Branch (599:25): [True: 0, False: 0]
  ------------------
  600|     72|        st->discard = selected ? AVDISCARD_DEFAULT : AVDISCARD_ALL;
  ------------------
  |  Branch (600:23): [True: 0, False: 72]
  ------------------
  601|     72|    }
  602|     72|}
demux_lavf.c:demux_close_lavf:
 1416|    276|{
 1417|    276|    lavf_priv_t *priv = demuxer->priv;
 1418|    276|    if (priv) {
  ------------------
  |  Branch (1418:9): [True: 276, False: 0]
  ------------------
 1419|       |        // This will be a dangling pointer; but see below.
 1420|    276|        AVIOContext *leaking = priv->avfc ? priv->avfc->pb : NULL;
  ------------------
  |  Branch (1420:32): [True: 90, False: 186]
  ------------------
 1421|    276|        avformat_close_input(&priv->avfc);
 1422|       |        // The ffmpeg garbage breaks its own API yet again: hls.c will call
 1423|       |        // io_open on the main playlist, but never calls io_close. This happens
 1424|       |        // to work out for us (since we don't really use custom I/O), but it's
 1425|       |        // still weird. Compensate.
 1426|    276|        if (priv->num_nested == 1 && priv->nested[0].id == leaking)
  ------------------
  |  Branch (1426:13): [True: 0, False: 276]
  |  Branch (1426:38): [True: 0, False: 0]
  ------------------
 1427|      0|            priv->num_nested = 0;
 1428|    276|        if (priv->num_nested) {
  ------------------
  |  Branch (1428:13): [True: 0, False: 276]
  ------------------
 1429|      0|            MP_WARN(demuxer, "Leaking %d nested connections (FFmpeg bug).\n",
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1430|      0|                    priv->num_nested);
 1431|      0|        }
 1432|    276|        if (priv->pb)
  ------------------
  |  Branch (1432:13): [True: 130, False: 146]
  ------------------
 1433|    130|            av_freep(&priv->pb->buffer);
 1434|    276|        av_freep(&priv->pb);
 1435|    348|        for (int n = 0; n < priv->num_streams; n++) {
  ------------------
  |  Branch (1435:25): [True: 72, False: 276]
  ------------------
 1436|     72|            struct stream_info *info = priv->streams[n];
 1437|     72|            if (info->sh)
  ------------------
  |  Branch (1437:17): [True: 72, False: 0]
  ------------------
 1438|     72|                avcodec_parameters_free(&info->sh->codec->lav_codecpar);
 1439|     72|        }
 1440|    276|        if (priv->own_stream)
  ------------------
  |  Branch (1440:13): [True: 0, False: 276]
  ------------------
 1441|      0|            free_stream(priv->stream);
 1442|    276|        if (priv->av_opts)
  ------------------
  |  Branch (1442:13): [True: 0, False: 276]
  ------------------
 1443|      0|            av_dict_free(&priv->av_opts);
 1444|    276|        talloc_free(priv);
  ------------------
  |  |   47|    276|#define talloc_free                     ta_free
  ------------------
 1445|    276|        demuxer->priv = NULL;
 1446|    276|    }
 1447|    276|}

demux_mf.c:demux_open_mf:
  372|     52|{
  373|     52|    mf_t *mf;
  374|       |
  375|     52|    if (strncmp(demuxer->stream->url, "mf://", 5) == 0 &&
  ------------------
  |  Branch (375:9): [True: 4, False: 48]
  ------------------
  376|     52|        demuxer->stream->info && strcmp(demuxer->stream->info->name, "mf") == 0)
  ------------------
  |  Branch (376:9): [True: 4, False: 0]
  |  Branch (376:34): [True: 4, False: 0]
  ------------------
  377|      4|    {
  378|      4|        mf = open_mf_pattern(demuxer, demuxer, demuxer->stream->url + 5);
  379|     48|    } else {
  380|     48|        mf = open_mf_single(demuxer, demuxer->log, demuxer->stream->url);
  381|     48|        int bog = 0;
  382|     48|        MP_TARRAY_APPEND(mf, mf->streams, bog, demuxer->stream);
  ------------------
  |  |  105|     48|    do {                                            \
  |  |  106|     48|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|     48|    do {                                            \
  |  |  |  |   97|     48|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|     48|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|     48|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|     48|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 48, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|     48|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|     48|    do {                                                        \
  |  |  |  |  |  |   89|     48|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|     48|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|     48|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|     48|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|     48|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|     48|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|     48|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|     48|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|     48|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|     48|        (idxvar)++;                                 \
  |  |  109|     48|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  383|     48|    }
  384|       |
  385|     52|    if (!mf || mf->nr_of_files < 1)
  ------------------
  |  Branch (385:9): [True: 0, False: 52]
  |  Branch (385:16): [True: 4, False: 48]
  ------------------
  386|      4|        goto error;
  387|       |
  388|     48|    const char *codec = mp_map_mimetype_to_video_codec(demuxer->stream->mime_type);
  389|     48|    if (!codec || (demuxer->opts->mf_type && demuxer->opts->mf_type[0]))
  ------------------
  |  Branch (389:9): [True: 48, False: 0]
  |  Branch (389:20): [True: 0, False: 0]
  |  Branch (389:46): [True: 0, False: 0]
  ------------------
  390|     48|        codec = probe_format(mf, demuxer->opts->mf_type, check);
  391|     48|    if (!codec)
  ------------------
  |  Branch (391:9): [True: 45, False: 3]
  ------------------
  392|     45|        goto error;
  393|       |
  394|      3|    mf->curr_frame = 0;
  395|       |
  396|       |    // create a new video stream header
  397|      3|    struct sh_stream *sh = demux_alloc_sh_stream(STREAM_VIDEO);
  398|      3|    if (mf->nr_of_files == 1) {
  ------------------
  |  Branch (398:9): [True: 3, False: 0]
  ------------------
  399|      3|        MP_VERBOSE(demuxer, "Assuming this is an image format.\n");
  ------------------
  |  |   88|      3|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      3|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  400|      3|        sh->image = true;
  401|      3|    }
  402|       |
  403|      3|    struct mp_codec_params *c = sh->codec;
  404|      3|    c->codec = codec;
  405|      3|    c->disp_w = 0;
  406|      3|    c->disp_h = 0;
  407|      3|    c->fps = demuxer->opts->mf_fps;
  408|      3|    c->reliable_fps = true;
  409|       |
  410|      3|    demux_add_sh_stream(demuxer, sh);
  411|       |
  412|      3|    mf->sh = sh;
  413|      3|    demuxer->priv = (void *)mf;
  414|      3|    demuxer->seekable = true;
  415|      3|    demuxer->duration = mf->nr_of_files / mf->sh->codec->fps;
  416|       |
  417|      3|    return 0;
  418|       |
  419|     49|error:
  420|     49|    return -1;
  421|     48|}
demux_mf.c:open_mf_pattern:
   59|      4|{
   60|      4|    struct mp_log *log = d->log;
   61|      4|    int error_count = 0;
   62|      4|    int count = 0;
   63|       |
   64|      4|    mf_t *mf = talloc_zero(talloc_ctx, mf_t);
  ------------------
  |  |   27|      4|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|      4|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      4|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   65|      4|    mf->log = log;
   66|       |
   67|      4|    if (filename[0] == '@') {
  ------------------
  |  Branch (67:9): [True: 0, False: 4]
  ------------------
   68|      0|        struct stream *s = stream_create(filename + 1,
   69|      0|                            d->stream_origin | STREAM_READ, d->cancel, d->global);
  ------------------
  |  |   41|      0|#define STREAM_READ               0
  ------------------
   70|      0|        if (s && !s->is_directory) {
  ------------------
  |  Branch (70:13): [True: 0, False: 0]
  |  Branch (70:18): [True: 0, False: 0]
  ------------------
   71|      0|            while (1) {
  ------------------
  |  Branch (71:20): [Folded - Ignored]
  ------------------
   72|      0|                char buf[512];
   73|      0|                int len = stream_read_peek(s, buf, sizeof(buf));
   74|      0|                if (!len)
  ------------------
  |  Branch (74:21): [True: 0, False: 0]
  ------------------
   75|      0|                    break;
   76|      0|                bstr data = (bstr){buf, len};
   77|      0|                int pos = bstrchr(data, '\n');
   78|      0|                data = bstr_splice(data, 0, pos < 0 ? data.len : pos + 1);
  ------------------
  |  Branch (78:45): [True: 0, False: 0]
  ------------------
   79|      0|                bstr fname = bstr_strip(data);
   80|      0|                if (fname.len) {
  ------------------
  |  Branch (80:21): [True: 0, False: 0]
  ------------------
   81|      0|                    if (bstrchr(fname, '\0') >= 0) {
  ------------------
  |  Branch (81:25): [True: 0, False: 0]
  ------------------
   82|      0|                        mp_err(log, "invalid filename\n");
  ------------------
  |  |   72|      0|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
   83|      0|                        break;
   84|      0|                    }
   85|      0|                    char *entry = bstrto0(mf, fname);
   86|      0|                    if (!mp_path_exists(entry) && !mp_is_url(fname)) {
  ------------------
  |  Branch (86:25): [True: 0, False: 0]
  |  Branch (86:51): [True: 0, False: 0]
  ------------------
   87|      0|                        mp_verbose(log, "file not found: '%s'\n", entry);
  ------------------
  |  |   75|      0|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
   88|      0|                    } else {
   89|      0|                        MP_TARRAY_APPEND(mf, mf->names, mf->nr_of_files, entry);
  ------------------
  |  |  105|      0|    do {                                            \
  |  |  106|      0|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      0|    do {                                            \
  |  |  |  |   97|      0|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      0|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      0|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      0|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      0|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      0|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      0|        (idxvar)++;                                 \
  |  |  109|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
   90|      0|                    }
   91|      0|                }
   92|      0|                stream_seek_skip(s, stream_tell(s) + data.len);
   93|      0|            }
   94|      0|            free_stream(s);
   95|       |
   96|      0|            goto exit_mf;
   97|      0|        }
   98|      0|        free_stream(s);
   99|      0|        mp_info(log, "%s is not indirect filelist\n", filename + 1);
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  100|      0|    }
  101|       |
  102|      4|    if (strchr(filename, ',')) {
  ------------------
  |  Branch (102:9): [True: 0, False: 4]
  ------------------
  103|      0|        mp_info(log, "filelist: %s\n", filename);
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  104|      0|        bstr bfilename = bstr0(filename);
  105|       |
  106|      0|        while (bfilename.len) {
  ------------------
  |  Branch (106:16): [True: 0, False: 0]
  ------------------
  107|      0|            bstr bfname;
  108|      0|            bstr_split_tok(bfilename, ",", &bfname, &bfilename);
  109|      0|            char *fname2 = bstrdup0(mf, bfname);
  110|       |
  111|      0|            if (!mp_path_exists(fname2) && !mp_is_url(bfname))
  ------------------
  |  Branch (111:17): [True: 0, False: 0]
  |  Branch (111:44): [True: 0, False: 0]
  ------------------
  112|      0|                mp_verbose(log, "file not found: '%s'\n", fname2);
  ------------------
  |  |   75|      0|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  113|      0|            else {
  114|      0|                mf_add(mf, fname2);
  115|      0|            }
  116|      0|            talloc_free(fname2);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  117|      0|        }
  118|       |
  119|      0|        goto exit_mf;
  120|      0|    }
  121|       |
  122|      4|    bstr bfilename = bstr0(filename);
  123|      4|    if (mp_is_url(bfilename))
  ------------------
  |  Branch (123:9): [True: 1, False: 3]
  ------------------
  124|      1|        goto exit_mf;
  125|       |
  126|      3|    size_t fname_avail = bfilename.len + 32;
  127|      3|    char *fname = talloc_size(mf, fname_avail);
  ------------------
  |  |   43|      3|#define talloc_size                     ta_xalloc_size
  |  |  ------------------
  |  |  |  |  120|      3|#define ta_xalloc_size(...)             ta_oom_p(ta_alloc_size(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  153|      3|#define ta_alloc_size(...)      ta_dbg_set_loc(ta_alloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|      3|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|      3|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|      3|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  128|       |
  129|       |#if HAVE_GLOB && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
  130|       |    if (!strchr(filename, '%')) {
  131|       |        // append * if none present
  132|       |        snprintf(fname, fname_avail, "%s%c", filename,
  133|       |            strchr(filename, '*') ? 0 : '*');
  134|       |        mp_info(log, "search expr: %s\n", fname);
  135|       |
  136|       |        glob_t gg;
  137|       |        if (glob(fname, 0, NULL, &gg)) {
  138|       |            talloc_free(mf);
  139|       |            return NULL;
  140|       |        }
  141|       |
  142|       |        for (int i = 0; i < gg.gl_pathc; i++) {
  143|       |            if (mp_path_isdir(gg.gl_pathv[i]))
  144|       |                continue;
  145|       |            mf_add(mf, gg.gl_pathv[i]);
  146|       |        }
  147|       |        globfree(&gg);
  148|       |        goto exit_mf;
  149|       |    }
  150|       |#endif
  151|       |
  152|       |    // We're using arbitrary user input as printf format with 1 int argument.
  153|       |    // Any format which uses exactly 1 int argument would be valid, but for
  154|       |    // simplicity we reject all conversion specifiers except %% and simple
  155|       |    // integer specifier: %[.][NUM]d where NUM is 1-3 digits (%.d is valid)
  156|      3|    const char *f = filename;
  157|      3|    int MAXDIGS = 3, nspec = 0, c;
  158|      3|    bool bad_spec = false;
  159|       |
  160|    113|    while (nspec < 2 && (c = *f++)) {
  ------------------
  |  Branch (160:12): [True: 113, False: 0]
  |  Branch (160:25): [True: 111, False: 2]
  ------------------
  161|    111|        if (c != '%')
  ------------------
  |  Branch (161:13): [True: 110, False: 1]
  ------------------
  162|    110|            continue;
  163|       |
  164|      1|        if (*f == '%') {
  ------------------
  |  Branch (164:13): [True: 0, False: 1]
  ------------------
  165|       |            // '%%', which ends up as an explicit % in the output.
  166|       |            // Skipping forwards as it doesn't require further attention.
  167|      0|            f++;
  168|      0|            continue;
  169|      0|        }
  170|       |
  171|       |        // Now c == '%' and *f != '%', thus we have entered territory of format
  172|       |        // specifiers which we are interested in.
  173|      1|        nspec++;
  174|       |
  175|      1|        if (*f == '.')
  ------------------
  |  Branch (175:13): [True: 0, False: 1]
  ------------------
  176|      0|            f++;
  177|       |
  178|      4|        for (int ndig = 0; mp_isdigit(*f) && ndig < MAXDIGS; ndig++, f++)
  ------------------
  |  Branch (178:28): [True: 3, False: 1]
  |  Branch (178:46): [True: 3, False: 0]
  ------------------
  179|      3|            /* no-op */;
  180|       |
  181|      1|        if (*f != 'd') {
  ------------------
  |  Branch (181:13): [True: 1, False: 0]
  ------------------
  182|      1|            bad_spec = true; // not int, or beyond our validation capacity
  183|      1|            break;
  184|      1|        }
  185|       |
  186|       |        // *f is 'd'
  187|      0|        f++;
  188|      0|    }
  189|       |
  190|       |    // nspec==0 (zero specifiers) is rejected because fname wouldn't advance.
  191|      3|    if (bad_spec || nspec != 1) {
  ------------------
  |  Branch (191:9): [True: 1, False: 2]
  |  Branch (191:21): [True: 2, False: 0]
  ------------------
  192|      3|        mp_err(log,
  ------------------
  |  |   72|      3|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  193|      3|               "unsupported expr format: '%s' - exactly one format specifier of the form %%[.][NUM]d is expected\n",
  194|      3|               filename);
  195|      3|        goto exit_mf;
  196|      3|    }
  197|       |
  198|      0|    mp_info(log, "search expr: %s\n", filename);
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  199|       |
  200|      0|    while (error_count < 5) {
  ------------------
  |  Branch (200:12): [True: 0, False: 0]
  ------------------
  201|      0|        if (snprintf(fname, fname_avail, filename, count++) >= fname_avail) {
  ------------------
  |  Branch (201:13): [True: 0, False: 0]
  ------------------
  202|      0|            mp_err(log, "format result too long: '%s'\n", filename);
  ------------------
  |  |   72|      0|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  203|      0|            goto exit_mf;
  204|      0|        }
  205|      0|        if (!mp_path_exists(fname)) {
  ------------------
  |  Branch (205:13): [True: 0, False: 0]
  ------------------
  206|      0|            error_count++;
  207|      0|            mp_verbose(log, "file not found: '%s'\n", fname);
  ------------------
  |  |   75|      0|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  208|      0|        } else {
  209|      0|            mf_add(mf, fname);
  210|      0|        }
  211|      0|    }
  212|       |
  213|      4|exit_mf:
  214|      4|    mp_info(log, "number of files: %d\n", mf->nr_of_files);
  ------------------
  |  |   74|      4|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  215|      4|    return mf;
  216|      0|}
demux_mf.c:mf_add:
   53|     48|{
   54|     48|    char *entry = talloc_strdup(mf, fname);
  ------------------
  |  |   50|     48|#define talloc_strdup                   ta_xstrdup
  ------------------
   55|     48|    MP_TARRAY_APPEND(mf, mf->names, mf->nr_of_files, entry);
  ------------------
  |  |  105|     48|    do {                                            \
  |  |  106|     48|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|     48|    do {                                            \
  |  |  |  |   97|     48|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|     48|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|     48|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|     48|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 48, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|     48|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|     48|    do {                                                        \
  |  |  |  |  |  |   89|     48|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|     48|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|     48|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|     48|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|     48|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|     48|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|     48|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|     48|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|     48|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|     48|        (idxvar)++;                                 \
  |  |  109|     48|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
   56|     48|}
demux_mf.c:open_mf_single:
  219|     48|{
  220|     48|    mf_t *mf = talloc_zero(talloc_ctx, mf_t);
  ------------------
  |  |   27|     48|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|     48|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     48|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  221|     48|    mf->log = log;
  222|     48|    mf_add(mf, filename);
  223|     48|    return mf;
  224|     48|}
demux_mf.c:probe_format:
  348|     48|{
  349|     48|    if (check > DEMUX_CHECK_REQUEST)
  ------------------
  |  Branch (349:9): [True: 31, False: 17]
  ------------------
  350|     31|        return NULL;
  351|     17|    char *org_type = type;
  352|     17|    if (!type || !type[0]) {
  ------------------
  |  Branch (352:9): [True: 17, False: 0]
  |  Branch (352:18): [True: 0, False: 0]
  ------------------
  353|     17|        char *p = strrchr(mf->names[0], '.');
  354|     17|        if (p)
  ------------------
  |  Branch (354:13): [True: 8, False: 9]
  ------------------
  355|      8|            type = p + 1;
  356|     17|    }
  357|    819|    for (int i = 0; type2format[i].type; i++) {
  ------------------
  |  Branch (357:21): [True: 805, False: 14]
  ------------------
  358|    805|        if (type && strcasecmp(type, type2format[i].type) == 0)
  ------------------
  |  Branch (358:13): [True: 355, False: 450]
  |  Branch (358:21): [True: 3, False: 352]
  ------------------
  359|      3|            return type2format[i].codec;
  360|    805|    }
  361|     14|    if (check == DEMUX_CHECK_REQUEST) {
  ------------------
  |  Branch (361:9): [True: 0, False: 14]
  ------------------
  362|      0|        if (!org_type) {
  ------------------
  |  Branch (362:13): [True: 0, False: 0]
  ------------------
  363|      0|            MP_ERR(mf, "file type was not set! (try --mf-type=ext)\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  364|      0|        } else {
  365|      0|            MP_ERR(mf, "--mf-type set to an unknown codec!\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  366|      0|        }
  367|      0|    }
  368|     14|    return NULL;
  369|     17|}
demux_mf.c:demux_close_mf:
  424|     52|{
  425|     52|}

demux_mkv.c:demux_mkv_open:
 2390|    280|{
 2391|    280|    stream_t *s = demuxer->stream;
 2392|    280|    mkv_demuxer_t *mkv_d;
 2393|    280|    int64_t start_pos;
 2394|    280|    int64_t end_pos;
 2395|       |
 2396|    280|    mkv_d = talloc_zero(demuxer, struct mkv_demuxer);
  ------------------
  |  |   27|    280|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    280|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    280|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2397|    280|    demuxer->priv = mkv_d;
 2398|    280|    mkv_d->tc_scale = 1000000;
 2399|    280|    mkv_d->a_skip_preroll = 1;
 2400|    280|    mkv_d->skip_to_timecode = INT64_MIN;
 2401|       |
 2402|    280|    if (demuxer->params)
  ------------------
  |  Branch (2402:9): [True: 280, False: 0]
  ------------------
 2403|    280|        mkv_d->probably_webm_dash_init = demuxer->params->init_fragment.len > 0;
 2404|       |
 2405|       |    // Make sure you can seek back after read_ebml_header() if no EBML ID.
 2406|    280|    if (stream_read_peek(s, &(char[4]){0}, 4) != 4)
  ------------------
  |  Branch (2406:9): [True: 4, False: 276]
  ------------------
 2407|      4|        return -1;
 2408|    276|    if (!read_ebml_header(demuxer))
  ------------------
  |  Branch (2408:9): [True: 276, False: 0]
  ------------------
 2409|    276|        return -1;
 2410|      0|    MP_DBG(demuxer, "Found the head...\n");
  ------------------
  |  |   89|      0|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2411|       |
 2412|      0|    if (!read_mkv_segment_header(demuxer, &end_pos))
  ------------------
  |  Branch (2412:9): [True: 0, False: 0]
  ------------------
 2413|      0|        return -1;
 2414|       |
 2415|      0|    mkv_d->segment_start = stream_tell(s);
 2416|      0|    mkv_d->segment_end = end_pos;
 2417|       |
 2418|      0|    struct MPOpts *mp_opts = mp_get_config_group(mkv_d, demuxer->global, &mp_opt_root);
 2419|      0|    mkv_d->edition_id = mp_opts->edition_id;
 2420|      0|    talloc_free(mp_opts);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 2421|       |
 2422|      0|    mkv_d->opts = mp_get_config_group(mkv_d, demuxer->global, &demux_mkv_conf);
 2423|       |
 2424|      0|    if (demuxer->params && demuxer->params->matroska_was_valid)
  ------------------
  |  Branch (2424:9): [True: 0, False: 0]
  |  Branch (2424:28): [True: 0, False: 0]
  ------------------
 2425|      0|        *demuxer->params->matroska_was_valid = true;
 2426|       |
 2427|      0|    while (1) {
  ------------------
  |  Branch (2427:12): [Folded - Ignored]
  ------------------
 2428|      0|        start_pos = stream_tell(s);
 2429|      0|        uint32_t id = ebml_read_id(s);
 2430|      0|        if (s->eof) {
  ------------------
  |  Branch (2430:13): [True: 0, False: 0]
  ------------------
 2431|      0|            if (!mkv_d->probably_webm_dash_init)
  ------------------
  |  Branch (2431:17): [True: 0, False: 0]
  ------------------
 2432|      0|                MP_WARN(demuxer, "Unexpected end of file (no clusters found)\n");
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2433|      0|            break;
 2434|      0|        }
 2435|      0|        if (id == MATROSKA_ID_CLUSTER) {
  ------------------
  |  |   28|      0|#define MATROSKA_ID_CLUSTER                      0x1f43b675
  ------------------
  |  Branch (2435:13): [True: 0, False: 0]
  ------------------
 2436|      0|            MP_DBG(demuxer, "|+ found cluster\n");
  ------------------
  |  |   89|      0|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2437|      0|            mkv_d->cluster_start = start_pos;
 2438|      0|            break;
 2439|      0|        }
 2440|      0|        int res = read_header_element(demuxer, id, start_pos);
 2441|      0|        if (res < 0)
  ------------------
  |  Branch (2441:13): [True: 0, False: 0]
  ------------------
 2442|      0|            return -1;
 2443|      0|    }
 2444|       |
 2445|      0|    int64_t end = stream_get_size(s);
 2446|       |
 2447|       |    // Read headers that come after the first cluster (i.e. require seeking).
 2448|       |    // Note: reading might increase ->num_headers.
 2449|       |    //       Likewise, ->headers might be reallocated.
 2450|      0|    int only_cue = -1;
 2451|      0|    for (int n = 0; n < mkv_d->num_headers; n++) {
  ------------------
  |  Branch (2451:21): [True: 0, False: 0]
  ------------------
 2452|      0|        struct header_elem *elem = &mkv_d->headers[n];
 2453|      0|        if (elem->parsed)
  ------------------
  |  Branch (2453:13): [True: 0, False: 0]
  ------------------
 2454|      0|            continue;
 2455|       |        // Warn against incomplete files and skip headers outside of range.
 2456|      0|        if (elem->pos >= end || !s->seekable) {
  ------------------
  |  Branch (2456:13): [True: 0, False: 0]
  |  Branch (2456:33): [True: 0, False: 0]
  ------------------
 2457|      0|            elem->parsed = true; // don't bother if file is incomplete
 2458|      0|            if (end < 0 || !s->seekable) {
  ------------------
  |  Branch (2458:17): [True: 0, False: 0]
  |  Branch (2458:28): [True: 0, False: 0]
  ------------------
 2459|      0|                MP_WARN(demuxer, "Stream is not seekable or unknown size, "
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2460|      0|                        "not reading mkv metadata at end of file.\n");
 2461|      0|            } else if (!mkv_d->eof_warning &&
  ------------------
  |  Branch (2461:24): [True: 0, False: 0]
  ------------------
 2462|      0|                       !(mkv_d->probably_webm_dash_init &&  elem->pos == end))
  ------------------
  |  Branch (2462:26): [True: 0, False: 0]
  |  Branch (2462:61): [True: 0, False: 0]
  ------------------
 2463|      0|            {
 2464|      0|                MP_WARN(demuxer, "mkv metadata beyond end of file - incomplete "
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2465|      0|                        "file?\n");
 2466|      0|                mkv_d->eof_warning = true;
 2467|      0|            }
 2468|      0|            continue;
 2469|      0|        }
 2470|      0|        only_cue = only_cue < 0 && elem->id == MATROSKA_ID_CUES;
  ------------------
  |  |  126|      0|#define MATROSKA_ID_CUES                         0x1c53bb6b
  ------------------
  |  Branch (2470:20): [True: 0, False: 0]
  |  Branch (2470:36): [True: 0, False: 0]
  ------------------
 2471|      0|    }
 2472|       |
 2473|       |    // If there's only 1 needed element, and it's the cues, defer reading.
 2474|      0|    if (only_cue == 1) {
  ------------------
  |  Branch (2474:9): [True: 0, False: 0]
  ------------------
 2475|       |        // Read cues when they are needed, to avoid seeking on opening.
 2476|      0|        MP_VERBOSE(demuxer, "Deferring reading cues.\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2477|      0|    } else {
 2478|       |        // Read them by ascending position to reduce unneeded seeks.
 2479|       |        // O(n^2) because the number of elements is very low.
 2480|      0|        while (1) {
  ------------------
  |  Branch (2480:16): [Folded - Ignored]
  ------------------
 2481|      0|            struct header_elem *lowest = NULL;
 2482|      0|            for (int n = 0; n < mkv_d->num_headers; n++) {
  ------------------
  |  Branch (2482:29): [True: 0, False: 0]
  ------------------
 2483|      0|                struct header_elem *elem = &mkv_d->headers[n];
 2484|      0|                if (elem->parsed)
  ------------------
  |  Branch (2484:21): [True: 0, False: 0]
  ------------------
 2485|      0|                    continue;
 2486|      0|                if (!lowest || elem->pos < lowest->pos)
  ------------------
  |  Branch (2486:21): [True: 0, False: 0]
  |  Branch (2486:32): [True: 0, False: 0]
  ------------------
 2487|      0|                    lowest = elem;
 2488|      0|            }
 2489|       |
 2490|      0|            if (!lowest)
  ------------------
  |  Branch (2490:17): [True: 0, False: 0]
  ------------------
 2491|      0|                break;
 2492|       |
 2493|      0|            if (read_deferred_element(demuxer, lowest) < 0)
  ------------------
  |  Branch (2493:17): [True: 0, False: 0]
  ------------------
 2494|      0|                return -1;
 2495|      0|        }
 2496|      0|    }
 2497|       |
 2498|      0|    if (!stream_seek(s, start_pos)) {
  ------------------
  |  Branch (2498:9): [True: 0, False: 0]
  ------------------
 2499|      0|        MP_ERR(demuxer, "Couldn't seek back after reading headers?\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2500|      0|        return -1;
 2501|      0|    }
 2502|       |
 2503|      0|    MP_VERBOSE(demuxer, "All headers are parsed!\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2504|       |
 2505|      0|    display_create_tracks(demuxer);
 2506|      0|    add_coverart(demuxer);
 2507|      0|    process_tags(demuxer);
 2508|       |
 2509|      0|    probe_first_timestamp(demuxer);
 2510|      0|    if (mkv_d->opts->probe_duration)
  ------------------
  |  Branch (2510:9): [True: 0, False: 0]
  ------------------
 2511|      0|        probe_last_timestamp(demuxer, start_pos);
 2512|      0|    probe_x264_garbage(demuxer);
 2513|      0|    probe_if_image(demuxer);
 2514|       |
 2515|      0|    return 0;
 2516|      0|}
demux_mkv.c:read_ebml_header:
 2303|    276|{
 2304|    276|    mkv_demuxer_t *mkv_d = demuxer->priv;
 2305|    276|    stream_t *s = demuxer->stream;
 2306|       |
 2307|    276|    if (ebml_read_id(s) != EBML_ID_EBML)
  ------------------
  |  |    3|    276|#define EBML_ID_EBML                             0x1a45dfa3
  ------------------
  |  Branch (2307:9): [True: 276, False: 0]
  ------------------
 2308|    276|        return 0;
 2309|      0|    struct ebml_ebml ebml_master = {0};
 2310|      0|    struct ebml_parse_ctx parse_ctx = { demuxer->log, .no_error_messages = true };
 2311|      0|    if (ebml_read_element(s, &parse_ctx, &ebml_master, &ebml_ebml_desc) < 0)
  ------------------
  |  Branch (2311:9): [True: 0, False: 0]
  ------------------
 2312|      0|        return 0;
 2313|      0|    bool is_matroska = false, is_webm = false;
 2314|      0|    if (!ebml_master.doc_type) {
  ------------------
  |  Branch (2314:9): [True: 0, False: 0]
  ------------------
 2315|      0|        MP_VERBOSE(demuxer, "File has EBML header but no doctype. "
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2316|      0|                   "Assuming \"matroska\".\n");
 2317|      0|        is_matroska = true;
 2318|      0|    } else if (strcmp(ebml_master.doc_type, "matroska") == 0) {
  ------------------
  |  Branch (2318:16): [True: 0, False: 0]
  ------------------
 2319|      0|        is_matroska = true;
 2320|      0|    } else if (strcmp(ebml_master.doc_type, "webm") == 0) {
  ------------------
  |  Branch (2320:16): [True: 0, False: 0]
  ------------------
 2321|      0|        is_webm = true;
 2322|      0|    }
 2323|      0|    if (!is_matroska && !is_webm) {
  ------------------
  |  Branch (2323:9): [True: 0, False: 0]
  |  Branch (2323:25): [True: 0, False: 0]
  ------------------
 2324|      0|        MP_TRACE(demuxer, "no head found\n");
  ------------------
  |  |   90|      0|#define MP_TRACE(obj, ...)      MP_MSG(obj, MSGL_TRACE, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2325|      0|        talloc_free(parse_ctx.talloc_ctx);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 2326|      0|        return 0;
 2327|      0|    }
 2328|      0|    mkv_d->probably_webm_dash_init &= is_webm;
 2329|      0|    if (ebml_master.doc_type_read_version > 2) {
  ------------------
  |  Branch (2329:9): [True: 0, False: 0]
  ------------------
 2330|      0|        MP_WARN(demuxer, "This looks like a Matroska file, "
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2331|      0|                "but we don't support format version %"PRIu64"\n",
 2332|      0|                ebml_master.doc_type_read_version);
 2333|      0|        talloc_free(parse_ctx.talloc_ctx);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 2334|      0|        return 0;
 2335|      0|    }
 2336|      0|    if ((ebml_master.n_ebml_read_version
  ------------------
  |  Branch (2336:10): [True: 0, False: 0]
  ------------------
 2337|      0|         && ebml_master.ebml_read_version != EBML_VERSION)
  ------------------
  |  |   31|      0|#define EBML_VERSION 1
  ------------------
  |  Branch (2337:13): [True: 0, False: 0]
  ------------------
 2338|      0|        || (ebml_master.n_ebml_max_size_length
  ------------------
  |  Branch (2338:13): [True: 0, False: 0]
  ------------------
 2339|      0|            && ebml_master.ebml_max_size_length > 8)
  ------------------
  |  Branch (2339:16): [True: 0, False: 0]
  ------------------
 2340|      0|        || (ebml_master.n_ebml_max_id_length
  ------------------
  |  Branch (2340:13): [True: 0, False: 0]
  ------------------
 2341|      0|            && ebml_master.ebml_max_id_length != 4))
  ------------------
  |  Branch (2341:16): [True: 0, False: 0]
  ------------------
 2342|      0|    {
 2343|      0|        MP_WARN(demuxer, "This looks like a Matroska file, "
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2344|      0|                "but the header has bad parameters\n");
 2345|      0|        talloc_free(parse_ctx.talloc_ctx);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 2346|      0|        return 0;
 2347|      0|    }
 2348|      0|    talloc_free(parse_ctx.talloc_ctx);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 2349|       |
 2350|      0|    return 1;
 2351|      0|}
demux_mkv.c:mkv_seek_reset:
 2715|    280|{
 2716|    280|    mkv_demuxer_t *mkv_d = demuxer->priv;
 2717|       |
 2718|    280|    for (int i = 0; i < mkv_d->num_tracks; i++) {
  ------------------
  |  Branch (2718:21): [True: 0, False: 280]
  ------------------
 2719|      0|        mkv_track_t *track = mkv_d->tracks[i];
 2720|      0|        if (track->av_parser)
  ------------------
  |  Branch (2720:13): [True: 0, False: 0]
  ------------------
 2721|      0|            av_parser_close(track->av_parser);
 2722|      0|        track->av_parser = NULL;
 2723|      0|        avcodec_free_context(&track->av_parser_codec);
 2724|      0|    }
 2725|       |
 2726|    280|    for (int n = 0; n < mkv_d->num_blocks; n++)
  ------------------
  |  Branch (2726:21): [True: 0, False: 280]
  ------------------
 2727|      0|        free_block(&mkv_d->blocks[n]);
 2728|    280|    mkv_d->num_blocks = 0;
 2729|       |
 2730|    280|    for (int n = 0; n < mkv_d->num_packets; n++)
  ------------------
  |  Branch (2730:21): [True: 0, False: 280]
  ------------------
 2731|      0|        talloc_free(mkv_d->packets[n]);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 2732|    280|    mkv_d->num_packets = 0;
 2733|       |
 2734|    280|    mkv_d->skip_to_timecode = INT64_MIN;
 2735|    280|}
demux_mkv.c:mkv_free:
 3638|    280|{
 3639|    280|    struct mkv_demuxer *mkv_d = demuxer->priv;
 3640|    280|    if (!mkv_d)
  ------------------
  |  Branch (3640:9): [True: 0, False: 280]
  ------------------
 3641|      0|        return;
 3642|    280|    mkv_seek_reset(demuxer);
 3643|    280|    for (int i = 0; i < mkv_d->num_tracks; i++)
  ------------------
  |  Branch (3643:21): [True: 0, False: 280]
  ------------------
 3644|      0|        demux_mkv_free_trackentry(mkv_d->tracks[i]);
 3645|    280|}

demux_mpv.c:open_mpv:
   24|    117|{
   25|    117|    if (check != DEMUX_CHECK_REQUEST)
  ------------------
  |  Branch (25:9): [True: 35, False: 82]
  ------------------
   26|     35|        return -1;
   27|       |
   28|     82|    struct stream *s = demuxer->stream;
   29|     82|    if (!s->info || strcmp(s->info->name, "mpv"))
  ------------------
  |  Branch (29:9): [True: 0, False: 82]
  |  Branch (29:21): [True: 0, False: 82]
  ------------------
   30|      0|        return -1;
   31|       |
   32|     82|    demuxer->playlist = talloc_zero(demuxer, struct playlist);
  ------------------
  |  |   27|     82|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|     82|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     82|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   33|     82|    mp_url_unescape_inplace(s->path);
   34|     82|    playlist_append_file(demuxer->playlist, s->path);
   35|     82|    playlist_set_stream_flags(demuxer->playlist, demuxer->stream_origin);
   36|     82|    demuxer->fully_read = true;
   37|     82|    demux_close_stream(demuxer);
   38|       |
   39|     82|    return 0;
   40|     82|}

demux_null.c:try_open_file:
   23|     36|{
   24|     36|    if (!bstr_startswith0(bstr0(demux->filename), "null://") &&
  ------------------
  |  Branch (24:9): [True: 35, False: 1]
  ------------------
   25|     36|        check != DEMUX_CHECK_REQUEST)
  ------------------
  |  Branch (25:9): [True: 35, False: 0]
  ------------------
   26|     35|        return -1;
   27|      1|    demux->seekable = true;
   28|      1|    return 0;
   29|     36|}

demux_playlist.c:open_file:
  654|    433|{
  655|    433|    if (!demuxer->access_references)
  ------------------
  |  Branch (655:9): [True: 0, False: 433]
  ------------------
  656|      0|        return -1;
  657|       |
  658|    433|    bool force = check < DEMUX_CHECK_UNSAFE || check == DEMUX_CHECK_REQUEST;
  ------------------
  |  Branch (658:18): [True: 0, False: 433]
  |  Branch (658:48): [True: 0, False: 433]
  ------------------
  659|       |
  660|    433|    struct pl_parser *p = talloc_zero(NULL, struct pl_parser);
  ------------------
  |  |   27|    433|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    433|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    433|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  661|    433|    p->global = demuxer->global;
  662|    433|    p->log = demuxer->log;
  663|    433|    p->pl = talloc_zero(p, struct playlist);
  ------------------
  |  |   27|    433|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    433|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    433|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  664|    433|    p->real_stream = demuxer->stream;
  665|    433|    p->add_base = true;
  666|       |
  667|    433|    struct demux_opts *opts = mp_get_config_group(p, p->global, &demux_conf);
  668|    433|    p->codepage = opts->meta_cp;
  669|       |
  670|    433|    char probe[PROBE_SIZE];
  671|    433|    int probe_len = stream_read_peek(p->real_stream, probe, sizeof(probe));
  672|    433|    p->s = stream_memory_open(demuxer->global, probe, probe_len);
  673|    433|    p->s->mime_type = demuxer->stream->mime_type;
  674|    433|    p->utf16 = stream_skip_bom(p->s);
  675|    433|    p->force = force;
  676|    433|    p->check_level = check;
  677|    433|    p->probing = true;
  678|    433|    p->autocreate_playlist = demuxer->params->allow_playlist_create ? opts->autocreate_playlist : 0;
  ------------------
  |  Branch (678:30): [True: 0, False: 433]
  ------------------
  679|    433|    p->mp_opts = mp_get_config_group(demuxer, demuxer->global, &mp_opt_root);
  680|    433|    p->opts = mp_get_config_group(demuxer, demuxer->global, &demux_playlist_conf);
  681|       |
  682|    433|    const struct pl_format *fmts = playlist_formats;
  683|    433|    if (demuxer->desc == &demuxer_desc_directory)
  ------------------
  |  Branch (683:9): [True: 388, False: 45]
  ------------------
  684|    388|        fmts = dir_formats;
  685|       |
  686|    433|    const struct pl_format *fmt = probe_pl(p, fmts);
  687|    433|    free_stream(p->s);
  688|    433|    playlist_clear(p->pl);
  689|    433|    if (!fmt) {
  ------------------
  |  Branch (689:9): [True: 429, False: 4]
  ------------------
  690|    429|        talloc_free(p);
  ------------------
  |  |   47|    429|#define talloc_free                     ta_free
  ------------------
  691|    429|        return -1;
  692|    429|    }
  693|       |
  694|      4|    p->probing = false;
  695|      4|    p->error = false;
  696|      4|    p->s = demuxer->stream;
  697|      4|    p->utf16 = stream_skip_bom(p->s);
  698|      4|    bool ok = fmt->parse(p) >= 0 && !p->error;
  ------------------
  |  Branch (698:15): [True: 4, False: 0]
  |  Branch (698:37): [True: 4, False: 0]
  ------------------
  699|      4|    if (p->add_base) {
  ------------------
  |  Branch (699:9): [True: 4, False: 0]
  ------------------
  700|      4|        bstr proto = mp_split_proto(bstr0(demuxer->filename), NULL);
  701|       |        // Don't add base path to self-expanding protocols
  702|      4|        if (bstrcasecmp0(proto, "memory") && bstrcasecmp0(proto, "lavf") &&
  ------------------
  |  Branch (702:13): [True: 4, False: 0]
  |  Branch (702:46): [True: 4, False: 0]
  ------------------
  703|      4|            bstrcasecmp0(proto, "hex") && bstrcasecmp0(proto, "data") &&
  ------------------
  |  Branch (703:13): [True: 2, False: 2]
  |  Branch (703:43): [True: 0, False: 2]
  ------------------
  704|      4|            bstrcasecmp0(proto, "fd"))
  ------------------
  |  Branch (704:13): [True: 0, False: 0]
  ------------------
  705|      0|        {
  706|      0|            playlist_add_base_path(p->pl, mp_dirname(demuxer->filename));
  707|      0|        }
  708|      4|    }
  709|      4|    playlist_set_stream_flags(p->pl, demuxer->stream_origin);
  710|      4|    demuxer->playlist = talloc_steal(demuxer, p->pl);
  ------------------
  |  |   38|      4|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      4|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  711|      4|    demuxer->filetype = p->format ? p->format : fmt->name;
  ------------------
  |  Branch (711:25): [True: 0, False: 4]
  ------------------
  712|      4|    demuxer->fully_read = true;
  713|      4|    talloc_free(p);
  ------------------
  |  |   47|      4|#define talloc_free                     ta_free
  ------------------
  714|      4|    if (ok)
  ------------------
  |  Branch (714:9): [True: 4, False: 0]
  ------------------
  715|      4|        demux_close_stream(demuxer);
  716|      4|    return ok ? 0 : -1;
  ------------------
  |  Branch (716:12): [True: 4, False: 0]
  ------------------
  717|    433|}
demux_playlist.c:parse_m3u:
  243|     49|{
  244|     49|    bstr line = pl_get_line(p);
  245|     49|    if (p->probing && !bstr_equals0(line, "#EXTM3U")) {
  ------------------
  |  Branch (245:9): [True: 45, False: 4]
  |  Branch (245:23): [True: 45, False: 0]
  ------------------
  246|       |        // Last resort: if the file extension is m3u, it might be headerless.
  247|     45|        if (p->check_level == DEMUX_CHECK_UNSAFE) {
  ------------------
  |  Branch (247:13): [True: 14, False: 31]
  ------------------
  248|     14|            char *ext = mp_splitext(p->real_stream->url, NULL);
  249|     14|            char probe[PROBE_SIZE];
  250|     14|            int len = stream_read_peek(p->real_stream, probe, sizeof(probe));
  251|     14|            bstr data = {probe, len};
  252|     14|            if (ext && data.len >= 2 && maybe_text(data)) {
  ------------------
  |  Branch (252:17): [True: 5, False: 9]
  |  Branch (252:24): [True: 5, False: 0]
  |  Branch (252:41): [True: 5, False: 0]
  ------------------
  253|      5|                const char *exts[] = {"m3u", "m3u8", NULL};
  254|      7|                for (int n = 0; exts[n]; n++) {
  ------------------
  |  Branch (254:33): [True: 6, False: 1]
  ------------------
  255|      6|                    if (strcasecmp(ext, exts[n]) == 0)
  ------------------
  |  Branch (255:25): [True: 4, False: 2]
  ------------------
  256|      4|                        goto ok;
  257|      6|                }
  258|      5|            }
  259|     14|        }
  260|     41|        pl_free_line(p, line);
  261|     41|        return -1;
  262|     45|    }
  263|       |
  264|      8|ok:
  265|      8|    if (p->probing) {
  ------------------
  |  Branch (265:9): [True: 4, False: 4]
  ------------------
  266|      4|        pl_free_line(p, line);
  267|      4|        return 0;
  268|      4|    }
  269|       |
  270|      4|    char *title = NULL;
  271|      8|    while (line.len || !pl_eof(p)) {
  ------------------
  |  Branch (271:12): [True: 4, False: 4]
  |  Branch (271:24): [True: 0, False: 4]
  ------------------
  272|      4|        bstr line_dup = line;
  273|      4|        if (bstr_eatstart0(&line_dup, "#EXTINF:")) {
  ------------------
  |  Branch (273:13): [True: 0, False: 4]
  ------------------
  274|      0|            bstr duration, btitle;
  275|      0|            if (bstr_split_tok(line_dup, ",", &duration, &btitle) && btitle.len) {
  ------------------
  |  Branch (275:17): [True: 0, False: 0]
  |  Branch (275:70): [True: 0, False: 0]
  ------------------
  276|      0|                talloc_free(title);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  277|      0|                title = bstrto0(NULL, btitle);
  278|      0|            }
  279|      4|        } else if (bstr_startswith0(line_dup, "#EXT-X-")) {
  ------------------
  |  Branch (279:20): [True: 0, False: 4]
  ------------------
  280|      0|            p->format = "hls";
  281|      4|        } else if (line_dup.len > 0 && !bstr_startswith0(line_dup, "#")) {
  ------------------
  |  Branch (281:20): [True: 4, False: 0]
  |  Branch (281:40): [True: 4, False: 0]
  ------------------
  282|      4|            char *fn = bstrto0(NULL, line_dup);
  283|      4|            struct playlist_entry *e = playlist_entry_new(fn);
  284|      4|            talloc_free(fn);
  ------------------
  |  |   47|      4|#define talloc_free                     ta_free
  ------------------
  285|      4|            e->title = talloc_steal(e, title);
  ------------------
  |  |   38|      4|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      4|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  286|      4|            title = NULL;
  287|      4|            playlist_insert_at(p->pl, e, NULL);
  288|      4|        }
  289|      4|        pl_free_line(p, line);
  290|      4|        line = pl_get_line(p);
  291|      4|    }
  292|      4|    pl_free_line(p, line);
  293|      4|    talloc_free(title);
  ------------------
  |  |   47|      4|#define talloc_free                     ta_free
  ------------------
  294|      4|    return 0;
  295|      8|}
demux_playlist.c:pl_get_line:
  198|    176|{
  199|    176|    bstr line = bstr_strip(bstr0(pl_get_line0(p)));
  200|    176|    const char *charset = mp_charset_guess(p, p->log, line, p->codepage, 0);
  201|    176|    if (charset && !mp_charset_is_utf8(charset)) {
  ------------------
  |  Branch (201:9): [True: 176, False: 0]
  |  Branch (201:20): [True: 140, False: 36]
  ------------------
  202|    140|        bstr utf8 = mp_iconv_to_utf8(p->log, line, charset, 0);
  203|    140|        if (utf8.start && utf8.start != line.start) {
  ------------------
  |  Branch (203:13): [True: 140, False: 0]
  |  Branch (203:27): [True: 140, False: 0]
  ------------------
  204|    140|            line = utf8;
  205|    140|            p->line_allocated = true;
  206|    140|        }
  207|    140|    }
  208|    176|    return line;
  209|    176|}
demux_playlist.c:pl_get_line0:
  185|    176|{
  186|    176|    char *res = read_line(p->s, p->buffer, sizeof(p->buffer), p->utf16);
  187|    176|    if (res) {
  ------------------
  |  Branch (187:9): [True: 168, False: 8]
  ------------------
  188|    168|        int len = strlen(res);
  189|    168|        if (len > 0 && res[len - 1] == '\n')
  ------------------
  |  Branch (189:13): [True: 168, False: 0]
  |  Branch (189:24): [True: 0, False: 168]
  ------------------
  190|      0|            res[len - 1] = '\0';
  191|    168|    } else {
  192|      8|        p->error |= !p->s->eof;
  193|      8|    }
  194|    176|    return res;
  195|    176|}
demux_playlist.c:read_line:
  163|    176|{
  164|    176|    if (max < 1)
  ------------------
  |  Branch (164:9): [True: 0, False: 176]
  ------------------
  165|      0|        return NULL;
  166|    176|    int read = 0;
  167|    348|    while (1) {
  ------------------
  |  Branch (167:12): [Folded - Ignored]
  ------------------
  168|       |        // Reserve 1 byte of ptr for terminating \0.
  169|    348|        int l = read_characters(s, &mem[read], max - read - 1, utf16);
  170|    348|        if (l < 0 || memchr(&mem[read], '\0', l)) {
  ------------------
  |  Branch (170:13): [True: 0, False: 348]
  |  Branch (170:22): [True: 0, False: 348]
  ------------------
  171|      0|            MP_WARN(s, "error reading line\n");
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  172|      0|            return NULL;
  173|      0|        }
  174|    348|        read += l;
  175|    348|        if (l == 0 || (read > 0 && mem[read - 1] == '\n'))
  ------------------
  |  Branch (175:13): [True: 176, False: 172]
  |  Branch (175:24): [True: 172, False: 0]
  |  Branch (175:36): [True: 0, False: 172]
  ------------------
  176|    176|            break;
  177|    348|    }
  178|    176|    mem[read] = '\0';
  179|    176|    if (!stream_read_peek(s, &(char){0}, 1) && read == 0) // legitimate EOF
  ------------------
  |  Branch (179:9): [True: 176, False: 0]
  |  Branch (179:48): [True: 8, False: 168]
  ------------------
  180|      8|        return NULL;
  181|    168|    return mem;
  182|    176|}
demux_playlist.c:read_characters:
  128|    348|{
  129|    348|    if (utf16 == 1 || utf16 == 2) {
  ------------------
  |  Branch (129:9): [True: 16, False: 332]
  |  Branch (129:23): [True: 0, False: 332]
  ------------------
  130|     16|        uint8_t *cur = dst;
  131|  1.18k|        while (1) {
  ------------------
  |  Branch (131:16): [Folded - Ignored]
  ------------------
  132|  1.18k|            if ((cur - dst) + 8 >= dstsize) // PUT_UTF8 writes max. 8 bytes
  ------------------
  |  Branch (132:17): [True: 0, False: 1.18k]
  ------------------
  133|      0|                return -1; // line too long
  134|  1.18k|            uint32_t c;
  135|  1.18k|            uint8_t tmp;
  136|  1.18k|            GET_UTF16(c, stream_read_word_endian(s, utf16 == 2), return -1;)
  137|  1.18k|            if (s->eof)
  ------------------
  |  Branch (137:17): [True: 16, False: 1.16k]
  ------------------
  138|     16|                break; // legitimate EOF; ignore the case of partial reads
  139|  1.16k|            PUT_UTF8(c, tmp, *cur++ = tmp;)
  140|  1.16k|            if (c == '\n')
  ------------------
  |  Branch (140:17): [True: 0, False: 1.16k]
  ------------------
  141|      0|                break;
  142|  1.16k|        }
  143|     16|        return cur - dst;
  144|    332|    } else {
  145|    332|        uint8_t buf[1024];
  146|    332|        int buf_len = stream_read_peek(s, buf, sizeof(buf));
  147|    332|        uint8_t *end = memchr(buf, '\n', buf_len);
  148|    332|        int len = end ? end - buf + 1 : buf_len;
  ------------------
  |  Branch (148:19): [True: 0, False: 332]
  ------------------
  149|    332|        if (len > dstsize)
  ------------------
  |  Branch (149:13): [True: 0, False: 332]
  ------------------
  150|      0|            return -1; // line too long
  151|    332|        memcpy(dst, buf, len);
  152|    332|        stream_seek_skip(s, stream_tell(s) + len);
  153|    332|        return len;
  154|    332|    }
  155|    348|}
demux_playlist.c:stream_read_word_endian:
  117|  1.18k|{
  118|  1.18k|    unsigned int y = stream_read_char(s);
  119|  1.18k|    y = (y << 8) | stream_read_char(s);
  120|  1.18k|    if (!big_endian)
  ------------------
  |  Branch (120:9): [True: 1.18k, False: 0]
  ------------------
  121|  1.18k|        y = ((y >> 8) & 0xFF) | (y << 8);
  122|  1.18k|    return y;
  123|  1.18k|}
demux_playlist.c:maybe_text:
  233|      5|{
  234|    164|    for (int n = 0; n < d.len; n++) {
  ------------------
  |  Branch (234:21): [True: 159, False: 5]
  ------------------
  235|    159|        unsigned char c = d.start[n];
  236|    159|        if (c < 32 && c != '\n' && c != '\r' && c != '\t')
  ------------------
  |  Branch (236:13): [True: 0, False: 159]
  |  Branch (236:23): [True: 0, False: 0]
  |  Branch (236:36): [True: 0, False: 0]
  |  Branch (236:49): [True: 0, False: 0]
  ------------------
  237|      0|            return false;
  238|    159|    }
  239|      5|    return true;
  240|      5|}
demux_playlist.c:pl_free_line:
  213|    176|{
  214|    176|    if (p->line_allocated) {
  ------------------
  |  Branch (214:9): [True: 140, False: 36]
  ------------------
  215|    140|        talloc_free(line.start);
  ------------------
  |  |   47|    140|#define talloc_free                     ta_free
  ------------------
  216|    140|        p->line_allocated = false;
  217|    140|    }
  218|    176|}
demux_playlist.c:pl_eof:
  228|     88|{
  229|     88|    return p->error || p->s->eof;
  ------------------
  |  Branch (229:12): [True: 0, False: 88]
  |  Branch (229:24): [True: 6, False: 82]
  ------------------
  230|     88|}
demux_playlist.c:parse_ref_init:
  298|     41|{
  299|     41|    bstr line = pl_get_line(p);
  300|     41|    if (!bstr_equals0(line, "[Reference]")) {
  ------------------
  |  Branch (300:9): [True: 41, False: 0]
  ------------------
  301|     41|        pl_free_line(p, line);
  302|     41|        return -1;
  303|     41|    }
  304|      0|    pl_free_line(p, line);
  305|       |
  306|       |    // ASF http streaming redirection - this is needed because ffmpeg http://
  307|       |    // and mmsh:// can not automatically switch automatically between each
  308|       |    // others. Both protocols use http - MMSH requires special http headers
  309|       |    // to "activate" it, and will in other cases return this playlist.
  310|      0|    static const char *const mmsh_types[] = {"audio/x-ms-wax",
  311|      0|        "audio/x-ms-wma", "video/x-ms-asf", "video/x-ms-afs", "video/x-ms-wmv",
  312|      0|        "video/x-ms-wma", "application/x-mms-framed",
  313|      0|        "application/vnd.ms.wms-hdr.asfv1", NULL};
  314|      0|    bstr burl = bstr0(p->s->url);
  315|      0|    if (bstr_eatstart0(&burl, "http://") && check_mimetype(p->s, mmsh_types)) {
  ------------------
  |  Branch (315:9): [True: 0, False: 0]
  |  Branch (315:45): [True: 0, False: 0]
  ------------------
  316|      0|        MP_INFO(p, "Redirecting to mmsh://\n");
  ------------------
  |  |   87|      0|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  317|      0|        playlist_append_file(p->pl, talloc_asprintf(p, "mmsh://%.*s", BSTR_P(burl)));
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (127:62): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  318|      0|        return 0;
  319|      0|    }
  320|       |
  321|      0|    while (!pl_eof(p)) {
  ------------------
  |  Branch (321:12): [True: 0, False: 0]
  ------------------
  322|      0|        line = pl_get_line(p);
  323|      0|        bstr value;
  324|      0|        if (bstr_case_startswith(line, bstr0("Ref"))) {
  ------------------
  |  Branch (324:13): [True: 0, False: 0]
  ------------------
  325|      0|            bstr_split_tok(line, "=", &(bstr){0}, &value);
  326|      0|            if (value.len)
  ------------------
  |  Branch (326:17): [True: 0, False: 0]
  ------------------
  327|      0|                pl_add(p, value);
  328|      0|        }
  329|      0|        pl_free_line(p, line);
  330|      0|    }
  331|      0|    return 0;
  332|      0|}
demux_playlist.c:check_mimetype:
   84|    597|{
   85|    597|    if (s->mime_type) {
  ------------------
  |  Branch (85:9): [True: 0, False: 597]
  ------------------
   86|      0|        for (int n = 0; list && list[n]; n++) {
  ------------------
  |  Branch (86:25): [True: 0, False: 0]
  |  Branch (86:33): [True: 0, False: 0]
  ------------------
   87|      0|            if (strcasecmp(s->mime_type, list[n]) == 0)
  ------------------
  |  Branch (87:17): [True: 0, False: 0]
  ------------------
   88|      0|                return true;
   89|      0|        }
   90|      0|    }
   91|    597|    return false;
   92|    597|}
demux_playlist.c:parse_pls:
  366|     41|{
  367|     41|    return parse_ini_thing(p, "[playlist]", "File");
  368|     41|}
demux_playlist.c:parse_ini_thing:
  336|     82|{
  337|     82|    bstr line = {0};
  338|    164|    while (!line.len && !pl_eof(p))
  ------------------
  |  Branch (338:12): [True: 84, False: 80]
  |  Branch (338:25): [True: 82, False: 2]
  ------------------
  339|     82|        line = pl_get_line(p);
  340|     82|    if (bstrcasecmp0(line, header) != 0) {
  ------------------
  |  Branch (340:9): [True: 82, False: 0]
  ------------------
  341|     82|        pl_free_line(p, line);
  342|     82|        return -1;
  343|     82|    }
  344|      0|    if (p->probing) {
  ------------------
  |  Branch (344:9): [True: 0, False: 0]
  ------------------
  345|      0|        pl_free_line(p, line);
  346|      0|        return 0;
  347|      0|    }
  348|      0|    pl_free_line(p, line);
  349|      0|    while (!pl_eof(p)) {
  ------------------
  |  Branch (349:12): [True: 0, False: 0]
  ------------------
  350|      0|        line = pl_get_line(p);
  351|      0|        bstr key, value;
  352|      0|        if (bstr_split_tok(line, "=", &key, &value) &&
  ------------------
  |  Branch (352:13): [True: 0, False: 0]
  ------------------
  353|      0|            bstr_case_startswith(key, bstr0(entry)))
  ------------------
  |  Branch (353:13): [True: 0, False: 0]
  ------------------
  354|      0|        {
  355|      0|            value = bstr_strip(value);
  356|      0|            if (bstr_startswith0(value, "\"") && bstr_endswith0(value, "\""))
  ------------------
  |  Branch (356:17): [True: 0, False: 0]
  |  Branch (356:50): [True: 0, False: 0]
  ------------------
  357|      0|                value = bstr_splice(value, 1, -1);
  358|      0|            pl_add(p, value);
  359|      0|        }
  360|      0|        pl_free_line(p, line);
  361|      0|    }
  362|      0|    return 0;
  363|      0|}
demux_playlist.c:parse_url:
  371|     41|{
  372|     41|    return parse_ini_thing(p, "[InternetShortcut]", "URL");
  373|     41|}
demux_playlist.c:parse_txt:
  376|     41|{
  377|     41|    if (!p->force)
  ------------------
  |  Branch (377:9): [True: 41, False: 0]
  ------------------
  378|     41|        return -1;
  379|      0|    if (p->probing)
  ------------------
  |  Branch (379:9): [True: 0, False: 0]
  ------------------
  380|      0|        return 0;
  381|      0|    MP_WARN(p, "Reading plaintext playlist.\n");
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  382|      0|    while (!pl_eof(p)) {
  ------------------
  |  Branch (382:12): [True: 0, False: 0]
  ------------------
  383|      0|        bstr line = pl_get_line(p);
  384|      0|        if (line.len == 0)
  ------------------
  |  Branch (384:13): [True: 0, False: 0]
  ------------------
  385|      0|            continue;
  386|      0|        pl_add(p, line);
  387|      0|        pl_free_line(p, line);
  388|      0|    }
  389|      0|    return 0;
  390|      0|}
demux_playlist.c:parse_dir:
  538|    388|{
  539|    388|    int ret = -1;
  540|    388|    struct stream *stream = p->real_stream;
  541|    388|    enum autocreate_mode autocreate = AUTO_NONE;
  542|    388|    p->pl->playlist_dir = NULL;
  543|    388|    if (p->autocreate_playlist && p->real_stream->is_local_fs && !p->real_stream->is_directory) {
  ------------------
  |  Branch (543:9): [True: 0, False: 388]
  |  Branch (543:35): [True: 0, False: 0]
  |  Branch (543:66): [True: 0, False: 0]
  ------------------
  544|      0|        bstr ext = bstr_get_ext(bstr0(p->real_stream->url));
  545|      0|        switch (p->autocreate_playlist) {
  ------------------
  |  Branch (545:17): [True: 0, False: 0]
  ------------------
  546|      0|        case 1: // filter
  ------------------
  |  Branch (546:9): [True: 0, False: 0]
  ------------------
  547|      0|            autocreate = get_directory_filter(p);
  548|      0|            break;
  549|      0|        case 2: // same
  ------------------
  |  Branch (549:9): [True: 0, False: 0]
  ------------------
  550|      0|            if (str_in_list(ext, p->mp_opts->video_exts)) {
  ------------------
  |  Branch (550:17): [True: 0, False: 0]
  ------------------
  551|      0|                autocreate = AUTO_VIDEO;
  552|      0|            } else if (str_in_list(ext, p->mp_opts->audio_exts)) {
  ------------------
  |  Branch (552:24): [True: 0, False: 0]
  ------------------
  553|      0|                autocreate = AUTO_AUDIO;
  554|      0|            } else if (str_in_list(ext, p->mp_opts->image_exts)) {
  ------------------
  |  Branch (554:24): [True: 0, False: 0]
  ------------------
  555|      0|                autocreate = AUTO_IMAGE;
  556|      0|            } else if (str_in_list(ext, p->mp_opts->archive_exts)) {
  ------------------
  |  Branch (556:24): [True: 0, False: 0]
  ------------------
  557|      0|                autocreate = AUTO_ARCHIVE;
  558|      0|            } else if (str_in_list(ext, p->mp_opts->playlist_exts)) {
  ------------------
  |  Branch (558:24): [True: 0, False: 0]
  ------------------
  559|      0|                autocreate = AUTO_PLAYLIST;
  560|      0|            }
  561|      0|            break;
  562|      0|        }
  563|      0|        int flags = STREAM_READ_FILE_FLAGS_DEFAULT;
  ------------------
  |  |   60|      0|    (STREAM_ORIGIN_DIRECT | STREAM_READ | STREAM_LOCAL_FS_ONLY | STREAM_LESS_NOISE)
  |  |  ------------------
  |  |  |  |   47|      0|#define STREAM_ORIGIN_DIRECT      (1 << 2) // passed from cmdline or loadfile
  |  |  ------------------
  |  |                   (STREAM_ORIGIN_DIRECT | STREAM_READ | STREAM_LOCAL_FS_ONLY | STREAM_LESS_NOISE)
  |  |  ------------------
  |  |  |  |   41|      0|#define STREAM_READ               0
  |  |  ------------------
  |  |                   (STREAM_ORIGIN_DIRECT | STREAM_READ | STREAM_LOCAL_FS_ONLY | STREAM_LESS_NOISE)
  |  |  ------------------
  |  |  |  |   54|      0|#define STREAM_LOCAL_FS_ONLY      (1 << 5) // stream_file only, no URLs
  |  |  ------------------
  |  |                   (STREAM_ORIGIN_DIRECT | STREAM_READ | STREAM_LOCAL_FS_ONLY | STREAM_LESS_NOISE)
  |  |  ------------------
  |  |  |  |   55|      0|#define STREAM_LESS_NOISE         (1 << 6) // try to log errors only
  |  |  ------------------
  ------------------
  564|      0|        bstr dir = mp_dirname(p->real_stream->url);
  565|      0|        if (!dir.len)
  ------------------
  |  Branch (565:13): [True: 0, False: 0]
  ------------------
  566|      0|            autocreate = AUTO_NONE;
  567|      0|        if (autocreate != AUTO_NONE) {
  ------------------
  |  Branch (567:13): [True: 0, False: 0]
  ------------------
  568|      0|            stream = stream_create(bstrdup0(p, dir), flags, NULL, p->global);
  569|      0|            p->pl->playlist_dir = bstrdup0(p->pl, dir);
  570|      0|        }
  571|    388|    } else {
  572|    388|        autocreate = get_directory_filter(p);
  573|    388|    }
  574|    388|    if (!stream->is_directory)
  ------------------
  |  Branch (574:9): [True: 388, False: 0]
  ------------------
  575|    388|        goto done;
  576|      0|    if (p->probing) {
  ------------------
  |  Branch (576:9): [True: 0, False: 0]
  ------------------
  577|      0|        ret = 0;
  578|      0|        goto done;
  579|      0|    }
  580|       |
  581|      0|    char *path = mp_file_get_path(p, bstr0(stream->url));
  582|      0|    if (!path)
  ------------------
  |  Branch (582:9): [True: 0, False: 0]
  ------------------
  583|      0|        goto done;
  584|       |
  585|      0|    if (autocreate == AUTO_NONE)
  ------------------
  |  Branch (585:9): [True: 0, False: 0]
  ------------------
  586|      0|        goto done;
  587|       |
  588|      0|    struct stat dir_stack[MAX_DIR_STACK];
  589|       |
  590|      0|    if (p->opts->dir_mode == DIR_AUTO) {
  ------------------
  |  Branch (590:9): [True: 0, False: 0]
  ------------------
  591|      0|        struct MPOpts *opts = mp_get_config_group(NULL, p->global, &mp_opt_root);
  592|      0|        p->opts->dir_mode = opts->shuffle ? DIR_RECURSIVE : DIR_LAZY;
  ------------------
  |  Branch (592:29): [True: 0, False: 0]
  ------------------
  593|      0|        talloc_free(opts);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  594|      0|    }
  595|       |
  596|      0|    scan_dir(p, path, dir_stack, 0, autocreate);
  597|       |
  598|      0|    p->add_base = false;
  599|      0|    ret = p->pl->num_entries > 0 ? 0 : -1;
  ------------------
  |  Branch (599:11): [True: 0, False: 0]
  ------------------
  600|       |
  601|    388|done:
  602|    388|    if (stream != p->real_stream)
  ------------------
  |  Branch (602:9): [True: 0, False: 388]
  ------------------
  603|      0|        free_stream(stream);
  604|    388|    return ret;
  605|      0|}
demux_playlist.c:get_directory_filter:
  520|    388|{
  521|    388|    enum autocreate_mode autocreate = AUTO_NONE;
  522|    388|    if (!p->opts->directory_filter || !p->opts->directory_filter[0])
  ------------------
  |  Branch (522:9): [True: 0, False: 388]
  |  Branch (522:39): [True: 0, False: 388]
  ------------------
  523|      0|        autocreate = AUTO_ANY;
  524|    388|    if (str_in_list(bstr0("video"), p->opts->directory_filter))
  ------------------
  |  Branch (524:9): [True: 388, False: 0]
  ------------------
  525|    388|        autocreate |= AUTO_VIDEO;
  526|    388|    if (str_in_list(bstr0("audio"), p->opts->directory_filter))
  ------------------
  |  Branch (526:9): [True: 388, False: 0]
  ------------------
  527|    388|        autocreate |= AUTO_AUDIO;
  528|    388|    if (str_in_list(bstr0("image"), p->opts->directory_filter))
  ------------------
  |  Branch (528:9): [True: 388, False: 0]
  ------------------
  529|    388|        autocreate |= AUTO_IMAGE;
  530|    388|    if (str_in_list(bstr0("archive"), p->opts->directory_filter))
  ------------------
  |  Branch (530:9): [True: 388, False: 0]
  ------------------
  531|    388|        autocreate |= AUTO_ARCHIVE;
  532|    388|    if (str_in_list(bstr0("playlist"), p->opts->directory_filter))
  ------------------
  |  Branch (532:9): [True: 388, False: 0]
  ------------------
  533|    388|        autocreate |= AUTO_PLAYLIST;
  534|    388|    return autocreate;
  535|    388|}
demux_playlist.c:probe_pl:
  633|    433|{
  634|    433|    int64_t start = stream_tell(p->s);
  635|    433|    const struct pl_format *fmt = fmts;
  636|  1.02k|    while (fmt->name) {
  ------------------
  |  Branch (636:12): [True: 597, False: 429]
  ------------------
  637|    597|        stream_seek(p->s, start);
  638|    597|        if (check_mimetype(p->s, fmt->mime_types)) {
  ------------------
  |  Branch (638:13): [True: 0, False: 597]
  ------------------
  639|      0|            MP_VERBOSE(p, "forcing format by mime-type.\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  640|      0|            p->force = true;
  641|      0|            return fmt;
  642|      0|        }
  643|    597|        if (fmt->parse(p) >= 0)
  ------------------
  |  Branch (643:13): [True: 4, False: 593]
  ------------------
  644|      4|            return fmt;
  645|    593|        fmt++;
  646|    593|    }
  647|    429|    return NULL;
  648|    433|}

demux_raw.c:demux_rawaudio_open:
  146|    290|{
  147|    290|    struct demux_rawaudio_opts *opts =
  148|    290|        mp_get_config_group(demuxer, demuxer->global, &demux_rawaudio_conf);
  149|       |
  150|    290|    if (check != DEMUX_CHECK_REQUEST && check != DEMUX_CHECK_FORCE)
  ------------------
  |  Branch (150:9): [True: 290, False: 0]
  |  Branch (150:41): [True: 290, False: 0]
  ------------------
  151|    290|        return -1;
  152|       |
  153|      0|    if (opts->channels.num_chmaps != 1) {
  ------------------
  |  Branch (153:9): [True: 0, False: 0]
  ------------------
  154|      0|        MP_ERR(demuxer, "Invalid channels option given.\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  155|      0|        return -1;
  156|      0|    }
  157|       |
  158|      0|    struct sh_stream *sh = demux_alloc_sh_stream(STREAM_AUDIO);
  159|      0|    struct mp_codec_params *c = sh->codec;
  160|      0|    c->channels = opts->channels.chmaps[0];
  161|      0|    c->force_channels = true;
  162|      0|    c->samplerate = opts->samplerate;
  163|       |
  164|      0|    c->native_tb_num = 1;
  165|      0|    c->native_tb_den = c->samplerate;
  166|       |
  167|      0|    int f = opts->aformat;
  168|       |    // See PCM():               sign   float  bits    endian
  169|      0|    mp_set_pcm_codec(sh->codec, f & 1, f & 2, f >> 3, f & 4);
  170|      0|    int samplesize = ((f >> 3) + 7) / 8;
  171|       |
  172|      0|    demux_add_sh_stream(demuxer, sh);
  173|       |
  174|      0|    struct priv *p = talloc_ptrtype(demuxer, p);
  ------------------
  |  |   34|      0|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|      0|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  175|      0|    demuxer->priv = p;
  176|      0|    *p = (struct priv) {
  177|      0|        .sh = sh,
  178|      0|        .frame_size = samplesize * c->channels.num,
  179|      0|        .frame_rate = c->samplerate,
  180|      0|        .read_frames = c->samplerate / 8,
  181|      0|    };
  182|       |
  183|      0|    return generic_open(demuxer);
  184|      0|}
demux_raw.c:demux_rawvideo_open:
  187|    286|{
  188|    286|    struct demux_rawvideo_opts *opts =
  189|    286|        mp_get_config_group(demuxer, demuxer->global, &demux_rawvideo_conf);
  190|       |
  191|    286|    if (check != DEMUX_CHECK_REQUEST && check != DEMUX_CHECK_FORCE)
  ------------------
  |  Branch (191:9): [True: 286, False: 0]
  |  Branch (191:41): [True: 286, False: 0]
  ------------------
  192|    286|        return -1;
  193|       |
  194|      0|    int width = opts->width;
  195|      0|    int height = opts->height;
  196|       |
  197|      0|    if (!width || !height) {
  ------------------
  |  Branch (197:9): [True: 0, False: 0]
  |  Branch (197:19): [True: 0, False: 0]
  ------------------
  198|      0|        MP_ERR(demuxer, "rawvideo: width or height not specified!\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  199|      0|        return -1;
  200|      0|    }
  201|       |
  202|      0|    const char *decoder = "rawvideo";
  203|      0|    int imgfmt = opts->vformat;
  204|      0|    int imgsize = opts->imgsize;
  205|      0|    int mp_imgfmt = 0;
  206|      0|    if (opts->mp_format && !IMGFMT_IS_HWACCEL(opts->mp_format)) {
  ------------------
  |  |  327|      0|#define IMGFMT_IS_HWACCEL(fmt) (!!(mp_imgfmt_get_desc(fmt).flags & MP_IMGFLAG_HWACCEL))
  |  |  ------------------
  |  |  |  |   70|      0|#define MP_IMGFLAG_HWACCEL      MP_IMGFLAG_TYPE_HW
  |  |  |  |  ------------------
  |  |  |  |  |  |   65|      0|#define MP_IMGFLAG_TYPE_HW      (8 << 10)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (206:9): [True: 0, False: 0]
  |  Branch (206:28): [True: 0, False: 0]
  ------------------
  207|      0|        mp_imgfmt = opts->mp_format;
  208|      0|        if (!imgsize) {
  ------------------
  |  Branch (208:13): [True: 0, False: 0]
  ------------------
  209|      0|            struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(opts->mp_format);
  210|      0|            for (int p = 0; p < desc.num_planes; p++) {
  ------------------
  |  Branch (210:29): [True: 0, False: 0]
  ------------------
  211|      0|                imgsize += ((width >> desc.xs[p]) * (height >> desc.ys[p]) *
  212|      0|                            desc.bpp[p] + 7) / 8;
  213|      0|            }
  214|      0|        }
  215|      0|    } else if (opts->codec && opts->codec[0])
  ------------------
  |  Branch (215:16): [True: 0, False: 0]
  |  Branch (215:31): [True: 0, False: 0]
  ------------------
  216|      0|        decoder = talloc_strdup(demuxer, opts->codec);
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  217|       |
  218|      0|    if (!imgsize) {
  ------------------
  |  Branch (218:9): [True: 0, False: 0]
  ------------------
  219|      0|        int bpp = 0;
  220|      0|        switch (imgfmt) {
  ------------------
  |  Branch (220:17): [True: 0, False: 0]
  ------------------
  221|      0|        case MKTAG('Y', 'V', '1', '2'):
  ------------------
  |  Branch (221:9): [True: 0, False: 0]
  ------------------
  222|      0|        case MKTAG('I', '4', '2', '0'):
  ------------------
  |  Branch (222:9): [True: 0, False: 0]
  ------------------
  223|      0|        case MKTAG('I', 'Y', 'U', 'V'):
  ------------------
  |  Branch (223:9): [True: 0, False: 0]
  ------------------
  224|      0|            bpp = 12;
  225|      0|            break;
  226|      0|        case MKTAG('U', 'Y', 'V', 'Y'):
  ------------------
  |  Branch (226:9): [True: 0, False: 0]
  ------------------
  227|      0|        case MKTAG('Y', 'U', 'Y', '2'):
  ------------------
  |  Branch (227:9): [True: 0, False: 0]
  ------------------
  228|      0|            bpp = 16;
  229|      0|            break;
  230|      0|        }
  231|      0|        if (!bpp) {
  ------------------
  |  Branch (231:13): [True: 0, False: 0]
  ------------------
  232|      0|            MP_ERR(demuxer, "rawvideo: img size not specified and unknown format!\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  233|      0|            return -1;
  234|      0|        }
  235|      0|        imgsize = width * height * bpp / 8;
  236|      0|    }
  237|       |
  238|      0|    struct sh_stream *sh = demux_alloc_sh_stream(STREAM_VIDEO);
  239|      0|    struct mp_codec_params *c = sh->codec;
  240|      0|    c->codec = decoder;
  241|      0|    c->codec_tag = imgfmt;
  242|      0|    c->fps = opts->fps;
  243|      0|    c->reliable_fps = true;
  244|      0|    c->disp_w = width;
  245|      0|    c->disp_h = height;
  246|      0|    if (mp_imgfmt) {
  ------------------
  |  Branch (246:9): [True: 0, False: 0]
  ------------------
  247|      0|        c->lav_codecpar = avcodec_parameters_alloc();
  248|      0|        MP_HANDLE_OOM(c->lav_codecpar);
  ------------------
  |  |  176|      0|#define MP_HANDLE_OOM(x) do {   \
  |  |  177|      0|        void *oom_p_ = (x);     \
  |  |  178|      0|        if (!oom_p_)            \
  |  |  ------------------
  |  |  |  Branch (178:13): [True: 0, False: 0]
  |  |  ------------------
  |  |  179|      0|            abort();            \
  |  |  180|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (180:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  249|      0|        c->lav_codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
  250|      0|        c->lav_codecpar->codec_id = mp_codec_to_av_codec_id(decoder);
  251|      0|        c->lav_codecpar->format = imgfmt2pixfmt(mp_imgfmt);
  252|      0|        c->lav_codecpar->width = width;
  253|      0|        c->lav_codecpar->height = height;
  254|      0|    }
  255|      0|    demux_add_sh_stream(demuxer, sh);
  256|       |
  257|      0|    struct priv *p = talloc_ptrtype(demuxer, p);
  ------------------
  |  |   34|      0|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|      0|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  258|      0|    demuxer->priv = p;
  259|      0|    *p = (struct priv) {
  260|      0|        .sh = sh,
  261|      0|        .frame_size = imgsize,
  262|      0|        .frame_rate = c->fps,
  263|      0|        .read_frames = 1,
  264|      0|    };
  265|       |
  266|      0|    return generic_open(demuxer);
  267|      0|}

demux_timeline.c:d_open:
  637|     18|{
  638|     18|    struct priv *p = demuxer->priv = talloc_zero(demuxer, struct priv);
  ------------------
  |  |   27|     18|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|     18|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     18|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  639|     18|    p->tl = demuxer->params ? demuxer->params->timeline : NULL;
  ------------------
  |  Branch (639:13): [True: 18, False: 0]
  ------------------
  640|     18|    if (!p->tl || p->tl->num_pars < 1)
  ------------------
  |  Branch (640:9): [True: 0, False: 18]
  |  Branch (640:19): [True: 0, False: 18]
  ------------------
  641|      0|        return -1;
  642|       |
  643|     18|    demuxer->chapters = p->tl->chapters;
  644|     18|    demuxer->num_chapters = p->tl->num_chapters;
  645|       |
  646|     18|    struct demuxer *meta = p->tl->meta;
  647|     18|    if (meta) {
  ------------------
  |  Branch (647:9): [True: 18, False: 0]
  ------------------
  648|     18|        demuxer->metadata = meta->metadata;
  649|     18|        demuxer->attachments = meta->attachments;
  650|     18|        demuxer->num_attachments = meta->num_attachments;
  651|     18|        demuxer->editions = meta->editions;
  652|     18|        demuxer->num_editions = meta->num_editions;
  653|     18|        demuxer->edition = meta->edition;
  654|     18|    }
  655|       |
  656|     36|    for (int n = 0; n < p->tl->num_pars; n++) {
  ------------------
  |  Branch (656:21): [True: 18, False: 18]
  ------------------
  657|     18|        if (!add_tl(demuxer, p->tl->pars[n]))
  ------------------
  |  Branch (657:13): [True: 0, False: 18]
  ------------------
  658|      0|            return -1;
  659|     18|    }
  660|       |
  661|     18|    if (!p->num_sources)
  ------------------
  |  Branch (661:9): [True: 0, False: 18]
  ------------------
  662|      0|        return -1;
  663|       |
  664|     18|    demuxer->is_network |= p->tl->is_network;
  665|     18|    demuxer->is_streaming |= p->tl->is_streaming;
  666|       |
  667|     18|    demuxer->duration = p->duration;
  668|       |
  669|     18|    print_timeline(demuxer);
  670|       |
  671|     18|    demuxer->seekable = true;
  672|     18|    demuxer->partially_seekable = false;
  673|       |
  674|     18|    const char *format_name = "unknown";
  675|     18|    if (meta)
  ------------------
  |  Branch (675:9): [True: 18, False: 0]
  ------------------
  676|     18|        format_name = meta->filetype ? meta->filetype : meta->desc->name;
  ------------------
  |  Branch (676:23): [True: 6, False: 12]
  ------------------
  677|     18|    demuxer->filetype = talloc_asprintf(p, "%s/%s", p->tl->format, format_name);
  ------------------
  |  |   52|     18|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|     18|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  678|       |
  679|     18|    reselect_streams(demuxer);
  680|       |
  681|     18|    p->owns_tl = true;
  682|     18|    return 0;
  683|     18|}
demux_timeline.c:add_tl:
  541|     18|{
  542|     18|    struct priv *p = demuxer->priv;
  543|       |
  544|     18|    struct virtual_source *src = talloc_ptrtype(p, src);
  ------------------
  |  |   34|     18|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|     18|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     18|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  545|     18|    *src = (struct virtual_source){
  546|     18|        .tl = tl,
  547|     18|        .dash = tl->dash,
  548|     18|        .delay_open = tl->delay_open,
  549|     18|        .no_clip = tl->no_clip || tl->dash,
  ------------------
  |  Branch (549:20): [True: 0, False: 18]
  |  Branch (549:35): [True: 0, False: 18]
  ------------------
  550|     18|        .dts = MP_NOPTS_VALUE,
  ------------------
  |  |   38|     18|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  551|     18|    };
  552|       |
  553|     18|    if (!tl->num_parts)
  ------------------
  |  Branch (553:9): [True: 0, False: 18]
  ------------------
  554|      0|        return false;
  555|       |
  556|     18|    MP_TARRAY_APPEND(p, p->sources, p->num_sources, src);
  ------------------
  |  |  105|     18|    do {                                            \
  |  |  106|     18|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|     18|    do {                                            \
  |  |  |  |   97|     18|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|     18|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|     18|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|     18|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 18, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|     18|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|     18|    do {                                                        \
  |  |  |  |  |  |   89|     18|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|     18|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|     18|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|     18|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|     18|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|     18|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|     18|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|     18|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|     18|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|     18|        (idxvar)++;                                 \
  |  |  109|     18|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  557|       |
  558|     18|    p->duration = MPMAX(p->duration, tl->parts[tl->num_parts - 1].end);
  ------------------
  |  |   43|     18|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 18]
  |  |  ------------------
  ------------------
  559|       |
  560|     18|    struct demuxer *meta = tl->track_layout;
  561|       |
  562|       |    // delay_open streams normally have meta==NULL, and 1 virtual stream
  563|     18|    int num_streams = 0;
  564|     18|    if (tl->delay_open) {
  ------------------
  |  Branch (564:9): [True: 0, False: 18]
  ------------------
  565|      0|        num_streams = tl->num_sh_meta;
  566|     18|    } else if (meta) {
  ------------------
  |  Branch (566:16): [True: 18, False: 0]
  ------------------
  567|     18|        num_streams = demux_get_num_stream(meta);
  568|     18|    }
  569|     24|    for (int n = 0; n < num_streams; n++) {
  ------------------
  |  Branch (569:21): [True: 6, False: 18]
  ------------------
  570|      6|        struct sh_stream *new = NULL;
  571|       |
  572|      6|        if (tl->delay_open) {
  ------------------
  |  Branch (572:13): [True: 0, False: 6]
  ------------------
  573|      0|            struct sh_stream *tsh = tl->sh_meta[n];
  574|      0|            new = demux_alloc_sh_stream(tsh->type);
  575|      0|            new->codec = tsh->codec;
  576|      0|            apply_meta(new, tsh);
  577|      0|            demuxer->is_network = true;
  578|      0|            demuxer->is_streaming = true;
  579|      6|        } else {
  580|      6|            struct sh_stream *sh = demux_get_stream(meta, n);
  581|      6|            new = demux_alloc_sh_stream(sh->type);
  582|      6|            apply_meta(new, sh);
  583|      6|            new->codec = sh->codec;
  584|      6|            struct sh_stream *tsh = find_matching_meta(tl, n);
  585|      6|            if (tsh)
  ------------------
  |  Branch (585:17): [True: 0, False: 6]
  ------------------
  586|      0|                apply_meta(new, tsh);
  587|      6|        }
  588|       |
  589|      6|        demux_add_sh_stream(demuxer, new);
  590|      6|        struct virtual_stream *vs = talloc_ptrtype(p, vs);
  ------------------
  |  |   34|      6|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|      6|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      6|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  591|      6|        *vs = (struct virtual_stream){
  592|      6|            .src = src,
  593|      6|            .sh = new,
  594|      6|        };
  595|      6|        MP_TARRAY_APPEND(p, p->streams, p->num_streams, vs);
  ------------------
  |  |  105|      6|    do {                                            \
  |  |  106|      6|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      6|    do {                                            \
  |  |  |  |   97|      6|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      6|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      6|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      6|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 6, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      6|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      6|    do {                                                        \
  |  |  |  |  |  |   89|      6|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      6|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      6|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      6|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      6|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      6|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      6|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      6|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      6|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      6|        (idxvar)++;                                 \
  |  |  109|      6|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  596|      6|        mp_assert(demux_get_stream(demuxer, p->num_streams - 1) == new);
  ------------------
  |  |   41|      6|#define mp_assert assert
  ------------------
  597|      6|        MP_TARRAY_APPEND(src, src->streams, src->num_streams, vs);
  ------------------
  |  |  105|      6|    do {                                            \
  |  |  106|      6|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      6|    do {                                            \
  |  |  |  |   97|      6|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      6|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      6|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      6|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 6, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      6|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      6|    do {                                                        \
  |  |  |  |  |  |   89|      6|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      6|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      6|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      6|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      6|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      6|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      6|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      6|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      6|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      6|        (idxvar)++;                                 \
  |  |  109|      6|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  598|      6|    }
  599|       |
  600|     70|    for (int n = 0; n < tl->num_parts; n++) {
  ------------------
  |  Branch (600:21): [True: 52, False: 18]
  ------------------
  601|     52|        struct timeline_part *part = &tl->parts[n];
  602|       |
  603|       |        // demux_timeline already does caching, doing it for the sub-demuxers
  604|       |        // would be pointless and wasteful.
  605|     52|        if (part->source) {
  ------------------
  |  Branch (605:13): [True: 52, False: 0]
  ------------------
  606|     52|            demuxer->is_network |= part->source->is_network;
  607|     52|            demuxer->is_streaming |= part->source->is_streaming;
  608|     52|        }
  609|       |
  610|     52|        if (!part->source)
  ------------------
  |  Branch (610:13): [True: 0, False: 52]
  ------------------
  611|     52|            mp_assert(tl->dash || tl->delay_open);
  ------------------
  |  |   41|     52|#define mp_assert assert
  ------------------
  612|       |
  613|     52|        struct segment *seg = talloc_ptrtype(src, seg);
  ------------------
  |  |   34|     52|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|     52|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     52|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  614|     52|        *seg = (struct segment){
  615|     52|            .d = part->source,
  616|     52|            .url = part->source ? part->source->filename : part->url,
  ------------------
  |  Branch (616:20): [True: 52, False: 0]
  ------------------
  617|     52|            .lazy = !part->source,
  618|     52|            .d_start = part->source_start,
  619|     52|            .start = part->start,
  620|     52|            .end = part->end,
  621|     52|        };
  622|       |
  623|     52|        associate_streams(demuxer, src, seg);
  624|       |
  625|     52|        seg->index = n;
  626|     52|        MP_TARRAY_APPEND(src, src->segments, src->num_segments, seg);
  ------------------
  |  |  105|     52|    do {                                            \
  |  |  106|     52|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|     52|    do {                                            \
  |  |  |  |   97|     52|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|     52|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|     52|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|     52|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 28, False: 24]
  |  |  |  |  ------------------
  |  |  |  |   99|     52|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|     28|    do {                                                        \
  |  |  |  |  |  |   89|     28|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|     28|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|     28|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|     28|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|     28|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|     28|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|     28|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|     52|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|     52|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|     52|        (idxvar)++;                                 \
  |  |  109|     52|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  627|     52|    }
  628|       |
  629|     18|    if (tl->track_layout) {
  ------------------
  |  Branch (629:9): [True: 18, False: 0]
  ------------------
  630|     18|        demuxer->is_network |= tl->track_layout->is_network;
  631|     18|        demuxer->is_streaming |= tl->track_layout->is_streaming;
  632|     18|    }
  633|     18|    return true;
  634|     18|}
demux_timeline.c:apply_meta:
  512|      6|{
  513|      6|    if (src->demuxer_id >= 0)
  ------------------
  |  Branch (513:9): [True: 0, False: 6]
  ------------------
  514|      0|        dst->demuxer_id = src->demuxer_id;
  515|      6|    if (src->title)
  ------------------
  |  Branch (515:9): [True: 0, False: 6]
  ------------------
  516|      0|        dst->title = src->title;
  517|      6|    if (src->lang)
  ------------------
  |  Branch (517:9): [True: 0, False: 6]
  ------------------
  518|      0|        dst->lang = src->lang;
  519|      6|    dst->default_track = src->default_track;
  520|      6|    dst->forced_track = src->forced_track;
  521|      6|    if (src->hls_bitrate)
  ------------------
  |  Branch (521:9): [True: 0, False: 6]
  ------------------
  522|      0|        dst->hls_bitrate = src->hls_bitrate;
  523|      6|    dst->missing_timestamps = src->missing_timestamps;
  524|      6|    if (src->attached_picture)
  ------------------
  |  Branch (524:9): [True: 0, False: 6]
  ------------------
  525|      0|        dst->attached_picture = src->attached_picture;
  526|      6|    dst->image = src->image;
  527|      6|}
demux_timeline.c:find_matching_meta:
  531|      6|{
  532|      6|    for (int n = 0; n < tl->num_sh_meta; n++) {
  ------------------
  |  Branch (532:21): [True: 0, False: 6]
  ------------------
  533|      0|        struct sh_stream *sh = tl->sh_meta[n];
  534|      0|        if (sh->index == index || sh->index < 0)
  ------------------
  |  Branch (534:13): [True: 0, False: 0]
  |  Branch (534:35): [True: 0, False: 0]
  ------------------
  535|      0|            return sh;
  536|      0|    }
  537|      6|    return NULL;
  538|      6|}
demux_timeline.c:associate_streams:
  111|     52|{
  112|     52|    if (!seg->d || seg->stream_map)
  ------------------
  |  Branch (112:9): [True: 0, False: 52]
  |  Branch (112:20): [True: 0, False: 52]
  ------------------
  113|      0|        return;
  114|       |
  115|     52|    int num_streams = demux_get_num_stream(seg->d);
  116|     66|    for (int n = 0; n < num_streams; n++) {
  ------------------
  |  Branch (116:21): [True: 14, False: 52]
  ------------------
  117|     14|        struct sh_stream *sh = demux_get_stream(seg->d, n);
  118|     14|        struct virtual_stream *other = NULL;
  119|       |
  120|     28|        for (int i = 0; i < src->num_streams; i++) {
  ------------------
  |  Branch (120:25): [True: 14, False: 14]
  ------------------
  121|     14|            struct virtual_stream *vs = src->streams[i];
  122|       |
  123|       |            // The stream must always have the same media type. Also, a stream
  124|       |            // can't be assigned multiple times.
  125|     14|            if (sh->type != vs->sh->type || target_stream_used(seg, vs))
  ------------------
  |  Branch (125:17): [True: 1, False: 13]
  |  Branch (125:45): [True: 0, False: 13]
  ------------------
  126|      1|                continue;
  127|       |
  128|       |            // By default pick the first matching stream.
  129|     13|            if (!other)
  ------------------
  |  Branch (129:17): [True: 13, False: 0]
  ------------------
  130|     13|                other = vs;
  131|       |
  132|       |            // Matching by demuxer ID is supposedly useful and preferable for
  133|       |            // ordered chapters.
  134|     13|            if (sh->demuxer_id >= 0 && sh->demuxer_id == vs->sh->demuxer_id)
  ------------------
  |  Branch (134:17): [True: 0, False: 13]
  |  Branch (134:40): [True: 0, False: 0]
  ------------------
  135|      0|                other = vs;
  136|     13|        }
  137|       |
  138|     14|        if (!other) {
  ------------------
  |  Branch (138:13): [True: 1, False: 13]
  ------------------
  139|      1|            MP_WARN(demuxer, "Source stream %d (%s) unused and hidden.\n",
  ------------------
  |  |   86|      1|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      1|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  140|      1|                    n, stream_type_name(sh->type));
  141|      1|        }
  142|       |
  143|     14|        MP_TARRAY_APPEND(seg, seg->stream_map, seg->num_stream_map, other);
  ------------------
  |  |  105|     14|    do {                                            \
  |  |  106|     14|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|     14|    do {                                            \
  |  |  |  |   97|     14|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|     14|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|     14|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|     14|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 14, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|     14|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|     14|    do {                                                        \
  |  |  |  |  |  |   89|     14|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|     14|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|     14|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|     14|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|     14|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|     14|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|     14|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|     14|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|     14|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|     14|        (idxvar)++;                                 \
  |  |  109|     14|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  144|     14|    }
  145|     52|}
demux_timeline.c:target_stream_used:
   99|     13|{
  100|     13|    for (int n = 0; n < seg->num_stream_map; n++) {
  ------------------
  |  Branch (100:21): [True: 0, False: 13]
  ------------------
  101|      0|        if (seg->stream_map[n] == vs)
  ------------------
  |  Branch (101:13): [True: 0, False: 0]
  ------------------
  102|      0|            return true;
  103|      0|    }
  104|     13|    return false;
  105|     13|}
demux_timeline.c:print_timeline:
  472|     18|{
  473|     18|    struct priv *p = demuxer->priv;
  474|       |
  475|     18|    MP_VERBOSE(demuxer, "Timeline segments:\n");
  ------------------
  |  |   88|     18|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     18|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  476|     36|    for (int x = 0; x < p->num_sources; x++) {
  ------------------
  |  Branch (476:21): [True: 18, False: 18]
  ------------------
  477|     18|        struct virtual_source *src = p->sources[x];
  478|       |
  479|     18|        if (x >= 1)
  ------------------
  |  Branch (479:13): [True: 0, False: 18]
  ------------------
  480|     18|            MP_VERBOSE(demuxer, " --- new parallel stream ---\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  481|       |
  482|     70|        for (int n = 0; n < src->num_segments; n++) {
  ------------------
  |  Branch (482:25): [True: 52, False: 18]
  ------------------
  483|     52|            struct segment *seg = src->segments[n];
  484|     52|            int src_num = n;
  485|    147|            for (int i = 0; i < n; i++) {
  ------------------
  |  Branch (485:29): [True: 99, False: 48]
  ------------------
  486|     99|                if (seg->d && src->segments[i]->d == seg->d) {
  ------------------
  |  Branch (486:21): [True: 99, False: 0]
  |  Branch (486:31): [True: 4, False: 95]
  ------------------
  487|      4|                    src_num = i;
  488|      4|                    break;
  489|      4|                }
  490|     99|            }
  491|     52|            MP_VERBOSE(demuxer, " %2d: %12f - %12f [%12f] (",
  ------------------
  |  |   88|     52|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     52|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  492|     52|                       n, seg->start, seg->end, seg->d_start);
  493|     66|            for (int i = 0; i < seg->num_stream_map; i++) {
  ------------------
  |  Branch (493:29): [True: 14, False: 52]
  ------------------
  494|     14|                struct virtual_stream *vs = seg->stream_map[i];
  495|     14|                MP_VERBOSE(demuxer, "%s%d", i ? " " : "",
  ------------------
  |  |   88|     14|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     56|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 0, False: 14]
  |  |  |  |  |  Branch (82:57): [True: 13, False: 1]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  496|     14|                           vs ? vs->sh->index : -1);
  497|     14|            }
  498|     52|            MP_VERBOSE(demuxer, ")\n  source %d:'%s'\n", src_num, seg->url);
  ------------------
  |  |   88|     52|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     52|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  499|     52|        }
  500|       |
  501|     18|        if (src->dash)
  ------------------
  |  Branch (501:13): [True: 0, False: 18]
  ------------------
  502|     18|            MP_VERBOSE(demuxer, " (Using pseudo-DASH mode.)\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  503|     18|    }
  504|     18|    MP_VERBOSE(demuxer, "Total duration: %f\n", p->duration);
  ------------------
  |  |   88|     18|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     18|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  505|     18|}
demux_timeline.c:reselect_streams:
  148|     18|{
  149|     18|    struct priv *p = demuxer->priv;
  150|       |
  151|     24|    for (int n = 0; n < p->num_streams; n++) {
  ------------------
  |  Branch (151:21): [True: 6, False: 18]
  ------------------
  152|      6|        struct virtual_stream *vs = p->streams[n];
  153|      6|        vs->selected = demux_stream_is_selected(vs->sh);
  154|      6|    }
  155|       |
  156|     36|    for (int x = 0; x < p->num_sources; x++) {
  ------------------
  |  Branch (156:21): [True: 18, False: 18]
  ------------------
  157|     18|        struct virtual_source *src = p->sources[x];
  158|       |
  159|     70|        for (int n = 0; n < src->num_segments; n++) {
  ------------------
  |  Branch (159:25): [True: 52, False: 18]
  ------------------
  160|     52|            struct segment *seg = src->segments[n];
  161|       |
  162|     52|            if (!seg->d)
  ------------------
  |  Branch (162:17): [True: 0, False: 52]
  ------------------
  163|      0|                continue;
  164|       |
  165|     66|            for (int i = 0; i < seg->num_stream_map; i++) {
  ------------------
  |  Branch (165:29): [True: 14, False: 52]
  ------------------
  166|     14|                bool selected =
  167|     14|                    seg->stream_map[i] && seg->stream_map[i]->selected;
  ------------------
  |  Branch (167:21): [True: 13, False: 1]
  |  Branch (167:43): [True: 0, False: 13]
  ------------------
  168|       |
  169|       |                // This stops demuxer readahead for inactive segments.
  170|     14|                if (!src->current || seg->d != src->current->d)
  ------------------
  |  Branch (170:21): [True: 14, False: 0]
  |  Branch (170:38): [True: 0, False: 0]
  ------------------
  171|     14|                    selected = false;
  172|     14|                struct sh_stream *sh = demux_get_stream(seg->d, i);
  173|     14|                demuxer_select_track(seg->d, sh, MP_NOPTS_VALUE, selected);
  ------------------
  |  |   38|     14|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  174|       |
  175|     14|                update_slave_stats(demuxer, seg->d);
  176|     14|            }
  177|     52|        }
  178|       |
  179|     18|        bool was_selected = src->any_selected;
  180|     18|        src->any_selected = false;
  181|       |
  182|     24|        for (int n = 0; n < src->num_streams; n++)
  ------------------
  |  Branch (182:25): [True: 6, False: 18]
  ------------------
  183|      6|            src->any_selected |= src->streams[n]->selected;
  184|       |
  185|     18|        if (!was_selected && src->any_selected) {
  ------------------
  |  Branch (185:13): [True: 18, False: 0]
  |  Branch (185:30): [True: 0, False: 18]
  ------------------
  186|      0|            src->eof_reached = false;
  187|      0|            src->dts = MP_NOPTS_VALUE;
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  188|      0|            TA_FREEP(&src->next);
  ------------------
  |  |   81|      0|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|      0|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  189|      0|        }
  190|     18|    }
  191|     18|}
demux_timeline.c:update_slave_stats:
   94|     14|{
   95|     14|    demux_report_unbuffered_read_bytes(demuxer, demux_get_bytes_read_hack(slave));
   96|     14|}
demux_timeline.c:d_close:
  686|     18|{
  687|     18|    struct priv *p = demuxer->priv;
  688|       |
  689|     36|    for (int x = 0; x < p->num_sources; x++) {
  ------------------
  |  Branch (689:21): [True: 18, False: 18]
  ------------------
  690|     18|        struct virtual_source *src = p->sources[x];
  691|       |
  692|     18|        src->current = NULL;
  693|     18|        TA_FREEP(&src->next);
  ------------------
  |  |   81|     18|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|     18|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  694|     18|        close_lazy_segments(demuxer, src);
  695|     18|    }
  696|       |
  697|     18|    if (p->owns_tl) {
  ------------------
  |  Branch (697:9): [True: 18, False: 0]
  ------------------
  698|     18|        struct demuxer *master = p->tl->demuxer;
  699|     18|        timeline_destroy(p->tl);
  700|     18|        demux_free(master);
  701|     18|    }
  702|     18|}
demux_timeline.c:close_lazy_segments:
  195|     18|{
  196|       |    // unload previous segment
  197|     70|    for (int n = 0; n < src->num_segments; n++) {
  ------------------
  |  Branch (197:21): [True: 52, False: 18]
  ------------------
  198|     52|        struct segment *seg = src->segments[n];
  199|     52|        if (seg != src->current && seg->d && seg->lazy) {
  ------------------
  |  Branch (199:13): [True: 52, False: 0]
  |  Branch (199:36): [True: 52, False: 0]
  |  Branch (199:46): [True: 0, False: 52]
  ------------------
  200|      0|            TA_FREEP(&src->next); // might depend on one of the sub-demuxers
  ------------------
  |  |   81|      0|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|      0|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  201|      0|            demux_free(seg->d);
  202|      0|            seg->d = NULL;
  203|      0|        }
  204|     52|    }
  205|     18|}

ebml_read_id:
   62|    276|{
   63|    276|    int i, len_mask = 0x80;
   64|    276|    uint32_t id;
   65|       |
   66|    618|    for (i = 0, id = stream_read_char(s); i < 4 && !(id & len_mask); i++)
  ------------------
  |  Branch (66:43): [True: 612, False: 6]
  |  Branch (66:52): [True: 342, False: 270]
  ------------------
   67|    342|        len_mask >>= 1;
   68|    276|    if (i >= 4)
  ------------------
  |  Branch (68:9): [True: 6, False: 270]
  ------------------
   69|      6|        return EBML_ID_INVALID;
  ------------------
  |  |   68|      6|#define EBML_ID_INVALID 0xffffffff
  ------------------
   70|    588|    while (i--)
  ------------------
  |  Branch (70:12): [True: 318, False: 270]
  ------------------
   71|    318|        id = (id << 8) | stream_read_char(s);
   72|    270|    return id;
   73|    276|}

demux_packet_pool_init:
   50|  17.0k|{
   51|  17.0k|    struct demux_packet_pool *pool = talloc(global, struct demux_packet_pool);
  ------------------
  |  |   26|  17.0k|#define talloc                          ta_xnew
  |  |  ------------------
  |  |  |  |  133|  17.0k|#define ta_xnew(...)                    ta_oom_g(ta_new(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   52|  17.0k|    talloc_set_destructor(pool, uninit);
  ------------------
  |  |   41|  17.0k|#define talloc_set_destructor           ta_set_destructor
  ------------------
   53|  17.0k|    mp_mutex_init(&pool->lock);
   54|  17.0k|    pool->packets = NULL;
   55|       |
   56|  17.0k|    mp_assert(!global->packet_pool);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
   57|  17.0k|    global->packet_pool = pool;
   58|  17.0k|}
demux_packet_pool_get:
   61|  9.56k|{
   62|       |    // Currently all clients use the same packet pool. There is no additional
   63|       |    // state for each client, may be extended in the future.
   64|  9.56k|    return global->packet_pool;
   65|  9.56k|}
demux_packet_pool_clear:
   68|  17.0k|{
   69|  17.0k|    mp_mutex_lock(&pool->lock);
  ------------------
  |  |  131|  17.0k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
   70|  17.0k|    struct demux_packet *dp = pool->packets;
   71|  17.0k|    pool->packets = NULL;
   72|  17.0k|    mp_mutex_unlock(&pool->lock);
  ------------------
  |  |  133|  17.0k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
   73|  17.0k|    free_demux_packets(dp);
   74|  17.0k|}
demux_packet_pool_prepend:
   87|    243|{
   88|    243|    if (!head)
  ------------------
  |  Branch (88:9): [True: 243, False: 0]
  ------------------
   89|    243|        return;
   90|      0|    mp_assert(tail);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
   91|      0|    mp_assert(head != tail ? !!head->next : !head->next);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
   92|       |
   93|      0|    mp_mutex_lock(&pool->lock);
  ------------------
  |  |  131|      0|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
   94|      0|    tail->next = pool->packets;
   95|      0|    pool->packets = head;
   96|       |#if HAVE_DISABLE_PACKET_POOL
   97|       |    struct demux_packet *dp = pool->packets;
   98|       |    pool->packets = NULL;
   99|       |#endif
  100|      0|    mp_mutex_unlock(&pool->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  101|       |
  102|       |#if HAVE_DISABLE_PACKET_POOL
  103|       |    free_demux_packets(dp);
  104|       |#endif
  105|      0|}
packet_pool.c:uninit:
   34|  17.0k|{
   35|  17.0k|    struct demux_packet_pool *pool = p;
   36|  17.0k|    demux_packet_pool_clear(pool);
   37|  17.0k|    mp_mutex_destroy(&pool->lock);
  ------------------
  |  |  130|  17.0k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
   38|  17.0k|}
packet_pool.c:free_demux_packets:
   41|  17.0k|{
   42|  17.0k|    while (dp) {
  ------------------
  |  Branch (42:12): [True: 0, False: 17.0k]
  ------------------
   43|      0|        struct demux_packet *next = dp->next;
   44|      0|        free_demux_packet(dp);
   45|      0|        dp = next;
   46|      0|    }
   47|  17.0k|}

timeline_load:
    9|    321|{
   10|    321|    if (!demuxer->desc->load_timeline)
  ------------------
  |  Branch (10:9): [True: 191, False: 130]
  ------------------
   11|    191|        return NULL;
   12|       |
   13|    130|    struct timeline *tl = talloc_ptrtype(NULL, tl);
  ------------------
  |  |   34|    130|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|    130|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    130|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   14|    130|    *tl = (struct timeline){
   15|    130|        .global = global,
   16|    130|        .log = log,
   17|    130|        .cancel = demuxer->cancel,
   18|    130|        .demuxer = demuxer,
   19|    130|        .format = "unknown",
   20|    130|        .stream_origin = demuxer->stream_origin,
   21|    130|    };
   22|       |
   23|    130|    demuxer->desc->load_timeline(tl);
   24|       |
   25|    130|    if (tl->num_pars)
  ------------------
  |  Branch (25:9): [True: 21, False: 109]
  ------------------
   26|     21|        return tl;
   27|    109|    timeline_destroy(tl);
   28|    109|    return NULL;
   29|    130|}
timeline_destroy:
   32|    130|{
   33|    130|    if (!tl)
  ------------------
  |  Branch (33:9): [True: 0, False: 130]
  ------------------
   34|      0|        return;
   35|    272|    for (int n = 0; n < tl->num_sources; n++) {
  ------------------
  |  Branch (35:21): [True: 142, False: 130]
  ------------------
   36|    142|        struct demuxer *d = tl->sources[n];
   37|    142|        if (d != tl->demuxer)
  ------------------
  |  Branch (37:13): [True: 142, False: 0]
  ------------------
   38|    142|            demux_free(d);
   39|    142|    }
   40|    130|    talloc_free(tl);
  ------------------
  |  |   47|    130|#define talloc_free                     ta_free
  ------------------
   41|    130|}

video_decoder_list:
  384|  2.57k|{
  385|  2.57k|    struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list);
  ------------------
  |  |   27|  2.57k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  2.57k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  2.57k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  386|  2.57k|    vd_lavc.add_decoders(list);
  387|  2.57k|    return list;
  388|  2.57k|}
audio_decoder_list:
  391|  2.58k|{
  392|  2.58k|    struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list);
  ------------------
  |  |   27|  2.58k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  2.58k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  2.58k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  393|  2.58k|    ad_lavc.add_decoders(list);
  394|  2.58k|    return list;
  395|  2.58k|}
f_decoder_wrapper.c:decoder_list_help:
  238|     13|{
  239|     13|    if (strcmp(opt->name, "ad") == 0) {
  ------------------
  |  Branch (239:9): [True: 12, False: 1]
  ------------------
  240|     12|        struct mp_decoder_list *list = audio_decoder_list();
  241|     12|        mp_print_decoders(log, MSGL_INFO, "Audio decoders:", list);
  242|     12|        talloc_free(list);
  ------------------
  |  |   47|     12|#define talloc_free                     ta_free
  ------------------
  243|     12|        return M_OPT_EXIT;
  ------------------
  |  |  533|     12|#define M_OPT_EXIT              -6
  ------------------
  244|     12|    }
  245|      1|    if (strcmp(opt->name, "vd") == 0) {
  ------------------
  |  Branch (245:9): [True: 1, False: 0]
  ------------------
  246|      1|        struct mp_decoder_list *list = video_decoder_list();
  247|      1|        mp_print_decoders(log, MSGL_INFO, "Video decoders:", list);
  248|      1|        talloc_free(list);
  ------------------
  |  |   47|      1|#define talloc_free                     ta_free
  ------------------
  249|      1|        return M_OPT_EXIT;
  ------------------
  |  |  533|      1|#define M_OPT_EXIT              -6
  ------------------
  250|      1|    }
  251|      0|    if (strcmp(opt->name, "audio-spdif") == 0) {
  ------------------
  |  Branch (251:9): [True: 0, False: 0]
  ------------------
  252|      0|        mp_info(log, "Choices: ac3,dts-hd,dts (and possibly more)\n");
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  253|      0|        return M_OPT_EXIT;
  ------------------
  |  |  533|      0|#define M_OPT_EXIT              -6
  ------------------
  254|      0|    }
  255|      0|    return 1;
  256|      0|}

mp_lavfi_is_usable:
  997|    189|{
  998|    189|    const AVFilter *f = avfilter_get_by_name(name);
  999|    189|    return f && is_usable(f, media_type);
  ------------------
  |  Branch (999:12): [True: 5, False: 184]
  |  Branch (999:17): [True: 0, False: 5]
  ------------------
 1000|    189|}
print_lavfi_help_list:
 1087|      2|{
 1088|      2|    dump_list(log, media_type);
 1089|      2|    mp_info(log, "\nIf libavfilter filters clash with builtin mpv filters,\n"
  ------------------
  |  |   74|      2|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 1090|      2|            "prefix them with lavfi- to select the libavfilter one.\n\n");
 1091|      2|}
f_lavfi.c:is_usable:
  982|     29|{
  983|     29|    int nb_inputs  = avfilter_filter_pad_count(filter, 0),
  984|     29|        nb_outputs = avfilter_filter_pad_count(filter, 1);
  985|     29|    if (nb_inputs > 1 || nb_outputs > 1)
  ------------------
  |  Branch (985:9): [True: 0, False: 29]
  |  Branch (985:26): [True: 0, False: 29]
  ------------------
  986|      0|        return false;
  987|     29|    bool input_ok = filter->flags & AVFILTER_FLAG_DYNAMIC_INPUTS;
  988|     29|    bool output_ok = filter->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS;
  989|     29|    if (nb_inputs == 1)
  ------------------
  |  Branch (989:9): [True: 9, False: 20]
  ------------------
  990|      9|        input_ok = avfilter_pad_get_type(filter->inputs, 0) == media_type;
  991|     29|    if (nb_outputs == 1)
  ------------------
  |  Branch (991:9): [True: 20, False: 9]
  ------------------
  992|     20|        output_ok = avfilter_pad_get_type(filter->outputs, 0) == media_type;
  993|     29|    return input_ok && output_ok;
  ------------------
  |  Branch (993:12): [True: 5, False: 24]
  |  Branch (993:24): [True: 0, False: 5]
  ------------------
  994|     29|}
f_lavfi.c:dump_list:
 1003|      4|{
 1004|      4|    mp_info(log, "Available libavfilter filters:\n");
  ------------------
  |  |   74|      4|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 1005|      4|    void *iter = NULL;
 1006|     28|    for (;;) {
 1007|     28|        const AVFilter *filter = av_filter_iterate(&iter);
 1008|     28|        if (!filter)
  ------------------
  |  Branch (1008:13): [True: 4, False: 24]
  ------------------
 1009|      4|            break;
 1010|     24|        if (is_usable(filter, media_type))
  ------------------
  |  Branch (1010:13): [True: 0, False: 24]
  ------------------
 1011|      0|            mp_info(log, "  %-16s %s\n", filter->name, filter->description);
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 1012|     24|    }
 1013|      4|}
f_lavfi.c:print_help_a:
 1116|      1|{
 1117|      1|    print_help(log, AVMEDIA_TYPE_AUDIO, "audio", "--af=lavfi=[volume=0.5]");
 1118|      1|}
f_lavfi.c:print_help:
 1094|      2|{
 1095|      2|    dump_list(log, mediatype);
 1096|      2|    mp_info(log, "\n"
  ------------------
  |  |   74|      2|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 1097|      2|        "This lists %s->%s filters only. Refer to\n"
 1098|      2|        "\n"
 1099|      2|        " https://ffmpeg.org/ffmpeg-filters.html\n"
 1100|      2|        "\n"
 1101|      2|        "to see how to use each filter and what arguments each filter takes.\n"
 1102|      2|        "Also, be sure to quote the FFmpeg filter string properly, e.g.:\n"
 1103|      2|        "\n"
 1104|      2|        " \"%s\"\n"
 1105|      2|        "\n"
 1106|      2|        "Otherwise, mpv and libavfilter syntax will conflict.\n"
 1107|      2|        "\n", name, name, ex);
 1108|      2|}
f_lavfi.c:print_help_v:
 1111|      1|{
 1112|      1|    print_help(log, AVMEDIA_TYPE_VIDEO, "video", "--vf=lavfi=[gradfun=20:30]");
 1113|      1|}

mp_filter_reset:
  595|  3.93k|{
  596|  3.93k|    if (!filter)
  ------------------
  |  Branch (596:9): [True: 0, False: 3.93k]
  ------------------
  597|      0|        return;
  598|       |
  599|  3.93k|    for (int n = 0; n < filter->in->num_children; n++)
  ------------------
  |  Branch (599:21): [True: 0, False: 3.93k]
  ------------------
  600|      0|        mp_filter_reset(filter->in->children[n]);
  601|       |
  602|  3.93k|    for (int n = 0; n < filter->num_pins; n++) {
  ------------------
  |  Branch (602:21): [True: 0, False: 3.93k]
  ------------------
  603|      0|        struct mp_pin *p = filter->ppins[n];
  604|      0|        reset_pin(p);
  605|      0|        reset_pin(p->other);
  606|      0|    }
  607|       |
  608|  3.93k|    if (filter->in->info->reset)
  ------------------
  |  Branch (608:9): [True: 0, False: 3.93k]
  ------------------
  609|      0|        filter->in->info->reset(filter);
  610|  3.93k|}
mp_filter_graph_set_max_run_time:
  736|  3.93k|{
  737|  3.93k|    struct filter_runner *r = f->in->runner;
  738|  3.93k|    mp_assert(f == r->root_filter); // user is supposed to call this on root only
  ------------------
  |  |   41|  3.93k|#define mp_assert assert
  ------------------
  739|  3.93k|    r->max_run_time = seconds;
  740|  3.93k|}
mp_filter_free_children:
  750|  3.93k|{
  751|  3.93k|    while(f->in->num_children)
  ------------------
  |  Branch (751:11): [True: 0, False: 3.93k]
  ------------------
  752|      0|        talloc_free(f->in->children[0]);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  753|  3.93k|}
mp_filter_create_with_params:
  800|  3.93k|{
  801|  3.93k|    struct mp_filter *f = talloc(NULL, struct mp_filter);
  ------------------
  |  |   26|  3.93k|#define talloc                          ta_xnew
  |  |  ------------------
  |  |  |  |  133|  3.93k|#define ta_xnew(...)                    ta_oom_g(ta_new(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  3.93k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  802|  3.93k|    talloc_set_destructor(f, filter_destructor);
  ------------------
  |  |   41|  3.93k|#define talloc_set_destructor           ta_set_destructor
  ------------------
  803|  3.93k|    *f = (struct mp_filter){
  804|  3.93k|        .priv = params->info->priv_size ?
  ------------------
  |  Branch (804:17): [True: 0, False: 3.93k]
  ------------------
  805|      0|                    talloc_zero_size(f, params->info->priv_size) : NULL,
  ------------------
  |  |   44|      0|#define talloc_zero_size                ta_xzalloc_size
  |  |  ------------------
  |  |  |  |  121|      0|#define ta_xzalloc_size(...)            ta_oom_p(ta_zalloc_size(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  154|      0|#define ta_zalloc_size(...)     ta_dbg_set_loc(ta_zalloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  806|  3.93k|        .global = params->global,
  807|  3.93k|        .packet_pool = demux_packet_pool_get(params->parent ? params->parent->global : params->global),
  ------------------
  |  Branch (807:46): [True: 0, False: 3.93k]
  ------------------
  808|  3.93k|        .in = talloc(f, struct mp_filter_internal),
  ------------------
  |  |   26|  3.93k|#define talloc                          ta_xnew
  |  |  ------------------
  |  |  |  |  133|  3.93k|#define ta_xnew(...)                    ta_oom_g(ta_new(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  3.93k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  809|  3.93k|    };
  810|  3.93k|    *f->in = (struct mp_filter_internal){
  811|  3.93k|        .info = params->info,
  812|  3.93k|        .parent = params->parent,
  813|  3.93k|        .runner = params->parent ? params->parent->in->runner : NULL,
  ------------------
  |  Branch (813:19): [True: 0, False: 3.93k]
  ------------------
  814|  3.93k|    };
  815|       |
  816|  3.93k|    if (!f->in->runner) {
  ------------------
  |  Branch (816:9): [True: 3.93k, False: 0]
  ------------------
  817|  3.93k|        mp_assert(params->global);
  ------------------
  |  |   41|  3.93k|#define mp_assert assert
  ------------------
  818|       |
  819|  3.93k|        f->in->runner = talloc(NULL, struct filter_runner);
  ------------------
  |  |   26|  3.93k|#define talloc                          ta_xnew
  |  |  ------------------
  |  |  |  |  133|  3.93k|#define ta_xnew(...)                    ta_oom_g(ta_new(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  3.93k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  820|  3.93k|        *f->in->runner = (struct filter_runner){
  821|  3.93k|            .global = params->global,
  822|  3.93k|            .root_filter = f,
  823|  3.93k|            .max_run_time = INFINITY,
  824|  3.93k|        };
  825|  3.93k|        mp_mutex_init(&f->in->runner->async_lock);
  826|  3.93k|    }
  827|       |
  828|  3.93k|    if (!f->global)
  ------------------
  |  Branch (828:9): [True: 0, False: 3.93k]
  ------------------
  829|      0|        f->global = f->in->runner->global;
  830|       |
  831|  3.93k|    if (f->in->parent) {
  ------------------
  |  Branch (831:9): [True: 0, False: 3.93k]
  ------------------
  832|      0|        struct mp_filter_internal *parent = f->in->parent->in;
  833|      0|        MP_TARRAY_APPEND(parent, parent->children, parent->num_children, f);
  ------------------
  |  |  105|      0|    do {                                            \
  |  |  106|      0|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      0|    do {                                            \
  |  |  |  |   97|      0|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      0|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      0|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      0|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      0|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      0|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      0|        (idxvar)++;                                 \
  |  |  109|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  834|      0|        f->log = mp_log_new(f, f->global->log, params->info->name);
  835|  3.93k|    } else {
  836|  3.93k|        f->log = mp_log_new(f, f->global->log, "!root");
  837|  3.93k|    }
  838|       |
  839|  3.93k|    if (f->in->info->init) {
  ------------------
  |  Branch (839:9): [True: 0, False: 3.93k]
  ------------------
  840|      0|        if (!f->in->info->init(f, params)) {
  ------------------
  |  Branch (840:13): [True: 0, False: 0]
  ------------------
  841|      0|            talloc_free(f);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  842|      0|            return NULL;
  843|      0|        }
  844|      0|    }
  845|       |
  846|  3.93k|    return f;
  847|  3.93k|}
mp_filter_create_root:
  868|  3.93k|{
  869|  3.93k|    struct mp_filter_params params = {
  870|  3.93k|        .info = &filter_root,
  871|  3.93k|        .global = global,
  872|  3.93k|    };
  873|  3.93k|    return mp_filter_create_with_params(&params);
  874|  3.93k|}
mp_filter_graph_set_wakeup_cb:
  878|  3.93k|{
  879|  3.93k|    struct filter_runner *r = root->in->runner;
  880|  3.93k|    mp_assert(root == r->root_filter); // user is supposed to call this on root only
  ------------------
  |  |   41|  3.93k|#define mp_assert assert
  ------------------
  881|  3.93k|    mp_mutex_lock(&r->async_lock);
  ------------------
  |  |  131|  3.93k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  882|  3.93k|    r->wakeup_cb = wakeup_cb;
  883|  3.93k|    r->wakeup_ctx = ctx;
  884|  3.93k|    mp_mutex_unlock(&r->async_lock);
  ------------------
  |  |  133|  3.93k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  885|  3.93k|}
filter.c:flush_async_notifications:
  199|  3.93k|{
  200|  3.93k|    mp_mutex_lock(&r->async_lock);
  ------------------
  |  |  131|  3.93k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  201|  3.93k|    for (int n = 0; n < r->num_async_pending; n++) {
  ------------------
  |  Branch (201:21): [True: 0, False: 3.93k]
  ------------------
  202|      0|        struct mp_filter *f = r->async_pending[n];
  203|      0|        add_pending(f);
  204|      0|        f->in->async_pending = false;
  205|      0|    }
  206|  3.93k|    r->num_async_pending = 0;
  207|  3.93k|    r->async_wakeup_sent = false;
  208|  3.93k|    mp_mutex_unlock(&r->async_lock);
  ------------------
  |  |  133|  3.93k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  209|  3.93k|}
filter.c:filter_destructor:
  756|  3.93k|{
  757|  3.93k|    struct mp_filter *f = p;
  758|  3.93k|    struct filter_runner *r = f->in->runner;
  759|       |
  760|  3.93k|    if (f->in->info->destroy)
  ------------------
  |  Branch (760:9): [True: 0, False: 3.93k]
  ------------------
  761|      0|        f->in->info->destroy(f);
  762|       |
  763|       |    // For convenience, free child filters.
  764|  3.93k|    mp_filter_free_children(f);
  765|       |
  766|  3.93k|    while (f->num_pins)
  ------------------
  |  Branch (766:12): [True: 0, False: 3.93k]
  ------------------
  767|      0|        mp_filter_remove_pin(f, f->ppins[0]);
  768|       |
  769|       |    // Just make sure the filter is not still in the async notifications set.
  770|       |    // There will be no more new notifications at this point (due to destroy()).
  771|  3.93k|    flush_async_notifications(r);
  772|       |
  773|  3.93k|    for (int n = 0; n < r->num_pending; n++) {
  ------------------
  |  Branch (773:21): [True: 0, False: 3.93k]
  ------------------
  774|      0|        if (r->pending[n] == f) {
  ------------------
  |  Branch (774:13): [True: 0, False: 0]
  ------------------
  775|      0|            MP_TARRAY_REMOVE_AT(r->pending, r->num_pending, n);
  ------------------
  |  |  143|      0|    do {                                            \
  |  |  144|      0|        size_t at_ = (at);                          \
  |  |  145|      0|        assert(at_ <= (idxvar));                    \
  |  |  146|      0|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|      0|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|      0|        (idxvar)--;                                 \
  |  |  149|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  776|      0|            break;
  777|      0|        }
  778|      0|    }
  779|       |
  780|  3.93k|    if (f->in->parent) {
  ------------------
  |  Branch (780:9): [True: 0, False: 3.93k]
  ------------------
  781|      0|        struct mp_filter_internal *p_in = f->in->parent->in;
  782|      0|        for (int n = 0; n < p_in->num_children; n++) {
  ------------------
  |  Branch (782:25): [True: 0, False: 0]
  ------------------
  783|      0|            if (p_in->children[n] == f) {
  ------------------
  |  Branch (783:17): [True: 0, False: 0]
  ------------------
  784|      0|                MP_TARRAY_REMOVE_AT(p_in->children, p_in->num_children, n);
  ------------------
  |  |  143|      0|    do {                                            \
  |  |  144|      0|        size_t at_ = (at);                          \
  |  |  145|      0|        assert(at_ <= (idxvar));                    \
  |  |  146|      0|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|      0|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|      0|        (idxvar)--;                                 \
  |  |  149|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  785|      0|                break;
  786|      0|            }
  787|      0|        }
  788|      0|    }
  789|       |
  790|  3.93k|    if (r->root_filter == f) {
  ------------------
  |  Branch (790:9): [True: 3.93k, False: 0]
  ------------------
  791|  3.93k|        mp_assert(!f->in->parent);
  ------------------
  |  |   41|  3.93k|#define mp_assert assert
  ------------------
  792|  3.93k|        mp_mutex_destroy(&r->async_lock);
  ------------------
  |  |  130|  3.93k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
  793|  3.93k|        talloc_free(r->async_pending);
  ------------------
  |  |   47|  3.93k|#define talloc_free                     ta_free
  ------------------
  794|  3.93k|        talloc_free(r);
  ------------------
  |  |   47|  3.93k|#define talloc_free                     ta_free
  ------------------
  795|  3.93k|    }
  796|  3.93k|}

user_filters.c:get_af_desc:
   47|   144k|{
   48|   144k|    return get_desc_from(af_list, MP_ARRAY_SIZE(af_list), dst, index);
  ------------------
  |  |   48|   144k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
   49|   144k|}
user_filters.c:get_desc_from:
   14|   236k|{
   15|   236k|    if (index >= num)
  ------------------
  |  Branch (15:9): [True: 34.3k, False: 202k]
  ------------------
   16|  34.3k|        return false;
   17|   202k|    const struct mp_user_filter_entry *entry = list[index];
   18|   202k|    *dst = entry->desc;
   19|   202k|    dst->p = entry;
   20|   202k|    return true;
   21|   236k|}
user_filters.c:check_af_lavfi:
   62|     70|{
   63|     70|    return check_unknown_entry(name, AVMEDIA_TYPE_AUDIO);
   64|     70|}
user_filters.c:check_unknown_entry:
   24|    189|{
   25|       |    // Generic lavfi bridge: skip the lavfi- prefix, if present.
   26|    189|    if (strncmp(name, "lavfi-", 6) == 0)
  ------------------
  |  Branch (26:9): [True: 2, False: 187]
  ------------------
   27|      2|        name += 6;
   28|    189|    return mp_lavfi_is_usable(name, media_type);
   29|    189|}
user_filters.c:print_af_help_list:
   52|      1|{
   53|      1|    print_lavfi_help_list(log, AVMEDIA_TYPE_AUDIO);
   54|      1|}
user_filters.c:get_vf_desc:
  109|  91.8k|{
  110|  91.8k|    return get_desc_from(vf_list, MP_ARRAY_SIZE(vf_list), dst, index);
  ------------------
  |  |   48|  91.8k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  111|  91.8k|}
user_filters.c:check_vf_lavfi:
  124|    119|{
  125|    119|    return check_unknown_entry(name, AVMEDIA_TYPE_VIDEO);
  126|    119|}
user_filters.c:print_vf_help_list:
  114|      1|{
  115|      1|    print_lavfi_help_list(log, AVMEDIA_TYPE_VIDEO);
  116|      1|}

LLVMFuzzerTestOneInput:
   30|  17.0k|{
   31|  17.0k|    char buff[MAX_INPUT_SIZE + 2];
   32|       |
   33|  17.0k|    if (!size || size > MAX_INPUT_SIZE)
  ------------------
  |  |   26|  17.0k|#define MAX_INPUT_SIZE 2048
  ------------------
  |  Branch (33:9): [True: 0, False: 17.0k]
  |  Branch (33:18): [True: 13, False: 17.0k]
  ------------------
   34|     13|        return 0;
   35|       |
   36|  17.0k|    memcpy(buff, data, size);
   37|  17.0k|    buff[size] = '\0';
   38|  17.0k|    buff[size + 1] = '\0';
   39|       |
   40|  17.0k|    char *opts[MAX_OPTS_NUM + 1];
   41|  17.0k|    char *opt = buff;
   42|  17.0k|    int count = 0;
   43|   276k|    while (*opt && count < MAX_OPTS_NUM) {
  ------------------
  |  |   27|   259k|#define MAX_OPTS_NUM 10000
  ------------------
  |  Branch (43:12): [True: 259k, False: 17.0k]
  |  Branch (43:20): [True: 259k, False: 0]
  ------------------
   44|   259k|        opts[count] = opt;
   45|       |
   46|  3.66M|        while (*opt && !isspace(*opt))
  ------------------
  |  Branch (46:16): [True: 3.58M, False: 85.0k]
  |  Branch (46:24): [True: 3.40M, False: 174k]
  ------------------
   47|  3.40M|            opt++;
   48|       |
   49|   259k|        *opt = '\0';
   50|   259k|        opt++;
   51|       |
   52|   270k|        while (*opt && isspace(*opt))
  ------------------
  |  Branch (52:16): [True: 253k, False: 17.0k]
  ------------------
   53|  10.7k|            opt++;
   54|       |
   55|   259k|        count++;
   56|   259k|    }
   57|  17.0k|    opts[count] = NULL;
   58|       |
   59|  17.0k|    mpv_handle *ctx = mpv_create();
   60|  17.0k|    if (!ctx)
  ------------------
  |  Branch (60:9): [True: 0, False: 17.0k]
  ------------------
   61|      0|        exit(1);
   62|       |
   63|  17.0k|    mpv_initialize_opts(ctx, opts);
   64|       |
   65|  17.0k|    mpv_terminate_destroy(ctx);
   66|       |
   67|  17.0k|    return 0;
   68|  17.0k|}

mp_input_parse_cmd_node:
  293|  17.0k|{
  294|  17.0k|    struct mp_cmd *cmd = talloc_ptrtype(NULL, cmd);
  ------------------
  |  |   34|  17.0k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  17.0k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  295|  17.0k|    talloc_set_destructor(cmd, destroy_cmd);
  ------------------
  |  |   41|  17.0k|#define talloc_set_destructor           ta_set_destructor
  ------------------
  296|  17.0k|    *cmd = (struct mp_cmd) { .scale = 1, .scale_units = 1 };
  297|       |
  298|  17.0k|    bool res = false;
  299|  17.0k|    if (node->format == MPV_FORMAT_NODE_ARRAY) {
  ------------------
  |  Branch (299:9): [True: 17.0k, False: 0]
  ------------------
  300|  17.0k|        res = cmd_node_array(log, cmd, node);
  301|  17.0k|    } else if (node->format == MPV_FORMAT_NODE_MAP) {
  ------------------
  |  Branch (301:16): [True: 0, False: 0]
  ------------------
  302|      0|        res = cmd_node_map(log, cmd, node);
  303|      0|    }
  304|       |
  305|  17.0k|    res = res && finish_cmd(log, cmd);
  ------------------
  |  Branch (305:11): [True: 17.0k, False: 0]
  |  Branch (305:18): [True: 17.0k, False: 0]
  ------------------
  306|       |
  307|  17.0k|    if (!res)
  ------------------
  |  Branch (307:9): [True: 0, False: 17.0k]
  ------------------
  308|      0|        TA_FREEP(&cmd);
  ------------------
  |  |   81|      0|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|      0|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  309|       |
  310|  17.0k|    return cmd;
  311|  17.0k|}
mp_input_parse_cmd_str:
  455|  2.34M|{
  456|  2.34M|    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|  2.34M|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  2.34M|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  457|  2.34M|    bstr original = str;
  458|  2.34M|    struct mp_cmd *cmd = parse_cmd_str(log, tmp, &str, loc);
  459|  2.34M|    if (!cmd)
  ------------------
  |  Branch (459:9): [True: 17.6k, False: 2.33M]
  ------------------
  460|  17.6k|        goto done;
  461|       |
  462|       |    // Handle "multi" commands
  463|  2.33M|    struct mp_cmd **p_prev = NULL;
  464|  2.55M|    while (1) {
  ------------------
  |  Branch (464:12): [Folded - Ignored]
  ------------------
  465|  2.55M|        str = bstr_lstrip(str);
  466|       |        // read_token just to check whether it's trailing whitespace only
  467|  2.55M|        bstr u1, u2;
  468|  2.55M|        if (!bstr_eatstart0(&str, ";") || !read_token(str, &u1, &u2))
  ------------------
  |  Branch (468:13): [True: 2.33M, False: 218k]
  |  Branch (468:43): [True: 0, False: 218k]
  ------------------
  469|  2.33M|            break;
  470|       |        // Multi-command. Since other input.c code uses queue_next for its
  471|       |        // own purposes, a pseudo-command is used to wrap the command list.
  472|   218k|        if (!p_prev) {
  ------------------
  |  Branch (472:13): [True: 157k, False: 60.7k]
  ------------------
  473|   157k|            struct mp_cmd *list = talloc_ptrtype(NULL, list);
  ------------------
  |  |   34|   157k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|   157k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|   157k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  474|   157k|            talloc_set_destructor(list, destroy_cmd);
  ------------------
  |  |   41|   157k|#define talloc_set_destructor           ta_set_destructor
  ------------------
  475|   157k|            *list = (struct mp_cmd) {
  476|   157k|                .name = (char *)mp_cmd_list.name,
  477|   157k|                .def = &mp_cmd_list,
  478|   157k|            };
  479|   157k|            talloc_steal(list, cmd);
  ------------------
  |  |   38|   157k|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|   157k|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  480|   157k|            struct mp_cmd_arg arg = {0};
  481|   157k|            arg.v.p = cmd;
  482|   157k|            list->args = talloc_dup(list, &arg);
  ------------------
  |  |   48|   157k|#define talloc_dup                      ta_xdup
  |  |  ------------------
  |  |  |  |  141|   157k|#define ta_xdup(...)                    ta_oom_g(ta_dup(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|   157k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  483|   157k|            p_prev = &cmd->queue_next;
  484|   157k|            cmd = list;
  485|   157k|        }
  486|   218k|        struct mp_cmd *sub = parse_cmd_str(log, tmp, &str, loc);
  487|   218k|        if (!sub) {
  ------------------
  |  Branch (487:13): [True: 0, False: 218k]
  ------------------
  488|      0|            talloc_free(cmd);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  489|      0|            cmd = NULL;
  490|      0|            goto done;
  491|      0|        }
  492|   218k|        talloc_steal(cmd, sub);
  ------------------
  |  |   38|   218k|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|   218k|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  493|   218k|        *p_prev = sub;
  494|   218k|        p_prev = &sub->queue_next;
  495|   218k|    }
  496|       |
  497|  2.33M|    cmd->original = bstrto0(cmd, bstr_strip(
  498|  2.33M|                        bstr_splice(original, 0, str.start - original.start)));
  499|       |
  500|  2.33M|    str = bstr_strip(str);
  501|  2.33M|    if (bstr_eatstart0(&str, "#") && !bstr_startswith0(str, "#")) {
  ------------------
  |  Branch (501:9): [True: 1.78M, False: 546k]
  |  Branch (501:38): [True: 1.78M, False: 0]
  ------------------
  502|  1.78M|        str = bstr_strip(str);
  503|  1.78M|        if (str.len)
  ------------------
  |  Branch (503:13): [True: 1.78M, False: 0]
  ------------------
  504|  1.78M|            cmd->desc = bstrto0(cmd, str);
  505|  1.78M|    }
  506|       |
  507|  2.34M|done:
  508|  2.34M|    talloc_free(tmp);
  ------------------
  |  |   47|  2.34M|#define talloc_free                     ta_free
  ------------------
  509|  2.34M|    return cmd;
  510|  2.33M|}
mp_input_parse_cmd_strv:
  513|  17.0k|{
  514|  17.0k|    int count = 0;
  515|  34.1k|    while (argv[count])
  ------------------
  |  Branch (515:12): [True: 17.0k, False: 17.0k]
  ------------------
  516|  17.0k|        count++;
  517|  17.0k|    mpv_node *items = talloc_zero_array(NULL, mpv_node, count);
  ------------------
  |  |   30|  17.0k|#define talloc_zero_array               ta_xznew_array
  |  |  ------------------
  |  |  |  |  136|  17.0k|#define ta_xznew_array(...)             ta_oom_g(ta_znew_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  518|  17.0k|    mpv_node_list list = {.values = items, .num = count};
  519|  17.0k|    mpv_node node = {.format = MPV_FORMAT_NODE_ARRAY, .u = {.list = &list}};
  520|  34.1k|    for (int n = 0; n < count; n++) {
  ------------------
  |  Branch (520:21): [True: 17.0k, False: 17.0k]
  ------------------
  521|  17.0k|        items[n] = (mpv_node){.format = MPV_FORMAT_STRING,
  522|  17.0k|                              .u = {.string = (char *)argv[n]}};
  523|  17.0k|    }
  524|  17.0k|    struct mp_cmd *res = mp_input_parse_cmd_node(log, &node);
  525|  17.0k|    talloc_free(items);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  526|  17.0k|    return res;
  527|  17.0k|}
mp_cmd_dump:
  582|  12.1k|{
  583|  12.1k|    if (!mp_msg_test(log, msgl))
  ------------------
  |  Branch (583:9): [True: 35, False: 12.1k]
  ------------------
  584|     35|        return;
  585|  12.1k|    if (header)
  ------------------
  |  Branch (585:9): [True: 12.1k, False: 0]
  ------------------
  586|  12.1k|        mp_msg(log, msgl, "%s ", header);
  587|  12.1k|    if (!cmd) {
  ------------------
  |  Branch (587:9): [True: 0, False: 12.1k]
  ------------------
  588|      0|        mp_msg(log, msgl, "(NULL)\n");
  589|      0|        return;
  590|      0|    }
  591|  12.1k|    mp_msg(log, msgl, "%s, flags=%d, args=[", cmd->name, cmd->flags);
  592|  12.1k|    int argc = get_arg_count(cmd->def);
  593|  24.2k|    for (int n = 0; n < cmd->nargs; n++) {
  ------------------
  |  Branch (593:21): [True: 12.1k, False: 12.1k]
  ------------------
  594|  12.1k|        const char *argname = cmd->def->args[MPMIN(n, argc - 1)].name;
  ------------------
  |  |   44|  12.1k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 12.1k]
  |  |  ------------------
  ------------------
  595|  12.1k|        char *s = m_option_print(cmd->args[n].type, &cmd->args[n].v);
  596|  12.1k|        if (n)
  ------------------
  |  Branch (596:13): [True: 0, False: 12.1k]
  ------------------
  597|      0|            mp_msg(log, msgl, ", ");
  598|  12.1k|        struct mpv_node node = {
  599|  12.1k|            .format = MPV_FORMAT_STRING,
  600|  12.1k|            .u.string = s ? s : "(NULL)",
  ------------------
  |  Branch (600:25): [True: 12.1k, False: 0]
  ------------------
  601|  12.1k|        };
  602|  12.1k|        char *esc = NULL;
  603|  12.1k|        json_write(&esc, &node);
  604|  12.1k|        mp_msg(log, msgl, "%s=%s", argname, esc ? esc : "<error>");
  ------------------
  |  Branch (604:45): [True: 12.1k, False: 0]
  ------------------
  605|  12.1k|        talloc_free(esc);
  ------------------
  |  |   47|  12.1k|#define talloc_free                     ta_free
  ------------------
  606|  12.1k|        talloc_free(s);
  ------------------
  |  |   47|  12.1k|#define talloc_free                     ta_free
  ------------------
  607|  12.1k|    }
  608|  12.1k|    mp_msg(log, msgl, "]\n");
  609|  12.1k|}
mp_print_cmd_list:
  626|    700|{
  627|  60.2k|    for (int i = 0; mp_cmds[i].name; i++) {
  ------------------
  |  Branch (627:21): [True: 59.5k, False: 700]
  ------------------
  628|  59.5k|        const struct mp_cmd_def *def = &mp_cmds[i];
  629|  59.5k|        mp_info(out, "%-25s", def->name);
  ------------------
  |  |   74|  59.5k|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  630|   165k|        for (int j = 0; j < MP_CMD_DEF_MAX_ARGS && def->args[j].type; j++) {
  ------------------
  |  |   26|   331k|#define MP_CMD_DEF_MAX_ARGS 11
  ------------------
  |  Branch (630:25): [True: 165k, False: 700]
  |  Branch (630:52): [True: 106k, False: 58.8k]
  ------------------
  631|   106k|            const struct m_option *arg = &def->args[j];
  632|   106k|            bool is_opt = arg->defval || (arg->flags & MP_CMD_OPT_ARG);
  ------------------
  |  |   27|  83.3k|#define MP_CMD_OPT_ARG M_OPT_OPTIONAL_PARAM
  |  |  ------------------
  |  |  |  |  485|  83.3k|#define M_OPT_OPTIONAL_PARAM    (UINT64_C(1) << 54)
  |  |  ------------------
  ------------------
  |  Branch (632:27): [True: 23.1k, False: 83.3k]
  |  Branch (632:42): [True: 26.6k, False: 56.7k]
  ------------------
  633|   106k|            mp_info(out, " %s%s=%s%s", is_opt ? "[" : "", arg->name,
  ------------------
  |  |   74|   425k|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (74:56): [True: 49.7k, False: 56.7k]
  |  |  |  Branch (74:56): [True: 49.7k, False: 56.7k]
  |  |  ------------------
  ------------------
  634|   106k|                    arg->type->name, is_opt ? "]" : "");
  635|   106k|        }
  636|  59.5k|        if (def->vararg)
  ------------------
  |  Branch (636:13): [True: 2.80k, False: 56.7k]
  ------------------
  637|  2.80k|            mp_info(out, "..."); // essentially append to last argument
  ------------------
  |  |   74|  2.80k|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  638|  59.5k|        mp_info(out, "\n");
  ------------------
  |  |   74|  59.5k|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  639|  59.5k|    }
  640|    700|}
cmd.c:destroy_cmd:
   33|  2.74M|{
   34|  2.74M|    struct mp_cmd *cmd = ptr;
   35|  7.81M|    for (int n = 0; n < cmd->nargs; n++) {
  ------------------
  |  Branch (35:21): [True: 5.07M, False: 2.74M]
  ------------------
   36|  5.07M|        if (cmd->args[n].type)
  ------------------
  |  Branch (36:13): [True: 5.07M, False: 0]
  ------------------
   37|  5.07M|            m_option_free(cmd->args[n].type, &cmd->args[n].v);
   38|  5.07M|    }
   39|  2.74M|}
cmd.c:cmd_node_array:
  205|  17.0k|{
  206|  17.0k|    mp_assert(node->format == MPV_FORMAT_NODE_ARRAY);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  207|  17.0k|    mpv_node_list *args = node->u.list;
  208|  17.0k|    int cur = 0;
  209|       |
  210|  17.0k|    while (cur < args->num) {
  ------------------
  |  Branch (210:12): [True: 17.0k, False: 0]
  ------------------
  211|  17.0k|        if (args->values[cur].format != MPV_FORMAT_STRING)
  ------------------
  |  Branch (211:13): [True: 0, False: 17.0k]
  ------------------
  212|      0|            break;
  213|  17.0k|        if (!apply_flag(cmd, bstr0(args->values[cur].u.string)))
  ------------------
  |  Branch (213:13): [True: 17.0k, False: 0]
  ------------------
  214|  17.0k|            break;
  215|      0|        cur++;
  216|      0|    }
  217|       |
  218|  17.0k|    bstr cmd_name = {0};
  219|  17.0k|    if (cur < args->num && args->values[cur].format == MPV_FORMAT_STRING)
  ------------------
  |  Branch (219:9): [True: 17.0k, False: 0]
  |  Branch (219:28): [True: 17.0k, False: 0]
  ------------------
  220|  17.0k|        cmd_name = bstr0(args->values[cur++].u.string);
  221|  17.0k|    if (!find_cmd(log, cmd, cmd_name))
  ------------------
  |  Branch (221:9): [True: 0, False: 17.0k]
  ------------------
  222|      0|        return false;
  223|       |
  224|  17.0k|    int first = cur;
  225|  17.0k|    for (int i = 0; i < args->num - first; i++) {
  ------------------
  |  Branch (225:21): [True: 0, False: 17.0k]
  ------------------
  226|      0|        if (!set_node_arg(log, cmd, cmd->nargs, &args->values[cur++]))
  ------------------
  |  Branch (226:13): [True: 0, False: 0]
  ------------------
  227|      0|            return false;
  228|      0|    }
  229|       |
  230|  17.0k|    return true;
  231|  17.0k|}
cmd.c:apply_flag:
   63|  2.75M|{
   64|  33.7M|    for (int n = 0; cmd_flags[n].name; n++) {
  ------------------
  |  Branch (64:21): [True: 31.1M, False: 2.58M]
  ------------------
   65|  31.1M|        if (bstr_equals0(str, cmd_flags[n].name)) {
  ------------------
  |  Branch (65:13): [True: 170k, False: 31.0M]
  ------------------
   66|   170k|            cmd->flags = (cmd->flags & ~cmd_flags[n].remove) | cmd_flags[n].add;
   67|   170k|            return true;
   68|   170k|        }
   69|  31.1M|    }
   70|  2.58M|    return false;
   71|  2.75M|}
cmd.c:find_cmd:
   74|  2.58M|{
   75|  2.58M|    if (name.len == 0) {
  ------------------
  |  Branch (75:9): [True: 13.3k, False: 2.57M]
  ------------------
   76|  13.3k|        mp_err(log, "Command name missing.\n");
  ------------------
  |  |   72|  13.3k|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
   77|  13.3k|        return false;
   78|  13.3k|    }
   79|       |
   80|  2.57M|    char nname[80];
   81|  2.57M|    snprintf(nname, sizeof(nname), "%.*s", BSTR_P(name));
  ------------------
  |  |  283|  2.57M|#define BSTR_P(bstr) (int)((bstr).len), ((bstr).start ? (char*)(bstr).start : "")
  |  |  ------------------
  |  |  |  Branch (283:42): [True: 2.57M, False: 0]
  |  |  ------------------
  ------------------
   82|  17.8M|    for (int n = 0; nname[n]; n++) {
  ------------------
  |  Branch (82:21): [True: 15.3M, False: 2.57M]
  ------------------
   83|  15.3M|        if (nname[n] == '_')
  ------------------
  |  Branch (83:13): [True: 841, False: 15.3M]
  ------------------
   84|    841|            nname[n] = '-';
   85|  15.3M|    }
   86|       |
   87|   102M|    for (int n = 0; mp_cmds[n].name; n++) {
  ------------------
  |  Branch (87:21): [True: 102M, False: 3.94k]
  ------------------
   88|   102M|        if (strcmp(nname, mp_cmds[n].name) == 0) {
  ------------------
  |  Branch (88:13): [True: 2.56M, False: 100M]
  ------------------
   89|  2.56M|            cmd->def = &mp_cmds[n];
   90|  2.56M|            cmd->name = (char *)cmd->def->name;
   91|  2.56M|            return true;
   92|  2.56M|        }
   93|   102M|    }
   94|  3.94k|    mp_err(log, "Command '%.*s' not found.\n", BSTR_P(name));
  ------------------
  |  |   72|  7.89k|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 3.94k, False: 0]
  |  |  ------------------
  ------------------
   95|  3.94k|    return false;
   96|  2.57M|}
cmd.c:get_arg_type:
  104|  10.1M|{
  105|  10.1M|    const struct m_option *opt = NULL;
  106|  10.1M|    if (is_vararg(cmd, i)) {
  ------------------
  |  Branch (106:9): [True: 206k, False: 9.98M]
  ------------------
  107|       |        // The last arg in a vararg command sets all vararg types.
  108|   412k|        for (int n = MPMIN(i, MP_CMD_DEF_MAX_ARGS - 1); n >= 0; n--) {
  ------------------
  |  |   44|   206k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 206k]
  |  |  ------------------
  ------------------
  |  Branch (108:57): [True: 412k, False: 0]
  ------------------
  109|   412k|            if (cmd->args[n].type) {
  ------------------
  |  Branch (109:17): [True: 206k, False: 206k]
  ------------------
  110|   206k|                opt = &cmd->args[n];
  111|   206k|                break;
  112|   206k|            }
  113|   412k|        }
  114|  9.98M|    } else if (i < MP_CMD_DEF_MAX_ARGS) {
  ------------------
  |  |   26|  9.98M|#define MP_CMD_DEF_MAX_ARGS 11
  ------------------
  |  Branch (114:16): [True: 9.98M, False: 0]
  ------------------
  115|  9.98M|        opt = &cmd->args[i];
  116|  9.98M|    }
  117|  10.1M|    return opt && opt->type ? opt : NULL;
  ------------------
  |  Branch (117:12): [True: 10.1M, False: 0]
  |  Branch (117:19): [True: 6.22M, False: 3.96M]
  ------------------
  118|  10.1M|}
cmd.c:is_vararg:
   99|  11.4M|{
  100|  11.4M|    return m->vararg && (i + 1 >= MP_CMD_DEF_MAX_ARGS || !m->args[i + 1].type);
  ------------------
  |  |   26|   777k|#define MP_CMD_DEF_MAX_ARGS 11
  ------------------
  |  Branch (100:12): [True: 388k, False: 11.1M]
  |  Branch (100:26): [True: 0, False: 388k]
  |  Branch (100:58): [True: 267k, False: 121k]
  ------------------
  101|  11.4M|}
cmd.c:finish_cmd:
  129|  2.56M|{
  130|  7.63M|    for (int i = 0; i < MP_CMD_DEF_MAX_ARGS; i++) {
  ------------------
  |  |   26|  7.63M|#define MP_CMD_DEF_MAX_ARGS 11
  ------------------
  |  Branch (130:21): [True: 7.63M, False: 0]
  ------------------
  131|       |        // (type==NULL is used for yet unset arguments)
  132|  7.63M|        if (i < cmd->nargs && cmd->args[i].type)
  ------------------
  |  Branch (132:13): [True: 3.82M, False: 3.81M]
  |  Branch (132:31): [True: 3.82M, False: 0]
  ------------------
  133|  3.82M|            continue;
  134|  3.81M|        const struct m_option *opt = get_arg_type(cmd->def, i);
  135|  3.81M|        if (i >= cmd->nargs && (!opt || is_vararg(cmd->def, i)))
  ------------------
  |  Branch (135:13): [True: 3.81M, False: 0]
  |  Branch (135:33): [True: 2.50M, False: 1.30M]
  |  Branch (135:41): [True: 60.7k, False: 1.24M]
  ------------------
  136|  2.56M|            break;
  137|  1.24M|        if (!opt->defval && !(opt->flags & MP_CMD_OPT_ARG)) {
  ------------------
  |  |   27|   478k|#define MP_CMD_OPT_ARG M_OPT_OPTIONAL_PARAM
  |  |  ------------------
  |  |  |  |  485|   478k|#define M_OPT_OPTIONAL_PARAM    (UINT64_C(1) << 54)
  |  |  ------------------
  ------------------
  |  Branch (137:13): [True: 478k, False: 765k]
  |  Branch (137:29): [True: 0, False: 478k]
  ------------------
  138|      0|            mp_err(log, "Command %s: required argument %s not set.\n",
  ------------------
  |  |   72|      0|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 0, False: 0]
  |  |  |  Branch (72:55): [True: 0, False: 0]
  |  |  |  Branch (72:55): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  139|      0|                   cmd->name, get_arg_name(cmd->def, i));
  140|      0|            return false;
  141|      0|        }
  142|  1.24M|        struct mp_cmd_arg arg = {.type = opt};
  143|  1.24M|        if (opt->defval)
  ------------------
  |  Branch (143:13): [True: 765k, False: 478k]
  ------------------
  144|   765k|            m_option_copy(opt, &arg.v, opt->defval);
  145|  1.24M|        mp_assert(i <= cmd->nargs);
  ------------------
  |  |   41|  1.24M|#define mp_assert assert
  ------------------
  146|  1.24M|        if (i == cmd->nargs) {
  ------------------
  |  Branch (146:13): [True: 1.24M, False: 0]
  ------------------
  147|  1.24M|            MP_TARRAY_APPEND(cmd, cmd->args, cmd->nargs, arg);
  ------------------
  |  |  105|  1.24M|    do {                                            \
  |  |  106|  1.24M|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  1.24M|    do {                                            \
  |  |  |  |   97|  1.24M|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  1.24M|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  1.24M|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  1.24M|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 442k, False: 801k]
  |  |  |  |  ------------------
  |  |  |  |   99|  1.24M|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|   442k|    do {                                                        \
  |  |  |  |  |  |   89|   442k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|   442k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|   442k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|   442k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|   442k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|   442k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|   442k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  1.24M|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  1.24M|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  1.24M|        (idxvar)++;                                 \
  |  |  109|  1.24M|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  148|  1.24M|        } else {
  149|      0|            cmd->args[i] = arg;
  150|      0|        }
  151|  1.24M|    }
  152|       |
  153|  2.56M|    if (!(cmd->flags & (MP_ASYNC_CMD | MP_SYNC_CMD)))
  ------------------
  |  Branch (153:9): [True: 2.56M, False: 0]
  ------------------
  154|  2.56M|        cmd->flags |= cmd->def->default_async ? MP_ASYNC_CMD : MP_SYNC_CMD;
  ------------------
  |  Branch (154:23): [True: 0, False: 2.56M]
  ------------------
  155|       |
  156|  2.56M|    return true;
  157|  2.56M|}
cmd.c:parse_cmd_str:
  374|  2.56M|{
  375|  2.56M|    struct parse_ctx *ctx = &(struct parse_ctx){
  376|  2.56M|        .log = log,
  377|  2.56M|        .tmp = tmp,
  378|  2.56M|        .str = *str,
  379|  2.56M|        .start = *str,
  380|  2.56M|    };
  381|       |
  382|  2.56M|    struct mp_cmd *cmd = talloc_ptrtype(NULL, cmd);
  ------------------
  |  |   34|  2.56M|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  2.56M|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  2.56M|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  383|  2.56M|    talloc_set_destructor(cmd, destroy_cmd);
  ------------------
  |  |   41|  2.56M|#define talloc_set_destructor           ta_set_destructor
  ------------------
  384|  2.56M|    *cmd = (struct mp_cmd) {
  385|  2.56M|        .flags = MP_ON_OSD_AUTO | MP_EXPAND_PROPERTIES,
  386|  2.56M|        .scale = 1,
  387|  2.56M|        .scale_units = 1,
  388|  2.56M|    };
  389|       |
  390|  2.56M|    ctx->str = bstr_lstrip(ctx->str);
  391|       |
  392|  2.56M|    bstr cur_token;
  393|  2.56M|    if (pctx_read_token(ctx, &cur_token) < 0)
  ------------------
  |  Branch (393:9): [True: 271, False: 2.56M]
  ------------------
  394|    271|        goto error;
  395|       |
  396|  2.73M|    while (1) {
  ------------------
  |  Branch (396:12): [Folded - Ignored]
  ------------------
  397|  2.73M|        if (!apply_flag(cmd, cur_token))
  ------------------
  |  Branch (397:13): [True: 2.56M, False: 170k]
  ------------------
  398|  2.56M|            break;
  399|   170k|        if (pctx_read_token(ctx, &cur_token) < 0)
  ------------------
  |  Branch (399:13): [True: 0, False: 170k]
  ------------------
  400|      0|            goto error;
  401|   170k|    }
  402|       |
  403|  2.56M|    if (!find_cmd(ctx->log, cmd, cur_token))
  ------------------
  |  Branch (403:9): [True: 17.3k, False: 2.55M]
  ------------------
  404|  17.3k|        goto error;
  405|       |
  406|  6.37M|    for (int i = 0; i < MP_CMD_MAX_ARGS; i++) {
  ------------------
  |  |   86|  6.37M|#define MP_CMD_MAX_ARGS 100
  ------------------
  |  Branch (406:21): [True: 6.37M, False: 0]
  ------------------
  407|  6.37M|        const struct m_option *opt = get_arg_type(cmd->def, i);
  408|  6.37M|        if (!opt)
  ------------------
  |  Branch (408:13): [True: 1.45M, False: 4.91M]
  ------------------
  409|  1.45M|            break;
  410|       |
  411|  4.91M|        int r = pctx_read_token(ctx, &cur_token);
  412|  4.91M|        if (r < 0) {
  ------------------
  |  Branch (412:13): [True: 0, False: 4.91M]
  ------------------
  413|      0|            MP_ERR(ctx, "Command %s: error in argument %d.\n", cmd->name, i + 1);
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  414|      0|            goto error;
  415|      0|        }
  416|  4.91M|        if (r < 1)
  ------------------
  |  Branch (416:13): [True: 1.09M, False: 3.82M]
  ------------------
  417|  1.09M|            break;
  418|       |
  419|  3.82M|        struct mp_cmd_arg arg = {.type = opt};
  420|  3.82M|        r = m_option_parse(ctx->log, opt, bstr0(cmd->name), cur_token, &arg.v);
  421|  3.82M|        if (r < 0) {
  ------------------
  |  Branch (421:13): [True: 0, False: 3.82M]
  ------------------
  422|      0|            MP_ERR(ctx, "Command %s: argument %d can't be parsed: %s.\n",
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  423|      0|                   cmd->name, i + 1, m_option_strerror(r));
  424|      0|            goto error;
  425|      0|        }
  426|       |
  427|  3.82M|        MP_TARRAY_APPEND(cmd, cmd->args, cmd->nargs, arg);
  ------------------
  |  |  105|  3.82M|    do {                                            \
  |  |  106|  3.82M|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  3.82M|    do {                                            \
  |  |  |  |   97|  3.82M|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  3.82M|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  3.82M|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  3.82M|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 2.34M, False: 1.48M]
  |  |  |  |  ------------------
  |  |  |  |   99|  3.82M|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  2.34M|    do {                                                        \
  |  |  |  |  |  |   89|  2.34M|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  2.34M|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  2.34M|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  2.34M|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  2.34M|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  2.34M|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  2.34M|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  3.82M|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  3.82M|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  3.82M|        (idxvar)++;                                 \
  |  |  109|  3.82M|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  428|  3.82M|    }
  429|       |
  430|  2.55M|    if (!finish_cmd(ctx->log, cmd))
  ------------------
  |  Branch (430:9): [True: 0, False: 2.55M]
  ------------------
  431|      0|        goto error;
  432|       |
  433|  2.55M|    bstr dummy;
  434|  2.55M|    if (read_token(ctx->str, &dummy, &dummy) && ctx->str.len) {
  ------------------
  |  Branch (434:9): [True: 0, False: 2.55M]
  |  Branch (434:49): [True: 0, False: 0]
  ------------------
  435|      0|        MP_ERR(ctx, "Command %s has trailing unused arguments: '%.*s'.\n",
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  436|      0|               cmd->name, BSTR_P(ctx->str));
  437|       |        // Better make it fatal to make it clear something is wrong.
  438|      0|        goto error;
  439|      0|    }
  440|       |
  441|  2.55M|    bstr orig = {ctx->start.start, ctx->str.start - ctx->start.start};
  442|  2.55M|    cmd->original = bstrto0(cmd, bstr_strip(orig));
  443|       |
  444|  2.55M|    *str = ctx->str;
  445|  2.55M|    return cmd;
  446|       |
  447|  17.6k|error:
  448|  17.6k|    MP_ERR(ctx, "Command was defined at %s.\n", loc);
  ------------------
  |  |   85|  17.6k|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  17.6k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  449|  17.6k|    talloc_free(cmd);
  ------------------
  |  |   47|  17.6k|#define talloc_free                     ta_free
  ------------------
  450|  17.6k|    *str = ctx->str;
  451|  17.6k|    return NULL;
  452|  2.55M|}
cmd.c:pctx_read_token:
  331|  7.65M|{
  332|  7.65M|    *out = (bstr){0};
  333|  7.65M|    ctx->str = bstr_lstrip(ctx->str);
  334|  7.65M|    bstr start = ctx->str;
  335|  7.65M|    if (bstr_eatstart0(&ctx->str, "\"")) {
  ------------------
  |  Branch (335:9): [True: 121k, False: 7.53M]
  ------------------
  336|   121k|        if (!mp_append_escaped_string_noalloc(ctx->tmp, out, &ctx->str)) {
  ------------------
  |  Branch (336:13): [True: 36, False: 121k]
  ------------------
  337|     36|            MP_ERR(ctx, "Broken string escapes: ...>%.*s<.\n", BSTR_P(start));
  ------------------
  |  |   85|     36|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     72|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 36, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  338|     36|            return -1;
  339|     36|        }
  340|   121k|        if (!bstr_eatstart0(&ctx->str, "\"")) {
  ------------------
  |  Branch (340:13): [True: 102, False: 121k]
  ------------------
  341|    102|            MP_ERR(ctx, "Unterminated double quote: ...>%.*s<.\n", BSTR_P(start));
  ------------------
  |  |   85|    102|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    204|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 102, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  342|    102|            return -1;
  343|    102|        }
  344|   121k|        return 1;
  345|   121k|    }
  346|  7.53M|    if (bstr_eatstart0(&ctx->str, "'")) {
  ------------------
  |  Branch (346:9): [True: 12.2k, False: 7.52M]
  ------------------
  347|  12.2k|        int next = bstrchr(ctx->str, '\'');
  348|  12.2k|        if (next < 0) {
  ------------------
  |  Branch (348:13): [True: 66, False: 12.2k]
  ------------------
  349|     66|            MP_ERR(ctx, "Unterminated single quote: ...>%.*s<.\n", BSTR_P(start));
  ------------------
  |  |   85|     66|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    132|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 66, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  350|     66|            return -1;
  351|     66|        }
  352|  12.2k|        *out = bstr_splice(ctx->str, 0, next);
  353|  12.2k|        ctx->str = bstr_cut(ctx->str, next+1);
  354|  12.2k|        return 1;
  355|  12.2k|    }
  356|  7.52M|    if (ctx->start.len > 1 && bstr_eatstart0(&ctx->str, "`")) {
  ------------------
  |  Branch (356:9): [True: 7.51M, False: 11.2k]
  |  Branch (356:31): [True: 85, False: 7.51M]
  ------------------
  357|     85|        char endquote[2] = {ctx->str.start[0], '`'};
  358|     85|        ctx->str = bstr_cut(ctx->str, 1);
  359|     85|        int next = bstr_find(ctx->str, (bstr){endquote, 2});
  360|     85|        if (next < 0) {
  ------------------
  |  Branch (360:13): [True: 67, False: 18]
  ------------------
  361|     67|            MP_ERR(ctx, "Unterminated custom quote: ...>%.*s<.\n", BSTR_P(start));
  ------------------
  |  |   85|     67|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    134|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 67, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  362|     67|            return -1;
  363|     67|        }
  364|     18|        *out = bstr_splice(ctx->str, 0, next);
  365|     18|        ctx->str = bstr_cut(ctx->str, next+2);
  366|     18|        return 1;
  367|     85|    }
  368|       |
  369|  7.52M|    return read_token(ctx->str, &ctx->str, out) ? 1 : 0;
  ------------------
  |  Branch (369:12): [True: 6.41M, False: 1.10M]
  ------------------
  370|  7.52M|}
cmd.c:read_token:
  314|  10.2M|{
  315|  10.2M|    bstr t = bstr_lstrip(str);
  316|  10.2M|    int next = bstrcspn(t, WHITESPACE "#;");
  ------------------
  |  |  285|  10.2M|#define WHITESPACE " \f\n\r\t\v"
  ------------------
  317|  10.2M|    if (!next)
  ------------------
  |  Branch (317:9): [True: 3.65M, False: 6.63M]
  ------------------
  318|  3.65M|        return false;
  319|  6.63M|    *out_token = bstr_splice(t, 0, next);
  320|  6.63M|    *out_rest = bstr_cut(t, next);
  321|  6.63M|    return true;
  322|  10.2M|}
cmd.c:get_arg_count:
  573|  12.1k|{
  574|   133k|    for (int i = MP_CMD_DEF_MAX_ARGS - 1; i >= 0; i--) {
  ------------------
  |  |   26|  12.1k|#define MP_CMD_DEF_MAX_ARGS 11
  ------------------
  |  Branch (574:43): [True: 133k, False: 0]
  ------------------
  575|   133k|        if (cmd->args[i].type)
  ------------------
  |  Branch (575:13): [True: 12.1k, False: 121k]
  ------------------
  576|  12.1k|            return i + 1;
  577|   133k|    }
  578|      0|    return 0;
  579|  12.1k|}

mp_input_set_mouse_transform:
  864|     76|{
  865|     76|    input_lock(ictx);
  ------------------
  |  |   56|     76|#define input_lock(ictx)    mp_mutex_lock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  131|     76|#define mp_mutex_lock       pthread_mutex_lock
  |  |  ------------------
  ------------------
  866|     76|    ictx->mouse_mangle = dst || src;
  ------------------
  |  Branch (866:26): [True: 0, False: 76]
  |  Branch (866:33): [True: 0, False: 76]
  ------------------
  867|     76|    if (ictx->mouse_mangle) {
  ------------------
  |  Branch (867:9): [True: 0, False: 76]
  ------------------
  868|      0|        ictx->mouse_dst = *dst;
  869|      0|        ictx->mouse_src_mangle = !!src;
  870|      0|        if (ictx->mouse_src_mangle)
  ------------------
  |  Branch (870:13): [True: 0, False: 0]
  ------------------
  871|      0|            ictx->mouse_src = *src;
  872|      0|    }
  873|     76|    input_unlock(ictx);
  ------------------
  |  |   57|     76|#define input_unlock(ictx)  mp_mutex_unlock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  133|     76|#define mp_mutex_unlock     pthread_mutex_unlock
  |  |  ------------------
  ------------------
  874|     76|}
mp_input_get_touch_pos:
 1057|     40|{
 1058|     40|    input_lock(ictx);
  ------------------
  |  |   56|     40|#define input_lock(ictx)    mp_mutex_lock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  131|     40|#define mp_mutex_lock       pthread_mutex_lock
  |  |  ------------------
  ------------------
 1059|     40|    int num_touch_points = ictx->num_touch_points;
 1060|     40|    for (int i = 0; i < MPMIN(num_touch_points, count); i++) {
  ------------------
  |  |   44|     40|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 40]
  |  |  ------------------
  ------------------
  |  Branch (1060:21): [True: 0, False: 40]
  ------------------
 1061|      0|        x[i] = ictx->touch_points[i].x;
 1062|      0|        y[i] = ictx->touch_points[i].y;
 1063|      0|        id[i] = ictx->touch_points[i].id;
 1064|      0|    }
 1065|     40|    input_unlock(ictx);
  ------------------
  |  |   57|     40|#define input_unlock(ictx)  mp_mutex_unlock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  133|     40|#define mp_mutex_unlock     pthread_mutex_unlock
  |  |  ------------------
  ------------------
 1066|     40|    return num_touch_points;
 1067|     40|}
mp_input_get_mouse_event_counter:
 1108|     39|{
 1109|       |    // Make the frontend always display the mouse cursor (as long as it's not
 1110|       |    // forced invisible) if mouse input is desired.
 1111|     39|    input_lock(ictx);
  ------------------
  |  |   56|     39|#define input_lock(ictx)    mp_mutex_lock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  131|     39|#define mp_mutex_lock       pthread_mutex_lock
  |  |  ------------------
  ------------------
 1112|     39|    if (test_mouse_active(ictx, ictx->mouse_x, ictx->mouse_y))
  ------------------
  |  Branch (1112:9): [True: 0, False: 39]
  ------------------
 1113|      0|        ictx->mouse_event_counter++;
 1114|     39|    int ret = ictx->mouse_event_counter;
 1115|     39|    input_unlock(ictx);
  ------------------
  |  |   57|     39|#define input_unlock(ictx)  mp_mutex_unlock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  133|     39|#define mp_mutex_unlock     pthread_mutex_unlock
  |  |  ------------------
  ------------------
 1116|     39|    return ret;
 1117|     39|}
mp_input_get_delay:
 1174|  18.4k|{
 1175|  18.4k|    input_lock(ictx);
  ------------------
  |  |   56|  18.4k|#define input_lock(ictx)    mp_mutex_lock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  131|  18.4k|#define mp_mutex_lock       pthread_mutex_lock
  |  |  ------------------
  ------------------
 1176|  18.4k|    double seconds = INFINITY;
 1177|  18.4k|    adjust_max_wait_time(ictx, &seconds);
 1178|  18.4k|    input_unlock(ictx);
  ------------------
  |  |   57|  18.4k|#define input_unlock(ictx)  mp_mutex_unlock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  133|  18.4k|#define mp_mutex_unlock     pthread_mutex_unlock
  |  |  ------------------
  ------------------
 1179|  18.4k|    return seconds;
 1180|  18.4k|}
mp_input_read_cmd:
 1188|  18.4k|{
 1189|  18.4k|    input_lock(ictx);
  ------------------
  |  |   56|  18.4k|#define input_lock(ictx)    mp_mutex_lock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  131|  18.4k|#define mp_mutex_lock       pthread_mutex_lock
  |  |  ------------------
  ------------------
 1190|  18.4k|    struct mp_cmd *ret = queue_remove_head(&ictx->cmd_queue);
 1191|  18.4k|    if (!ret)
  ------------------
  |  Branch (1191:9): [True: 18.4k, False: 0]
  ------------------
 1192|  18.4k|        ret = check_autorepeat(ictx);
 1193|  18.4k|    if (ret && ret->mouse_move) {
  ------------------
  |  Branch (1193:9): [True: 0, False: 18.4k]
  |  Branch (1193:16): [True: 0, False: 0]
  ------------------
 1194|      0|        ictx->mouse_x = ret->mouse_x;
 1195|      0|        ictx->mouse_y = ret->mouse_y;
 1196|      0|    }
 1197|  18.4k|    input_unlock(ictx);
  ------------------
  |  |   57|  18.4k|#define input_unlock(ictx)  mp_mutex_unlock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  133|  18.4k|#define mp_mutex_unlock     pthread_mutex_unlock
  |  |  ------------------
  ------------------
 1198|  18.4k|    return ret;
 1199|  18.4k|}
mp_input_get_mouse_pos:
 1202|     61|{
 1203|     61|    input_lock(ictx);
  ------------------
  |  |   56|     61|#define input_lock(ictx)    mp_mutex_lock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  131|     61|#define mp_mutex_lock       pthread_mutex_lock
  |  |  ------------------
  ------------------
 1204|     61|    *x = ictx->mouse_x;
 1205|     61|    *y = ictx->mouse_y;
 1206|     61|    *hover = ictx->mouse_hover;
 1207|     61|    input_unlock(ictx);
  ------------------
  |  |   57|     61|#define input_unlock(ictx)  mp_mutex_unlock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  133|     61|#define mp_mutex_unlock     pthread_mutex_unlock
  |  |  ------------------
  ------------------
 1208|     61|}
mp_input_enable_section:
 1240|  17.4k|{
 1241|  17.4k|    bstr bname = bstr0(name);
 1242|  17.4k|    input_lock(ictx);
  ------------------
  |  |   56|  17.4k|#define input_lock(ictx)    mp_mutex_lock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  131|  17.4k|#define mp_mutex_lock       pthread_mutex_lock
  |  |  ------------------
  ------------------
 1243|  17.4k|    bname = normalize_section(ictx, bname);
 1244|       |
 1245|  17.4k|    disable_section(ictx, bname);
 1246|       |
 1247|  17.4k|    MP_TRACE(ictx, "enable section '%.*s'\n", BSTR_P(bname));
  ------------------
  |  |   90|  17.4k|#define MP_TRACE(obj, ...)      MP_MSG(obj, MSGL_TRACE, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  34.9k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 17.4k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1248|       |
 1249|  17.4k|    int top = ictx->num_active_sections;
 1250|  17.4k|    if (!(flags & MP_INPUT_ON_TOP)) {
  ------------------
  |  Branch (1250:9): [True: 17.4k, False: 0]
  ------------------
 1251|       |        // insert before the first top entry
 1252|  17.8k|        for (top = 0; top < ictx->num_active_sections; top++) {
  ------------------
  |  Branch (1252:23): [True: 392, False: 17.4k]
  ------------------
 1253|    392|            if (ictx->active_sections[top].flags & MP_INPUT_ON_TOP)
  ------------------
  |  Branch (1253:17): [True: 0, False: 392]
  ------------------
 1254|      0|                break;
 1255|    392|        }
 1256|  17.4k|    }
 1257|  17.4k|    MP_TARRAY_INSERT_AT(ictx, ictx->active_sections, ictx->num_active_sections,
  ------------------
  |  |  115|  17.4k|    do {                                            \
  |  |  116|  17.4k|        size_t at_ = (at);                          \
  |  |  117|  17.4k|        assert(at_ <= (idxvar));                    \
  |  |  118|  17.4k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  17.4k|    do {                                            \
  |  |  |  |   97|  17.4k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  17.4k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  17.4k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  17.4k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 17.0k, False: 392]
  |  |  |  |  ------------------
  |  |  |  |   99|  17.4k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  17.0k|    do {                                                        \
  |  |  |  |  |  |   89|  17.0k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  17.0k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  17.0k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  17.0k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  17.0k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  17.0k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  17.0k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  17.4k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  119|  17.4k|        memmove((p) + at_ + 1, (p) + at_,           \
  |  |  120|  17.4k|                ((idxvar) - at_) * sizeof((p)[0])); \
  |  |  121|  17.4k|        (idxvar)++;                                 \
  |  |  122|  17.4k|        (p)[at_] = (__VA_ARGS__);                   \
  |  |  123|  17.4k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (123:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1258|  17.4k|                        top, (struct active_section){bname, flags});
 1259|       |
 1260|  17.4k|    MP_TRACE(ictx, "active section stack:\n");
  ------------------
  |  |   90|  17.4k|#define MP_TRACE(obj, ...)      MP_MSG(obj, MSGL_TRACE, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  17.4k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1261|  35.3k|    for (int n = 0; n < ictx->num_active_sections; n++) {
  ------------------
  |  Branch (1261:21): [True: 17.8k, False: 17.4k]
  ------------------
 1262|  17.8k|        MP_TRACE(ictx, " %.*s %d\n", BSTR_P(ictx->active_sections[n].name),
  ------------------
  |  |   90|  17.8k|#define MP_TRACE(obj, ...)      MP_MSG(obj, MSGL_TRACE, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  35.7k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 17.8k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1263|  17.8k|                 ictx->active_sections[n].flags);
 1264|  17.8k|    }
 1265|       |
 1266|  17.4k|    input_unlock(ictx);
  ------------------
  |  |   57|  17.4k|#define input_unlock(ictx)  mp_mutex_unlock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  133|  17.4k|#define mp_mutex_unlock     pthread_mutex_unlock
  |  |  ------------------
  ------------------
 1267|  17.4k|}
mp_input_remove_sections_by_owner:
 1332|  22.2k|{
 1333|  22.2k|    input_lock(ictx);
  ------------------
  |  |   56|  22.2k|#define input_lock(ictx)    mp_mutex_lock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  131|  22.2k|#define mp_mutex_lock       pthread_mutex_lock
  |  |  ------------------
  ------------------
 1334|  62.4k|    for (int n = 0; n < ictx->num_sections; n++) {
  ------------------
  |  Branch (1334:21): [True: 40.1k, False: 22.2k]
  ------------------
 1335|  40.1k|        struct cmd_bind_section *bs = ictx->sections[n];
 1336|  40.1k|        if (bs->owner && owner && strcmp(bs->owner, owner) == 0) {
  ------------------
  |  Branch (1336:13): [True: 0, False: 40.1k]
  |  Branch (1336:26): [True: 0, False: 0]
  |  Branch (1336:35): [True: 0, False: 0]
  ------------------
 1337|      0|            disable_section(ictx, bs->section);
 1338|      0|            remove_binds(bs, false);
 1339|      0|            remove_binds(bs, true);
 1340|      0|        }
 1341|  40.1k|    }
 1342|  22.2k|    input_unlock(ictx);
  ------------------
  |  |   57|  22.2k|#define input_unlock(ictx)  mp_mutex_unlock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  133|  22.2k|#define mp_mutex_unlock     pthread_mutex_unlock
  |  |  ------------------
  ------------------
 1343|  22.2k|}
mp_input_init:
 1504|  17.0k|{
 1505|       |
 1506|  17.0k|    struct input_ctx *ictx = talloc_ptrtype(NULL, ictx);
  ------------------
  |  |   34|  17.0k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  17.0k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1507|  17.0k|    *ictx = (struct input_ctx){
 1508|  17.0k|        .global = global,
 1509|  17.0k|        .ar_state = -1,
 1510|  17.0k|        .log = mp_log_new(ictx, global->log, "input"),
 1511|  17.0k|        .mouse_section = bstr0("default"),
 1512|  17.0k|        .opts_cache = m_config_cache_alloc(ictx, global, &input_config),
 1513|  17.0k|        .wakeup_cb = wakeup_cb,
 1514|  17.0k|        .wakeup_ctx = wakeup_ctx,
 1515|  17.0k|        .active_sections = talloc_array(ictx, struct active_section, 0),
  ------------------
  |  |   29|  17.0k|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|  17.0k|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1516|  17.0k|        .touch_points = talloc_array(ictx, struct touch_point, 0),
  ------------------
  |  |   29|  17.0k|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|  17.0k|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1517|  17.0k|    };
 1518|       |
 1519|  17.0k|    ictx->opts = ictx->opts_cache->opts;
 1520|       |
 1521|  17.0k|    mp_mutex_init(&ictx->mutex);
 1522|       |
 1523|       |    // Setup default section, so that it does nothing.
 1524|  17.0k|    mp_input_enable_section(ictx, NULL, MP_INPUT_ALLOW_VO_DRAGGING |
 1525|  17.0k|                                        MP_INPUT_ALLOW_HIDE_CURSOR);
 1526|       |
 1527|  17.0k|    return ictx;
 1528|  17.0k|}
mp_input_update_opts:
 1549|  12.1k|{
 1550|  12.1k|    input_lock(ictx);
  ------------------
  |  |   56|  12.1k|#define input_lock(ictx)    mp_mutex_lock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  131|  12.1k|#define mp_mutex_lock       pthread_mutex_lock
  |  |  ------------------
  ------------------
 1551|  12.1k|    reload_opts(ictx, false);
 1552|  12.1k|    input_unlock(ictx);
  ------------------
  |  |   57|  12.1k|#define input_unlock(ictx)  mp_mutex_unlock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  133|  12.1k|#define mp_mutex_unlock     pthread_mutex_unlock
  |  |  ------------------
  ------------------
 1553|  12.1k|}
mp_input_load_config:
 1556|  12.1k|{
 1557|  12.1k|    input_lock(ictx);
  ------------------
  |  |   56|  12.1k|#define input_lock(ictx)    mp_mutex_lock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  131|  12.1k|#define mp_mutex_lock       pthread_mutex_lock
  |  |  ------------------
  ------------------
 1558|       |
 1559|  12.1k|    reload_opts(ictx, false);
 1560|       |
 1561|       |    // "Uncomment" the default key bindings in etc/input.conf and add them.
 1562|       |    // All lines that do not start with '# ' are parsed.
 1563|  12.1k|    bstr builtin = bstr0(builtin_input_conf);
 1564|  3.00M|    while (ictx->opts->builtin_bindings && builtin.len) {
  ------------------
  |  Branch (1564:12): [True: 3.00M, False: 0]
  |  Branch (1564:44): [True: 2.98M, False: 12.1k]
  ------------------
 1565|  2.98M|        bstr line = bstr_getline(builtin, &builtin);
 1566|  2.98M|        bstr_eatstart0(&line, "#");
 1567|  2.98M|        if (!bstr_startswith0(line, " "))
  ------------------
  |  Branch (1567:13): [True: 2.63M, False: 352k]
  ------------------
 1568|  2.63M|            parse_config(ictx, true, line, "<builtin>", (bstr){0});
 1569|  2.98M|    }
 1570|       |
 1571|  12.1k|    bool config_ok = false;
 1572|  12.1k|    if (ictx->opts->config_file && ictx->opts->config_file[0])
  ------------------
  |  Branch (1572:9): [True: 2.94k, False: 9.20k]
  |  Branch (1572:36): [True: 2.94k, False: 0]
  ------------------
 1573|  2.94k|        config_ok = parse_config_file(ictx, ictx->opts->config_file);
 1574|  12.1k|    if (!config_ok) {
  ------------------
  |  Branch (1574:9): [True: 11.1k, False: 957]
  ------------------
 1575|       |        // Try global conf dir
 1576|  11.1k|        void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|  11.1k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  11.1k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
 1577|  11.1k|        char **files = mp_find_all_config_files(tmp, ictx->global, "input.conf");
 1578|  11.1k|        for (int n = 0; files && files[n]; n++)
  ------------------
  |  Branch (1578:25): [True: 11.1k, False: 0]
  |  Branch (1578:34): [True: 0, False: 11.1k]
  ------------------
 1579|      0|            parse_config_file(ictx, files[n]);
 1580|  11.1k|        talloc_free(tmp);
  ------------------
  |  |   47|  11.1k|#define talloc_free                     ta_free
  ------------------
 1581|  11.1k|    }
 1582|       |
 1583|  12.1k|    bool use_gamepad = ictx->opts->use_gamepad;
 1584|  12.1k|    input_unlock(ictx);
  ------------------
  |  |   57|  12.1k|#define input_unlock(ictx)  mp_mutex_unlock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  133|  12.1k|#define mp_mutex_unlock     pthread_mutex_unlock
  |  |  ------------------
  ------------------
 1585|       |
 1586|       |#if HAVE_SDL2_GAMEPAD
 1587|       |    if (use_gamepad)
 1588|       |        mp_input_sdl_gamepad_add(ictx);
 1589|       |#else
 1590|  12.1k|    (void)use_gamepad;
 1591|  12.1k|#endif
 1592|  12.1k|}
mp_input_uninit:
 1612|  17.0k|{
 1613|  17.0k|    if (!ictx)
  ------------------
  |  Branch (1613:9): [True: 0, False: 17.0k]
  ------------------
 1614|      0|        return;
 1615|       |
 1616|  17.0k|    input_lock(ictx);
  ------------------
  |  |   56|  17.0k|#define input_lock(ictx)    mp_mutex_lock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  131|  17.0k|#define mp_mutex_lock       pthread_mutex_lock
  |  |  ------------------
  ------------------
 1617|  17.0k|    reload_opts(ictx, true);
 1618|  17.0k|    input_unlock(ictx);
  ------------------
  |  |   57|  17.0k|#define input_unlock(ictx)  mp_mutex_unlock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  133|  17.0k|#define mp_mutex_unlock     pthread_mutex_unlock
  |  |  ------------------
  ------------------
 1619|       |
 1620|  17.0k|    close_input_sources(ictx);
 1621|  17.0k|    clear_queue(&ictx->cmd_queue);
 1622|  17.0k|    talloc_free(ictx->current_down_cmd);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
 1623|  17.0k|    mp_mutex_destroy(&ictx->mutex);
  ------------------
  |  |  130|  17.0k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
 1624|  17.0k|    talloc_free(ictx);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
 1625|  17.0k|}
mp_input_parse_cmd:
 1645|  2.34M|{
 1646|  2.34M|    return mp_input_parse_cmd_str(ictx->log, str, location);
 1647|  2.34M|}
input.c:test_mouse_active:
 1086|     39|{
 1087|     39|    return test_mouse(ictx, x, y, MP_INPUT_ALLOW_HIDE_CURSOR);
 1088|     39|}
input.c:test_mouse:
 1070|     39|{
 1071|     39|    bool res = false;
 1072|     78|    for (int i = 0; i < ictx->num_active_sections; i++) {
  ------------------
  |  Branch (1072:21): [True: 39, False: 39]
  ------------------
 1073|     39|        struct active_section *as = &ictx->active_sections[i];
 1074|     39|        if (as->flags & rej_flags)
  ------------------
  |  Branch (1074:13): [True: 39, False: 0]
  ------------------
 1075|     39|            continue;
 1076|      0|        struct cmd_bind_section *s = get_bind_section(ictx, as->name);
 1077|      0|        if (s->mouse_area_set && test_rect(&s->mouse_area, x, y)) {
  ------------------
  |  Branch (1077:13): [True: 0, False: 0]
  |  Branch (1077:34): [True: 0, False: 0]
  ------------------
 1078|      0|            res = true;
 1079|      0|            break;
 1080|      0|        }
 1081|      0|    }
 1082|     39|    return res;
 1083|     39|}
input.c:adjust_max_wait_time:
 1121|  18.4k|{
 1122|  18.4k|    struct input_opts *opts = ictx->opts;
 1123|  18.4k|    if (ictx->last_key_down && opts->ar_rate > 0 && ictx->ar_state >= 0) {
  ------------------
  |  Branch (1123:9): [True: 0, False: 18.4k]
  |  Branch (1123:32): [True: 0, False: 0]
  |  Branch (1123:53): [True: 0, False: 0]
  ------------------
 1124|      0|        *time = MPMIN(*time, 1.0 / opts->ar_rate);
  ------------------
  |  |   44|      0|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1125|      0|        *time = MPMIN(*time, opts->ar_delay / 1000.0);
  ------------------
  |  |   44|      0|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1126|      0|    }
 1127|  18.4k|}
input.c:queue_remove_head:
  279|  18.4k|{
  280|  18.4k|    struct mp_cmd *ret = queue->first;
  281|  18.4k|    if (ret)
  ------------------
  |  Branch (281:9): [True: 0, False: 18.4k]
  ------------------
  282|      0|        queue_remove(queue, ret);
  283|  18.4k|    return ret;
  284|  18.4k|}
input.c:check_autorepeat:
 1140|  18.4k|{
 1141|  18.4k|    struct input_opts *opts = ictx->opts;
 1142|       |
 1143|       |    // No input : autorepeat ?
 1144|  18.4k|    if (opts->ar_rate <= 0 || !ictx->current_down_cmd || !ictx->last_key_down ||
  ------------------
  |  Branch (1144:9): [True: 0, False: 18.4k]
  |  Branch (1144:31): [True: 18.4k, False: 0]
  |  Branch (1144:58): [True: 0, False: 0]
  ------------------
 1145|  18.4k|        (ictx->last_key_down & MP_NO_REPEAT_KEY) ||
  ------------------
  |  |  235|      0|#define MP_NO_REPEAT_KEY       (1u<<23)
  ------------------
  |  Branch (1145:9): [True: 0, False: 0]
  ------------------
 1146|  18.4k|        !mp_input_is_repeatable_cmd(ictx->current_down_cmd))
  ------------------
  |  Branch (1146:9): [True: 0, False: 0]
  ------------------
 1147|  18.4k|        ictx->ar_state = -1; // disable
 1148|       |
 1149|  18.4k|    if (ictx->ar_state >= 0) {
  ------------------
  |  Branch (1149:9): [True: 0, False: 18.4k]
  ------------------
 1150|      0|        int64_t t = mp_time_ns();
 1151|      0|        if (ictx->last_ar + MP_TIME_S_TO_NS(2) < t)
  ------------------
  |  |   59|      0|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  |  Branch (1151:13): [True: 0, False: 0]
  ------------------
 1152|      0|            ictx->last_ar = t;
 1153|       |        // First time : wait delay
 1154|      0|        if (ictx->ar_state == 0
  ------------------
  |  Branch (1154:13): [True: 0, False: 0]
  ------------------
 1155|      0|            && (t - ictx->last_key_down_time) >= MP_TIME_MS_TO_NS(opts->ar_delay))
  ------------------
  |  |   60|      0|#define MP_TIME_MS_TO_NS(ms) ((ms) * INT64_C(1000000))
  ------------------
  |  Branch (1155:16): [True: 0, False: 0]
  ------------------
 1156|      0|        {
 1157|      0|            ictx->ar_state = 1;
 1158|      0|            ictx->last_ar = ictx->last_key_down_time + MP_TIME_MS_TO_NS(opts->ar_delay);
  ------------------
  |  |   60|      0|#define MP_TIME_MS_TO_NS(ms) ((ms) * INT64_C(1000000))
  ------------------
 1159|       |            // Then send rate / sec event
 1160|      0|        } else if (ictx->ar_state == 1
  ------------------
  |  Branch (1160:20): [True: 0, False: 0]
  ------------------
 1161|      0|                   && (t - ictx->last_ar) >= 1e9 / opts->ar_rate) {
  ------------------
  |  Branch (1161:23): [True: 0, False: 0]
  ------------------
 1162|      0|            ictx->last_ar += 1e9 / opts->ar_rate;
 1163|      0|        } else {
 1164|      0|            return NULL;
 1165|      0|        }
 1166|      0|        struct mp_cmd *ret = mp_cmd_clone(ictx->current_down_cmd);
 1167|      0|        ret->repeated = true;
 1168|      0|        return ret;
 1169|      0|    }
 1170|  18.4k|    return NULL;
 1171|  18.4k|}
input.c:disable_section:
 1219|  17.4k|{
 1220|  17.4k|    name = normalize_section(ictx, name);
 1221|       |
 1222|       |    // Remove old section, or make sure it's on top if re-enabled
 1223|  17.8k|    for (int i = ictx->num_active_sections - 1; i >= 0; i--) {
  ------------------
  |  Branch (1223:49): [True: 392, False: 17.4k]
  ------------------
 1224|    392|        struct active_section *as = &ictx->active_sections[i];
 1225|    392|        if (bstr_equals(as->name, name)) {
  ------------------
  |  Branch (1225:13): [True: 0, False: 392]
  ------------------
 1226|      0|            MP_TARRAY_REMOVE_AT(ictx->active_sections,
  ------------------
  |  |  143|      0|    do {                                            \
  |  |  144|      0|        size_t at_ = (at);                          \
  |  |  145|      0|        assert(at_ <= (idxvar));                    \
  |  |  146|      0|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|      0|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|      0|        (idxvar)--;                                 \
  |  |  149|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1227|      0|                                ictx->num_active_sections, i);
 1228|      0|        }
 1229|    392|    }
 1230|  17.4k|}
input.c:normalize_section:
 1214|  34.9k|{
 1215|  34.9k|    return get_bind_section(ictx, name)->section;
 1216|  34.9k|}
input.c:get_bind_section:
  384|  2.38M|{
  385|  2.38M|    if (section.len == 0)
  ------------------
  |  Branch (385:9): [True: 2.32M, False: 54.7k]
  ------------------
  386|  2.32M|        section = bstr0("default");
  387|  2.38M|    struct cmd_bind_section *bind_section = find_section(ictx, section);
  388|  2.38M|    if (bind_section)
  ------------------
  |  Branch (388:9): [True: 2.35M, False: 29.5k]
  ------------------
  389|  2.35M|        return bind_section;
  390|  29.5k|    bind_section = talloc_ptrtype(ictx, bind_section);
  ------------------
  |  |   34|  29.5k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  29.5k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  29.5k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  391|  29.5k|    *bind_section = (struct cmd_bind_section) {
  392|  29.5k|        .section = bstrdup(bind_section, section),
  393|  29.5k|        .mouse_area = {INT_MIN, INT_MIN, INT_MAX, INT_MAX},
  394|  29.5k|        .mouse_area_set = true,
  395|  29.5k|    };
  396|  29.5k|    MP_TARRAY_APPEND(ictx, ictx->sections, ictx->num_sections, bind_section);
  ------------------
  |  |  105|  29.5k|    do {                                            \
  |  |  106|  29.5k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  29.5k|    do {                                            \
  |  |  |  |   97|  29.5k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  29.5k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  29.5k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  29.5k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 17.1k, False: 12.4k]
  |  |  |  |  ------------------
  |  |  |  |   99|  29.5k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  17.1k|    do {                                                        \
  |  |  |  |  |  |   89|  17.1k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  17.1k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  17.1k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  17.1k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  17.1k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  17.1k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  17.1k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  29.5k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  29.5k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  29.5k|        (idxvar)++;                                 \
  |  |  109|  29.5k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  397|  29.5k|    return bind_section;
  398|  2.38M|}
input.c:find_section:
  373|  2.38M|{
  374|  2.42M|    for (int n = 0; n < ictx->num_sections; n++) {
  ------------------
  |  Branch (374:21): [True: 2.39M, False: 29.5k]
  ------------------
  375|  2.39M|        struct cmd_bind_section *bs = ictx->sections[n];
  376|  2.39M|        if (bstr_equals(section, bs->section))
  ------------------
  |  Branch (376:13): [True: 2.35M, False: 39.5k]
  ------------------
  377|  2.35M|            return bs;
  378|  2.39M|    }
  379|  29.5k|    return NULL;
  380|  2.38M|}
input.c:bind_dealloc:
 1287|  2.34M|{
 1288|  2.34M|    talloc_free(bind->cmd);
  ------------------
  |  |   47|  2.34M|#define talloc_free                     ta_free
  ------------------
 1289|  2.34M|    talloc_free(bind->location);
  ------------------
  |  |   47|  2.34M|#define talloc_free                     ta_free
  ------------------
 1290|  2.34M|    talloc_free(bind->desc);
  ------------------
  |  |   47|  2.34M|#define talloc_free                     ta_free
  ------------------
 1291|  2.34M|}
input.c:parse_config:
 1403|  2.63M|{
 1404|  2.63M|    int n_binds = 0;
 1405|  2.63M|    int line_no = 0;
 1406|  2.63M|    char *cur_loc = NULL;
 1407|       |
 1408|  5.30M|    while (data.len) {
  ------------------
  |  Branch (1408:12): [True: 2.66M, False: 2.63M]
  ------------------
 1409|  2.66M|        line_no++;
 1410|  2.66M|        if (cur_loc)
  ------------------
  |  Branch (1410:13): [True: 31.9k, False: 2.63M]
  ------------------
 1411|  31.9k|            talloc_free(cur_loc);
  ------------------
  |  |   47|  31.9k|#define talloc_free                     ta_free
  ------------------
 1412|  2.66M|        cur_loc = talloc_asprintf(NULL, "%s:%d", location, line_no);
  ------------------
  |  |   52|  2.66M|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|  2.66M|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 1413|       |
 1414|  2.66M|        bstr line = bstr_strip_linebreaks(bstr_getline(data, &data));
 1415|  2.66M|        line = bstr_lstrip(line);
 1416|  2.66M|        if (line.len == 0 || bstr_startswith0(line, "#"))
  ------------------
  |  Branch (1416:13): [True: 285k, False: 2.38M]
  |  Branch (1416:30): [True: 12.1k, False: 2.37M]
  ------------------
 1417|   297k|            continue;
 1418|  2.37M|        if (bstr_eatstart0(&line, "default-bindings ")) {
  ------------------
  |  Branch (1418:13): [True: 12.1k, False: 2.35M]
  ------------------
 1419|  12.1k|            bstr orig = line;
 1420|  12.1k|            bstr_split_tok(line, "#", &line, &(bstr){0});
 1421|  12.1k|            line = bstr_strip(line);
 1422|  12.1k|            if (bstr_equals0(line, "start")) {
  ------------------
  |  Branch (1422:17): [True: 12.1k, False: 0]
  ------------------
 1423|  12.1k|                builtin = true;
 1424|  12.1k|            } else {
 1425|      0|                MP_ERR(ictx, "Broken line: %.*s at %s\n", BSTR_P(orig), cur_loc);
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1426|      0|            }
 1427|  12.1k|            continue;
 1428|  12.1k|        }
 1429|  2.35M|        struct bstr command;
 1430|       |        // Find the key name starting a line
 1431|  2.35M|        struct bstr keyname = bstr_split(line, WHITESPACE, &command);
  ------------------
  |  |  285|  2.35M|#define WHITESPACE " \f\n\r\t\v"
  ------------------
 1432|  2.35M|        command = bstr_strip(command);
 1433|  2.35M|        if (command.len == 0) {
  ------------------
  |  Branch (1433:13): [True: 6.53k, False: 2.35M]
  ------------------
 1434|  6.53k|            MP_ERR(ictx, "Unfinished key binding: %.*s at %s\n", BSTR_P(line),
  ------------------
  |  |   85|  6.53k|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  13.0k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 6.53k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1435|  6.53k|                   cur_loc);
 1436|  6.53k|            continue;
 1437|  6.53k|        }
 1438|  2.35M|        char *name = bstrdup0(NULL, keyname);
 1439|  2.35M|        int keys[MP_MAX_KEY_DOWN];
 1440|  2.35M|        int num_keys = 0;
 1441|  2.35M|        if (!mp_input_get_keys_from_string(name, MP_MAX_KEY_DOWN, &num_keys, keys)) {
  ------------------
  |  |   59|  2.35M|#define MP_MAX_KEY_DOWN 16
  ------------------
  |  Branch (1441:13): [True: 3.25k, False: 2.34M]
  ------------------
 1442|  3.25k|            talloc_free(name);
  ------------------
  |  |   47|  3.25k|#define talloc_free                     ta_free
  ------------------
 1443|  3.25k|            MP_ERR(ictx, "Unknown key '%.*s' at %s\n", BSTR_P(keyname), cur_loc);
  ------------------
  |  |   85|  3.25k|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  6.50k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 3.25k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1444|  3.25k|            continue;
 1445|  3.25k|        }
 1446|  2.34M|        talloc_free(name);
  ------------------
  |  |   47|  2.34M|#define talloc_free                     ta_free
  ------------------
 1447|       |
 1448|  2.34M|        bstr section = restrict_section;
 1449|  2.34M|        if (!section.len) {
  ------------------
  |  Branch (1449:13): [True: 2.34M, False: 0]
  ------------------
 1450|  2.34M|            if (bstr_startswith0(command, "{")) {
  ------------------
  |  Branch (1450:17): [True: 37.8k, False: 2.31M]
  ------------------
 1451|  37.8k|                int p = bstrchr(command, '}');
 1452|  37.8k|                if (p != -1) {
  ------------------
  |  Branch (1452:21): [True: 36.8k, False: 986]
  ------------------
 1453|  36.8k|                    section = bstr_strip(bstr_splice(command, 1, p));
 1454|  36.8k|                    command = bstr_lstrip(bstr_cut(command, p + 1));
 1455|  36.8k|                }
 1456|  37.8k|            }
 1457|  2.34M|        }
 1458|       |
 1459|       |        // Print warnings if invalid commands are encountered.
 1460|  2.34M|        struct mp_cmd *cmd = mp_input_parse_cmd(ictx, command, cur_loc);
 1461|  2.34M|        const char *desc = NULL;
 1462|  2.34M|        if (cmd) {
  ------------------
  |  Branch (1462:13): [True: 2.33M, False: 17.2k]
  ------------------
 1463|  2.33M|            desc = cmd->desc;
 1464|  2.33M|            command = bstr0(cmd->original);
 1465|  2.33M|        }
 1466|       |
 1467|  2.34M|        bind_keys(ictx, builtin, section, keys, num_keys, command, cur_loc, desc);
 1468|  2.34M|        n_binds++;
 1469|       |
 1470|  2.34M|        talloc_free(cmd);
  ------------------
  |  |   47|  2.34M|#define talloc_free                     ta_free
  ------------------
 1471|  2.34M|    }
 1472|       |
 1473|  2.63M|    talloc_free(cur_loc);
  ------------------
  |  |   47|  2.63M|#define talloc_free                     ta_free
  ------------------
 1474|       |
 1475|  2.63M|    return n_binds;
 1476|  2.63M|}
input.c:reload_opts:
 1531|  41.3k|{
 1532|  41.3k|    m_config_cache_update(ictx->opts_cache);
 1533|       |
 1534|       |#if HAVE_COCOA
 1535|       |    struct input_opts *opts = ictx->opts;
 1536|       |
 1537|       |    if (ictx->using_cocoa_media_keys != (opts->use_media_keys && !shutdown)) {
 1538|       |        ictx->using_cocoa_media_keys = !ictx->using_cocoa_media_keys;
 1539|       |        if (ictx->using_cocoa_media_keys) {
 1540|       |            cocoa_init_media_keys();
 1541|       |        } else {
 1542|       |            cocoa_uninit_media_keys();
 1543|       |        }
 1544|       |    }
 1545|       |#endif
 1546|  41.3k|}
input.c:parse_config_file:
 1479|  2.94k|{
 1480|  2.94k|    bool r = false;
 1481|  2.94k|    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|  2.94k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  2.94k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
 1482|       |
 1483|  2.94k|    file = mp_get_user_path(tmp, ictx->global, file);
 1484|       |
 1485|  2.94k|    bstr data = stream_read_file2(file, tmp, STREAM_ORIGIN_DIRECT | STREAM_READ,
  ------------------
  |  |   47|  2.94k|#define STREAM_ORIGIN_DIRECT      (1 << 2) // passed from cmdline or loadfile
  ------------------
                  bstr data = stream_read_file2(file, tmp, STREAM_ORIGIN_DIRECT | STREAM_READ,
  ------------------
  |  |   41|  2.94k|#define STREAM_READ               0
  ------------------
 1486|  2.94k|                                  ictx->global, 1000000);
 1487|  2.94k|    if (data.start) {
  ------------------
  |  Branch (1487:9): [True: 957, False: 1.98k]
  ------------------
 1488|    957|        MP_VERBOSE(ictx, "Parsing input config file %s\n", file);
  ------------------
  |  |   88|    957|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    957|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1489|    957|        bstr_eatstart0(&data, "\xEF\xBB\xBF"); // skip BOM
 1490|    957|        int num = parse_config(ictx, false, data, file, (bstr){0});
 1491|    957|        MP_VERBOSE(ictx, "Input config file %s parsed: %d binds\n", file, num);
  ------------------
  |  |   88|    957|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    957|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1492|    957|        r = true;
 1493|  1.98k|    } else {
 1494|  1.98k|        MP_ERR(ictx, "Error reading input config file %s\n", file);
  ------------------
  |  |   85|  1.98k|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  1.98k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1495|  1.98k|    }
 1496|       |
 1497|  2.94k|    talloc_free(tmp);
  ------------------
  |  |   47|  2.94k|#define talloc_free                     ta_free
  ------------------
 1498|  2.94k|    return r;
 1499|  2.94k|}
input.c:clear_queue:
 1603|  17.0k|{
 1604|  17.0k|    while (queue->first) {
  ------------------
  |  Branch (1604:12): [True: 0, False: 17.0k]
  ------------------
 1605|      0|        struct mp_cmd *item = queue->first;
 1606|      0|        queue_remove(queue, item);
 1607|      0|        talloc_free(item);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 1608|      0|    }
 1609|  17.0k|}
input.c:bind_keys:
 1359|  2.34M|{
 1360|  2.34M|    struct cmd_bind_section *bs = get_bind_section(ictx, section);
 1361|  2.34M|    struct cmd_bind *bind = NULL;
 1362|       |
 1363|  2.34M|    mp_assert(num_keys <= MP_MAX_KEY_DOWN);
  ------------------
  |  |   41|  2.34M|#define mp_assert assert
  ------------------
 1364|       |
 1365|   221M|    for (int n = 0; n < bs->num_binds; n++) {
  ------------------
  |  Branch (1365:21): [True: 219M, False: 2.33M]
  ------------------
 1366|   219M|        struct cmd_bind *b = &bs->binds[n];
 1367|   219M|        if (bind_matches_key(b, num_keys, keys) && b->is_builtin == builtin) {
  ------------------
  |  Branch (1367:13): [True: 16.6k, False: 219M]
  |  Branch (1367:52): [True: 15.8k, False: 877]
  ------------------
 1368|  15.8k|            bind = b;
 1369|  15.8k|            break;
 1370|  15.8k|        }
 1371|   219M|    }
 1372|       |
 1373|  2.34M|    if (!bind) {
  ------------------
  |  Branch (1373:9): [True: 2.33M, False: 15.8k]
  ------------------
 1374|  2.33M|        struct cmd_bind empty = {{0}};
 1375|  2.33M|        MP_TARRAY_APPEND(bs, bs->binds, bs->num_binds, empty);
  ------------------
  |  |  105|  2.33M|    do {                                            \
  |  |  106|  2.33M|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  2.33M|    do {                                            \
  |  |  |  |   97|  2.33M|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  2.33M|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  2.33M|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  2.33M|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 109k, False: 2.22M]
  |  |  |  |  ------------------
  |  |  |  |   99|  2.33M|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|   109k|    do {                                                        \
  |  |  |  |  |  |   89|   109k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|   109k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|   109k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|   109k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|   109k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|   109k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|   109k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  2.33M|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  2.33M|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  2.33M|        (idxvar)++;                                 \
  |  |  109|  2.33M|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1376|  2.33M|        bind = &bs->binds[bs->num_binds - 1];
 1377|  2.33M|    }
 1378|       |
 1379|  2.34M|    bind_dealloc(bind);
 1380|       |
 1381|  2.34M|    *bind = (struct cmd_bind) {
 1382|  2.34M|        .cmd = bstrdup0(bs->binds, command),
 1383|  2.34M|        .location = talloc_strdup(bs->binds, loc),
  ------------------
  |  |   50|  2.34M|#define talloc_strdup                   ta_xstrdup
  ------------------
 1384|  2.34M|        .desc = talloc_strdup(bs->binds, desc),
  ------------------
  |  |   50|  2.34M|#define talloc_strdup                   ta_xstrdup
  ------------------
 1385|  2.34M|        .owner = bs,
 1386|  2.34M|        .is_builtin = builtin,
 1387|  2.34M|        .num_keys = num_keys,
 1388|  2.34M|    };
 1389|  2.34M|    memcpy(bind->keys, keys, num_keys * sizeof(bind->keys[0]));
 1390|  2.34M|    if (mp_msg_test(ictx->log, MSGL_DEBUG)) {
  ------------------
  |  Branch (1390:9): [True: 2.34M, False: 0]
  ------------------
 1391|  2.34M|        char *s = mp_input_get_key_combo_name(keys, num_keys);
 1392|  2.34M|        MP_TRACE(ictx, "add: section='%.*s' key='%s'%s cmd='%s' location='%s'\n",
  ------------------
  |  |   90|  2.34M|#define MP_TRACE(obj, ...)      MP_MSG(obj, MSGL_TRACE, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  9.39M|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 2.34M, False: 0]
  |  |  |  |  |  Branch (82:57): [True: 2.33M, False: 17.2k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1393|  2.34M|                 BSTR_P(bind->owner->section), s, bind->is_builtin ? " builtin" : "",
 1394|  2.34M|                 bind->cmd, bind->location);
 1395|  2.34M|        talloc_free(s);
  ------------------
  |  |   47|  2.34M|#define talloc_free                     ta_free
  ------------------
 1396|  2.34M|    }
 1397|  2.34M|}
input.c:bind_matches_key:
 1346|   219M|{
 1347|   219M|    if (bind->num_keys != num_keys)
  ------------------
  |  Branch (1347:9): [True: 31.9M, False: 187M]
  ------------------
 1348|  31.9M|        return false;
 1349|   188M|    for (int i = 0; i < num_keys; i++) {
  ------------------
  |  Branch (1349:21): [True: 188M, False: 16.6k]
  ------------------
 1350|   188M|        if (bind->keys[i] != keys[i])
  ------------------
  |  Branch (1350:13): [True: 187M, False: 1.29M]
  ------------------
 1351|   187M|            return false;
 1352|   188M|    }
 1353|  16.6k|    return true;
 1354|   187M|}
input.c:close_input_sources:
 1762|  17.0k|{
 1763|       |    // To avoid lock-order issues, we first remove each source from the context,
 1764|       |    // and then destroy it.
 1765|  17.0k|    while (1) {
  ------------------
  |  Branch (1765:12): [Folded - Ignored]
  ------------------
 1766|  17.0k|        input_lock(ictx);
  ------------------
  |  |   56|  17.0k|#define input_lock(ictx)    mp_mutex_lock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  131|  17.0k|#define mp_mutex_lock       pthread_mutex_lock
  |  |  ------------------
  ------------------
 1767|  17.0k|        struct mp_input_src *src = ictx->num_sources ? ictx->sources[0] : NULL;
  ------------------
  |  Branch (1767:36): [True: 0, False: 17.0k]
  ------------------
 1768|  17.0k|        input_unlock(ictx);
  ------------------
  |  |   57|  17.0k|#define input_unlock(ictx)  mp_mutex_unlock(&ictx->mutex)
  |  |  ------------------
  |  |  |  |  133|  17.0k|#define mp_mutex_unlock     pthread_mutex_unlock
  |  |  ------------------
  ------------------
 1769|  17.0k|        if (!src)
  ------------------
  |  Branch (1769:13): [True: 17.0k, False: 0]
  ------------------
 1770|  17.0k|            break;
 1771|      0|        input_src_kill(src);
 1772|      0|    }
 1773|  17.0k|}

mp_ipc_start_anon_client:
  269|  4.32k|{
  270|  4.32k|    int pair[2];
  271|  4.32k|    if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair))
  ------------------
  |  Branch (271:9): [True: 0, False: 4.32k]
  ------------------
  272|      0|        return false;
  273|  4.32k|    mp_set_cloexec(pair[0]);
  274|  4.32k|    mp_set_cloexec(pair[1]);
  275|       |
  276|  4.32k|    struct client_arg *client = talloc_ptrtype(NULL, client);
  ------------------
  |  |   34|  4.32k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  4.32k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  4.32k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  277|  4.32k|    *client = (struct client_arg){
  278|  4.32k|        .client = h,
  279|  4.32k|        .client_name = mpv_client_name(h),
  280|  4.32k|        .client_fd   = pair[1],
  281|  4.32k|        .close_client_fd = true,
  282|  4.32k|        .writable = true,
  283|  4.32k|    };
  284|       |
  285|  4.32k|    if (!ipc_start_client(ctx, client, false)) {
  ------------------
  |  Branch (285:9): [True: 0, False: 4.32k]
  ------------------
  286|      0|        close(pair[0]);
  287|      0|        close(pair[1]);
  288|      0|        return false;
  289|      0|    }
  290|       |
  291|  4.32k|    out_fd[0] = pair[0];
  292|  4.32k|    out_fd[1] = -1;
  293|  4.32k|    return true;
  294|  4.32k|}
mp_init_ipc:
  385|  12.1k|{
  386|  12.1k|    struct MPOpts *opts = mp_get_config_group(NULL, global, &mp_opt_root);
  387|       |
  388|  12.1k|    struct mp_ipc_ctx *arg = talloc_ptrtype(NULL, arg);
  ------------------
  |  |   34|  12.1k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  12.1k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  12.1k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  389|  12.1k|    *arg = (struct mp_ipc_ctx){
  390|  12.1k|        .log        = mp_log_new(arg, global->log, "ipc"),
  391|  12.1k|        .client_api = client_api,
  392|  12.1k|        .path       = mp_get_user_path(arg, global, opts->ipc_path),
  393|  12.1k|        .death_pipe = {-1, -1},
  394|  12.1k|    };
  395|       |
  396|  12.1k|    if (opts->ipc_client && opts->ipc_client[0]) {
  ------------------
  |  Branch (396:9): [True: 0, False: 12.1k]
  |  Branch (396:29): [True: 0, False: 0]
  ------------------
  397|      0|        int fd = -1;
  398|      0|        bstr str = bstr0(opts->ipc_client);
  399|      0|        if (bstr_eatstart0(&str, "fd://") && str.len) {
  ------------------
  |  Branch (399:13): [True: 0, False: 0]
  |  Branch (399:46): [True: 0, False: 0]
  ------------------
  400|      0|            long long ll = bstrtoll(str, &str, 0);
  401|      0|            if (!str.len && ll >= 0 && ll <= INT_MAX)
  ------------------
  |  Branch (401:17): [True: 0, False: 0]
  |  Branch (401:29): [True: 0, False: 0]
  |  Branch (401:40): [True: 0, False: 0]
  ------------------
  402|      0|                fd = ll;
  403|      0|        }
  404|      0|        if (fd < 0) {
  ------------------
  |  Branch (404:13): [True: 0, False: 0]
  ------------------
  405|      0|            MP_ERR(arg, "Invalid IPC client argument: '%s'\n", opts->ipc_client);
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  406|      0|        } else {
  407|      0|            ipc_start_client_json(arg, -1, fd);
  408|      0|        }
  409|      0|    }
  410|       |
  411|  12.1k|    talloc_free(opts);
  ------------------
  |  |   47|  12.1k|#define talloc_free                     ta_free
  ------------------
  412|       |
  413|  12.1k|    if (!arg->path || !arg->path[0])
  ------------------
  |  Branch (413:9): [True: 12.1k, False: 0]
  |  Branch (413:23): [True: 0, False: 0]
  ------------------
  414|  12.1k|        goto out;
  415|       |
  416|      0|    if (mp_make_wakeup_pipe(arg->death_pipe) < 0)
  ------------------
  |  Branch (416:9): [True: 0, False: 0]
  ------------------
  417|      0|        goto out;
  418|       |
  419|      0|    if (mp_thread_create(&arg->thread, ipc_thread, arg))
  ------------------
  |  |  211|      0|#define mp_thread_create(t, f, a) pthread_create(t, NULL, f, a)
  |  |  ------------------
  |  |  |  Branch (211:35): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  420|      0|        goto out;
  421|       |
  422|      0|    return arg;
  423|       |
  424|  12.1k|out:
  425|  12.1k|    if (arg->death_pipe[0] >= 0) {
  ------------------
  |  Branch (425:9): [True: 0, False: 12.1k]
  ------------------
  426|      0|        close(arg->death_pipe[0]);
  427|      0|        close(arg->death_pipe[1]);
  428|      0|    }
  429|  12.1k|    talloc_free(arg);
  ------------------
  |  |   47|  12.1k|#define talloc_free                     ta_free
  ------------------
  430|  12.1k|    return NULL;
  431|      0|}
mp_uninit_ipc:
  434|  17.0k|{
  435|  17.0k|    if (!arg)
  ------------------
  |  Branch (435:9): [True: 17.0k, False: 0]
  ------------------
  436|  17.0k|        return;
  437|       |
  438|      0|    (void)write(arg->death_pipe[1], &(char){0}, 1);
  439|      0|    mp_thread_join(arg->thread);
  ------------------
  |  |  212|      0|#define mp_thread_join(t)         pthread_join(t, NULL)
  ------------------
  440|       |
  441|      0|    close(arg->death_pipe[0]);
  442|      0|    close(arg->death_pipe[1]);
  443|      0|    talloc_free(arg);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  444|      0|}
ipc-unix.c:ipc_start_client:
  224|  4.32k|{
  225|  4.32k|    if (!client->client)
  ------------------
  |  Branch (225:9): [True: 0, False: 4.32k]
  ------------------
  226|      0|        client->client = mp_new_client(ctx->client_api, client->client_name);
  227|  4.32k|    if (!client->client)
  ------------------
  |  Branch (227:9): [True: 0, False: 4.32k]
  ------------------
  228|      0|        goto err;
  229|       |
  230|  4.32k|    client->log = mp_client_get_log(client->client);
  231|       |
  232|  4.32k|    mp_thread client_thr;
  233|  4.32k|    if (mp_thread_create(&client_thr, client_thread, client))
  ------------------
  |  |  211|  4.32k|#define mp_thread_create(t, f, a) pthread_create(t, NULL, f, a)
  |  |  ------------------
  |  |  |  Branch (211:35): [True: 0, False: 4.32k]
  |  |  ------------------
  ------------------
  234|      0|        goto err;
  235|  4.32k|    mp_thread_detach(client_thr);
  ------------------
  |  |  213|  4.32k|#define mp_thread_detach          pthread_detach
  ------------------
  236|       |
  237|  4.32k|    return true;
  238|       |
  239|      0|err:
  240|      0|    if (free_on_init_fail) {
  ------------------
  |  Branch (240:9): [True: 0, False: 0]
  ------------------
  241|      0|        if (client->client)
  ------------------
  |  Branch (241:13): [True: 0, False: 0]
  ------------------
  242|      0|            mpv_destroy(client->client);
  243|       |
  244|      0|        if (client->close_client_fd)
  ------------------
  |  Branch (244:13): [True: 0, False: 0]
  ------------------
  245|      0|            close(client->client_fd);
  246|      0|    }
  247|       |
  248|      0|    talloc_free(client);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  249|      0|    return false;
  250|  4.32k|}
ipc-unix.c:client_thread:
   94|  4.32k|{
   95|       |    // We don't use MSG_NOSIGNAL because the moldy fruit OS doesn't support it.
   96|  4.32k|    struct sigaction sa = { .sa_handler = SIG_IGN, .sa_flags = SA_RESTART };
   97|  4.32k|    sigfillset(&sa.sa_mask);
   98|  4.32k|    sigaction(SIGPIPE, &sa, NULL);
   99|       |
  100|  4.32k|    int rc;
  101|       |
  102|  4.32k|    struct client_arg *arg = p;
  103|  4.32k|    bstr client_msg = { talloc_strdup(NULL, ""), 0 };
  ------------------
  |  |   50|  4.32k|#define talloc_strdup                   ta_xstrdup
  ------------------
  104|       |
  105|  4.32k|    char *tname = talloc_asprintf(NULL, "ipc/%s", arg->client_name);
  ------------------
  |  |   52|  4.32k|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|  4.32k|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  106|  4.32k|    mp_thread_set_name(tname);
  107|  4.32k|    talloc_free(tname);
  ------------------
  |  |   47|  4.32k|#define talloc_free                     ta_free
  ------------------
  108|       |
  109|  4.32k|    int pipe_fd = mpv_get_wakeup_pipe(arg->client);
  110|  4.32k|    if (pipe_fd < 0) {
  ------------------
  |  Branch (110:9): [True: 0, False: 4.32k]
  ------------------
  111|      0|        MP_ERR(arg, "Could not get wakeup pipe\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  112|      0|        goto done;
  113|      0|    }
  114|       |
  115|  4.32k|    MP_VERBOSE(arg, "Client connected\n");
  ------------------
  |  |   88|  4.32k|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  4.32k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  116|       |
  117|  4.32k|    struct pollfd fds[2] = {
  118|  4.32k|        {.events = POLLIN, .fd = pipe_fd},
  119|  4.32k|        {.events = POLLIN, .fd = arg->client_fd},
  120|  4.32k|    };
  121|       |
  122|  4.32k|    fcntl(arg->client_fd, F_SETFL, fcntl(arg->client_fd, F_GETFL, 0) | O_NONBLOCK);
  123|       |
  124|  4.38k|    while (1) {
  ------------------
  |  Branch (124:12): [Folded - Ignored]
  ------------------
  125|  4.38k|        rc = poll(fds, 2, 0);
  126|  4.38k|        if (rc == 0)
  ------------------
  |  Branch (126:13): [True: 6, False: 4.37k]
  ------------------
  127|      6|            rc = poll(fds, 2, -1);
  128|  4.38k|        if (rc < 0) {
  ------------------
  |  Branch (128:13): [True: 0, False: 4.38k]
  ------------------
  129|      0|            MP_ERR(arg, "Poll error\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  130|      0|            continue;
  131|      0|        }
  132|       |
  133|  4.38k|        if (fds[0].revents & POLLIN) {
  ------------------
  |  Branch (133:13): [True: 4.32k, False: 60]
  ------------------
  134|  4.32k|            mp_flush_wakeup_pipe(pipe_fd);
  135|       |
  136|  4.32k|            while (1) {
  ------------------
  |  Branch (136:20): [Folded - Ignored]
  ------------------
  137|  4.32k|                mpv_event *event = mpv_wait_event(arg->client, 0);
  138|       |
  139|  4.32k|                if (event->event_id == MPV_EVENT_NONE)
  ------------------
  |  Branch (139:21): [True: 4.23k, False: 89]
  ------------------
  140|  4.23k|                    break;
  141|       |
  142|     89|                if (event->event_id == MPV_EVENT_SHUTDOWN)
  ------------------
  |  Branch (142:21): [True: 88, False: 1]
  ------------------
  143|     88|                    goto done;
  144|       |
  145|      1|                if (!arg->writable)
  ------------------
  |  Branch (145:21): [True: 0, False: 1]
  ------------------
  146|      0|                    continue;
  147|       |
  148|      1|                char *event_msg = mp_json_encode_event(event);
  149|      1|                if (!event_msg) {
  ------------------
  |  Branch (149:21): [True: 0, False: 1]
  ------------------
  150|      0|                    MP_ERR(arg, "Encoding error\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  151|      0|                    goto done;
  152|      0|                }
  153|       |
  154|      1|                rc = ipc_write_str(arg, event_msg);
  155|      1|                talloc_free(event_msg);
  ------------------
  |  |   47|      1|#define talloc_free                     ta_free
  ------------------
  156|      1|                if (rc < 0) {
  ------------------
  |  Branch (156:21): [True: 1, False: 0]
  ------------------
  157|      1|                    MP_ERR(arg, "Write error (%s)\n", mp_strerror(errno));
  ------------------
  |  |   85|      1|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      1|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  158|      1|                    goto done;
  159|      1|                }
  160|      1|            }
  161|  4.32k|        }
  162|       |
  163|  4.29k|        if (fds[1].revents & (POLLIN | POLLHUP | POLLNVAL)) {
  ------------------
  |  Branch (163:13): [True: 4.23k, False: 60]
  ------------------
  164|  4.39k|            while (1) {
  ------------------
  |  Branch (164:20): [Folded - Ignored]
  ------------------
  165|  4.39k|                char buf[128];
  166|  4.39k|                bstr append = { buf, 0 };
  167|       |
  168|  4.39k|                ssize_t bytes = read(arg->client_fd, buf, sizeof(buf));
  169|  4.39k|                if (bytes < 0) {
  ------------------
  |  Branch (169:21): [True: 0, False: 4.39k]
  ------------------
  170|      0|                    if (errno == EAGAIN)
  ------------------
  |  Branch (170:25): [True: 0, False: 0]
  ------------------
  171|      0|                        break;
  172|       |
  173|      0|                    MP_ERR(arg, "Read error (%s)\n", mp_strerror(errno));
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  174|      0|                    goto done;
  175|      0|                }
  176|       |
  177|  4.39k|                if (bytes == 0) {
  ------------------
  |  Branch (177:21): [True: 4.23k, False: 160]
  ------------------
  178|  4.23k|                    MP_VERBOSE(arg, "Client disconnected\n");
  ------------------
  |  |   88|  4.23k|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  4.23k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  179|  4.23k|                    goto done;
  180|  4.23k|                }
  181|       |
  182|    160|                append.len = bytes;
  183|       |
  184|    160|                bstr_xappend(NULL, &client_msg, append);
  185|       |
  186|    496|                while (bstrchr(client_msg, '\n') != -1) {
  ------------------
  |  Branch (186:24): [True: 336, False: 160]
  ------------------
  187|    336|                    char *reply_msg = mp_ipc_consume_next_command(arg->client,
  188|    336|                        NULL, &client_msg);
  189|       |
  190|    336|                    if (reply_msg && arg->writable) {
  ------------------
  |  Branch (190:25): [True: 0, False: 336]
  |  Branch (190:38): [True: 0, False: 0]
  ------------------
  191|      0|                        rc = ipc_write_str(arg, reply_msg);
  192|      0|                        if (rc < 0) {
  ------------------
  |  Branch (192:29): [True: 0, False: 0]
  ------------------
  193|      0|                            MP_ERR(arg, "Write error (%s)\n", mp_strerror(errno));
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  194|      0|                            talloc_free(reply_msg);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  195|      0|                            goto done;
  196|      0|                        }
  197|      0|                    }
  198|       |
  199|    336|                    talloc_free(reply_msg);
  ------------------
  |  |   47|    336|#define talloc_free                     ta_free
  ------------------
  200|    336|                }
  201|    160|            }
  202|  4.23k|        }
  203|  4.29k|    }
  204|       |
  205|  4.32k|done:
  206|  4.32k|    if (client_msg.len > 0)
  ------------------
  |  Branch (206:9): [True: 0, False: 4.32k]
  ------------------
  207|  4.32k|        MP_WARN(arg, "Ignoring unterminated command on disconnect.\n");
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  208|  4.32k|    talloc_free(client_msg.start);
  ------------------
  |  |   47|  4.32k|#define talloc_free                     ta_free
  ------------------
  209|  4.32k|    if (arg->close_client_fd)
  ------------------
  |  Branch (209:9): [True: 4.32k, False: 0]
  ------------------
  210|  4.32k|        close(arg->client_fd);
  211|  4.32k|    struct mpv_handle *h = arg->client;
  212|  4.32k|    bool quit = arg->quit_on_close;
  213|  4.32k|    talloc_free(arg);
  ------------------
  |  |   47|  4.32k|#define talloc_free                     ta_free
  ------------------
  214|  4.32k|    if (quit) {
  ------------------
  |  Branch (214:9): [True: 0, False: 4.32k]
  ------------------
  215|      0|        mpv_terminate_destroy(h);
  216|  4.32k|    } else {
  217|  4.32k|        mpv_destroy(h);
  218|  4.32k|    }
  219|  4.32k|    MP_THREAD_RETURN();
  ------------------
  |  |  209|  4.32k|#define MP_THREAD_RETURN() return NULL
  ------------------
  220|  4.32k|}
ipc-unix.c:ipc_write_str:
   67|      1|{
   68|      1|    size_t count = strlen(buf);
   69|      1|    while (count > 0) {
  ------------------
  |  Branch (69:12): [True: 1, False: 0]
  ------------------
   70|      1|        ssize_t rc = send(client->client_fd, buf, count, MSG_NOSIGNAL);
   71|      1|        if (rc <= 0) {
  ------------------
  |  Branch (71:13): [True: 1, False: 0]
  ------------------
   72|      1|            if (rc == 0)
  ------------------
  |  Branch (72:17): [True: 0, False: 1]
  ------------------
   73|      0|                return -1;
   74|       |
   75|      1|            if (errno == EBADF || errno == ENOTSOCK) {
  ------------------
  |  Branch (75:17): [True: 0, False: 1]
  |  Branch (75:35): [True: 0, False: 1]
  ------------------
   76|      0|                client->writable = false;
   77|      0|                return 0;
   78|      0|            }
   79|       |
   80|      1|            if (errno == EINTR || errno == EAGAIN)
  ------------------
  |  Branch (80:17): [True: 0, False: 1]
  |  Branch (80:35): [True: 0, False: 1]
  ------------------
   81|      0|                continue;
   82|       |
   83|      1|            return rc;
   84|      1|        }
   85|       |
   86|      0|        count -= rc;
   87|      0|        buf   += rc;
   88|      0|    }
   89|       |
   90|      0|    return 0;
   91|      1|}

mp_json_encode_event:
   93|      1|{
   94|      1|    void *ta_parent = talloc_new(NULL);
  ------------------
  |  |   40|      1|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|      1|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
   95|       |
   96|      1|    struct mpv_node event_node;
   97|      1|    if (event->event_id == MPV_EVENT_COMMAND_REPLY) {
  ------------------
  |  Branch (97:9): [True: 0, False: 1]
  ------------------
   98|      0|        event_node = (mpv_node){.format = MPV_FORMAT_NODE_MAP, .u.list = NULL};
   99|      0|        mpv_format_command_reply(ta_parent, event, &event_node);
  100|      1|    } else {
  101|      1|        mpv_event_to_node(&event_node, event);
  102|       |        // Abuse mpv_event_to_node() internals.
  103|      1|        talloc_steal(ta_parent, node_get_alloc(&event_node));
  ------------------
  |  |   38|      1|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      1|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  104|      1|    }
  105|       |
  106|      1|    char *output = talloc_strdup(NULL, "");
  ------------------
  |  |   50|      1|#define talloc_strdup                   ta_xstrdup
  ------------------
  107|      1|    json_write(&output, &event_node);
  108|      1|    output = ta_talloc_strdup_append(output, "\n");
  109|       |
  110|      1|    talloc_free(ta_parent);
  ------------------
  |  |   47|      1|#define talloc_free                     ta_free
  ------------------
  111|       |
  112|      1|    return output;
  113|      1|}
mp_ipc_consume_next_command:
  393|    336|{
  394|    336|    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|    336|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|    336|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  395|       |
  396|    336|    bstr rest;
  397|    336|    bstr line = bstr_getline(*buf, &rest);
  398|    336|    char *line0 = bstrto0(tmp, line);
  399|    336|    talloc_steal(tmp, buf->start);
  ------------------
  |  |   38|    336|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|    336|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  400|    336|    *buf = bstrdup(NULL, rest);
  401|       |
  402|    336|    json_skip_whitespace(&line0);
  403|       |
  404|    336|    char *reply_msg = NULL;
  405|    336|    if (line0[0] == '\0' || line0[0] == '#') {
  ------------------
  |  Branch (405:9): [True: 0, False: 336]
  |  Branch (405:29): [True: 0, False: 336]
  ------------------
  406|       |        // skip
  407|    336|    } else if (line0[0] == '{') {
  ------------------
  |  Branch (407:16): [True: 0, False: 336]
  ------------------
  408|      0|        reply_msg = json_execute_command(client, tmp, line0);
  409|    336|    } else {
  410|    336|        reply_msg = text_execute_command(client, tmp, line0);
  411|    336|    }
  412|       |
  413|    336|    talloc_steal(ctx, reply_msg);
  ------------------
  |  |   38|    336|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|    336|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  414|    336|    talloc_free(tmp);
  ------------------
  |  |   47|    336|#define talloc_free                     ta_free
  ------------------
  415|    336|    return reply_msg;
  416|    336|}
ipc.c:text_execute_command:
  386|    336|{
  387|    336|    mpv_command_string(client, src);
  388|       |
  389|    336|    return NULL;
  390|    336|}

mp_input_get_key_from_name:
  242|  2.53M|{
  243|  2.53M|    int modifiers = 0;
  244|  2.53M|    const char *p;
  245|  3.32M|    while ((p = strchr(name, '+'))) {
  ------------------
  |  Branch (245:12): [True: 815k, False: 2.50M]
  ------------------
  246|  1.76M|        for (const struct key_name *m = modifier_names; m->name; m++)
  ------------------
  |  Branch (246:57): [True: 1.74M, False: 25.5k]
  ------------------
  247|  1.74M|            if (!bstrcasecmp(bstr0(m->name),
  ------------------
  |  Branch (247:17): [True: 789k, False: 952k]
  ------------------
  248|  1.74M|                             (struct bstr){(char *)name, p - name})) {
  249|   789k|                modifiers |= m->key;
  250|   789k|                goto found;
  251|   789k|            }
  252|  25.5k|        if (!strcmp(name, "+"))
  ------------------
  |  Branch (252:13): [True: 24.5k, False: 1.06k]
  ------------------
  253|  24.5k|            return '+' + modifiers;
  254|  1.06k|        return -1;
  255|   789k|found:
  256|   789k|        name = p + 1;
  257|   789k|    }
  258|       |
  259|  2.50M|    struct bstr bname = bstr0(name);
  260|       |
  261|  2.50M|    struct bstr rest;
  262|  2.50M|    int code = bstr_decode_utf8(bname, &rest);
  263|  2.50M|    if (code >= 0 && rest.len == 0)
  ------------------
  |  Branch (263:9): [True: 2.50M, False: 1.81k]
  |  Branch (263:22): [True: 1.29M, False: 1.21M]
  ------------------
  264|  1.29M|        return mp_normalize_keycode(code + modifiers);
  265|       |
  266|  1.21M|    if (bstr_startswith0(bname, "0x")) {
  ------------------
  |  Branch (266:9): [True: 1, False: 1.21M]
  ------------------
  267|      1|        char *end;
  268|      1|        long long val = strtoll(name, &end, 16);
  269|      1|        if (name == end || val > INT_MAX || val < INT_MIN)
  ------------------
  |  Branch (269:13): [True: 0, False: 1]
  |  Branch (269:28): [True: 0, False: 1]
  |  Branch (269:45): [True: 0, False: 1]
  ------------------
  270|      0|            return -1;
  271|      1|        long long keycode = val + modifiers;
  272|      1|        if (keycode > INT_MAX || keycode < INT_MIN)
  ------------------
  |  Branch (272:13): [True: 0, False: 1]
  |  Branch (272:34): [True: 0, False: 1]
  ------------------
  273|      0|            return -1;
  274|      1|        return mp_normalize_keycode(keycode);
  275|      1|    }
  276|       |
  277|  70.2M|    for (int i = 0; key_names[i].name != NULL; i++) {
  ------------------
  |  Branch (277:21): [True: 70.2M, False: 2.19k]
  ------------------
  278|  70.2M|        if (strcasecmp(key_names[i].name, name) == 0)
  ------------------
  |  Branch (278:13): [True: 1.21M, False: 69.0M]
  ------------------
  279|  1.21M|            return mp_normalize_keycode(key_names[i].key + modifiers);
  280|  70.2M|    }
  281|       |
  282|  2.19k|    return -1;
  283|  1.21M|}
mp_input_get_key_combo_name:
  317|  2.34M|{
  318|  2.34M|    bstr dst = {0};
  319|  2.53M|    while (max > 0) {
  ------------------
  |  Branch (319:12): [True: 2.53M, False: 0]
  ------------------
  320|  2.53M|        mp_input_append_key_name(&dst, *keys);
  321|  2.53M|        if (--max && *++keys)
  ------------------
  |  Branch (321:13): [True: 182k, False: 2.34M]
  |  Branch (321:22): [True: 182k, False: 0]
  ------------------
  322|   182k|            bstr_xappend(NULL, &dst, bstr0("-"));
  323|  2.34M|        else
  324|  2.34M|            break;
  325|  2.53M|    }
  326|  2.34M|    return dst.start;
  327|  2.34M|}
mp_input_get_keys_from_string:
  331|  2.35M|{
  332|  2.35M|    char *end, *ptr;
  333|  2.35M|    int n = 0;
  334|       |
  335|  2.35M|    ptr = name;
  336|  2.35M|    n = 0;
  337|  2.53M|    for (end = strchr(ptr, '-'); ; end = strchr(ptr, '-')) {
  338|  2.53M|        if (end && end[1] != '\0') {
  ------------------
  |  Branch (338:13): [True: 207k, False: 2.32M]
  |  Branch (338:20): [True: 182k, False: 24.3k]
  ------------------
  339|   182k|            if (end[1] == '-')
  ------------------
  |  Branch (339:17): [True: 26, False: 182k]
  ------------------
  340|     26|                end = &end[1];
  341|   182k|            end[0] = '\0';
  342|   182k|        }
  343|  2.53M|        keys[n] = mp_input_get_key_from_name(ptr);
  344|  2.53M|        if (keys[n] < 0)
  ------------------
  |  Branch (344:13): [True: 3.25k, False: 2.53M]
  ------------------
  345|  3.25k|            return 0;
  346|  2.53M|        n++;
  347|  2.53M|        if (end && end[1] != '\0' && n < max_num_keys)
  ------------------
  |  Branch (347:13): [True: 207k, False: 2.32M]
  |  Branch (347:20): [True: 182k, False: 24.3k]
  |  Branch (347:38): [True: 182k, False: 0]
  ------------------
  348|   182k|            ptr = &end[1];
  349|  2.34M|        else
  350|  2.34M|            break;
  351|  2.53M|    }
  352|  2.34M|    *out_num_keys = n;
  353|  2.34M|    return 1;
  354|  2.35M|}
mp_print_key_list:
  357|    326|{
  358|    326|    mp_info(out, "\n");
  ------------------
  |  |   74|    326|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  359|  60.3k|    for (int i = 0; key_names[i].name != NULL; i++)
  ------------------
  |  Branch (359:21): [True: 59.9k, False: 326]
  ------------------
  360|  59.9k|        mp_info(out, "%s\n", key_names[i].name);
  ------------------
  |  |   74|  59.9k|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  361|    326|}
mp_get_key_list:
  364|     72|{
  365|     72|    char **list = NULL;
  366|     72|    int num = 0;
  367|  13.3k|    for (int i = 0; key_names[i].name != NULL; i++)
  ------------------
  |  Branch (367:21): [True: 13.2k, False: 72]
  ------------------
  368|  13.2k|        MP_TARRAY_APPEND(NULL, list, num, talloc_strdup(NULL, key_names[i].name));
  ------------------
  |  |  105|  13.2k|    do {                                            \
  |  |  106|  13.2k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  13.2k|    do {                                            \
  |  |  |  |   97|  13.2k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  13.2k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  13.2k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  13.2k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 504, False: 12.7k]
  |  |  |  |  ------------------
  |  |  |  |   99|  13.2k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|    504|    do {                                                        \
  |  |  |  |  |  |   89|    504|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|    504|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|    504|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|    504|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|    504|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|    504|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|    504|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  13.2k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  13.2k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  13.2k|        (idxvar)++;                                 \
  |  |  109|  13.2k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  369|     72|    MP_TARRAY_APPEND(NULL, list, num, NULL);
  ------------------
  |  |  105|     72|    do {                                            \
  |  |  106|     72|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|     72|    do {                                            \
  |  |  |  |   97|     72|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|     72|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|     72|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|     72|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 72]
  |  |  |  |  ------------------
  |  |  |  |   99|     72|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|     72|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|     72|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|     72|        (idxvar)++;                                 \
  |  |  109|     72|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  370|     72|    return list;
  371|     72|}
mp_normalize_keycode:
  374|  2.50M|{
  375|  2.50M|    if (keycode <= 0)
  ------------------
  |  Branch (375:9): [True: 1, False: 2.50M]
  ------------------
  376|      1|        return keycode;
  377|  2.50M|    int code = keycode & ~MP_KEY_MODIFIER_MASK;
  ------------------
  |  |  257|  2.50M|#define MP_KEY_MODIFIER_MASK (MP_KEY_MODIFIER_SHIFT | MP_KEY_MODIFIER_CTRL | \
  |  |  ------------------
  |  |  |  |  238|  2.50M|#define MP_KEY_MODIFIER_SHIFT  (1u<<24)
  |  |  ------------------
  |  |               #define MP_KEY_MODIFIER_MASK (MP_KEY_MODIFIER_SHIFT | MP_KEY_MODIFIER_CTRL | \
  |  |  ------------------
  |  |  |  |  239|  2.50M|#define MP_KEY_MODIFIER_CTRL   (1u<<25)
  |  |  ------------------
  |  |  258|  2.50M|                              MP_KEY_MODIFIER_ALT | MP_KEY_MODIFIER_META | \
  |  |  ------------------
  |  |  |  |  240|  2.50M|#define MP_KEY_MODIFIER_ALT    (1u<<26)
  |  |  ------------------
  |  |                                             MP_KEY_MODIFIER_ALT | MP_KEY_MODIFIER_META | \
  |  |  ------------------
  |  |  |  |  241|  2.50M|#define MP_KEY_MODIFIER_META   (1u<<27)
  |  |  ------------------
  |  |  259|  2.50M|                              MP_KEY_STATE_DOWN | MP_KEY_STATE_UP)
  |  |  ------------------
  |  |  |  |  246|  2.50M|#define MP_KEY_STATE_DOWN      (1u<<28)
  |  |  ------------------
  |  |                                             MP_KEY_STATE_DOWN | MP_KEY_STATE_UP)
  |  |  ------------------
  |  |  |  |  252|  2.50M|#define MP_KEY_STATE_UP        (1u<<29)
  |  |  ------------------
  ------------------
  378|  2.50M|    int mod = keycode & MP_KEY_MODIFIER_MASK;
  ------------------
  |  |  257|  2.50M|#define MP_KEY_MODIFIER_MASK (MP_KEY_MODIFIER_SHIFT | MP_KEY_MODIFIER_CTRL | \
  |  |  ------------------
  |  |  |  |  238|  2.50M|#define MP_KEY_MODIFIER_SHIFT  (1u<<24)
  |  |  ------------------
  |  |               #define MP_KEY_MODIFIER_MASK (MP_KEY_MODIFIER_SHIFT | MP_KEY_MODIFIER_CTRL | \
  |  |  ------------------
  |  |  |  |  239|  2.50M|#define MP_KEY_MODIFIER_CTRL   (1u<<25)
  |  |  ------------------
  |  |  258|  2.50M|                              MP_KEY_MODIFIER_ALT | MP_KEY_MODIFIER_META | \
  |  |  ------------------
  |  |  |  |  240|  2.50M|#define MP_KEY_MODIFIER_ALT    (1u<<26)
  |  |  ------------------
  |  |                                             MP_KEY_MODIFIER_ALT | MP_KEY_MODIFIER_META | \
  |  |  ------------------
  |  |  |  |  241|  2.50M|#define MP_KEY_MODIFIER_META   (1u<<27)
  |  |  ------------------
  |  |  259|  2.50M|                              MP_KEY_STATE_DOWN | MP_KEY_STATE_UP)
  |  |  ------------------
  |  |  |  |  246|  2.50M|#define MP_KEY_STATE_DOWN      (1u<<28)
  |  |  ------------------
  |  |                                             MP_KEY_STATE_DOWN | MP_KEY_STATE_UP)
  |  |  ------------------
  |  |  |  |  252|  2.50M|#define MP_KEY_STATE_UP        (1u<<29)
  |  |  ------------------
  ------------------
  379|       |    /* On normal keyboards shift changes the character code of non-special
  380|       |     * keys, so don't count the modifier separately for those. In other words
  381|       |     * we want to have "a" and "A" instead of "a" and "Shift+A"; but a separate
  382|       |     * shift modifier is still kept for special keys like arrow keys. */
  383|  2.50M|    if (code >= 32 && code < MP_KEY_BASE) {
  ------------------
  |  |   23|  2.48M|#define MP_KEY_BASE (1<<21)
  ------------------
  |  Branch (383:9): [True: 2.48M, False: 22.6k]
  |  Branch (383:23): [True: 1.30M, False: 1.17M]
  ------------------
  384|       |        /* Still try to support ASCII case-modifications properly. For example,
  385|       |         * we want to change "Shift+a" to "A", not "a". Doing this for unicode
  386|       |         * in general would require huge lookup tables, or a libc with proper
  387|       |         * unicode support, so we don't do that. */
  388|  1.30M|        if (code >= 'a' && code <= 'z' && (mod & MP_KEY_MODIFIER_SHIFT))
  ------------------
  |  |  238|   704k|#define MP_KEY_MODIFIER_SHIFT  (1u<<24)
  ------------------
  |  Branch (388:13): [True: 729k, False: 577k]
  |  Branch (388:28): [True: 704k, False: 24.4k]
  |  Branch (388:43): [True: 0, False: 704k]
  ------------------
  389|      0|            code &= 0x5F;
  390|  1.30M|        mod &= ~MP_KEY_MODIFIER_SHIFT;
  ------------------
  |  |  238|  1.30M|#define MP_KEY_MODIFIER_SHIFT  (1u<<24)
  ------------------
  391|  1.30M|    }
  392|  2.50M|    return code | mod;
  393|  2.50M|}
keycodes.c:mp_input_append_key_name:
  286|  2.53M|{
  287|  12.6M|    for (int i = 0; modifier_names[i].name; i++) {
  ------------------
  |  Branch (287:21): [True: 10.1M, False: 2.53M]
  ------------------
  288|  10.1M|        if (modifier_names[i].key & key) {
  ------------------
  |  Branch (288:13): [True: 789k, False: 9.33M]
  ------------------
  289|   789k|            bstr_xappend_asprintf(NULL, buf, "%s+", modifier_names[i].name);
  290|   789k|            key -= modifier_names[i].key;
  291|   789k|        }
  292|  10.1M|    }
  293|   313M|    for (int i = 0; key_names[i].name != NULL; i++) {
  ------------------
  |  Branch (293:21): [True: 312M, False: 1.31M]
  ------------------
  294|   312M|        if (key_names[i].key == key) {
  ------------------
  |  Branch (294:13): [True: 1.21M, False: 311M]
  ------------------
  295|  1.21M|            bstr_xappend_asprintf(NULL, buf, "%s", key_names[i].name);
  296|  1.21M|            return;
  297|  1.21M|        }
  298|   312M|    }
  299|       |
  300|  1.31M|    if (MP_KEY_IS_UNICODE(key)) {
  ------------------
  |  |   27|  1.31M|#define MP_KEY_IS_UNICODE(key) ((key) >= 32 && (key) <= 0x10FFFF)
  |  |  ------------------
  |  |  |  Branch (27:33): [True: 1.30M, False: 10.5k]
  |  |  |  Branch (27:48): [True: 1.30M, False: 0]
  |  |  ------------------
  ------------------
  301|  1.30M|        mp_append_utf8_bstr(NULL, buf, key);
  302|  1.30M|        return;
  303|  1.30M|    }
  304|       |
  305|       |    // Print the hex key code
  306|  10.5k|    bstr_xappend_asprintf(NULL, buf, "0x%x", key);
  307|  10.5k|}

bstrcmp:
   31|   724M|{
   32|   724M|    int ret = 0;
   33|   724M|    if (str1.len && str2.len)
  ------------------
  |  Branch (33:9): [True: 724M, False: 17.7k]
  |  Branch (33:21): [True: 724M, False: 17.1k]
  ------------------
   34|   724M|        ret = memcmp(str1.start, str2.start, MPMIN(str1.len, str2.len));
  ------------------
  |  |   44|   724M|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 408M, False: 316M]
  |  |  ------------------
  ------------------
   35|       |
   36|   724M|    if (!ret) {
  ------------------
  |  Branch (36:9): [True: 8.47M, False: 715M]
  ------------------
   37|  8.47M|        if (str1.len == str2.len)
  ------------------
  |  Branch (37:13): [True: 5.76M, False: 2.71M]
  ------------------
   38|  5.76M|            return 0;
   39|  2.71M|        else if (str1.len > str2.len)
  ------------------
  |  Branch (39:18): [True: 1.64M, False: 1.07M]
  ------------------
   40|  1.64M|            return 1;
   41|  1.07M|        else
   42|  1.07M|            return -1;
   43|  8.47M|    }
   44|   715M|    return ret;
   45|   724M|}
bstrcasecmp:
   48|  1.90M|{
   49|  1.90M|    int ret = 0;
   50|  1.90M|    if (str1.len && str2.len)
  ------------------
  |  Branch (50:9): [True: 1.81M, False: 91.0k]
  |  Branch (50:21): [True: 1.71M, False: 98.8k]
  ------------------
   51|  1.71M|        ret = strncasecmp(str1.start, str2.start, MPMIN(str1.len, str2.len));
  ------------------
  |  |   44|  1.71M|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 857k, False: 858k]
  |  |  ------------------
  ------------------
   52|       |
   53|  1.90M|    if (!ret) {
  ------------------
  |  Branch (53:9): [True: 1.01M, False: 888k]
  ------------------
   54|  1.01M|        if (str1.len == str2.len)
  ------------------
  |  Branch (54:13): [True: 810k, False: 207k]
  ------------------
   55|   810k|            return 0;
   56|   207k|        else if (str1.len > str2.len)
  ------------------
  |  Branch (56:18): [True: 98.9k, False: 108k]
  ------------------
   57|  98.9k|            return 1;
   58|   108k|        else
   59|   108k|            return -1;
   60|  1.01M|    }
   61|   888k|    return ret;
   62|  1.90M|}
bstrchr:
   65|  11.0M|{
   66|  11.0M|    if (!str.len)
  ------------------
  |  Branch (66:9): [True: 1.20k, False: 11.0M]
  ------------------
   67|  1.20k|        return -1;
   68|  11.0M|    unsigned char *pos = memchr(str.start, c, str.len);
   69|  11.0M|    return pos ? pos - str.start : -1;
  ------------------
  |  Branch (69:12): [True: 8.86M, False: 2.14M]
  ------------------
   70|  11.0M|}
bstrrchr:
   73|    275|{
   74|    275|    if (!str.len)
  ------------------
  |  Branch (74:9): [True: 0, False: 275]
  ------------------
   75|      0|        return -1;
   76|    275|#if HAVE_MEMRCHR
   77|    275|    unsigned char *pos = memrchr(str.start, c, str.len);
   78|    275|    return pos ? pos - str.start : -1;
  ------------------
  |  Branch (78:12): [True: 76, False: 199]
  ------------------
   79|       |#else
   80|       |    for (int i = str.len - 1; i >= 0; i--)
   81|       |        if (str.start[i] == c)
   82|       |            return i;
   83|       |    return -1;
   84|       |#endif
   85|    275|}
bstrcspn:
   88|  12.8M|{
   89|  12.8M|    int i;
   90|  72.0M|    for (i = 0; i < str.len; i++)
  ------------------
  |  Branch (90:17): [True: 70.6M, False: 1.39M]
  ------------------
   91|  70.6M|        if (strchr(reject, str.start[i]))
  ------------------
  |  Branch (91:13): [True: 11.4M, False: 59.2M]
  ------------------
   92|  11.4M|            break;
   93|  12.8M|    return i;
   94|  12.8M|}
bstrspn:
   97|  76.6k|{
   98|  76.6k|    int i;
   99|   312k|    for (i = 0; i < str.len; i++)
  ------------------
  |  Branch (99:17): [True: 271k, False: 41.6k]
  ------------------
  100|   271k|        if (!strchr(accept, str.start[i]))
  ------------------
  |  Branch (100:13): [True: 34.9k, False: 236k]
  ------------------
  101|  34.9k|            break;
  102|  76.6k|    return i;
  103|  76.6k|}
bstr_find:
  106|  1.22M|{
  107|  7.47M|    for (int i = 0; i < haystack.len; i++)
  ------------------
  |  Branch (107:21): [True: 6.57M, False: 901k]
  ------------------
  108|  6.57M|        if (bstr_startswith(bstr_splice(haystack, i, haystack.len), needle))
  ------------------
  |  Branch (108:13): [True: 320k, False: 6.25M]
  ------------------
  109|   320k|            return i;
  110|   901k|    return -1;
  111|  1.22M|}
bstr_lstrip:
  114|  44.5M|{
  115|  90.9M|    while (str.len && mp_isspace(*str.start)) {
  ------------------
  |  Branch (115:12): [True: 87.0M, False: 3.91M]
  |  Branch (115:23): [True: 46.4M, False: 40.5M]
  ------------------
  116|  46.4M|        str.start++;
  117|  46.4M|        str.len--;
  118|  46.4M|    }
  119|  44.5M|    return str;
  120|  44.5M|}
bstr_strip:
  123|  12.4M|{
  124|  12.4M|    str = bstr_lstrip(str);
  125|  50.0M|    while (str.len && mp_isspace(str.start[str.len - 1]))
  ------------------
  |  Branch (125:12): [True: 49.4M, False: 553k]
  |  Branch (125:23): [True: 37.5M, False: 11.8M]
  ------------------
  126|  37.5M|        str.len--;
  127|  12.4M|    return str;
  128|  12.4M|}
bstr_split:
  131|  2.35M|{
  132|  2.35M|    int start;
  133|  2.36M|    for (start = 0; start < str.len; start++)
  ------------------
  |  Branch (133:21): [True: 2.36M, False: 489]
  ------------------
  134|  2.36M|        if (!strchr(sep, str.start[start]))
  ------------------
  |  Branch (134:13): [True: 2.35M, False: 5.37k]
  ------------------
  135|  2.35M|            break;
  136|  2.35M|    str = bstr_cut(str, start);
  137|  2.35M|    int end = bstrcspn(str, sep);
  138|  2.35M|    if (rest) {
  ------------------
  |  Branch (138:9): [True: 2.35M, False: 275]
  ------------------
  139|  2.35M|        *rest = bstr_cut(str, end);
  140|  2.35M|    }
  141|  2.35M|    return bstr_splice(str, 0, end);
  142|  2.35M|}
bstr_split_tok:
  148|   603k|{
  149|   603k|    bstr bsep = bstr0(tok);
  150|   603k|    int pos = bstr_find(str, bsep);
  151|   603k|    if (pos < 0)
  ------------------
  |  Branch (151:9): [True: 316k, False: 286k]
  ------------------
  152|   316k|        pos = str.len;
  153|   603k|    *out_left = bstr_splice(str, 0, pos);
  154|   603k|    *out_right = bstr_cut(str, pos + bsep.len);
  155|   603k|    return pos != str.len;
  156|   603k|}
bstr_splice:
  159|  33.3M|{
  160|  33.3M|    if (start < 0)
  ------------------
  |  Branch (160:9): [True: 0, False: 33.3M]
  ------------------
  161|      0|        start += str.len;
  162|  33.3M|    if (end < 0)
  ------------------
  |  Branch (162:9): [True: 149, False: 33.3M]
  ------------------
  163|    149|        end += str.len;
  164|  33.3M|    end = MPMIN(end, str.len);
  ------------------
  |  |   44|  33.3M|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 764k, False: 32.6M]
  |  |  ------------------
  ------------------
  165|  33.3M|    start = MPMAX(start, 0);
  ------------------
  |  |   43|  33.3M|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 5.52M, False: 27.8M]
  |  |  ------------------
  ------------------
  166|  33.3M|    end = MPMAX(end, start);
  ------------------
  |  |   43|  33.3M|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 32.8M, False: 547k]
  |  |  ------------------
  ------------------
  167|  33.3M|    str.start += start;
  168|  33.3M|    str.len = end - start;
  169|  33.3M|    return str;
  170|  33.3M|}
bstrtoll:
  173|   145k|{
  174|   145k|    str = bstr_lstrip(str);
  175|   145k|    char buf[51];
  176|   145k|    int len = MPMIN(str.len, 50);
  ------------------
  |  |   44|   145k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 531, False: 145k]
  |  |  ------------------
  ------------------
  177|   145k|    memcpy(buf, str.start, len);
  178|   145k|    buf[len] = 0;
  179|   145k|    char *endptr;
  180|   145k|    long long r = strtoll(buf, &endptr, base);
  181|   145k|    if (rest)
  ------------------
  |  Branch (181:9): [True: 145k, False: 0]
  ------------------
  182|   145k|        *rest = bstr_cut(str, endptr - buf);
  183|   145k|    return r;
  184|   145k|}
bstrtod:
  187|  1.20M|{
  188|  1.20M|    str = bstr_lstrip(str);
  189|  1.20M|    char buf[101];
  190|  1.20M|    int len = MPMIN(str.len, 100);
  ------------------
  |  |   44|  1.20M|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 8, False: 1.20M]
  |  |  ------------------
  ------------------
  191|  1.20M|    memcpy(buf, str.start, len);
  192|  1.20M|    buf[len] = 0;
  193|  1.20M|    char *endptr;
  194|  1.20M|    double r = strtod(buf, &endptr);
  195|  1.20M|    if (rest)
  ------------------
  |  Branch (195:9): [True: 1.20M, False: 0]
  ------------------
  196|  1.20M|        *rest = bstr_cut(str, endptr - buf);
  197|  1.20M|    return r;
  198|  1.20M|}
bstr_splitchar:
  201|  9.35M|{
  202|  9.35M|    int pos = bstrchr(str, c);
  203|  9.35M|    if (pos < 0)
  ------------------
  |  Branch (203:9): [True: 764k, False: 8.59M]
  ------------------
  204|   764k|        pos = str.len;
  205|  9.35M|    if (rest)
  ------------------
  |  Branch (205:9): [True: 9.35M, False: 18.4E]
  ------------------
  206|  9.35M|        *rest = bstr_cut(str, pos + 1);
  207|  9.35M|    return bstr_splice(str, 0, pos + 1);
  208|  9.35M|}
bstr_strip_linebreaks:
  211|  4.32M|{
  212|  4.32M|    if (bstr_endswith0(str, "\r\n")) {
  ------------------
  |  Branch (212:9): [True: 1.00k, False: 4.32M]
  ------------------
  213|  1.00k|        str = bstr_splice(str, 0, str.len - 2);
  214|  4.32M|    } else if (bstr_endswith0(str, "\n")) {
  ------------------
  |  Branch (214:16): [True: 4.32M, False: 1.01k]
  ------------------
  215|  4.32M|        str = bstr_splice(str, 0, str.len - 1);
  216|  4.32M|    }
  217|  4.32M|    return str;
  218|  4.32M|}
bstr_eatstart:
  221|  69.7M|{
  222|  69.7M|    if (!bstr_startswith(*s, prefix))
  ------------------
  |  Branch (222:9): [True: 62.7M, False: 6.90M]
  ------------------
  223|  62.7M|        return false;
  224|  6.90M|    *s = bstr_cut(*s, prefix.len);
  225|  6.90M|    return true;
  226|  69.7M|}
bstr_sscanf:
  243|   549k|{
  244|   549k|    char *ptr = bstrdup0(NULL, str);
  245|   549k|    va_list va;
  246|   549k|    va_start(va, format);
  247|   549k|    int ret = vsscanf(ptr, format, va);
  248|   549k|    va_end(va);
  249|   549k|    talloc_free(ptr);
  ------------------
  |  |   47|   549k|#define talloc_free                     ta_free
  ------------------
  250|   549k|    return ret;
  251|   549k|}
bstr_parse_utf8_code_length:
  254|  45.8k|{
  255|  45.8k|    if (b < 128)
  ------------------
  |  Branch (255:9): [True: 0, False: 45.8k]
  ------------------
  256|      0|        return 1;
  257|  45.8k|    int bytes = 7 - mp_log2(b ^ 255);
  258|  45.8k|    return (bytes >= 2 && bytes <= 4) ? bytes : -1;
  ------------------
  |  Branch (258:13): [True: 28.4k, False: 17.4k]
  |  Branch (258:27): [True: 20.8k, False: 7.52k]
  ------------------
  259|  45.8k|}
bstr_decode_utf8:
  262|  28.4M|{
  263|  28.4M|    if (s.len == 0)
  ------------------
  |  Branch (263:9): [True: 69, False: 28.4M]
  ------------------
  264|     69|        return -1;
  265|  28.4M|    unsigned int codepoint = s.start[0];
  266|  28.4M|    s.start++; s.len--;
  267|  28.4M|    if (codepoint >= 128) {
  ------------------
  |  Branch (267:9): [True: 45.6k, False: 28.4M]
  ------------------
  268|  45.6k|        int bytes = bstr_parse_utf8_code_length(codepoint);
  269|  45.6k|        if (bytes < 1 || s.len < bytes - 1)
  ------------------
  |  Branch (269:13): [True: 24.8k, False: 20.8k]
  |  Branch (269:26): [True: 1.69k, False: 19.1k]
  ------------------
  270|  26.5k|            return -1;
  271|  19.1k|        codepoint &= 127 >> bytes;
  272|  33.7k|        for (int n = 1; n < bytes; n++) {
  ------------------
  |  Branch (272:25): [True: 24.8k, False: 8.87k]
  ------------------
  273|  24.8k|            int tmp = (unsigned char)s.start[0];
  274|  24.8k|            if ((tmp & 0xC0) != 0x80)
  ------------------
  |  Branch (274:17): [True: 10.2k, False: 14.5k]
  ------------------
  275|  10.2k|                return -1;
  276|  14.5k|            codepoint = (codepoint << 6) | (tmp & ~0xC0);
  277|  14.5k|            s.start++; s.len--;
  278|  14.5k|        }
  279|  8.87k|        if (codepoint > 0x10FFFF || (codepoint >= 0xD800 && codepoint <= 0xDFFF))
  ------------------
  |  Branch (279:13): [True: 192, False: 8.68k]
  |  Branch (279:38): [True: 2.36k, False: 6.31k]
  |  Branch (279:61): [True: 525, False: 1.84k]
  ------------------
  280|    717|            return -1;
  281|       |        // Overlong sequences - check taken from libavcodec.
  282|       |        // (The only reason we even bother with this is to make libavcodec's
  283|       |        //  retarded subtitle utf-8 check happy.)
  284|  8.15k|        unsigned int min = bytes == 2 ? 0x80 : 1 << (5 * bytes - 4);
  ------------------
  |  Branch (284:28): [True: 4.35k, False: 3.79k]
  ------------------
  285|  8.15k|        if (codepoint < min)
  ------------------
  |  Branch (285:13): [True: 37, False: 8.11k]
  ------------------
  286|     37|            return -1;
  287|  8.15k|    }
  288|  28.4M|    if (out_next)
  ------------------
  |  Branch (288:9): [True: 28.4M, False: 0]
  ------------------
  289|  28.4M|        *out_next = s;
  290|  28.4M|    return codepoint;
  291|  28.4M|}
bstr_validate_utf8:
  305|    525|{
  306|  4.69k|    while (s.len) {
  ------------------
  |  Branch (306:12): [True: 4.36k, False: 333]
  ------------------
  307|  4.36k|        if (bstr_decode_utf8(s, &s) < 0) {
  ------------------
  |  Branch (307:13): [True: 192, False: 4.17k]
  ------------------
  308|       |            // Try to guess whether the sequence was just cut-off.
  309|    192|            unsigned int codepoint = (unsigned char)s.start[0];
  310|    192|            int bytes = bstr_parse_utf8_code_length(codepoint);
  311|    192|            if (bytes > 1 && s.len < 6) {
  ------------------
  |  Branch (311:17): [True: 62, False: 130]
  |  Branch (311:30): [True: 1, False: 61]
  ------------------
  312|       |                // Manually check validity of left bytes
  313|      1|                for (int n = 1; n < bytes; n++) {
  ------------------
  |  Branch (313:33): [True: 1, False: 0]
  ------------------
  314|      1|                    if (n >= s.len) {
  ------------------
  |  Branch (314:25): [True: 0, False: 1]
  ------------------
  315|       |                        // Everything valid until now - just cut off.
  316|      0|                        return -(bytes - s.len);
  317|      0|                    }
  318|      1|                    int tmp = (unsigned char)s.start[n];
  319|      1|                    if ((tmp & 0xC0) != 0x80)
  ------------------
  |  Branch (319:25): [True: 1, False: 0]
  ------------------
  320|      1|                        break;
  321|      1|                }
  322|      1|            }
  323|    192|            return -8;
  324|    192|        }
  325|  4.36k|    }
  326|    333|    return 0;
  327|    525|}
bstr_sanitize_utf8_latin1:
  330|     71|{
  331|     71|    bstr new = {0};
  332|     71|    bstr left = s;
  333|     71|    unsigned char *first_ok = s.start;
  334|  11.5k|    while (left.len) {
  ------------------
  |  Branch (334:12): [True: 11.5k, False: 71]
  ------------------
  335|  11.5k|        int r = bstr_decode_utf8(left, &left);
  336|  11.5k|        if (r < 0) {
  ------------------
  |  Branch (336:13): [True: 5.83k, False: 5.67k]
  ------------------
  337|  5.83k|            bstr_xappend(talloc_ctx, &new, (bstr){first_ok, left.start - first_ok});
  338|  5.83k|            mp_append_utf8_bstr(talloc_ctx, &new, (unsigned char)left.start[0]);
  339|  5.83k|            left.start += 1;
  340|  5.83k|            left.len -= 1;
  341|  5.83k|            first_ok = left.start;
  342|  5.83k|        }
  343|  11.5k|    }
  344|     71|    if (!new.start)
  ------------------
  |  Branch (344:9): [True: 0, False: 71]
  ------------------
  345|      0|        return s;
  346|     71|    if (first_ok != left.start)
  ------------------
  |  Branch (346:9): [True: 39, False: 32]
  ------------------
  347|     39|        bstr_xappend(talloc_ctx, &new, (bstr){first_ok, left.start - first_ok});
  348|     71|    return new;
  349|     71|}
bstr_xappend:
  365|  18.2M|{
  366|  18.2M|    if (!append.len)
  ------------------
  |  Branch (366:9): [True: 35.9k, False: 18.2M]
  ------------------
  367|  35.9k|        return;
  368|  18.2M|    resize_append(talloc_ctx, s, append.len + 1);
  369|  18.2M|    memmove(s->start + s->len, append.start, append.len);
  370|  18.2M|    s->len += append.len;
  371|  18.2M|    s->start[s->len] = '\0';
  372|  18.2M|}
bstr_xappend_asprintf:
  375|  2.30M|{
  376|  2.30M|    va_list ap;
  377|  2.30M|    va_start(ap, fmt);
  378|  2.30M|    int ret = bstr_xappend_vasprintf(talloc_ctx, s, fmt, ap);
  379|  2.30M|    va_end(ap);
  380|  2.30M|    return ret;
  381|  2.30M|}
bstr_xappend_vasprintf:
  385|  4.35M|{
  386|  4.35M|    int size;
  387|  4.35M|    va_list copy;
  388|  4.35M|    va_copy(copy, ap);
  389|  4.35M|    size_t avail = talloc_get_size(s->start) - s->len;
  ------------------
  |  |   45|  4.35M|#define talloc_get_size                 ta_get_size
  ------------------
  390|  4.35M|    char *dest = s->start ? s->start + s->len : NULL;
  ------------------
  |  Branch (390:18): [True: 2.91M, False: 1.43M]
  ------------------
  391|  4.35M|    size = vsnprintf(dest, avail, fmt, copy);
  392|  4.35M|    va_end(copy);
  393|       |
  394|  4.35M|    if (size < 0)
  ------------------
  |  Branch (394:9): [True: 0, False: 4.35M]
  ------------------
  395|      0|        return size;
  396|       |
  397|  4.35M|    if (avail < 1 || size + 1 > avail) {
  ------------------
  |  Branch (397:9): [True: 1.43M, False: 2.91M]
  |  Branch (397:22): [True: 646k, False: 2.27M]
  ------------------
  398|  2.08M|        resize_append(talloc_ctx, s, size + 1);
  399|  2.08M|        vsnprintf(s->start + s->len, size + 1, fmt, ap);
  400|  2.08M|    }
  401|  4.35M|    s->len += size;
  402|  4.35M|    return size;
  403|  4.35M|}
bstr_case_startswith:
  406|  4.17k|{
  407|  4.17k|    struct bstr start = bstr_splice(s, 0, prefix.len);
  408|  4.17k|    return start.len == prefix.len && bstrcasecmp(start, prefix) == 0;
  ------------------
  |  Branch (408:12): [True: 4.12k, False: 52]
  |  Branch (408:39): [True: 0, False: 4.12k]
  ------------------
  409|  4.17k|}
bstr_get_ext:
  426|    275|{
  427|    275|    int dotpos = bstrrchr(s, '.');
  428|    275|    if (dotpos < 0)
  ------------------
  |  Branch (428:9): [True: 199, False: 76]
  ------------------
  429|    199|        return (struct bstr){NULL, 0};
  430|     76|    return bstr_splice(s, dotpos + 1, s.len);
  431|    275|}
bstr_decode_hex:
  446|    751|{
  447|    751|    if (!out)
  ------------------
  |  Branch (447:9): [True: 0, False: 751]
  ------------------
  448|      0|        return false;
  449|       |
  450|    751|    char *arr = talloc_array(talloc_ctx, char, hex.len / 2);
  ------------------
  |  |   29|    751|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|    751|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    751|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  451|    751|    int len = 0;
  452|       |
  453|   133k|    while (hex.len >= 2) {
  ------------------
  |  Branch (453:12): [True: 133k, False: 710]
  ------------------
  454|   133k|        int a = h_to_i(hex.start[0]);
  455|   133k|        int b = h_to_i(hex.start[1]);
  456|   133k|        hex = bstr_splice(hex, 2, hex.len);
  457|       |
  458|   133k|        if (a < 0 || b < 0) {
  ------------------
  |  Branch (458:13): [True: 25, False: 133k]
  |  Branch (458:22): [True: 16, False: 133k]
  ------------------
  459|     41|            talloc_free(arr);
  ------------------
  |  |   47|     41|#define talloc_free                     ta_free
  ------------------
  460|     41|            return false;
  461|     41|        }
  462|       |
  463|   133k|        arr[len++] = (a << 4) | b;
  464|   133k|    }
  465|       |
  466|    710|    *out = (struct bstr){ .start = arr, .len = len };
  467|    710|    return true;
  468|    751|}
bstr.c:resize_append:
  352|  20.3M|{
  353|  20.3M|    size_t size = talloc_get_size(s->start);
  ------------------
  |  |   45|  20.3M|#define talloc_get_size                 ta_get_size
  ------------------
  354|  20.3M|    mp_assert(s->len <= size);
  ------------------
  |  |   41|  20.3M|#define mp_assert assert
  ------------------
  355|  20.3M|    if (append_min > size - s->len) {
  ------------------
  |  Branch (355:9): [True: 3.53M, False: 16.7M]
  ------------------
  356|  3.53M|        if (append_min < size)
  ------------------
  |  Branch (356:13): [True: 568k, False: 2.97M]
  ------------------
  357|   568k|            append_min = size; // preallocate in power of 2s
  358|  3.53M|        if (size >= SIZE_MAX / 2 || append_min >= SIZE_MAX / 2)
  ------------------
  |  Branch (358:13): [True: 0, False: 3.53M]
  |  Branch (358:37): [True: 0, False: 3.53M]
  ------------------
  359|      0|            abort(); // oom
  360|  3.53M|        s->start = talloc_realloc_size(talloc_ctx, s->start, size + append_min);
  ------------------
  |  |   39|  3.53M|#define talloc_realloc_size             ta_xrealloc_size
  |  |  ------------------
  |  |  |  |  158|  3.53M|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|  3.53M|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|  3.53M|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|  3.53M|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  361|  3.53M|    }
  362|  20.3M|}
bstr.c:h_to_i:
  434|   266k|{
  435|   266k|    if (c >= '0' && c <= '9')
  ------------------
  |  Branch (435:9): [True: 266k, False: 14]
  |  Branch (435:21): [True: 185k, False: 80.5k]
  ------------------
  436|   185k|        return c - '0';
  437|  80.5k|    if (c >= 'a' && c <= 'f')
  ------------------
  |  Branch (437:9): [True: 60.1k, False: 20.3k]
  |  Branch (437:21): [True: 60.1k, False: 35]
  ------------------
  438|  60.1k|        return c - 'a' + 10;
  439|  20.4k|    if (c >= 'A' && c <= 'F')
  ------------------
  |  Branch (439:9): [True: 20.3k, False: 18]
  |  Branch (439:21): [True: 20.3k, False: 41]
  ------------------
  440|  20.3k|        return c - 'A' + 10;
  441|       |
  442|     59|    return -1; // invalid char
  443|  20.4k|}

chmap.c:bstr_eatstart0:
  267|  2.98k|{
  268|  2.98k|    return bstr_eatstart(s, bstr0(prefix));
  269|  2.98k|}
chmap.c:bstr_equals0:
  252|  58.1k|{
  253|  58.1k|    return bstr_equals(str1, bstr0(str2));
  254|  58.1k|}
chmap.c:bstr_equals:
  244|  58.1k|{
  245|  58.1k|    if (str1.len != str2.len)
  ------------------
  |  Branch (245:9): [True: 43.2k, False: 14.9k]
  ------------------
  246|  43.2k|        return false;
  247|       |
  248|  14.9k|    return str1.start == str2.start || bstrcmp(str1, str2) == 0;
  ------------------
  |  Branch (248:12): [True: 117, False: 14.8k]
  |  Branch (248:40): [True: 1.54k, False: 13.2k]
  ------------------
  249|  58.1k|}
chmap.c:bstr0:
   62|  61.4k|{
   63|  61.4k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 61.4k, False: 0]
  ------------------
   64|  61.4k|}
common.c:bstr0:
   62|     39|{
   63|     39|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 39, False: 0]
  ------------------
   64|     39|}
common.c:bstr_cut:
  203|   134k|{
  204|   134k|    if (n < 0) {
  ------------------
  |  Branch (204:9): [True: 0, False: 134k]
  ------------------
  205|      0|        n += str.len;
  206|      0|        if (n < 0)
  ------------------
  |  Branch (206:13): [True: 0, False: 0]
  ------------------
  207|      0|            n = 0;
  208|      0|    }
  209|   134k|    if (((size_t)n) > str.len)
  ------------------
  |  Branch (209:9): [True: 0, False: 134k]
  ------------------
  210|      0|        n = str.len;
  211|   134k|    return (struct bstr){str.start + n, str.len - n};
  212|   134k|}
msg.c:bstr_eatstart0:
  267|  1.28M|{
  268|  1.28M|    return bstr_eatstart(s, bstr0(prefix));
  269|  1.28M|}
msg.c:bstr0:
   62|  1.28M|{
   63|  1.28M|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 1.28M, False: 0]
  ------------------
   64|  1.28M|}
msg.c:bstr_getline:
  130|  2.04M|{
  131|  2.04M|    return bstr_splitchar(str, rest, '\n');
  132|  2.04M|}
msg.c:bstrdup0:
   40|  1.24M|{
   41|  1.24M|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|  1.24M|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|  1.24M|}
playlist.c:bstr0:
   62|  96.3k|{
   63|  96.3k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 96.3k, False: 0]
  ------------------
   64|  96.3k|}
playlist.c:bstrdup:
   52|  46.4k|{
   53|  46.4k|    struct bstr r = { NULL, str.len };
   54|  46.4k|    if (str.start)
  ------------------
  |  Branch (54:9): [True: 46.4k, False: 0]
  ------------------
   55|  46.4k|        r.start = (unsigned char *)talloc_memdup(talloc_ctx, str.start, str.len);
  ------------------
  |  |   49|  46.4k|#define talloc_memdup                   ta_xmemdup
  |  |  ------------------
  |  |  |  |  157|  46.4k|#define ta_xmemdup(...)         ta_dbg_set_loc(ta_xmemdup(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|  46.4k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|  46.4k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|  46.4k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   56|  46.4k|    return r;
   57|  46.4k|}
tags.c:bstr0:
   62|    709|{
   63|    709|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 709, False: 0]
  ------------------
   64|    709|}
tags.c:bstrcasecmp0:
  257|      7|{
  258|      7|    return bstrcasecmp(str1, bstr0(str2));
  259|      7|}
tags.c:bstrto0:
   46|    324|{
   47|    324|    return str.start ? bstrdup0(talloc_ctx, str) : talloc_strdup(talloc_ctx, "");
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  |  Branch (47:12): [True: 324, False: 0]
  ------------------
   48|    324|}
tags.c:bstrdup0:
   40|    324|{
   41|    324|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|    324|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|    324|}
cue.c:bstr_startswith0:
  222|    295|{
  223|    295|    return bstr_startswith(str, bstr0(prefix));
  224|    295|}
cue.c:bstr_startswith:
  215|    295|{
  216|    295|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 2, False: 293]
  ------------------
  217|      2|        return false;
  218|    293|    return !memcmp(str.start, prefix.start, prefix.len);
  219|    295|}
cue.c:bstr_cut:
  203|      1|{
  204|      1|    if (n < 0) {
  ------------------
  |  Branch (204:9): [True: 0, False: 1]
  ------------------
  205|      0|        n += str.len;
  206|      0|        if (n < 0)
  ------------------
  |  Branch (206:13): [True: 0, False: 0]
  ------------------
  207|      0|            n = 0;
  208|      0|    }
  209|      1|    if (((size_t)n) > str.len)
  ------------------
  |  Branch (209:9): [True: 0, False: 1]
  ------------------
  210|      0|        n = str.len;
  211|      1|    return (struct bstr){str.start + n, str.len - n};
  212|      1|}
cue.c:bstr_getline:
  130|    295|{
  131|    295|    return bstr_splitchar(str, rest, '\n');
  132|    295|}
cue.c:bstr0:
   62|  4.41k|{
   63|  4.41k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 4.41k, False: 0]
  ------------------
   64|  4.41k|}
demux.c:bstr0:
   62|    379|{
   63|    379|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 379, False: 0]
  ------------------
   64|    379|}
demux_edl.c:bstr0:
   62|  34.3k|{
   63|  34.3k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 34.3k, False: 0]
  ------------------
   64|  34.3k|}
demux_edl.c:bstr_eatstart0:
  267|  17.4k|{
  268|  17.4k|    return bstr_eatstart(s, bstr0(prefix));
  269|  17.4k|}
demux_edl.c:bstr_cut:
  203|  1.96k|{
  204|  1.96k|    if (n < 0) {
  ------------------
  |  Branch (204:9): [True: 0, False: 1.96k]
  ------------------
  205|      0|        n += str.len;
  206|      0|        if (n < 0)
  ------------------
  |  Branch (206:13): [True: 0, False: 0]
  ------------------
  207|      0|            n = 0;
  208|      0|    }
  209|  1.96k|    if (((size_t)n) > str.len)
  ------------------
  |  Branch (209:9): [True: 0, False: 1.96k]
  ------------------
  210|      0|        n = str.len;
  211|  1.96k|    return (struct bstr){str.start + n, str.len - n};
  212|  1.96k|}
demux_edl.c:bstr_startswith0:
  222|    575|{
  223|    575|    return bstr_startswith(str, bstr0(prefix));
  224|    575|}
demux_edl.c:bstr_startswith:
  215|    575|{
  216|    575|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 0, False: 575]
  ------------------
  217|      0|        return false;
  218|    575|    return !memcmp(str.start, prefix.start, prefix.len);
  219|    575|}
demux_edl.c:bstr_equals:
  244|  4.02k|{
  245|  4.02k|    if (str1.len != str2.len)
  ------------------
  |  Branch (245:9): [True: 2.01k, False: 2.01k]
  ------------------
  246|  2.01k|        return false;
  247|       |
  248|  2.01k|    return str1.start == str2.start || bstrcmp(str1, str2) == 0;
  ------------------
  |  Branch (248:12): [True: 1.96k, False: 51]
  |  Branch (248:40): [True: 45, False: 6]
  ------------------
  249|  4.02k|}
demux_edl.c:bstr_equals0:
  252|  2.06k|{
  253|  2.06k|    return bstr_equals(str1, bstr0(str2));
  254|  2.06k|}
demux_edl.c:bstrdup0:
   40|  3.82k|{
   41|  3.82k|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|  3.82k|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|  3.82k|}
demux_edl.c:bstrcasecmp0:
  257|    508|{
  258|    508|    return bstrcasecmp(str1, bstr0(str2));
  259|    508|}
demux_lavf.c:bstrcasecmp0:
  257|    835|{
  258|    835|    return bstrcasecmp(str1, bstr0(str2));
  259|    835|}
demux_lavf.c:bstr0:
   62|  1.19k|{
   63|  1.19k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 1.19k, False: 0]
  ------------------
   64|  1.19k|}
demux_lavf.c:bstr_endswith0:
  234|     43|{
  235|     43|    return bstr_endswith(str, bstr0(suffix));
  236|     43|}
demux_lavf.c:bstr_endswith:
  227|     43|{
  228|     43|    if (str.len < suffix.len)
  ------------------
  |  Branch (228:9): [True: 33, False: 10]
  ------------------
  229|     33|        return false;
  230|     10|    return !memcmp(str.start + str.len - suffix.len, suffix.start, suffix.len);
  231|     43|}
demux_mf.c:bstr0:
   62|      4|{
   63|      4|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 4, False: 0]
  ------------------
   64|      4|}
demux_null.c:bstr_startswith0:
  222|     36|{
  223|     36|    return bstr_startswith(str, bstr0(prefix));
  224|     36|}
demux_null.c:bstr_startswith:
  215|     36|{
  216|     36|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 0, False: 36]
  ------------------
  217|      0|        return false;
  218|     36|    return !memcmp(str.start, prefix.start, prefix.len);
  219|     36|}
demux_null.c:bstr0:
   62|     72|{
   63|     72|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 72, False: 0]
  ------------------
   64|     72|}
demux_playlist.c:bstr_equals0:
  252|     86|{
  253|     86|    return bstr_equals(str1, bstr0(str2));
  254|     86|}
demux_playlist.c:bstr_equals:
  244|     86|{
  245|     86|    if (str1.len != str2.len)
  ------------------
  |  Branch (245:9): [True: 86, False: 0]
  ------------------
  246|     86|        return false;
  247|       |
  248|      0|    return str1.start == str2.start || bstrcmp(str1, str2) == 0;
  ------------------
  |  Branch (248:12): [True: 0, False: 0]
  |  Branch (248:40): [True: 0, False: 0]
  ------------------
  249|     86|}
demux_playlist.c:bstr_eatstart0:
  267|      4|{
  268|      4|    return bstr_eatstart(s, bstr0(prefix));
  269|      4|}
demux_playlist.c:bstrto0:
   46|      4|{
   47|      4|    return str.start ? bstrdup0(talloc_ctx, str) : talloc_strdup(talloc_ctx, "");
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  |  Branch (47:12): [True: 4, False: 0]
  ------------------
   48|      4|}
demux_playlist.c:bstrdup0:
   40|      4|{
   41|      4|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|      4|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|      4|}
demux_playlist.c:bstr_startswith0:
  222|      8|{
  223|      8|    return bstr_startswith(str, bstr0(prefix));
  224|      8|}
demux_playlist.c:bstr_startswith:
  215|      8|{
  216|      8|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 0, False: 8]
  ------------------
  217|      0|        return false;
  218|      8|    return !memcmp(str.start, prefix.start, prefix.len);
  219|      8|}
demux_playlist.c:bstr0:
   62|  2.31k|{
   63|  2.31k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 2.30k, False: 8]
  ------------------
   64|  2.31k|}
demux_playlist.c:bstrcasecmp0:
  257|     96|{
  258|     96|    return bstrcasecmp(str1, bstr0(str2));
  259|     96|}
cmd.c:bstr_equals0:
  252|  31.1M|{
  253|  31.1M|    return bstr_equals(str1, bstr0(str2));
  254|  31.1M|}
cmd.c:bstr_equals:
  244|  31.1M|{
  245|  31.1M|    if (str1.len != str2.len)
  ------------------
  |  Branch (245:9): [True: 28.8M, False: 2.35M]
  ------------------
  246|  28.8M|        return false;
  247|       |
  248|  2.35M|    return str1.start == str2.start || bstrcmp(str1, str2) == 0;
  ------------------
  |  Branch (248:12): [True: 18.4E, False: 2.35M]
  |  Branch (248:40): [True: 170k, False: 2.18M]
  ------------------
  249|  31.1M|}
cmd.c:bstr0:
   62|  64.5M|{
   63|  64.5M|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 64.5M, False: 0]
  ------------------
   64|  64.5M|}
cmd.c:bstr_cut:
  203|  6.64M|{
  204|  6.64M|    if (n < 0) {
  ------------------
  |  Branch (204:9): [True: 0, False: 6.64M]
  ------------------
  205|      0|        n += str.len;
  206|      0|        if (n < 0)
  ------------------
  |  Branch (206:13): [True: 0, False: 0]
  ------------------
  207|      0|            n = 0;
  208|      0|    }
  209|  6.64M|    if (((size_t)n) > str.len)
  ------------------
  |  Branch (209:9): [True: 0, False: 6.64M]
  ------------------
  210|      0|        n = str.len;
  211|  6.64M|    return (struct bstr){str.start + n, str.len - n};
  212|  6.64M|}
cmd.c:bstr_eatstart0:
  267|  27.7M|{
  268|  27.7M|    return bstr_eatstart(s, bstr0(prefix));
  269|  27.7M|}
cmd.c:bstrto0:
   46|  6.66M|{
   47|  6.66M|    return str.start ? bstrdup0(talloc_ctx, str) : talloc_strdup(talloc_ctx, "");
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  |  Branch (47:12): [True: 6.66M, False: 0]
  ------------------
   48|  6.66M|}
cmd.c:bstrdup0:
   40|  6.66M|{
   41|  6.66M|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|  6.66M|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|  6.66M|}
cmd.c:bstr_startswith0:
  222|  1.78M|{
  223|  1.78M|    return bstr_startswith(str, bstr0(prefix));
  224|  1.78M|}
cmd.c:bstr_startswith:
  215|  1.78M|{
  216|  1.78M|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 0, False: 1.78M]
  ------------------
  217|      0|        return false;
  218|  1.78M|    return !memcmp(str.start, prefix.start, prefix.len);
  219|  1.78M|}
input.c:bstr0:
   62|  17.8M|{
   63|  17.8M|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 17.7M, False: 17.0k]
  ------------------
   64|  17.8M|}
input.c:bstrdup:
   52|  29.5k|{
   53|  29.5k|    struct bstr r = { NULL, str.len };
   54|  29.5k|    if (str.start)
  ------------------
  |  Branch (54:9): [True: 29.5k, False: 0]
  ------------------
   55|  29.5k|        r.start = (unsigned char *)talloc_memdup(talloc_ctx, str.start, str.len);
  ------------------
  |  |   49|  29.5k|#define talloc_memdup                   ta_xmemdup
  |  |  ------------------
  |  |  |  |  157|  29.5k|#define ta_xmemdup(...)         ta_dbg_set_loc(ta_xmemdup(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|  29.5k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|  29.5k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|  29.5k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   56|  29.5k|    return r;
   57|  29.5k|}
input.c:bstr_equals0:
  252|  12.1k|{
  253|  12.1k|    return bstr_equals(str1, bstr0(str2));
  254|  12.1k|}
input.c:bstrdup0:
   40|  4.70M|{
   41|  4.70M|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|  4.70M|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|  4.70M|}
input.c:bstr_cut:
  203|  36.8k|{
  204|  36.8k|    if (n < 0) {
  ------------------
  |  Branch (204:9): [True: 0, False: 36.8k]
  ------------------
  205|      0|        n += str.len;
  206|      0|        if (n < 0)
  ------------------
  |  Branch (206:13): [True: 0, False: 0]
  ------------------
  207|      0|            n = 0;
  208|      0|    }
  209|  36.8k|    if (((size_t)n) > str.len)
  ------------------
  |  Branch (209:9): [True: 0, False: 36.8k]
  ------------------
  210|      0|        n = str.len;
  211|  36.8k|    return (struct bstr){str.start + n, str.len - n};
  212|  36.8k|}
input.c:bstr_getline:
  130|  5.65M|{
  131|  5.65M|    return bstr_splitchar(str, rest, '\n');
  132|  5.65M|}
input.c:bstr_eatstart0:
  267|  5.36M|{
  268|  5.36M|    return bstr_eatstart(s, bstr0(prefix));
  269|  5.36M|}
input.c:bstr_startswith0:
  222|  7.72M|{
  223|  7.72M|    return bstr_startswith(str, bstr0(prefix));
  224|  7.72M|}
input.c:bstr_startswith:
  215|  7.72M|{
  216|  7.72M|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 0, False: 7.72M]
  ------------------
  217|      0|        return false;
  218|  7.72M|    return !memcmp(str.start, prefix.start, prefix.len);
  219|  7.72M|}
input.c:bstr_equals:
  244|  2.40M|{
  245|  2.40M|    if (str1.len != str2.len)
  ------------------
  |  Branch (245:9): [True: 39.4k, False: 2.36M]
  ------------------
  246|  39.4k|        return false;
  247|       |
  248|  2.36M|    return str1.start == str2.start || bstrcmp(str1, str2) == 0;
  ------------------
  |  Branch (248:12): [True: 17.4k, False: 2.35M]
  |  Branch (248:40): [True: 2.34M, False: 490]
  ------------------
  249|  2.40M|}
ipc.c:bstr_getline:
  130|    336|{
  131|    336|    return bstr_splitchar(str, rest, '\n');
  132|    336|}
ipc.c:bstrto0:
   46|    336|{
   47|    336|    return str.start ? bstrdup0(talloc_ctx, str) : talloc_strdup(talloc_ctx, "");
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  |  Branch (47:12): [True: 336, False: 0]
  ------------------
   48|    336|}
ipc.c:bstrdup0:
   40|    336|{
   41|    336|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|    336|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|    336|}
ipc.c:bstrdup:
   52|    336|{
   53|    336|    struct bstr r = { NULL, str.len };
   54|    336|    if (str.start)
  ------------------
  |  Branch (54:9): [True: 336, False: 0]
  ------------------
   55|    336|        r.start = (unsigned char *)talloc_memdup(talloc_ctx, str.start, str.len);
  ------------------
  |  |   49|    336|#define talloc_memdup                   ta_xmemdup
  |  |  ------------------
  |  |  |  |  157|    336|#define ta_xmemdup(...)         ta_dbg_set_loc(ta_xmemdup(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|    336|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|    336|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|    336|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   56|    336|    return r;
   57|    336|}
keycodes.c:bstr0:
   62|  5.65M|{
   63|  5.65M|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 5.65M, False: 0]
  ------------------
   64|  5.65M|}
keycodes.c:bstr_startswith0:
  222|  1.21M|{
  223|  1.21M|    return bstr_startswith(str, bstr0(prefix));
  224|  1.21M|}
keycodes.c:bstr_startswith:
  215|  1.21M|{
  216|  1.21M|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 1.71k, False: 1.21M]
  ------------------
  217|  1.71k|        return false;
  218|  1.21M|    return !memcmp(str.start, prefix.start, prefix.len);
  219|  1.21M|}
bstr.c:bstr_startswith:
  215|  76.2M|{
  216|  76.2M|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 5.72M, False: 70.5M]
  ------------------
  217|  5.72M|        return false;
  218|  70.5M|    return !memcmp(str.start, prefix.start, prefix.len);
  219|  76.2M|}
bstr.c:bstr_cut:
  203|  22.9M|{
  204|  22.9M|    if (n < 0) {
  ------------------
  |  Branch (204:9): [True: 0, False: 22.9M]
  ------------------
  205|      0|        n += str.len;
  206|      0|        if (n < 0)
  ------------------
  |  Branch (206:13): [True: 0, False: 0]
  ------------------
  207|      0|            n = 0;
  208|      0|    }
  209|  22.9M|    if (((size_t)n) > str.len)
  ------------------
  |  Branch (209:9): [True: 1.08M, False: 21.8M]
  ------------------
  210|  1.08M|        n = str.len;
  211|  22.9M|    return (struct bstr){str.start + n, str.len - n};
  212|  22.9M|}
bstr.c:bstr0:
   62|  9.25M|{
   63|  9.25M|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 9.25M, False: 0]
  ------------------
   64|  9.25M|}
bstr.c:bstr_endswith0:
  234|  8.64M|{
  235|  8.64M|    return bstr_endswith(str, bstr0(suffix));
  236|  8.64M|}
bstr.c:bstr_endswith:
  227|  8.64M|{
  228|  8.64M|    if (str.len < suffix.len)
  ------------------
  |  Branch (228:9): [True: 506k, False: 8.14M]
  ------------------
  229|   506k|        return false;
  230|  8.14M|    return !memcmp(str.start + str.len - suffix.len, suffix.start, suffix.len);
  231|  8.64M|}
bstr.c:bstrdup0:
   40|   549k|{
   41|   549k|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|   549k|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|   549k|}
charset_conv.c:bstr0:
   62|  1.65k|{
   63|  1.65k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 1.65k, False: 0]
  ------------------
   64|  1.65k|}
charset_conv.c:bstr_startswith0:
  222|  1.57k|{
  223|  1.57k|    return bstr_startswith(str, bstr0(prefix));
  224|  1.57k|}
charset_conv.c:bstr_startswith:
  215|  1.57k|{
  216|  1.57k|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 915, False: 660]
  ------------------
  217|    915|        return false;
  218|    660|    return !memcmp(str.start, prefix.start, prefix.len);
  219|  1.57k|}
codepoint_width.c:bstr_eatstart0:
  267|  25.9M|{
  268|  25.9M|    return bstr_eatstart(s, bstr0(prefix));
  269|  25.9M|}
codepoint_width.c:bstr0:
   62|  25.9M|{
   63|  25.9M|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 25.9M, False: 0]
  ------------------
   64|  25.9M|}
codepoint_width.c:bstr_cut:
  203|  15.4k|{
  204|  15.4k|    if (n < 0) {
  ------------------
  |  Branch (204:9): [True: 0, False: 15.4k]
  ------------------
  205|      0|        n += str.len;
  206|      0|        if (n < 0)
  ------------------
  |  Branch (206:13): [True: 0, False: 0]
  ------------------
  207|      0|            n = 0;
  208|      0|    }
  209|  15.4k|    if (((size_t)n) > str.len)
  ------------------
  |  Branch (209:9): [True: 196, False: 15.2k]
  ------------------
  210|    196|        n = str.len;
  211|  15.4k|    return (struct bstr){str.start + n, str.len - n};
  212|  15.4k|}
json.c:bstr0:
   62|  14.5M|{
   63|  14.5M|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 14.5M, False: 12.1k]
  ------------------
   64|  14.5M|}
node.c:bstr0:
   62|  8.87k|{
   63|  8.87k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 8.87k, False: 0]
  ------------------
   64|  8.87k|}
node.c:bstrdup0:
   40|  8.87k|{
   41|  8.87k|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|  8.87k|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|  8.87k|}
path_utils.c:bstr0:
   62|   567k|{
   63|   567k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 567k, False: 0]
  ------------------
   64|   567k|}
path_utils.c:bstrdup0:
   40|  42.6k|{
   41|  42.6k|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|  42.6k|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|  42.6k|}
path_utils.c:bstr_find0:
  262|   237k|{
  263|   237k|    return bstr_find(haystack, bstr0(needle));
  264|   237k|}
m_config_frontend.c:bstr0:
   62|   799M|{
   63|   799M|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 799M, False: 0]
  ------------------
   64|   799M|}
m_config_frontend.c:bstr_eatstart0:
  267|   266k|{
  268|   266k|    return bstr_eatstart(s, bstr0(prefix));
  269|   266k|}
m_config_frontend.c:bstr_startswith:
  215|  76.3M|{
  216|  76.3M|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 57.7M, False: 18.5M]
  ------------------
  217|  57.7M|        return false;
  218|  18.5M|    return !memcmp(str.start, prefix.start, prefix.len);
  219|  76.3M|}
m_config_frontend.c:bstr_endswith:
  227|   423k|{
  228|   423k|    if (str.len < suffix.len)
  ------------------
  |  Branch (228:9): [True: 2.37k, False: 421k]
  ------------------
  229|  2.37k|        return false;
  230|   421k|    return !memcmp(str.start + str.len - suffix.len, suffix.start, suffix.len);
  231|   423k|}
m_config_frontend.c:bstr_equals0:
  252|  5.10M|{
  253|  5.10M|    return bstr_equals(str1, bstr0(str2));
  254|  5.10M|}
m_config_frontend.c:bstr_equals:
  244|  5.10M|{
  245|  5.10M|    if (str1.len != str2.len)
  ------------------
  |  Branch (245:9): [True: 4.59M, False: 507k]
  ------------------
  246|  4.59M|        return false;
  247|       |
  248|   507k|    return str1.start == str2.start || bstrcmp(str1, str2) == 0;
  ------------------
  |  Branch (248:12): [True: 17.0k, False: 490k]
  |  Branch (248:40): [True: 68.5k, False: 421k]
  ------------------
  249|  5.10M|}
m_config_frontend.c:bstrto0:
   46|  1.91M|{
   47|  1.91M|    return str.start ? bstrdup0(talloc_ctx, str) : talloc_strdup(talloc_ctx, "");
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  |  Branch (47:12): [True: 1.91M, False: 0]
  ------------------
   48|  1.91M|}
m_config_frontend.c:bstrdup0:
   40|  1.91M|{
   41|  1.91M|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|  1.91M|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|  1.91M|}
m_option.c:bstr_equals0:
  252|  7.18M|{
  253|  7.18M|    return bstr_equals(str1, bstr0(str2));
  254|  7.18M|}
m_option.c:bstr_equals:
  244|  7.33M|{
  245|  7.33M|    if (str1.len != str2.len)
  ------------------
  |  Branch (245:9): [True: 5.93M, False: 1.39M]
  ------------------
  246|  5.93M|        return false;
  247|       |
  248|  1.39M|    return str1.start == str2.start || bstrcmp(str1, str2) == 0;
  ------------------
  |  Branch (248:12): [True: 66.5k, False: 1.33M]
  |  Branch (248:40): [True: 679k, False: 652k]
  ------------------
  249|  7.33M|}
m_option.c:bstr0:
   62|  14.4M|{
   63|  14.4M|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 14.3M, False: 194k]
  ------------------
   64|  14.4M|}
m_option.c:bstrcasecmp0:
  257|  55.8k|{
  258|  55.8k|    return bstrcasecmp(str1, bstr0(str2));
  259|  55.8k|}
m_option.c:bstrcmp0:
  239|  1.29M|{
  240|  1.29M|    return bstrcmp(str1, bstr0(str2));
  241|  1.29M|}
m_option.c:bstr_eatstart0:
  267|  3.70M|{
  268|  3.70M|    return bstr_eatstart(s, bstr0(prefix));
  269|  3.70M|}
m_option.c:bstrdup0:
   40|  2.92M|{
   41|  2.92M|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|  2.92M|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|  2.92M|}
m_option.c:bstr_endswith0:
  234|  1.49M|{
  235|  1.49M|    return bstr_endswith(str, bstr0(suffix));
  236|  1.49M|}
m_option.c:bstr_endswith:
  227|  1.49M|{
  228|  1.49M|    if (str.len < suffix.len)
  ------------------
  |  Branch (228:9): [True: 430k, False: 1.06M]
  ------------------
  229|   430k|        return false;
  230|  1.06M|    return !memcmp(str.start + str.len - suffix.len, suffix.start, suffix.len);
  231|  1.49M|}
m_option.c:bstr_cut:
  203|   587k|{
  204|   587k|    if (n < 0) {
  ------------------
  |  Branch (204:9): [True: 0, False: 587k]
  ------------------
  205|      0|        n += str.len;
  206|      0|        if (n < 0)
  ------------------
  |  Branch (206:13): [True: 0, False: 0]
  ------------------
  207|      0|            n = 0;
  208|      0|    }
  209|   587k|    if (((size_t)n) > str.len)
  ------------------
  |  Branch (209:9): [True: 88.6k, False: 498k]
  ------------------
  210|  88.6k|        n = str.len;
  211|   587k|    return (struct bstr){str.start + n, str.len - n};
  212|   587k|}
m_option.c:bstrdup:
   52|  89.6k|{
   53|  89.6k|    struct bstr r = { NULL, str.len };
   54|  89.6k|    if (str.start)
  ------------------
  |  Branch (54:9): [True: 89.6k, False: 0]
  ------------------
   55|  89.6k|        r.start = (unsigned char *)talloc_memdup(talloc_ctx, str.start, str.len);
  ------------------
  |  |   49|  89.6k|#define talloc_memdup                   ta_xmemdup
  |  |  ------------------
  |  |  |  |  157|  89.6k|#define ta_xmemdup(...)         ta_dbg_set_loc(ta_xmemdup(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|  89.6k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|  89.6k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|  89.6k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   56|  89.6k|    return r;
   57|  89.6k|}
m_option.c:bstr_startswith0:
  222|  12.2k|{
  223|  12.2k|    return bstr_startswith(str, bstr0(prefix));
  224|  12.2k|}
m_option.c:bstr_startswith:
  215|  12.2k|{
  216|  12.2k|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 1.04k, False: 11.1k]
  ------------------
  217|  1.04k|        return false;
  218|  11.1k|    return !memcmp(str.start, prefix.start, prefix.len);
  219|  12.2k|}
m_option.c:bstrto0:
   46|   301k|{
   47|   301k|    return str.start ? bstrdup0(talloc_ctx, str) : talloc_strdup(talloc_ctx, "");
  ------------------
  |  |   50|    931|#define talloc_strdup                   ta_xstrdup
  ------------------
  |  Branch (47:12): [True: 300k, False: 931]
  ------------------
   48|   301k|}
m_option.c:bstr_find0:
  262|   366k|{
  263|   366k|    return bstr_find(haystack, bstr0(needle));
  264|   366k|}
m_property.c:bstr0:
   62|   775k|{
   63|   775k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 771k, False: 4.50k]
  ------------------
   64|   775k|}
m_property.c:bstr_eatstart0:
  267|   564k|{
  268|   564k|    return bstr_eatstart(s, bstr0(prefix));
  269|   564k|}
m_property.c:bstr_startswith0:
  222|   176k|{
  223|   176k|    return bstr_startswith(str, bstr0(prefix));
  224|   176k|}
m_property.c:bstr_startswith:
  215|   176k|{
  216|   176k|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 4.22k, False: 172k]
  ------------------
  217|  4.22k|        return false;
  218|   172k|    return !memcmp(str.start, prefix.start, prefix.len);
  219|   176k|}
m_property.c:bstr_find0:
  262|  14.5k|{
  263|  14.5k|    return bstr_find(haystack, bstr0(needle));
  264|  14.5k|}
m_property.c:bstr_cut:
  203|   187k|{
  204|   187k|    if (n < 0) {
  ------------------
  |  Branch (204:9): [True: 0, False: 187k]
  ------------------
  205|      0|        n += str.len;
  206|      0|        if (n < 0)
  ------------------
  |  Branch (206:13): [True: 0, False: 0]
  ------------------
  207|      0|            n = 0;
  208|      0|    }
  209|   187k|    if (((size_t)n) > str.len)
  ------------------
  |  Branch (209:9): [True: 0, False: 187k]
  ------------------
  210|      0|        n = str.len;
  211|   187k|    return (struct bstr){str.start + n, str.len - n};
  212|   187k|}
m_property.c:bstrdup0:
   40|  12.4k|{
   41|  12.4k|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|  12.4k|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|  12.4k|}
m_property.c:bstr_equals0:
  252|    129|{
  253|    129|    return bstr_equals(str1, bstr0(str2));
  254|    129|}
m_property.c:bstr_equals:
  244|    129|{
  245|    129|    if (str1.len != str2.len)
  ------------------
  |  Branch (245:9): [True: 91, False: 38]
  ------------------
  246|     91|        return false;
  247|       |
  248|     38|    return str1.start == str2.start || bstrcmp(str1, str2) == 0;
  ------------------
  |  Branch (248:12): [True: 0, False: 38]
  |  Branch (248:40): [True: 0, False: 38]
  ------------------
  249|    129|}
parse_commandline.c:bstr0:
   62|  2.20M|{
   63|  2.20M|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 1.81M, False: 385k]
  ------------------
   64|  2.20M|}
parse_commandline.c:bstr_startswith0:
  222|   383k|{
  223|   383k|    return bstr_startswith(str, bstr0(prefix));
  224|   383k|}
parse_commandline.c:bstr_startswith:
  215|   383k|{
  216|   383k|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 2.27k, False: 381k]
  ------------------
  217|  2.27k|        return false;
  218|   381k|    return !memcmp(str.start, prefix.start, prefix.len);
  219|   383k|}
parse_commandline.c:bstr_eatstart0:
  267|   380k|{
  268|   380k|    return bstr_eatstart(s, bstr0(prefix));
  269|   380k|}
parse_commandline.c:bstrcmp0:
  239|   547k|{
  240|   547k|    return bstrcmp(str1, bstr0(str2));
  241|   547k|}
parse_commandline.c:bstrdup0:
   40|  95.4k|{
   41|  95.4k|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|  95.4k|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|  95.4k|}
parse_configfile.c:bstr_eatstart0:
  267|  4.31M|{
  268|  4.31M|    return bstr_eatstart(s, bstr0(prefix));
  269|  4.31M|}
parse_configfile.c:bstr0:
   62|  9.25M|{
   63|  9.25M|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 9.25M, False: 0]
  ------------------
   64|  9.25M|}
parse_configfile.c:bstr_getline:
  130|  1.65M|{
  131|  1.65M|    return bstr_splitchar(str, rest, '\n');
  132|  1.65M|}
parse_configfile.c:bstr_startswith0:
  222|  4.93M|{
  223|  4.93M|    return bstr_startswith(str, bstr0(prefix));
  224|  4.93M|}
parse_configfile.c:bstr_startswith:
  215|  4.93M|{
  216|  4.93M|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 1.45M, False: 3.48M]
  ------------------
  217|  1.45M|        return false;
  218|  3.48M|    return !memcmp(str.start, prefix.start, prefix.len);
  219|  4.93M|}
parse_configfile.c:bstrto0:
   46|   204k|{
   47|   204k|    return str.start ? bstrdup0(talloc_ctx, str) : talloc_strdup(talloc_ctx, "");
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  |  Branch (47:12): [True: 204k, False: 0]
  ------------------
   48|   204k|}
parse_configfile.c:bstrdup0:
   40|   204k|{
   41|   204k|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|   204k|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|   204k|}
parse_configfile.c:bstr_cut:
  203|  12.8M|{
  204|  12.8M|    if (n < 0) {
  ------------------
  |  Branch (204:9): [True: 0, False: 12.8M]
  ------------------
  205|      0|        n += str.len;
  206|      0|        if (n < 0)
  ------------------
  |  Branch (206:13): [True: 0, False: 0]
  ------------------
  207|      0|            n = 0;
  208|      0|    }
  209|  12.8M|    if (((size_t)n) > str.len)
  ------------------
  |  Branch (209:9): [True: 0, False: 12.8M]
  ------------------
  210|      0|        n = str.len;
  211|  12.8M|    return (struct bstr){str.start + n, str.len - n};
  212|  12.8M|}
path.c:bstr0:
   62|   659k|{
   63|   659k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 623k, False: 35.9k]
  ------------------
   64|   659k|}
path.c:bstr_eatstart0:
  267|   113k|{
  268|   113k|    return bstr_eatstart(s, bstr0(prefix));
  269|   113k|}
path.c:bstr_equals0:
  252|  80.3k|{
  253|  80.3k|    return bstr_equals(str1, bstr0(str2));
  254|  80.3k|}
path.c:bstr_equals:
  244|  80.3k|{
  245|  80.3k|    if (str1.len != str2.len)
  ------------------
  |  Branch (245:9): [True: 72.2k, False: 8.10k]
  ------------------
  246|  72.2k|        return false;
  247|       |
  248|  8.10k|    return str1.start == str2.start || bstrcmp(str1, str2) == 0;
  ------------------
  |  Branch (248:12): [True: 0, False: 8.10k]
  |  Branch (248:40): [True: 7.90k, False: 195]
  ------------------
  249|  80.3k|}
client.c:bstr0:
   62|    336|{
   63|    336|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 336, False: 0]
  ------------------
   64|    336|}
command.c:bstr0:
   62|   415k|{
   63|   415k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 411k, False: 3.64k]
  ------------------
   64|   415k|}
command.c:bstr_eatstart0:
  267|  6.36k|{
  268|  6.36k|    return bstr_eatstart(s, bstr0(prefix));
  269|  6.36k|}
configfiles.c:bstr0:
   62|  67.5k|{
   63|  67.5k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 67.2k, False: 272]
  ------------------
   64|  67.5k|}
main.c:bstr0:
   62|  17.0k|{
   63|  17.0k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 17.0k, False: 0]
  ------------------
   64|  17.0k|}
misc.c:bstr0:
   62|  15.7k|{
   63|  15.7k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 15.7k, False: 0]
  ------------------
   64|  15.7k|}
misc.c:bstrcasecmp0:
  257|  5.82k|{
  258|  5.82k|    return bstrcasecmp(str1, bstr0(str2));
  259|  5.82k|}
osd.c:bstr_equals:
  244|  3.49k|{
  245|  3.49k|    if (str1.len != str2.len)
  ------------------
  |  Branch (245:9): [True: 15, False: 3.47k]
  ------------------
  246|     15|        return false;
  247|       |
  248|  3.47k|    return str1.start == str2.start || bstrcmp(str1, str2) == 0;
  ------------------
  |  Branch (248:12): [True: 0, False: 3.47k]
  |  Branch (248:40): [True: 3.47k, False: 0]
  ------------------
  249|  3.49k|}
osd.c:bstr0:
   62|  6.98k|{
   63|  6.98k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 3.49k, False: 3.49k]
  ------------------
   64|  6.98k|}
video.c:bstr0:
   62|    626|{
   63|    626|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 626, False: 0]
  ------------------
   64|    626|}
video.c:bstr_equals:
  244|    313|{
  245|    313|    if (str1.len != str2.len)
  ------------------
  |  Branch (245:9): [True: 303, False: 10]
  ------------------
  246|    303|        return false;
  247|       |
  248|     10|    return str1.start == str2.start || bstrcmp(str1, str2) == 0;
  ------------------
  |  Branch (248:12): [True: 0, False: 10]
  |  Branch (248:40): [True: 1, False: 9]
  ------------------
  249|    313|}
video.c:bstr_equals0:
  252|    313|{
  253|    313|    return bstr_equals(str1, bstr0(str2));
  254|    313|}
stream.c:bstr0:
   62|  3.87k|{
   63|  3.87k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 3.87k, False: 0]
  ------------------
   64|  3.87k|}
stream.c:bstr_startswith0:
  222|  1.30k|{
  223|  1.30k|    return bstr_startswith(str, bstr0(prefix));
  224|  1.30k|}
stream.c:bstr_startswith:
  215|  1.30k|{
  216|  1.30k|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 183, False: 1.12k]
  ------------------
  217|    183|        return false;
  218|  1.12k|    return !memcmp(str.start, prefix.start, prefix.len);
  219|  1.30k|}
stream_cb.c:bstr0:
   62|  1.97k|{
   63|  1.97k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 1.97k, False: 0]
  ------------------
   64|  1.97k|}
stream_cb.c:bstrto0:
   46|  1.97k|{
   47|  1.97k|    return str.start ? bstrdup0(talloc_ctx, str) : talloc_strdup(talloc_ctx, "");
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  |  Branch (47:12): [True: 1.97k, False: 0]
  ------------------
   48|  1.97k|}
stream_cb.c:bstrdup0:
   40|  1.97k|{
   41|  1.97k|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|  1.97k|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|  1.97k|}
stream_file.c:bstrcasecmp0:
  257|  96.8k|{
  258|  96.8k|    return bstrcasecmp(str1, bstr0(str2));
  259|  96.8k|}
stream_file.c:bstr0:
   62|  98.1k|{
   63|  98.1k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 98.1k, False: 0]
  ------------------
   64|  98.1k|}
stream_file.c:bstrto0:
   46|    814|{
   47|    814|    return str.start ? bstrdup0(talloc_ctx, str) : talloc_strdup(talloc_ctx, "");
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  |  Branch (47:12): [True: 814, False: 0]
  ------------------
   48|    814|}
stream_file.c:bstrdup0:
   40|    814|{
   41|    814|    return talloc_strndup(talloc_ctx, (char *)str.start, str.len);
  ------------------
  |  |   51|    814|#define talloc_strndup                  ta_xstrndup
  ------------------
   42|    814|}
stream_file.c:bstr_startswith0:
  222|    408|{
  223|    408|    return bstr_startswith(str, bstr0(prefix));
  224|    408|}
stream_file.c:bstr_startswith:
  215|    408|{
  216|    408|    if (str.len < prefix.len)
  ------------------
  |  Branch (216:9): [True: 177, False: 231]
  ------------------
  217|    177|        return false;
  218|    231|    return !memcmp(str.start, prefix.start, prefix.len);
  219|    408|}
stream_lavf.c:bstr0:
   62|  26.3k|{
   63|  26.3k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 26.3k, False: 0]
  ------------------
   64|  26.3k|}
stream_lavf.c:bstr_eatstart0:
  267|  12.1k|{
  268|  12.1k|    return bstr_eatstart(s, bstr0(prefix));
  269|  12.1k|}
stream_lavf.c:bstr_equals0:
  252|  10.1k|{
  253|  10.1k|    return bstr_equals(str1, bstr0(str2));
  254|  10.1k|}
stream_lavf.c:bstr_equals:
  244|  10.1k|{
  245|  10.1k|    if (str1.len != str2.len)
  ------------------
  |  Branch (245:9): [True: 9.13k, False: 969]
  ------------------
  246|  9.13k|        return false;
  247|       |
  248|    969|    return str1.start == str2.start || bstrcmp(str1, str2) == 0;
  ------------------
  |  Branch (248:12): [True: 0, False: 969]
  |  Branch (248:40): [True: 41, False: 928]
  ------------------
  249|  10.1k|}
stream_memory.c:bstr0:
   62|  2.99k|{
   63|  2.99k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 2.99k, False: 0]
  ------------------
   64|  2.99k|}
stream_memory.c:bstr_eatstart0:
  267|  1.74k|{
  268|  1.74k|    return bstr_eatstart(s, bstr0(prefix));
  269|  1.74k|}
stream_memory.c:bstrdup:
   52|  1.24k|{
   53|  1.24k|    struct bstr r = { NULL, str.len };
   54|  1.24k|    if (str.start)
  ------------------
  |  Branch (54:9): [True: 1.24k, False: 0]
  ------------------
   55|  1.24k|        r.start = (unsigned char *)talloc_memdup(talloc_ctx, str.start, str.len);
  ------------------
  |  |   49|  1.24k|#define talloc_memdup                   ta_xmemdup
  |  |  ------------------
  |  |  |  |  157|  1.24k|#define ta_xmemdup(...)         ta_dbg_set_loc(ta_xmemdup(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|  1.24k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|  1.24k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|  1.24k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   56|  1.24k|    return r;
   57|  1.24k|}
osd_libass.c:bstr0:
   62|  10.7k|{
   63|  10.7k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 10.7k, False: 0]
  ------------------
   64|  10.7k|}
hwdec.c:bstr0:
   62|  1.40k|{
   63|  1.40k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 1.40k, False: 0]
  ------------------
   64|  1.40k|}
hwdec.c:bstr_equals:
  244|  1.00k|{
  245|  1.00k|    if (str1.len != str2.len)
  ------------------
  |  Branch (245:9): [True: 665, False: 336]
  ------------------
  246|    665|        return false;
  247|       |
  248|    336|    return str1.start == str2.start || bstrcmp(str1, str2) == 0;
  ------------------
  |  Branch (248:12): [True: 0, False: 336]
  |  Branch (248:40): [True: 218, False: 118]
  ------------------
  249|  1.00k|}
hwdec.c:bstr_equals0:
  252|  1.00k|{
  253|  1.00k|    return bstr_equals(str1, bstr0(str2));
  254|  1.00k|}
img_format.c:bstr_equals0:
  252|  24.2k|{
  253|  24.2k|    return bstr_equals(str1, bstr0(str2));
  254|  24.2k|}
img_format.c:bstr_equals:
  244|  24.2k|{
  245|  24.2k|    if (str1.len != str2.len)
  ------------------
  |  Branch (245:9): [True: 21.3k, False: 2.86k]
  ------------------
  246|  21.3k|        return false;
  247|       |
  248|  2.86k|    return str1.start == str2.start || bstrcmp(str1, str2) == 0;
  ------------------
  |  Branch (248:12): [True: 0, False: 2.86k]
  |  Branch (248:40): [True: 76, False: 2.79k]
  ------------------
  249|  24.2k|}
img_format.c:bstr0:
   62|  24.2k|{
   63|  24.2k|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 24.2k, False: 0]
  ------------------
   64|  24.2k|}
vo.c:bstr0:
   62|    104|{
   63|    104|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 104, False: 0]
  ------------------
   64|    104|}
vo_kitty.c:bstr0:
   62|    195|{
   63|    195|    return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
  ------------------
  |  Branch (63:46): [True: 195, False: 0]
  ------------------
   64|    195|}

mp_charset_is_utf8:
   42|  1.12k|{
   43|  1.12k|    return user_cp && (strcasecmp(user_cp, "utf8") == 0 ||
  ------------------
  |  Branch (43:12): [True: 1.12k, False: 0]
  |  Branch (43:24): [True: 0, False: 1.12k]
  ------------------
   44|  1.12k|                       strcasecmp(user_cp, "utf-8") == 0);
  ------------------
  |  Branch (44:24): [True: 333, False: 795]
  ------------------
   45|  1.12k|}
mp_charset_is_utf16:
   48|     28|{
   49|     28|    bstr s = bstr0(user_cp);
   50|     28|    return bstr_case_startswith(s, bstr0("utf16")) ||
  ------------------
  |  Branch (50:12): [True: 0, False: 28]
  ------------------
   51|     28|           bstr_case_startswith(s, bstr0("utf-16"));
  ------------------
  |  Branch (51:12): [True: 0, False: 28]
  ------------------
   52|     28|}
mp_charset_guess:
  103|    525|{
  104|    525|    if (user_cp[0] == '+') {
  ------------------
  |  Branch (104:9): [True: 0, False: 525]
  ------------------
  105|      0|        mp_verbose(log, "Forcing charset '%s'.\n", user_cp + 1);
  ------------------
  |  |   75|      0|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  106|      0|        return user_cp + 1;
  107|      0|    }
  108|       |
  109|    525|    const char *bom_cp = ms_bom_guess(buf);
  110|    525|    if (bom_cp) {
  ------------------
  |  Branch (110:9): [True: 0, False: 525]
  ------------------
  111|      0|        mp_verbose(log, "Data has a BOM, assuming %s as charset.\n", bom_cp);
  ------------------
  |  |   75|      0|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  112|      0|        return bom_cp;
  113|      0|    }
  114|       |
  115|    525|    int r = bstr_validate_utf8(buf);
  116|    525|    if (r >= 0 || (r > -8 && (flags & MP_ICONV_ALLOW_CUTOFF))) {
  ------------------
  |  Branch (116:9): [True: 333, False: 192]
  |  Branch (116:20): [True: 0, False: 192]
  |  Branch (116:30): [True: 0, False: 0]
  ------------------
  117|    333|        if (strcmp(user_cp, "auto") != 0 && !mp_charset_is_utf8(user_cp))
  ------------------
  |  Branch (117:13): [True: 0, False: 333]
  |  Branch (117:45): [True: 0, False: 0]
  ------------------
  118|      0|            mp_verbose(log, "Data looks like UTF-8, ignoring user-provided charset.\n");
  ------------------
  |  |   75|      0|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  119|    333|        return "utf-8";
  120|    333|    }
  121|       |
  122|    192|    const char *res = NULL;
  123|    192|    if (strcasecmp(user_cp, "auto") == 0) {
  ------------------
  |  Branch (123:9): [True: 192, False: 0]
  ------------------
  124|    192|#if HAVE_UCHARDET
  125|    192|        res = mp_uchardet(talloc_ctx, log, buf);
  126|    192|#endif
  127|    192|        if (!res) {
  ------------------
  |  Branch (127:13): [True: 36, False: 156]
  ------------------
  128|     36|            mp_verbose(log, "Charset auto-detection failed.\n");
  ------------------
  |  |   75|     36|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  129|     36|            res = "UTF-8-BROKEN";
  130|     36|        }
  131|    192|    } else {
  132|      0|        res = user_cp;
  133|      0|    }
  134|       |
  135|    192|    mp_verbose(log, "Using charset '%s'.\n", res);
  ------------------
  |  |   75|    192|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  136|    192|    return res;
  137|    525|}
mp_iconv_to_utf8:
  151|    226|{
  152|    226|#if HAVE_ICONV
  153|    226|    if (!buf.len)
  ------------------
  |  Branch (153:9): [True: 0, False: 226]
  ------------------
  154|      0|        return buf;
  155|       |
  156|    226|    if (!cp || !cp[0] || mp_charset_is_utf8(cp))
  ------------------
  |  Branch (156:9): [True: 0, False: 226]
  |  Branch (156:16): [True: 0, False: 226]
  |  Branch (156:26): [True: 0, False: 226]
  ------------------
  157|      0|        return buf;
  158|       |
  159|    226|    if (strcasecmp(cp, "ASCII") == 0)
  ------------------
  |  Branch (159:9): [True: 0, False: 226]
  ------------------
  160|      0|        return buf;
  161|       |
  162|    226|    if (strcasecmp(cp, "UTF-8-BROKEN") == 0)
  ------------------
  |  Branch (162:9): [True: 45, False: 181]
  ------------------
  163|     45|        return bstr_sanitize_utf8_latin1(NULL, buf);
  164|       |
  165|       |    // Force CP949 over EUC-KR since iconv distinguishes them and
  166|       |    // EUC-KR causes error on CP949 encoded data
  167|    181|    if (strcasecmp(cp, "EUC-KR") == 0)
  ------------------
  |  Branch (167:9): [True: 0, False: 181]
  ------------------
  168|      0|        cp = "CP949";
  169|       |
  170|    181|    iconv_t icdsc;
  171|    181|    if ((icdsc = iconv_open("UTF-8", cp)) == (iconv_t) (-1)) {
  ------------------
  |  Branch (171:9): [True: 0, False: 181]
  ------------------
  172|      0|        if (flags & MP_ICONV_VERBOSE)
  ------------------
  |  Branch (172:13): [True: 0, False: 0]
  ------------------
  173|      0|            mp_err(log, "Error opening iconv with codepage '%s'\n", cp);
  ------------------
  |  |   72|      0|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  174|      0|        goto failure;
  175|      0|    }
  176|       |
  177|    181|    size_t size = buf.len;
  178|    181|    size_t osize = size;
  179|    181|    size_t ileft = size;
  180|    181|    size_t oleft = size - 1;
  181|       |
  182|    181|    char *outbuf = talloc_size(NULL, osize);
  ------------------
  |  |   43|    181|#define talloc_size                     ta_xalloc_size
  |  |  ------------------
  |  |  |  |  120|    181|#define ta_xalloc_size(...)             ta_oom_p(ta_alloc_size(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  153|    181|#define ta_alloc_size(...)      ta_dbg_set_loc(ta_alloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|    181|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|    181|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|    181|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  183|    181|    char *ip = buf.start;
  184|    181|    char *op = outbuf;
  185|       |
  186|    513|    while (1) {
  ------------------
  |  Branch (186:12): [Folded - Ignored]
  ------------------
  187|    513|        int clear = 0;
  188|    513|        size_t rc;
  189|    513|        if (ileft)
  ------------------
  |  Branch (189:13): [True: 358, False: 155]
  ------------------
  190|    358|            rc = iconv(icdsc, &ip, &ileft, &op, &oleft);
  191|    155|        else {
  192|    155|            clear = 1; // clear the conversion state and leave
  193|    155|            rc = iconv(icdsc, NULL, NULL, &op, &oleft);
  194|    155|        }
  195|    513|        if (rc == (size_t) (-1)) {
  ------------------
  |  Branch (195:13): [True: 203, False: 310]
  ------------------
  196|    203|            if (errno == E2BIG) {
  ------------------
  |  Branch (196:17): [True: 177, False: 26]
  ------------------
  197|    177|                size_t offset = op - outbuf;
  198|    177|                outbuf = talloc_realloc_size(NULL, outbuf, osize + size);
  ------------------
  |  |   39|    177|#define talloc_realloc_size             ta_xrealloc_size
  |  |  ------------------
  |  |  |  |  158|    177|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|    177|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|    177|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|    177|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  199|    177|                op = outbuf + offset;
  200|    177|                osize += size;
  201|    177|                oleft += size;
  202|    177|            } else {
  203|     26|                if (errno == EINVAL && (flags & MP_ICONV_ALLOW_CUTOFF)) {
  ------------------
  |  Branch (203:21): [True: 5, False: 21]
  |  Branch (203:40): [True: 0, False: 5]
  ------------------
  204|       |                    // This is intended for cases where the input buffer is cut
  205|       |                    // at a random byte position. If this happens in the middle
  206|       |                    // of the buffer, it should still be an error. We say it's
  207|       |                    // fine if the error is within 10 bytes of the end.
  208|      0|                    if (ileft <= 10)
  ------------------
  |  Branch (208:25): [True: 0, False: 0]
  ------------------
  209|      0|                        break;
  210|      0|                }
  211|     26|                if (flags & MP_ICONV_VERBOSE) {
  ------------------
  |  Branch (211:21): [True: 18, False: 8]
  ------------------
  212|     18|                    mp_err(log, "Error recoding text with codepage '%s'\n", cp);
  ------------------
  |  |   72|     18|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  213|     18|                }
  214|     26|                talloc_free(outbuf);
  ------------------
  |  |   47|     26|#define talloc_free                     ta_free
  ------------------
  215|     26|                iconv_close(icdsc);
  216|     26|                goto failure;
  217|     26|            }
  218|    310|        } else if (clear)
  ------------------
  |  Branch (218:20): [True: 155, False: 155]
  ------------------
  219|    155|            break;
  220|    513|    }
  221|       |
  222|    155|    iconv_close(icdsc);
  223|       |
  224|    155|    outbuf[osize - oleft - 1] = 0;
  225|    155|    return (bstr){outbuf, osize - oleft - 1};
  226|       |
  227|     26|failure:
  228|     26|#endif
  229|       |
  230|     26|    if (flags & MP_NO_LATIN1_FALLBACK) {
  ------------------
  |  Branch (230:9): [True: 0, False: 26]
  ------------------
  231|      0|        return buf;
  232|     26|    } else {
  233|     26|        return bstr_sanitize_utf8_latin1(NULL, buf);
  234|     26|    }
  235|     26|}
charset_conv.c:ms_bom_guess:
   58|    525|{
   59|  2.10k|    for (int n = 0; n < 3; n++) {
  ------------------
  |  Branch (59:21): [True: 1.57k, False: 525]
  ------------------
   60|  1.57k|        if (bstr_startswith0(buf, utf_bom[n]))
  ------------------
  |  Branch (60:13): [True: 0, False: 1.57k]
  ------------------
   61|      0|            return utf_enc[n];
   62|  1.57k|    }
   63|    525|    return NULL;
   64|    525|}
charset_conv.c:mp_uchardet:
   68|    192|{
   69|    192|    uchardet_t det = uchardet_new();
   70|    192|    if (!det)
  ------------------
  |  Branch (70:9): [True: 0, False: 192]
  ------------------
   71|      0|        return NULL;
   72|    192|    if (uchardet_handle_data(det, buf.start, buf.len) != 0) {
  ------------------
  |  Branch (72:9): [True: 0, False: 192]
  ------------------
   73|      0|        uchardet_delete(det);
   74|      0|        return NULL;
   75|      0|    }
   76|    192|    uchardet_data_end(det);
   77|    192|    char *res = talloc_strdup(talloc_ctx, uchardet_get_charset(det));
  ------------------
  |  |   50|    192|#define talloc_strdup                   ta_xstrdup
  ------------------
   78|    192|    if (res && !res[0])
  ------------------
  |  Branch (78:9): [True: 192, False: 0]
  |  Branch (78:16): [True: 36, False: 156]
  ------------------
   79|     36|        res = NULL;
   80|    192|    if (res) {
  ------------------
  |  Branch (80:9): [True: 156, False: 36]
  ------------------
   81|    156|        mp_verbose(log, "libuchardet detected charset as %s\n", res);
  ------------------
  |  |   75|    156|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
   82|    156|        iconv_t icdsc = iconv_open("UTF-8", res);
   83|    156|        if (icdsc == (iconv_t)(-1)) {
  ------------------
  |  Branch (83:13): [True: 0, False: 156]
  ------------------
   84|      0|            mp_warn(log, "Charset '%s' not supported by iconv.\n", res);
  ------------------
  |  |   73|      0|#define mp_warn(log, ...)       mp_msg(log, MSGL_WARN, __VA_ARGS__)
  ------------------
   85|      0|            res = NULL;
   86|    156|        } else {
   87|    156|            iconv_close(icdsc);
   88|    156|        }
   89|    156|    }
   90|    192|    uchardet_delete(det);
   91|    192|    return res;
   92|    192|}

term_disp_width:
  662|   264k|{
  663|   264k|    static const int ambiguous_width = 1;
  664|       |
  665|   264k|    int width = 0;
  666|       |
  667|   264k|    const unsigned char *prev_pos = str.start;
  668|  26.1M|    while (str.len) {
  ------------------
  |  Branch (668:12): [True: 25.9M, False: 234k]
  ------------------
  669|  25.9M|        int current_width = 0;
  670|       |
  671|  25.9M|        if (bstr_eatstart0(&str, "\033[")) {
  ------------------
  |  Branch (671:13): [True: 1.89k, False: 25.9M]
  ------------------
  672|  15.4k|            while (str.len && !((*str.start >= '@' && *str.start <= '~') || *str.start == 'm'))
  ------------------
  |  Branch (672:20): [True: 15.2k, False: 196]
  |  Branch (672:34): [True: 5.61k, False: 9.63k]
  |  Branch (672:55): [True: 1.70k, False: 3.91k]
  |  Branch (672:77): [True: 0, False: 13.5k]
  ------------------
  673|  13.5k|                str = bstr_cut(str, 1);
  674|  1.89k|            str = bstr_cut(str, 1);
  675|  1.89k|            goto next;
  676|  1.89k|        }
  677|       |
  678|  25.9M|        prev_pos = str.start;
  679|  25.9M|        int cp = bstr_decode_utf8(str, &str);
  680|       |
  681|       |        // Stop processing on any invalid input
  682|  25.9M|        if (cp < 0)
  ------------------
  |  Branch (682:13): [True: 28.6k, False: 25.9M]
  ------------------
  683|  28.6k|            return 0;
  684|       |
  685|  25.9M|        if (cp == '\r') {
  ------------------
  |  Branch (685:13): [True: 18, False: 25.9M]
  ------------------
  686|     18|            width = 0;
  687|     18|            goto next;
  688|     18|        }
  689|       |
  690|  25.9M|        if (cp == '\t') {
  ------------------
  |  Branch (690:13): [True: 76, False: 25.9M]
  ------------------
  691|       |            // Assume tabstop width is 8
  692|     76|            current_width = 8 - width % 8;
  693|     76|            goto next;
  694|     76|        }
  695|       |
  696|  25.9M|        if (cp < 0x20)
  ------------------
  |  Branch (696:13): [True: 302k, False: 25.6M]
  ------------------
  697|   302k|            goto next;
  698|       |
  699|  25.6M|        if (cp <= 0x7E) {
  ------------------
  |  Branch (699:13): [True: 25.6M, False: 5.88k]
  ------------------
  700|  25.6M|            current_width = 1;
  701|  25.6M|            goto next;
  702|  25.6M|        }
  703|       |
  704|  5.88k|        int state = 0;
  705|       |
  706|  6.30k|        while (true) {
  707|  6.30k|            int lead = ucdLookup(cp);
  708|  6.30k|            int w = ucdToCharacterWidth(lead);
  709|  6.30k|            if (w == 3)
  ------------------
  |  Branch (709:17): [True: 375, False: 5.93k]
  ------------------
  710|    375|                w = ambiguous_width;
  711|       |
  712|       |            // U+FE0F Variation Selector-16 is used to turn unqualified Emojis into qualified ones.
  713|       |            // By convention, this turns them from being ambiguous width (= narrow) into wide ones.
  714|       |            // We achieve this here by explicitly giving this codepoint a wide width.
  715|       |            // Later down below we'll clamp width back to <= 2.
  716|  6.30k|            if (cp == 0xFE0F)
  ------------------
  |  Branch (716:17): [True: 219, False: 6.08k]
  ------------------
  717|    219|                w = 2;
  718|       |
  719|  6.30k|            current_width += w;
  720|       |
  721|  6.30k|            if (!str.len)
  ------------------
  |  Branch (721:17): [True: 0, False: 6.30k]
  ------------------
  722|      0|                break;
  723|       |
  724|       |            // Fetch next codepoint in grapheme cluster
  725|  6.30k|            bstr cluster_end;
  726|  6.30k|            cp = bstr_decode_utf8(str, &cluster_end);
  727|       |            // Stop processing on any invalid input
  728|  6.30k|            if (cp < 0)
  ------------------
  |  Branch (728:17): [True: 1.08k, False: 5.22k]
  ------------------
  729|  1.08k|                return 0;
  730|  5.22k|            int trail = ucdLookup(cp);
  731|       |
  732|  5.22k|            state = ucdGraphemeJoins(state, lead, trail);
  733|  5.22k|            if (ucdGraphemeDone(state))
  ------------------
  |  Branch (733:17): [True: 4.80k, False: 426]
  ------------------
  734|  4.80k|                break;
  735|       |
  736|    426|            str = cluster_end;
  737|    426|        }
  738|       |
  739|  4.80k|        current_width = MPMIN(current_width, 2);
  ------------------
  |  |   44|  4.80k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 207, False: 4.59k]
  |  |  ------------------
  ------------------
  740|  25.9M|next:
  741|  25.9M|        if (width + current_width > max_width) {
  ------------------
  |  Branch (741:13): [True: 0, False: 25.9M]
  ------------------
  742|      0|            mp_assert(prev_pos < str.start + str.len);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  743|      0|            *cut_pos = prev_pos;
  744|      0|            break;
  745|      0|        }
  746|  25.9M|        width += current_width;
  747|  25.9M|        if (width == max_width) {
  ------------------
  |  Branch (747:13): [True: 0, False: 25.9M]
  ------------------
  748|      0|            if (str.len)
  ------------------
  |  Branch (748:17): [True: 0, False: 0]
  ------------------
  749|      0|                *cut_pos = str.start;
  750|      0|            break;
  751|      0|        }
  752|  25.9M|    }
  753|       |
  754|   234k|    return width;
  755|   264k|}
codepoint_width.c:ucdLookup:
  618|  11.5k|{
  619|  11.5k|    const uint16_t s0 = s_stage0[cp >> 11];
  620|  11.5k|    const uint16_t s1 = s_stage1[s0 + ((cp >> 6) & 31)];
  621|  11.5k|    const uint16_t s2 = s_stage2[s1 + ((cp >> 3) & 7)];
  622|  11.5k|    const uint8_t s3 = s_stage3[s2 + ((cp >> 0) & 7)];
  623|  11.5k|    return s3;
  624|  11.5k|}
codepoint_width.c:ucdToCharacterWidth:
  636|  6.30k|{
  637|  6.30k|    return val >> 6;
  638|  6.30k|}
codepoint_width.c:ucdGraphemeJoins:
  626|  5.22k|{
  627|  5.22k|    const int l = lead & 15;
  628|  5.22k|    const int t = trail & 15;
  629|  5.22k|    return (s_joinRules[state][l] >> (t * 2)) & 3;
  630|  5.22k|}
codepoint_width.c:ucdGraphemeDone:
  632|  5.22k|{
  633|  5.22k|    return state == 3;
  634|  5.22k|}

demux_mf.c:mp_isdigit:
   12|      4|static inline int mp_isdigit(char c) { return c >= '0' && c <= '9'; }
  ------------------
  |  Branch (12:47): [True: 4, False: 0]
  |  Branch (12:59): [True: 3, False: 1]
  ------------------
bstr.c:mp_isspace:
    8|   136M|static inline int mp_isspace(char c) { return c == ' ' || c == '\f' || c == '\n' ||
  ------------------
  |  Branch (8:47): [True: 84.0M, False: 52.4M]
  |  Branch (8:59): [True: 377, False: 52.4M]
  |  Branch (8:72): [True: 0, False: 52.4M]
  ------------------
    9|   136M|                                              c == '\r' || c == '\t' || c =='\v'; }
  ------------------
  |  Branch (9:47): [True: 3.78k, False: 52.4M]
  |  Branch (9:60): [True: 298, False: 52.4M]
  |  Branch (9:73): [True: 1.18k, False: 52.4M]
  ------------------
path_utils.c:mp_isalpha:
   13|   103k|static inline int mp_isalpha(char c) { return mp_isupper(c) || mp_islower(c); }
  ------------------
  |  Branch (13:47): [True: 5.03k, False: 98.7k]
  |  Branch (13:64): [True: 87.8k, False: 10.8k]
  ------------------
path_utils.c:mp_isupper:
   10|   103k|static inline int mp_isupper(char c) { return c >= 'A' && c <= 'Z'; }
  ------------------
  |  Branch (10:47): [True: 93.8k, False: 9.90k]
  |  Branch (10:59): [True: 5.03k, False: 88.8k]
  ------------------
path_utils.c:mp_islower:
   11|  98.7k|static inline int mp_islower(char c) { return c >= 'a' && c <= 'z'; }
  ------------------
  |  Branch (11:47): [True: 88.7k, False: 9.94k]
  |  Branch (11:59): [True: 87.8k, False: 884]
  ------------------
path_utils.c:mp_isalnum:
   14|  82.6k|static inline int mp_isalnum(char c) { return mp_isalpha(c) || mp_isdigit(c); }
  ------------------
  |  Branch (14:47): [True: 74.8k, False: 7.77k]
  |  Branch (14:64): [True: 1.62k, False: 6.15k]
  ------------------
path_utils.c:mp_isdigit:
   12|  7.77k|static inline int mp_isdigit(char c) { return c >= '0' && c <= '9'; }
  ------------------
  |  Branch (12:47): [True: 2.10k, False: 5.67k]
  |  Branch (12:59): [True: 1.62k, False: 481]
  ------------------
parse_configfile.c:mp_isalnum:
   14|  13.8M|static inline int mp_isalnum(char c) { return mp_isalpha(c) || mp_isdigit(c); }
  ------------------
  |  Branch (14:47): [True: 11.7M, False: 2.13M]
  |  Branch (14:64): [True: 0, False: 2.13M]
  ------------------
parse_configfile.c:mp_isalpha:
   13|  13.8M|static inline int mp_isalpha(char c) { return mp_isupper(c) || mp_islower(c); }
  ------------------
  |  Branch (13:47): [True: 0, False: 13.8M]
  |  Branch (13:64): [True: 11.7M, False: 2.13M]
  ------------------
parse_configfile.c:mp_isupper:
   10|  13.8M|static inline int mp_isupper(char c) { return c >= 'A' && c <= 'Z'; }
  ------------------
  |  Branch (10:47): [True: 11.7M, False: 2.13M]
  |  Branch (10:59): [True: 0, False: 11.7M]
  ------------------
parse_configfile.c:mp_islower:
   11|  13.8M|static inline int mp_islower(char c) { return c >= 'a' && c <= 'z'; }
  ------------------
  |  Branch (11:47): [True: 11.7M, False: 2.13M]
  |  Branch (11:59): [True: 11.7M, False: 0]
  ------------------
parse_configfile.c:mp_isdigit:
   12|  2.13M|static inline int mp_isdigit(char c) { return c >= '0' && c <= '9'; }
  ------------------
  |  Branch (12:47): [True: 1.02M, False: 1.10M]
  |  Branch (12:59): [True: 0, False: 1.02M]
  ------------------
client.c:mp_isalnum:
   14|   183k|static inline int mp_isalnum(char c) { return mp_isalpha(c) || mp_isdigit(c); }
  ------------------
  |  Branch (14:47): [True: 113k, False: 69.9k]
  |  Branch (14:64): [True: 19.3k, False: 50.6k]
  ------------------
client.c:mp_isalpha:
   13|   183k|static inline int mp_isalpha(char c) { return mp_isupper(c) || mp_islower(c); }
  ------------------
  |  Branch (13:47): [True: 14.0k, False: 168k]
  |  Branch (13:64): [True: 99.0k, False: 69.9k]
  ------------------
client.c:mp_isupper:
   10|   183k|static inline int mp_isupper(char c) { return c >= 'A' && c <= 'Z'; }
  ------------------
  |  Branch (10:47): [True: 163k, False: 19.3k]
  |  Branch (10:59): [True: 14.0k, False: 149k]
  ------------------
client.c:mp_islower:
   11|   168k|static inline int mp_islower(char c) { return c >= 'a' && c <= 'z'; }
  ------------------
  |  Branch (11:47): [True: 99.0k, False: 69.9k]
  |  Branch (11:59): [True: 99.0k, False: 0]
  ------------------
client.c:mp_isdigit:
   12|  69.9k|static inline int mp_isdigit(char c) { return c >= '0' && c <= '9'; }
  ------------------
  |  Branch (12:47): [True: 69.9k, False: 0]
  |  Branch (12:59): [True: 19.3k, False: 50.6k]
  ------------------

mp_dispatch_create:
   84|  17.1k|{
   85|  17.1k|    struct mp_dispatch_queue *queue = talloc_ptrtype(ta_parent, queue);
  ------------------
  |  |   34|  17.1k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  17.1k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.1k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   86|  17.1k|    *queue = (struct mp_dispatch_queue){0};
   87|  17.1k|    talloc_set_destructor(queue, queue_dtor);
  ------------------
  |  |   41|  17.1k|#define talloc_set_destructor           ta_set_destructor
  ------------------
   88|  17.1k|    mp_mutex_init(&queue->lock);
   89|  17.1k|    mp_cond_init(&queue->cond);
   90|  17.1k|    return queue;
   91|  17.1k|}
mp_dispatch_set_wakeup_fn:
  105|     76|{
  106|     76|    queue->wakeup_fn = wakeup_fn;
  107|     76|    queue->wakeup_ctx = wakeup_ctx;
  108|     76|}
mp_dispatch_enqueue_autofree:
  186|     39|{
  187|     39|    struct mp_dispatch_item *item = talloc_ptrtype(NULL, item);
  ------------------
  |  |   34|     39|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|     39|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     39|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  188|     39|    *item = (struct mp_dispatch_item){
  189|     39|        .fn = fn,
  190|     39|        .fn_data = talloc_steal(item, fn_data),
  ------------------
  |  |   38|     39|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     39|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  191|     39|        .asynchronous = true,
  192|     39|    };
  193|     39|    mp_dispatch_append(queue, item);
  194|     39|}
mp_dispatch_enqueue_notify:
  199|      6|{
  200|      6|    struct mp_dispatch_item *item = talloc_ptrtype(NULL, item);
  ------------------
  |  |   34|      6|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|      6|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      6|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  201|      6|    *item = (struct mp_dispatch_item){
  202|      6|        .fn = fn,
  203|      6|        .fn_data = fn_data,
  204|      6|        .mergeable = true,
  205|      6|        .asynchronous = true,
  206|      6|    };
  207|      6|    mp_dispatch_append(queue, item);
  208|      6|}
mp_dispatch_cancel_fn:
  220|  12.2k|{
  221|  12.2k|    mp_mutex_lock(&queue->lock);
  ------------------
  |  |  131|  12.2k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  222|  12.2k|    struct mp_dispatch_item **pcur = &queue->head;
  223|  12.2k|    queue->tail = NULL;
  224|  12.2k|    while (*pcur) {
  ------------------
  |  Branch (224:12): [True: 0, False: 12.2k]
  ------------------
  225|      0|        struct mp_dispatch_item *cur = *pcur;
  226|      0|        if (cur->fn == fn && cur->fn_data == fn_data) {
  ------------------
  |  Branch (226:13): [True: 0, False: 0]
  |  Branch (226:30): [True: 0, False: 0]
  ------------------
  227|      0|            *pcur = cur->next;
  228|      0|            talloc_free(cur);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  229|      0|        } else {
  230|      0|            queue->tail = cur;
  231|      0|            pcur = &cur->next;
  232|      0|        }
  233|      0|    }
  234|  12.2k|    mp_mutex_unlock(&queue->lock);
  ------------------
  |  |  133|  12.2k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  235|  12.2k|}
mp_dispatch_run:
  243|    217|{
  244|    217|    struct mp_dispatch_item item = {
  245|    217|        .fn = fn,
  246|    217|        .fn_data = fn_data,
  247|    217|    };
  248|    217|    mp_dispatch_append(queue, &item);
  249|       |
  250|    217|    mp_mutex_lock(&queue->lock);
  ------------------
  |  |  131|    217|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  251|    433|    while (!item.completed)
  ------------------
  |  Branch (251:12): [True: 216, False: 217]
  ------------------
  252|    216|        mp_cond_wait(&queue->cond, &queue->lock);
  253|    217|    mp_mutex_unlock(&queue->lock);
  ------------------
  |  |  133|    217|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  254|    217|}
mp_dispatch_queue_process:
  273|  19.4k|{
  274|  19.4k|    mp_mutex_lock(&queue->lock);
  ------------------
  |  |  131|  19.4k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  275|  19.4k|    queue->wait = timeout > 0 ? mp_time_ns_add(mp_time_ns(), timeout) : 0;
  ------------------
  |  Branch (275:19): [True: 1.96k, False: 17.4k]
  ------------------
  276|  19.4k|    mp_assert(!queue->in_process); // recursion not allowed
  ------------------
  |  |   41|  19.4k|#define mp_assert assert
  ------------------
  277|  19.4k|    queue->in_process = true;
  278|  19.4k|    queue->in_process_thread_id = mp_thread_current_id();
  ------------------
  |  |  214|  19.4k|#define mp_thread_current_id      pthread_self
  ------------------
  279|       |    // Wake up thread which called mp_dispatch_lock().
  280|  19.4k|    if (queue->lock_requests)
  ------------------
  |  Branch (280:9): [True: 17.9k, False: 1.51k]
  ------------------
  281|  17.9k|        mp_cond_broadcast(&queue->cond);
  282|  42.4k|    while (1) {
  ------------------
  |  Branch (282:12): [Folded - Ignored]
  ------------------
  283|  42.4k|        if (queue->lock_requests) {
  ------------------
  |  Branch (283:13): [True: 21.7k, False: 20.6k]
  ------------------
  284|       |            // Block due to something having called mp_dispatch_lock().
  285|  21.7k|            mp_cond_wait(&queue->cond, &queue->lock);
  286|  21.7k|        } else if (queue->head) {
  ------------------
  |  Branch (286:20): [True: 262, False: 20.4k]
  ------------------
  287|    262|            struct mp_dispatch_item *item = queue->head;
  288|    262|            queue->head = item->next;
  289|    262|            if (!queue->head)
  ------------------
  |  Branch (289:17): [True: 262, False: 0]
  ------------------
  290|    262|                queue->tail = NULL;
  291|    262|            item->next = NULL;
  292|       |            // Unlock, because we want to allow other threads to queue items
  293|       |            // while the dispatch item is processed.
  294|       |            // At the same time, we must prevent other threads from returning
  295|       |            // from mp_dispatch_lock(), which is done by locked=true.
  296|    262|            mp_assert(!queue->locked);
  ------------------
  |  |   41|    262|#define mp_assert assert
  ------------------
  297|    262|            queue->locked = true;
  298|    262|            mp_mutex_unlock(&queue->lock);
  ------------------
  |  |  133|    262|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  299|       |
  300|    262|            item->fn(item->fn_data);
  301|       |
  302|    262|            mp_mutex_lock(&queue->lock);
  ------------------
  |  |  131|    262|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  303|    262|            mp_assert(queue->locked);
  ------------------
  |  |   41|    262|#define mp_assert assert
  ------------------
  304|    262|            queue->locked = false;
  305|       |            // Wakeup mp_dispatch_run(), also mp_dispatch_lock().
  306|    262|            mp_cond_broadcast(&queue->cond);
  307|    262|            if (item->asynchronous) {
  ------------------
  |  Branch (307:17): [True: 45, False: 217]
  ------------------
  308|     45|                talloc_free(item);
  ------------------
  |  |   47|     45|#define talloc_free                     ta_free
  ------------------
  309|    217|            } else {
  310|    217|                item->completed = true;
  311|    217|            }
  312|  20.4k|        } else if (queue->wait > 0 && !queue->interrupted) {
  ------------------
  |  Branch (312:20): [True: 2.92k, False: 17.4k]
  |  Branch (312:39): [True: 956, False: 1.96k]
  ------------------
  313|    956|            if (mp_cond_timedwait_until(&queue->cond, &queue->lock, queue->wait))
  ------------------
  |  Branch (313:17): [True: 0, False: 956]
  ------------------
  314|      0|                queue->wait = 0;
  315|  19.4k|        } else {
  316|  19.4k|            break;
  317|  19.4k|        }
  318|  42.4k|    }
  319|  19.4k|    mp_assert(!queue->locked);
  ------------------
  |  |   41|  19.4k|#define mp_assert assert
  ------------------
  320|  19.4k|    queue->in_process = false;
  321|  19.4k|    queue->interrupted = false;
  322|  19.4k|    mp_mutex_unlock(&queue->lock);
  ------------------
  |  |  133|  19.4k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  323|  19.4k|}
mp_dispatch_interrupt:
  332|  87.5k|{
  333|  87.5k|    mp_mutex_lock(&queue->lock);
  ------------------
  |  |  131|  87.5k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  334|  87.5k|    queue->interrupted = true;
  335|  87.5k|    mp_cond_broadcast(&queue->cond);
  336|  87.5k|    mp_mutex_unlock(&queue->lock);
  ------------------
  |  |  133|  87.5k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  337|  87.5k|}
mp_dispatch_adjust_timeout:
  348|    685|{
  349|    685|    mp_mutex_lock(&queue->lock);
  ------------------
  |  |  131|    685|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  350|    685|    if (queue->in_process && queue->wait > until) {
  ------------------
  |  Branch (350:9): [True: 0, False: 685]
  |  Branch (350:30): [True: 0, False: 0]
  ------------------
  351|      0|        queue->wait = until;
  352|      0|        mp_cond_broadcast(&queue->cond);
  353|      0|    }
  354|    685|    mp_mutex_unlock(&queue->lock);
  ------------------
  |  |  133|    685|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  355|    685|}
mp_dispatch_lock:
  365|  46.2k|{
  366|  46.2k|    mp_mutex_lock(&queue->lock);
  ------------------
  |  |  131|  46.2k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  367|       |    // Must not be called recursively from dispatched callbacks.
  368|  46.2k|    if (queue->in_process)
  ------------------
  |  Branch (368:9): [True: 28.3k, False: 17.9k]
  ------------------
  369|  46.2k|        mp_assert(!mp_thread_id_equal(queue->in_process_thread_id, mp_thread_current_id()));
  ------------------
  |  |   41|  46.2k|#define mp_assert assert
  ------------------
  370|       |    // Must not be called recursively at all.
  371|  46.2k|    if (queue->locked_explicit)
  ------------------
  |  Branch (371:9): [True: 0, False: 46.2k]
  ------------------
  372|  46.2k|        mp_assert(!mp_thread_id_equal(queue->locked_explicit_thread_id, mp_thread_current_id()));
  ------------------
  |  |   41|  46.2k|#define mp_assert assert
  ------------------
  373|  46.2k|    queue->lock_requests += 1;
  374|       |    // And now wait until the target thread gets "trapped" within the
  375|       |    // mp_dispatch_queue_process() call, which will mean we get exclusive
  376|       |    // access to the target's thread state.
  377|  46.2k|    if (queue->onlock_fn)
  ------------------
  |  Branch (377:9): [True: 0, False: 46.2k]
  ------------------
  378|      0|        queue->onlock_fn(queue->onlock_ctx);
  379|  68.5k|    while (!queue->in_process) {
  ------------------
  |  Branch (379:12): [True: 22.2k, False: 46.2k]
  ------------------
  380|  22.2k|        mp_mutex_unlock(&queue->lock);
  ------------------
  |  |  133|  22.2k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  381|  22.2k|        if (queue->wakeup_fn)
  ------------------
  |  Branch (381:13): [True: 0, False: 22.2k]
  ------------------
  382|      0|            queue->wakeup_fn(queue->wakeup_ctx);
  383|  22.2k|        mp_mutex_lock(&queue->lock);
  ------------------
  |  |  131|  22.2k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  384|  22.2k|        if (queue->in_process)
  ------------------
  |  Branch (384:13): [True: 5, False: 22.2k]
  ------------------
  385|      5|            break;
  386|  22.2k|        mp_cond_wait(&queue->cond, &queue->lock);
  387|  22.2k|    }
  388|       |    // Wait until we can get the lock.
  389|  46.2k|    while (!queue->in_process || queue->locked)
  ------------------
  |  Branch (389:12): [True: 0, False: 46.2k]
  |  Branch (389:34): [True: 4, False: 46.2k]
  ------------------
  390|      4|        mp_cond_wait(&queue->cond, &queue->lock);
  391|       |    // "Lock".
  392|  46.2k|    mp_assert(queue->lock_requests);
  ------------------
  |  |   41|  46.2k|#define mp_assert assert
  ------------------
  393|  46.2k|    mp_assert(!queue->locked);
  ------------------
  |  |   41|  46.2k|#define mp_assert assert
  ------------------
  394|  46.2k|    mp_assert(!queue->locked_explicit);
  ------------------
  |  |   41|  46.2k|#define mp_assert assert
  ------------------
  395|  46.2k|    queue->locked = true;
  396|  46.2k|    queue->locked_explicit = true;
  397|  46.2k|    queue->locked_explicit_thread_id = mp_thread_current_id();
  ------------------
  |  |  214|  46.2k|#define mp_thread_current_id      pthread_self
  ------------------
  398|  46.2k|    mp_mutex_unlock(&queue->lock);
  ------------------
  |  |  133|  46.2k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  399|  46.2k|}
mp_dispatch_unlock:
  403|  46.2k|{
  404|  46.2k|    mp_mutex_lock(&queue->lock);
  ------------------
  |  |  131|  46.2k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  405|  46.2k|    mp_assert(queue->locked);
  ------------------
  |  |   41|  46.2k|#define mp_assert assert
  ------------------
  406|       |    // Must be called after a mp_dispatch_lock(), from the same thread.
  407|  46.2k|    mp_assert(queue->locked_explicit);
  ------------------
  |  |   41|  46.2k|#define mp_assert assert
  ------------------
  408|  46.2k|    mp_assert(mp_thread_id_equal(queue->locked_explicit_thread_id, mp_thread_current_id()));
  ------------------
  |  |   41|  46.2k|#define mp_assert assert
  ------------------
  409|       |    // "Unlock".
  410|  46.2k|    queue->locked = false;
  411|  46.2k|    queue->locked_explicit = false;
  412|  46.2k|    queue->lock_requests -= 1;
  413|       |    // Wakeup mp_dispatch_queue_process(), and maybe other mp_dispatch_lock()s.
  414|       |    // (Would be nice to wake up only 1 other locker if lock_requests>0.)
  415|  46.2k|    mp_cond_broadcast(&queue->cond);
  416|  46.2k|    mp_mutex_unlock(&queue->lock);
  ------------------
  |  |  133|  46.2k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  417|  46.2k|}
dispatch.c:queue_dtor:
   64|  17.1k|{
   65|  17.1k|    struct mp_dispatch_queue *queue = p;
   66|  17.1k|    mp_assert(!queue->head);
  ------------------
  |  |   41|  17.1k|#define mp_assert assert
  ------------------
   67|  17.1k|    mp_assert(!queue->in_process);
  ------------------
  |  |   41|  17.1k|#define mp_assert assert
  ------------------
   68|  17.1k|    mp_assert(!queue->lock_requests);
  ------------------
  |  |   41|  17.1k|#define mp_assert assert
  ------------------
   69|  17.1k|    mp_assert(!queue->locked);
  ------------------
  |  |   41|  17.1k|#define mp_assert assert
  ------------------
   70|  17.1k|    mp_cond_destroy(&queue->cond);
   71|  17.1k|    mp_mutex_destroy(&queue->lock);
  ------------------
  |  |  130|  17.1k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
   72|  17.1k|}
dispatch.c:mp_dispatch_append:
  128|    262|{
  129|    262|    mp_mutex_lock(&queue->lock);
  ------------------
  |  |  131|    262|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  130|    262|    if (item->mergeable) {
  ------------------
  |  Branch (130:9): [True: 6, False: 256]
  ------------------
  131|      6|        for (struct mp_dispatch_item *cur = queue->head; cur; cur = cur->next) {
  ------------------
  |  Branch (131:58): [True: 0, False: 6]
  ------------------
  132|      0|            if (cur->mergeable && cur->fn == item->fn &&
  ------------------
  |  Branch (132:17): [True: 0, False: 0]
  |  Branch (132:35): [True: 0, False: 0]
  ------------------
  133|      0|                cur->fn_data == item->fn_data)
  ------------------
  |  Branch (133:17): [True: 0, False: 0]
  ------------------
  134|      0|            {
  135|      0|                talloc_free(item);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  136|      0|                mp_mutex_unlock(&queue->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  137|      0|                return;
  138|      0|            }
  139|      0|        }
  140|      6|    }
  141|       |
  142|    262|    if (queue->tail) {
  ------------------
  |  Branch (142:9): [True: 0, False: 262]
  ------------------
  143|      0|        queue->tail->next = item;
  144|    262|    } else {
  145|    262|        queue->head = item;
  146|    262|    }
  147|    262|    queue->tail = item;
  148|       |
  149|       |    // Wake up the main thread; note that other threads might wait on this
  150|       |    // condition for reasons, so broadcast the condition.
  151|    262|    mp_cond_broadcast(&queue->cond);
  152|       |    // No wakeup callback -> assume mp_dispatch_queue_process() needs to be
  153|       |    // interrupted instead.
  154|    262|    if (!queue->wakeup_fn)
  ------------------
  |  Branch (154:9): [True: 6, False: 256]
  ------------------
  155|      6|        queue->interrupted = true;
  156|    262|    mp_mutex_unlock(&queue->lock);
  ------------------
  |  |  133|    262|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  157|       |
  158|    262|    if (queue->wakeup_fn)
  ------------------
  |  Branch (158:9): [True: 256, False: 6]
  ------------------
  159|    256|        queue->wakeup_fn(queue->wakeup_ctx);
  160|    262|}

json_skip_whitespace:
   79|    336|{
   80|    336|    eat_ws(src);
   81|    336|}
json_append:
  295|  2.10M|{
  296|  2.10M|    switch (src->format) {
  ------------------
  |  Branch (296:13): [True: 0, False: 2.10M]
  ------------------
  297|      0|    case MPV_FORMAT_NONE:
  ------------------
  |  Branch (297:5): [True: 0, False: 2.10M]
  ------------------
  298|      0|        APPEND(b, "null");
  ------------------
  |  |  248|      0|#define APPEND(b, s) bstr_xappend(NULL, (b), bstr0(s))
  ------------------
  299|      0|        return 0;
  300|     63|    case MPV_FORMAT_FLAG:
  ------------------
  |  Branch (300:5): [True: 63, False: 2.10M]
  ------------------
  301|     63|        APPEND(b, src->u.flag ? "true" : "false");
  ------------------
  |  |  248|    126|#define APPEND(b, s) bstr_xappend(NULL, (b), bstr0(s))
  |  |  ------------------
  |  |  |  Branch (248:52): [True: 2, False: 61]
  |  |  ------------------
  ------------------
  302|     63|        return 0;
  303|  18.3k|    case MPV_FORMAT_INT64:
  ------------------
  |  Branch (303:5): [True: 18.3k, False: 2.08M]
  ------------------
  304|  18.3k|        bstr_xappend_asprintf(NULL, b, "%"PRId64, src->u.int64);
  305|  18.3k|        return 0;
  306|      0|    case MPV_FORMAT_DOUBLE: {
  ------------------
  |  Branch (306:5): [True: 0, False: 2.10M]
  ------------------
  307|      0|        const char *px = (isfinite(src->u.double_) || indent == 0) ? "" : "\"";
  ------------------
  |  Branch (307:55): [True: 0, False: 0]
  ------------------
  308|      0|        bstr_xappend_asprintf(NULL, b, "%s%f%s", px, src->u.double_, px);
  309|      0|        return 0;
  310|      0|    }
  311|  1.55M|    case MPV_FORMAT_STRING:
  ------------------
  |  Branch (311:5): [True: 1.55M, False: 549k]
  ------------------
  312|  1.55M|        if (indent == 0)
  ------------------
  |  Branch (312:13): [True: 0, False: 1.55M]
  ------------------
  313|      0|            APPEND(b, src->u.string);
  ------------------
  |  |  248|      0|#define APPEND(b, s) bstr_xappend(NULL, (b), bstr0(s))
  ------------------
  314|  1.55M|        else
  315|  1.55M|            write_json_str(b, src->u.string);
  316|  1.55M|        return 0;
  317|  2.43k|    case MPV_FORMAT_NODE_ARRAY:
  ------------------
  |  Branch (317:5): [True: 2.43k, False: 2.10M]
  ------------------
  318|   531k|    case MPV_FORMAT_NODE_MAP: {
  ------------------
  |  Branch (318:5): [True: 528k, False: 1.57M]
  ------------------
  319|   531k|        struct mpv_node_list *list = src->u.list;
  320|   531k|        bool is_obj = src->format == MPV_FORMAT_NODE_MAP;
  321|   531k|        APPEND(b, is_obj ? "{" : "[");
  ------------------
  |  |  248|  1.06M|#define APPEND(b, s) bstr_xappend(NULL, (b), bstr0(s))
  |  |  ------------------
  |  |  |  Branch (248:52): [True: 528k, False: 2.43k]
  |  |  ------------------
  ------------------
  322|   531k|        int next_indent = indent >= 0 ? indent + 1 : -1;
  ------------------
  |  Branch (322:27): [True: 79.4k, False: 451k]
  ------------------
  323|  2.62M|        for (int n = 0; n < list->num; n++) {
  ------------------
  |  Branch (323:25): [True: 2.09M, False: 531k]
  ------------------
  324|  2.09M|            if (n)
  ------------------
  |  Branch (324:17): [True: 1.56M, False: 531k]
  ------------------
  325|  1.56M|                APPEND(b, ",");
  ------------------
  |  |  248|  1.56M|#define APPEND(b, s) bstr_xappend(NULL, (b), bstr0(s))
  ------------------
  326|  2.09M|            add_indent(b, next_indent);
  327|  2.09M|            if (is_obj) {
  ------------------
  |  Branch (327:17): [True: 1.56M, False: 528k]
  ------------------
  328|  1.56M|                write_json_str(b, list->keys[n]);
  329|  1.56M|                APPEND(b, ":");
  ------------------
  |  |  248|  1.56M|#define APPEND(b, s) bstr_xappend(NULL, (b), bstr0(s))
  ------------------
  330|  1.56M|            }
  331|  2.09M|            json_append(b, &list->values[n], next_indent);
  332|  2.09M|        }
  333|   531k|        add_indent(b, indent);
  334|   531k|        APPEND(b, is_obj ? "}" : "]");
  ------------------
  |  |  248|  1.06M|#define APPEND(b, s) bstr_xappend(NULL, (b), bstr0(s))
  |  |  ------------------
  |  |  |  Branch (248:52): [True: 528k, False: 2.43k]
  |  |  ------------------
  ------------------
  335|   531k|        return 0;
  336|  2.43k|    }
  337|  2.10M|    }
  338|      0|    return -1; // unknown format
  339|  2.10M|}
json_write:
  355|  13.1k|{
  356|  13.1k|    return json_append_str(dst, src, -1);
  357|  13.1k|}
json_write_pretty:
  361|    675|{
  362|    675|    return json_append_str(dst, src, 0);
  363|    675|}
json.c:eat_ws:
   69|    336|{
   70|  3.64k|    while (1) {
  ------------------
  |  Branch (70:12): [Folded - Ignored]
  ------------------
   71|  3.64k|        char c = **src;
   72|  3.64k|        if (c != ' ' && c != '\t' && c != '\n' && c != '\r')
  ------------------
  |  Branch (72:13): [True: 336, False: 3.30k]
  |  Branch (72:25): [True: 336, False: 0]
  |  Branch (72:38): [True: 336, False: 0]
  |  Branch (72:51): [True: 336, False: 0]
  ------------------
   73|    336|            return;
   74|  3.30k|        *src += 1;
   75|  3.30k|    }
   76|    336|}
json.c:write_json_str:
  259|  3.12M|{
  260|  3.12M|    mp_assert(str);
  ------------------
  |  |   41|  3.12M|#define mp_assert assert
  ------------------
  261|       |
  262|  3.12M|    APPEND(b, "\"");
  ------------------
  |  |  248|  3.12M|#define APPEND(b, s) bstr_xappend(NULL, (b), bstr0(s))
  ------------------
  263|  3.13M|    while (1) {
  ------------------
  |  Branch (263:12): [Folded - Ignored]
  ------------------
  264|  3.13M|        unsigned char *cur = str;
  265|  32.8M|        while (cur[0] >= 32 && cur[0] != '"' && cur[0] != '\\')
  ------------------
  |  Branch (265:16): [True: 29.7M, False: 3.12M]
  |  Branch (265:32): [True: 29.7M, False: 649]
  |  Branch (265:49): [True: 29.7M, False: 7.72k]
  ------------------
  266|  29.7M|            cur++;
  267|  3.13M|        if (!cur[0])
  ------------------
  |  Branch (267:13): [True: 3.12M, False: 12.2k]
  ------------------
  268|  3.12M|            break;
  269|  12.2k|        bstr_xappend(NULL, b, (bstr){str, cur - str});
  270|  12.2k|        if (cur[0] == '\"') {
  ------------------
  |  Branch (270:13): [True: 649, False: 11.6k]
  ------------------
  271|    649|            bstr_xappend(NULL, b, (bstr){"\\\"", 2});
  272|  11.6k|        } else if (cur[0] == '\\') {
  ------------------
  |  Branch (272:20): [True: 7.72k, False: 3.90k]
  ------------------
  273|  7.72k|            bstr_xappend(NULL, b, (bstr){"\\\\", 2});
  274|  7.72k|        } else if (cur[0] < sizeof(special_escape) && special_escape[cur[0]]) {
  ------------------
  |  Branch (274:20): [True: 1.85k, False: 2.04k]
  |  Branch (274:55): [True: 475, False: 1.38k]
  ------------------
  275|    475|            bstr_xappend_asprintf(NULL, b, "\\%c", special_escape[cur[0]]);
  276|  3.42k|        } else {
  277|  3.42k|            bstr_xappend_asprintf(NULL, b, "\\u%04x", (unsigned char)cur[0]);
  278|  3.42k|        }
  279|  12.2k|        str = cur + 1;
  280|  12.2k|    }
  281|  3.12M|    APPEND(b, str);
  ------------------
  |  |  248|  3.12M|#define APPEND(b, s) bstr_xappend(NULL, (b), bstr0(s))
  ------------------
  282|  3.12M|    APPEND(b, "\"");
  ------------------
  |  |  248|  3.12M|#define APPEND(b, s) bstr_xappend(NULL, (b), bstr0(s))
  ------------------
  283|  3.12M|}
json.c:add_indent:
  286|  2.62M|{
  287|  2.62M|    if (indent < 0)
  ------------------
  |  Branch (287:9): [True: 2.25M, False: 369k]
  ------------------
  288|  2.25M|        return;
  289|   369k|    bstr_xappend(NULL, b, bstr0("\n"));
  290|   978k|    for (int n = 0; n < indent; n++)
  ------------------
  |  Branch (290:21): [True: 609k, False: 369k]
  ------------------
  291|   609k|        bstr_xappend(NULL, b, bstr0(" "));
  292|   369k|}
json.c:json_append_str:
  342|  13.8k|{
  343|  13.8k|    bstr buffer = bstr0(*dst);
  344|  13.8k|    int r = json_append(&buffer, src, indent);
  345|  13.8k|    *dst = buffer.start;
  346|  13.8k|    return r;
  347|  13.8k|}

node_init:
   13|  47.4k|{
   14|       |    // Other formats need to be initialized manually.
   15|  47.4k|    mp_assert(format == MPV_FORMAT_NODE_MAP || format == MPV_FORMAT_NODE_ARRAY ||
  ------------------
  |  |   41|  47.4k|#define mp_assert assert
  ------------------
   16|  47.4k|           format == MPV_FORMAT_FLAG || format == MPV_FORMAT_INT64 ||
   17|  47.4k|           format == MPV_FORMAT_DOUBLE || format == MPV_FORMAT_BYTE_ARRAY ||
   18|  47.4k|           format == MPV_FORMAT_NONE);
   19|       |
   20|  47.4k|    void *ta_parent = NULL;
   21|  47.4k|    if (parent) {
  ------------------
  |  Branch (21:9): [True: 13.2k, False: 34.2k]
  ------------------
   22|  13.2k|        mp_assert(parent->format == MPV_FORMAT_NODE_MAP ||
  ------------------
  |  |   41|  13.2k|#define mp_assert assert
  ------------------
   23|  13.2k|               parent->format == MPV_FORMAT_NODE_ARRAY);
   24|  13.2k|        ta_parent = parent->u.list;
   25|  13.2k|    }
   26|       |
   27|  47.4k|    *dst = (struct mpv_node){ .format = format };
   28|  47.4k|    if (format == MPV_FORMAT_NODE_MAP || format == MPV_FORMAT_NODE_ARRAY)
  ------------------
  |  Branch (28:9): [True: 21.4k, False: 26.0k]
  |  Branch (28:42): [True: 17.9k, False: 8.06k]
  ------------------
   29|  39.4k|        dst->u.list = talloc_zero(ta_parent, struct mpv_node_list);
  ------------------
  |  |   27|  39.4k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  39.4k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  39.4k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   30|  47.4k|    if (format == MPV_FORMAT_BYTE_ARRAY)
  ------------------
  |  Branch (30:9): [True: 0, False: 47.4k]
  ------------------
   31|      0|        dst->u.ba = talloc_zero(ta_parent, struct mpv_byte_array);
  ------------------
  |  |   27|      0|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|      0|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   32|  47.4k|}
node_array_add:
   37|  4.34k|{
   38|  4.34k|    struct mpv_node_list *list = dst->u.list;
   39|  4.34k|    mp_assert(dst->format == MPV_FORMAT_NODE_ARRAY && dst->u.list);
  ------------------
  |  |   41|  4.34k|#define mp_assert assert
  ------------------
   40|  4.34k|    MP_TARRAY_GROW(list, list->values, list->num);
  ------------------
  |  |   96|  4.34k|    do {                                            \
  |  |   97|  4.34k|        size_t nextidx_ = (nextidx);                \
  |  |   98|  4.34k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  ------------------
  |  |  |  |   84|  4.34k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  ------------------
  |  |  |  |  |  |   45|  4.34k|#define talloc_get_size                 ta_get_size
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  |  Branch (98:13): [True: 1.70k, False: 2.64k]
  |  |  ------------------
  |  |   99|  4.34k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  ------------------
  |  |  |  |   88|  1.70k|    do {                                                        \
  |  |  |  |   89|  1.70k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|  1.70k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|  1.70k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|  1.70k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|  1.70k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   90|  1.70k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |   91|  1.70k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  100|  4.34k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
   41|  4.34k|    node_init(&list->values[list->num], format, dst);
   42|  4.34k|    return &list->values[list->num++];
   43|  4.34k|}
node_map_add:
   49|  8.87k|{
   50|  8.87k|    mp_assert(key);
  ------------------
  |  |   41|  8.87k|#define mp_assert assert
  ------------------
   51|  8.87k|    return node_map_badd(dst, bstr0(key), format);
   52|  8.87k|}
node_map_badd:
   55|  8.87k|{
   56|  8.87k|    mp_assert(key.start);
  ------------------
  |  |   41|  8.87k|#define mp_assert assert
  ------------------
   57|       |
   58|  8.87k|    struct mpv_node_list *list = dst->u.list;
   59|  8.87k|    mp_assert(dst->format == MPV_FORMAT_NODE_MAP && dst->u.list);
  ------------------
  |  |   41|  8.87k|#define mp_assert assert
  ------------------
   60|  8.87k|    MP_TARRAY_GROW(list, list->values, list->num);
  ------------------
  |  |   96|  8.87k|    do {                                            \
  |  |   97|  8.87k|        size_t nextidx_ = (nextidx);                \
  |  |   98|  8.87k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  ------------------
  |  |  |  |   84|  8.87k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  ------------------
  |  |  |  |  |  |   45|  8.87k|#define talloc_get_size                 ta_get_size
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  |  Branch (98:13): [True: 4.47k, False: 4.40k]
  |  |  ------------------
  |  |   99|  8.87k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  ------------------
  |  |  |  |   88|  4.47k|    do {                                                        \
  |  |  |  |   89|  4.47k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|  4.47k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|  4.47k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|  4.47k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|  4.47k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   90|  4.47k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |   91|  4.47k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  100|  8.87k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
   61|  8.87k|    MP_TARRAY_GROW(list, list->keys, list->num);
  ------------------
  |  |   96|  8.87k|    do {                                            \
  |  |   97|  8.87k|        size_t nextidx_ = (nextidx);                \
  |  |   98|  8.87k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  ------------------
  |  |  |  |   84|  8.87k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  ------------------
  |  |  |  |  |  |   45|  8.87k|#define talloc_get_size                 ta_get_size
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  |  Branch (98:13): [True: 4.47k, False: 4.40k]
  |  |  ------------------
  |  |   99|  8.87k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  ------------------
  |  |  |  |   88|  4.47k|    do {                                                        \
  |  |  |  |   89|  4.47k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|  4.47k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|  4.47k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|  4.47k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|  4.47k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   90|  4.47k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |   91|  4.47k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  100|  8.87k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
   62|  8.87k|    list->keys[list->num] = bstrdup0(list, key);
   63|  8.87k|    node_init(&list->values[list->num], format, dst);
   64|  8.87k|    return &list->values[list->num++];
   65|  8.87k|}
node_map_add_string:
   71|  7.87k|{
   72|  7.87k|    mp_assert(val);
  ------------------
  |  |   41|  7.87k|#define mp_assert assert
  ------------------
   73|       |
   74|  7.87k|    struct mpv_node *entry = node_map_add(dst, key, MPV_FORMAT_NONE);
   75|  7.87k|    entry->format = MPV_FORMAT_STRING;
   76|  7.87k|    entry->u.string = talloc_strdup(dst->u.list, val);
  ------------------
  |  |   50|  7.87k|#define talloc_strdup                   ta_xstrdup
  ------------------
   77|  7.87k|}
node_map_add_int64:
   89|    123|{
   90|    123|    node_map_add(dst, key, MPV_FORMAT_INT64)->u.int64 = v;
   91|    123|}
node_map_add_flag:
   99|     61|{
  100|     61|    node_map_add(dst, key, MPV_FORMAT_FLAG)->u.flag = v;
  101|     61|}

mp_basename:
   43|  15.9k|{
   44|  15.9k|    char *s;
   45|       |
   46|       |#if HAVE_DOS_PATHS
   47|       |    if (!mp_is_url(bstr0(path))) {
   48|       |        s = strrchr(path, '\\');
   49|       |        if (s)
   50|       |            path = s + 1;
   51|       |        s = strrchr(path, ':');
   52|       |        if (s)
   53|       |            path = s + 1;
   54|       |    }
   55|       |#endif
   56|  15.9k|    s = strrchr(path, '/');
   57|  15.9k|    return s ? s + 1 : (char *)path;
  ------------------
  |  Branch (57:12): [True: 1.90k, False: 14.0k]
  ------------------
   58|  15.9k|}
mp_splitext:
   86|  14.5k|{
   87|  14.5k|    mp_assert(path);
  ------------------
  |  |   41|  14.5k|#define mp_assert assert
  ------------------
   88|  14.5k|    int skip = (*path == '.'); // skip leading dot for "hidden" unix files
   89|  14.5k|    const char *split = strrchr(path + skip, '.');
   90|  14.5k|    if (!split || !split[1] || strchr(split, '/'))
  ------------------
  |  Branch (90:9): [True: 7.69k, False: 6.85k]
  |  Branch (90:19): [True: 112, False: 6.74k]
  |  Branch (90:32): [True: 418, False: 6.32k]
  ------------------
   91|  8.22k|        return NULL;
   92|  6.32k|    if (root)
  ------------------
  |  Branch (92:9): [True: 0, False: 6.32k]
  ------------------
   93|      0|        *root = (bstr){(char *)path, split - path};
   94|  6.32k|    return (char *)split + 1;
   95|  14.5k|}
mp_path_is_absolute:
   98|   189k|{
   99|   189k|    if (path.len && strchr(mp_path_separators, path.start[0]))
  ------------------
  |  Branch (99:9): [True: 188k, False: 1.17k]
  |  Branch (99:21): [True: 9.80k, False: 178k]
  ------------------
  100|  9.80k|        return true;
  101|       |
  102|       |#if HAVE_DOS_PATHS
  103|       |    // Note: "X:filename" is a path relative to the current working directory
  104|       |    //       of drive X, and thus is not an absolute path. It needs to be
  105|       |    //       followed by \ or /.
  106|       |    if (path.len >= 3 && path.start[1] == ':' &&
  107|       |        strchr(mp_path_separators, path.start[2]))
  108|       |        return true;
  109|       |#endif
  110|       |
  111|   180k|    return false;
  112|   189k|}
mp_path_join_bstr:
  115|   166k|{
  116|   166k|    if (p1.len == 0)
  ------------------
  |  Branch (116:9): [True: 35.9k, False: 130k]
  ------------------
  117|  35.9k|        return bstrdup0(talloc_ctx, p2);
  118|   130k|    if (p2.len == 0)
  ------------------
  |  Branch (118:9): [True: 4.29k, False: 126k]
  ------------------
  119|  4.29k|        return bstrdup0(talloc_ctx, p1);
  120|       |
  121|   126k|    if (mp_path_is_absolute(p2))
  ------------------
  |  Branch (121:9): [True: 2.40k, False: 124k]
  ------------------
  122|  2.40k|        return bstrdup0(talloc_ctx, p2);
  123|       |
  124|   124k|    bool have_separator = strchr(mp_path_separators, p1.start[p1.len - 1]);
  125|       |#if HAVE_DOS_PATHS
  126|       |    // "X:" only => path relative to "X:" current working directory.
  127|       |    if (p1.len == 2 && p1.start[1] == ':')
  128|       |        have_separator = true;
  129|       |#endif
  130|       |
  131|   124k|    return talloc_asprintf(talloc_ctx, "%.*s%s%.*s", BSTR_P(p1),
  ------------------
  |  |   52|   124k|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|   744k|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (127:62): [True: 124k, False: 0]
  |  |  |  |  |  Branch (127:62): [True: 3.64k, False: 120k]
  |  |  |  |  |  Branch (127:62): [True: 124k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  132|   126k|                           have_separator ? "" : "/", BSTR_P(p2));
  133|   126k|}
mp_path_join:
  136|   101k|{
  137|   101k|    return mp_path_join_bstr(talloc_ctx, bstr0(p1), bstr0(p2));
  138|   101k|}
mp_getcwd:
  141|  56.0k|{
  142|  56.0k|    char *e_wd = getenv("PWD");
  143|  56.0k|    if (e_wd)
  ------------------
  |  Branch (143:9): [True: 56.0k, False: 0]
  ------------------
  144|  56.0k|        return talloc_strdup(talloc_ctx, e_wd);
  ------------------
  |  |   50|  56.0k|#define talloc_strdup                   ta_xstrdup
  ------------------
  145|       |
  146|      0|    char *wd = talloc_array(talloc_ctx, char, 20);
  ------------------
  |  |   29|      0|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|      0|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  147|      0|    while (getcwd(wd, talloc_get_size(wd)) == NULL) {
  ------------------
  |  |   45|      0|#define talloc_get_size                 ta_get_size
  ------------------
  |  Branch (147:12): [True: 0, False: 0]
  ------------------
  148|      0|        if (errno != ERANGE) {
  ------------------
  |  Branch (148:13): [True: 0, False: 0]
  ------------------
  149|      0|            talloc_free(wd);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  150|      0|            return NULL;
  151|      0|        }
  152|      0|        wd = talloc_realloc(talloc_ctx, wd, char, talloc_get_size(wd) * 2);
  ------------------
  |  |   33|      0|#define talloc_realloc                  ta_xrealloc
  |  |  ------------------
  |  |  |  |  144|      0|    (type *)ta_xrealloc_size(ta_parent, ptr, ta_calc_array_size(sizeof(type), count))
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  153|      0|    }
  154|      0|    return wd;
  155|      0|}
mp_normalize_path:
  158|  63.3k|{
  159|  63.3k|    if (!path)
  ------------------
  |  Branch (159:9): [True: 0, False: 63.3k]
  ------------------
  160|      0|        return NULL;
  161|       |
  162|  63.3k|    if (mp_is_url(bstr0(path)))
  ------------------
  |  Branch (162:9): [True: 0, False: 63.3k]
  ------------------
  163|      0|        return talloc_strdup(talloc_ctx, path);
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  164|       |
  165|  63.3k|    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|  63.3k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  63.3k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  166|  63.3k|    if (!mp_path_is_absolute(bstr0(path))) {
  ------------------
  |  Branch (166:9): [True: 56.0k, False: 7.39k]
  ------------------
  167|  56.0k|        char *cwd = mp_getcwd(tmp);
  168|  56.0k|        if (!cwd) {
  ------------------
  |  Branch (168:13): [True: 0, False: 56.0k]
  ------------------
  169|      0|            talloc_free(tmp);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  170|      0|            return NULL;
  171|      0|        }
  172|  56.0k|        path = mp_path_join(tmp, cwd, path);
  173|  56.0k|    }
  174|       |
  175|       |#if HAVE_DOS_PATHS
  176|       |    wchar_t *pathw = mp_from_utf8(tmp, path);
  177|       |    wchar_t *read = pathw, *write = pathw;
  178|       |    wchar_t prev = '\0';
  179|       |    // preserve leading double backslashes
  180|       |    if (read[0] == '\\' && read[1] == '\\') {
  181|       |        prev = '\\';
  182|       |        write += 2;
  183|       |        read += 2;
  184|       |    }
  185|       |    wchar_t curr;
  186|       |    while ((curr = *read)) {
  187|       |        if (curr == '/')
  188|       |            curr = '\\';
  189|       |        if (curr != '\\' || prev != '\\')
  190|       |            *write++ = curr;
  191|       |        prev = curr;
  192|       |        read++;
  193|       |    }
  194|       |    *write = '\0';
  195|       |    size_t max_size = wcslen(pathw) + 1;
  196|       |    wchar_t *pathc = talloc_array(tmp, wchar_t, max_size);
  197|       |    HRESULT hr = PathCchCanonicalizeEx(pathc, max_size, pathw, PATHCCH_ALLOW_LONG_PATHS);
  198|       |    char *ret = SUCCEEDED(hr) ? mp_to_utf8(talloc_ctx, pathc) : talloc_strdup(talloc_ctx, path);
  199|       |    talloc_free(tmp);
  200|       |    return ret;
  201|       |#else
  202|  63.3k|    char *result = talloc_strdup(tmp, "");
  ------------------
  |  |   50|  63.3k|#define talloc_strdup                   ta_xstrdup
  ------------------
  203|  63.3k|    const char *next;
  204|  63.3k|    const char *end = path + strlen(path);
  205|       |
  206|   361k|    for (const char *ptr = path; ptr < end; ptr = next + 1) {
  ------------------
  |  Branch (206:34): [True: 298k, False: 62.9k]
  ------------------
  207|   298k|        next = memchr(ptr, '/', end - ptr);
  208|   298k|        if (next == NULL)
  ------------------
  |  Branch (208:13): [True: 55.3k, False: 243k]
  ------------------
  209|  55.3k|            next = end;
  210|       |
  211|   298k|        switch (next - ptr) {
  ------------------
  |  Branch (211:17): [True: 195k, False: 102k]
  ------------------
  212|  65.5k|            case 0:
  ------------------
  |  Branch (212:13): [True: 65.5k, False: 232k]
  ------------------
  213|  65.5k|                continue;
  214|  30.6k|            case 1:
  ------------------
  |  Branch (214:13): [True: 30.6k, False: 267k]
  ------------------
  215|  30.6k|                if (ptr[0] == '.')
  ------------------
  |  Branch (215:21): [True: 9.48k, False: 21.1k]
  ------------------
  216|  9.48k|                    continue;
  217|  21.1k|                break;
  218|  21.1k|            case 2:
  ------------------
  |  Branch (218:13): [True: 6.83k, False: 291k]
  ------------------
  219|       |                // Normalizing symlink/.. results in a wrong path: if the
  220|       |                // current working directory is /tmp/foo, and it is a symlink to
  221|       |                // /usr/bin, mpv ../file.mkv opens /usr/file.mkv, so we can't
  222|       |                // normalize the path to /tmp/file.mkv. Resolve symlinks to fix
  223|       |                // this. Otherwise we don't use realpath so users can use
  224|       |                // symlinks e.g. to hide how media files are distributed over
  225|       |                // real storage and move them while still resuming playback as
  226|       |                // long as the symlinked path doesn't change.
  227|  6.83k|                if (ptr[0] == '.' && ptr[1] == '.') {
  ------------------
  |  Branch (227:21): [True: 975, False: 5.86k]
  |  Branch (227:38): [True: 483, False: 492]
  ------------------
  228|    483|                    char *tmp_result = realpath(path, NULL);
  229|    483|                    result = talloc_strdup(talloc_ctx, tmp_result);
  ------------------
  |  |   50|    483|#define talloc_strdup                   ta_xstrdup
  ------------------
  230|    483|                    free(tmp_result);
  231|    483|                    talloc_free(tmp);
  ------------------
  |  |   47|    483|#define talloc_free                     ta_free
  ------------------
  232|    483|                    return result;
  233|    483|                }
  234|   298k|        }
  235|       |
  236|   222k|        result = talloc_strdup_append_buffer(result, "/");
  ------------------
  |  |   58|   222k|#define talloc_strdup_append_buffer     ta_talloc_strdup_append_buffer
  ------------------
  237|   222k|        result = talloc_strndup_append_buffer(result, ptr, next - ptr);
  ------------------
  |  |   60|   222k|#define talloc_strndup_append_buffer    ta_talloc_strndup_append_buffer
  ------------------
  238|   222k|    }
  239|       |
  240|  62.9k|    result = talloc_steal(talloc_ctx, result);
  ------------------
  |  |   38|  62.9k|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|  62.9k|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  241|  62.9k|    talloc_free(tmp);
  ------------------
  |  |   47|  62.9k|#define talloc_free                     ta_free
  ------------------
  242|  62.9k|    return result;
  243|  63.3k|#endif
  244|  63.3k|}
mp_path_exists:
  247|  50.4k|{
  248|  50.4k|    struct stat st;
  249|  50.4k|    return path && stat(path, &st) == 0;
  ------------------
  |  Branch (249:12): [True: 50.4k, False: 0]
  |  Branch (249:20): [True: 2.16k, False: 48.3k]
  ------------------
  250|  50.4k|}
mp_is_url:
  260|   237k|{
  261|   237k|    int proto = bstr_find0(path, "://");
  262|   237k|    if (proto < 1)
  ------------------
  |  Branch (262:9): [True: 215k, False: 21.1k]
  ------------------
  263|   215k|        return false;
  264|       |    // Per RFC3986, the first character of the protocol must be alphabetic.
  265|       |    // The rest must be alphanumeric plus -, + and .
  266|   102k|    for (int i = 0; i < proto; i++) {
  ------------------
  |  Branch (266:21): [True: 85.6k, False: 16.4k]
  ------------------
  267|  85.6k|        unsigned char c = path.start[i];
  268|  85.6k|        if ((i == 0 && !mp_isalpha(c)) ||
  ------------------
  |  Branch (268:14): [True: 21.1k, False: 64.5k]
  |  Branch (268:24): [True: 3.05k, False: 18.0k]
  ------------------
  269|  85.6k|            (!mp_isalnum(c) && c != '.' && c != '-' && c != '+'))
  ------------------
  |  Branch (269:14): [True: 6.15k, False: 76.4k]
  |  Branch (269:32): [True: 5.35k, False: 794]
  |  Branch (269:44): [True: 4.13k, False: 1.22k]
  |  Branch (269:56): [True: 1.64k, False: 2.49k]
  ------------------
  270|  4.69k|        {
  271|  4.69k|            return false;
  272|  4.69k|        }
  273|  85.6k|    }
  274|  16.4k|    return true;
  275|  21.1k|}
mp_split_proto:
  280|   101k|{
  281|   101k|    if (!mp_is_url(path))
  ------------------
  |  Branch (281:9): [True: 90.9k, False: 10.4k]
  ------------------
  282|  90.9k|        return (bstr){0};
  283|  10.4k|    bstr r;
  284|  10.4k|    bstr_split_tok(path, "://", &r, out_url ? out_url : &(bstr){0});
  ------------------
  |  Branch (284:37): [True: 6.39k, False: 4.04k]
  ------------------
  285|  10.4k|    return r;
  286|   101k|}
mp_mkdirp:
  289|    720|{
  290|    720|    if (mp_path_exists(dir))
  ------------------
  |  Branch (290:9): [True: 680, False: 40]
  ------------------
  291|    680|        return;
  292|       |
  293|     40|    char *path = talloc_strdup(NULL, dir);
  ------------------
  |  |   50|     40|#define talloc_strdup                   ta_xstrdup
  ------------------
  294|     40|    char *cdir = path + 1;
  295|       |
  296|    280|    while (cdir) {
  ------------------
  |  Branch (296:12): [True: 240, False: 40]
  ------------------
  297|    240|        cdir = strchr(cdir, '/');
  298|    240|        if (cdir)
  ------------------
  |  Branch (298:13): [True: 200, False: 40]
  ------------------
  299|    200|            *cdir = 0;
  300|       |
  301|    240|        mkdir(path, 0777);
  302|       |
  303|    240|        if (cdir)
  ------------------
  |  Branch (303:13): [True: 200, False: 40]
  ------------------
  304|    200|            *cdir++ = '/';
  305|    240|    }
  306|       |
  307|     40|    talloc_free(path);
  ------------------
  |  |   47|     40|#define talloc_free                     ta_free
  ------------------
  308|     40|}

mp_rand_seed:
   45|    173|{
   46|    173|    mp_rand_state ret;
   47|       |
   48|    173|#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
   49|    173|    seed = 42;
   50|    173|#endif
   51|       |
   52|    173|    if (seed == 0) {
  ------------------
  |  Branch (52:9): [True: 0, False: 173]
  ------------------
   53|      0|        if (av_random_bytes((void *)ret.v, sizeof(ret.v)) == 0) {
  ------------------
  |  Branch (53:13): [True: 0, False: 0]
  ------------------
   54|      0|            return ret;
   55|      0|        }
   56|      0|        seed = mp_raw_time_ns();
   57|      0|        seed ^= (uintptr_t)&mp_rand_seed; // ASLR, hopefully
   58|      0|        seed += (uintptr_t)&ret; // stack position
   59|      0|    }
   60|       |
   61|    173|    ret.v[0] = seed;
   62|    692|    for (int i = 1; i < 4; i++)
  ------------------
  |  Branch (62:21): [True: 519, False: 173]
  ------------------
   63|    519|        ret.v[i] = splitmix64(&seed);
   64|    173|    return ret;
   65|    173|}
mp_rand_next:
   68|  26.6k|{
   69|  26.6k|    uint64_t result, t;
   70|  26.6k|    uint64_t *state = s->v;
   71|       |
   72|  26.6k|    result = rotl_u64(state[1] * 5, 7) * 9;
   73|  26.6k|    t = state[1] << 17;
   74|       |
   75|  26.6k|    state[2] ^= state[0];
   76|  26.6k|    state[3] ^= state[1];
   77|  26.6k|    state[1] ^= state[2];
   78|  26.6k|    state[0] ^= state[3];
   79|  26.6k|    state[2] ^= t;
   80|  26.6k|    state[3] = rotl_u64(state[3], 45);
   81|       |
   82|  26.6k|    return result;
   83|  26.6k|}
mp_rand_in_range32:
   93|  19.0k|{
   94|  19.0k|    mp_assert(min < max);
  ------------------
  |  |   41|  19.0k|#define mp_assert assert
  ------------------
   95|  19.0k|    uint32_t range = max - min;
   96|  19.0k|    uint32_t mask = mp_round_next_power_of_2(range) - 1;
   97|  19.0k|    uint32_t ret;
   98|  26.6k|    do {
   99|  26.6k|        ret = mp_rand_next(s) & mask;
  100|  26.6k|    } while (ret >= range);
  ------------------
  |  Branch (100:14): [True: 7.65k, False: 19.0k]
  ------------------
  101|  19.0k|    return min + ret;
  102|  19.0k|}
random.c:splitmix64:
   37|    519|{
   38|    519|    uint64_t z = (*x += UINT64_C(0x9e3779b97f4a7c15));
   39|    519|    z = (z ^ (z >> 30)) * UINT64_C(0xbf58476d1ce4e5b9);
   40|    519|    z = (z ^ (z >> 27)) * UINT64_C(0x94d049bb133111eb);
   41|    519|    return z ^ (z >> 31);
   42|    519|}
random.c:rotl_u64:
   32|  53.3k|{
   33|  53.3k|    return (x << k) | (x >> (64 - k));
   34|  53.3k|}

mp_rendezvous:
   33|    152|{
   34|    152|    struct waiter wait = { .tag = tag, .value = &value };
   35|    152|    mp_mutex_lock(&lock);
  ------------------
  |  |  131|    152|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
   36|    152|    struct waiter **prev = &waiters;
   37|    152|    while (*prev) {
  ------------------
  |  Branch (37:12): [True: 76, False: 76]
  ------------------
   38|     76|        if ((*prev)->tag == tag) {
  ------------------
  |  Branch (38:13): [True: 76, False: 0]
  ------------------
   39|     76|            intptr_t tmp = *(*prev)->value;
   40|     76|            *(*prev)->value = value;
   41|     76|            value = tmp;
   42|     76|            (*prev)->value = NULL; // signals completion
   43|     76|            *prev = (*prev)->next; // unlink
   44|     76|            mp_cond_broadcast(&wakeup);
   45|     76|            goto done;
   46|     76|        }
   47|      0|        prev = &(*prev)->next;
   48|      0|    }
   49|     76|    *prev = &wait;
   50|    152|    while (wait.value)
  ------------------
  |  Branch (50:12): [True: 76, False: 76]
  ------------------
   51|     76|        mp_cond_wait(&wakeup, &lock);
   52|    152|done:
   53|    152|    mp_mutex_unlock(&lock);
  ------------------
  |  |  133|    152|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
   54|    152|    return value;
   55|     76|}

mp_thread_pool_create:
  155|  17.0k|{
  156|  17.0k|    mp_assert(min_threads >= 0);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  157|  17.0k|    mp_assert(init_threads <= min_threads);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  158|  17.0k|    mp_assert(max_threads > 0 && max_threads >= min_threads);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  159|       |
  160|  17.0k|    struct mp_thread_pool *pool = talloc_zero(ta_parent, struct mp_thread_pool);
  ------------------
  |  |   27|  17.0k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  17.0k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  161|  17.0k|    talloc_set_destructor(pool, thread_pool_dtor);
  ------------------
  |  |   41|  17.0k|#define talloc_set_destructor           ta_set_destructor
  ------------------
  162|       |
  163|  17.0k|    mp_mutex_init(&pool->lock);
  164|  17.0k|    mp_cond_init(&pool->wakeup);
  165|       |
  166|  17.0k|    pool->min_threads = min_threads;
  167|  17.0k|    pool->max_threads = max_threads;
  168|       |
  169|  17.0k|    mp_mutex_lock(&pool->lock);
  ------------------
  |  |  131|  17.0k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  170|  17.0k|    for (int n = 0; n < init_threads; n++)
  ------------------
  |  Branch (170:21): [True: 0, False: 17.0k]
  ------------------
  171|      0|        add_thread(pool);
  172|  17.0k|    bool ok = pool->num_threads >= init_threads;
  173|  17.0k|    mp_mutex_unlock(&pool->lock);
  ------------------
  |  |  133|  17.0k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  174|       |
  175|  17.0k|    if (!ok)
  ------------------
  |  Branch (175:9): [True: 0, False: 17.0k]
  ------------------
  176|      0|        TA_FREEP(&pool);
  ------------------
  |  |   81|      0|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|      0|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  177|       |
  178|  17.0k|    return pool;
  179|  17.0k|}
thread_pool.c:thread_pool_dtor:
  116|  17.0k|{
  117|  17.0k|    struct mp_thread_pool *pool = ctx;
  118|       |
  119|       |
  120|  17.0k|    mp_mutex_lock(&pool->lock);
  ------------------
  |  |  131|  17.0k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  121|       |
  122|  17.0k|    pool->terminate = true;
  123|  17.0k|    mp_cond_broadcast(&pool->wakeup);
  124|       |
  125|  17.0k|    mp_thread *threads = pool->threads;
  126|  17.0k|    int num_threads = pool->num_threads;
  127|       |
  128|  17.0k|    pool->threads = NULL;
  129|  17.0k|    pool->num_threads = 0;
  130|       |
  131|  17.0k|    mp_mutex_unlock(&pool->lock);
  ------------------
  |  |  133|  17.0k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  132|       |
  133|  17.0k|    for (int n = 0; n < num_threads; n++)
  ------------------
  |  Branch (133:21): [True: 0, False: 17.0k]
  ------------------
  134|      0|        mp_thread_join(threads[n]);
  ------------------
  |  |  212|      0|#define mp_thread_join(t)         pthread_join(t, NULL)
  ------------------
  135|       |
  136|  17.0k|    mp_assert(pool->num_work == 0);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  137|  17.0k|    mp_assert(pool->num_threads == 0);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  138|  17.0k|    mp_cond_destroy(&pool->wakeup);
  139|  17.0k|    mp_mutex_destroy(&pool->lock);
  ------------------
  |  |  130|  17.0k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
  140|  17.0k|}

mp_waiter_wait:
   36|  12.1k|{
   37|  12.1k|    mp_mutex_lock(&waiter->lock);
  ------------------
  |  |  131|  12.1k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
   38|  12.1k|    while (!waiter->done)
  ------------------
  |  Branch (38:12): [True: 0, False: 12.1k]
  ------------------
   39|      0|        mp_cond_wait(&waiter->wakeup, &waiter->lock);
   40|  12.1k|    mp_mutex_unlock(&waiter->lock);
  ------------------
  |  |  133|  12.1k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
   41|       |
   42|  12.1k|    uintptr_t ret = waiter->value;
   43|       |
   44|       |    // We document that after mp_waiter_wait() the waiter object becomes
   45|       |    // invalid. (It strictly returns only after mp_waiter_wakeup() has returned,
   46|       |    // and the object is "single-shot".) So destroy it here.
   47|       |
   48|       |    // Normally, we expect that the system uses futexes, in which case the
   49|       |    // following functions will do nearly nothing. This is true for Windows
   50|       |    // and Linux. But some lesser OSes still might allocate kernel objects
   51|       |    // when initializing mutexes, so destroy them here.
   52|  12.1k|    mp_mutex_destroy(&waiter->lock);
  ------------------
  |  |  130|  12.1k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
   53|  12.1k|    mp_cond_destroy(&waiter->wakeup);
   54|       |
   55|  12.1k|    memset(waiter, 0xCA, sizeof(*waiter)); // for debugging
   56|       |
   57|  12.1k|    return ret;
   58|  12.1k|}
mp_waiter_wakeup:
   61|  12.1k|{
   62|  12.1k|    mp_mutex_lock(&waiter->lock);
  ------------------
  |  |  131|  12.1k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
   63|  12.1k|    mp_assert(!waiter->done);
  ------------------
  |  |   41|  12.1k|#define mp_assert assert
  ------------------
   64|  12.1k|    waiter->done = true;
   65|  12.1k|    waiter->value = value;
   66|  12.1k|    mp_cond_signal(&waiter->wakeup);
   67|  12.1k|    mp_mutex_unlock(&waiter->lock);
  ------------------
  |  |  133|  12.1k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
   68|  12.1k|}
mp_cancel_new:
  124|  18.1k|{
  125|  18.1k|    struct mp_cancel *c = talloc_ptrtype(talloc_ctx, c);
  ------------------
  |  |   34|  18.1k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  18.1k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  18.1k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  126|  18.1k|    talloc_set_destructor(c, cancel_destroy);
  ------------------
  |  |   41|  18.1k|#define talloc_set_destructor           ta_set_destructor
  ------------------
  127|  18.1k|    *c = (struct mp_cancel){
  128|  18.1k|        .triggered = false,
  129|  18.1k|        .wakeup_pipe = {-1, -1},
  130|  18.1k|    };
  131|  18.1k|    mp_mutex_init(&c->lock);
  132|  18.1k|    mp_cond_init(&c->wakeup);
  133|  18.1k|    return c;
  134|  18.1k|}
mp_cancel_trigger:
  158|  24.3k|{
  159|  24.3k|    mp_mutex_lock(&c->lock);
  ------------------
  |  |  131|  24.3k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  160|  24.3k|    trigger_locked(c);
  161|  24.3k|    mp_mutex_unlock(&c->lock);
  ------------------
  |  |  133|  24.3k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  162|  24.3k|}
mp_cancel_reset:
  165|  3.93k|{
  166|  3.93k|    mp_mutex_lock(&c->lock);
  ------------------
  |  |  131|  3.93k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  167|       |
  168|  3.93k|    atomic_store(&c->triggered, false);
  169|       |
  170|  3.93k|    if (c->wakeup_pipe[0] >= 0) {
  ------------------
  |  Branch (170:9): [True: 0, False: 3.93k]
  ------------------
  171|       |        // Flush it fully.
  172|      0|        while (1) {
  ------------------
  |  Branch (172:16): [Folded - Ignored]
  ------------------
  173|      0|            int r = read(c->wakeup_pipe[0], &(char[256]){0}, 256);
  174|      0|            if (r <= 0 && !(r < 0 && errno == EINTR))
  ------------------
  |  Branch (174:17): [True: 0, False: 0]
  |  Branch (174:29): [True: 0, False: 0]
  |  Branch (174:38): [True: 0, False: 0]
  ------------------
  175|      0|                break;
  176|      0|        }
  177|      0|    }
  178|       |
  179|       |#ifdef _WIN32
  180|       |    if (c->win32_event)
  181|       |        ResetEvent(c->win32_event);
  182|       |#endif
  183|       |
  184|  3.93k|    mp_mutex_unlock(&c->lock);
  ------------------
  |  |  133|  3.93k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  185|  3.93k|}
mp_cancel_test:
  188|  18.6k|{
  189|  18.6k|    return c ? atomic_load_explicit(&c->triggered, memory_order_relaxed) : false;
  ------------------
  |  Branch (189:12): [True: 13.2k, False: 5.30k]
  ------------------
  190|  18.6k|}
mp_cancel_set_parent:
  223|  19.3k|{
  224|       |    // We can access c->parent without synchronization, because:
  225|       |    //  - concurrent mp_cancel_set_parent() calls to slave are not allowed
  226|       |    //  - slave->parent needs to stay valid as long as the slave exists
  227|  19.3k|    if (slave->parent == parent)
  ------------------
  |  Branch (227:9): [True: 17.0k, False: 2.27k]
  ------------------
  228|  17.0k|        return;
  229|  2.27k|    if (slave->parent) {
  ------------------
  |  Branch (229:9): [True: 1.21k, False: 1.05k]
  ------------------
  230|  1.21k|        mp_mutex_lock(&slave->parent->lock);
  ------------------
  |  |  131|  1.21k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  231|  1.21k|        LL_REMOVE(siblings, &slave->parent->slaves, slave);
  ------------------
  |  |   78|  1.21k|#define LL_REMOVE(field, list, item) do {                               \
  |  |   79|  1.21k|    if ((item)->field.prev) {                                           \
  |  |  ------------------
  |  |  |  Branch (79:9): [True: 41, False: 1.17k]
  |  |  ------------------
  |  |   80|     41|        (item)->field.prev->field.next = (item)->field.next;            \
  |  |   81|  1.17k|    } else {                                                            \
  |  |   82|  1.17k|        (list)->head = (item)->field.next;                              \
  |  |   83|  1.17k|    }                                                                   \
  |  |   84|  1.21k|    if ((item)->field.next) {                                           \
  |  |  ------------------
  |  |  |  Branch (84:9): [True: 241, False: 978]
  |  |  ------------------
  |  |   85|    241|        (item)->field.next->field.prev = (item)->field.prev;            \
  |  |   86|    978|    } else {                                                            \
  |  |   87|    978|        (list)->tail = (item)->field.prev;                              \
  |  |   88|    978|    }                                                                   \
  |  |   89|  1.21k|} while (0)
  |  |  ------------------
  |  |  |  Branch (89:10): [Folded - Ignored]
  |  |  ------------------
  ------------------
  232|  1.21k|        mp_mutex_unlock(&slave->parent->lock);
  ------------------
  |  |  133|  1.21k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  233|  1.21k|    }
  234|  2.27k|    slave->parent = parent;
  235|  2.27k|    if (slave->parent) {
  ------------------
  |  Branch (235:9): [True: 1.21k, False: 1.05k]
  ------------------
  236|  1.21k|        mp_mutex_lock(&slave->parent->lock);
  ------------------
  |  |  131|  1.21k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  237|  1.21k|        LL_APPEND(siblings, &slave->parent->slaves, slave);
  ------------------
  |  |   44|  1.21k|#define LL_APPEND(field, list, item)  do {                              \
  |  |   45|  1.21k|    (item)->field.prev = (list)->tail;                                  \
  |  |   46|  1.21k|    (item)->field.next = NULL;                                          \
  |  |   47|  1.21k|    LL_RELINK_(field, list, item)                                       \
  |  |  ------------------
  |  |  |  |   98|  1.21k|    if ((item)->field.prev) {                                           \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:9): [True: 282, False: 937]
  |  |  |  |  ------------------
  |  |  |  |   99|    282|        (item)->field.prev->field.next = (item);                        \
  |  |  |  |  100|    937|    } else {                                                            \
  |  |  |  |  101|    937|        (list)->head = (item);                                          \
  |  |  |  |  102|    937|    }                                                                   \
  |  |  |  |  103|  1.21k|    if ((item)->field.next) {                                           \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (103:9): [True: 0, False: 1.21k]
  |  |  |  |  ------------------
  |  |  |  |  104|      0|        (item)->field.next->field.prev = (item);                        \
  |  |  |  |  105|  1.21k|    } else {                                                            \
  |  |  |  |  106|  1.21k|        (list)->tail = (item);                                          \
  |  |  |  |  107|  1.21k|    }
  |  |  ------------------
  |  |   48|  1.21k|} while (0)
  |  |  ------------------
  |  |  |  Branch (48:10): [Folded - Ignored]
  |  |  ------------------
  ------------------
  238|  1.21k|        retrigger_locked(slave->parent);
  239|  1.21k|        mp_mutex_unlock(&slave->parent->lock);
  ------------------
  |  |  133|  1.21k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  240|  1.21k|    }
  241|  2.27k|}
thread_tools.c:cancel_destroy:
  102|  18.1k|{
  103|  18.1k|    struct mp_cancel *c = p;
  104|       |
  105|  18.1k|    mp_assert(!c->slaves.head); // API user error
  ------------------
  |  |   41|  18.1k|#define mp_assert assert
  ------------------
  106|       |
  107|  18.1k|    mp_cancel_set_parent(c, NULL);
  108|       |
  109|  18.1k|    if (c->wakeup_pipe[0] >= 0) {
  ------------------
  |  Branch (109:9): [True: 0, False: 18.1k]
  ------------------
  110|      0|        close(c->wakeup_pipe[0]);
  111|      0|        close(c->wakeup_pipe[1]);
  112|      0|    }
  113|       |
  114|       |#ifdef _WIN32
  115|       |    if (c->win32_event)
  116|       |        CloseHandle(c->win32_event);
  117|       |#endif
  118|       |
  119|  18.1k|    mp_mutex_destroy(&c->lock);
  ------------------
  |  |  130|  18.1k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
  120|  18.1k|    mp_cond_destroy(&c->wakeup);
  121|  18.1k|}
thread_tools.c:trigger_locked:
  137|  24.5k|{
  138|  24.5k|    atomic_store(&c->triggered, true);
  139|       |
  140|  24.5k|    mp_cond_broadcast(&c->wakeup); // condition bound to c->triggered
  141|       |
  142|  24.5k|    if (c->cb)
  ------------------
  |  Branch (142:9): [True: 0, False: 24.5k]
  ------------------
  143|      0|        c->cb(c->cb_ctx);
  144|       |
  145|  26.6k|    for (struct mp_cancel *sub = c->slaves.head; sub; sub = sub->siblings.next)
  ------------------
  |  Branch (145:50): [True: 2.02k, False: 24.5k]
  ------------------
  146|  2.02k|        mp_cancel_trigger(sub);
  147|       |
  148|  24.5k|    if (c->wakeup_pipe[1] >= 0)
  ------------------
  |  Branch (148:9): [True: 0, False: 24.5k]
  ------------------
  149|      0|        (void)write(c->wakeup_pipe[1], &(char){0}, 1);
  150|       |
  151|       |#ifdef _WIN32
  152|       |    if (c->win32_event)
  153|       |        SetEvent(c->win32_event);
  154|       |#endif
  155|  24.5k|}
thread_tools.c:retrigger_locked:
  208|  1.21k|{
  209|  1.21k|    if (mp_cancel_test(c))
  ------------------
  |  Branch (209:9): [True: 187, False: 1.03k]
  ------------------
  210|    187|        trigger_locked(c);
  211|  1.21k|}

m_config_shadow_get_next_opt:
  187|  12.8M|{
  188|  12.8M|    return iter_next(shadow, 0, shadow->num_groups, p_id);
  189|  12.8M|}
m_config_shadow_get_opt:
  212|  12.7M|{
  213|  12.7M|    int group_index, opt_index;
  214|  12.7M|    get_opt_from_id(shadow, id, &group_index, &opt_index);
  215|       |
  216|  12.7M|    return &shadow->groups[group_index].group->opts[opt_index];
  217|  12.7M|}
m_config_shadow_get_opt_name:
  221|  12.7M|{
  222|  12.7M|    int group_index, opt_index;
  223|  12.7M|    get_opt_from_id(shadow, id, &group_index, &opt_index);
  224|       |
  225|  12.7M|    struct m_config_group *g = &shadow->groups[group_index];
  226|  12.7M|    return concat_name_buf(buf, buf_size, g->prefix,
  227|  12.7M|                           g->group->opts[opt_index].name);
  228|  12.7M|}
m_config_shadow_get_alias_from_opt:
  232|   792k|{
  233|   792k|    int group_index, opt_index;
  234|   792k|    get_opt_from_id(shadow, id, &group_index, &opt_index);
  235|       |
  236|   792k|    struct m_config_group *g = &shadow->groups[group_index];
  237|   792k|    const struct m_option *opt = &shadow->groups[group_index].group->opts[opt_index];
  238|   792k|    if (opt->alias_use_prefix)
  ------------------
  |  Branch (238:9): [True: 205k, False: 586k]
  ------------------
  239|   205k|        return concat_name_buf(buf, buf_size, g->prefix, (const char *)opt->priv);
  240|   586k|    return (const char *)opt->priv;
  241|   792k|}
m_config_shadow_get_opt_default:
  245|  26.7k|{
  246|  26.7k|    int group_index, opt_index;
  247|  26.7k|    get_opt_from_id(shadow, id, &group_index, &opt_index);
  248|       |
  249|  26.7k|    const struct m_sub_options *subopt = shadow->groups[group_index].group;
  250|  26.7k|    const struct m_option *opt = &subopt->opts[opt_index];
  251|       |
  252|  26.7k|    if (opt->offset < 0)
  ------------------
  |  Branch (252:9): [True: 1.52k, False: 25.2k]
  ------------------
  253|  1.52k|        return NULL;
  254|       |
  255|  25.2k|    if (opt->defval)
  ------------------
  |  Branch (255:9): [True: 42, False: 25.1k]
  ------------------
  256|     42|        return opt->defval;
  257|       |
  258|  25.1k|    if (subopt->defaults)
  ------------------
  |  Branch (258:9): [True: 24.8k, False: 339]
  ------------------
  259|  24.8k|        return (char *)subopt->defaults + opt->offset;
  260|       |
  261|    339|    return &m_option_value_default;
  262|  25.1k|}
m_config_cache_get_opt_data:
  265|  12.7M|{
  266|  12.7M|    int group_index, opt_index;
  267|  12.7M|    get_opt_from_id(cache->shadow, id, &group_index, &opt_index);
  268|       |
  269|  12.7M|    mp_assert(group_index >= cache->internal->group_start &&
  ------------------
  |  |   41|  12.7M|#define mp_assert assert
  ------------------
  270|  12.7M|           group_index < cache->internal->group_end);
  271|       |
  272|  12.7M|    struct m_group_data *gd = m_config_gdata(cache->internal->data, group_index);
  273|  12.7M|    const struct m_option *opt =
  274|  12.7M|        &cache->shadow->groups[group_index].group->opts[opt_index];
  275|       |
  276|  12.7M|    return gd && opt->offset >= 0 ? gd->udata + opt->offset : NULL;
  ------------------
  |  Branch (276:12): [True: 12.7M, False: 0]
  |  Branch (276:18): [True: 11.8M, False: 853k]
  ------------------
  277|  12.7M|}
m_config_cache_get_option_change_mask:
  293|   221k|{
  294|   221k|    struct m_config_shadow *shadow = cache->shadow;
  295|   221k|    int group_index, opt_index;
  296|   221k|    get_opt_from_id(shadow, id, &group_index, &opt_index);
  297|       |
  298|   221k|    mp_assert(group_index >= cache->internal->group_start &&
  ------------------
  |  |   41|   221k|#define mp_assert assert
  ------------------
  299|   221k|           group_index < cache->internal->group_end);
  300|       |
  301|   221k|    return get_opt_change_mask(cache->shadow, group_index,
  302|   221k|                               cache->internal->data->group_index,
  303|   221k|                               &shadow->groups[group_index].group->opts[opt_index]);
  304|   221k|}
m_config_shadow_new:
  443|  28.2k|{
  444|  28.2k|    struct m_config_shadow *shadow = talloc_zero(NULL, struct m_config_shadow);
  ------------------
  |  |   27|  28.2k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  28.2k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  28.2k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  445|  28.2k|    talloc_set_destructor(shadow, shadow_destroy);
  ------------------
  |  |   41|  28.2k|#define talloc_set_destructor           ta_set_destructor
  ------------------
  446|  28.2k|    mp_mutex_init(&shadow->lock);
  447|       |
  448|  28.2k|    add_sub_group(shadow, NULL, -1, -1, root);
  449|       |
  450|  28.2k|    if (!root->size)
  ------------------
  |  Branch (450:9): [True: 11.1k, False: 17.0k]
  ------------------
  451|  11.1k|        return shadow;
  452|       |
  453|  17.0k|    shadow->data = allocate_option_data(shadow, shadow, 0, NULL);
  454|       |
  455|  17.0k|    return shadow;
  456|  28.2k|}
m_config_cache_from_shadow:
  561|   101k|{
  562|   101k|    int group_index = -1;
  563|       |
  564|  2.15M|    for (int n = 0; n < shadow->num_groups; n++) {
  ------------------
  |  Branch (564:21): [True: 2.15M, False: 0]
  ------------------
  565|  2.15M|        if (shadow->groups[n].group == group) {
  ------------------
  |  Branch (565:13): [True: 101k, False: 2.05M]
  ------------------
  566|   101k|            group_index = n;
  567|   101k|            break;
  568|   101k|        }
  569|  2.15M|    }
  570|       |
  571|   101k|    mp_assert(group_index >= 0); // invalid group (or not in option tree)
  ------------------
  |  |   41|   101k|#define mp_assert assert
  ------------------
  572|       |
  573|   101k|    struct cache_alloc {
  574|   101k|        struct m_config_cache a;
  575|   101k|        struct config_cache b;
  576|   101k|    };
  577|   101k|    struct cache_alloc *alloc = talloc_zero(ta_parent, struct cache_alloc);
  ------------------
  |  |   27|   101k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|   101k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|   101k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  578|   101k|    mp_assert((void *)&alloc->a == (void *)alloc);
  ------------------
  |  |   41|   101k|#define mp_assert assert
  ------------------
  579|   101k|    struct m_config_cache *cache = &alloc->a;
  580|   101k|    talloc_set_destructor(cache, cache_destroy);
  ------------------
  |  |   41|   101k|#define talloc_set_destructor           ta_set_destructor
  ------------------
  581|   101k|    cache->internal = &alloc->b;
  582|   101k|    cache->shadow = shadow;
  583|       |
  584|   101k|    struct config_cache *in = cache->internal;
  585|   101k|    in->shadow = shadow;
  586|   101k|    in->src = shadow->data;
  587|       |
  588|   101k|    mp_mutex_lock(&shadow->lock);
  ------------------
  |  |  131|   101k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  589|   101k|    in->data = allocate_option_data(cache, shadow, group_index, in->src);
  590|   101k|    mp_mutex_unlock(&shadow->lock);
  ------------------
  |  |  133|   101k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  591|       |
  592|   101k|    cache->opts = in->data->gdata[0].udata;
  593|       |
  594|   101k|    in->group_start = in->data->group_index;
  595|   101k|    in->group_end = in->group_start + in->data->num_gdata;
  596|   101k|    mp_assert(shadow->groups[in->group_start].group_count == in->data->num_gdata);
  ------------------
  |  |   41|   101k|#define mp_assert assert
  ------------------
  597|       |
  598|   101k|    in->upd_group = -1;
  599|       |
  600|   101k|    return cache;
  601|   101k|}
m_config_cache_alloc:
  606|  84.4k|{
  607|  84.4k|    return m_config_cache_from_shadow(ta_parent, global->config, group);
  608|  84.4k|}
m_config_cache_update:
  720|  53.8k|{
  721|  53.8k|    struct config_cache *in = cache->internal;
  722|  53.8k|    struct m_config_shadow *shadow = in->shadow;
  723|       |
  724|  53.8k|    if (!cache_check_update(cache))
  ------------------
  |  Branch (724:9): [True: 24.4k, False: 29.3k]
  ------------------
  725|  24.4k|        return false;
  726|       |
  727|  29.3k|    mp_mutex_lock(&shadow->lock);
  ------------------
  |  |  131|  29.3k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  728|  29.3k|    bool res = false;
  729|  83.8k|    while (1) {
  ------------------
  |  Branch (729:12): [Folded - Ignored]
  ------------------
  730|  83.8k|        void *p;
  731|  83.8k|        update_next_option(cache, &p);
  732|  83.8k|        if (!p)
  ------------------
  |  Branch (732:13): [True: 29.3k, False: 54.4k]
  ------------------
  733|  29.3k|            break;
  734|  54.4k|        res = true;
  735|  54.4k|    }
  736|  29.3k|    mp_mutex_unlock(&shadow->lock);
  ------------------
  |  |  133|  29.3k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  737|  29.3k|    return res;
  738|  53.8k|}
m_config_cache_get_next_changed:
  741|      6|{
  742|      6|    struct config_cache *in = cache->internal;
  743|      6|    struct m_config_shadow *shadow = in->shadow;
  744|       |
  745|      6|    *opt = NULL;
  746|      6|    if (!cache_check_update(cache) && in->upd_group < 0)
  ------------------
  |  Branch (746:9): [True: 0, False: 6]
  |  Branch (746:39): [True: 0, False: 0]
  ------------------
  747|      0|        return false;
  748|       |
  749|      6|    mp_mutex_lock(&shadow->lock);
  ------------------
  |  |  131|      6|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  750|      6|    update_next_option(cache, opt);
  751|      6|    mp_mutex_unlock(&shadow->lock);
  ------------------
  |  |  133|      6|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  752|      6|    return !!*opt;
  753|      6|}
m_config_cache_write_opt:
  782|   327k|{
  783|   327k|    struct config_cache *in = cache->internal;
  784|   327k|    struct m_config_shadow *shadow = in->shadow;
  785|       |
  786|   327k|    int group_idx = -1;
  787|   327k|    int opt_idx = -1;
  788|   327k|    find_opt(shadow, in->data, ptr, &group_idx, &opt_idx);
  789|       |
  790|       |    // ptr was not in cache->opts, or no option declaration matching it.
  791|   327k|    mp_assert(group_idx >= 0);
  ------------------
  |  |   41|   327k|#define mp_assert assert
  ------------------
  792|       |
  793|   327k|    struct m_config_group *g = &shadow->groups[group_idx];
  794|   327k|    const struct m_option *opt = &g->group->opts[opt_idx];
  795|       |
  796|   327k|    mp_mutex_lock(&shadow->lock);
  ------------------
  |  |  131|   327k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  797|       |
  798|   327k|    struct m_group_data *gdst = m_config_gdata(in->data, group_idx);
  799|   327k|    struct m_group_data *gsrc = m_config_gdata(in->src, group_idx);
  800|   327k|    mp_assert(gdst && gsrc);
  ------------------
  |  |   41|   327k|#define mp_assert assert
  ------------------
  801|       |
  802|   327k|    bool changed = !m_option_equal(opt, gsrc->udata + opt->offset, ptr) ||
  ------------------
  |  Branch (802:20): [True: 221k, False: 106k]
  ------------------
  803|   327k|                   opt->force_update;
  ------------------
  |  Branch (803:20): [True: 737, False: 105k]
  ------------------
  804|   327k|    if (changed) {
  ------------------
  |  Branch (804:9): [True: 221k, False: 105k]
  ------------------
  805|   221k|        m_option_copy(opt, gsrc->udata + opt->offset, ptr);
  806|       |
  807|   221k|        gsrc->ts = atomic_fetch_add(&shadow->ts, 1) + 1;
  808|       |
  809|   221k|        for (int n = 0; n < shadow->num_listeners; n++) {
  ------------------
  |  Branch (809:25): [True: 6, False: 221k]
  ------------------
  810|      6|            struct config_cache *listener = shadow->listeners[n];
  811|      6|            if (listener->wakeup_cb && m_config_gdata(listener->data, group_idx))
  ------------------
  |  Branch (811:17): [True: 6, False: 0]
  |  Branch (811:40): [True: 6, False: 0]
  ------------------
  812|      6|                listener->wakeup_cb(listener->wakeup_cb_ctx);
  813|      6|        }
  814|   221k|    }
  815|       |
  816|   327k|    if (opt->force_update)
  ------------------
  |  Branch (816:9): [True: 2.46k, False: 325k]
  ------------------
  817|  2.46k|        append_force_update(cache, gsrc, opt->name);
  818|       |
  819|   327k|    mp_mutex_unlock(&shadow->lock);
  ------------------
  |  |  133|   327k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  820|       |
  821|   327k|    return changed;
  822|   327k|}
m_config_cache_set_wakeup_cb:
  826|   227k|{
  827|   227k|    struct config_cache *in = cache->internal;
  828|   227k|    struct m_config_shadow *shadow = in->shadow;
  829|       |
  830|   227k|    mp_mutex_lock(&shadow->lock);
  ------------------
  |  |  131|   227k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  831|   227k|    if (in->in_list) {
  ------------------
  |  Branch (831:9): [True: 24.4k, False: 203k]
  ------------------
  832|  24.5k|        for (int n = 0; n < shadow->num_listeners; n++) {
  ------------------
  |  Branch (832:25): [True: 12.3k, False: 12.2k]
  ------------------
  833|  12.3k|            if (shadow->listeners[n] == in) {
  ------------------
  |  Branch (833:17): [True: 12.2k, False: 152]
  ------------------
  834|  12.2k|                MP_TARRAY_REMOVE_AT(shadow->listeners, shadow->num_listeners, n);
  ------------------
  |  |  143|  12.2k|    do {                                            \
  |  |  144|  12.2k|        size_t at_ = (at);                          \
  |  |  145|  12.2k|        assert(at_ <= (idxvar));                    \
  |  |  146|  12.2k|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|  12.2k|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|  12.2k|        (idxvar)--;                                 \
  |  |  149|  12.2k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  835|  12.2k|                break;
  836|  12.2k|            }
  837|  12.3k|        }
  838|  24.5k|        for (int n = 0; n < shadow->num_listeners; n++)
  ------------------
  |  Branch (838:25): [True: 152, False: 24.4k]
  ------------------
  839|  24.4k|            mp_assert(shadow->listeners[n] != in); // only 1 wakeup_cb per cache
  ------------------
  |  |   41|  24.4k|#define mp_assert assert
  ------------------
  840|       |        // (The deinitialization path relies on this to free all memory.)
  841|  24.4k|        if (!shadow->num_listeners) {
  ------------------
  |  Branch (841:13): [True: 24.2k, False: 152]
  ------------------
  842|  24.2k|            talloc_free(shadow->listeners);
  ------------------
  |  |   47|  24.2k|#define talloc_free                     ta_free
  ------------------
  843|  24.2k|            shadow->listeners = NULL;
  844|  24.2k|        }
  845|  24.4k|    }
  846|   227k|    if (cb) {
  ------------------
  |  Branch (846:9): [True: 12.2k, False: 215k]
  ------------------
  847|  12.2k|        MP_TARRAY_APPEND(NULL, shadow->listeners, shadow->num_listeners, in);
  ------------------
  |  |  105|  12.2k|    do {                                            \
  |  |  106|  12.2k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  12.2k|    do {                                            \
  |  |  |  |   97|  12.2k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  12.2k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  12.2k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  12.2k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 12.1k, False: 76]
  |  |  |  |  ------------------
  |  |  |  |   99|  12.2k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  12.1k|    do {                                                        \
  |  |  |  |  |  |   89|  12.1k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  12.1k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  12.1k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  12.1k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  12.1k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  12.1k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  12.1k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  12.2k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  12.2k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  12.2k|        (idxvar)++;                                 \
  |  |  109|  12.2k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  848|  12.2k|        in->in_list = true;
  849|  12.2k|        in->wakeup_cb = cb;
  850|  12.2k|        in->wakeup_cb_ctx = cb_ctx;
  851|  12.2k|    }
  852|   227k|    mp_mutex_unlock(&shadow->lock);
  ------------------
  |  |  133|   227k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  853|   227k|}
m_config_cache_set_dispatch_change_cb:
  868|   113k|{
  869|   113k|    struct config_cache *in = cache->internal;
  870|       |
  871|       |    // Removing the old one is tricky. First make sure no new notifications will
  872|       |    // come.
  873|   113k|    m_config_cache_set_wakeup_cb(cache, NULL, NULL);
  874|       |    // Remove any pending notifications (assume we're on the same thread as
  875|       |    // any potential mp_dispatch_queue_process() callers).
  876|   113k|    if (in->wakeup_dispatch_queue) {
  ------------------
  |  Branch (876:9): [True: 12.2k, False: 101k]
  ------------------
  877|  12.2k|        mp_dispatch_cancel_fn(in->wakeup_dispatch_queue,
  878|  12.2k|                              in->wakeup_dispatch_cb,
  879|  12.2k|                              in->wakeup_dispatch_cb_ctx);
  880|  12.2k|    }
  881|       |
  882|   113k|    in->wakeup_dispatch_queue = NULL;
  883|   113k|    in->wakeup_dispatch_cb = NULL;
  884|   113k|    in->wakeup_dispatch_cb_ctx = NULL;
  885|       |
  886|   113k|    if (cb) {
  ------------------
  |  Branch (886:9): [True: 12.2k, False: 101k]
  ------------------
  887|  12.2k|        in->wakeup_dispatch_queue = dispatch;
  888|  12.2k|        in->wakeup_dispatch_cb = cb;
  889|  12.2k|        in->wakeup_dispatch_cb_ctx = cb_ctx;
  890|  12.2k|        m_config_cache_set_wakeup_cb(cache, dispatch_notify, in);
  891|  12.2k|    }
  892|   113k|}
mp_get_config_group:
  896|  47.1k|{
  897|  47.1k|    struct m_config_cache *cache = m_config_cache_alloc(NULL, global, group);
  898|       |    // Make talloc_free(cache->opts) free the entire cache.
  899|  47.1k|    ta_set_parent(cache->opts, ta_parent);
  900|  47.1k|    ta_set_parent(cache, cache->opts);
  901|  47.1k|    return cache->opts;
  902|  47.1k|}
m_config_group_from_desc:
  919|     76|{
  920|     76|    const struct m_config_group *group = find_group(global, desc->options);
  921|     76|    if (group) {
  ------------------
  |  Branch (921:9): [True: 39, False: 37]
  ------------------
  922|     39|        return mp_get_config_group(ta_parent, global, group->group);
  923|     39|    } else {
  924|     37|        void *d = talloc_zero_size(ta_parent, desc->priv_size);
  ------------------
  |  |   44|     37|#define talloc_zero_size                ta_xzalloc_size
  |  |  ------------------
  |  |  |  |  121|     37|#define ta_xzalloc_size(...)            ta_oom_p(ta_zalloc_size(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  154|     37|#define ta_zalloc_size(...)     ta_dbg_set_loc(ta_zalloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|     37|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|     37|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|     37|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  925|     37|        if (desc->priv_defaults)
  ------------------
  |  Branch (925:13): [True: 0, False: 37]
  ------------------
  926|      0|            memcpy(d, desc->priv_defaults, desc->priv_size);
  927|     37|        return d;
  928|     37|    }
  929|     76|}
m_config_core.c:iter_next:
  154|  12.8M|{
  155|  12.8M|    int32_t id = *p_id;
  156|  12.8M|    int group_index = id == -1 ? group_start : id >> 16;
  ------------------
  |  Branch (156:23): [True: 28.2k, False: 12.7M]
  ------------------
  157|  12.8M|    int opt_index = id == -1 ? -1 : id & 0xFFFF;
  ------------------
  |  Branch (157:21): [True: 28.2k, False: 12.7M]
  ------------------
  158|       |
  159|  12.8M|    mp_assert(group_index >= group_start && group_index <= group_end);
  ------------------
  |  |   41|  12.8M|#define mp_assert assert
  ------------------
  160|       |
  161|  14.3M|    while (1) {
  ------------------
  |  Branch (161:12): [Folded - Ignored]
  ------------------
  162|  14.3M|        if (group_index >= group_end)
  ------------------
  |  Branch (162:13): [True: 28.2k, False: 14.3M]
  ------------------
  163|  28.2k|            return false;
  164|       |
  165|  14.3M|        struct m_config_group *g = &shadow->groups[group_index];
  166|  14.3M|        const struct m_option *opts = g->group->opts;
  167|       |
  168|  14.3M|        mp_assert(opt_index >= -1 && opt_index < g->opt_count);
  ------------------
  |  |   41|  14.3M|#define mp_assert assert
  ------------------
  169|       |
  170|  14.3M|        opt_index += 1;
  171|       |
  172|  14.3M|        if (!opts || !opts[opt_index].name) {
  ------------------
  |  Branch (172:13): [True: 6.17k, False: 14.3M]
  |  Branch (172:22): [True: 824k, False: 13.4M]
  ------------------
  173|   830k|            group_index += 1;
  174|   830k|            opt_index = -1;
  175|   830k|            continue;
  176|   830k|        }
  177|       |
  178|  13.4M|        if (opts[opt_index].type == &m_option_type_subconfig)
  ------------------
  |  Branch (178:13): [True: 699k, False: 12.7M]
  ------------------
  179|   699k|            continue;
  180|       |
  181|  12.7M|        *p_id = (group_index << 16) | opt_index;
  182|  12.7M|        return true;
  183|  13.4M|    }
  184|  12.8M|}
m_config_core.c:get_opt_from_id:
  199|  39.3M|{
  200|  39.3M|    int group_index = id >> 16;
  201|  39.3M|    int opt_index = id & 0xFFFF;
  202|       |
  203|  39.3M|    mp_assert(group_index >= 0 && group_index < shadow->num_groups);
  ------------------
  |  |   41|  39.3M|#define mp_assert assert
  ------------------
  204|  39.3M|    mp_assert(opt_index >= 0 && opt_index < shadow->groups[group_index].opt_count);
  ------------------
  |  |   41|  39.3M|#define mp_assert assert
  ------------------
  205|       |
  206|  39.3M|    *out_group_index = group_index;
  207|  39.3M|    *out_opt_index = opt_index;
  208|  39.3M|}
m_config_core.c:concat_name_buf:
  132|  13.6M|{
  133|  13.6M|    mp_assert(a);
  ------------------
  |  |   41|  13.6M|#define mp_assert assert
  ------------------
  134|  13.6M|    mp_assert(b);
  ------------------
  |  |   41|  13.6M|#define mp_assert assert
  ------------------
  135|  13.6M|    if (!a[0])
  ------------------
  |  Branch (135:9): [True: 10.5M, False: 3.09M]
  ------------------
  136|  10.5M|        return b;
  137|  3.09M|    if (!b[0])
  ------------------
  |  Branch (137:9): [True: 0, False: 3.09M]
  ------------------
  138|      0|        return a;
  139|  3.09M|    snprintf(buf, buf_size, "%s-%s", a, b);
  140|  3.09M|    return buf;
  141|  3.09M|}
m_config_core.c:m_config_gdata:
  120|  21.1M|{
  121|  21.1M|    if (group_index < data->group_index ||
  ------------------
  |  Branch (121:9): [True: 0, False: 21.1M]
  ------------------
  122|  21.1M|        group_index >= data->group_index + data->num_gdata)
  ------------------
  |  Branch (122:9): [True: 0, False: 21.1M]
  ------------------
  123|      0|        return NULL;
  124|       |
  125|  21.1M|    return &data->gdata[group_index - data->group_index];
  126|  21.1M|}
m_config_core.c:get_opt_change_mask:
  281|   276k|{
  282|   276k|    uint64_t changed = opt->flags & UPDATE_OPTS_MASK;
  ------------------
  |  |  453|   276k|#define UPDATE_OPTS_MASK        ((UPDATE_OPT_LAST << 1) - 1)
  |  |  ------------------
  |  |  |  |  450|   276k|#define UPDATE_OPT_LAST         (UINT64_C(1) << 20)
  |  |  ------------------
  ------------------
  283|   347k|    while (group_index != group_root) {
  ------------------
  |  Branch (283:12): [True: 70.7k, False: 276k]
  ------------------
  284|  70.7k|        struct m_config_group *g = &shadow->groups[group_index];
  285|  70.7k|        changed |= g->group->change_flags;
  286|  70.7k|        group_index = g->parent_group;
  287|  70.7k|    }
  288|   276k|    return changed;
  289|   276k|}
m_config_core.c:shadow_destroy:
  432|  28.2k|{
  433|  28.2k|    struct m_config_shadow *shadow = p;
  434|       |
  435|       |    // must all have been unregistered
  436|  28.2k|    mp_assert(shadow->num_listeners == 0);
  ------------------
  |  |   41|  28.2k|#define mp_assert assert
  ------------------
  437|       |
  438|  28.2k|    talloc_free(shadow->data);
  ------------------
  |  |   47|  28.2k|#define talloc_free                     ta_free
  ------------------
  439|  28.2k|    mp_mutex_destroy(&shadow->lock);
  ------------------
  |  |  130|  28.2k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
  440|  28.2k|}
m_config_core.c:allocate_option_data:
  414|   118k|{
  415|   118k|    mp_assert(group_index >= 0 && group_index < shadow->num_groups);
  ------------------
  |  |   41|   118k|#define mp_assert assert
  ------------------
  416|   118k|    struct m_config_data *data = talloc_zero(ta_parent, struct m_config_data);
  ------------------
  |  |   27|   118k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|   118k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|   118k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  417|   118k|    talloc_set_destructor(data, free_option_data);
  ------------------
  |  |   41|   118k|#define talloc_set_destructor           ta_set_destructor
  ------------------
  418|       |
  419|   118k|    data->shadow = shadow;
  420|   118k|    data->group_index = group_index;
  421|       |
  422|   118k|    struct m_config_group *root_group = &shadow->groups[group_index];
  423|   118k|    mp_assert(root_group->group_count > 0);
  ------------------
  |  |   41|   118k|#define mp_assert assert
  ------------------
  424|       |
  425|  2.46M|    for (int n = group_index; n < group_index + root_group->group_count; n++)
  ------------------
  |  Branch (425:31): [True: 2.34M, False: 118k]
  ------------------
  426|  2.34M|        alloc_group(data, n, copy);
  427|       |
  428|   118k|    return data;
  429|   118k|}
m_config_core.c:free_option_data:
  388|   118k|{
  389|   118k|    struct m_config_data *data = p;
  390|       |
  391|  2.46M|    for (int i = 0; i < data->num_gdata; i++) {
  ------------------
  |  Branch (391:21): [True: 2.34M, False: 118k]
  ------------------
  392|  2.34M|        struct m_group_data *gdata = &data->gdata[i];
  393|  2.34M|        struct m_config_group *group =
  394|  2.34M|            &data->shadow->groups[data->group_index + i];
  395|  2.34M|        const struct m_option *opts = group->group->opts;
  396|       |
  397|  40.5M|        for (int n = 0; opts && opts[n].name; n++) {
  ------------------
  |  Branch (397:25): [True: 40.5M, False: 0]
  |  Branch (397:33): [True: 38.1M, False: 2.34M]
  ------------------
  398|  38.1M|            const struct m_option *opt = &opts[n];
  399|       |
  400|  38.1M|            if (opt->offset >= 0 && opt->type->size > 0)
  ------------------
  |  Branch (400:17): [True: 35.7M, False: 2.43M]
  |  Branch (400:37): [True: 33.7M, False: 1.94M]
  ------------------
  401|  33.7M|                m_option_free(opt, gdata->udata + opt->offset);
  402|  38.1M|        }
  403|  2.34M|    }
  404|   118k|}
m_config_core.c:alloc_group:
  341|  2.34M|{
  342|  2.34M|    mp_assert(group_index == data->group_index + data->num_gdata);
  ------------------
  |  |   41|  2.34M|#define mp_assert assert
  ------------------
  343|  2.34M|    mp_assert(group_index < data->shadow->num_groups);
  ------------------
  |  |   41|  2.34M|#define mp_assert assert
  ------------------
  344|  2.34M|    struct m_config_group *group = &data->shadow->groups[group_index];
  345|  2.34M|    const struct m_sub_options *opts = group->group;
  346|       |
  347|  2.34M|    MP_TARRAY_GROW(data, data->gdata, data->num_gdata);
  ------------------
  |  |   96|  2.34M|    do {                                            \
  |  |   97|  2.34M|        size_t nextidx_ = (nextidx);                \
  |  |   98|  2.34M|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  ------------------
  |  |  |  |   84|  2.34M|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  ------------------
  |  |  |  |  |  |   45|  2.34M|#define talloc_get_size                 ta_get_size
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  |  Branch (98:13): [True: 322k, False: 2.02M]
  |  |  ------------------
  |  |   99|  2.34M|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  ------------------
  |  |  |  |   88|   322k|    do {                                                        \
  |  |  |  |   89|   322k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|   322k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|   322k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|   322k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|   322k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   90|   322k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |   91|   322k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  100|  2.34M|    } while (0)
  |  |  ------------------
  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  348|  2.34M|    struct m_group_data *gdata = &data->gdata[data->num_gdata++];
  349|       |
  350|  2.34M|    struct m_group_data *copy_gdata =
  351|  2.34M|        copy ? m_config_gdata(copy, group_index) : NULL;
  ------------------
  |  Branch (351:9): [True: 1.52M, False: 819k]
  ------------------
  352|       |
  353|  2.34M|    *gdata = (struct m_group_data){
  354|  2.34M|        .udata = talloc_zero_size(data, opts->size),
  ------------------
  |  |   44|  2.34M|#define talloc_zero_size                ta_xzalloc_size
  |  |  ------------------
  |  |  |  |  121|  2.34M|#define ta_xzalloc_size(...)            ta_oom_p(ta_zalloc_size(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  154|  2.34M|#define ta_zalloc_size(...)     ta_dbg_set_loc(ta_zalloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|  2.34M|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|  2.34M|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|  2.34M|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  355|  2.34M|        .ts = copy_gdata ? copy_gdata->ts : 0,
  ------------------
  |  Branch (355:15): [True: 1.52M, False: 819k]
  ------------------
  356|  2.34M|    };
  357|       |
  358|  2.34M|    if (opts->defaults)
  ------------------
  |  Branch (358:9): [True: 2.11M, False: 233k]
  ------------------
  359|  2.11M|        memcpy(gdata->udata, opts->defaults, opts->size);
  360|       |
  361|  2.34M|    char *copy_src = copy_gdata ? copy_gdata->udata : NULL;
  ------------------
  |  Branch (361:22): [True: 1.52M, False: 819k]
  ------------------
  362|       |
  363|  40.5M|    for (int n = 0; opts->opts && opts->opts[n].name; n++) {
  ------------------
  |  Branch (363:21): [True: 40.5M, False: 0]
  |  Branch (363:35): [True: 38.1M, False: 2.34M]
  ------------------
  364|  38.1M|        const struct m_option *opt = &opts->opts[n];
  365|       |
  366|  38.1M|        if (opt->offset < 0 || opt->type->size == 0)
  ------------------
  |  Branch (366:13): [True: 2.43M, False: 35.7M]
  |  Branch (366:32): [True: 1.94M, False: 33.7M]
  ------------------
  367|  4.38M|            continue;
  368|       |
  369|  33.7M|        void *dst = gdata->udata + opt->offset;
  370|  33.7M|        const void *defptr = opt->defval ? opt->defval : dst;
  ------------------
  |  Branch (370:30): [True: 46.9k, False: 33.7M]
  ------------------
  371|  33.7M|        if (copy_src)
  ------------------
  |  Branch (371:13): [True: 21.9M, False: 11.8M]
  ------------------
  372|  21.9M|            defptr = copy_src + opt->offset;
  373|       |
  374|  33.7M|        init_opt_inplace(opt, dst, defptr);
  375|  33.7M|    }
  376|       |
  377|       |    // If there's a parent, update its pointer to the new struct.
  378|  2.34M|    if (group->parent_group >= data->group_index && group->parent_ptr >= 0) {
  ------------------
  |  Branch (378:9): [True: 2.22M, False: 118k]
  |  Branch (378:53): [True: 1.94M, False: 280k]
  ------------------
  379|  1.94M|        struct m_group_data *parent_gdata =
  380|  1.94M|            m_config_gdata(data, group->parent_group);
  381|  1.94M|        mp_assert(parent_gdata);
  ------------------
  |  |   41|  1.94M|#define mp_assert assert
  ------------------
  382|       |
  383|  1.94M|        substruct_write_ptr(parent_gdata->udata + group->parent_ptr, gdata->udata);
  384|  1.94M|    }
  385|  2.34M|}
m_config_core.c:init_opt_inplace:
  327|  33.7M|{
  328|       |    // The option will use dynamic memory allocation iff it has a free callback.
  329|  33.7M|    if (opt->type->free) {
  ------------------
  |  Branch (329:9): [True: 6.38M, False: 27.4M]
  ------------------
  330|  6.38M|        union m_option_value temp;
  331|  6.38M|        memcpy(&temp, src, opt->type->size);
  332|  6.38M|        memset(dst, 0, opt->type->size);
  333|  6.38M|        m_option_copy(opt, dst, &temp);
  334|  27.4M|    } else if (src != dst) {
  ------------------
  |  Branch (334:16): [True: 17.8M, False: 9.59M]
  ------------------
  335|  17.8M|        memcpy(dst, src, opt->type->size);
  336|  17.8M|    }
  337|  33.7M|}
m_config_core.c:substruct_write_ptr:
  318|  1.94M|{
  319|  1.94M|    struct mp_dummy_ *src = val;
  320|  1.94M|    memcpy(ptr, &src, sizeof(src));
  321|  1.94M|}
m_config_core.c:add_sub_group:
  486|   830k|{
  487|       |    // Can't be used multiple times.
  488|  20.0M|    for (int n = 0; n < shadow->num_groups; n++)
  ------------------
  |  Branch (488:21): [True: 19.2M, False: 830k]
  ------------------
  489|  19.2M|        mp_assert(shadow->groups[n].group != subopts);
  ------------------
  |  |   41|   830k|#define mp_assert assert
  ------------------
  490|       |
  491|   830k|    if (!name_prefix)
  ------------------
  |  Branch (491:9): [True: 130k, False: 699k]
  ------------------
  492|   130k|        name_prefix = "";
  493|   830k|    if (subopts->prefix && subopts->prefix[0]) {
  ------------------
  |  Branch (493:9): [True: 85.3k, False: 745k]
  |  Branch (493:28): [True: 85.3k, False: 0]
  ------------------
  494|  85.3k|        mp_assert(!name_prefix[0]);
  ------------------
  |  |   41|  85.3k|#define mp_assert assert
  ------------------
  495|  85.3k|        name_prefix = subopts->prefix;
  496|  85.3k|    }
  497|       |
  498|       |    // You can only use UPDATE_ flags here.
  499|   830k|    mp_assert(!(subopts->change_flags & ~UPDATE_OPTS_MASK));
  ------------------
  |  |   41|   830k|#define mp_assert assert
  ------------------
  500|       |
  501|   830k|    mp_assert(parent_group_index >= -1 && parent_group_index < shadow->num_groups);
  ------------------
  |  |   41|   830k|#define mp_assert assert
  ------------------
  502|       |
  503|   830k|    int group_index = shadow->num_groups++;
  504|   830k|    MP_TARRAY_GROW(shadow, shadow->groups, group_index);
  ------------------
  |  |   96|   830k|    do {                                            \
  |  |   97|   830k|        size_t nextidx_ = (nextidx);                \
  |  |   98|   830k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  ------------------
  |  |  |  |   84|   830k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  ------------------
  |  |  |  |  |  |   45|   830k|#define talloc_get_size                 ta_get_size
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  |  Branch (98:13): [True: 96.4k, False: 734k]
  |  |  ------------------
  |  |   99|   830k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  ------------------
  |  |  |  |   88|  96.4k|    do {                                                        \
  |  |  |  |   89|  96.4k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|  96.4k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|  96.4k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|  96.4k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|  96.4k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   90|  96.4k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |   91|  96.4k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  100|   830k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  505|   830k|    shadow->groups[group_index] = (struct m_config_group){
  506|   830k|        .group = subopts,
  507|   830k|        .parent_group = parent_group_index,
  508|   830k|        .parent_ptr = parent_ptr,
  509|   830k|        .prefix = name_prefix,
  510|   830k|    };
  511|       |
  512|  14.3M|    for (int i = 0; subopts->opts && subopts->opts[i].name; i++) {
  ------------------
  |  Branch (512:21): [True: 14.3M, False: 6.17k]
  |  Branch (512:38): [True: 13.4M, False: 824k]
  ------------------
  513|  13.4M|        const struct m_option *opt = &subopts->opts[i];
  514|       |
  515|  13.4M|        if (opt->type == &m_option_type_subconfig) {
  ------------------
  |  Branch (515:13): [True: 699k, False: 12.7M]
  ------------------
  516|   699k|            const struct m_sub_options *new_subopts = opt->priv;
  517|       |
  518|       |            // Providing default structs in-place is not allowed.
  519|   699k|            if (opt->offset >= 0 && subopts->defaults) {
  ------------------
  |  Branch (519:17): [True: 699k, False: 0]
  |  Branch (519:37): [True: 682k, False: 17.0k]
  ------------------
  520|   682k|                void *ptr = (char *)subopts->defaults + opt->offset;
  521|   682k|                mp_assert(!substruct_read_ptr(ptr));
  ------------------
  |  |   41|   682k|#define mp_assert assert
  ------------------
  522|   682k|            }
  523|       |
  524|   699k|            const char *prefix = concat_name(shadow, name_prefix, opt->name);
  525|   699k|            add_sub_group(shadow, prefix, group_index, opt->offset, new_subopts);
  526|       |
  527|  12.7M|        } else if (opt->type == &m_option_type_obj_settings_list) {
  ------------------
  |  Branch (527:20): [True: 119k, False: 12.6M]
  ------------------
  528|   119k|            const struct m_obj_list *objlist = opt->priv;
  529|   119k|            init_obj_settings_list(shadow, group_index, objlist);
  530|   119k|        }
  531|       |
  532|  13.4M|        shadow->groups[group_index].opt_count = i + 1;
  533|  13.4M|    }
  534|       |
  535|   830k|    if (subopts->get_sub_options) {
  ------------------
  |  Branch (535:9): [True: 17.0k, False: 813k]
  ------------------
  536|   221k|        for (int i = 0; ; i++) {
  537|   221k|            const struct m_sub_options *sub = NULL;
  538|   221k|            if (!subopts->get_sub_options(i, &sub))
  ------------------
  |  Branch (538:17): [True: 17.0k, False: 204k]
  ------------------
  539|  17.0k|                break;
  540|   204k|            if (sub)
  ------------------
  |  Branch (540:17): [True: 0, False: 204k]
  ------------------
  541|      0|                add_sub_group(shadow, NULL, group_index, -1, sub);
  542|   204k|        }
  543|  17.0k|    }
  544|       |
  545|   830k|    shadow->groups[group_index].group_count = shadow->num_groups - group_index;
  546|   830k|}
m_config_core.c:substruct_read_ptr:
  312|   682k|{
  313|   682k|    struct mp_dummy_ *res;
  314|   682k|    memcpy(&res, ptr, sizeof(res));
  315|   682k|    return res;
  316|   682k|}
m_config_core.c:concat_name:
  146|   699k|{
  147|   699k|    char buf[M_CONFIG_MAX_OPT_NAME_LEN];
  148|   699k|    const char *r = concat_name_buf(buf, sizeof(buf), a, b);
  149|   699k|    return r == buf ? talloc_strdup(ta_parent, r) : r;
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  |  Branch (149:12): [True: 0, False: 699k]
  ------------------
  150|   699k|}
m_config_core.c:init_obj_settings_list:
  461|   119k|{
  462|   119k|    struct m_obj_desc desc;
  463|   546k|    for (int n = 0; ; n++) {
  464|   546k|        if (!list->get_desc(&desc, n))
  ------------------
  |  Branch (464:13): [True: 119k, False: 426k]
  ------------------
  465|   119k|            break;
  466|   426k|        if (desc.global_opts) {
  ------------------
  |  Branch (466:13): [True: 17.0k, False: 409k]
  ------------------
  467|  17.0k|            add_sub_group(shadow, NULL, parent_group_index, -1,
  468|  17.0k|                          desc.global_opts);
  469|  17.0k|        }
  470|   426k|        if (list->use_global_options && desc.options) {
  ------------------
  |  Branch (470:13): [True: 238k, False: 187k]
  |  Branch (470:41): [True: 85.3k, False: 153k]
  ------------------
  471|  85.3k|            struct m_sub_options *conf = talloc_ptrtype(shadow, conf);
  ------------------
  |  |   34|  85.3k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  85.3k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  85.3k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  472|  85.3k|            *conf = (struct m_sub_options){
  473|  85.3k|                .prefix = desc.options_prefix,
  474|  85.3k|                .opts = desc.options,
  475|  85.3k|                .defaults = desc.priv_defaults,
  476|  85.3k|                .size = desc.priv_size,
  477|  85.3k|            };
  478|  85.3k|            add_sub_group(shadow, NULL, parent_group_index, -1, conf);
  479|  85.3k|        }
  480|   426k|    }
  481|   119k|}
m_config_core.c:cache_destroy:
  549|   101k|{
  550|   101k|    struct m_config_cache *cache = p;
  551|       |
  552|       |    // (technically speaking, being able to call them both without anything
  553|       |    // breaking is a feature provided by these functions)
  554|   101k|    m_config_cache_set_wakeup_cb(cache, NULL, NULL);
  555|   101k|    m_config_cache_set_dispatch_change_cb(cache, NULL, NULL, NULL);
  556|   101k|}
m_config_core.c:cache_check_update:
  703|  53.8k|{
  704|  53.8k|    struct config_cache *in = cache->internal;
  705|  53.8k|    struct m_config_shadow *shadow = in->shadow;
  706|       |
  707|       |    // Using atomics and checking outside of the lock - it's unknown whether
  708|       |    // this makes it faster or slower. Just cargo culting it.
  709|  53.8k|    uint64_t new_ts = atomic_load(&shadow->ts);
  710|  53.8k|    if (in->ts >= new_ts)
  ------------------
  |  Branch (710:9): [True: 24.4k, False: 29.3k]
  ------------------
  711|  24.4k|        return false;
  712|       |
  713|  29.3k|    in->ts = new_ts;
  714|  29.3k|    in->upd_group = in->data->group_index;
  715|  29.3k|    in->upd_opt = 0;
  716|  29.3k|    return true;
  717|  53.8k|}
m_config_core.c:update_next_option:
  639|  83.8k|{
  640|  83.8k|    struct config_cache *in = cache->internal;
  641|  83.8k|    struct m_config_data *dst = in->data;
  642|  83.8k|    struct m_config_data *src = in->src;
  643|       |
  644|  83.8k|    mp_assert(src->group_index == 0); // must be the option root currently
  ------------------
  |  |   41|  83.8k|#define mp_assert assert
  ------------------
  645|       |
  646|  83.8k|    *p_opt = NULL;
  647|       |
  648|   137k|    while (in->upd_group < dst->group_index + dst->num_gdata) {
  ------------------
  |  Branch (648:12): [True: 108k, False: 29.3k]
  ------------------
  649|   108k|        struct m_group_data *gsrc = m_config_gdata(src, in->upd_group);
  650|   108k|        struct m_group_data *gdst = m_config_gdata(dst, in->upd_group);
  651|   108k|        mp_assert(gsrc && gdst);
  ------------------
  |  |   41|   108k|#define mp_assert assert
  ------------------
  652|       |
  653|   108k|        if (gdst->ts < gsrc->ts) {
  ------------------
  |  Branch (653:13): [True: 71.6k, False: 36.9k]
  ------------------
  654|  71.6k|            struct m_config_group *g = &dst->shadow->groups[in->upd_group];
  655|  71.6k|            const struct m_option *opts = g->group->opts;
  656|       |
  657|   346k|            while (opts && opts[in->upd_opt].name) {
  ------------------
  |  Branch (657:20): [True: 346k, False: 0]
  |  Branch (657:28): [True: 328k, False: 17.2k]
  ------------------
  658|   328k|                const struct m_option *opt = &opts[in->upd_opt];
  659|   328k|                void *dsrc = gsrc->udata + opt->offset;
  660|   328k|                void *ddst = gdst->udata + opt->offset;
  661|       |
  662|   328k|                if (opt->offset >= 0 && opt->type->size) {
  ------------------
  |  Branch (662:21): [True: 294k, False: 34.6k]
  |  Branch (662:41): [True: 294k, False: 222]
  ------------------
  663|   294k|                    bool opt_equal = m_option_equal(opt, ddst, dsrc);
  664|   294k|                    bool force_update = opt->force_update &&
  ------------------
  |  Branch (664:41): [True: 32, False: 294k]
  ------------------
  665|   294k|                                        check_force_update(gsrc, opt->name, in->ts);
  ------------------
  |  Branch (665:41): [True: 0, False: 32]
  ------------------
  666|   294k|                    if (!opt_equal || force_update) {
  ------------------
  |  Branch (666:25): [True: 54.4k, False: 239k]
  |  Branch (666:39): [True: 0, False: 239k]
  ------------------
  667|  54.4k|                        uint64_t ch = get_opt_change_mask(dst->shadow,
  668|  54.4k|                                        in->upd_group, dst->group_index, opt);
  669|       |
  670|  54.4k|                        if (cache->debug && !opt_equal) {
  ------------------
  |  Branch (670:29): [True: 0, False: 54.4k]
  |  Branch (670:45): [True: 0, False: 0]
  ------------------
  671|      0|                            char *vdst = m_option_print(opt, ddst);
  672|      0|                            char *vsrc = m_option_print(opt, dsrc);
  673|      0|                            mp_warn(cache->debug, "Option '%s' changed from "
  ------------------
  |  |   73|      0|#define mp_warn(log, ...)       mp_msg(log, MSGL_WARN, __VA_ARGS__)
  ------------------
  674|      0|                                    "'%s' to' %s' (flags = 0x%"PRIx64")\n",
  675|      0|                                    opt->name, vdst, vsrc, ch);
  676|      0|                            talloc_free(vdst);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  677|      0|                            talloc_free(vsrc);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  678|      0|                        }
  679|       |
  680|  54.4k|                        m_option_copy(opt, ddst, dsrc);
  681|  54.4k|                        cache->change_flags |= ch;
  682|       |
  683|  54.4k|                        in->upd_opt++; // skip this next time
  684|  54.4k|                        *p_opt = ddst;
  685|  54.4k|                        return;
  686|  54.4k|                    }
  687|   294k|                }
  688|       |
  689|   274k|                in->upd_opt++;
  690|   274k|            }
  691|       |
  692|  17.2k|            gdst->ts = gsrc->ts;
  693|  17.2k|        }
  694|       |
  695|  54.1k|        in->upd_group++;
  696|  54.1k|        in->upd_opt = 0;
  697|  54.1k|    }
  698|       |
  699|  29.3k|    in->upd_group = -1;
  700|  29.3k|}
m_config_core.c:check_force_update:
  627|     32|{
  628|     34|    for (int i = 0; i < gdata->force_update_len; ++i) {
  ------------------
  |  Branch (628:21): [True: 2, False: 32]
  ------------------
  629|      2|        if ((strcmp(opt_name, gdata->force_update[i]->name) == 0) &&
  ------------------
  |  Branch (629:13): [True: 1, False: 1]
  ------------------
  630|      2|            gdata->force_update[i]->ts == timestamp)
  ------------------
  |  Branch (630:13): [True: 0, False: 1]
  ------------------
  631|      0|        {
  632|      0|            return true;
  633|      0|        }
  634|      2|    }
  635|     32|    return false;
  636|     32|}
m_config_core.c:find_opt:
  757|   327k|{
  758|   327k|    *group_idx = -1;
  759|   327k|    *opt_idx = -1;
  760|       |
  761|  4.11M|    for (int n = data->group_index; n < data->group_index + data->num_gdata; n++)
  ------------------
  |  Branch (761:37): [True: 4.11M, False: 0]
  ------------------
  762|  4.11M|    {
  763|  4.11M|        struct m_group_data *gd = m_config_gdata(data, n);
  764|  4.11M|        struct m_config_group *g = &shadow->groups[n];
  765|  4.11M|        const struct m_option *opts = g->group->opts;
  766|       |
  767|  87.9M|        for (int i = 0; opts && opts[i].name; i++) {
  ------------------
  |  Branch (767:25): [True: 87.9M, False: 0]
  |  Branch (767:33): [True: 84.2M, False: 3.78M]
  ------------------
  768|  84.2M|            const struct m_option *opt = &opts[i];
  769|       |
  770|  84.2M|            if (opt->offset >= 0 && opt->type->size &&
  ------------------
  |  Branch (770:17): [True: 75.5M, False: 8.66M]
  |  Branch (770:37): [True: 68.9M, False: 6.54M]
  ------------------
  771|  84.2M|                ptr == gd->udata + opt->offset)
  ------------------
  |  Branch (771:17): [True: 327k, False: 68.6M]
  ------------------
  772|   327k|            {
  773|   327k|                *group_idx = n;
  774|   327k|                *opt_idx = i;
  775|   327k|                return;
  776|   327k|            }
  777|  84.2M|        }
  778|  4.11M|    }
  779|   327k|}
m_config_core.c:append_force_update:
  612|  2.46k|{
  613|  2.56k|    for (int i = 0; i < gdata->force_update_len; ++i) {
  ------------------
  |  Branch (613:21): [True: 2.04k, False: 520]
  ------------------
  614|  2.04k|        if (strcmp(opt_name, gdata->force_update[i]->name) == 0) {
  ------------------
  |  Branch (614:13): [True: 1.94k, False: 101]
  ------------------
  615|  1.94k|            gdata->force_update[i]->ts = gdata->ts;
  616|  1.94k|            return;
  617|  1.94k|        }
  618|  2.04k|    }
  619|    520|    struct force_update *new_update = talloc_zero(cache, struct force_update);
  ------------------
  |  |   27|    520|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    520|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    520|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  620|    520|    new_update->name = talloc_strdup(cache, opt_name);
  ------------------
  |  |   50|    520|#define talloc_strdup                   ta_xstrdup
  ------------------
  621|    520|    new_update->ts = gdata->ts;
  622|    520|    MP_TARRAY_APPEND(cache, gdata->force_update, gdata->force_update_len, new_update);
  ------------------
  |  |  105|    520|    do {                                            \
  |  |  106|    520|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|    520|    do {                                            \
  |  |  |  |   97|    520|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|    520|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|    520|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|    520|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 509, False: 11]
  |  |  |  |  ------------------
  |  |  |  |   99|    520|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|    509|    do {                                                        \
  |  |  |  |  |  |   89|    509|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|    509|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|    509|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|    509|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|    509|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|    509|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|    509|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|    520|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|    520|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|    520|        (idxvar)++;                                 \
  |  |  109|    520|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  623|    520|}
m_config_core.c:dispatch_notify:
  856|      6|{
  857|      6|    struct config_cache *in = p;
  858|       |
  859|      6|    mp_assert(in->wakeup_dispatch_queue);
  ------------------
  |  |   41|      6|#define mp_assert assert
  ------------------
  860|      6|    mp_dispatch_enqueue_notify(in->wakeup_dispatch_queue,
  861|      6|                               in->wakeup_dispatch_cb,
  862|      6|                               in->wakeup_dispatch_cb_ctx);
  863|      6|}
m_config_core.c:find_group:
  906|     76|{
  907|     76|    struct m_config_shadow *shadow = global->config;
  908|       |
  909|  3.21k|    for (int n = 0; n < shadow->num_groups; n++) {
  ------------------
  |  Branch (909:21): [True: 3.18k, False: 37]
  ------------------
  910|  3.18k|        if (shadow->groups[n].group->opts == cfg)
  ------------------
  |  Branch (910:13): [True: 39, False: 3.14k]
  ------------------
  911|     39|            return &shadow->groups[n];
  912|  3.18k|    }
  913|       |
  914|     37|    return NULL;
  915|     76|}

m_config_from_obj_desc_noalloc:
  146|  11.1k|{
  147|  11.1k|    return m_config_from_obj_desc(talloc_ctx, log, NULL, desc);
  148|  11.1k|}
m_config_restore_backups:
  229|  50.1k|{
  230|  50.1k|    restore_backups(&config->backup_opts, config);
  231|  50.1k|}
m_config_backup_watch_later_opts:
  270|  12.1k|{
  271|  9.07M|    for (int n = 0; n < config->num_opts; n++)
  ------------------
  |  Branch (271:21): [True: 9.06M, False: 12.1k]
  ------------------
  272|  9.06M|        ensure_backup(&config->watch_later_backup_opts, 0, &config->opts[n]);
  273|  12.1k|}
m_config_get_co_raw:
  277|  2.35M|{
  278|  2.35M|    if (!name.len)
  ------------------
  |  Branch (278:9): [True: 9.24k, False: 2.34M]
  ------------------
  279|  9.24k|        return NULL;
  280|       |
  281|   716M|    for (int n = 0; n < config->num_opts; n++) {
  ------------------
  |  Branch (281:21): [True: 715M, False: 249k]
  ------------------
  282|   715M|        struct m_config_option *co = &config->opts[n];
  283|   715M|        struct bstr coname = bstr0(co->name);
  284|   715M|        if (bstrcmp(coname, name) == 0)
  ------------------
  |  Branch (284:13): [True: 2.09M, False: 713M]
  ------------------
  285|  2.09M|            return co;
  286|   715M|    }
  287|       |
  288|   249k|    return NULL;
  289|  2.34M|}
m_config_get_co:
  343|  1.69M|{
  344|  1.69M|    struct m_config_option *co = m_config_get_co_any(config, name);
  345|       |    // CLI aliases should not be real options, and are explicitly handled by
  346|       |    // m_config_set_option_cli(). So pretend it does not exist.
  347|  1.69M|    if (co && co->opt->type == &m_option_type_cli_alias)
  ------------------
  |  Branch (347:9): [True: 1.56M, False: 130k]
  |  Branch (347:15): [True: 136k, False: 1.42M]
  ------------------
  348|   136k|        co = NULL;
  349|  1.69M|    return co;
  350|  1.69M|}
m_config_get_co_count:
  353|  17.0k|{
  354|  17.0k|    return config->num_opts;
  355|  17.0k|}
m_config_get_co_index:
  358|  12.7M|{
  359|  12.7M|    return &config->opts[index];
  360|  12.7M|}
m_config_get_co_default:
  364|  26.7k|{
  365|  26.7k|    return m_config_shadow_get_opt_default(config->shadow, co->opt_id);
  366|  26.7k|}
m_config_get_positional_option:
  369|  3.95k|{
  370|  3.95k|    int pos = 0;
  371|  6.39k|    for (int n = 0; n < config->num_opts; n++) {
  ------------------
  |  Branch (371:21): [True: 6.37k, False: 14]
  ------------------
  372|  6.37k|        struct m_config_option *co = &config->opts[n];
  373|  6.37k|        if (!co->opt->deprecation_message) {
  ------------------
  |  Branch (373:13): [True: 6.37k, False: 0]
  ------------------
  374|  6.37k|            if (pos == p)
  ------------------
  |  Branch (374:17): [True: 3.93k, False: 2.44k]
  ------------------
  375|  3.93k|                return co->name;
  376|  2.44k|            pos++;
  377|  2.44k|        }
  378|  6.37k|    }
  379|     14|    return NULL;
  380|  3.95k|}
m_config_mark_co_flags:
  415|   323k|{
  416|   323k|    if (flags & M_SETOPT_FROM_CMDLINE)
  ------------------
  |  Branch (416:9): [True: 183k, False: 139k]
  ------------------
  417|   183k|        co->is_set_from_cmdline = true;
  418|       |
  419|   323k|    if (flags & M_SETOPT_FROM_CONFIG_FILE)
  ------------------
  |  Branch (419:9): [True: 243k, False: 80.0k]
  ------------------
  420|   243k|        co->is_set_from_config = true;
  421|   323k|}
m_config_set_update_dispatch_queue:
  514|  12.1k|{
  515|  12.1k|    m_config_cache_set_dispatch_change_cb(config->cache, dispatch,
  516|  12.1k|                                          async_change_cb, config);
  517|  12.1k|}
m_config_new:
  538|  28.2k|{
  539|  28.2k|    struct m_config *config = talloc(talloc_ctx, struct m_config);
  ------------------
  |  |   26|  28.2k|#define talloc                          ta_xnew
  |  |  ------------------
  |  |  |  |  133|  28.2k|#define ta_xnew(...)                    ta_oom_g(ta_new(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  28.2k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  540|  28.2k|    talloc_set_destructor(config, config_destroy);
  ------------------
  |  |   41|  28.2k|#define talloc_set_destructor           ta_set_destructor
  ------------------
  541|  28.2k|    *config = (struct m_config){.log = log,};
  542|       |
  543|  28.2k|    config->shadow = m_config_shadow_new(root);
  544|       |
  545|  28.2k|    if (root->size) {
  ------------------
  |  Branch (545:9): [True: 17.0k, False: 11.1k]
  ------------------
  546|  17.0k|        config->cache = m_config_cache_from_shadow(config, config->shadow, root);
  547|  17.0k|        config->optstruct = config->cache->opts;
  548|  17.0k|    }
  549|       |
  550|  28.2k|    int32_t optid = -1;
  551|  12.8M|    while (m_config_shadow_get_next_opt(config->shadow, &optid)) {
  ------------------
  |  Branch (551:12): [True: 12.7M, False: 28.2k]
  ------------------
  552|  12.7M|        char buf[M_CONFIG_MAX_OPT_NAME_LEN];
  553|  12.7M|        const char *opt_name =
  554|  12.7M|            m_config_shadow_get_opt_name(config->shadow, optid, buf, sizeof(buf));
  555|       |
  556|  12.7M|        struct m_config_option co = {
  557|  12.7M|            .name = talloc_strdup(config, opt_name),
  ------------------
  |  |   50|  12.7M|#define talloc_strdup                   ta_xstrdup
  ------------------
  558|  12.7M|            .opt = m_config_shadow_get_opt(config->shadow, optid),
  559|  12.7M|            .opt_id = optid,
  560|  12.7M|        };
  561|       |
  562|  12.7M|        if (config->cache)
  ------------------
  |  Branch (562:13): [True: 12.7M, False: 44.8k]
  ------------------
  563|  12.7M|            co.data = m_config_cache_get_opt_data(config->cache, optid);
  564|       |
  565|  12.7M|        MP_TARRAY_APPEND(config, config->opts, config->num_opts, co);
  ------------------
  |  |  105|  12.7M|    do {                                            \
  |  |  106|  12.7M|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  12.7M|    do {                                            \
  |  |  |  |   97|  12.7M|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  12.7M|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  12.7M|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  12.7M|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 166k, False: 12.6M]
  |  |  |  |  ------------------
  |  |  |  |   99|  12.7M|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|   166k|    do {                                                        \
  |  |  |  |  |  |   89|   166k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|   166k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|   166k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|   166k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|   166k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|   166k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|   166k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  12.7M|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  12.7M|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  12.7M|        (idxvar)++;                                 \
  |  |  109|  12.7M|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  566|  12.7M|    }
  567|       |
  568|  28.2k|    return config;
  569|  28.2k|}
m_config_notify_change_opt_ptr:
  602|  3.93k|{
  603|  3.93k|    notify_opt(config, ptr, true);
  604|  3.93k|}
m_config_set_option_raw:
  616|  1.32M|{
  617|  1.32M|    if (!co)
  ------------------
  |  Branch (617:9): [True: 0, False: 1.32M]
  ------------------
  618|      0|        return M_OPT_UNKNOWN;
  ------------------
  |  |  517|      0|#define M_OPT_UNKNOWN           -1
  ------------------
  619|       |
  620|  1.32M|    int r = handle_set_opt_flags(config, co, flags);
  621|  1.32M|    if (r <= 1)
  ------------------
  |  Branch (621:9): [True: 966k, False: 355k]
  ------------------
  622|   966k|        return r;
  623|       |
  624|   355k|    r = m_config_handle_special_options(config, co, data, flags);
  625|   355k|    if (r != M_OPT_UNKNOWN)
  ------------------
  |  |  517|   355k|#define M_OPT_UNKNOWN           -1
  ------------------
  |  Branch (625:9): [True: 23.4k, False: 331k]
  ------------------
  626|  23.4k|        return r;
  627|       |
  628|       |    // This affects some special options like "playlist", "v". Maybe these
  629|       |    // should work, or maybe not. For now they would require special code.
  630|   331k|    if (!co->data)
  ------------------
  |  Branch (630:9): [True: 8.08k, False: 323k]
  ------------------
  631|  8.08k|        return flags & M_SETOPT_FROM_CMDLINE ? 0 : M_OPT_UNKNOWN;
  ------------------
  |  |  517|      0|#define M_OPT_UNKNOWN           -1
  ------------------
  |  Branch (631:16): [True: 8.08k, False: 0]
  ------------------
  632|       |
  633|   323k|    if (config->profile_backup_tmp)
  ------------------
  |  Branch (633:9): [True: 0, False: 323k]
  ------------------
  634|      0|        ensure_backup(config->profile_backup_tmp, config->profile_backup_flags, co);
  635|       |
  636|   323k|    m_config_mark_co_flags(co, flags);
  637|       |
  638|   323k|    m_option_copy(co->opt, co->data, data);
  639|   323k|    if (m_config_cache_write_opt(config->cache, co->data))
  ------------------
  |  Branch (639:9): [True: 221k, False: 101k]
  ------------------
  640|   221k|        force_self_notify_change_opt(config, co, false);
  641|       |
  642|   323k|    return 0;
  643|   331k|}
m_config_set_option_cli:
  718|  1.48M|{
  719|  1.48M|    int r;
  720|  1.48M|    mp_assert(config != NULL);
  ------------------
  |  |   41|  1.48M|#define mp_assert assert
  ------------------
  721|       |
  722|  1.48M|    bool negate;
  723|  1.48M|    struct m_config_option *co =
  724|  1.48M|        m_config_mogrify_cli_opt(config, &name, &negate, &(int){0});
  725|       |
  726|  1.48M|    if (!co) {
  ------------------
  |  Branch (726:9): [True: 73.2k, False: 1.41M]
  ------------------
  727|  73.2k|        r = M_OPT_UNKNOWN;
  ------------------
  |  |  517|  73.2k|#define M_OPT_UNKNOWN           -1
  ------------------
  728|  73.2k|        goto done;
  729|  73.2k|    }
  730|       |
  731|  1.41M|    if (negate) {
  ------------------
  |  Branch (731:9): [True: 562, False: 1.41M]
  ------------------
  732|    562|        if (param.len) {
  ------------------
  |  Branch (732:13): [True: 195, False: 367]
  ------------------
  733|    195|            r = M_OPT_DISALLOW_PARAM;
  ------------------
  |  |  530|    195|#define M_OPT_DISALLOW_PARAM    -5
  ------------------
  734|    195|            goto done;
  735|    195|        }
  736|       |
  737|    367|        param = bstr0("no");
  738|    367|    }
  739|       |
  740|  1.41M|    if (flags & M_SETOPT_FROM_CONFIG_FILE)
  ------------------
  |  Branch (740:9): [True: 1.22M, False: 192k]
  ------------------
  741|  1.22M|        co->coalesce = true;
  742|       |
  743|       |    // This is the only mandatory function
  744|  1.41M|    mp_assert(co->opt->type->parse);
  ------------------
  |  |   41|  1.41M|#define mp_assert assert
  ------------------
  745|       |
  746|  1.41M|    r = handle_set_opt_flags(config, co, flags);
  747|  1.41M|    if (r <= 0)
  ------------------
  |  Branch (747:9): [True: 82.3k, False: 1.33M]
  ------------------
  748|  82.3k|        goto done;
  749|       |
  750|  1.33M|    if (r == 2) {
  ------------------
  |  Branch (750:9): [True: 364k, False: 967k]
  ------------------
  751|   364k|        MP_VERBOSE(config, "Setting option '%.*s' = '%.*s' (flags = %d)\n",
  ------------------
  |  |   88|   364k|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  1.45M|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 364k, False: 0]
  |  |  |  |  |  Branch (82:57): [True: 364k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  752|   364k|                   BSTR_P(name), BSTR_P(param), flags);
  753|   364k|    }
  754|       |
  755|  1.33M|    union m_option_value val = m_option_value_default;
  756|       |
  757|       |    // Some option types are "impure" and work on the existing data.
  758|       |    // (Prime examples: --vf-add, --sub-file)
  759|  1.33M|    if (co->data)
  ------------------
  |  Branch (759:9): [True: 1.23M, False: 96.6k]
  ------------------
  760|  1.23M|        m_option_copy(co->opt, &val, co->data);
  761|       |
  762|  1.33M|    r = m_option_parse(config->log, co->opt, name, param, &val);
  763|       |
  764|  1.33M|    if (r >= 0)
  ------------------
  |  Branch (764:9): [True: 1.32M, False: 9.68k]
  ------------------
  765|  1.32M|        r = m_config_set_option_raw(config, co, &val, flags);
  766|       |
  767|  1.33M|    m_option_free(co->opt, &val);
  768|       |
  769|  1.48M|done:
  770|  1.48M|    if (r < 0 && r != M_OPT_EXIT) {
  ------------------
  |  |  533|  83.5k|#define M_OPT_EXIT              -6
  ------------------
  |  Branch (770:9): [True: 83.5k, False: 1.40M]
  |  Branch (770:18): [True: 79.0k, False: 4.47k]
  ------------------
  771|  79.0k|        MP_ERR(config, "Error parsing option %.*s (%s)\n",
  ------------------
  |  |   85|  79.0k|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|   158k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 79.0k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  772|  79.0k|               BSTR_P(name), m_option_strerror(r));
  773|  79.0k|        r = M_OPT_INVALID;
  ------------------
  |  |  523|  79.0k|#define M_OPT_INVALID           -3
  ------------------
  774|  79.0k|    }
  775|  1.48M|    return r;
  776|  1.33M|}
m_config_option_requires_param:
  813|   200k|{
  814|   200k|    bool negate;
  815|   200k|    int flags;
  816|   200k|    struct m_config_option *co =
  817|   200k|        m_config_mogrify_cli_opt(config, &name, &negate, &flags);
  818|       |
  819|   200k|    if (!co)
  ------------------
  |  Branch (819:9): [True: 13.2k, False: 187k]
  ------------------
  820|  13.2k|        return M_OPT_UNKNOWN;
  ------------------
  |  |  517|  13.2k|#define M_OPT_UNKNOWN           -1
  ------------------
  821|       |
  822|   187k|    if (negate || (flags & M_OPT_TYPE_OPTIONAL_PARAM))
  ------------------
  |  |  495|   186k|#define M_OPT_TYPE_OPTIONAL_PARAM       (1 << 0)
  ------------------
  |  Branch (822:9): [True: 562, False: 186k]
  |  Branch (822:19): [True: 1.23k, False: 185k]
  ------------------
  823|  1.79k|        return 0;
  824|       |
  825|   185k|    return m_option_required_params(co->opt);
  826|   187k|}
m_config_print_option_list:
  836|    147|{
  837|    147|    char min[50], max[50];
  838|    147|    int count = 0;
  839|    147|    const char *prefix = config->is_toplevel ? "--" : "";
  ------------------
  |  Branch (839:26): [True: 142, False: 5]
  ------------------
  840|       |
  841|    147|    struct m_config_option *sorted =
  842|    147|        talloc_memdup(NULL, config->opts, config->num_opts * sizeof(sorted[0]));
  ------------------
  |  |   49|    147|#define talloc_memdup                   ta_xmemdup
  |  |  ------------------
  |  |  |  |  157|    147|#define ta_xmemdup(...)         ta_dbg_set_loc(ta_xmemdup(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|    147|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|    147|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|    147|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  843|    147|    if (config->is_toplevel)
  ------------------
  |  Branch (843:9): [True: 142, False: 5]
  ------------------
  844|    142|        qsort(sorted, config->num_opts, sizeof(sorted[0]), sort_opt_compare);
  845|       |
  846|    147|    MP_INFO(config, "Options:\n\n");
  ------------------
  |  |   87|    147|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    147|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  847|   106k|    for (int i = 0; i < config->num_opts; i++) {
  ------------------
  |  Branch (847:21): [True: 105k, False: 147]
  ------------------
  848|   105k|        struct m_config_option *co = &sorted[i];
  849|   105k|        const struct m_option *opt = co->opt;
  850|   105k|        if (strcmp(name, "*") != 0 && !strstr(co->name, name))
  ------------------
  |  Branch (850:13): [True: 99.2k, False: 6.74k]
  |  Branch (850:39): [True: 79.2k, False: 20.0k]
  ------------------
  851|  79.2k|            continue;
  852|  26.7k|        MP_INFO(config, " %s%-30s", prefix, co->name);
  ------------------
  |  |   87|  26.7k|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  26.7k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  853|  26.7k|        if (opt->type == &m_option_type_choice) {
  ------------------
  |  Branch (853:13): [True: 4.15k, False: 22.6k]
  ------------------
  854|  4.15k|            MP_INFO(config, " Choices:");
  ------------------
  |  |   87|  4.15k|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  4.15k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  855|  4.15k|            const struct m_opt_choice_alternatives *alt = opt->priv;
  856|  26.8k|            for (int n = 0; alt[n].name; n++)
  ------------------
  |  Branch (856:29): [True: 22.7k, False: 4.15k]
  ------------------
  857|  22.7k|                MP_INFO(config, " %s", alt[n].name);
  ------------------
  |  |   87|  22.7k|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  22.7k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  858|  4.15k|            if (opt->min < opt->max)
  ------------------
  |  Branch (858:17): [True: 761, False: 3.39k]
  ------------------
  859|  4.15k|                MP_INFO(config, " (or an integer)");
  ------------------
  |  |   87|    761|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    761|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  860|  22.6k|        } else {
  861|  22.6k|            MP_INFO(config, " %s", opt->type->name);
  ------------------
  |  |   87|  22.6k|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  22.6k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  862|  22.6k|        }
  863|  26.7k|        if ((opt->type->flags & M_OPT_TYPE_USES_RANGE) && opt->min < opt->max) {
  ------------------
  |  |  503|  26.7k|#define M_OPT_TYPE_USES_RANGE           (1 << 2)
  ------------------
  |  Branch (863:13): [True: 12.9k, False: 13.7k]
  |  Branch (863:59): [True: 7.55k, False: 5.43k]
  ------------------
  864|  7.55k|            snprintf(min, sizeof(min), "any");
  865|  7.55k|            snprintf(max, sizeof(max), "any");
  866|  7.55k|            if (opt->min != DBL_MIN)
  ------------------
  |  Branch (866:17): [True: 7.55k, False: 0]
  ------------------
  867|  7.55k|                snprintf(min, sizeof(min), "%.14g", opt->min);
  868|  7.55k|            if (opt->max != DBL_MAX)
  ------------------
  |  Branch (868:17): [True: 6.88k, False: 670]
  ------------------
  869|  6.88k|                snprintf(max, sizeof(max), "%.14g", opt->max);
  870|  7.55k|            MP_INFO(config, " (%s to %s)", min, max);
  ------------------
  |  |   87|  7.55k|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  7.55k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  871|  7.55k|        }
  872|  26.7k|        char *def = NULL;
  873|  26.7k|        const void *defptr = m_config_get_co_default(config, co);
  874|  26.7k|        if (!defptr)
  ------------------
  |  Branch (874:13): [True: 1.52k, False: 25.2k]
  ------------------
  875|  1.52k|            defptr = &m_option_value_default;
  876|  26.7k|        if (defptr)
  ------------------
  |  Branch (876:13): [True: 26.7k, False: 0]
  ------------------
  877|  26.7k|            def = m_option_pretty_print(opt, defptr, false);
  878|  26.7k|        if (def) {
  ------------------
  |  Branch (878:13): [True: 25.3k, False: 1.44k]
  ------------------
  879|  25.3k|            MP_INFO(config, " (default: %s)", def);
  ------------------
  |  |   87|  25.3k|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  25.3k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  880|  25.3k|            talloc_free(def);
  ------------------
  |  |   47|  25.3k|#define talloc_free                     ta_free
  ------------------
  881|  25.3k|        }
  882|  26.7k|        if (opt->flags & M_OPT_NOCFG)
  ------------------
  |  |  456|  26.7k|#define M_OPT_NOCFG             (UINT64_C(1) << 63)
  ------------------
  |  Branch (882:13): [True: 315, False: 26.4k]
  ------------------
  883|  26.7k|            MP_INFO(config, " [not in config files]");
  ------------------
  |  |   87|    315|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    315|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  884|  26.7k|        if (opt->flags & M_OPT_FILE)
  ------------------
  |  |  462|  26.7k|#define M_OPT_FILE              (UINT64_C(1) << 61)
  ------------------
  |  Branch (884:13): [True: 1.19k, False: 25.5k]
  ------------------
  885|  26.7k|            MP_INFO(config, " [file]");
  ------------------
  |  |   87|  1.19k|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  1.19k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  886|  26.7k|        if (opt->deprecation_message)
  ------------------
  |  Branch (886:13): [True: 576, False: 26.1k]
  ------------------
  887|  26.7k|            MP_INFO(config, " [deprecated]");
  ------------------
  |  |   87|    576|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    576|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  888|  26.7k|        if (opt->type == &m_option_type_alias) {
  ------------------
  |  Branch (888:13): [True: 738, False: 26.0k]
  ------------------
  889|    738|            char buf[M_CONFIG_MAX_OPT_NAME_LEN];
  890|    738|            const char *alias = m_config_shadow_get_alias_from_opt(config->shadow, co->opt_id,
  891|    738|                                                                   buf, sizeof(buf));
  892|    738|            MP_INFO(config, " for %s", alias);
  ------------------
  |  |   87|    738|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    738|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  893|    738|        }
  894|  26.7k|        if (opt->type == &m_option_type_cli_alias)
  ------------------
  |  Branch (894:13): [True: 215, False: 26.5k]
  ------------------
  895|  26.7k|            MP_INFO(config, " for --%s (CLI/config files only)", (char *)opt->priv);
  ------------------
  |  |   87|    215|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    215|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  896|  26.7k|        MP_INFO(config, "\n");
  ------------------
  |  |   87|  26.7k|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  26.7k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  897|  38.2k|        for (int n = 0; opt->type->actions && opt->type->actions[n].name; n++) {
  ------------------
  |  Branch (897:25): [True: 13.0k, False: 25.2k]
  |  Branch (897:47): [True: 11.4k, False: 1.56k]
  ------------------
  898|  11.4k|            const struct m_option_action *action = &opt->type->actions[n];
  899|  11.4k|            MP_INFO(config, "    %s%s-%s\n", prefix, co->name, action->name);
  ------------------
  |  |   87|  11.4k|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  11.4k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  900|  11.4k|            count++;
  901|  11.4k|        }
  902|  26.7k|        count++;
  903|  26.7k|    }
  904|    147|    MP_INFO(config, "\nTotal: %d options\n", count);
  ------------------
  |  |   87|    147|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    147|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  905|    147|    talloc_free(sorted);
  ------------------
  |  |   47|    147|#define talloc_free                     ta_free
  ------------------
  906|    147|}
m_config_list_options:
  909|  5.26k|{
  910|  5.26k|    char **list = talloc_new(ta_parent);
  ------------------
  |  |   40|  5.26k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  5.26k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  911|  5.26k|    int count = 0;
  912|  3.93M|    for (int i = 0; i < config->num_opts; i++) {
  ------------------
  |  Branch (912:21): [True: 3.92M, False: 5.26k]
  ------------------
  913|  3.92M|        struct m_config_option *co = &config->opts[i];
  914|       |        // For use with CONF_TYPE_STRING_LIST, it's important not to set list
  915|       |        // as allocation parent.
  916|  3.92M|        char *s = talloc_strdup(ta_parent, co->name);
  ------------------
  |  |   50|  3.92M|#define talloc_strdup                   ta_xstrdup
  ------------------
  917|  3.92M|        MP_TARRAY_APPEND(ta_parent, list, count, s);
  ------------------
  |  |  105|  3.92M|    do {                                            \
  |  |  106|  3.92M|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  3.92M|    do {                                            \
  |  |  |  |   97|  3.92M|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  3.92M|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  3.92M|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  3.92M|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 47.3k, False: 3.87M]
  |  |  |  |  ------------------
  |  |  |  |   99|  3.92M|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  47.3k|    do {                                                        \
  |  |  |  |  |  |   89|  47.3k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  47.3k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  47.3k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  47.3k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  47.3k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  47.3k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  47.3k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  3.92M|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  3.92M|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  3.92M|        (idxvar)++;                                 \
  |  |  109|  3.92M|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  918|  3.92M|    }
  919|  5.26k|    MP_TARRAY_APPEND(ta_parent, list, count, NULL);
  ------------------
  |  |  105|  5.26k|    do {                                            \
  |  |  106|  5.26k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  5.26k|    do {                                            \
  |  |  |  |   97|  5.26k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  5.26k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  5.26k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  5.26k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 5.26k]
  |  |  |  |  ------------------
  |  |  |  |   99|  5.26k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  5.26k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  5.26k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  5.26k|        (idxvar)++;                                 \
  |  |  109|  5.26k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  920|  5.26k|    return list;
  921|  5.26k|}
m_config_get_profile:
  924|   308k|{
  925|  2.25M|    for (struct m_profile *p = config->profiles; p; p = p->next) {
  ------------------
  |  Branch (925:50): [True: 2.03M, False: 222k]
  ------------------
  926|  2.03M|        if (bstr_equals0(name, p->name))
  ------------------
  |  Branch (926:13): [True: 85.6k, False: 1.94M]
  ------------------
  927|  85.6k|            return p;
  928|  2.03M|    }
  929|   222k|    return NULL;
  930|   308k|}
m_config_get_profile0:
  934|   308k|{
  935|   308k|    return m_config_get_profile(config, bstr0(name));
  936|   308k|}
m_config_add_profile:
  939|   238k|{
  940|   238k|    if (!name || !name[0])
  ------------------
  |  Branch (940:9): [True: 34.1k, False: 204k]
  |  Branch (940:18): [True: 0, False: 204k]
  ------------------
  941|  34.1k|        name = "default";
  942|   238k|    struct m_profile *p = m_config_get_profile0(config, name);
  943|   238k|    if (p)
  ------------------
  |  Branch (943:9): [True: 17.0k, False: 221k]
  ------------------
  944|  17.0k|        return p;
  945|   221k|    p = talloc_zero(config, struct m_profile);
  ------------------
  |  |   27|   221k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|   221k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|   221k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  946|   221k|    p->name = talloc_strdup(p, name);
  ------------------
  |  |   50|   221k|#define talloc_strdup                   ta_xstrdup
  ------------------
  947|   221k|    p->next = config->profiles;
  948|   221k|    config->profiles = p;
  949|   221k|    return p;
  950|   238k|}
m_config_set_profile_option:
  954|  1.02M|{
  955|  1.02M|    if (bstr_equals0(name, "profile-desc")) {
  ------------------
  |  Branch (955:9): [True: 0, False: 1.02M]
  ------------------
  956|      0|        talloc_free(p->desc);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  957|      0|        p->desc = bstrto0(p, val);
  958|      0|        return 0;
  959|      0|    }
  960|  1.02M|    if (bstr_equals0(name, "profile-cond")) {
  ------------------
  |  Branch (960:9): [True: 0, False: 1.02M]
  ------------------
  961|      0|        TA_FREEP(&p->cond);
  ------------------
  |  |   81|      0|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|      0|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  962|      0|        val = bstr_strip(val);
  963|      0|        if (val.len)
  ------------------
  |  Branch (963:13): [True: 0, False: 0]
  ------------------
  964|      0|            p->cond = bstrto0(p, val);
  965|      0|        return 0;
  966|      0|    }
  967|  1.02M|    if (bstr_equals0(name, profile_restore_mode_opt.name)) {
  ------------------
  |  Branch (967:9): [True: 0, False: 1.02M]
  ------------------
  968|      0|        return m_option_parse(config->log, &profile_restore_mode_opt, name, val,
  969|      0|                              &p->restore_mode);
  970|      0|    }
  971|       |
  972|  1.02M|    int i = m_config_set_option_cli(config, name, val,
  973|  1.02M|                                    M_SETOPT_CHECK_ONLY |
  974|  1.02M|                                    M_SETOPT_FROM_CONFIG_FILE);
  975|  1.02M|    if (i < 0)
  ------------------
  |  Branch (975:9): [True: 68.2k, False: 955k]
  ------------------
  976|  68.2k|        return i;
  977|   955k|    p->opts = talloc_realloc(p, p->opts, char *, 2 * (p->num_opts + 2));
  ------------------
  |  |   33|   955k|#define talloc_realloc                  ta_xrealloc
  |  |  ------------------
  |  |  |  |  144|   955k|    (type *)ta_xrealloc_size(ta_parent, ptr, ta_calc_array_size(sizeof(type), count))
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|   955k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|   955k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|   955k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|   955k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  978|   955k|    p->opts[p->num_opts * 2] = bstrto0(p, name);
  979|   955k|    p->opts[p->num_opts * 2 + 1] = bstrto0(p, val);
  980|   955k|    p->num_opts++;
  981|   955k|    p->opts[p->num_opts * 2] = p->opts[p->num_opts * 2 + 1] = NULL;
  982|   955k|    return 1;
  983|  1.02M|}
m_config_set_profile:
 1006|  68.7k|{
 1007|  68.7k|    MP_VERBOSE(config, "Applying profile '%s'...\n", name);
  ------------------
  |  |   88|  68.7k|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  68.7k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1008|  68.7k|    struct m_profile *p = find_check_profile(config, name);
 1009|  68.7k|    if (!p)
  ------------------
  |  Branch (1009:9): [True: 208, False: 68.5k]
  ------------------
 1010|    208|        return M_OPT_INVALID;
  ------------------
  |  |  523|    208|#define M_OPT_INVALID           -3
  ------------------
 1011|       |
 1012|  68.5k|    if (!config->profile_backup_tmp && p->restore_mode) {
  ------------------
  |  Branch (1012:9): [True: 68.5k, False: 0]
  |  Branch (1012:40): [True: 0, False: 68.5k]
  ------------------
 1013|      0|        config->profile_backup_tmp = &p->backups;
 1014|      0|        config->profile_backup_flags = p->restore_mode == 2 ? BACKUP_NVAL : 0;
  ------------------
  |  |  187|      0|#define BACKUP_NVAL 2
  ------------------
  |  Branch (1014:40): [True: 0, False: 0]
  ------------------
 1015|      0|    }
 1016|       |
 1017|  68.5k|    char *profile_name = talloc_strdup(NULL, name);
  ------------------
  |  |   50|  68.5k|#define talloc_strdup                   ta_xstrdup
  ------------------
 1018|       |    // Note that we don't check if profile applied correctly, it doesn't matter.
 1019|  68.5k|    MP_TARRAY_APPEND(config, config->profile_stack, config->profile_stack_depth, profile_name);
  ------------------
  |  |  105|  68.5k|    do {                                            \
  |  |  106|  68.5k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  68.5k|    do {                                            \
  |  |  |  |   97|  68.5k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  68.5k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  68.5k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  68.5k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 17.0k, False: 51.4k]
  |  |  |  |  ------------------
  |  |  |  |   99|  68.5k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  17.0k|    do {                                                        \
  |  |  |  |  |  |   89|  17.0k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  17.0k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  17.0k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  17.0k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  17.0k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  17.0k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  17.0k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  68.5k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  68.5k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  68.5k|        (idxvar)++;                                 \
  |  |  109|  68.5k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1020|  68.5k|    talloc_steal(config->profile_stack, profile_name);
  ------------------
  |  |   38|  68.5k|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|  68.5k|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 1021|   334k|    for (int i = 0; i < p->num_opts; i++) {
  ------------------
  |  Branch (1021:21): [True: 265k, False: 68.5k]
  ------------------
 1022|   265k|        m_config_set_option_cli(config,
 1023|   265k|                                bstr0(p->opts[2 * i]),
 1024|   265k|                                bstr0(p->opts[2 * i + 1]),
 1025|   265k|                                flags | M_SETOPT_FROM_CONFIG_FILE);
 1026|   265k|    }
 1027|  68.5k|    if (MP_TARRAY_POP(config->profile_stack, config->profile_stack_depth, &profile_name))
  ------------------
  |  |  153|  68.5k|    ((idxvar) > 0                                   \
  |  |  ------------------
  |  |  |  Branch (153:5): [True: 68.5k, False: 0]
  |  |  |  Branch (153:6): [True: 68.5k, False: 0]
  |  |  ------------------
  |  |  154|  68.5k|        ? (*(out) = (p)[--(idxvar)], true)          \
  |  |  155|  68.5k|        : false                                     \
  |  |  156|  68.5k|    )
  ------------------
 1028|  68.5k|        talloc_free(profile_name);
  ------------------
  |  |   47|  68.5k|#define talloc_free                     ta_free
  ------------------
 1029|       |
 1030|  68.5k|    if (config->profile_backup_tmp == &p->backups) {
  ------------------
  |  Branch (1030:9): [True: 0, False: 68.5k]
  ------------------
 1031|      0|        config->profile_backup_tmp = NULL;
 1032|       |
 1033|      0|        for (struct m_opt_backup *bc = p->backups; bc; bc = bc->next) {
  ------------------
  |  Branch (1033:52): [True: 0, False: 0]
  ------------------
 1034|      0|            if (bc && bc->nval)
  ------------------
  |  Branch (1034:17): [True: 0, False: 0]
  |  Branch (1034:23): [True: 0, False: 0]
  ------------------
 1035|      0|                m_option_copy(bc->co->opt, bc->nval, bc->co->data);
 1036|      0|            talloc_steal(p, bc);
  ------------------
  |  |   38|      0|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 1037|      0|        }
 1038|      0|    }
 1039|       |
 1040|  68.5k|    return 0;
 1041|  68.7k|}
m_config_finish_default_profile:
 1059|  17.0k|{
 1060|  17.0k|    struct m_profile *p = m_config_add_profile(config, NULL);
 1061|  17.0k|    m_config_set_profile(config, p->name, flags & ~M_SETOPT_FROM_CONFIG_FILE);
 1062|  17.0k|    p->num_opts = 0;
 1063|  17.0k|}
m_config_get_profiles:
 1066|     63|{
 1067|     63|    struct mpv_node root;
 1068|     63|    node_init(&root, MPV_FORMAT_NODE_ARRAY, NULL);
 1069|       |
 1070|    882|    for (m_profile_t *profile = config->profiles; profile; profile = profile->next)
  ------------------
  |  Branch (1070:51): [True: 819, False: 63]
  ------------------
 1071|    819|    {
 1072|    819|        struct mpv_node *entry = node_array_add(&root, MPV_FORMAT_NODE_MAP);
 1073|       |
 1074|    819|        node_map_add_string(entry, "name", profile->name);
 1075|    819|        if (profile->desc)
  ------------------
  |  Branch (1075:13): [True: 0, False: 819]
  ------------------
 1076|      0|            node_map_add_string(entry, "profile-desc", profile->desc);
 1077|    819|        if (profile->cond)
  ------------------
  |  Branch (1077:13): [True: 0, False: 819]
  ------------------
 1078|      0|            node_map_add_string(entry, "profile-cond", profile->cond);
 1079|    819|        if (profile->restore_mode) {
  ------------------
  |  Branch (1079:13): [True: 0, False: 819]
  ------------------
 1080|      0|            char *s =
 1081|      0|                m_option_print(&profile_restore_mode_opt, &profile->restore_mode);
 1082|      0|            node_map_add_string(entry, profile_restore_mode_opt.name, s);
 1083|      0|            talloc_free(s);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 1084|      0|        }
 1085|       |
 1086|    819|        struct mpv_node *opts =
 1087|    819|            node_map_add(entry, "options", MPV_FORMAT_NODE_ARRAY);
 1088|       |
 1089|  4.34k|        for (int n = 0; n < profile->num_opts; n++) {
  ------------------
  |  Branch (1089:25): [True: 3.52k, False: 819]
  ------------------
 1090|  3.52k|            struct mpv_node *opt_entry = node_array_add(opts, MPV_FORMAT_NODE_MAP);
 1091|  3.52k|            node_map_add_string(opt_entry, "key", profile->opts[n * 2 + 0]);
 1092|  3.52k|            node_map_add_string(opt_entry, "value", profile->opts[n * 2 + 1]);
 1093|  3.52k|        }
 1094|    819|    }
 1095|       |
 1096|     63|    return root;
 1097|     63|}
m_config_frontend.c:m_config_from_obj_desc:
  128|  11.1k|{
  129|  11.1k|    struct m_sub_options *root = talloc_ptrtype(NULL, root);
  ------------------
  |  |   34|  11.1k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  11.1k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  11.1k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  130|  11.1k|    *root = (struct m_sub_options){
  131|  11.1k|        .opts = desc->options,
  132|       |        // (global == NULL got repurposed to mean "no alloc")
  133|  11.1k|        .size = global ? desc->priv_size : 0,
  ------------------
  |  Branch (133:17): [True: 0, False: 11.1k]
  ------------------
  134|  11.1k|        .defaults = desc->priv_defaults,
  135|  11.1k|    };
  136|       |
  137|  11.1k|    struct m_config *c = m_config_new(talloc_ctx, log, root);
  138|  11.1k|    talloc_steal(c, root);
  ------------------
  |  |   38|  11.1k|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|  11.1k|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  139|  11.1k|    c->global = global;
  140|  11.1k|    return c;
  141|  11.1k|}
m_config_frontend.c:restore_backups:
  214|  50.1k|{
  215|  50.1k|    while (*list) {
  ------------------
  |  Branch (215:12): [True: 0, False: 50.1k]
  ------------------
  216|      0|        struct m_opt_backup *bc = *list;
  217|      0|        *list = bc->next;
  218|       |
  219|      0|        if (!bc->nval || m_option_equal(bc->co->opt, bc->co->data, bc->nval))
  ------------------
  |  Branch (219:13): [True: 0, False: 0]
  |  Branch (219:26): [True: 0, False: 0]
  ------------------
  220|      0|            m_config_set_option_raw(config, bc->co, bc->backup, 0);
  221|       |
  222|      0|        if (bc->flags & BACKUP_LOCAL)
  ------------------
  |  |  186|      0|#define BACKUP_LOCAL 1
  ------------------
  |  Branch (222:13): [True: 0, False: 0]
  ------------------
  223|      0|            bc->co->is_set_locally = false;
  224|      0|        talloc_free(bc);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  225|      0|    }
  226|  50.1k|}
m_config_frontend.c:ensure_backup:
  190|  9.06M|{
  191|  9.06M|    if (!co->data)
  ------------------
  |  Branch (191:9): [True: 607k, False: 8.45M]
  ------------------
  192|   607k|        return;
  193|  2.94G|    for (struct m_opt_backup *cur = *list; cur; cur = cur->next) {
  ------------------
  |  Branch (193:44): [True: 2.93G, False: 8.45M]
  ------------------
  194|  2.93G|        if (cur->co->data == co->data) // comparing data ptr catches aliases
  ------------------
  |  Branch (194:13): [True: 0, False: 2.93G]
  ------------------
  195|      0|            return;
  196|  2.93G|    }
  197|  8.45M|    struct m_opt_backup *bc = talloc_ptrtype(NULL, bc);
  ------------------
  |  |   34|  8.45M|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  8.45M|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  8.45M|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  198|  8.45M|    talloc_set_destructor(bc, backup_dtor);
  ------------------
  |  |   41|  8.45M|#define talloc_set_destructor           ta_set_destructor
  ------------------
  199|  8.45M|    *bc = (struct m_opt_backup) {
  200|  8.45M|        .co = co,
  201|  8.45M|        .backup = talloc_zero_size(bc, co->opt->type->size),
  ------------------
  |  |   44|  8.45M|#define talloc_zero_size                ta_xzalloc_size
  |  |  ------------------
  |  |  |  |  121|  8.45M|#define ta_xzalloc_size(...)            ta_oom_p(ta_zalloc_size(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  154|  8.45M|#define ta_zalloc_size(...)     ta_dbg_set_loc(ta_zalloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|  8.45M|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|  8.45M|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|  8.45M|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  202|  8.45M|        .nval = flags & BACKUP_NVAL
  ------------------
  |  |  187|  8.45M|#define BACKUP_NVAL 2
  ------------------
  |  Branch (202:17): [True: 0, False: 8.45M]
  ------------------
  203|  8.45M|            ? talloc_zero_size(bc, co->opt->type->size) : NULL,
  ------------------
  |  |   44|      0|#define talloc_zero_size                ta_xzalloc_size
  |  |  ------------------
  |  |  |  |  121|      0|#define ta_xzalloc_size(...)            ta_oom_p(ta_zalloc_size(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  154|      0|#define ta_zalloc_size(...)     ta_dbg_set_loc(ta_zalloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  204|  8.45M|        .flags = flags,
  205|  8.45M|    };
  206|  8.45M|    m_option_copy(co->opt, bc->backup, co->data);
  207|  8.45M|    bc->next = *list;
  208|  8.45M|    *list = bc;
  209|  8.45M|    if (bc->flags & BACKUP_LOCAL)
  ------------------
  |  |  186|  8.45M|#define BACKUP_LOCAL 1
  ------------------
  |  Branch (209:9): [True: 0, False: 8.45M]
  ------------------
  210|      0|        co->is_set_locally = true;
  211|  8.45M|}
m_config_frontend.c:backup_dtor:
  179|  8.45M|{
  180|  8.45M|    struct m_opt_backup *bc = p;
  181|  8.45M|    m_option_free(bc->co->opt, bc->backup);
  182|  8.45M|    if (bc->nval)
  ------------------
  |  Branch (182:9): [True: 0, False: 8.45M]
  ------------------
  183|      0|        m_option_free(bc->co->opt, bc->nval);
  184|  8.45M|}
m_config_frontend.c:m_config_get_co_any:
  294|  1.96M|{
  295|  1.96M|    struct m_config_option *co = m_config_get_co_raw(config, name);
  296|  1.96M|    if (!co)
  ------------------
  |  Branch (296:9): [True: 258k, False: 1.70M]
  ------------------
  297|   258k|        return NULL;
  298|       |
  299|  1.70M|    const char *prefix = config->is_toplevel ? "--" : "";
  ------------------
  |  Branch (299:26): [True: 1.69M, False: 5.70k]
  ------------------
  300|  1.70M|    if (co->opt->type == &m_option_type_alias) {
  ------------------
  |  Branch (300:9): [True: 5.99k, False: 1.69M]
  ------------------
  301|  5.99k|        char buf[M_CONFIG_MAX_OPT_NAME_LEN];
  302|  5.99k|        const char *alias = m_config_shadow_get_alias_from_opt(config->shadow, co->opt_id,
  303|  5.99k|                                                               buf, sizeof(buf));
  304|  5.99k|        if (co->opt->deprecation_message && !co->warning_was_printed) {
  ------------------
  |  Branch (304:13): [True: 221, False: 5.77k]
  |  Branch (304:45): [True: 22, False: 199]
  ------------------
  305|     22|            if (co->opt->deprecation_message[0]) {
  ------------------
  |  Branch (305:17): [True: 0, False: 22]
  ------------------
  306|      0|                MP_WARN(config, "Warning: option %s%s was replaced with "
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  307|      0|                        "%s%s: %s\n", prefix, co->name, prefix, alias,
  308|      0|                        co->opt->deprecation_message);
  309|     22|            } else {
  310|     22|                MP_WARN(config, "Warning: option %s%s was replaced with "
  ------------------
  |  |   86|     22|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     22|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  311|     22|                        "%s%s and might be removed in the future.\n",
  312|     22|                        prefix, co->name, prefix, alias);
  313|     22|            }
  314|     22|            co->warning_was_printed = true;
  315|     22|        }
  316|  5.99k|        return m_config_get_co_any(config, bstr0(alias));
  317|  1.69M|    } else if (co->opt->type == &m_option_type_removed) {
  ------------------
  |  Branch (317:16): [True: 234, False: 1.69M]
  ------------------
  318|    234|        if (!co->warning_was_printed) {
  ------------------
  |  Branch (318:13): [True: 17, False: 217]
  ------------------
  319|     17|            char *msg = co->opt->priv;
  320|     17|            if (msg) {
  ------------------
  |  Branch (320:17): [True: 17, False: 0]
  ------------------
  321|     17|                MP_FATAL(config, "Option %s%s was removed: %s\n",
  ------------------
  |  |   84|     17|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     17|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  322|     17|                         prefix, co->name, msg);
  323|     17|            } else {
  324|      0|                MP_FATAL(config, "Option %s%s was removed.\n",
  ------------------
  |  |   84|      0|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  325|      0|                         prefix, co->name);
  326|      0|            }
  327|     17|            co->warning_was_printed = true;
  328|     17|        }
  329|    234|        return NULL;
  330|  1.69M|    } else if (co->opt->deprecation_message) {
  ------------------
  |  Branch (330:16): [True: 214, False: 1.69M]
  ------------------
  331|    214|        if (!co->warning_was_printed) {
  ------------------
  |  Branch (331:13): [True: 14, False: 200]
  ------------------
  332|     14|            MP_WARN(config, "Warning: option %s%s is deprecated "
  ------------------
  |  |   86|     14|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     14|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  333|     14|                    "and might be removed in the future (%s).\n",
  334|     14|                    prefix, co->name, co->opt->deprecation_message);
  335|     14|            co->warning_was_printed = true;
  336|     14|        }
  337|    214|    }
  338|  1.69M|    return co;
  339|  1.70M|}
m_config_frontend.c:async_change_cb:
  491|      6|{
  492|      6|    struct m_config *config = p;
  493|       |
  494|      6|    void *ptr;
  495|      6|    while (m_config_cache_get_next_changed(config->cache, &ptr)) {
  ------------------
  |  Branch (495:12): [True: 0, False: 6]
  ------------------
  496|       |        // Regrettable linear search, might degenerate to quadratic.
  497|      0|        for (int n = 0; n < config->num_opts; n++) {
  ------------------
  |  Branch (497:25): [True: 0, False: 0]
  ------------------
  498|      0|            struct m_config_option *co = &config->opts[n];
  499|      0|            if (co->data == ptr) {
  ------------------
  |  Branch (499:17): [True: 0, False: 0]
  ------------------
  500|      0|                if (config->option_change_callback) {
  ------------------
  |  Branch (500:21): [True: 0, False: 0]
  ------------------
  501|      0|                    config->option_change_callback(
  502|      0|                        config->option_change_callback_ctx, co,
  503|      0|                        config->cache->change_flags, false);
  504|      0|                }
  505|      0|                break;
  506|      0|            }
  507|      0|        }
  508|      0|        config->cache->change_flags = 0;
  509|      0|    }
  510|      6|}
m_config_frontend.c:config_destroy:
  520|  28.2k|{
  521|  28.2k|    struct m_config *config = p;
  522|  28.2k|    config->option_change_callback = NULL;
  523|  28.2k|    m_config_restore_backups(config);
  524|       |
  525|  28.2k|    struct m_opt_backup **list = &config->watch_later_backup_opts;
  526|  8.48M|    while (*list) {
  ------------------
  |  Branch (526:12): [True: 8.45M, False: 28.2k]
  ------------------
  527|  8.45M|        struct m_opt_backup *bc = *list;
  528|  8.45M|        *list = bc->next;
  529|  8.45M|        talloc_free(bc);
  ------------------
  |  |   47|  8.45M|#define talloc_free                     ta_free
  ------------------
  530|  8.45M|    }
  531|       |
  532|  28.2k|    talloc_free(config->cache);
  ------------------
  |  |   47|  28.2k|#define talloc_free                     ta_free
  ------------------
  533|  28.2k|    talloc_free(config->shadow);
  ------------------
  |  |   47|  28.2k|#define talloc_free                     ta_free
  ------------------
  534|  28.2k|}
m_config_frontend.c:notify_opt:
  587|  3.93k|{
  588|   169k|    for (int n = 0; n < config->num_opts; n++) {
  ------------------
  |  Branch (588:21): [True: 169k, False: 0]
  ------------------
  589|   169k|        struct m_config_option *co = &config->opts[n];
  590|   169k|        if (co->data == ptr) {
  ------------------
  |  Branch (590:13): [True: 3.93k, False: 165k]
  ------------------
  591|  3.93k|            if (m_config_cache_write_opt(config->cache, co->data))
  ------------------
  |  Branch (591:17): [True: 6, False: 3.93k]
  ------------------
  592|      6|                force_self_notify_change_opt(config, co, self_notification);
  593|  3.93k|            return;
  594|  3.93k|        }
  595|   169k|    }
  596|       |    // ptr doesn't point to any config->optstruct field declared in the
  597|       |    // option list?
  598|      0|    mp_assert(false);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  599|      0|}
m_config_frontend.c:handle_set_opt_flags:
  385|  2.73M|{
  386|  2.73M|    uint64_t optflags = co->opt->flags;
  387|  2.73M|    bool set = !(flags & M_SETOPT_CHECK_ONLY);
  388|       |
  389|  2.73M|    if ((flags & M_SETOPT_PRE_PARSE_ONLY) && !(optflags & M_OPT_PRE_PARSE))
  ------------------
  |  |  459|   106k|#define M_OPT_PRE_PARSE         (UINT64_C(1) << 62)
  ------------------
  |  Branch (389:9): [True: 106k, False: 2.63M]
  |  Branch (389:46): [True: 82.3k, False: 23.7k]
  ------------------
  390|  82.3k|        return 0;
  391|       |
  392|  2.65M|    if ((flags & M_SETOPT_PRESERVE_CMDLINE) && co->is_set_from_cmdline)
  ------------------
  |  Branch (392:9): [True: 0, False: 2.65M]
  |  Branch (392:48): [True: 0, False: 0]
  ------------------
  393|      0|        set = false;
  394|       |
  395|  2.65M|    if ((flags & M_SETOPT_NO_OVERWRITE) &&
  ------------------
  |  Branch (395:9): [True: 32, False: 2.65M]
  ------------------
  396|  2.65M|        (co->is_set_from_cmdline || co->is_set_from_config))
  ------------------
  |  Branch (396:10): [True: 8, False: 24]
  |  Branch (396:37): [True: 12, False: 12]
  ------------------
  397|     20|        set = false;
  398|       |
  399|  2.65M|    if ((flags & M_SETOPT_NO_PRE_PARSE) && (optflags & M_OPT_PRE_PARSE))
  ------------------
  |  |  459|      0|#define M_OPT_PRE_PARSE         (UINT64_C(1) << 62)
  ------------------
  |  Branch (399:9): [True: 0, False: 2.65M]
  |  Branch (399:44): [True: 0, False: 0]
  ------------------
  400|      0|        return M_OPT_INVALID;
  ------------------
  |  |  523|      0|#define M_OPT_INVALID           -3
  ------------------
  401|       |
  402|       |    // Check if this option isn't forbidden in the current mode
  403|  2.65M|    if ((flags & M_SETOPT_FROM_CONFIG_FILE) && (optflags & M_OPT_NOCFG)) {
  ------------------
  |  |  456|  2.44M|#define M_OPT_NOCFG             (UINT64_C(1) << 63)
  ------------------
  |  Branch (403:9): [True: 2.44M, False: 210k]
  |  Branch (403:48): [True: 0, False: 2.44M]
  ------------------
  404|      0|        MP_ERR(config, "The %s option can't be used in a config file.\n",
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  405|      0|               co->name);
  406|      0|        return M_OPT_INVALID;
  ------------------
  |  |  523|      0|#define M_OPT_INVALID           -3
  ------------------
  407|      0|    }
  408|  2.65M|    if ((flags & M_SETOPT_BACKUP) && set)
  ------------------
  |  Branch (408:9): [True: 11.5k, False: 2.64M]
  |  Branch (408:38): [True: 0, False: 11.5k]
  ------------------
  409|      0|        ensure_backup(&config->backup_opts, BACKUP_LOCAL, co);
  ------------------
  |  |  186|      0|#define BACKUP_LOCAL 1
  ------------------
  410|       |
  411|  2.65M|    return set ? 2 : 1;
  ------------------
  |  Branch (411:12): [True: 719k, False: 1.93M]
  ------------------
  412|  2.65M|}
m_config_frontend.c:m_config_handle_special_options:
  430|   355k|{
  431|   355k|    if (config->use_profiles && strcmp(co->name, "profile") == 0) {
  ------------------
  |  Branch (431:9): [True: 355k, False: 0]
  |  Branch (431:33): [True: 23.2k, False: 331k]
  ------------------
  432|  23.2k|        char **list = *(char ***)data;
  433|       |
  434|  23.2k|        if (list && list[0] && !list[1] && strcmp(list[0], "help") == 0) {
  ------------------
  |  Branch (434:13): [True: 23.2k, False: 67]
  |  Branch (434:21): [True: 23.2k, False: 0]
  |  Branch (434:32): [True: 22.7k, False: 446]
  |  Branch (434:44): [True: 1, False: 22.7k]
  ------------------
  435|      1|            if (!config->profiles) {
  ------------------
  |  Branch (435:17): [True: 0, False: 1]
  ------------------
  436|      0|                MP_INFO(config, "No profiles have been defined.\n");
  ------------------
  |  |   87|      0|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  437|      0|                return M_OPT_EXIT;
  ------------------
  |  |  533|      0|#define M_OPT_EXIT              -6
  ------------------
  438|      0|            }
  439|      1|            list_profiles(config);
  440|      1|            return M_OPT_EXIT;
  ------------------
  |  |  533|      1|#define M_OPT_EXIT              -6
  ------------------
  441|      1|        }
  442|       |
  443|  57.2k|        for (int n = 0; list && list[n]; n++) {
  ------------------
  |  Branch (443:25): [True: 57.2k, False: 67]
  |  Branch (443:33): [True: 34.2k, False: 23.0k]
  ------------------
  444|  34.2k|            int r = m_config_set_profile(config, list[n], flags);
  445|  34.2k|            if (r < 0)
  ------------------
  |  Branch (445:17): [True: 208, False: 33.9k]
  ------------------
  446|    208|                return r;
  447|  34.2k|        }
  448|  23.0k|        return 0;
  449|  23.2k|    }
  450|       |
  451|   331k|    if (config->includefunc && strcmp(co->name, "include") == 0) {
  ------------------
  |  Branch (451:9): [True: 331k, False: 0]
  |  Branch (451:32): [True: 0, False: 331k]
  ------------------
  452|      0|        char *param = *(char **)data;
  453|      0|        if (!param || !param[0])
  ------------------
  |  Branch (453:13): [True: 0, False: 0]
  |  Branch (453:23): [True: 0, False: 0]
  ------------------
  454|      0|            return M_OPT_MISSING_PARAM;
  ------------------
  |  |  520|      0|#define M_OPT_MISSING_PARAM     -2
  ------------------
  455|      0|        if (config->recursion_depth >= MAX_RECURSION_DEPTH) {
  ------------------
  |  |   45|      0|#define MAX_RECURSION_DEPTH 8
  ------------------
  |  Branch (455:13): [True: 0, False: 0]
  ------------------
  456|      0|            MP_ERR(config, "Maximum 'include' nesting depth exceeded.\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  457|      0|            return M_OPT_INVALID;
  ------------------
  |  |  523|      0|#define M_OPT_INVALID           -3
  ------------------
  458|      0|        }
  459|      0|        config->recursion_depth += 1;
  460|      0|        config->includefunc(config->includefunc_ctx, param, flags);
  461|      0|        config->recursion_depth -= 1;
  462|      0|        if (config->recursion_depth == 0 && config->profile_stack_depth == 0)
  ------------------
  |  Branch (462:13): [True: 0, False: 0]
  |  Branch (462:45): [True: 0, False: 0]
  ------------------
  463|      0|            m_config_finish_default_profile(config, flags);
  464|      0|        return 1;
  465|      0|    }
  466|       |
  467|   331k|    if (config->use_profiles && strcmp(co->name, "show-profile") == 0)
  ------------------
  |  Branch (467:9): [True: 331k, False: 0]
  |  Branch (467:33): [True: 32, False: 331k]
  ------------------
  468|     32|        return show_profile(config, bstr0(*(char **)data), 0);
  469|       |
  470|   331k|    if (config->is_toplevel && (strcmp(co->name, "h") == 0 ||
  ------------------
  |  Branch (470:9): [True: 331k, False: 0]
  |  Branch (470:33): [True: 152, False: 331k]
  ------------------
  471|   331k|                                strcmp(co->name, "help") == 0))
  ------------------
  |  Branch (471:33): [True: 1, False: 331k]
  ------------------
  472|    153|    {
  473|    153|        char *h = *(char **)data;
  474|    153|        mp_info(config->log, "%s", mp_help_text);
  ------------------
  |  |   74|    153|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  475|    153|        if (h && h[0])
  ------------------
  |  Branch (475:13): [True: 153, False: 0]
  |  Branch (475:18): [True: 136, False: 17]
  ------------------
  476|    136|            m_config_print_option_list(config, h);
  477|    153|        return M_OPT_EXIT;
  ------------------
  |  |  533|    153|#define M_OPT_EXIT              -6
  ------------------
  478|    153|    }
  479|       |
  480|   331k|    if (strcmp(co->name, "list-options") == 0) {
  ------------------
  |  Branch (480:9): [True: 6, False: 331k]
  ------------------
  481|      6|        m_config_print_option_list(config, "*");
  482|      6|        return M_OPT_EXIT;
  ------------------
  |  |  533|      6|#define M_OPT_EXIT              -6
  ------------------
  483|      6|    }
  484|       |
  485|   331k|    return M_OPT_UNKNOWN;
  ------------------
  |  |  517|   331k|#define M_OPT_UNKNOWN           -1
  ------------------
  486|   331k|}
m_config_frontend.c:list_profiles:
   77|      3|{
   78|      3|    MP_INFO(config, "Available profiles:\n");
  ------------------
  |  |   87|      3|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      3|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
   79|     42|    for (struct m_profile *p = config->profiles; p; p = p->next)
  ------------------
  |  Branch (79:50): [True: 39, False: 3]
  ------------------
   80|     39|        MP_INFO(config, "\t%s\t%s\n", p->name, p->desc ? p->desc : "");
  ------------------
  |  |   87|     39|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     78|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 0, False: 39]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   81|      3|}
m_config_frontend.c:show_profile:
   84|     34|{
   85|     34|    struct m_profile *p;
   86|     34|    if (!param.len) {
  ------------------
  |  Branch (86:9): [True: 2, False: 32]
  ------------------
   87|      2|        list_profiles(config);
   88|      2|        return M_OPT_EXIT;
  ------------------
  |  |  533|      2|#define M_OPT_EXIT              -6
  ------------------
   89|      2|    }
   90|     32|    if (!(p = m_config_get_profile(config, param))) {
  ------------------
  |  Branch (90:9): [True: 24, False: 8]
  ------------------
   91|     24|        MP_ERR(config, "Unknown profile '%.*s'.\n", BSTR_P(param));
  ------------------
  |  |   85|     24|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     48|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 24, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   92|     24|        return M_OPT_EXIT;
  ------------------
  |  |  533|     24|#define M_OPT_EXIT              -6
  ------------------
   93|     24|    }
   94|      8|    if (!depth)
  ------------------
  |  Branch (94:9): [True: 6, False: 2]
  ------------------
   95|      8|        MP_INFO(config, "Profile %s: %s\n", p->name,
  ------------------
  |  |   87|      6|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     12|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 0, False: 6]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   96|      8|                p->desc ? p->desc : "");
   97|      8|    depth++;
   98|      8|    if (p->cond) {
  ------------------
  |  Branch (98:9): [True: 0, False: 8]
  ------------------
   99|      0|        MP_INFO(config, "%*sprofile-cond=%s\n", depth, "",
  ------------------
  |  |   87|      0|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  100|      0|                p->cond);
  101|      0|    }
  102|     40|    for (int i = 0; i < p->num_opts; i++) {
  ------------------
  |  Branch (102:21): [True: 32, False: 8]
  ------------------
  103|     32|        MP_INFO(config, "%*s%s=%s\n", depth, "",
  ------------------
  |  |   87|     32|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     32|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  104|     32|                p->opts[2 * i], p->opts[2 * i + 1]);
  105|       |
  106|     32|        if (depth < MAX_PROFILE_DEPTH
  ------------------
  |  |   43|     64|#define MAX_PROFILE_DEPTH 20
  ------------------
  |  Branch (106:13): [True: 32, False: 0]
  ------------------
  107|     32|            && !strcmp(p->opts[2*i], "profile")) {
  ------------------
  |  Branch (107:16): [True: 2, False: 30]
  ------------------
  108|      2|            char *e, *list = p->opts[2 * i + 1];
  109|      2|            while ((e = strchr(list, ','))) {
  ------------------
  |  Branch (109:20): [True: 0, False: 2]
  ------------------
  110|      0|                int l = e - list;
  111|      0|                if (!l)
  ------------------
  |  Branch (111:21): [True: 0, False: 0]
  ------------------
  112|      0|                    continue;
  113|      0|                show_profile(config, (bstr){list, e - list}, depth);
  114|      0|                list = e + 1;
  115|      0|            }
  116|      2|            if (list[0] != '\0')
  ------------------
  |  Branch (116:17): [True: 2, False: 0]
  ------------------
  117|      2|                show_profile(config, bstr0(list), depth);
  118|      2|        }
  119|     32|    }
  120|      8|    depth--;
  121|      8|    return M_OPT_EXIT;
  ------------------
  |  |  533|      8|#define M_OPT_EXIT              -6
  ------------------
  122|     32|}
m_config_frontend.c:force_self_notify_change_opt:
  576|   221k|{
  577|   221k|    int changed =
  578|   221k|        m_config_cache_get_option_change_mask(config->cache, co->opt_id);
  579|       |
  580|   221k|    if (config->option_change_callback) {
  ------------------
  |  Branch (580:9): [True: 6, False: 221k]
  ------------------
  581|      6|        config->option_change_callback(config->option_change_callback_ctx, co,
  582|      6|                                       changed, self_notification);
  583|      6|    }
  584|   221k|}
m_config_frontend.c:m_config_mogrify_cli_opt:
  652|  1.68M|{
  653|  1.68M|    *out_negate = false;
  654|  1.68M|    *out_add_flags = 0;
  655|       |
  656|  1.68M|    struct m_config_option *co = m_config_get_co(config, *name);
  657|  1.68M|    if (co)
  ------------------
  |  Branch (657:9): [True: 1.42M, False: 266k]
  ------------------
  658|  1.42M|        return co;
  659|       |
  660|       |    // Turn "--no-foo" into "foo" + set *out_negate.
  661|   266k|    bstr no_name = *name;
  662|   266k|    if (!co && bstr_eatstart0(&no_name, "no-")) {
  ------------------
  |  Branch (662:9): [True: 266k, False: 0]
  |  Branch (662:16): [True: 1.75k, False: 264k]
  ------------------
  663|  1.75k|        co = m_config_get_co(config, no_name);
  664|  1.75k|        if (!co)
  ------------------
  |  Branch (664:13): [True: 433, False: 1.32k]
  ------------------
  665|    433|            return NULL;
  666|       |
  667|       |        // Not all choice types have this value - if they don't, then parsing
  668|       |        // them will simply result in an error. Good enough.
  669|  1.32k|        if (!(co->opt->type->flags & M_OPT_TYPE_CHOICE) &&
  ------------------
  |  |  500|  1.32k|#define M_OPT_TYPE_CHOICE               (1 << 1)
  ------------------
  |  Branch (669:13): [True: 390, False: 930]
  ------------------
  670|  1.32k|            !(co->opt->flags & M_OPT_ALLOW_NO))
  ------------------
  |  |  476|    390|#define M_OPT_ALLOW_NO          (UINT64_C(1) << 57)
  ------------------
  |  Branch (670:13): [True: 196, False: 194]
  ------------------
  671|    196|            return NULL;
  672|       |
  673|  1.12k|        *name = no_name;
  674|  1.12k|        *out_negate = true;
  675|  1.12k|        return co;
  676|  1.32k|    }
  677|       |
  678|       |    // Resolve CLI alias. (We don't allow you to combine them with "--no-".)
  679|   264k|    co = m_config_get_co_any(config, *name);
  680|   264k|    if (co && co->opt->type == &m_option_type_cli_alias)
  ------------------
  |  Branch (680:9): [True: 136k, False: 128k]
  |  Branch (680:15): [True: 136k, False: 0]
  ------------------
  681|   136k|        *name = bstr0((char *)co->opt->priv);
  682|       |
  683|       |    // Might be a suffix "action", like "--vf-add". Expensively check for
  684|       |    // matches. (We don't allow you to combine them with "--no-".)
  685|  76.4M|    for (int n = 0; n < config->num_opts; n++) {
  ------------------
  |  Branch (685:21): [True: 76.3M, False: 85.9k]
  ------------------
  686|  76.3M|        co = &config->opts[n];
  687|  76.3M|        struct bstr basename = bstr0(co->name);
  688|       |
  689|  76.3M|        if (!bstr_startswith(*name, basename))
  ------------------
  |  Branch (689:13): [True: 75.9M, False: 341k]
  ------------------
  690|  75.9M|            continue;
  691|       |
  692|       |        // Aliased option + a suffix action, e.g. --opengl-shaders-append
  693|   341k|        if (co->opt->type == &m_option_type_alias)
  ------------------
  |  Branch (693:13): [True: 743, False: 340k]
  ------------------
  694|    743|            co = m_config_get_co_any(config, basename);
  695|   341k|        if (!co)
  ------------------
  |  Branch (695:13): [True: 0, False: 341k]
  ------------------
  696|      0|            continue;
  697|       |
  698|   341k|        const struct m_option_type *type = co->opt->type;
  699|   586k|        for (int i = 0; type->actions && type->actions[i].name; i++) {
  ------------------
  |  Branch (699:25): [True: 424k, False: 161k]
  |  Branch (699:42): [True: 423k, False: 1.23k]
  ------------------
  700|   423k|            const struct m_option_action *action = &type->actions[i];
  701|   423k|            bstr suffix = bstr0(action->name);
  702|       |
  703|   423k|            if (bstr_endswith(*name, suffix) &&
  ------------------
  |  Branch (703:17): [True: 179k, False: 244k]
  ------------------
  704|   423k|                (name->len == basename.len + 1 + suffix.len) &&
  ------------------
  |  Branch (704:17): [True: 179k, False: 254]
  ------------------
  705|   423k|                name->start[basename.len] == '-')
  ------------------
  |  Branch (705:17): [True: 178k, False: 227]
  ------------------
  706|   178k|            {
  707|   178k|                *out_add_flags = action->flags;
  708|   178k|                return co;
  709|   178k|            }
  710|   423k|        }
  711|   341k|    }
  712|       |
  713|  85.9k|    return NULL;
  714|   264k|}
m_config_frontend.c:sort_opt_compare:
  829|   826k|{
  830|   826k|    const struct m_config_option *a = pa;
  831|   826k|    const struct m_config_option *b = pb;
  832|   826k|    return strcasecmp(a->name, b->name);
  833|   826k|}
m_config_frontend.c:find_check_profile:
  986|  68.7k|{
  987|  68.7k|    struct m_profile *p = m_config_get_profile0(config, name);
  988|  68.7k|    if (!p) {
  ------------------
  |  Branch (988:9): [True: 208, False: 68.5k]
  ------------------
  989|    208|        MP_WARN(config, "Unknown profile '%s'.\n", name);
  ------------------
  |  |   86|    208|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    208|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  990|    208|        return NULL;
  991|    208|    }
  992|  90.7k|    for (size_t i = 0; i < config->profile_stack_depth; ++i) {
  ------------------
  |  Branch (992:24): [True: 22.2k, False: 68.5k]
  ------------------
  993|  22.2k|        if (strcmp(config->profile_stack[i], name))
  ------------------
  |  Branch (993:13): [True: 22.2k, False: 0]
  ------------------
  994|  22.2k|            continue;
  995|      0|        MP_WARN(config, "Profile '%s' has already been applied.\n", name);
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  996|      0|        return NULL;
  997|  22.2k|    }
  998|  68.5k|    if (config->profile_stack_depth > MAX_PROFILE_DEPTH) {
  ------------------
  |  |   43|  68.5k|#define MAX_PROFILE_DEPTH 20
  ------------------
  |  Branch (998:9): [True: 0, False: 68.5k]
  ------------------
  999|      0|        MP_WARN(config, "Profile inclusion too deep.\n");
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1000|      0|        return NULL;
 1001|      0|    }
 1002|  68.5k|    return p;
 1003|  68.5k|}

m_option_parse:
   65|  5.15M|{
   66|  5.15M|    int r = M_OPT_INVALID;
  ------------------
  |  |  523|  5.15M|#define M_OPT_INVALID           -3
  ------------------
   67|  5.15M|    if (bstr_equals0(param, "help") && opt->help) {
  ------------------
  |  Branch (67:9): [True: 1.15k, False: 5.15M]
  |  Branch (67:40): [True: 15, False: 1.14k]
  ------------------
   68|     15|        r = opt->help(log, opt, name);
   69|     15|        if (r < 0)
  ------------------
  |  Branch (69:13): [True: 15, False: 0]
  ------------------
   70|     15|            return r;
   71|     15|    }
   72|       |
   73|  5.15M|    r = opt->type->parse(log, opt, name, param, dst);
   74|  5.15M|    if (r < 0)
  ------------------
  |  Branch (74:9): [True: 9.45k, False: 5.14M]
  ------------------
   75|  9.45k|        return r;
   76|       |
   77|  5.14M|    if (opt->validate) {
  ------------------
  |  Branch (77:9): [True: 753, False: 5.14M]
  ------------------
   78|    753|        r = opt->validate(log, opt, name, dst);
   79|    753|        if (r < 0) {
  ------------------
  |  Branch (79:13): [True: 214, False: 539]
  ------------------
   80|    214|            if (opt->type->free)
  ------------------
  |  Branch (80:17): [True: 214, False: 0]
  ------------------
   81|    214|                opt->type->free(dst);
   82|    214|            return r;
   83|    214|        }
   84|    753|    }
   85|  5.14M|    return 1;
   86|  5.14M|}
m_option_strerror:
   89|  79.2k|{
   90|  79.2k|    switch (code) {
   91|  73.2k|    case M_OPT_UNKNOWN:
  ------------------
  |  |  517|  73.2k|#define M_OPT_UNKNOWN           -1
  ------------------
  |  Branch (91:5): [True: 73.2k, False: 5.96k]
  ------------------
   92|  73.2k|        return "option not found";
   93|    179|    case M_OPT_MISSING_PARAM:
  ------------------
  |  |  520|    179|#define M_OPT_MISSING_PARAM     -2
  ------------------
  |  Branch (93:5): [True: 179, False: 79.0k]
  ------------------
   94|    179|        return "option requires parameter";
   95|  5.39k|    case M_OPT_INVALID:
  ------------------
  |  |  523|  5.39k|#define M_OPT_INVALID           -3
  ------------------
  |  Branch (95:5): [True: 5.39k, False: 73.8k]
  ------------------
   96|  5.39k|        return "option parameter could not be parsed";
   97|    192|    case M_OPT_OUT_OF_RANGE:
  ------------------
  |  |  527|    192|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
  |  Branch (97:5): [True: 192, False: 79.0k]
  ------------------
   98|    192|        return "parameter is outside values allowed for option";
   99|    199|    case M_OPT_DISALLOW_PARAM:
  ------------------
  |  |  530|    199|#define M_OPT_DISALLOW_PARAM    -5
  ------------------
  |  Branch (99:5): [True: 199, False: 79.0k]
  ------------------
  100|    199|        return "option doesn't take a parameter";
  101|      0|    default:
  ------------------
  |  Branch (101:5): [True: 0, False: 79.2k]
  ------------------
  102|      0|        return "parser error";
  103|  79.2k|    }
  104|  79.2k|}
m_option_required_params:
  107|   185k|{
  108|   185k|    if (opt->type->flags & M_OPT_TYPE_OPTIONAL_PARAM)
  ------------------
  |  |  495|   185k|#define M_OPT_TYPE_OPTIONAL_PARAM       (1 << 0)
  ------------------
  |  Branch (108:9): [True: 48.5k, False: 136k]
  ------------------
  109|  48.5k|        return 0;
  110|   136k|    if (opt->flags & M_OPT_OPTIONAL_PARAM)
  ------------------
  |  |  485|   136k|#define M_OPT_OPTIONAL_PARAM    (UINT64_C(1) << 54)
  ------------------
  |  Branch (110:9): [True: 572, False: 136k]
  ------------------
  111|    572|        return 0;
  112|   136k|    if (opt->type == &m_option_type_choice) {
  ------------------
  |  Branch (112:9): [True: 4.19k, False: 131k]
  ------------------
  113|  4.19k|        const struct m_opt_choice_alternatives *alt;
  114|  12.8k|        for (alt = opt->priv; alt->name; alt++) {
  ------------------
  |  Branch (114:31): [True: 10.0k, False: 2.79k]
  ------------------
  115|  10.0k|            if (strcmp(alt->name, "yes") == 0)
  ------------------
  |  Branch (115:17): [True: 1.40k, False: 8.65k]
  ------------------
  116|  1.40k|                return 0;
  117|  10.0k|        }
  118|  4.19k|    }
  119|   134k|    return 1;
  120|   136k|}
format_file_size:
  574|    270|{
  575|    270|    double s = size;
  576|    270|    if (size < 1024)
  ------------------
  |  Branch (576:9): [True: 0, False: 270]
  ------------------
  577|      0|        return talloc_asprintf(NULL, "%.0f B", s);
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  578|       |
  579|    270|    if (size < (1024 * 1024))
  ------------------
  |  Branch (579:9): [True: 34, False: 236]
  ------------------
  580|     34|        return talloc_asprintf(NULL, "%.3f KiB", s / (1024.0));
  ------------------
  |  |   52|     34|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|     34|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  581|       |
  582|    236|    if (size < (1024 * 1024 * 1024))
  ------------------
  |  Branch (582:9): [True: 198, False: 38]
  ------------------
  583|    198|        return talloc_asprintf(NULL, "%.3f MiB", s / (1024.0 * 1024.0));
  ------------------
  |  |   52|    198|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|    198|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  584|       |
  585|     38|    if (size < (1024LL * 1024LL * 1024LL * 1024LL))
  ------------------
  |  Branch (585:9): [True: 38, False: 0]
  ------------------
  586|     38|        return talloc_asprintf(NULL, "%.3f GiB", s / (1024.0 * 1024.0 * 1024.0));
  ------------------
  |  |   52|     38|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|     38|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  587|       |
  588|      0|    return talloc_asprintf(NULL, "%.3f TiB", s / (1024.0 * 1024.0 * 1024.0 * 1024.0));
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  589|     38|}
m_opt_choice_str:
  613|    234|{
  614|    234|    for (const struct m_opt_choice_alternatives *c = choices; c->name; c++) {
  ------------------
  |  Branch (614:63): [True: 234, False: 0]
  ------------------
  615|    234|        if (c->value == value)
  ------------------
  |  Branch (615:13): [True: 234, False: 0]
  ------------------
  616|    234|            return c->name;
  617|    234|    }
  618|      0|    mp_require(false && "Invalid choice value!");
  ------------------
  |  |   42|      0|#define mp_require assert
  ------------------
  619|      0|}
m_obj_list_find:
 2940|  86.0k|{
 2941|   518k|    for (int i = 0; ; i++) {
 2942|   518k|        if (!l->get_desc(dst, i))
  ------------------
  |  Branch (2942:13): [True: 33.7k, False: 484k]
  ------------------
 2943|  33.7k|            break;
 2944|   484k|        if (bstr_equals0(name, dst->name))
  ------------------
  |  Branch (2944:13): [True: 52.2k, False: 432k]
  ------------------
 2945|  52.2k|            return true;
 2946|   484k|    }
 2947|   118k|    for (int i = 0; l->aliases[i][0]; i++) {
  ------------------
  |  Branch (2947:21): [True: 95.9k, False: 22.3k]
  ------------------
 2948|  95.9k|        const char *aname = l->aliases[i][0];
 2949|  95.9k|        const char *alias = l->aliases[i][1];
 2950|  95.9k|        if (bstr_equals0(name, aname) && m_obj_list_find(dst, l, bstr0(alias)))
  ------------------
  |  Branch (2950:13): [True: 11.5k, False: 84.4k]
  |  Branch (2950:42): [True: 11.4k, False: 77]
  ------------------
 2951|  11.4k|        {
 2952|  11.4k|            dst->replaced_name = aname;
 2953|  11.4k|            return true;
 2954|  11.4k|        }
 2955|  95.9k|    }
 2956|  22.3k|    return false;
 2957|  33.7k|}
m_obj_settings_equal:
 3779|  70.6k|{
 3780|  70.6k|    if (!str_equal(NULL, &a->name, &b->name))
  ------------------
  |  Branch (3780:9): [True: 28.0k, False: 42.5k]
  ------------------
 3781|  28.0k|        return false;
 3782|       |
 3783|  42.5k|    if (!str_equal(NULL, &a->label, &b->label))
  ------------------
  |  Branch (3783:9): [True: 510, False: 42.0k]
  ------------------
 3784|    510|        return false;
 3785|       |
 3786|  42.0k|    if (a->enabled != b->enabled)
  ------------------
  |  Branch (3786:9): [True: 136, False: 41.9k]
  ------------------
 3787|    136|        return false;
 3788|       |
 3789|  41.9k|    return str_list_equal(NULL, &a->attribs, &b->attribs);
 3790|  42.0k|}
node_get_alloc:
 3906|   538k|{
 3907|       |    // Assume it was allocated with copy_node(), which allocates all
 3908|       |    // sub-nodes with the parent node as talloc parent.
 3909|   538k|    switch (node->format) {
 3910|      0|    case MPV_FORMAT_STRING:
  ------------------
  |  Branch (3910:5): [True: 0, False: 538k]
  ------------------
 3911|      0|        return node->u.string;
 3912|  1.61k|    case MPV_FORMAT_NODE_ARRAY:
  ------------------
  |  Branch (3912:5): [True: 1.61k, False: 536k]
  ------------------
 3913|   526k|    case MPV_FORMAT_NODE_MAP:
  ------------------
  |  Branch (3913:5): [True: 524k, False: 13.7k]
  ------------------
 3914|   526k|        return node->u.list;
 3915|  12.1k|    default:
  ------------------
  |  Branch (3915:5): [True: 12.1k, False: 526k]
  ------------------
 3916|  12.1k|        return NULL;
 3917|   538k|    }
 3918|   538k|}
m_option.c:parse_bool:
  151|   445k|{
  152|   445k|    if (bstr_equals0(param, "yes") || !param.len) {
  ------------------
  |  Branch (152:9): [True: 51.3k, False: 394k]
  |  Branch (152:39): [True: 14.1k, False: 380k]
  ------------------
  153|  65.4k|        if (dst)
  ------------------
  |  Branch (153:13): [True: 65.4k, False: 0]
  ------------------
  154|  65.4k|            VAL(dst) = 1;
  ------------------
  |  |  147|  65.4k|#define VAL(x) (*(bool *)(x))
  ------------------
  155|  65.4k|        return 1;
  156|  65.4k|    }
  157|   380k|    if (bstr_equals0(param, "no")) {
  ------------------
  |  Branch (157:9): [True: 379k, False: 782]
  ------------------
  158|   379k|        if (dst)
  ------------------
  |  Branch (158:13): [True: 379k, False: 0]
  ------------------
  159|   379k|            VAL(dst) = 0;
  ------------------
  |  |  147|   379k|#define VAL(x) (*(bool *)(x))
  ------------------
  160|   379k|        return 1;
  161|   379k|    }
  162|    782|    bool is_help = bstr_equals0(param, "help");
  163|    782|    if (is_help) {
  ------------------
  |  Branch (163:9): [True: 66, False: 716]
  ------------------
  164|     66|        mp_info(log, "Valid values for %.*s flag are:\n", BSTR_P(name));
  ------------------
  |  |   74|    132|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (74:56): [True: 66, False: 0]
  |  |  ------------------
  ------------------
  165|    716|    } else {
  166|    716|        mp_fatal(log, "Invalid parameter for %.*s flag: %.*s\n",
  ------------------
  |  |   71|  2.86k|#define mp_fatal(log, ...)      mp_msg(log, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (71:57): [True: 716, False: 0]
  |  |  |  Branch (71:57): [True: 716, False: 0]
  |  |  ------------------
  ------------------
  167|    716|                 BSTR_P(name), BSTR_P(param));
  168|    716|        mp_info(log, "Valid values are:\n");
  ------------------
  |  |   74|    716|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  169|    716|    }
  170|    782|    mp_info(log, "    yes\n");
  ------------------
  |  |   74|    782|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  171|    782|    mp_info(log, "    no\n");
  ------------------
  |  |   74|    782|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  172|    782|    mp_info(log, "    (passing nothing)\n");
  ------------------
  |  |   74|    782|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  173|    782|    return is_help ? M_OPT_EXIT : M_OPT_INVALID;
  ------------------
  |  |  533|     66|#define M_OPT_EXIT              -6
  ------------------
                  return is_help ? M_OPT_EXIT : M_OPT_INVALID;
  ------------------
  |  |  523|    716|#define M_OPT_INVALID           -3
  ------------------
  |  Branch (173:12): [True: 66, False: 716]
  ------------------
  174|   380k|}
m_option.c:print_bool:
  177|  7.33k|{
  178|  7.33k|    return talloc_strdup(NULL, VAL(val) ? "yes" : "no");
  ------------------
  |  |   50|  7.33k|#define talloc_strdup                   ta_xstrdup
  ------------------
                  return talloc_strdup(NULL, VAL(val) ? "yes" : "no");
  ------------------
  |  |  147|  7.33k|#define VAL(x) (*(bool *)(x))
  |  |  ------------------
  |  |  |  Branch (147:16): [True: 3.21k, False: 4.11k]
  |  |  ------------------
  ------------------
  179|  7.33k|}
m_option.c:copy_opt:
  140|  8.78M|{
  141|  8.78M|    if (dst && src)
  ------------------
  |  Branch (141:9): [True: 8.78M, False: 0]
  |  Branch (141:16): [True: 8.78M, False: 0]
  ------------------
  142|  8.78M|        memcpy(dst, src, opt->type->size);
  143|  8.78M|}
m_option.c:bool_get:
  200|      2|{
  201|      2|    dst->format = MPV_FORMAT_FLAG;
  202|      2|    dst->u.flag = !!VAL(src);
  ------------------
  |  |  147|      2|#define VAL(x) (*(bool *)(x))
  ------------------
  203|      2|    return 1;
  204|      2|}
m_option.c:bool_equal:
  207|   330k|{
  208|   330k|    return VAL(a) == VAL(b);
  ------------------
  |  |  147|   330k|#define VAL(x) (*(bool *)(x))
  ------------------
                  return VAL(a) == VAL(b);
  ------------------
  |  |  147|   330k|#define VAL(x) (*(bool *)(x))
  ------------------
  209|   330k|}
m_option.c:parse_int:
  357|   114k|{
  358|   114k|    long long tmp;
  359|   114k|    int r = parse_longlong(log, opt, INT_MIN, INT_MAX, name, param, &tmp);
  360|   114k|    if (r >= 0 && dst)
  ------------------
  |  Branch (360:9): [True: 114k, False: 16]
  |  Branch (360:19): [True: 114k, False: 0]
  ------------------
  361|   114k|        *(int *)dst = tmp;
  362|   114k|    return r;
  363|   114k|}
m_option.c:parse_longlong:
  313|   116k|{
  314|   116k|    if (param.len == 0)
  ------------------
  |  Branch (314:9): [True: 4, False: 116k]
  ------------------
  315|      4|        return M_OPT_MISSING_PARAM;
  ------------------
  |  |  520|      4|#define M_OPT_MISSING_PARAM     -2
  ------------------
  316|       |
  317|   116k|    struct bstr rest;
  318|   116k|    long long tmp_int = bstrtoll(param, &rest, 10);
  319|   116k|    if (rest.len)
  ------------------
  |  Branch (319:9): [True: 398, False: 115k]
  ------------------
  320|    398|        tmp_int = bstrtoll(param, &rest, 0);
  321|   116k|    if (rest.len) {
  ------------------
  |  Branch (321:9): [True: 69, False: 116k]
  ------------------
  322|     69|        mp_err(log, "The %.*s option must be an integer: %.*s\n",
  ------------------
  |  |   72|    276|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 69, False: 0]
  |  |  |  Branch (72:55): [True: 69, False: 0]
  |  |  ------------------
  ------------------
  323|     69|               BSTR_P(name), BSTR_P(param));
  324|     69|        return M_OPT_INVALID;
  ------------------
  |  |  523|     69|#define M_OPT_INVALID           -3
  ------------------
  325|     69|    }
  326|       |
  327|   116k|    long long min = OPT_INT_MIN(opt, long long, i_min);
  ------------------
  |  |   58|   116k|#define OPT_INT_MIN(opt, T, Tm) ((opt)->min < (opt)->max \
  |  |  ------------------
  |  |  |  Branch (58:34): [True: 18.4k, False: 97.8k]
  |  |  ------------------
  |  |   59|   116k|    ? ((opt)->min <= (double)(Tm) ? (Tm) : (T)((opt)->min)) : (Tm))
  |  |  ------------------
  |  |  |  Branch (59:8): [True: 0, False: 18.4k]
  |  |  ------------------
  ------------------
  328|   116k|    if (tmp_int < min) {
  ------------------
  |  Branch (328:9): [True: 10, False: 116k]
  ------------------
  329|     10|        mp_err(log, "The %.*s option must be >= %lld: %.*s\n",
  ------------------
  |  |   72|     40|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 10, False: 0]
  |  |  |  Branch (72:55): [True: 10, False: 0]
  |  |  ------------------
  ------------------
  330|     10|               BSTR_P(name), min, BSTR_P(param));
  331|     10|        return M_OPT_OUT_OF_RANGE;
  ------------------
  |  |  527|     10|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
  332|     10|    }
  333|       |
  334|   116k|    long long max = OPT_INT_MAX(opt, long long, i_max);
  ------------------
  |  |   60|   116k|#define OPT_INT_MAX(opt, T, Tm) ((opt)->min < (opt)->max \
  |  |  ------------------
  |  |  |  Branch (60:34): [True: 18.4k, False: 97.8k]
  |  |  ------------------
  |  |   61|   116k|    ? ((opt)->max >= (double)(Tm) ? (Tm) : (T)((opt)->max)) : (Tm))
  |  |  ------------------
  |  |  |  Branch (61:8): [True: 17.2k, False: 1.22k]
  |  |  ------------------
  ------------------
  335|   116k|    if (tmp_int > max) {
  ------------------
  |  Branch (335:9): [True: 58, False: 116k]
  ------------------
  336|     58|        mp_err(log, "The %.*s option must be <= %lld: %.*s\n",
  ------------------
  |  |   72|    232|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 58, False: 0]
  |  |  |  Branch (72:55): [True: 58, False: 0]
  |  |  ------------------
  ------------------
  337|     58|               BSTR_P(name), max, BSTR_P(param));
  338|     58|        return M_OPT_OUT_OF_RANGE;
  ------------------
  |  |  527|     58|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
  339|     58|    }
  340|       |
  341|   116k|    if (dst)
  ------------------
  |  Branch (341:9): [True: 116k, False: 0]
  ------------------
  342|   116k|        *(long long *)dst = tmp_int;
  343|       |
  344|   116k|    return 1;
  345|   116k|}
m_option.c:print_int:
  376|  15.1k|{
  377|  15.1k|    if (opt->type->size == sizeof(int64_t))
  ------------------
  |  Branch (377:9): [True: 196, False: 14.9k]
  ------------------
  378|    196|        return talloc_asprintf(NULL, "%"PRId64, *(const int64_t *)val);
  ------------------
  |  |   52|    196|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|    196|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  379|  14.9k|    return talloc_asprintf(NULL, "%d", *(const int *)val);
  ------------------
  |  |   52|  14.9k|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|  14.9k|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  380|  15.1k|}
m_option.c:int_equal:
  473|   130k|{
  474|   130k|    return *(int *)a == *(int *)b;
  475|   130k|}
m_option.c:parse_int64:
  367|    692|{
  368|    692|    long long tmp;
  369|    692|    int r = parse_longlong(log, opt, INT64_MIN, INT64_MAX, name, param, &tmp);
  370|    692|    if (r >= 0 && dst)
  ------------------
  |  Branch (370:9): [True: 672, False: 20]
  |  Branch (370:19): [True: 672, False: 0]
  ------------------
  371|    672|        *(int64_t *)dst = tmp;
  372|    692|    return r;
  373|    692|}
m_option.c:int64_get:
  458|  18.2k|{
  459|  18.2k|    dst->format = MPV_FORMAT_INT64;
  460|  18.2k|    dst->u.int64 = *(int64_t *)src;
  461|  18.2k|    return 1;
  462|  18.2k|}
m_option.c:int64_equal:
  478|  1.57k|{
  479|  1.57k|    return *(int64_t *)a == *(int64_t *)b;
  480|  1.57k|}
m_option.c:parse_byte_size:
  512|  18.1k|{
  513|  18.1k|    if (param.len == 0)
  ------------------
  |  Branch (513:9): [True: 1, False: 18.1k]
  ------------------
  514|      1|        return M_OPT_MISSING_PARAM;
  ------------------
  |  |  520|      1|#define M_OPT_MISSING_PARAM     -2
  ------------------
  515|       |
  516|  18.1k|    struct bstr r;
  517|  18.1k|    long long tmp_int = bstrtoll(param, &r, 0);
  518|  18.1k|    int64_t unit = 1;
  519|  18.1k|    if (r.len) {
  ------------------
  |  Branch (519:9): [True: 17.8k, False: 261]
  ------------------
  520|  17.8k|        if (bstrcasecmp0(r, "b") == 0) {
  ------------------
  |  Branch (520:13): [True: 67, False: 17.8k]
  ------------------
  521|     67|            unit = 1;
  522|  17.8k|        } else if (bstrcasecmp0(r, "kib") == 0 || bstrcasecmp0(r, "k") == 0) {
  ------------------
  |  Branch (522:20): [True: 69, False: 17.7k]
  |  Branch (522:51): [True: 17.1k, False: 617]
  ------------------
  523|  17.2k|            unit = 1024;
  524|  17.2k|        } else if (bstrcasecmp0(r, "mib") == 0 || bstrcasecmp0(r, "m") == 0) {
  ------------------
  |  Branch (524:20): [True: 73, False: 544]
  |  Branch (524:51): [True: 109, False: 435]
  ------------------
  525|    182|            unit = 1024 * 1024;
  526|    435|        } else if (bstrcasecmp0(r, "gib") == 0 || bstrcasecmp0(r, "g") == 0) {
  ------------------
  |  Branch (526:20): [True: 71, False: 364]
  |  Branch (526:51): [True: 95, False: 269]
  ------------------
  527|    166|            unit = 1024 * 1024 * 1024;
  528|    269|        } else if (bstrcasecmp0(r, "tib") == 0 || bstrcasecmp0(r, "t") == 0) {
  ------------------
  |  Branch (528:20): [True: 72, False: 197]
  |  Branch (528:51): [True: 165, False: 32]
  ------------------
  529|    237|            unit = 1024 * 1024 * 1024 * 1024LL;
  530|    237|        } else {
  531|     32|            mp_err(log, "The %.*s option must be an integer: %.*s\n",
  ------------------
  |  |   72|    128|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 32, False: 0]
  |  |  |  Branch (72:55): [True: 32, False: 0]
  |  |  ------------------
  ------------------
  532|     32|                   BSTR_P(name), BSTR_P(param));
  533|     32|            mp_err(log, "The following suffixes are also allowed: "
  ------------------
  |  |   72|     32|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  534|     32|                   "KiB, MiB, GiB, TiB, B, K, M, G, T.\n");
  535|     32|            return M_OPT_INVALID;
  ------------------
  |  |  523|     32|#define M_OPT_INVALID           -3
  ------------------
  536|     32|        }
  537|  17.8k|    }
  538|       |
  539|  18.1k|    if (tmp_int < 0) {
  ------------------
  |  Branch (539:9): [True: 66, False: 18.0k]
  ------------------
  540|     66|        mp_err(log, "The %.*s option does not support negative numbers: %.*s\n",
  ------------------
  |  |   72|    264|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 66, False: 0]
  |  |  |  Branch (72:55): [True: 66, False: 0]
  |  |  ------------------
  ------------------
  541|     66|               BSTR_P(name), BSTR_P(param));
  542|     66|        return M_OPT_OUT_OF_RANGE;
  ------------------
  |  |  527|     66|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
  543|     66|    }
  544|       |
  545|  18.0k|    if (INT64_MAX / unit < tmp_int) {
  ------------------
  |  Branch (545:9): [True: 1, False: 18.0k]
  ------------------
  546|      1|        mp_err(log, "The %.*s option overflows: %.*s\n",
  ------------------
  |  |   72|      4|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 1, False: 0]
  |  |  |  Branch (72:55): [True: 1, False: 0]
  |  |  ------------------
  ------------------
  547|      1|               BSTR_P(name), BSTR_P(param));
  548|      1|        return M_OPT_OUT_OF_RANGE;
  ------------------
  |  |  527|      1|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
  549|      1|    }
  550|       |
  551|  18.0k|    tmp_int *= unit;
  552|       |
  553|  18.0k|    int64_t min = OPT_INT_MIN(opt, int64_t, INT64_MIN);
  ------------------
  |  |   58|  18.0k|#define OPT_INT_MIN(opt, T, Tm) ((opt)->min < (opt)->max \
  |  |  ------------------
  |  |  |  Branch (58:34): [True: 18.0k, False: 0]
  |  |  ------------------
  |  |   59|  18.0k|    ? ((opt)->min <= (double)(Tm) ? (Tm) : (T)((opt)->min)) : (Tm))
  |  |  ------------------
  |  |  |  Branch (59:8): [True: 0, False: 18.0k]
  |  |  ------------------
  ------------------
  554|  18.0k|    if (tmp_int < min) {
  ------------------
  |  Branch (554:9): [True: 0, False: 18.0k]
  ------------------
  555|      0|        mp_err(log, "The %.*s option must be >= %"PRId64": %.*s\n",
  ------------------
  |  |   72|      0|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 0, False: 0]
  |  |  |  Branch (72:55): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  556|      0|               BSTR_P(name), min, BSTR_P(param));
  557|      0|        return M_OPT_OUT_OF_RANGE;
  ------------------
  |  |  527|      0|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
  558|      0|    }
  559|       |
  560|  18.0k|    int64_t max = OPT_INT_MAX(opt, int64_t, INT64_MAX);
  ------------------
  |  |   60|  18.0k|#define OPT_INT_MAX(opt, T, Tm) ((opt)->min < (opt)->max \
  |  |  ------------------
  |  |  |  Branch (60:34): [True: 18.0k, False: 0]
  |  |  ------------------
  |  |   61|  18.0k|    ? ((opt)->max >= (double)(Tm) ? (Tm) : (T)((opt)->max)) : (Tm))
  |  |  ------------------
  |  |  |  Branch (61:8): [True: 0, False: 18.0k]
  |  |  ------------------
  ------------------
  561|  18.0k|    if (tmp_int > max) {
  ------------------
  |  Branch (561:9): [True: 88, False: 17.9k]
  ------------------
  562|     88|        mp_err(log, "The %.*s option must be <= %"PRId64": %.*s\n",
  ------------------
  |  |   72|    352|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 88, False: 0]
  |  |  |  Branch (72:55): [True: 88, False: 0]
  |  |  ------------------
  ------------------
  563|     88|               BSTR_P(name), max, BSTR_P(param));
  564|     88|        return M_OPT_OUT_OF_RANGE;
  ------------------
  |  |  527|     88|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
  565|     88|    }
  566|       |
  567|  17.9k|    if (dst)
  ------------------
  |  Branch (567:9): [True: 17.9k, False: 0]
  ------------------
  568|  17.9k|        *(int64_t *)dst = tmp_int;
  569|       |
  570|  17.9k|    return 1;
  571|  18.0k|}
m_option.c:pretty_print_byte_size:
  592|    270|{
  593|    270|    return format_file_size(*(int64_t *)val);
  594|    270|}
m_option.c:parse_choice:
  632|   363k|{
  633|   363k|    const struct m_opt_choice_alternatives *alt = opt->priv;
  634|  1.21M|    for ( ; alt->name; alt++) {
  ------------------
  |  Branch (634:13): [True: 1.20M, False: 2.07k]
  ------------------
  635|  1.20M|        if (!bstrcmp0(param, alt->name))
  ------------------
  |  Branch (635:13): [True: 361k, False: 847k]
  ------------------
  636|   361k|            break;
  637|  1.20M|    }
  638|   363k|    if (!alt->name && param.len == 0) {
  ------------------
  |  Branch (638:9): [True: 2.07k, False: 361k]
  |  Branch (638:23): [True: 700, False: 1.37k]
  ------------------
  639|       |        // allow flag-style options, e.g. "--mute" implies "--mute=yes"
  640|  1.79k|        for (alt = opt->priv; alt->name; alt++) {
  ------------------
  |  Branch (640:31): [True: 1.78k, False: 6]
  ------------------
  641|  1.78k|            if (!strcmp("yes", alt->name))
  ------------------
  |  Branch (641:17): [True: 694, False: 1.09k]
  ------------------
  642|    694|                break;
  643|  1.78k|        }
  644|    700|    }
  645|   363k|    if (!alt->name) {
  ------------------
  |  Branch (645:9): [True: 1.38k, False: 361k]
  ------------------
  646|  1.38k|        if (!bstrcmp0(param, "help")) {
  ------------------
  |  Branch (646:13): [True: 9, False: 1.37k]
  ------------------
  647|      9|            mp_info(log, "Valid values for option %.*s are:\n", BSTR_P(name));
  ------------------
  |  |   74|     18|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (74:56): [True: 9, False: 0]
  |  |  ------------------
  ------------------
  648|      9|            print_choice_values(log, opt);
  649|      9|            return M_OPT_EXIT;
  ------------------
  |  |  533|      9|#define M_OPT_EXIT              -6
  ------------------
  650|      9|        }
  651|  1.37k|        if (param.len == 0)
  ------------------
  |  Branch (651:13): [True: 6, False: 1.36k]
  ------------------
  652|      6|            return M_OPT_MISSING_PARAM;
  ------------------
  |  |  520|      6|#define M_OPT_MISSING_PARAM     -2
  ------------------
  653|  1.36k|        if (opt->min < opt->max) {
  ------------------
  |  Branch (653:13): [True: 1.35k, False: 13]
  ------------------
  654|  1.35k|            long long val;
  655|  1.35k|            if (parse_longlong(mp_null_log, opt, INT_MIN, INT_MAX, name, param,
  ------------------
  |  Branch (655:17): [True: 1.25k, False: 105]
  ------------------
  656|  1.35k|                               &val) == 1)
  657|  1.25k|            {
  658|  1.25k|                if (dst)
  ------------------
  |  Branch (658:21): [True: 1.25k, False: 0]
  ------------------
  659|  1.25k|                    *(int *)dst = val;
  660|  1.25k|                return 1;
  661|  1.25k|            }
  662|  1.35k|        }
  663|    118|        mp_fatal(log, "Invalid value for option %.*s: %.*s\n",
  ------------------
  |  |   71|    472|#define mp_fatal(log, ...)      mp_msg(log, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (71:57): [True: 118, False: 0]
  |  |  |  Branch (71:57): [True: 118, False: 0]
  |  |  ------------------
  ------------------
  664|    118|                 BSTR_P(name), BSTR_P(param));
  665|    118|        mp_info(log, "Valid values are:\n");
  ------------------
  |  |   74|    118|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  666|    118|        print_choice_values(log, opt);
  667|    118|        return M_OPT_INVALID;
  ------------------
  |  |  523|    118|#define M_OPT_INVALID           -3
  ------------------
  668|  1.36k|    }
  669|   361k|    if (dst)
  ------------------
  |  Branch (669:9): [True: 361k, False: 0]
  ------------------
  670|   361k|        *(int *)dst = alt->value;
  671|       |
  672|   361k|    return 1;
  673|   363k|}
m_option.c:print_choice_values:
  622|    127|{
  623|    127|    const struct m_opt_choice_alternatives *alt = opt->priv;
  624|    776|    for ( ; alt->name; alt++)
  ------------------
  |  Branch (624:13): [True: 649, False: 127]
  ------------------
  625|    649|        mp_info(log, "    %s\n", alt->name[0] ? alt->name : "(passing nothing)");
  ------------------
  |  |   74|  1.29k|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (74:56): [True: 645, False: 4]
  |  |  ------------------
  ------------------
  626|    127|    if (opt->min < opt->max)
  ------------------
  |  Branch (626:9): [True: 107, False: 20]
  ------------------
  627|    107|        mp_info(log, "    %g-%g (integer range)\n", opt->min, opt->max);
  ------------------
  |  |   74|    107|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  628|    127|}
m_option.c:print_choice:
  810|  4.26k|{
  811|  4.26k|    int ival = 0;
  812|  4.26k|    const struct m_opt_choice_alternatives *alt = get_choice(opt, val, &ival);
  813|  4.26k|    return alt ? talloc_strdup(NULL, alt->name)
  ------------------
  |  |   50|  4.09k|#define talloc_strdup                   ta_xstrdup
  ------------------
  |  Branch (813:12): [True: 4.09k, False: 176]
  ------------------
  814|  4.26k|               : talloc_asprintf(NULL, "%d", ival);
  ------------------
  |  |   52|    176|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|    176|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  815|  4.26k|}
m_option.c:get_choice:
  760|  4.26k|{
  761|  4.26k|    int v = *(int *)val;
  762|  4.26k|    const struct m_opt_choice_alternatives *alt;
  763|  7.94k|    for (alt = opt->priv; alt->name; alt++) {
  ------------------
  |  Branch (763:27): [True: 7.76k, False: 176]
  ------------------
  764|  7.76k|        if (alt->value == v)
  ------------------
  |  Branch (764:13): [True: 4.09k, False: 3.67k]
  ------------------
  765|  4.09k|            return alt;
  766|  7.76k|    }
  767|    176|    if (opt->min < opt->max) {
  ------------------
  |  Branch (767:9): [True: 176, False: 0]
  ------------------
  768|    176|        if (v >= opt->min && v <= opt->max) {
  ------------------
  |  Branch (768:13): [True: 176, False: 0]
  |  Branch (768:30): [True: 176, False: 0]
  ------------------
  769|    176|            *out_val = v;
  770|    176|            return NULL;
  771|    176|        }
  772|    176|    }
  773|      0|    MP_ASSERT_UNREACHABLE();
  ------------------
  |  |   42|      0|#define MP_ASSERT_UNREACHABLE() (assert(!"unreachable"), __builtin_unreachable())
  ------------------
  774|      0|}
m_option.c:parse_flags:
  864|   109k|{
  865|   109k|    int value = 0;
  866|   218k|    while (param.len) {
  ------------------
  |  Branch (866:12): [True: 109k, False: 109k]
  ------------------
  867|   109k|        bstr flag;
  868|   109k|        bstr_split_tok(param, "+", &flag, &param);
  869|   109k|        int r = apply_flag(opt, &value, flag);
  870|   109k|        if (r == M_OPT_UNKNOWN) {
  ------------------
  |  |  517|   109k|#define M_OPT_UNKNOWN           -1
  ------------------
  |  Branch (870:13): [True: 0, False: 109k]
  ------------------
  871|      0|            mp_fatal(log, "Invalid flag for option %.*s: %.*s\n",
  ------------------
  |  |   71|      0|#define mp_fatal(log, ...)      mp_msg(log, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (71:57): [True: 0, False: 0]
  |  |  |  Branch (71:57): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  872|      0|                     BSTR_P(name), BSTR_P(flag));
  873|      0|            mp_info(log, "Valid flags are:\n");
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  874|      0|            const struct m_opt_choice_alternatives *alt;
  875|      0|            for (alt = opt->priv; alt->name; alt++)
  ------------------
  |  Branch (875:35): [True: 0, False: 0]
  ------------------
  876|      0|                mp_info(log, "    %s\n", alt->name);
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  877|      0|            mp_info(log, "Flags can usually be combined with '+'.\n");
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  878|      0|            return M_OPT_INVALID;
  ------------------
  |  |  523|      0|#define M_OPT_INVALID           -3
  ------------------
  879|   109k|        } else if (r < 0) {
  ------------------
  |  Branch (879:20): [True: 0, False: 109k]
  ------------------
  880|      0|            mp_fatal(log, "Option %.*s: flag '%.*s' conflicts with a previous "
  ------------------
  |  |   71|      0|#define mp_fatal(log, ...)      mp_msg(log, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (71:57): [True: 0, False: 0]
  |  |  |  Branch (71:57): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  881|      0|                     "flag value.\n", BSTR_P(name), BSTR_P(flag));
  882|      0|            return M_OPT_INVALID;
  ------------------
  |  |  523|      0|#define M_OPT_INVALID           -3
  ------------------
  883|      0|        }
  884|   109k|    }
  885|   109k|    if (dst)
  ------------------
  |  Branch (885:9): [True: 109k, False: 0]
  ------------------
  886|   109k|        *(int *)dst = value;
  887|   109k|    return 1;
  888|   109k|}
m_option.c:apply_flag:
  831|   109k|{
  832|   109k|    const struct m_opt_choice_alternatives *alt;
  833|   510k|    for (alt = opt->priv; alt->name; alt++) {
  ------------------
  |  Branch (833:27): [True: 510k, False: 0]
  ------------------
  834|   510k|        if (bstr_equals0(flag, alt->name)) {
  ------------------
  |  Branch (834:13): [True: 109k, False: 400k]
  ------------------
  835|   109k|            if (*val & alt->value)
  ------------------
  |  Branch (835:17): [True: 0, False: 109k]
  ------------------
  836|      0|                return M_OPT_INVALID;
  ------------------
  |  |  523|      0|#define M_OPT_INVALID           -3
  ------------------
  837|   109k|            *val |= alt->value;
  838|   109k|            return 0;
  839|   109k|        }
  840|   510k|    }
  841|      0|    return M_OPT_UNKNOWN;
  ------------------
  |  |  517|      0|#define M_OPT_UNKNOWN           -1
  ------------------
  842|   109k|}
m_option.c:parse_double:
  983|  1.18M|{
  984|  1.18M|    if (param.len == 0)
  ------------------
  |  Branch (984:9): [True: 1, False: 1.18M]
  ------------------
  985|      1|        return M_OPT_MISSING_PARAM;
  ------------------
  |  |  520|      1|#define M_OPT_MISSING_PARAM     -2
  ------------------
  986|       |
  987|  1.18M|    struct bstr rest;
  988|  1.18M|    double tmp_float = bstrtod(param, &rest);
  989|       |
  990|  1.18M|    if (bstr_eatstart0(&rest, ":") || bstr_eatstart0(&rest, "/"))
  ------------------
  |  Branch (990:9): [True: 68, False: 1.18M]
  |  Branch (990:39): [True: 12.3k, False: 1.17M]
  ------------------
  991|  12.4k|        tmp_float /= bstrtod(rest, &rest);
  992|       |
  993|  1.18M|    if ((opt->flags & M_OPT_DEFAULT_NAN) && bstr_equals0(param, "default")) {
  ------------------
  |  |  471|  1.18M|#define M_OPT_DEFAULT_NAN       (UINT64_C(1) << 58)
  ------------------
  |  Branch (993:9): [True: 244, False: 1.18M]
  |  Branch (993:45): [True: 1, False: 243]
  ------------------
  994|      1|        tmp_float = NAN;
  995|      1|        goto done;
  996|      1|    }
  997|       |
  998|  1.18M|    if (rest.len) {
  ------------------
  |  Branch (998:9): [True: 40, False: 1.18M]
  ------------------
  999|     40|        mp_err(log, "The %.*s option must be a floating point number or a "
  ------------------
  |  |   72|    160|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 40, False: 0]
  |  |  |  Branch (72:55): [True: 40, False: 0]
  |  |  ------------------
  ------------------
 1000|     40|               "ratio (numerator[:/]denominator): %.*s\n",
 1001|     40|               BSTR_P(name), BSTR_P(param));
 1002|     40|        return M_OPT_INVALID;
  ------------------
  |  |  523|     40|#define M_OPT_INVALID           -3
  ------------------
 1003|     40|    }
 1004|       |
 1005|  1.18M|    if (clamp_double(opt, &tmp_float) < 0) {
  ------------------
  |  Branch (1005:9): [True: 11, False: 1.18M]
  ------------------
 1006|     11|        mp_err(log, "The %.*s option is out of range: %.*s\n",
  ------------------
  |  |   72|     44|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 11, False: 0]
  |  |  |  Branch (72:55): [True: 11, False: 0]
  |  |  ------------------
  ------------------
 1007|     11|               BSTR_P(name), BSTR_P(param));
 1008|     11|        return M_OPT_OUT_OF_RANGE;
  ------------------
  |  |  527|     11|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
 1009|     11|    }
 1010|       |
 1011|  1.18M|done:
 1012|  1.18M|    if (dst)
  ------------------
  |  Branch (1012:9): [True: 1.18M, False: 0]
  ------------------
 1013|  1.18M|        VAL(dst) = tmp_float;
  ------------------
  |  |  956|  1.18M|#define VAL(x) (*(double *)(x))
  ------------------
 1014|  1.18M|    return 1;
 1015|  1.18M|}
m_option.c:clamp_double:
  959|  1.35M|{
  960|  1.35M|    double v = VAL(val);
  ------------------
  |  |  956|  1.35M|#define VAL(x) (*(double *)(x))
  ------------------
  961|  1.35M|    int r = 0;
  962|  1.35M|    if (opt->min < opt->max) {
  ------------------
  |  Branch (962:9): [True: 120k, False: 1.23M]
  ------------------
  963|   120k|        if (v > opt->max) {
  ------------------
  |  Branch (963:13): [True: 4, False: 120k]
  ------------------
  964|      4|            v = opt->max;
  965|      4|            r = M_OPT_OUT_OF_RANGE;
  ------------------
  |  |  527|      4|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
  966|      4|        }
  967|   120k|        if (v < opt->min) {
  ------------------
  |  Branch (967:13): [True: 1, False: 120k]
  ------------------
  968|      1|            v = opt->min;
  969|      1|            r = M_OPT_OUT_OF_RANGE;
  ------------------
  |  |  527|      1|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
  970|      1|        }
  971|   120k|    }
  972|       |    // (setting max/min to INFINITY/-INFINITY is allowed)
  973|  1.35M|    if (!isfinite(v) && v != opt->max && v != opt->min) {
  ------------------
  |  Branch (973:9): [True: 7, False: 1.35M]
  |  Branch (973:25): [True: 7, False: 0]
  |  Branch (973:42): [True: 7, False: 0]
  ------------------
  974|      7|        v = opt->min;
  975|      7|        r = M_OPT_OUT_OF_RANGE;
  ------------------
  |  |  527|      7|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
  976|      7|    }
  977|  1.35M|    VAL(val) = v;
  ------------------
  |  |  956|  1.35M|#define VAL(x) (*(double *)(x))
  ------------------
  978|  1.35M|    return r;
  979|  1.35M|}
m_option.c:print_double:
 1018|    664|{
 1019|    664|    double f = VAL(val);
  ------------------
  |  |  956|    664|#define VAL(x) (*(double *)(x))
  ------------------
 1020|    664|    if (isnan(f) && (opt->flags & M_OPT_DEFAULT_NAN))
  ------------------
  |  |  471|    588|#define M_OPT_DEFAULT_NAN       (UINT64_C(1) << 58)
  ------------------
  |  Branch (1020:21): [True: 588, False: 0]
  ------------------
 1021|    588|        return talloc_strdup(NULL, "default");
  ------------------
  |  |   50|    588|#define talloc_strdup                   ta_xstrdup
  ------------------
 1022|     76|    return talloc_asprintf(NULL, "%f", f);
  ------------------
  |  |   52|     76|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|     76|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 1023|    664|}
m_option.c:pretty_print_double:
 1026|  5.81k|{
 1027|  5.81k|    double f = VAL(val);
  ------------------
  |  |  956|  5.81k|#define VAL(x) (*(double *)(x))
  ------------------
 1028|  5.81k|    if (isnan(f))
 1029|    570|        return print_double(opt, val);
 1030|  5.24k|    return mp_format_double(NULL, f, 4, false, false, !(opt->flags & M_OPT_FIXED_LEN_PRINT));
  ------------------
  |  |  482|  5.24k|#define M_OPT_FIXED_LEN_PRINT   (UINT64_C(1) << 55)
  ------------------
 1031|  5.81k|}
m_option.c:double_equal:
 1088|  46.4k|{
 1089|  46.4k|    double fa = VAL(a), fb = VAL(b);
  ------------------
  |  |  956|  46.4k|#define VAL(x) (*(double *)(x))
  ------------------
                  double fa = VAL(a), fb = VAL(b);
  ------------------
  |  |  956|  46.4k|#define VAL(x) (*(double *)(x))
  ------------------
 1090|  46.4k|    if (isnan(fa) || isnan(fb))
 1091|     40|        return isnan(fa) == isnan(fb);
 1092|  46.3k|    return fa == fb;
 1093|  46.4k|}
m_option.c:parse_double_aspect:
 1113|    131|{
 1114|    131|    if (bstr_equals0(param, "no")) {
  ------------------
  |  Branch (1114:9): [True: 73, False: 58]
  ------------------
 1115|     73|        if (dst)
  ------------------
  |  Branch (1115:13): [True: 73, False: 0]
  ------------------
 1116|     73|            VAL(dst) = -2.0;
  ------------------
  |  |  956|     73|#define VAL(x) (*(double *)(x))
  ------------------
 1117|     73|        return 1;
 1118|     73|    }
 1119|     58|    return parse_double(log, opt, name, param, dst);
 1120|    131|}
m_option.c:parse_float:
 1160|   164k|{
 1161|   164k|    double tmp;
 1162|   164k|    int r = parse_double(log, opt, name, param, &tmp);
 1163|       |
 1164|   164k|    if (r == 1 && clamp_float(opt, &tmp) < 0) {
  ------------------
  |  Branch (1164:9): [True: 164k, False: 14]
  |  Branch (1164:19): [True: 3, False: 164k]
  ------------------
 1165|      3|        mp_err(log, "The %.*s option is out of range: %.*s\n",
  ------------------
  |  |   72|     12|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 3, False: 0]
  |  |  |  Branch (72:55): [True: 3, False: 0]
  |  |  ------------------
  ------------------
 1166|      3|               BSTR_P(name), BSTR_P(param));
 1167|      3|        return M_OPT_OUT_OF_RANGE;
  ------------------
  |  |  527|      3|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
 1168|      3|    }
 1169|       |
 1170|   164k|    if (r == 1 && dst)
  ------------------
  |  Branch (1170:9): [True: 164k, False: 14]
  |  Branch (1170:19): [True: 164k, False: 0]
  ------------------
 1171|   164k|        VAL(dst) = tmp;
  ------------------
  |  | 1138|   164k|#define VAL(x) (*(float *)(x))
  ------------------
 1172|   164k|    return r;
 1173|   164k|}
m_option.c:clamp_float:
 1141|   164k|{
 1142|   164k|    double v = *val;
 1143|   164k|    int r = clamp_double(opt, &v);
 1144|       |    // Handle the case where range is not set and v is finite
 1145|       |    // but overflows the float range.
 1146|   164k|    if (isfinite(v) && v > FLT_MAX) {
  ------------------
  |  Branch (1146:24): [True: 1, False: 164k]
  ------------------
 1147|      1|        v = FLT_MAX;
 1148|      1|        r = M_OPT_OUT_OF_RANGE;
  ------------------
  |  |  527|      1|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
 1149|      1|    }
 1150|   164k|    if (isfinite(v) && v < -FLT_MAX) {
  ------------------
  |  Branch (1150:24): [True: 1, False: 164k]
  ------------------
 1151|      1|        v = -FLT_MAX;
 1152|      1|        r = M_OPT_OUT_OF_RANGE;
  ------------------
  |  |  527|      1|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
 1153|      1|    }
 1154|   164k|    *val = v;
 1155|   164k|    return r;
 1156|   164k|}
m_option.c:print_float:
 1176|     52|{
 1177|     52|    double tmp = VAL(val);
  ------------------
  |  | 1138|     52|#define VAL(x) (*(float *)(x))
  ------------------
 1178|     52|    return print_double(opt, &tmp);
 1179|     52|}
m_option.c:pretty_print_float:
 1182|  4.47k|{
 1183|  4.47k|    double tmp = VAL(val);
  ------------------
  |  | 1138|  4.47k|#define VAL(x) (*(float *)(x))
  ------------------
 1184|  4.47k|    return pretty_print_double(opt, &tmp);
 1185|  4.47k|}
m_option.c:float_equal:
 1222|  45.6k|{
 1223|  45.6k|    return double_equal(opt, &(double){VAL(a)}, &(double){VAL(b)});
  ------------------
  |  | 1138|  45.6k|#define VAL(x) (*(float *)(x))
  ------------------
                  return double_equal(opt, &(double){VAL(a)}, &(double){VAL(b)});
  ------------------
  |  | 1138|  45.6k|#define VAL(x) (*(float *)(x))
  ------------------
 1224|  45.6k|}
m_option.c:parse_str:
 1249|  2.44M|{
 1250|  2.44M|    if (dst) {
  ------------------
  |  Branch (1250:9): [True: 2.44M, False: 0]
  ------------------
 1251|  2.44M|        talloc_free(VAL(dst));
  ------------------
  |  |   47|  2.44M|#define talloc_free                     ta_free
  ------------------
                      talloc_free(VAL(dst));
  ------------------
  |  | 1245|  2.44M|#define VAL(x) (*(char **)(x))
  ------------------
 1252|  2.44M|        VAL(dst) = bstrdup0(NULL, param);
  ------------------
  |  | 1245|  2.44M|#define VAL(x) (*(char **)(x))
  ------------------
 1253|  2.44M|    }
 1254|       |
 1255|  2.44M|    return 0;
 1256|  2.44M|}
m_option.c:print_str:
 1259|   115k|{
 1260|   115k|    return talloc_strdup(NULL, VAL(val) ? VAL(val) : "");
  ------------------
  |  |   50|   115k|#define talloc_strdup                   ta_xstrdup
  ------------------
                  return talloc_strdup(NULL, VAL(val) ? VAL(val) : "");
  ------------------
  |  | 1245|   115k|#define VAL(x) (*(char **)(x))
  |  |  ------------------
  |  |  |  Branch (1245:16): [True: 113k, False: 1.93k]
  |  |  ------------------
  ------------------
                  return talloc_strdup(NULL, VAL(val) ? VAL(val) : "");
  ------------------
  |  | 1245|   113k|#define VAL(x) (*(char **)(x))
  ------------------
 1261|   115k|}
m_option.c:copy_str:
 1264|  5.11M|{
 1265|  5.11M|    if (dst && src)
  ------------------
  |  Branch (1265:9): [True: 5.11M, False: 0]
  |  Branch (1265:16): [True: 5.11M, False: 0]
  ------------------
 1266|  5.11M|        talloc_replace(NULL, VAL(dst), VAL(src));
  ------------------
  |  |   54|  5.11M|#define talloc_replace                  ta_replace
  |  |  ------------------
  |  |  |  |  106|  5.11M|    do {                                                \
  |  |  |  |  107|  5.11M|        if (!(str)) {                                   \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (107:13): [True: 5.10M, False: 10.9k]
  |  |  |  |  ------------------
  |  |  |  |  108|  5.10M|            (str) = ta_xstrdup((ta_parent), (replace)); \
  |  |  |  |  109|  5.10M|        } else {                                        \
  |  |  |  |  110|  10.9k|            *(str) = '\0';                              \
  |  |  |  |  111|  10.9k|            ta_xstrdup_append(&(str), (replace));       \
  |  |  |  |  ------------------
  |  |  |  |  |  |  123|  10.9k|#define ta_xstrdup_append(...)          ta_oom_b(ta_strdup_append(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  112|  10.9k|        }                                               \
  |  |  |  |  113|  5.11M|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (113:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1267|  5.11M|}
m_option.c:free_str:
 1294|  7.49M|{
 1295|  7.49M|    if (src && VAL(src)) {
  ------------------
  |  | 1245|  7.49M|#define VAL(x) (*(char **)(x))
  |  |  ------------------
  |  |  |  Branch (1245:16): [True: 3.96M, False: 3.52M]
  |  |  ------------------
  ------------------
  |  Branch (1295:9): [True: 7.49M, False: 0]
  ------------------
 1296|  3.96M|        talloc_free(VAL(src));
  ------------------
  |  |   47|  3.96M|#define talloc_free                     ta_free
  ------------------
                      talloc_free(VAL(src));
  ------------------
  |  | 1245|  3.96M|#define VAL(x) (*(char **)(x))
  ------------------
 1297|  3.96M|        VAL(src) = NULL;
  ------------------
  |  | 1245|  3.96M|#define VAL(x) (*(char **)(x))
  ------------------
 1298|  3.96M|    }
 1299|  7.49M|}
m_option.c:str_get:
 1282|  1.53M|{
 1283|  1.53M|    dst->format = MPV_FORMAT_STRING;
 1284|  1.53M|    dst->u.string = talloc_strdup(ta_parent, VAL(src) ? VAL(src) : "");
  ------------------
  |  |   50|  1.53M|#define talloc_strdup                   ta_xstrdup
  ------------------
                  dst->u.string = talloc_strdup(ta_parent, VAL(src) ? VAL(src) : "");
  ------------------
  |  | 1245|  1.53M|#define VAL(x) (*(char **)(x))
  |  |  ------------------
  |  |  |  Branch (1245:16): [True: 1.53M, False: 0]
  |  |  ------------------
  ------------------
                  dst->u.string = talloc_strdup(ta_parent, VAL(src) ? VAL(src) : "");
  ------------------
  |  | 1245|  1.53M|#define VAL(x) (*(char **)(x))
  ------------------
 1285|  1.53M|    return 1;
 1286|  1.53M|}
m_option.c:str_equal:
 1289|   146k|{
 1290|   146k|    return bstr_equals(bstr0(VAL(a)), bstr0(VAL(b)));
  ------------------
  |  | 1245|   146k|#define VAL(x) (*(char **)(x))
  ------------------
                  return bstr_equals(bstr0(VAL(a)), bstr0(VAL(b)));
  ------------------
  |  | 1245|   146k|#define VAL(x) (*(char **)(x))
  ------------------
 1291|   146k|}
m_option.c:parse_str_list:
 1626|  90.1k|{
 1627|  90.1k|    return parse_str_list_impl(log, opt, name, param, dst, OP_NONE);
  ------------------
  |  | 1318|  90.1k|#define OP_NONE 0
  ------------------
 1628|  90.1k|}
m_option.c:parse_str_list_impl:
 1471|  90.1k|{
 1472|  90.1k|    char **res;
 1473|  90.1k|    int op = default_op;
 1474|       |
 1475|  90.1k|    if (bstr_endswith0(name, "-add")) {
  ------------------
  |  Branch (1475:9): [True: 213, False: 89.9k]
  ------------------
 1476|    213|        op = OP_ADD;
  ------------------
  |  | 1319|    213|#define OP_ADD 1
  ------------------
 1477|  89.9k|    } else if (bstr_endswith0(name, "-append")) {
  ------------------
  |  Branch (1477:16): [True: 13.0k, False: 76.9k]
  ------------------
 1478|  13.0k|        op = OP_APPEND;
  ------------------
  |  | 1324|  13.0k|#define OP_APPEND 6
  ------------------
 1479|  76.9k|    } else if (bstr_endswith0(name, "-pre")) {
  ------------------
  |  Branch (1479:16): [True: 67, False: 76.8k]
  ------------------
 1480|     67|        op = OP_PRE;
  ------------------
  |  | 1320|     67|#define OP_PRE 2
  ------------------
 1481|  76.8k|    } else if (bstr_endswith0(name, "-clr")) {
  ------------------
  |  Branch (1481:16): [True: 362, False: 76.5k]
  ------------------
 1482|    362|        op = OP_CLR;
  ------------------
  |  | 1321|    362|#define OP_CLR 3
  ------------------
 1483|  76.5k|    } else if (bstr_endswith0(name, "-del")) {
  ------------------
  |  Branch (1483:16): [True: 96, False: 76.4k]
  ------------------
 1484|     96|        op = OP_DEL;
  ------------------
  |  | 1322|     96|#define OP_DEL 4
  ------------------
 1485|  76.4k|    } else if (bstr_endswith0(name, "-set")) {
  ------------------
  |  Branch (1485:16): [True: 68, False: 76.3k]
  ------------------
 1486|     68|        op = OP_NONE;
  ------------------
  |  | 1318|     68|#define OP_NONE 0
  ------------------
 1487|  76.3k|    } else if (bstr_endswith0(name, "-toggle")) {
  ------------------
  |  Branch (1487:16): [True: 217, False: 76.1k]
  ------------------
 1488|    217|        op = OP_TOGGLE;
  ------------------
  |  | 1323|    217|#define OP_TOGGLE 5
  ------------------
 1489|  76.1k|    } else if (bstr_endswith0(name, "-remove")) {
  ------------------
  |  Branch (1489:16): [True: 394, False: 75.7k]
  ------------------
 1490|    394|        op = OP_REMOVE;
  ------------------
  |  | 1325|    394|#define OP_REMOVE 7
  ------------------
 1491|    394|    }
 1492|       |
 1493|  90.1k|    if (op == OP_TOGGLE || op == OP_REMOVE) {
  ------------------
  |  | 1323|   180k|#define OP_TOGGLE 5
  ------------------
                  if (op == OP_TOGGLE || op == OP_REMOVE) {
  ------------------
  |  | 1325|  89.9k|#define OP_REMOVE 7
  ------------------
  |  Branch (1493:9): [True: 217, False: 89.9k]
  |  Branch (1493:28): [True: 394, False: 89.5k]
  ------------------
 1494|    611|        if (dst) {
  ------------------
  |  Branch (1494:13): [True: 611, False: 0]
  ------------------
 1495|    611|            res = talloc_array(NULL, char *, 2);
  ------------------
  |  |   29|    611|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|    611|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    611|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1496|    611|            res[0] = bstrdup0(res, param);
 1497|    611|            res[1] = NULL;
 1498|    611|            bool found = str_list_remove(res, 2, dst);
 1499|    611|            if (found)
  ------------------
  |  Branch (1499:17): [True: 272, False: 339]
  ------------------
 1500|    272|                return 1;
 1501|    611|        }
 1502|    339|        if (op == OP_REMOVE)
  ------------------
  |  | 1325|    339|#define OP_REMOVE 7
  ------------------
  |  Branch (1502:13): [True: 216, False: 123]
  ------------------
 1503|    216|            return 1; // ignore if not found
 1504|    123|        op = OP_APPEND;
  ------------------
  |  | 1324|    123|#define OP_APPEND 6
  ------------------
 1505|    123|    }
 1506|       |
 1507|       |    // Clear the list ??
 1508|  89.7k|    if (op == OP_CLR) {
  ------------------
  |  | 1321|  89.7k|#define OP_CLR 3
  ------------------
  |  Branch (1508:9): [True: 362, False: 89.3k]
  ------------------
 1509|    362|        if (dst)
  ------------------
  |  Branch (1509:13): [True: 362, False: 0]
  ------------------
 1510|    362|            free_str_list(dst);
 1511|    362|        return 0;
 1512|    362|    }
 1513|       |
 1514|       |    // All other ops need a param
 1515|  89.3k|    if (param.len == 0 && op != OP_NONE)
  ------------------
  |  | 1318|    571|#define OP_NONE 0
  ------------------
  |  Branch (1515:9): [True: 571, False: 88.7k]
  |  Branch (1515:27): [True: 1, False: 570]
  ------------------
 1516|      1|        return M_OPT_MISSING_PARAM;
  ------------------
  |  |  520|      1|#define M_OPT_MISSING_PARAM     -2
  ------------------
 1517|       |
 1518|  89.3k|    if (!dst)
  ------------------
  |  Branch (1518:9): [True: 0, False: 89.3k]
  ------------------
 1519|      0|        return 1;
 1520|       |
 1521|  89.3k|    int n = 0;
 1522|  89.3k|    res = separate_input_param(opt, param, &n, op);
 1523|  89.3k|    if (!res)
  ------------------
  |  Branch (1523:9): [True: 0, False: 89.3k]
  ------------------
 1524|      0|        return M_OPT_INVALID;
  ------------------
  |  |  523|      0|#define M_OPT_INVALID           -3
  ------------------
 1525|       |
 1526|  89.3k|    switch (op) {
  ------------------
  |  Branch (1526:13): [True: 75.8k, False: 13.5k]
  ------------------
 1527|    213|    case OP_ADD:
  ------------------
  |  | 1319|    213|#define OP_ADD 1
  ------------------
  |  Branch (1527:5): [True: 213, False: 89.1k]
  ------------------
 1528|  13.3k|    case OP_APPEND:
  ------------------
  |  | 1324|  13.3k|#define OP_APPEND 6
  ------------------
  |  Branch (1528:5): [True: 13.1k, False: 76.1k]
  ------------------
 1529|  13.3k|        return str_list_add(res, n, dst, 0);
 1530|     67|    case OP_PRE:
  ------------------
  |  | 1320|     67|#define OP_PRE 2
  ------------------
  |  Branch (1530:5): [True: 67, False: 89.2k]
  ------------------
 1531|     67|        return str_list_add(res, n, dst, 1);
 1532|     96|    case OP_DEL:
  ------------------
  |  | 1322|     96|#define OP_DEL 4
  ------------------
  |  Branch (1532:5): [True: 96, False: 89.2k]
  ------------------
 1533|     96|        return str_list_remove(res, n, dst);
 1534|  89.3k|    }
 1535|       |
 1536|  75.8k|    if (VAL(dst))
  ------------------
  |  | 1316|  75.8k|#define VAL(x) (*(char ***)(x))
  |  |  ------------------
  |  |  |  Branch (1316:16): [True: 859, False: 74.9k]
  |  |  ------------------
  ------------------
 1537|    859|        free_str_list(dst);
 1538|  75.8k|    VAL(dst) = res;
  ------------------
  |  | 1316|  75.8k|#define VAL(x) (*(char ***)(x))
  ------------------
 1539|       |
 1540|  75.8k|    if (!res[0])
  ------------------
  |  Branch (1540:9): [True: 0, False: 75.8k]
  ------------------
 1541|      0|        free_str_list(dst);
 1542|       |
 1543|  75.8k|    return 1;
 1544|  89.3k|}
m_option.c:str_list_remove:
 1447|    707|{
 1448|    707|    bool found = false;
 1449|    707|    char **list = VAL(dst);
  ------------------
  |  | 1316|    707|#define VAL(x) (*(char ***)(x))
  ------------------
 1450|  2.35k|    for (int i = 0; i < n; i++) {
  ------------------
  |  Branch (1450:21): [True: 1.64k, False: 707]
  ------------------
 1451|  1.64k|        int index = 0;
 1452|  2.70k|        do {
 1453|  2.70k|            index = find_list_bstr(list, bstr0(remove[i]));
 1454|  2.70k|            if (index >= 0) {
  ------------------
  |  Branch (1454:17): [True: 1.06k, False: 1.64k]
  ------------------
 1455|  1.06k|                found = true;
 1456|  1.06k|                char *old = list[index];
 1457|  21.8k|                for (int j = index; list[j]; j++)
  ------------------
  |  Branch (1457:37): [True: 20.7k, False: 1.06k]
  ------------------
 1458|  20.7k|                    list[j] = list[j + 1];
 1459|  1.06k|                talloc_free(old);
  ------------------
  |  |   47|  1.06k|#define talloc_free                     ta_free
  ------------------
 1460|  1.06k|            }
 1461|  2.70k|        } while (index >= 0);
  ------------------
  |  Branch (1461:18): [True: 1.06k, False: 1.64k]
  ------------------
 1462|  1.64k|        talloc_free(remove[i]);
  ------------------
  |  |   47|  1.64k|#define talloc_free                     ta_free
  ------------------
 1463|  1.64k|    }
 1464|    707|    talloc_free(remove);
  ------------------
  |  |   47|    707|#define talloc_free                     ta_free
  ------------------
 1465|    707|    return found;
 1466|    707|}
m_option.c:find_list_bstr:
 1399|  2.70k|{
 1400|  9.79k|    for (int n = 0; list && list[n]; n++) {
  ------------------
  |  Branch (1400:21): [True: 9.07k, False: 719]
  |  Branch (1400:29): [True: 8.15k, False: 924]
  ------------------
 1401|  8.15k|        if (bstr_equals0(item, list[n]))
  ------------------
  |  Branch (1401:13): [True: 1.06k, False: 7.09k]
  ------------------
 1402|  1.06k|            return n;
 1403|  8.15k|    }
 1404|  1.64k|    return -1;
 1405|  2.70k|}
m_option.c:separate_input_param:
 1409|  89.6k|{
 1410|  89.6k|    char separator = opt->priv ? *(char *)opt->priv : OPTION_LIST_SEPARATOR;
  ------------------
  |  |  632|   165k|#define OPTION_LIST_SEPARATOR ','
  ------------------
  |  Branch (1410:22): [True: 13.4k, False: 76.2k]
  ------------------
 1411|  89.6k|    if (op == OP_APPEND || op == OP_REMOVE)
  ------------------
  |  | 1324|   179k|#define OP_APPEND 6
  ------------------
                  if (op == OP_APPEND || op == OP_REMOVE)
  ------------------
  |  | 1325|  76.5k|#define OP_REMOVE 7
  ------------------
  |  Branch (1411:9): [True: 13.1k, False: 76.5k]
  |  Branch (1411:28): [True: 183, False: 76.3k]
  ------------------
 1412|  13.3k|        separator = 0; // specially handled
 1413|  89.6k|    struct bstr str = param;
 1414|  89.6k|    int n = *len;
 1415|   202k|    while (str.len) {
  ------------------
  |  Branch (1415:12): [True: 112k, False: 89.6k]
  ------------------
 1416|   112k|        get_nextsep(&str, separator, 0);
 1417|   112k|        str = bstr_cut(str, 1);
 1418|   112k|        n++;
 1419|   112k|    }
 1420|  89.6k|    if (n == 0 && op != OP_NONE)
  ------------------
  |  | 1318|    574|#define OP_NONE 0
  ------------------
  |  Branch (1420:9): [True: 574, False: 89.1k]
  |  Branch (1420:19): [True: 4, False: 570]
  ------------------
 1421|      4|        return NULL;
 1422|       |
 1423|  89.6k|    char **list = talloc_array(NULL, char *, n + 2);
  ------------------
  |  |   29|  89.6k|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|  89.6k|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  89.6k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1424|  89.6k|    str = bstrdup(NULL, param);
 1425|  89.6k|    char *ptr = str.start;
 1426|  89.6k|    n = 0;
 1427|       |
 1428|   112k|    while (1) {
  ------------------
  |  Branch (1428:12): [Folded - Ignored]
  ------------------
 1429|   112k|#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 1430|   112k|        if (n >= 100)
  ------------------
  |  Branch (1430:13): [True: 42, False: 112k]
  ------------------
 1431|     42|            break;
 1432|   112k|#endif
 1433|   112k|        struct bstr el = get_nextsep(&str, separator, 1);
 1434|   112k|        list[n] = bstrdup0(NULL, el);
 1435|   112k|        n++;
 1436|   112k|        if (!str.len)
  ------------------
  |  Branch (1436:13): [True: 89.6k, False: 23.0k]
  ------------------
 1437|  89.6k|            break;
 1438|  23.0k|        str = bstr_cut(str, 1);
 1439|  23.0k|    }
 1440|  89.6k|    list[n] = NULL;
 1441|  89.6k|    *len = n;
 1442|  89.6k|    talloc_free(ptr);
  ------------------
  |  |   47|  89.6k|#define talloc_free                     ta_free
  ------------------
 1443|  89.6k|    return list;
 1444|  89.6k|}
m_option.c:get_nextsep:
 1377|   225k|{
 1378|   225k|    struct bstr str = *ptr;
 1379|   225k|    struct bstr orig = str;
 1380|   226k|    for (;;) {
 1381|   226k|        int idx = sep ? bstrchr(str, sep) : -1;
  ------------------
  |  Branch (1381:19): [True: 199k, False: 26.6k]
  ------------------
 1382|   226k|        if (idx > 0 && str.start[idx - 1] == '\\') {
  ------------------
  |  Branch (1382:13): [True: 29.1k, False: 197k]
  |  Branch (1382:24): [True: 1.23k, False: 27.9k]
  ------------------
 1383|  1.23k|            if (modify) {
  ------------------
  |  Branch (1383:17): [True: 618, False: 618]
  ------------------
 1384|    618|                memmove(str.start + idx - 1, str.start + idx, str.len - idx);
 1385|    618|                str.len--;
 1386|    618|                str = bstr_cut(str, idx);
 1387|    618|            } else
 1388|    618|                str = bstr_cut(str, idx + 1);
 1389|   225k|        } else {
 1390|   225k|            str = bstr_cut(str, idx < 0 ? str.len : idx);
  ------------------
  |  Branch (1390:33): [True: 178k, False: 47.0k]
  ------------------
 1391|   225k|            break;
 1392|   225k|        }
 1393|   226k|    }
 1394|   225k|    *ptr = str;
 1395|   225k|    return bstr_splice(orig, 0, str.start - orig.start);
 1396|   225k|}
m_option.c:str_list_add:
 1343|  13.4k|{
 1344|  13.4k|    char **lst = VAL(dst);
  ------------------
  |  | 1316|  13.4k|#define VAL(x) (*(char ***)(x))
  ------------------
 1345|       |
 1346|  13.4k|    int ln;
 1347|   107k|    for (ln = 0; lst && lst[ln]; ln++)
  ------------------
  |  Branch (1347:18): [True: 104k, False: 3.50k]
  |  Branch (1347:25): [True: 94.1k, False: 9.91k]
  ------------------
 1348|  94.1k|        /**/;
 1349|       |
 1350|  13.4k|#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 1351|  13.4k|    if (ln >= 100) {
  ------------------
  |  Branch (1351:9): [True: 121, False: 13.3k]
  ------------------
 1352|    716|        while (n--)
  ------------------
  |  Branch (1352:16): [True: 595, False: 121]
  ------------------
 1353|    595|            talloc_free(add[n]);
  ------------------
  |  |   47|    595|#define talloc_free                     ta_free
  ------------------
 1354|    121|        talloc_free(add);
  ------------------
  |  |   47|    121|#define talloc_free                     ta_free
  ------------------
 1355|    121|        return 0;
 1356|    121|    }
 1357|  13.3k|#endif
 1358|       |
 1359|  13.3k|    lst = talloc_realloc(NULL, lst, char *, n + ln + 1);
  ------------------
  |  |   33|  13.3k|#define talloc_realloc                  ta_xrealloc
  |  |  ------------------
  |  |  |  |  144|  13.3k|    (type *)ta_xrealloc_size(ta_parent, ptr, ta_calc_array_size(sizeof(type), count))
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|  13.3k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|  13.3k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|  13.3k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|  13.3k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1360|       |
 1361|  13.3k|    if (pre) {
  ------------------
  |  Branch (1361:9): [True: 67, False: 13.2k]
  ------------------
 1362|     67|        memmove(&lst[n], lst, ln * sizeof(char *));
 1363|     67|        memcpy(lst, add, n * sizeof(char *));
 1364|     67|    } else
 1365|  13.2k|        memcpy(&lst[ln], add, n * sizeof(char *));
 1366|       |    // (re-)add NULL-termination
 1367|  13.3k|    lst[ln + n] = NULL;
 1368|       |
 1369|  13.3k|    talloc_free(add);
  ------------------
  |  |   47|  13.3k|#define talloc_free                     ta_free
  ------------------
 1370|       |
 1371|  13.3k|    VAL(dst) = lst;
  ------------------
  |  | 1316|  13.3k|#define VAL(x) (*(char ***)(x))
  ------------------
 1372|       |
 1373|  13.3k|    return 1;
 1374|  13.4k|}
m_option.c:print_str_list:
 1573|  6.32k|{
 1574|  6.32k|    char **lst = NULL;
 1575|  6.32k|    char *ret = talloc_strdup(NULL, "");
  ------------------
  |  |   50|  6.32k|#define talloc_strdup                   ta_xstrdup
  ------------------
 1576|  6.32k|    const char sep = opt->priv ? *(char *)opt->priv : OPTION_LIST_SEPARATOR;
  ------------------
  |  |  632|  12.4k|#define OPTION_LIST_SEPARATOR ','
  ------------------
  |  Branch (1576:22): [True: 252, False: 6.07k]
  ------------------
 1577|       |
 1578|  6.32k|    if (!(src && VAL(src)))
  ------------------
  |  | 1316|  6.32k|#define VAL(x) (*(char ***)(x))
  |  |  ------------------
  |  |  |  Branch (1316:16): [True: 5.80k, False: 521]
  |  |  ------------------
  ------------------
  |  Branch (1578:11): [True: 6.32k, False: 0]
  ------------------
 1579|    521|        return ret;
 1580|  5.80k|    lst = VAL(src);
  ------------------
  |  | 1316|  5.80k|#define VAL(x) (*(char ***)(x))
  ------------------
 1581|       |
 1582|  3.97M|    for (int i = 0; lst[i]; i++) {
  ------------------
  |  Branch (1582:21): [True: 3.96M, False: 5.80k]
  ------------------
 1583|  3.96M|        if (i > 0)
  ------------------
  |  Branch (1583:13): [True: 3.96M, False: 5.80k]
  ------------------
 1584|  3.96M|            ret = talloc_strndup_append_buffer(ret, &sep, 1);
  ------------------
  |  |   60|  3.96M|#define talloc_strndup_append_buffer    ta_talloc_strndup_append_buffer
  ------------------
 1585|  3.96M|        ret = talloc_strdup_append_buffer(ret, lst[i]);
  ------------------
  |  |   58|  3.96M|#define talloc_strdup_append_buffer     ta_talloc_strdup_append_buffer
  ------------------
 1586|  3.96M|    }
 1587|  5.80k|    return ret;
 1588|  6.32k|}
m_option.c:copy_str_list:
 1547|  3.36M|{
 1548|  3.36M|    int n;
 1549|  3.36M|    char **d, **s;
 1550|       |
 1551|  3.36M|    if (!(dst && src))
  ------------------
  |  Branch (1551:11): [True: 3.36M, False: 0]
  |  Branch (1551:18): [True: 3.36M, False: 0]
  ------------------
 1552|      0|        return;
 1553|  3.36M|    s = VAL(src);
  ------------------
  |  | 1316|  3.36M|#define VAL(x) (*(char ***)(x))
  ------------------
 1554|       |
 1555|  3.36M|    if (VAL(dst))
  ------------------
  |  | 1316|  3.36M|#define VAL(x) (*(char ***)(x))
  |  |  ------------------
  |  |  |  Branch (1316:16): [True: 91.2k, False: 3.27M]
  |  |  ------------------
  ------------------
 1556|  91.2k|        free_str_list(dst);
 1557|       |
 1558|  3.36M|    if (!s) {
  ------------------
  |  Branch (1558:9): [True: 2.43M, False: 931k]
  ------------------
 1559|  2.43M|        VAL(dst) = NULL;
  ------------------
  |  | 1316|  2.43M|#define VAL(x) (*(char ***)(x))
  ------------------
 1560|  2.43M|        return;
 1561|  2.43M|    }
 1562|       |
 1563|  12.1M|    for (n = 0; s[n] != NULL; n++)
  ------------------
  |  Branch (1563:17): [True: 11.1M, False: 931k]
  ------------------
 1564|  11.1M|        /* NOTHING */;
 1565|   931k|    d = talloc_array(NULL, char *, n + 1);
  ------------------
  |  |   29|   931k|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|   931k|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|   931k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1566|  13.0M|    for (; n >= 0; n--)
  ------------------
  |  Branch (1566:12): [True: 12.1M, False: 931k]
  ------------------
 1567|  12.1M|        d[n] = talloc_strdup(NULL, s[n]);
  ------------------
  |  |   50|  12.1M|#define talloc_strdup                   ta_xstrdup
  ------------------
 1568|       |
 1569|   931k|    VAL(dst) = d;
  ------------------
  |  | 1316|   931k|#define VAL(x) (*(char ***)(x))
  ------------------
 1570|   931k|}
m_option.c:free_str_list:
 1328|  3.58M|{
 1329|  3.58M|    char **d;
 1330|  3.58M|    int i;
 1331|       |
 1332|  3.58M|    if (!dst || !VAL(dst))
  ------------------
  |  | 1316|  3.58M|#define VAL(x) (*(char ***)(x))
  ------------------
  |  Branch (1332:9): [True: 0, False: 3.58M]
  |  Branch (1332:17): [True: 2.48M, False: 1.09M]
  ------------------
 1333|  2.48M|        return;
 1334|  1.09M|    d = VAL(dst);
  ------------------
  |  | 1316|  1.09M|#define VAL(x) (*(char ***)(x))
  ------------------
 1335|       |
 1336|  16.5M|    for (i = 0; d[i] != NULL; i++)
  ------------------
  |  Branch (1336:17): [True: 15.4M, False: 1.09M]
  ------------------
 1337|  15.4M|        talloc_free(d[i]);
  ------------------
  |  |   47|  15.4M|#define talloc_free                     ta_free
  ------------------
 1338|  1.09M|    talloc_free(d);
  ------------------
  |  |   47|  1.09M|#define talloc_free                     ta_free
  ------------------
 1339|  1.09M|    VAL(dst) = NULL;
  ------------------
  |  | 1316|  1.09M|#define VAL(x) (*(char ***)(x))
  ------------------
 1340|  1.09M|}
m_option.c:str_list_equal:
 1631|  93.8k|{
 1632|  93.8k|    char **la = VAL(a);
  ------------------
  |  | 1316|  93.8k|#define VAL(x) (*(char ***)(x))
  ------------------
 1633|  93.8k|    char **lb = VAL(b);
  ------------------
  |  | 1316|  93.8k|#define VAL(x) (*(char ***)(x))
  ------------------
 1634|       |
 1635|  93.8k|    bool a_empty = !la || !la[0];
  ------------------
  |  Branch (1635:20): [True: 43.1k, False: 50.7k]
  |  Branch (1635:27): [True: 349, False: 50.3k]
  ------------------
 1636|  93.8k|    bool b_empty = !lb || !lb[0];
  ------------------
  |  Branch (1636:20): [True: 38.9k, False: 54.8k]
  |  Branch (1636:27): [True: 325, False: 54.5k]
  ------------------
 1637|  93.8k|    if (a_empty || b_empty)
  ------------------
  |  Branch (1637:9): [True: 43.5k, False: 50.3k]
  |  Branch (1637:20): [True: 554, False: 49.8k]
  ------------------
 1638|  44.0k|        return a_empty == b_empty;
 1639|       |
 1640|   159k|    for (int n = 0; la[n] || lb[n]; n++) {
  ------------------
  |  Branch (1640:21): [True: 144k, False: 15.5k]
  |  Branch (1640:30): [True: 10.4k, False: 5.14k]
  ------------------
 1641|   154k|        if (!la[n] || !lb[n])
  ------------------
  |  Branch (1641:13): [True: 10.4k, False: 144k]
  |  Branch (1641:23): [True: 231, False: 143k]
  ------------------
 1642|  10.6k|            return false;
 1643|   143k|        if (strcmp(la[n], lb[n]) != 0)
  ------------------
  |  Branch (1643:13): [True: 34.0k, False: 109k]
  ------------------
 1644|  34.0k|            return false;
 1645|   143k|    }
 1646|       |
 1647|  5.14k|    return true;
 1648|  49.8k|}
m_option.c:parse_keyvalue_list:
 1700|   107k|{
 1701|   107k|    char **lst = NULL;
 1702|   107k|    int num = 0;
 1703|   107k|    int r = 0;
 1704|   107k|    bool append = false;
 1705|   107k|    bool full_value = false;
 1706|       |
 1707|   107k|    if ((opt->flags & M_OPT_HAVE_HELP) && bstr_equals0(param, "help"))
  ------------------
  |  |  468|   107k|#define M_OPT_HAVE_HELP         (UINT64_C(1) << 59)
  ------------------
  |  Branch (1707:9): [True: 2.51k, False: 105k]
  |  Branch (1707:43): [True: 79, False: 2.43k]
  ------------------
 1708|     79|        param = bstr0("help=");
 1709|       |
 1710|   107k|    int op = 0;
 1711|   107k|    if (bstr_endswith0(name, "-del")) {
  ------------------
  |  Branch (1711:9): [True: 168, False: 107k]
  ------------------
 1712|    168|        op = OP_DEL;
  ------------------
  |  | 1322|    168|#define OP_DEL 4
  ------------------
 1713|   107k|    } else if (bstr_endswith0(name, "-remove")) {
  ------------------
  |  Branch (1713:16): [True: 183, False: 107k]
  ------------------
 1714|    183|        op = OP_REMOVE;
  ------------------
  |  | 1325|    183|#define OP_REMOVE 7
  ------------------
 1715|    183|    }
 1716|       |
 1717|   107k|    if (bstr_endswith0(name, "-add")) {
  ------------------
  |  Branch (1717:9): [True: 17.2k, False: 90.3k]
  ------------------
 1718|  17.2k|        append = true;
 1719|  90.3k|    } else if (bstr_endswith0(name, "-append")) {
  ------------------
  |  Branch (1719:16): [True: 84.3k, False: 6.02k]
  ------------------
 1720|  84.3k|        append = full_value = true;
 1721|  84.3k|    } else if (bstr_endswith0(name, "-clr")) {
  ------------------
  |  Branch (1721:16): [True: 176, False: 5.85k]
  ------------------
 1722|    176|        if (dst)
  ------------------
  |  Branch (1722:13): [True: 176, False: 0]
  ------------------
 1723|    176|            free_str_list(dst);
 1724|    176|        return 0;
 1725|  5.85k|    } else if (op == OP_DEL || op == OP_REMOVE) {
  ------------------
  |  | 1322|  11.7k|#define OP_DEL 4
  ------------------
                  } else if (op == OP_DEL || op == OP_REMOVE) {
  ------------------
  |  | 1325|  5.68k|#define OP_REMOVE 7
  ------------------
  |  Branch (1725:16): [True: 168, False: 5.68k]
  |  Branch (1725:32): [True: 183, False: 5.49k]
  ------------------
 1726|    351|        int n = 0;
 1727|    351|        char **res = separate_input_param(opt, param, &n, op);
 1728|    351|        if (!res)
  ------------------
  |  Branch (1728:13): [True: 4, False: 347]
  ------------------
 1729|      4|            return M_OPT_INVALID;
  ------------------
  |  |  523|      4|#define M_OPT_INVALID           -3
  ------------------
 1730|    347|        lst = dst ? VAL(dst) : NULL;
  ------------------
  |  | 1316|    347|#define VAL(x) (*(char ***)(x))
  ------------------
  |  Branch (1730:15): [True: 347, False: 0]
  ------------------
 1731|  1.38k|        for (int i = 0; i < n; i++) {
  ------------------
  |  Branch (1731:25): [True: 1.03k, False: 347]
  ------------------
 1732|  1.03k|            int index = dst ? keyvalue_list_find_key(lst, bstr0(res[i])) : -1;
  ------------------
  |  Branch (1732:25): [True: 1.03k, False: 0]
  ------------------
 1733|  1.03k|            if (index >= 0) {
  ------------------
  |  Branch (1733:17): [True: 177, False: 862]
  ------------------
 1734|    177|                keyvalue_list_del_key(lst, index);
 1735|    177|                VAL(dst) = lst;
  ------------------
  |  | 1316|    177|#define VAL(x) (*(char ***)(x))
  ------------------
 1736|    177|            }
 1737|  1.03k|            talloc_free(res[i]);
  ------------------
  |  |   47|  1.03k|#define talloc_free                     ta_free
  ------------------
 1738|  1.03k|        }
 1739|    347|        talloc_free(res);
  ------------------
  |  |   47|    347|#define talloc_free                     ta_free
  ------------------
 1740|    347|        return 1;
 1741|    351|    }
 1742|       |
 1743|   107k|    if (append && dst) {
  ------------------
  |  Branch (1743:9): [True: 101k, False: 5.49k]
  |  Branch (1743:19): [True: 101k, False: 0]
  ------------------
 1744|   101k|        lst = VAL(dst);
  ------------------
  |  | 1316|   101k|#define VAL(x) (*(char ***)(x))
  ------------------
 1745|   298k|        for (int n = 0; lst && lst[n]; n++)
  ------------------
  |  Branch (1745:25): [True: 229k, False: 68.5k]
  |  Branch (1745:32): [True: 196k, False: 33.0k]
  ------------------
 1746|   196k|            num++;
 1747|   101k|    }
 1748|       |
 1749|   111k|    while (param.len) {
  ------------------
  |  Branch (1749:12): [True: 109k, False: 2.02k]
  ------------------
 1750|   109k|        bstr key, val;
 1751|   109k|        r = read_subparam(log, name, "=", &param, &key);
 1752|   109k|        if (r < 0)
  ------------------
  |  Branch (1752:13): [True: 489, False: 109k]
  ------------------
 1753|    489|            break;
 1754|   109k|        if (!bstr_eatstart0(&param, "=")) {
  ------------------
  |  Branch (1754:13): [True: 451, False: 108k]
  ------------------
 1755|    451|            mp_err(log, "Expected '=' and a value.\n");
  ------------------
  |  |   72|    451|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
 1756|    451|            r = M_OPT_INVALID;
  ------------------
  |  |  523|    451|#define M_OPT_INVALID           -3
  ------------------
 1757|    451|            break;
 1758|    451|        }
 1759|   108k|        if (full_value) {
  ------------------
  |  Branch (1759:13): [True: 84.3k, False: 24.2k]
  ------------------
 1760|  84.3k|            val = param;
 1761|  84.3k|            param.len = 0;
 1762|  84.3k|        } else {
 1763|  24.2k|            r = read_subparam(log, name, ",", &param, &val);
 1764|  24.2k|            if (r < 0)
  ------------------
  |  Branch (1764:17): [True: 67, False: 24.1k]
  ------------------
 1765|     67|                break;
 1766|  24.2k|        }
 1767|   108k|        if (dst) {
  ------------------
  |  Branch (1767:13): [True: 108k, False: 0]
  ------------------
 1768|   108k|            int index = keyvalue_list_find_key(lst, key);
 1769|   108k|            if (index >= 0) {
  ------------------
  |  Branch (1769:17): [True: 34.4k, False: 74.1k]
  ------------------
 1770|  34.4k|                keyvalue_list_del_key(lst, index);
 1771|  34.4k|                num -= 2;
 1772|  34.4k|            }
 1773|   108k|            MP_TARRAY_APPEND(NULL, lst, num, bstrto0(NULL, key));
  ------------------
  |  |  105|   108k|    do {                                            \
  |  |  106|   108k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|   108k|    do {                                            \
  |  |  |  |   97|   108k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|   108k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|   108k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|   108k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 71.3k, False: 37.2k]
  |  |  |  |  ------------------
  |  |  |  |   99|   108k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  71.3k|    do {                                                        \
  |  |  |  |  |  |   89|  71.3k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  71.3k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  71.3k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  71.3k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  71.3k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  71.3k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  71.3k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|   108k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|   108k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|   108k|        (idxvar)++;                                 \
  |  |  109|   108k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1774|   108k|            MP_TARRAY_APPEND(NULL, lst, num, bstrto0(NULL, val));
  ------------------
  |  |  105|   108k|    do {                                            \
  |  |  106|   108k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|   108k|    do {                                            \
  |  |  |  |   97|   108k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|   108k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|   108k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|   108k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 527, False: 108k]
  |  |  |  |  ------------------
  |  |  |  |   99|   108k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|    527|    do {                                                        \
  |  |  |  |  |  |   89|    527|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|    527|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|    527|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|    527|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|    527|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|    527|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|    527|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|   108k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|   108k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|   108k|        (idxvar)++;                                 \
  |  |  109|   108k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1775|   108k|            MP_TARRAY_APPEND(NULL, lst, num, NULL);
  ------------------
  |  |  105|   108k|    do {                                            \
  |  |  106|   108k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|   108k|    do {                                            \
  |  |  |  |   97|   108k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|   108k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|   108k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|   108k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 71.8k, False: 36.7k]
  |  |  |  |  ------------------
  |  |  |  |   99|   108k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  71.8k|    do {                                                        \
  |  |  |  |  |  |   89|  71.8k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  71.8k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  71.8k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  71.8k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  71.8k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  71.8k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  71.8k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|   108k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|   108k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|   108k|        (idxvar)++;                                 \
  |  |  109|   108k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1776|   108k|            num -= 1;
 1777|   108k|        }
 1778|       |
 1779|   108k|        if (!bstr_eatstart0(&param, ",") && !bstr_eatstart0(&param, ":"))
  ------------------
  |  Branch (1779:13): [True: 104k, False: 4.25k]
  |  Branch (1779:45): [True: 104k, False: 208]
  ------------------
 1780|   104k|            break;
 1781|   108k|    }
 1782|       |
 1783|   107k|    if (param.len) {
  ------------------
  |  Branch (1783:9): [True: 624, False: 106k]
  ------------------
 1784|    624|        mp_err(log, "Unparsable garbage at end of option value: '%.*s'\n",
  ------------------
  |  |   72|  1.24k|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 624, False: 0]
  |  |  ------------------
  ------------------
 1785|    624|               BSTR_P(param));
 1786|    624|        r = M_OPT_INVALID;
  ------------------
  |  |  523|    624|#define M_OPT_INVALID           -3
  ------------------
 1787|    624|    }
 1788|       |
 1789|   107k|    if (dst) {
  ------------------
  |  Branch (1789:9): [True: 107k, False: 0]
  ------------------
 1790|   107k|        if (!append)
  ------------------
  |  Branch (1790:13): [True: 5.49k, False: 101k]
  ------------------
 1791|  5.49k|            free_str_list(dst);
 1792|   107k|        VAL(dst) = lst;
  ------------------
  |  | 1316|   107k|#define VAL(x) (*(char ***)(x))
  ------------------
 1793|   107k|        if (r < 0)
  ------------------
  |  Branch (1793:13): [True: 1.00k, False: 106k]
  ------------------
 1794|  1.00k|            free_str_list(dst);
 1795|   107k|    } else {
 1796|      0|        free_str_list(&lst);
 1797|      0|    }
 1798|   107k|    return r;
 1799|   107k|}
m_option.c:keyvalue_list_find_key:
 1677|   109k|{
 1678|   129k|    for (int n = 0; lst && lst[n] && lst[n + 1]; n += 2) {
  ------------------
  |  Branch (1678:21): [True: 58.1k, False: 71.7k]
  |  Branch (1678:28): [True: 54.8k, False: 3.25k]
  |  Branch (1678:38): [True: 54.8k, False: 0]
  ------------------
 1679|  54.8k|        if (bstr_equals0(str, lst[n]))
  ------------------
  |  Branch (1679:13): [True: 34.5k, False: 20.3k]
  ------------------
 1680|  34.5k|            return n / 2;
 1681|  54.8k|    }
 1682|  74.9k|    return -1;
 1683|   109k|}
m_option.c:keyvalue_list_del_key:
 1686|  34.5k|{
 1687|  34.5k|    int count = 0;
 1688|   260k|    for (int n = 0; lst && lst[n]; n++)
  ------------------
  |  Branch (1688:21): [True: 260k, False: 0]
  |  Branch (1688:28): [True: 225k, False: 34.5k]
  ------------------
 1689|   225k|        count++;
 1690|  34.5k|    mp_assert(index * 2 + 1 < count);
  ------------------
  |  |   41|  34.5k|#define mp_assert assert
  ------------------
 1691|  34.5k|    count += 1; // terminating item
 1692|  34.5k|    talloc_free(lst[index * 2 + 0]);
  ------------------
  |  |   47|  34.5k|#define talloc_free                     ta_free
  ------------------
 1693|  34.5k|    talloc_free(lst[index * 2 + 1]);
  ------------------
  |  |   47|  34.5k|#define talloc_free                     ta_free
  ------------------
 1694|  34.5k|    MP_TARRAY_REMOVE_AT(lst, count, index * 2 + 1);
  ------------------
  |  |  143|  34.5k|    do {                                            \
  |  |  144|  34.5k|        size_t at_ = (at);                          \
  |  |  145|  34.5k|        assert(at_ <= (idxvar));                    \
  |  |  146|  34.5k|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|  34.5k|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|  34.5k|        (idxvar)--;                                 \
  |  |  149|  34.5k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1695|  34.5k|    MP_TARRAY_REMOVE_AT(lst, count, index * 2 + 0);
  ------------------
  |  |  143|  34.5k|    do {                                            \
  |  |  144|  34.5k|        size_t at_ = (at);                          \
  |  |  145|  34.5k|        assert(at_ <= (idxvar));                    \
  |  |  146|  34.5k|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|  34.5k|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|  34.5k|        (idxvar)--;                                 \
  |  |  149|  34.5k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1696|  34.5k|}
m_option.c:read_subparam:
 1982|   145k|{
 1983|   145k|    bstr p = *str;
 1984|   145k|    bstr subparam = {0};
 1985|       |
 1986|   145k|    if (bstr_eatstart0(&p, "\"")) {
  ------------------
  |  Branch (1986:9): [True: 411, False: 145k]
  ------------------
 1987|    411|        int optlen = bstrcspn(p, "\"");
 1988|    411|        subparam = bstr_splice(p, 0, optlen);
 1989|    411|        p = bstr_cut(p, optlen);
 1990|    411|        if (!bstr_startswith0(p, "\"")) {
  ------------------
  |  Branch (1990:13): [True: 204, False: 207]
  ------------------
 1991|    204|            mp_err(log, "Terminating '\"' missing for '%.*s'\n",
  ------------------
  |  |   72|    408|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 204, False: 0]
  |  |  ------------------
  ------------------
 1992|    204|                   BSTR_P(optname));
 1993|    204|            return M_OPT_INVALID;
  ------------------
  |  |  523|    204|#define M_OPT_INVALID           -3
  ------------------
 1994|    204|        }
 1995|    207|        p = bstr_cut(p, 1);
 1996|   145k|    } else if (bstr_eatstart0(&p, "[")) {
  ------------------
  |  Branch (1996:16): [True: 373, False: 144k]
  ------------------
 1997|    373|        bstr s = p;
 1998|    373|        int balance = 1;
 1999|  3.18k|        while (p.len && balance > 0) {
  ------------------
  |  Branch (1999:16): [True: 3.02k, False: 159]
  |  Branch (1999:25): [True: 2.81k, False: 214]
  ------------------
 2000|  2.81k|            if (p.start[0] == '[') {
  ------------------
  |  Branch (2000:17): [True: 401, False: 2.41k]
  ------------------
 2001|    401|                balance++;
 2002|  2.41k|            } else if (p.start[0] == ']') {
  ------------------
  |  Branch (2002:24): [True: 465, False: 1.94k]
  ------------------
 2003|    465|                balance--;
 2004|    465|            }
 2005|  2.81k|            p = bstr_cut(p, 1);
 2006|  2.81k|        }
 2007|    373|        if (balance != 0) {
  ------------------
  |  Branch (2007:13): [True: 100, False: 273]
  ------------------
 2008|    100|            mp_err(log, "Terminating ']' missing for '%.*s'\n",
  ------------------
  |  |   72|    200|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 100, False: 0]
  |  |  ------------------
  ------------------
 2009|    100|                   BSTR_P(optname));
 2010|    100|            return M_OPT_INVALID;
  ------------------
  |  |  523|    100|#define M_OPT_INVALID           -3
  ------------------
 2011|    100|        }
 2012|    273|        subparam = bstr_splice(s, 0, s.len - p.len - 1);
 2013|   144k|    } else if (bstr_eatstart0(&p, "%")) {
  ------------------
  |  Branch (2013:16): [True: 355, False: 144k]
  ------------------
 2014|    355|        int optlen = bstrtoll(p, &p, 0);
 2015|    355|        if (!bstr_startswith0(p, "%") || (optlen > p.len - 1)) {
  ------------------
  |  Branch (2015:13): [True: 140, False: 215]
  |  Branch (2015:42): [True: 141, False: 74]
  ------------------
 2016|    281|            mp_err(log, "Invalid length %d for '%.*s'\n",
  ------------------
  |  |   72|    562|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 281, False: 0]
  |  |  ------------------
  ------------------
 2017|    281|                   optlen, BSTR_P(optname));
 2018|    281|            return M_OPT_INVALID;
  ------------------
  |  |  523|    281|#define M_OPT_INVALID           -3
  ------------------
 2019|    281|        }
 2020|     74|        subparam = bstr_splice(p, 1, optlen + 1);
 2021|     74|        p = bstr_cut(p, optlen + 1);
 2022|   144k|    } else {
 2023|       |        // Skip until the next character that could possibly be a meta
 2024|       |        // character in option parsing.
 2025|   144k|        int optlen = bstrcspn(p, termset);
 2026|   144k|        subparam = bstr_splice(p, 0, optlen);
 2027|   144k|        p = bstr_cut(p, optlen);
 2028|   144k|    }
 2029|       |
 2030|   144k|    *str = p;
 2031|   144k|    *out_subparam = subparam;
 2032|   144k|    return 0;
 2033|   145k|}
m_option.c:print_keyvalue_list:
 1802|    514|{
 1803|    514|    char **lst = VAL(src);
  ------------------
  |  | 1316|    514|#define VAL(x) (*(char ***)(x))
  ------------------
 1804|    514|    char *ret = talloc_strdup(NULL, "");
  ------------------
  |  |   50|    514|#define talloc_strdup                   ta_xstrdup
  ------------------
 1805|    785|    for (int n = 0; lst && lst[n] && lst[n + 1]; n += 2) {
  ------------------
  |  Branch (1805:21): [True: 362, False: 423]
  |  Branch (1805:28): [True: 271, False: 91]
  |  Branch (1805:38): [True: 271, False: 0]
  ------------------
 1806|    271|        if (ret[0])
  ------------------
  |  Branch (1806:13): [True: 180, False: 91]
  ------------------
 1807|    180|            ret = talloc_strdup_append(ret, ",");
  ------------------
  |  |   57|    180|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
 1808|    271|        ret = talloc_asprintf_append(ret, "%s=%s", lst[n], lst[n + 1]);
  ------------------
  |  |   63|    271|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 1809|    271|    }
 1810|    514|    return ret;
 1811|    514|}
m_option.c:parse_msglevels:
 1894|  2.23k|{
 1895|  2.23k|    if (bstr_equals0(param, "help")) {
  ------------------
  |  Branch (1895:9): [True: 66, False: 2.16k]
  ------------------
 1896|     66|        mp_info(log, "Syntax:\n\n   --msg-level=module1=level,module2=level,...\n\n"
  ------------------
  |  |   74|     66|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 1897|     66|                     "'module' is output prefix as shown with -v, or a prefix\n"
 1898|     66|                     "of it. level is one of:\n\n"
 1899|     66|                     "  fatal error warn info status v debug trace\n\n"
 1900|     66|                     "The level specifies the minimum log level a message\n"
 1901|     66|                     "must have to be printed.\n"
 1902|     66|                     "The special module name 'all' affects all modules.\n");
 1903|     66|        return M_OPT_EXIT;
  ------------------
  |  |  533|     66|#define M_OPT_EXIT              -6
  ------------------
 1904|     66|    }
 1905|       |
 1906|  2.16k|    char **dst_copy = NULL;
 1907|  2.16k|    int r = m_option_type_keyvalue_list.parse(log, opt, name, param, &dst_copy);
 1908|  2.16k|    if (r >= 0)
  ------------------
  |  Branch (1908:9): [True: 1.29k, False: 871]
  ------------------
 1909|  1.29k|        r = check_msg_levels(log, dst_copy);
 1910|       |
 1911|  2.16k|    if (r >= 0)
  ------------------
  |  Branch (1911:9): [True: 990, False: 1.17k]
  ------------------
 1912|    990|        m_option_type_keyvalue_list.copy(opt, dst, &dst_copy);
 1913|  2.16k|    m_option_type_keyvalue_list.free(&dst_copy);
 1914|  2.16k|    return r;
 1915|  2.23k|}
m_option.c:check_msg_levels:
 1881|  1.29k|{
 1882|  2.09k|    for (int n = 0; list && list[n * 2 + 0]; n++) {
  ------------------
  |  Branch (1882:21): [True: 1.90k, False: 194]
  |  Branch (1882:29): [True: 1.10k, False: 796]
  ------------------
 1883|  1.10k|        char *level = list[n * 2 + 1];
 1884|  1.10k|        if (mp_msg_find_level(level) < 0 && strcmp(level, "no") != 0) {
  ------------------
  |  Branch (1884:13): [True: 570, False: 535]
  |  Branch (1884:45): [True: 304, False: 266]
  ------------------
 1885|    304|            mp_err(log, "Invalid message level '%s'\n", level);
  ------------------
  |  |   72|    304|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
 1886|    304|            return M_OPT_INVALID;
  ------------------
  |  |  523|    304|#define M_OPT_INVALID           -3
  ------------------
 1887|    304|        }
 1888|  1.10k|    }
 1889|    990|    return 1;
 1890|  1.29k|}
m_option.c:parse_print:
 1945|  4.10k|{
 1946|  4.10k|    ((m_opt_print_fn) opt->priv)(log);
 1947|  4.10k|    return M_OPT_EXIT;
  ------------------
  |  |  533|  4.10k|#define M_OPT_EXIT              -6
  ------------------
 1948|  4.10k|}
m_option.c:parse_dummy_flag:
 1958|  12.2k|{
 1959|  12.2k|    if (param.len) {
  ------------------
  |  Branch (1959:9): [True: 4, False: 12.2k]
  ------------------
 1960|      4|        mp_err(log, "Invalid parameter for %.*s flag: %.*s\n",
  ------------------
  |  |   72|     16|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 4, False: 0]
  |  |  |  Branch (72:55): [True: 4, False: 0]
  |  |  ------------------
  ------------------
 1961|      4|               BSTR_P(name), BSTR_P(param));
 1962|      4|        return M_OPT_DISALLOW_PARAM;
  ------------------
  |  |  530|      4|#define M_OPT_DISALLOW_PARAM    -5
  ------------------
 1963|      4|    }
 1964|  12.2k|    return 0;
 1965|  12.2k|}
m_option.c:parse_color:
 2085|    672|{
 2086|    672|    if (param.len == 0)
  ------------------
  |  Branch (2086:9): [True: 1, False: 671]
  ------------------
 2087|      1|        return M_OPT_MISSING_PARAM;
  ------------------
  |  |  520|      1|#define M_OPT_MISSING_PARAM     -2
  ------------------
 2088|       |
 2089|    671|    bool is_help = bstr_equals0(param, "help");
 2090|    671|    if (is_help)
  ------------------
  |  Branch (2090:9): [True: 1, False: 670]
  ------------------
 2091|      1|        goto exit;
 2092|       |
 2093|    670|    bstr val = param;
 2094|    670|    struct m_color color = {0};
 2095|       |
 2096|    670|    if (bstr_eatstart0(&val, "#")) {
  ------------------
  |  Branch (2096:9): [True: 11, False: 659]
  ------------------
 2097|       |        // #[AA]RRGGBB
 2098|     11|        if (val.len != 6 && val.len != 8)
  ------------------
  |  Branch (2098:13): [True: 9, False: 2]
  |  Branch (2098:29): [True: 8, False: 1]
  ------------------
 2099|      8|            goto exit;
 2100|      3|        bool has_alpha = val.len == 8;
 2101|      3|        uint32_t c = bstrtoll(val, &val, 16);
 2102|      3|        if (val.len)
  ------------------
  |  Branch (2102:13): [True: 1, False: 2]
  ------------------
 2103|      1|            goto exit;
 2104|      2|        color = (struct m_color) {
 2105|      2|            (c >> 16) & 0xFF,
 2106|      2|            (c >> 8) & 0xFF,
 2107|      2|            c & 0xFF,
 2108|      2|            has_alpha ? (c >> 24) & 0xFF : 0xFF,
  ------------------
  |  Branch (2108:13): [True: 1, False: 1]
  ------------------
 2109|      2|        };
 2110|    659|    } else {
 2111|    659|        bstr comp_str[5];
 2112|    659|        int num = split_char(param, '/', 5, comp_str);
 2113|    659|        if (num < 1 || num > 4)
  ------------------
  |  Branch (2113:13): [True: 0, False: 659]
  |  Branch (2113:24): [True: 2, False: 657]
  ------------------
 2114|      2|            goto exit;
 2115|    657|        double comp[4] = {0, 0, 0, 1};
 2116|  1.91k|        for (int n = 0; n < num; n++) {
  ------------------
  |  Branch (2116:25): [True: 1.27k, False: 637]
  ------------------
 2117|  1.27k|            bstr rest;
 2118|  1.27k|            double d = bstrtod(comp_str[n], &rest);
 2119|  1.27k|            if (rest.len || !comp_str[n].len || d < 0 || d > 1 || !isfinite(d))
  ------------------
  |  Branch (2119:17): [True: 14, False: 1.25k]
  |  Branch (2119:29): [True: 4, False: 1.25k]
  |  Branch (2119:49): [True: 1, False: 1.25k]
  |  Branch (2119:58): [True: 1, False: 1.25k]
  |  Branch (2119:67): [True: 0, False: 1.25k]
  ------------------
 2120|     20|                goto exit;
 2121|  1.25k|            comp[n] = d;
 2122|  1.25k|        }
 2123|    637|        if (num == 2)
  ------------------
  |  Branch (2123:13): [True: 272, False: 365]
  ------------------
 2124|    272|            comp[3] = comp[1];
 2125|    637|        if (num < 3)
  ------------------
  |  Branch (2125:13): [True: 470, False: 167]
  ------------------
 2126|    470|            comp[2] = comp[1] = comp[0];
 2127|    637|        color = (struct m_color) { comp[0] * 0xFF, comp[1] * 0xFF,
 2128|    637|                                   comp[2] * 0xFF, comp[3] * 0xFF };
 2129|    637|    }
 2130|       |
 2131|    639|    if (dst)
  ------------------
  |  Branch (2131:9): [True: 639, False: 0]
  ------------------
 2132|    639|        *((struct m_color *)dst) = color;
 2133|       |
 2134|    639|    return 1;
 2135|       |
 2136|     32|exit:
 2137|     32|    if (!is_help) {
  ------------------
  |  Branch (2137:9): [True: 31, False: 1]
  ------------------
 2138|     31|        mp_err(log, "Option %.*s: invalid color: '%.*s'\n",
  ------------------
  |  |   72|    124|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 31, False: 0]
  |  |  |  Branch (72:55): [True: 31, False: 0]
  |  |  ------------------
  ------------------
 2139|     31|               BSTR_P(name), BSTR_P(param));
 2140|     31|    }
 2141|     32|    mp_info(log, "Valid colors must be in the form #RRGGBB or #AARRGGBB (in hex)\n"
  ------------------
  |  |   74|     32|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2142|     32|            "or in the form 'r/g/b/a', where each component is a value in the\n"
 2143|     32|            "range 0.0-1.0. (Also allowed: 'gray', 'gray/a', 'r/g/b').\n");
 2144|     32|    return is_help ? M_OPT_EXIT : M_OPT_INVALID;
  ------------------
  |  |  533|      1|#define M_OPT_EXIT              -6
  ------------------
                  return is_help ? M_OPT_EXIT : M_OPT_INVALID;
  ------------------
  |  |  523|     31|#define M_OPT_INVALID           -3
  ------------------
  |  Branch (2144:12): [True: 1, False: 31]
  ------------------
 2145|    670|}
m_option.c:split_char:
 2065|    659|{
 2066|    659|    if (max < 1)
  ------------------
  |  Branch (2066:9): [True: 0, False: 659]
  ------------------
 2067|      0|        return 0;
 2068|       |
 2069|    659|    int count = 0;
 2070|  1.29k|    while (1) {
  ------------------
  |  Branch (2070:12): [Folded - Ignored]
  ------------------
 2071|  1.29k|        int next = bstrchr(str, split);
 2072|  1.29k|        if (next >= 0 && max - count > 1) {
  ------------------
  |  Branch (2072:13): [True: 637, False: 658]
  |  Branch (2072:26): [True: 636, False: 1]
  ------------------
 2073|    636|            out_arr[count++] = bstr_splice(str, 0, next);
 2074|    636|            str = bstr_cut(str, next + 1);
 2075|    659|        } else {
 2076|    659|            out_arr[count++] = str;
 2077|    659|            break;
 2078|    659|        }
 2079|  1.29k|    }
 2080|    659|    return count;
 2081|    659|}
m_option.c:print_color:
 2148|    326|{
 2149|    326|    const struct m_color *c = val;
 2150|    326|    return talloc_asprintf(NULL, "#%02X%02X%02X%02X", c->a, c->r, c->g, c->b);
  ------------------
  |  |   52|    326|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|    326|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 2151|    326|}
m_option.c:color_equal:
 2154|  1.03k|{
 2155|  1.03k|    struct m_color *ca = a;
 2156|  1.03k|    struct m_color *cb = b;
 2157|  1.03k|    return ca->a == cb->a && ca->r == cb->r && ca->g == cb->g && ca->b == cb->b;
  ------------------
  |  Branch (2157:12): [True: 902, False: 136]
  |  Branch (2157:30): [True: 744, False: 158]
  |  Branch (2157:48): [True: 643, False: 101]
  |  Branch (2157:66): [True: 620, False: 23]
  ------------------
 2158|  1.03k|}
m_option.c:parse_geometry:
 2329|  1.33k|{
 2330|  1.33k|    bool is_help = bstr_equals0(param, "help");
 2331|  1.33k|    if (is_help)
  ------------------
  |  Branch (2331:9): [True: 1, False: 1.33k]
  ------------------
 2332|      1|        goto exit;
 2333|       |
 2334|  1.33k|    struct m_geometry gm;
 2335|  1.33k|    if (!parse_geometry_str(&gm, param))
  ------------------
  |  Branch (2335:9): [True: 92, False: 1.24k]
  ------------------
 2336|     92|        goto exit;
 2337|       |
 2338|  1.24k|    if (dst)
  ------------------
  |  Branch (2338:9): [True: 1.24k, False: 0]
  ------------------
 2339|  1.24k|        *((struct m_geometry *)dst) = gm;
 2340|       |
 2341|  1.24k|    return 1;
 2342|       |
 2343|     93|exit:
 2344|     93|    if (!is_help) {
  ------------------
  |  Branch (2344:9): [True: 92, False: 1]
  ------------------
 2345|     92|        mp_err(log, "Option %.*s: invalid geometry: '%.*s'\n",
  ------------------
  |  |   72|    368|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 92, False: 0]
  |  |  |  Branch (72:55): [True: 92, False: 0]
  |  |  ------------------
  ------------------
 2346|     92|               BSTR_P(name), BSTR_P(param));
 2347|     92|    }
 2348|     93|    mp_info(log,
  ------------------
  |  |   74|     93|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2349|     93|         "Valid format: [W[%%][xH[%%]]][{+-}X[%%]{+-}Y[%%]] | [X[%%]:Y[%%]]\n");
 2350|     93|    return is_help ? M_OPT_EXIT : M_OPT_INVALID;
  ------------------
  |  |  533|      1|#define M_OPT_EXIT              -6
  ------------------
                  return is_help ? M_OPT_EXIT : M_OPT_INVALID;
  ------------------
  |  |  523|     92|#define M_OPT_INVALID           -3
  ------------------
  |  Branch (2350:12): [True: 1, False: 92]
  ------------------
 2351|  1.33k|}
m_option.c:parse_geometry_str:
 2190|  4.02k|{
 2191|  4.02k|    *gm = (struct m_geometry) { .x = INT_MIN, .y = INT_MIN };
 2192|  4.02k|    if (s.len == 0)
  ------------------
  |  Branch (2192:9): [True: 386, False: 3.64k]
  ------------------
 2193|    386|        return true;
 2194|       |    // Approximate grammar:
 2195|       |    // [[W][xH]][{+-}X{+-}Y][/WS] | [X:Y]
 2196|       |    // (meaning: [optional] {one character of} one|alternative)
 2197|       |    // Every number can be followed by '%'
 2198|  3.64k|    int num;
 2199|  3.64k|    bool per;
 2200|       |
 2201|  3.64k|#define READ_NUM(F, F_PER) do {         \
 2202|  3.64k|    if (!eat_num_per(&s, &num, &per))   \
 2203|  3.64k|        goto error;                     \
 2204|  3.64k|    gm->F = num;                        \
 2205|  3.64k|    gm->F_PER = per;                    \
 2206|  3.64k|} while(0)
 2207|       |
 2208|  3.64k|#define READ_SIGN(F) do {               \
 2209|  3.64k|    if (bstr_eatstart0(&s, "+")) {      \
 2210|  3.64k|        gm->F = false;                  \
 2211|  3.64k|    } else if (bstr_eatstart0(&s, "-")) {\
 2212|  3.64k|        gm->F = true;                   \
 2213|  3.64k|    } else goto error;                  \
 2214|  3.64k|} while(0)
 2215|       |
 2216|  3.64k|    if (bstrchr(s, ':') < 0) {
  ------------------
  |  Branch (2216:9): [True: 3.00k, False: 640]
  ------------------
 2217|  3.00k|        gm->wh_valid = true;
 2218|  3.00k|        if (!bstr_startswith0(s, "+") && !bstr_startswith0(s, "-")) {
  ------------------
  |  Branch (2218:13): [True: 2.52k, False: 482]
  |  Branch (2218:42): [True: 1.68k, False: 841]
  ------------------
 2219|  1.68k|            if (!bstr_startswith0(s, "x"))
  ------------------
  |  Branch (2219:17): [True: 997, False: 683]
  ------------------
 2220|    997|                READ_NUM(w, w_per);
  ------------------
  |  | 2201|    997|#define READ_NUM(F, F_PER) do {         \
  |  | 2202|    997|    if (!eat_num_per(&s, &num, &per))   \
  |  |  ------------------
  |  |  |  Branch (2202:9): [True: 46, False: 951]
  |  |  ------------------
  |  | 2203|    997|        goto error;                     \
  |  | 2204|    997|    gm->F = num;                        \
  |  | 2205|    951|    gm->F_PER = per;                    \
  |  | 2206|    951|} while(0)
  |  |  ------------------
  |  |  |  Branch (2206:9): [Folded - Ignored]
  |  |  ------------------
  ------------------
 2221|  1.63k|            if (bstr_eatstart0(&s, "x"))
  ------------------
  |  Branch (2221:17): [True: 686, False: 948]
  ------------------
 2222|    686|                READ_NUM(h, h_per);
  ------------------
  |  | 2201|    686|#define READ_NUM(F, F_PER) do {         \
  |  | 2202|    686|    if (!eat_num_per(&s, &num, &per))   \
  |  |  ------------------
  |  |  |  Branch (2202:9): [True: 59, False: 627]
  |  |  ------------------
  |  | 2203|    686|        goto error;                     \
  |  | 2204|    686|    gm->F = num;                        \
  |  | 2205|    627|    gm->F_PER = per;                    \
  |  | 2206|    627|} while(0)
  |  |  ------------------
  |  |  |  Branch (2206:9): [Folded - Ignored]
  |  |  ------------------
  ------------------
 2223|  1.63k|        }
 2224|  2.89k|        if (s.len > 0) {
  ------------------
  |  Branch (2224:13): [True: 1.49k, False: 1.40k]
  ------------------
 2225|  1.49k|            gm->xy_valid = true;
 2226|  1.49k|            READ_SIGN(x_sign);
  ------------------
  |  | 2208|  1.49k|#define READ_SIGN(F) do {               \
  |  | 2209|  1.49k|    if (bstr_eatstart0(&s, "+")) {      \
  |  |  ------------------
  |  |  |  Branch (2209:9): [True: 484, False: 1.00k]
  |  |  ------------------
  |  | 2210|    484|        gm->F = false;                  \
  |  | 2211|  1.00k|    } else if (bstr_eatstart0(&s, "-")) {\
  |  |  ------------------
  |  |  |  Branch (2211:16): [True: 884, False: 122]
  |  |  ------------------
  |  | 2212|    884|        gm->F = true;                   \
  |  | 2213|    884|    } else goto error;                  \
  |  | 2214|  1.49k|} while(0)
  |  |  ------------------
  |  |  |  Branch (2214:9): [Folded - Ignored]
  |  |  ------------------
  ------------------
 2227|  1.36k|            READ_NUM(x, x_per);
  ------------------
  |  | 2201|  1.36k|#define READ_NUM(F, F_PER) do {         \
  |  | 2202|  1.36k|    if (!eat_num_per(&s, &num, &per))   \
  |  |  ------------------
  |  |  |  Branch (2202:9): [True: 38, False: 1.33k]
  |  |  ------------------
  |  | 2203|  1.36k|        goto error;                     \
  |  | 2204|  1.36k|    gm->F = num;                        \
  |  | 2205|  1.33k|    gm->F_PER = per;                    \
  |  | 2206|  1.33k|} while(0)
  |  |  ------------------
  |  |  |  Branch (2206:9): [Folded - Ignored]
  |  |  ------------------
  ------------------
 2228|  1.33k|            READ_SIGN(y_sign);
  ------------------
  |  | 2208|  1.33k|#define READ_SIGN(F) do {               \
  |  | 2209|  1.33k|    if (bstr_eatstart0(&s, "+")) {      \
  |  |  ------------------
  |  |  |  Branch (2209:9): [True: 482, False: 848]
  |  |  ------------------
  |  | 2210|    482|        gm->F = false;                  \
  |  | 2211|    848|    } else if (bstr_eatstart0(&s, "-")) {\
  |  |  ------------------
  |  |  |  Branch (2211:16): [True: 700, False: 148]
  |  |  ------------------
  |  | 2212|    700|        gm->F = true;                   \
  |  | 2213|    700|    } else goto error;                  \
  |  | 2214|  1.33k|} while(0)
  |  |  ------------------
  |  |  |  Branch (2214:9): [Folded - Ignored]
  |  |  ------------------
  ------------------
 2229|  1.18k|            READ_NUM(y, y_per);
  ------------------
  |  | 2201|  1.18k|#define READ_NUM(F, F_PER) do {         \
  |  | 2202|  1.18k|    if (!eat_num_per(&s, &num, &per))   \
  |  |  ------------------
  |  |  |  Branch (2202:9): [True: 57, False: 1.12k]
  |  |  ------------------
  |  | 2203|  1.18k|        goto error;                     \
  |  | 2204|  1.18k|    gm->F = num;                        \
  |  | 2205|  1.12k|    gm->F_PER = per;                    \
  |  | 2206|  1.12k|} while(0)
  |  |  ------------------
  |  |  |  Branch (2206:9): [Folded - Ignored]
  |  |  ------------------
  ------------------
 2230|  1.18k|        }
 2231|  2.53k|        if (bstr_eatstart0(&s, "/")) {
  ------------------
  |  Branch (2231:13): [True: 274, False: 2.25k]
  ------------------
 2232|    274|            bstr rest;
 2233|    274|            long long v = bstrtoll(s, &rest, 10);
 2234|    274|            if (s.len == rest.len || v < 1 || v > INT_MAX)
  ------------------
  |  Branch (2234:17): [True: 2, False: 272]
  |  Branch (2234:38): [True: 71, False: 201]
  |  Branch (2234:47): [True: 22, False: 179]
  ------------------
 2235|     95|                goto error;
 2236|    179|            s = rest;
 2237|    179|            gm->ws = v;
 2238|    179|        }
 2239|  2.53k|    } else {
 2240|    640|        gm->xy_valid = true;
 2241|    640|        READ_NUM(x, x_per);
  ------------------
  |  | 2201|    640|#define READ_NUM(F, F_PER) do {         \
  |  | 2202|    640|    if (!eat_num_per(&s, &num, &per))   \
  |  |  ------------------
  |  |  |  Branch (2202:9): [True: 56, False: 584]
  |  |  ------------------
  |  | 2203|    640|        goto error;                     \
  |  | 2204|    640|    gm->F = num;                        \
  |  | 2205|    584|    gm->F_PER = per;                    \
  |  | 2206|    584|} while(0)
  |  |  ------------------
  |  |  |  Branch (2206:9): [Folded - Ignored]
  |  |  ------------------
  ------------------
 2242|    584|        if (!bstr_eatstart0(&s, ":"))
  ------------------
  |  Branch (2242:13): [True: 69, False: 515]
  ------------------
 2243|     69|            goto error;
 2244|    515|        READ_NUM(y, y_per);
  ------------------
  |  | 2201|    515|#define READ_NUM(F, F_PER) do {         \
  |  | 2202|    515|    if (!eat_num_per(&s, &num, &per))   \
  |  |  ------------------
  |  |  |  Branch (2202:9): [True: 115, False: 400]
  |  |  ------------------
  |  | 2203|    515|        goto error;                     \
  |  | 2204|    515|    gm->F = num;                        \
  |  | 2205|    400|    gm->F_PER = per;                    \
  |  | 2206|    400|} while(0)
  |  |  ------------------
  |  |  |  Branch (2206:9): [Folded - Ignored]
  |  |  ------------------
  ------------------
 2245|    515|    }
 2246|       |
 2247|  2.83k|    return s.len == 0;
 2248|       |
 2249|    805|error:
 2250|    805|    return false;
 2251|  3.64k|}
m_option.c:eat_num_per:
 2174|  5.38k|{
 2175|  5.38k|    bstr rest;
 2176|  5.38k|    long long v = bstrtoll(*s, &rest, 10);
 2177|  5.38k|    if (s->len == rest.len || v < INT_MIN || v > INT_MAX)
  ------------------
  |  Branch (2177:9): [True: 93, False: 5.29k]
  |  Branch (2177:31): [True: 234, False: 5.06k]
  |  Branch (2177:46): [True: 44, False: 5.01k]
  ------------------
 2178|    371|        return false;
 2179|  5.01k|    *out_num = v;
 2180|  5.01k|    *out_per = false;
 2181|  5.01k|    *s = rest;
 2182|  5.01k|    if (bstr_eatstart0(&rest, "%") && v >= 0 && v <= 100) {
  ------------------
  |  Branch (2182:9): [True: 1.06k, False: 3.95k]
  |  Branch (2182:39): [True: 896, False: 170]
  |  Branch (2182:49): [True: 685, False: 211]
  ------------------
 2183|    685|        *out_per = true;
 2184|    685|        *s = rest;
 2185|    685|    }
 2186|  5.01k|    return true;
 2187|  5.38k|}
m_option.c:print_geometry:
 2260|    149|{
 2261|    149|    const struct m_geometry *gm = val;
 2262|    149|    char *res = talloc_strdup(NULL, "");
  ------------------
  |  |   50|    149|#define talloc_strdup                   ta_xstrdup
  ------------------
 2263|    149|    if (gm->wh_valid || gm->xy_valid) {
  ------------------
  |  Branch (2263:9): [True: 0, False: 149]
  |  Branch (2263:25): [True: 0, False: 149]
  ------------------
 2264|      0|        if (gm->wh_valid) {
  ------------------
  |  Branch (2264:13): [True: 0, False: 0]
  ------------------
 2265|      0|            APPEND_PER(w, w_per);
  ------------------
  |  | 2257|      0|    res = talloc_asprintf_append(res, "%d%s", gm->F, gm->F_PER ? "%" : "")
  |  |  ------------------
  |  |  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  |  |  ------------------
  |  |  |  Branch (2257:54): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2266|      0|            res = talloc_asprintf_append(res, "x");
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 2267|      0|            APPEND_PER(h, h_per);
  ------------------
  |  | 2257|      0|    res = talloc_asprintf_append(res, "%d%s", gm->F, gm->F_PER ? "%" : "")
  |  |  ------------------
  |  |  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  |  |  ------------------
  |  |  |  Branch (2257:54): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2268|      0|        }
 2269|      0|        if (gm->xy_valid) {
  ------------------
  |  Branch (2269:13): [True: 0, False: 0]
  ------------------
 2270|      0|            res = talloc_asprintf_append(res, gm->x_sign ? "-" : "+");
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
  |  Branch (2270:47): [True: 0, False: 0]
  ------------------
 2271|      0|            APPEND_PER(x, x_per);
  ------------------
  |  | 2257|      0|    res = talloc_asprintf_append(res, "%d%s", gm->F, gm->F_PER ? "%" : "")
  |  |  ------------------
  |  |  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  |  |  ------------------
  |  |  |  Branch (2257:54): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2272|      0|            res = talloc_asprintf_append(res, gm->y_sign ? "-" : "+");
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
  |  Branch (2272:47): [True: 0, False: 0]
  ------------------
 2273|      0|            APPEND_PER(y, y_per);
  ------------------
  |  | 2257|      0|    res = talloc_asprintf_append(res, "%d%s", gm->F, gm->F_PER ? "%" : "")
  |  |  ------------------
  |  |  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  |  |  ------------------
  |  |  |  Branch (2257:54): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 2274|      0|        }
 2275|      0|        if (gm->ws > 0)
  ------------------
  |  Branch (2275:13): [True: 0, False: 0]
  ------------------
 2276|      0|            res = talloc_asprintf_append(res, "/%d", gm->ws);
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 2277|      0|    }
 2278|    149|    return res;
 2279|    149|}
m_option.c:geometry_equal:
 2354|  2.96k|{
 2355|  2.96k|    struct m_geometry *ga = a;
 2356|  2.96k|    struct m_geometry *gb = b;
 2357|  2.96k|    return ga->x == gb->x && ga->y == gb->y && ga->w == gb->w && ga->h == gb->h &&
  ------------------
  |  Branch (2357:12): [True: 2.18k, False: 781]
  |  Branch (2357:30): [True: 1.98k, False: 200]
  |  Branch (2357:48): [True: 1.69k, False: 289]
  |  Branch (2357:66): [True: 1.48k, False: 210]
  ------------------
 2358|  2.96k|           ga->xy_valid == gb->xy_valid && ga->wh_valid == gb->wh_valid &&
  ------------------
  |  Branch (2358:12): [True: 1.47k, False: 9]
  |  Branch (2358:44): [True: 1.40k, False: 66]
  ------------------
 2359|  2.96k|           ga->w_per == gb->w_per && ga->h_per == gb->h_per &&
  ------------------
  |  Branch (2359:12): [True: 1.33k, False: 69]
  |  Branch (2359:38): [True: 1.25k, False: 83]
  ------------------
 2360|  2.96k|           ga->x_per == gb->x_per && ga->y_per == gb->y_per &&
  ------------------
  |  Branch (2360:12): [True: 1.14k, False: 108]
  |  Branch (2360:38): [True: 1.07k, False: 71]
  ------------------
 2361|  2.96k|           ga->x_sign == gb->x_sign && ga->y_sign == gb->y_sign &&
  ------------------
  |  Branch (2361:12): [True: 1.01k, False: 66]
  |  Branch (2361:40): [True: 942, False: 68]
  ------------------
 2362|  2.96k|           ga->ws == gb->ws;
  ------------------
  |  Branch (2362:12): [True: 908, False: 34]
  ------------------
 2363|  2.96k|}
m_option.c:parse_size_box:
 2376|  2.18k|{
 2377|  2.18k|    bool is_help = bstr_equals0(param, "help");
 2378|  2.18k|    if (is_help)
  ------------------
  |  Branch (2378:9): [True: 1, False: 2.18k]
  ------------------
 2379|      1|        goto exit;
 2380|       |
 2381|  2.18k|    struct m_geometry gm;
 2382|  2.18k|    if (!parse_geometry_str(&gm, param))
  ------------------
  |  Branch (2382:9): [True: 865, False: 1.31k]
  ------------------
 2383|    865|        goto exit;
 2384|       |
 2385|  1.31k|    if (gm.xy_valid)
  ------------------
  |  Branch (2385:9): [True: 119, False: 1.19k]
  ------------------
 2386|    119|        goto exit;
 2387|       |
 2388|  1.19k|    if (dst)
  ------------------
  |  Branch (2388:9): [True: 1.19k, False: 0]
  ------------------
 2389|  1.19k|        *((struct m_geometry *)dst) = gm;
 2390|       |
 2391|  1.19k|    return 1;
 2392|       |
 2393|    985|exit:
 2394|    985|    if (!is_help) {
  ------------------
  |  Branch (2394:9): [True: 984, False: 1]
  ------------------
 2395|    984|        mp_err(log, "Option %.*s: invalid size: '%.*s'\n",
  ------------------
  |  |   72|  3.93k|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 984, False: 0]
  |  |  |  Branch (72:55): [True: 984, False: 0]
  |  |  ------------------
  ------------------
 2396|    984|               BSTR_P(name), BSTR_P(param));
 2397|    984|    }
 2398|    985|    mp_info(log, "Valid format: W[%%][xH[%%]] or empty string\n");
  ------------------
  |  |   74|    985|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2399|    985|    return is_help ? M_OPT_EXIT : M_OPT_INVALID;
  ------------------
  |  |  533|      1|#define M_OPT_EXIT              -6
  ------------------
                  return is_help ? M_OPT_EXIT : M_OPT_INVALID;
  ------------------
  |  |  523|    984|#define M_OPT_INVALID           -3
  ------------------
  |  Branch (2399:12): [True: 1, False: 984]
  ------------------
 2400|  1.31k|}
m_option.c:parse_rect:
 2431|    514|{
 2432|    514|    bool is_help = bstr_equals0(param, "help");
 2433|    514|    if (is_help)
  ------------------
  |  Branch (2433:9): [True: 1, False: 513]
  ------------------
 2434|      1|        goto exit;
 2435|       |
 2436|    513|    struct m_geometry gm;
 2437|    513|    if (!parse_geometry_str(&gm, param))
  ------------------
  |  Branch (2437:9): [True: 6, False: 507]
  ------------------
 2438|      6|        goto exit;
 2439|       |
 2440|    507|    bool invalid = gm.x_sign || gm.y_sign || gm.ws;
  ------------------
  |  Branch (2440:20): [True: 1, False: 506]
  |  Branch (2440:33): [True: 1, False: 505]
  |  Branch (2440:46): [True: 0, False: 505]
  ------------------
 2441|    507|    invalid |= gm.wh_valid && (gm.w < 0 || gm.h < 0);
  ------------------
  |  Branch (2441:16): [True: 271, False: 236]
  |  Branch (2441:32): [True: 0, False: 271]
  |  Branch (2441:44): [True: 2, False: 269]
  ------------------
 2442|    507|    invalid |= gm.wh_valid && !gm.xy_valid && gm.w <= 0 && gm.h <= 0;
  ------------------
  |  Branch (2442:16): [True: 271, False: 236]
  |  Branch (2442:31): [True: 269, False: 2]
  |  Branch (2442:47): [True: 68, False: 201]
  |  Branch (2442:60): [True: 3, False: 65]
  ------------------
 2443|       |
 2444|    507|    if (invalid)
  ------------------
  |  Branch (2444:9): [True: 5, False: 502]
  ------------------
 2445|      5|        goto exit;
 2446|       |
 2447|    502|    if (dst)
  ------------------
  |  Branch (2447:9): [True: 502, False: 0]
  ------------------
 2448|    502|        *((struct m_geometry *)dst) = gm;
 2449|       |
 2450|    502|    return 1;
 2451|       |
 2452|     12|exit:
 2453|     12|    if (!is_help) {
  ------------------
  |  Branch (2453:9): [True: 11, False: 1]
  ------------------
 2454|     11|        mp_err(log, "Option %.*s: invalid rect: '%.*s'\n",
  ------------------
  |  |   72|     44|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 11, False: 0]
  |  |  |  Branch (72:55): [True: 11, False: 0]
  |  |  ------------------
  ------------------
 2455|     11|               BSTR_P(name), BSTR_P(param));
 2456|     11|    }
 2457|     12|    mp_info(log, "Valid format: W[%%][xH[%%]][+x+y]\n");
  ------------------
  |  |   74|     12|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2458|     12|    return is_help ? M_OPT_EXIT : M_OPT_INVALID;
  ------------------
  |  |  533|      1|#define M_OPT_EXIT              -6
  ------------------
                  return is_help ? M_OPT_EXIT : M_OPT_INVALID;
  ------------------
  |  |  523|     11|#define M_OPT_INVALID           -3
  ------------------
  |  Branch (2458:12): [True: 1, False: 11]
  ------------------
 2459|    507|}
m_option.c:parse_imgfmt:
 2474|    962|{
 2475|    962|    if (param.len == 0)
  ------------------
  |  Branch (2475:9): [True: 0, False: 962]
  ------------------
 2476|      0|        return M_OPT_MISSING_PARAM;
  ------------------
  |  |  520|      0|#define M_OPT_MISSING_PARAM     -2
  ------------------
 2477|       |
 2478|    962|    if (!bstrcmp0(param, "help")) {
  ------------------
  |  Branch (2478:9): [True: 0, False: 962]
  ------------------
 2479|      0|        mp_info(log, "Available formats:");
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2480|      0|        char **list = mp_imgfmt_name_list();
 2481|      0|        for (int i = 0; list[i]; i++)
  ------------------
  |  Branch (2481:25): [True: 0, False: 0]
  ------------------
 2482|      0|            mp_info(log, " %s", list[i]);
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2483|      0|        mp_info(log, " no");
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2484|      0|        mp_info(log, "\n");
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2485|      0|        talloc_free(list);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 2486|      0|        return M_OPT_EXIT;
  ------------------
  |  |  533|      0|#define M_OPT_EXIT              -6
  ------------------
 2487|      0|    }
 2488|       |
 2489|    962|    unsigned int fmt = mp_imgfmt_from_name(param);
 2490|    962|    if (!fmt && !bstr_equals0(param, "no")) {
  ------------------
  |  Branch (2490:9): [True: 319, False: 643]
  |  Branch (2490:17): [True: 225, False: 94]
  ------------------
 2491|    225|        mp_err(log, "Option %.*s: unknown format name: '%.*s'\n",
  ------------------
  |  |   72|    900|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 225, False: 0]
  |  |  |  Branch (72:55): [True: 225, False: 0]
  |  |  ------------------
  ------------------
 2492|    225|               BSTR_P(name), BSTR_P(param));
 2493|    225|        return M_OPT_INVALID;
  ------------------
  |  |  523|    225|#define M_OPT_INVALID           -3
  ------------------
 2494|    225|    }
 2495|       |
 2496|    737|    if (dst)
  ------------------
  |  Branch (2496:9): [True: 737, False: 0]
  ------------------
 2497|    737|        *((int *)dst) = fmt;
 2498|       |
 2499|    737|    return 1;
 2500|    962|}
m_option.c:print_imgfmt:
 2503|     98|{
 2504|     98|    int fmt = *(int *)val;
 2505|     98|    return talloc_strdup(NULL, fmt ? mp_imgfmt_to_name(fmt) : "no");
  ------------------
  |  |   50|     98|#define talloc_strdup                   ta_xstrdup
  ------------------
                  return talloc_strdup(NULL, fmt ? mp_imgfmt_to_name(fmt) : "no");
  ------------------
  |  |  331|      0|#define mp_imgfmt_to_name(fmt) mp_imgfmt_to_name_buf((char[16]){0}, 16, (fmt))
  ------------------
  |  Branch (2505:32): [True: 0, False: 98]
  ------------------
 2506|     98|}
m_option.c:print_fourcc:
 2545|     45|{
 2546|     45|    unsigned int fourcc = *(unsigned int *)val;
 2547|     45|    return talloc_asprintf(NULL, "%08x", fourcc);
  ------------------
  |  |   52|     45|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|     45|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 2548|     45|}
m_option.c:parse_afmt:
 2563|    507|{
 2564|    507|    if (param.len == 0)
  ------------------
  |  Branch (2564:9): [True: 1, False: 506]
  ------------------
 2565|      1|        return M_OPT_MISSING_PARAM;
  ------------------
  |  |  520|      1|#define M_OPT_MISSING_PARAM     -2
  ------------------
 2566|       |
 2567|    506|    if (!bstrcmp0(param, "help")) {
  ------------------
  |  Branch (2567:9): [True: 1, False: 505]
  ------------------
 2568|      1|        mp_info(log, "Available formats:");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2569|     20|        for (int i = 1; i < AF_FORMAT_COUNT; i++)
  ------------------
  |  Branch (2569:25): [True: 19, False: 1]
  ------------------
 2570|     19|            mp_info(log, " %s", af_fmt_to_str(i));
  ------------------
  |  |   74|     19|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2571|      1|        mp_info(log, "\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2572|      1|        return M_OPT_EXIT;
  ------------------
  |  |  533|      1|#define M_OPT_EXIT              -6
  ------------------
 2573|      1|    }
 2574|       |
 2575|    505|    int fmt = 0;
 2576|  10.1k|    for (int i = 1; i < AF_FORMAT_COUNT; i++) {
  ------------------
  |  Branch (2576:21): [True: 9.59k, False: 505]
  ------------------
 2577|  9.59k|        if (bstr_equals0(param, af_fmt_to_str(i)))
  ------------------
  |  Branch (2577:13): [True: 447, False: 9.14k]
  ------------------
 2578|    447|            fmt = i;
 2579|  9.59k|    }
 2580|    505|    if (!fmt) {
  ------------------
  |  Branch (2580:9): [True: 58, False: 447]
  ------------------
 2581|     58|        mp_err(log, "Option %.*s: unknown format name: '%.*s'\n",
  ------------------
  |  |   72|    232|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 58, False: 0]
  |  |  |  Branch (72:55): [True: 58, False: 0]
  |  |  ------------------
  ------------------
 2582|     58|               BSTR_P(name), BSTR_P(param));
 2583|     58|        return M_OPT_INVALID;
  ------------------
  |  |  523|     58|#define M_OPT_INVALID           -3
  ------------------
 2584|     58|    }
 2585|       |
 2586|    447|    if (dst)
  ------------------
  |  Branch (2586:9): [True: 447, False: 0]
  ------------------
 2587|    447|        *((int *)dst) = fmt;
 2588|       |
 2589|    447|    return 1;
 2590|    505|}
m_option.c:print_afmt:
 2593|     65|{
 2594|     65|    int fmt = *(int *)val;
 2595|     65|    return talloc_strdup(NULL, fmt ? af_fmt_to_str(fmt) : "no");
  ------------------
  |  |   50|     65|#define talloc_strdup                   ta_xstrdup
  ------------------
  |  Branch (2595:32): [True: 0, False: 65]
  ------------------
 2596|     65|}
m_option.c:parse_channels:
 2611|  2.23k|{
 2612|  2.23k|    bool limited = opt->flags & M_OPT_CHANNELS_LIMITED;
  ------------------
  |  |  479|  2.23k|#define M_OPT_CHANNELS_LIMITED  (UINT64_C(1) << 56)
  ------------------
 2613|       |
 2614|  2.23k|    struct m_channels res = {0};
 2615|       |
 2616|  2.23k|    if (bstr_equals0(param, "help")) {
  ------------------
  |  Branch (2616:9): [True: 1, False: 2.23k]
  ------------------
 2617|      1|        mp_chmap_print_help(log);
 2618|      1|        if (!limited) {
  ------------------
  |  Branch (2618:13): [True: 1, False: 0]
  ------------------
 2619|      1|            mp_info(log, "\nOther values:\n"
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 2620|      1|                         "    auto-safe\n");
 2621|      1|        }
 2622|      1|        return M_OPT_EXIT;
  ------------------
  |  |  533|      1|#define M_OPT_EXIT              -6
  ------------------
 2623|      1|    }
 2624|       |
 2625|  2.23k|    bool auto_safe = bstr_equals0(param, "auto-safe");
 2626|  2.23k|    if (bstr_equals0(param, "auto") || bstr_equals0(param, "empty") || auto_safe) {
  ------------------
  |  Branch (2626:9): [True: 68, False: 2.16k]
  |  Branch (2626:40): [True: 66, False: 2.09k]
  |  Branch (2626:72): [True: 111, False: 1.98k]
  ------------------
 2627|    245|        if (limited) {
  ------------------
  |  Branch (2627:13): [True: 1, False: 244]
  ------------------
 2628|      1|            mp_err(log, "Disallowed parameter.\n");
  ------------------
  |  |   72|      1|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
 2629|      1|            return M_OPT_INVALID;
  ------------------
  |  |  523|      1|#define M_OPT_INVALID           -3
  ------------------
 2630|      1|        }
 2631|    244|        param.len = 0;
 2632|    244|        res.set = true;
 2633|    244|        res.auto_safe = auto_safe;
 2634|    244|    }
 2635|       |
 2636|  4.43k|    while (param.len) {
  ------------------
  |  Branch (2636:12): [True: 2.43k, False: 2.00k]
  ------------------
 2637|  2.43k|        bstr item;
 2638|  2.43k|        if (limited) {
  ------------------
  |  Branch (2638:13): [True: 793, False: 1.63k]
  ------------------
 2639|    793|            item = param;
 2640|    793|            param.len = 0;
 2641|  1.63k|        } else {
 2642|  1.63k|            bstr_split_tok(param, ",", &item, &param);
 2643|  1.63k|        }
 2644|       |
 2645|  2.43k|        struct mp_chmap map = {0};
 2646|  2.43k|        if (!mp_chmap_from_str(&map, item) || !mp_chmap_is_valid(&map)) {
  ------------------
  |  Branch (2646:13): [True: 226, False: 2.20k]
  |  Branch (2646:47): [True: 3, False: 2.20k]
  ------------------
 2647|    229|            mp_err(log, "Invalid channel layout: %.*s\n", BSTR_P(item));
  ------------------
  |  |   72|    458|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 229, False: 0]
  |  |  ------------------
  ------------------
 2648|    229|            talloc_free(res.chmaps);
  ------------------
  |  |   47|    229|#define talloc_free                     ta_free
  ------------------
 2649|    229|            return M_OPT_INVALID;
  ------------------
  |  |  523|    229|#define M_OPT_INVALID           -3
  ------------------
 2650|    229|        }
 2651|       |
 2652|  2.20k|        MP_TARRAY_APPEND(NULL, res.chmaps, res.num_chmaps, map);
  ------------------
  |  |  105|  2.20k|    do {                                            \
  |  |  106|  2.20k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  2.20k|    do {                                            \
  |  |  |  |   97|  2.20k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  2.20k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  2.20k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  2.20k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 1.76k, False: 434]
  |  |  |  |  ------------------
  |  |  |  |   99|  2.20k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  1.76k|    do {                                                        \
  |  |  |  |  |  |   89|  1.76k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  1.76k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  1.76k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  1.76k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  1.76k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  1.76k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  1.76k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  2.20k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  2.20k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  2.20k|        (idxvar)++;                                 \
  |  |  109|  2.20k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 2653|  2.20k|        res.set = true;
 2654|  2.20k|    }
 2655|       |
 2656|  2.00k|    if (dst) {
  ------------------
  |  Branch (2656:9): [True: 2.00k, False: 0]
  ------------------
 2657|  2.00k|        opt->type->free(dst);
 2658|  2.00k|        *(struct m_channels *)dst = res;
 2659|  2.00k|    } else {
 2660|      0|        talloc_free(res.chmaps);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 2661|      0|    }
 2662|       |
 2663|  2.00k|    return 1;
 2664|  2.23k|}
m_option.c:print_channels:
 2667|    147|{
 2668|    147|    const struct m_channels *ch = val;
 2669|    147|    if (!ch->set)
  ------------------
  |  Branch (2669:9): [True: 45, False: 102]
  ------------------
 2670|     45|        return talloc_strdup(NULL, "");
  ------------------
  |  |   50|     45|#define talloc_strdup                   ta_xstrdup
  ------------------
 2671|    102|    if (ch->auto_safe)
  ------------------
  |  Branch (2671:9): [True: 45, False: 57]
  ------------------
 2672|     45|        return talloc_strdup(NULL, "auto-safe");
  ------------------
  |  |   50|     45|#define talloc_strdup                   ta_xstrdup
  ------------------
 2673|     57|    if (ch->num_chmaps > 0) {
  ------------------
  |  Branch (2673:9): [True: 57, False: 0]
  ------------------
 2674|     57|        char *res = talloc_strdup(NULL, "");
  ------------------
  |  |   50|     57|#define talloc_strdup                   ta_xstrdup
  ------------------
 2675|    114|        for (int n = 0; n < ch->num_chmaps; n++) {
  ------------------
  |  Branch (2675:25): [True: 57, False: 57]
  ------------------
 2676|     57|            if (n > 0)
  ------------------
  |  Branch (2676:17): [True: 0, False: 57]
  ------------------
 2677|      0|                res = talloc_strdup_append(res, ",");
  ------------------
  |  |   57|      0|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
 2678|     57|            res = talloc_strdup_append(res, mp_chmap_to_str(&ch->chmaps[n]));
  ------------------
  |  |   57|     57|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
                          res = talloc_strdup_append(res, mp_chmap_to_str(&ch->chmaps[n]));
  ------------------
  |  |  133|     57|#define mp_chmap_to_str(m) mp_chmap_to_str_(m, MP_NUM_CHANNELS * 4)
  |  |  ------------------
  |  |  |  |  132|     57|#define mp_chmap_to_str_(m, sz) mp_chmap_to_str_buf((char[sz]){0}, sz, (m))
  |  |  ------------------
  ------------------
 2679|     57|        }
 2680|     57|        return res;
 2681|     57|    }
 2682|      0|    return talloc_strdup(NULL, "auto");
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
 2683|     57|}
m_option.c:copy_channels:
 2696|   180k|{
 2697|   180k|    if (!(dst && src))
  ------------------
  |  Branch (2697:11): [True: 180k, False: 0]
  |  Branch (2697:18): [True: 180k, False: 0]
  ------------------
 2698|      0|        return;
 2699|       |
 2700|   180k|    struct m_channels *ch = dst;
 2701|   180k|    free_channels(dst);
 2702|   180k|    *ch = *(struct m_channels *)src;
 2703|   180k|    ch->chmaps =
 2704|   180k|        talloc_memdup(NULL, ch->chmaps, sizeof(ch->chmaps[0]) * ch->num_chmaps);
  ------------------
  |  |   49|   180k|#define talloc_memdup                   ta_xmemdup
  |  |  ------------------
  |  |  |  |  157|   180k|#define ta_xmemdup(...)         ta_dbg_set_loc(ta_xmemdup(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|   180k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|   180k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|   180k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2705|   180k|}
m_option.c:free_channels:
 2686|   361k|{
 2687|   361k|    if (!src)
  ------------------
  |  Branch (2687:9): [True: 0, False: 361k]
  ------------------
 2688|      0|        return;
 2689|       |
 2690|   361k|    struct m_channels *ch = src;
 2691|   361k|    talloc_free(ch->chmaps);
  ------------------
  |  |   47|   361k|#define talloc_free                     ta_free
  ------------------
 2692|   361k|    *ch = (struct m_channels){0};
 2693|   361k|}
m_option.c:channels_equal:
 2708|  1.43k|{
 2709|  1.43k|    struct m_channels *ca = a;
 2710|  1.43k|    struct m_channels *cb = b;
 2711|       |
 2712|  1.43k|    if (ca->set         != cb->set ||
  ------------------
  |  Branch (2712:9): [True: 78, False: 1.35k]
  ------------------
 2713|  1.43k|        ca->auto_safe   != cb->auto_safe ||
  ------------------
  |  Branch (2713:9): [True: 181, False: 1.17k]
  ------------------
 2714|  1.43k|        ca->num_chmaps  != cb->num_chmaps)
  ------------------
  |  Branch (2714:9): [True: 73, False: 1.10k]
  ------------------
 2715|    332|        return false;
 2716|       |
 2717|  1.89k|    for (int n = 0; n < ca->num_chmaps; n++) {
  ------------------
  |  Branch (2717:21): [True: 1.18k, False: 714]
  ------------------
 2718|  1.18k|        if (!mp_chmap_equals(&ca->chmaps[n], &cb->chmaps[n]))
  ------------------
  |  Branch (2718:13): [True: 391, False: 790]
  ------------------
 2719|    391|            return false;
 2720|  1.18k|    }
 2721|       |
 2722|    714|    return true;
 2723|  1.10k|}
m_option.c:parse_time:
 2774|   182k|{
 2775|   182k|    if (param.len == 0)
  ------------------
  |  Branch (2775:9): [True: 1, False: 182k]
  ------------------
 2776|      1|        return M_OPT_MISSING_PARAM;
  ------------------
  |  |  520|      1|#define M_OPT_MISSING_PARAM     -2
  ------------------
 2777|       |
 2778|   182k|    double time = MP_NOPTS_VALUE;
  ------------------
  |  |   38|   182k|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
 2779|   182k|    if (HAS_NOPTS(opt) && bstr_equals0(param, "no")) {
  ------------------
  |  | 2770|   365k|#define HAS_NOPTS(opt) ((opt)->flags & M_OPT_ALLOW_NO)
  |  |  ------------------
  |  |  |  |  476|   182k|#define M_OPT_ALLOW_NO          (UINT64_C(1) << 57)
  |  |  ------------------
  |  |  |  Branch (2770:24): [True: 592, False: 182k]
  |  |  ------------------
  ------------------
  |  Branch (2779:27): [True: 422, False: 170]
  ------------------
 2780|       |        // nothing
 2781|   182k|    } else if (!parse_timestring(param, &time, 0)) {
  ------------------
  |  Branch (2781:16): [True: 32, False: 182k]
  ------------------
 2782|     32|        mp_err(log, "Option %.*s: invalid time: '%.*s'\n",
  ------------------
  |  |   72|    128|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 32, False: 0]
  |  |  |  Branch (72:55): [True: 32, False: 0]
  |  |  ------------------
  ------------------
 2783|     32|               BSTR_P(name), BSTR_P(param));
 2784|     32|        return M_OPT_INVALID;
  ------------------
  |  |  523|     32|#define M_OPT_INVALID           -3
  ------------------
 2785|     32|    }
 2786|       |
 2787|   182k|    if (dst)
  ------------------
  |  Branch (2787:9): [True: 182k, False: 0]
  ------------------
 2788|   182k|        *(double *)dst = time;
 2789|   182k|    return 1;
 2790|   182k|}
m_option.c:parse_timestring:
 2736|   183k|{
 2737|   183k|    int len;
 2738|   183k|    unsigned h, m;
 2739|   183k|    double s;
 2740|   183k|    *time = 0; /* ensure initialization for error cases */
 2741|   183k|    bool neg = bstr_eatstart0(&str, "-");
 2742|   183k|    if (!neg)
  ------------------
  |  Branch (2742:9): [True: 98.0k, False: 85.3k]
  ------------------
 2743|  98.0k|        bstr_eatstart0(&str, "+");
 2744|   183k|    bool sci = bstr_find0(str, "e-") >= 0 || bstr_find0(str, "e+") >= 0;
  ------------------
  |  Branch (2744:16): [True: 88, False: 183k]
  |  Branch (2744:46): [True: 13, False: 183k]
  ------------------
 2745|       |    /* non-scientific notation timestamps shouldn't contain anymore +/- after this point */
 2746|   183k|    if (!sci && (bstrchr(str, '-') >= 0 || bstrchr(str, '+') >= 0))
  ------------------
  |  Branch (2746:9): [True: 183k, False: 101]
  |  Branch (2746:18): [True: 12, False: 183k]
  |  Branch (2746:44): [True: 9, False: 183k]
  ------------------
 2747|     21|        return 0;
 2748|   183k|    if (bstr_sscanf(str, "%u:%u:%lf%n", &h, &m, &s, &len) >= 3) {
  ------------------
  |  Branch (2748:9): [True: 109, False: 183k]
  ------------------
 2749|    109|        if (m >= 60 || s >= 60)
  ------------------
  |  Branch (2749:13): [True: 38, False: 71]
  |  Branch (2749:24): [True: 1, False: 70]
  ------------------
 2750|     39|            return 0; /* minutes or seconds are out of range */
 2751|     70|        *time = 3600.0 * h + 60 * m + s;
 2752|   183k|    } else if (bstr_sscanf(str, "%u:%lf%n", &m, &s, &len) >= 2) {
  ------------------
  |  Branch (2752:16): [True: 71, False: 183k]
  ------------------
 2753|     71|        if (s >= 60)
  ------------------
  |  Branch (2753:13): [True: 1, False: 70]
  ------------------
 2754|      1|            return 0; /* seconds are out of range */
 2755|     70|        *time = 60.0 * m + s;
 2756|   183k|    } else if (bstr_sscanf(str, "%lf%n", &s, &len) >= 1) {
  ------------------
  |  Branch (2756:16): [True: 183k, False: 103]
  ------------------
 2757|   183k|        *time = s;
 2758|   183k|    } else {
 2759|    103|        return 0;  /* unsupported time format */
 2760|    103|    }
 2761|   183k|    if (len < str.len && str.start[len] != endchar)
  ------------------
  |  Branch (2761:9): [True: 29, False: 183k]
  |  Branch (2761:26): [True: 29, False: 0]
  ------------------
 2762|     29|        return 0;  /* invalid extra characters at the end */
 2763|   183k|    if (!isfinite(*time))
  ------------------
  |  Branch (2763:9): [True: 1, False: 183k]
  ------------------
 2764|      1|        return 0;
 2765|   183k|    if (neg)
  ------------------
  |  Branch (2765:9): [True: 85.3k, False: 97.9k]
  ------------------
 2766|  85.3k|        *time = -*time;
 2767|   183k|    return len;
 2768|   183k|}
m_option.c:print_time:
 2793|     52|{
 2794|     52|    double pts = *(double *)val;
 2795|     52|    if (pts == MP_NOPTS_VALUE && HAS_NOPTS(opt))
  ------------------
  |  |   38|    104|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
                  if (pts == MP_NOPTS_VALUE && HAS_NOPTS(opt))
  ------------------
  |  | 2770|     34|#define HAS_NOPTS(opt) ((opt)->flags & M_OPT_ALLOW_NO)
  |  |  ------------------
  |  |  |  |  476|     34|#define M_OPT_ALLOW_NO          (UINT64_C(1) << 57)
  |  |  ------------------
  |  |  |  Branch (2770:24): [True: 34, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2795:9): [True: 34, False: 18]
  ------------------
 2796|     34|        return talloc_strdup(NULL, "no"); // symmetry with parsing
  ------------------
  |  |   50|     34|#define talloc_strdup                   ta_xstrdup
  ------------------
 2797|     18|    return talloc_asprintf(NULL, "%f", pts);
  ------------------
  |  |   52|     18|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|     18|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 2798|     52|}
m_option.c:pretty_print_time:
 2801|    112|{
 2802|    112|    double pts = *(double *)val;
 2803|    112|    if (pts == MP_NOPTS_VALUE && HAS_NOPTS(opt))
  ------------------
  |  |   38|    224|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
                  if (pts == MP_NOPTS_VALUE && HAS_NOPTS(opt))
  ------------------
  |  | 2770|     76|#define HAS_NOPTS(opt) ((opt)->flags & M_OPT_ALLOW_NO)
  |  |  ------------------
  |  |  |  |  476|     76|#define M_OPT_ALLOW_NO          (UINT64_C(1) << 57)
  |  |  ------------------
  |  |  |  Branch (2770:24): [True: 76, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (2803:9): [True: 76, False: 36]
  ------------------
 2804|     76|        return talloc_strdup(NULL, "no"); // symmetry with parsing
  ------------------
  |  |   50|     76|#define talloc_strdup                   ta_xstrdup
  ------------------
 2805|     36|    return mp_format_time(pts, false);
 2806|    112|}
m_option.c:parse_rel_time:
 2848|  1.33k|{
 2849|  1.33k|    struct m_rel_time t = {0};
 2850|       |
 2851|  1.33k|    if (param.len == 0)
  ------------------
  |  Branch (2851:9): [True: 1, False: 1.33k]
  ------------------
 2852|      1|        return M_OPT_MISSING_PARAM;
  ------------------
  |  |  520|      1|#define M_OPT_MISSING_PARAM     -2
  ------------------
 2853|       |
 2854|  1.33k|    if (bstr_equals0(param, "none")) {
  ------------------
  |  Branch (2854:9): [True: 66, False: 1.27k]
  ------------------
 2855|     66|        t.type = REL_TIME_NONE;
 2856|     66|        goto out;
 2857|     66|    }
 2858|       |
 2859|       |    // Percent pos
 2860|  1.27k|    if (bstr_endswith0(param, "%")) {
  ------------------
  |  Branch (2860:9): [True: 149, False: 1.12k]
  ------------------
 2861|    149|        double percent = bstrtod(bstr_splice(param, 0, -1), &param);
 2862|    149|        if (param.len == 0 && percent >= 0 && percent <= 100) {
  ------------------
  |  Branch (2862:13): [True: 77, False: 72]
  |  Branch (2862:31): [True: 76, False: 1]
  |  Branch (2862:47): [True: 75, False: 1]
  ------------------
 2863|     75|            t.type = REL_TIME_PERCENT;
 2864|     75|            t.pos = percent;
 2865|     75|            goto out;
 2866|     75|        }
 2867|    149|    }
 2868|       |
 2869|       |    // Chapter pos
 2870|  1.19k|    if (bstr_startswith0(param, "#")) {
  ------------------
  |  Branch (2870:9): [True: 249, False: 946]
  ------------------
 2871|    249|        int chapter = bstrtoll(bstr_cut(param, 1), &param, 10);
 2872|    249|        if (param.len == 0 && chapter >= 1) {
  ------------------
  |  Branch (2872:13): [True: 172, False: 77]
  |  Branch (2872:31): [True: 134, False: 38]
  ------------------
 2873|    134|            t.type = REL_TIME_CHAPTER;
 2874|    134|            t.pos = chapter - 1;
 2875|    134|            goto out;
 2876|    134|        }
 2877|    249|    }
 2878|       |
 2879|  1.06k|    double time;
 2880|  1.06k|    if (parse_timestring(param, &time, 0)) {
  ------------------
  |  Branch (2880:9): [True: 899, False: 162]
  ------------------
 2881|    899|        if (bstr_startswith0(param, "+") || bstr_startswith0(param, "-")) {
  ------------------
  |  Branch (2881:13): [True: 101, False: 798]
  |  Branch (2881:45): [True: 258, False: 540]
  ------------------
 2882|    359|            t.type = REL_TIME_RELATIVE;
 2883|    540|        } else {
 2884|    540|            t.type = REL_TIME_ABSOLUTE;
 2885|    540|        }
 2886|    899|        t.pos = time;
 2887|    899|        goto out;
 2888|    899|    }
 2889|       |
 2890|    162|    mp_err(log, "Option %.*s: invalid time or position: '%.*s'\n",
  ------------------
  |  |   72|    648|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 162, False: 0]
  |  |  |  Branch (72:55): [True: 162, False: 0]
  |  |  ------------------
  ------------------
 2891|    162|           BSTR_P(name), BSTR_P(param));
 2892|    162|    return M_OPT_INVALID;
  ------------------
  |  |  523|    162|#define M_OPT_INVALID           -3
  ------------------
 2893|       |
 2894|  1.17k|out:
 2895|  1.17k|    if (dst)
  ------------------
  |  Branch (2895:9): [True: 1.17k, False: 0]
  ------------------
 2896|  1.17k|        *(struct m_rel_time *)dst = t;
 2897|  1.17k|    return 1;
 2898|  1.06k|}
m_option.c:print_rel_time:
 2901|     68|{
 2902|     68|    const struct m_rel_time *t = val;
 2903|     68|    switch(t->type) {
  ------------------
  |  Branch (2903:12): [True: 68, False: 0]
  ------------------
 2904|      0|    case REL_TIME_ABSOLUTE:
  ------------------
  |  Branch (2904:5): [True: 0, False: 68]
  ------------------
 2905|      0|        return talloc_asprintf(NULL, "%g", t->pos);
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 2906|      0|    case REL_TIME_RELATIVE:
  ------------------
  |  Branch (2906:5): [True: 0, False: 68]
  ------------------
 2907|      0|        return talloc_asprintf(NULL, "%+g", t->pos);
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 2908|      0|    case REL_TIME_CHAPTER:
  ------------------
  |  Branch (2908:5): [True: 0, False: 68]
  ------------------
 2909|      0|        return talloc_asprintf(NULL, "#%g", t->pos + 1);
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 2910|      0|    case REL_TIME_PERCENT:
  ------------------
  |  Branch (2910:5): [True: 0, False: 68]
  ------------------
 2911|      0|        return talloc_asprintf(NULL, "%g%%", t->pos);
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 2912|     68|    }
 2913|     68|    return talloc_strdup(NULL, "none");
  ------------------
  |  |   50|     68|#define talloc_strdup                   ta_xstrdup
  ------------------
 2914|     68|}
m_option.c:rel_time_equal:
 2917|  1.19k|{
 2918|  1.19k|    struct m_rel_time *ta = a;
 2919|  1.19k|    struct m_rel_time *tb = b;
 2920|  1.19k|    return ta->type == tb->type && ta->pos == tb->pos;
  ------------------
  |  Branch (2920:12): [True: 824, False: 368]
  |  Branch (2920:36): [True: 524, False: 300]
  ------------------
 2921|  1.19k|}
m_option.c:parse_obj_settings_list:
 3398|  56.4k|{
 3399|  56.4k|    m_obj_settings_t *res = NULL;
 3400|  56.4k|    int op = OP_NONE;
  ------------------
  |  | 1318|  56.4k|#define OP_NONE 0
  ------------------
 3401|  56.4k|    bool *mark_del = NULL;
 3402|  56.4k|    int num_items = obj_settings_list_num_items(dst ? VAL(dst) : 0);
  ------------------
  |  | 2936|  56.4k|#define VAL(x) (*(m_obj_settings_t **)(x))
  ------------------
  |  Branch (3402:49): [True: 56.4k, False: 0]
  ------------------
 3403|  56.4k|    const struct m_obj_list *ol = opt->priv;
 3404|  56.4k|    int ret = 1;
 3405|       |
 3406|  56.4k|    mp_assert(opt->priv);
  ------------------
  |  |   41|  56.4k|#define mp_assert assert
  ------------------
 3407|       |
 3408|  56.4k|    if (bstr_endswith0(name, "-add")) {
  ------------------
  |  Branch (3408:9): [True: 1.05k, False: 55.3k]
  ------------------
 3409|  1.05k|        op = OP_ADD;
  ------------------
  |  | 1319|  1.05k|#define OP_ADD 1
  ------------------
 3410|  55.3k|    } else if (bstr_endswith0(name, "-append")) {
  ------------------
  |  Branch (3410:16): [True: 68, False: 55.2k]
  ------------------
 3411|     68|        op = OP_APPEND;
  ------------------
  |  | 1324|     68|#define OP_APPEND 6
  ------------------
 3412|  55.2k|    } else if (bstr_endswith0(name, "-set")) {
  ------------------
  |  Branch (3412:16): [True: 75, False: 55.2k]
  ------------------
 3413|     75|        op = OP_NONE;
  ------------------
  |  | 1318|     75|#define OP_NONE 0
  ------------------
 3414|  55.2k|    } else if (bstr_endswith0(name, "-pre")) {
  ------------------
  |  Branch (3414:16): [True: 1.07k, False: 54.1k]
  ------------------
 3415|  1.07k|        op = OP_PRE;
  ------------------
  |  | 1320|  1.07k|#define OP_PRE 2
  ------------------
 3416|  54.1k|    } else if (bstr_endswith0(name, "-remove")) {
  ------------------
  |  Branch (3416:16): [True: 989, False: 53.1k]
  ------------------
 3417|    989|        op = OP_REMOVE;
  ------------------
  |  | 1325|    989|#define OP_REMOVE 7
  ------------------
 3418|  53.1k|    } else if (bstr_endswith0(name, "-clr")) {
  ------------------
  |  Branch (3418:16): [True: 67, False: 53.0k]
  ------------------
 3419|     67|        op = OP_CLR;
  ------------------
  |  | 1321|     67|#define OP_CLR 3
  ------------------
 3420|  53.0k|    } else if (bstr_endswith0(name, "-toggle")) {
  ------------------
  |  Branch (3420:16): [True: 872, False: 52.2k]
  ------------------
 3421|    872|        op = OP_TOGGLE;
  ------------------
  |  | 1323|    872|#define OP_TOGGLE 5
  ------------------
 3422|  52.2k|    } else if (bstr_endswith0(name, "-help")) {
  ------------------
  |  Branch (3422:16): [True: 4, False: 52.2k]
  ------------------
 3423|      4|        mp_err(log, "Option %s:\n"
  ------------------
  |  |   72|      4|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
 3424|      4|                "Supported operations are:\n"
 3425|      4|                "  %s-set\n"
 3426|      4|                " Overwrite the old list with the given list\n\n"
 3427|      4|                "  %s-append\n"
 3428|      4|                " Append the given item to the current list\n\n"
 3429|      4|                "  %s-add\n"
 3430|      4|                " Append the given list to the current list\n\n"
 3431|      4|                "  %s-pre\n"
 3432|      4|                " Prepend the given list to the current list\n\n"
 3433|      4|                "  %s-remove\n"
 3434|      4|                " Remove the given item from the current list\n\n"
 3435|      4|                "  %s-toggle\n"
 3436|      4|                " Add the item to the list, or remove it if it's already added.\n\n"
 3437|      4|                "  %s-clr\n"
 3438|      4|                " Clear the current list.\n\n",
 3439|      4|                opt->name, opt->name, opt->name, opt->name, opt->name,
 3440|      4|                opt->name, opt->name, opt->name);
 3441|       |
 3442|      4|        ret = M_OPT_EXIT;
  ------------------
  |  |  533|      4|#define M_OPT_EXIT              -6
  ------------------
 3443|      4|        goto done;
 3444|      4|    }
 3445|       |
 3446|  56.4k|    if (!bstrcmp0(param, "help")) {
  ------------------
  |  Branch (3446:9): [True: 6, False: 56.4k]
  ------------------
 3447|      6|        mp_info(log, "Available %s:\n", ol->description);
  ------------------
  |  |   74|      6|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 3448|     37|        for (int n = 0; ; n++) {
 3449|     37|            struct m_obj_desc desc;
 3450|     37|            if (!ol->get_desc(&desc, n))
  ------------------
  |  Branch (3450:17): [True: 6, False: 31]
  ------------------
 3451|      6|                break;
 3452|     31|            if (!desc.hidden) {
  ------------------
  |  Branch (3452:17): [True: 28, False: 3]
  ------------------
 3453|     28|                mp_info(log, "  %-16s %s\n",
  ------------------
  |  |   74|     28|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 3454|     28|                       desc.name, desc.description);
 3455|     28|            }
 3456|     31|        }
 3457|      6|        mp_info(log, "\n");
  ------------------
  |  |   74|      6|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 3458|      6|        if (ol->print_help_list)
  ------------------
  |  Branch (3458:13): [True: 3, False: 3]
  ------------------
 3459|      3|            ol->print_help_list(log);
 3460|      6|        if (!ol->use_global_options) {
  ------------------
  |  Branch (3460:13): [True: 2, False: 4]
  ------------------
 3461|      2|            mp_info(log, "Get help on individual entries via: --%s=entry=help\n",
  ------------------
  |  |   74|      2|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 3462|      2|                    opt->name);
 3463|      2|        }
 3464|      6|        ret = M_OPT_EXIT;
  ------------------
  |  |  533|      6|#define M_OPT_EXIT              -6
  ------------------
 3465|      6|        goto done;
 3466|      6|    }
 3467|       |
 3468|  56.4k|    if (op == OP_CLR) {
  ------------------
  |  | 1321|  56.4k|#define OP_CLR 3
  ------------------
  |  Branch (3468:9): [True: 67, False: 56.3k]
  ------------------
 3469|     67|        if (param.len) {
  ------------------
  |  Branch (3469:13): [True: 1, False: 66]
  ------------------
 3470|      1|            mp_err(log, "Option %.*s: -clr does not take an argument.\n",
  ------------------
  |  |   72|      2|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 1, False: 0]
  |  |  ------------------
  ------------------
 3471|      1|                   BSTR_P(name));
 3472|      1|            ret = M_OPT_INVALID;
  ------------------
  |  |  523|      1|#define M_OPT_INVALID           -3
  ------------------
 3473|      1|            goto done;
 3474|      1|        }
 3475|     66|        if (dst)
  ------------------
  |  Branch (3475:13): [True: 66, False: 0]
  ------------------
 3476|     66|            free_obj_settings_list(dst);
 3477|     66|        ret = 0;
 3478|     66|        goto done;
 3479|  56.3k|    } else if (op == OP_REMOVE) {
  ------------------
  |  | 1325|  56.3k|#define OP_REMOVE 7
  ------------------
  |  Branch (3479:16): [True: 989, False: 55.3k]
  ------------------
 3480|    989|        mark_del = talloc_zero_array(NULL, bool, num_items + 1);
  ------------------
  |  |   30|    989|#define talloc_zero_array               ta_xznew_array
  |  |  ------------------
  |  |  |  |  136|    989|#define ta_xznew_array(...)             ta_oom_g(ta_znew_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    989|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3481|    989|    }
 3482|       |
 3483|  56.3k|    if (op != OP_NONE && param.len == 0) {
  ------------------
  |  | 1318|   112k|#define OP_NONE 0
  ------------------
  |  Branch (3483:9): [True: 4.05k, False: 52.2k]
  |  Branch (3483:26): [True: 1, False: 4.05k]
  ------------------
 3484|      1|        ret = M_OPT_MISSING_PARAM;
  ------------------
  |  |  520|      1|#define M_OPT_MISSING_PARAM     -2
  ------------------
 3485|      1|        goto done;
 3486|      1|    }
 3487|       |
 3488|   131k|    while (param.len > 0) {
  ------------------
  |  Branch (3488:12): [True: 76.5k, False: 55.4k]
  ------------------
 3489|  76.5k|        int r = 0;
 3490|  76.5k|        if (op == OP_REMOVE)
  ------------------
  |  | 1325|  76.5k|#define OP_REMOVE 7
  ------------------
  |  Branch (3490:13): [True: 2.49k, False: 74.0k]
  ------------------
 3491|  2.49k|            r = parse_obj_settings_del(log, name, &param, dst, mark_del);
 3492|  76.5k|        if (r == 0) {
  ------------------
  |  Branch (3492:13): [True: 75.3k, False: 1.25k]
  ------------------
 3493|  75.3k|            r = parse_obj_settings(log, name, op, &param, ol, dst ? &res : NULL);
  ------------------
  |  Branch (3493:63): [True: 75.3k, False: 0]
  ------------------
 3494|  75.3k|        }
 3495|  76.5k|        if (r < 0) {
  ------------------
  |  Branch (3495:13): [True: 871, False: 75.6k]
  ------------------
 3496|    871|            free_obj_settings_list(&res);
 3497|    871|            ret = r;
 3498|    871|            goto done;
 3499|    871|        }
 3500|  75.6k|        if (param.len > 0) {
  ------------------
  |  Branch (3500:13): [True: 23.3k, False: 52.3k]
  ------------------
 3501|  23.3k|            const char sep[2] = {OPTION_LIST_SEPARATOR, 0};
  ------------------
  |  |  632|  23.3k|#define OPTION_LIST_SEPARATOR ','
  ------------------
 3502|  23.3k|            if (!bstr_eatstart0(&param, sep)) {
  ------------------
  |  Branch (3502:17): [True: 46, False: 23.3k]
  ------------------
 3503|     46|                free_obj_settings_list(&res);
 3504|     46|                ret = M_OPT_INVALID;
  ------------------
  |  |  523|     46|#define M_OPT_INVALID           -3
  ------------------
 3505|     46|                goto done;
 3506|     46|            }
 3507|  23.3k|            if (param.len == 0) {
  ------------------
  |  Branch (3507:17): [True: 906, False: 22.4k]
  ------------------
 3508|    906|                if (!ol->allow_trailer) {
  ------------------
  |  Branch (3508:21): [True: 5, False: 901]
  ------------------
 3509|      5|                    free_obj_settings_list(&res);
 3510|      5|                    ret = M_OPT_INVALID;
  ------------------
  |  |  523|      5|#define M_OPT_INVALID           -3
  ------------------
 3511|      5|                    goto done;
 3512|      5|                }
 3513|    901|                if (dst) {
  ------------------
  |  Branch (3513:21): [True: 901, False: 0]
  ------------------
 3514|    901|                    m_obj_settings_t item = {
 3515|    901|                        .name = talloc_strdup(NULL, ""),
  ------------------
  |  |   50|    901|#define talloc_strdup                   ta_xstrdup
  ------------------
 3516|    901|                    };
 3517|    901|                    if (!obj_settings_list_insert_at(log, &res, -1, &item))
  ------------------
  |  Branch (3517:25): [True: 28, False: 873]
  ------------------
 3518|     28|                        obj_setting_free(&item);
 3519|    901|                }
 3520|    901|            }
 3521|  23.3k|        }
 3522|  75.6k|    }
 3523|       |
 3524|  55.4k|    if (op != OP_NONE && res && res[0].name && res[1].name) {
  ------------------
  |  | 1318|   110k|#define OP_NONE 0
  ------------------
  |  Branch (3524:9): [True: 4.00k, False: 51.4k]
  |  Branch (3524:26): [True: 3.24k, False: 760]
  |  Branch (3524:33): [True: 3.24k, False: 0]
  |  Branch (3524:48): [True: 1.07k, False: 2.16k]
  ------------------
 3525|  1.07k|        if (op == OP_APPEND) {
  ------------------
  |  | 1324|  1.07k|#define OP_APPEND 6
  ------------------
  |  Branch (3525:13): [True: 1, False: 1.07k]
  ------------------
 3526|      1|            mp_err(log, "Option %.*s: -append takes only 1 item (no ',').\n",
  ------------------
  |  |   72|      2|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 1, False: 0]
  |  |  ------------------
  ------------------
 3527|      1|                   BSTR_P(name));
 3528|      1|            free_obj_settings_list(&res);
 3529|      1|            ret = M_OPT_INVALID;
  ------------------
  |  |  523|      1|#define M_OPT_INVALID           -3
  ------------------
 3530|      1|            goto done;
 3531|      1|        }
 3532|  1.07k|    }
 3533|       |
 3534|  55.4k|    if (dst) {
  ------------------
  |  Branch (3534:9): [True: 55.4k, False: 0]
  ------------------
 3535|  55.4k|        m_obj_settings_t *list = VAL(dst);
  ------------------
  |  | 2936|  55.4k|#define VAL(x) (*(m_obj_settings_t **)(x))
  ------------------
 3536|  55.4k|        if (op == OP_PRE) {
  ------------------
  |  | 1320|  55.4k|#define OP_PRE 2
  ------------------
  |  Branch (3536:13): [True: 1.06k, False: 54.3k]
  ------------------
 3537|  1.06k|            int prepend_counter = 0;
 3538|  3.57k|            for (int n = 0; res && res[n].name; n++) {
  ------------------
  |  Branch (3538:29): [True: 3.57k, False: 0]
  |  Branch (3538:36): [True: 2.51k, False: 1.06k]
  ------------------
 3539|  2.51k|                int label = obj_settings_list_find_by_label0(list, res[n].label);
 3540|  2.51k|                if (label < 0) {
  ------------------
  |  Branch (3540:21): [True: 2.35k, False: 153]
  ------------------
 3541|  2.35k|                    if (!obj_settings_list_insert_at(log, &list, prepend_counter, &res[n]))
  ------------------
  |  Branch (3541:25): [True: 418, False: 1.93k]
  ------------------
 3542|    418|                        obj_setting_free(&res[n]);
 3543|  2.35k|                    prepend_counter++;
 3544|  2.35k|                } else {
 3545|       |                    // Prefer replacement semantics, instead of actually
 3546|       |                    // prepending.
 3547|    153|                    obj_setting_free(&list[label]);
 3548|    153|                    list[label] = res[n];
 3549|    153|                }
 3550|  2.51k|            }
 3551|  1.06k|            talloc_free(res);
  ------------------
  |  |   47|  1.06k|#define talloc_free                     ta_free
  ------------------
 3552|  54.3k|        } else if (op == OP_ADD || op == OP_APPEND) {
  ------------------
  |  | 1319|   108k|#define OP_ADD 1
  ------------------
                      } else if (op == OP_ADD || op == OP_APPEND) {
  ------------------
  |  | 1324|  53.2k|#define OP_APPEND 6
  ------------------
  |  Branch (3552:20): [True: 1.05k, False: 53.2k]
  |  Branch (3552:36): [True: 67, False: 53.2k]
  ------------------
 3553|  7.21k|            for (int n = 0; res && res[n].name; n++) {
  ------------------
  |  Branch (3553:29): [True: 7.21k, False: 0]
  |  Branch (3553:36): [True: 6.09k, False: 1.12k]
  ------------------
 3554|  6.09k|                int label = obj_settings_list_find_by_label0(list, res[n].label);
 3555|  6.09k|                if (label < 0) {
  ------------------
  |  Branch (3555:21): [True: 5.97k, False: 120]
  ------------------
 3556|  5.97k|                    if (!obj_settings_list_insert_at(log, &list, -1, &res[n]))
  ------------------
  |  Branch (3556:25): [True: 1.15k, False: 4.81k]
  ------------------
 3557|  1.15k|                        obj_setting_free(&res[n]);
 3558|  5.97k|                } else {
 3559|       |                    // Prefer replacement semantics, instead of actually
 3560|       |                    // appending.
 3561|    120|                    obj_setting_free(&list[label]);
 3562|    120|                    list[label] = res[n];
 3563|    120|                }
 3564|  6.09k|            }
 3565|  1.12k|            talloc_free(res);
  ------------------
  |  |   47|  1.12k|#define talloc_free                     ta_free
  ------------------
 3566|  53.2k|        } else if (op == OP_TOGGLE) {
  ------------------
  |  | 1323|  53.2k|#define OP_TOGGLE 5
  ------------------
  |  Branch (3566:20): [True: 863, False: 52.3k]
  ------------------
 3567|  4.77k|            for (int n = 0; res && res[n].name; n++) {
  ------------------
  |  Branch (3567:29): [True: 4.77k, False: 0]
  |  Branch (3567:36): [True: 3.90k, False: 863]
  ------------------
 3568|  3.90k|                if (res[n].label && !res[n].name[0]) {
  ------------------
  |  Branch (3568:21): [True: 1.23k, False: 2.67k]
  |  Branch (3568:37): [True: 802, False: 429]
  ------------------
 3569|       |                    // Toggle enable/disable special case.
 3570|    802|                    int found =
 3571|    802|                        obj_settings_list_find_by_label0(list, res[n].label);
 3572|    802|                    if (found < 0) {
  ------------------
  |  Branch (3572:25): [True: 731, False: 71]
  ------------------
 3573|    731|                        mp_warn(log, "Option %.*s: Label %s not found\n",
  ------------------
  |  |   73|  1.46k|#define mp_warn(log, ...)       mp_msg(log, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (73:56): [True: 731, False: 0]
  |  |  ------------------
  ------------------
 3574|    731|                                BSTR_P(name), res[n].label);
 3575|    731|                    } else {
 3576|     71|                        list[found].enabled = !list[found].enabled;
 3577|     71|                    }
 3578|    802|                    obj_setting_free(&res[n]);
 3579|  3.10k|                } else {
 3580|  3.10k|                    int found = obj_settings_find_by_content(list, &res[n]);
 3581|  3.10k|                    if (found < 0) {
  ------------------
  |  Branch (3581:25): [True: 2.05k, False: 1.04k]
  ------------------
 3582|  2.05k|                        if (!obj_settings_list_insert_at(log, &list, -1, &res[n]))
  ------------------
  |  Branch (3582:29): [True: 195, False: 1.86k]
  ------------------
 3583|    195|                            obj_setting_free(&res[n]);
 3584|  2.05k|                    } else {
 3585|  1.04k|                        obj_settings_list_del_at(&list, found);
 3586|  1.04k|                        obj_setting_free(&res[n]);
 3587|  1.04k|                    }
 3588|  3.10k|                }
 3589|  3.90k|            }
 3590|    863|            talloc_free(res);
  ------------------
  |  |   47|    863|#define talloc_free                     ta_free
  ------------------
 3591|  52.3k|        } else if (op == OP_REMOVE) {
  ------------------
  |  | 1325|  52.3k|#define OP_REMOVE 7
  ------------------
  |  Branch (3591:20): [True: 957, False: 51.4k]
  ------------------
 3592|  2.38k|            for (int n = num_items - 1; n >= 0; n--) {
  ------------------
  |  Branch (3592:41): [True: 1.42k, False: 957]
  ------------------
 3593|  1.42k|                if (mark_del[n])
  ------------------
  |  Branch (3593:21): [True: 68, False: 1.35k]
  ------------------
 3594|     68|                    obj_settings_list_del_at(&list, n);
 3595|  1.42k|            }
 3596|  2.18k|            for (int n = 0; res && res[n].name; n++) {
  ------------------
  |  Branch (3596:29): [True: 1.42k, False: 760]
  |  Branch (3596:36): [True: 1.22k, False: 197]
  ------------------
 3597|  1.22k|                int found = obj_settings_find_by_content(list, &res[n]);
 3598|  1.22k|                if (found >= 0)
  ------------------
  |  Branch (3598:21): [True: 232, False: 997]
  ------------------
 3599|    232|                    obj_settings_list_del_at(&list, found);
 3600|  1.22k|            }
 3601|    957|            free_obj_settings_list(&res);
 3602|  51.4k|        } else {
 3603|  51.4k|            mp_assert(op == OP_NONE);
  ------------------
  |  |   41|  51.4k|#define mp_assert assert
  ------------------
 3604|  51.4k|            free_obj_settings_list(&list);
 3605|  51.4k|            list = res;
 3606|  51.4k|        }
 3607|  55.4k|        VAL(dst) = list;
  ------------------
  |  | 2936|  55.4k|#define VAL(x) (*(m_obj_settings_t **)(x))
  ------------------
 3608|  55.4k|    }
 3609|       |
 3610|  56.4k|done:
 3611|  56.4k|    talloc_free(mark_del);
  ------------------
  |  |   47|  56.4k|#define talloc_free                     ta_free
  ------------------
 3612|  56.4k|    return ret;
 3613|  55.4k|}
m_option.c:obj_settings_list_num_items:
 2977|   143k|{
 2978|   143k|    int num = 0;
 2979|  1.33M|    while (obj_list && obj_list[num].name)
  ------------------
  |  Branch (2979:12): [True: 1.24M, False: 94.0k]
  |  Branch (2979:24): [True: 1.19M, False: 49.3k]
  ------------------
 2980|  1.19M|        num++;
 2981|   143k|    return num;
 2982|   143k|}
m_option.c:parse_obj_settings_del:
 3370|  2.49k|{
 3371|  2.49k|    bstr s = *param;
 3372|  2.49k|    if (bstr_eatstart0(&s, "@")) {
  ------------------
  |  Branch (3372:9): [True: 1.34k, False: 1.15k]
  ------------------
 3373|       |        // '@name:' -> parse as normal filter entry
 3374|       |        // '@name,' or '@name<end>' -> parse here
 3375|  1.34k|        int idx = bstrspn(s, NAMECH);
  ------------------
  |  | 3271|  1.34k|#define NAMECH "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
  ------------------
 3376|  1.34k|        bstr label = bstr_splice(s, 0, idx);
 3377|  1.34k|        s = bstr_cut(s, idx);
 3378|  1.34k|        if (bstr_startswith0(s, ":"))
  ------------------
  |  Branch (3378:13): [True: 85, False: 1.25k]
  ------------------
 3379|     85|            return 0;
 3380|  1.25k|        if (dst) {
  ------------------
  |  Branch (3380:13): [True: 1.25k, False: 0]
  ------------------
 3381|  1.25k|            int label_index = 0;
 3382|  1.25k|            label_index = obj_settings_list_find_by_label(VAL(dst), label);
  ------------------
  |  | 2936|  1.25k|#define VAL(x) (*(m_obj_settings_t **)(x))
  ------------------
 3383|  1.25k|            if (label_index >= 0) {
  ------------------
  |  Branch (3383:17): [True: 71, False: 1.18k]
  ------------------
 3384|     71|                mark_del[label_index] = true;
 3385|  1.18k|            } else {
 3386|  1.18k|                mp_warn(log, "Option %.*s: item label @%.*s not found.\n",
  ------------------
  |  |   73|  4.74k|#define mp_warn(log, ...)       mp_msg(log, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (73:56): [True: 1.18k, False: 0]
  |  |  |  Branch (73:56): [True: 1.18k, False: 0]
  |  |  ------------------
  ------------------
 3387|  1.18k|                        BSTR_P(opt_name), BSTR_P(label));
 3388|  1.18k|            }
 3389|  1.25k|        }
 3390|  1.25k|        *param = s;
 3391|  1.25k|        return 1;
 3392|  1.34k|    }
 3393|  1.15k|    return 0;
 3394|  2.49k|}
m_option.c:obj_settings_list_find_by_label:
 3029|  10.6k|{
 3030|   349k|    for (int n = 0; obj_list && obj_list[n].name; n++) {
  ------------------
  |  Branch (3030:21): [True: 348k, False: 1.40k]
  |  Branch (3030:33): [True: 339k, False: 8.84k]
  ------------------
 3031|   339k|        if (label.len && bstr_equals0(label, obj_list[n].label))
  ------------------
  |  Branch (3031:13): [True: 5.83k, False: 333k]
  |  Branch (3031:26): [True: 415, False: 5.42k]
  ------------------
 3032|    415|            return n;
 3033|   339k|    }
 3034|  10.2k|    return -1;
 3035|  10.6k|}
m_option.c:parse_obj_settings:
 3277|  75.3k|{
 3278|  75.3k|    int r;
 3279|  75.3k|    char **plist = NULL;
 3280|  75.3k|    struct m_obj_desc desc;
 3281|  75.3k|    bstr str = {0};
 3282|  75.3k|    bstr label = {0};
 3283|  75.3k|    bool nopos = list->disallow_positional_parameters;
 3284|  75.3k|    bool enabled = true;
 3285|       |
 3286|  75.3k|    if (bstr_eatstart0(pstr, "@")) {
  ------------------
  |  Branch (3286:9): [True: 2.51k, False: 72.7k]
  ------------------
 3287|  2.51k|        bstr rest;
 3288|  2.51k|        if (!bstr_split_tok(*pstr, ":", &label, &rest)) {
  ------------------
  |  Branch (3288:13): [True: 862, False: 1.65k]
  ------------------
 3289|       |            // "@labelname" is the special enable/disable toggle syntax
 3290|    862|            if (op == OP_TOGGLE) {
  ------------------
  |  | 1323|    862|#define OP_TOGGLE 5
  ------------------
  |  Branch (3290:17): [True: 858, False: 4]
  ------------------
 3291|    858|                int idx = bstrspn(*pstr, NAMECH);
  ------------------
  |  | 3271|    858|#define NAMECH "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
  ------------------
 3292|    858|                label = bstr_splice(*pstr, 0, idx);
 3293|    858|                if (label.len) {
  ------------------
  |  Branch (3293:21): [True: 857, False: 1]
  ------------------
 3294|    857|                    *pstr = bstr_cut(*pstr, idx);
 3295|    857|                    goto done;
 3296|    857|                }
 3297|    858|            }
 3298|      5|            mp_err(log, "Option %.*s: ':' expected after label.\n", BSTR_P(opt));
  ------------------
  |  |   72|     10|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 5, False: 0]
  |  |  ------------------
  ------------------
 3299|      5|            return M_OPT_INVALID;
  ------------------
  |  |  523|      5|#define M_OPT_INVALID           -3
  ------------------
 3300|    862|        }
 3301|  1.65k|        *pstr = rest;
 3302|  1.65k|        if (label.len == 0) {
  ------------------
  |  Branch (3302:13): [True: 5, False: 1.64k]
  ------------------
 3303|      5|            mp_err(log, "Option %.*s: label name expected.\n", BSTR_P(opt));
  ------------------
  |  |   72|     10|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 5, False: 0]
  |  |  ------------------
  ------------------
 3304|      5|            return M_OPT_INVALID;
  ------------------
  |  |  523|      5|#define M_OPT_INVALID           -3
  ------------------
 3305|      5|        }
 3306|  1.65k|    }
 3307|       |
 3308|  74.4k|    if (list->allow_disable_entries && bstr_eatstart0(pstr, "!"))
  ------------------
  |  Branch (3308:9): [True: 5.46k, False: 68.9k]
  |  Branch (3308:40): [True: 113, False: 5.35k]
  ------------------
 3309|    113|        enabled = false;
 3310|       |
 3311|  74.4k|    bool has_param = false;
 3312|  74.4k|    int idx = bstrspn(*pstr, NAMECH);
  ------------------
  |  | 3271|  74.4k|#define NAMECH "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
  ------------------
 3313|  74.4k|    str = bstr_splice(*pstr, 0, idx);
 3314|  74.4k|    if (!str.len) {
  ------------------
  |  Branch (3314:9): [True: 37, False: 74.4k]
  ------------------
 3315|     37|        mp_err(log, "Option %.*s: item name expected.\n", BSTR_P(opt));
  ------------------
  |  |   72|     74|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 37, False: 0]
  |  |  ------------------
  ------------------
 3316|     37|        return M_OPT_INVALID;
  ------------------
  |  |  523|     37|#define M_OPT_INVALID           -3
  ------------------
 3317|     37|    }
 3318|  74.4k|    *pstr = bstr_cut(*pstr, idx);
 3319|       |    // video filters use "=", VOs use ":"
 3320|  74.4k|    if (bstr_eatstart0(pstr, "=") || bstr_eatstart0(pstr, ":"))
  ------------------
  |  Branch (3320:9): [True: 6.24k, False: 68.1k]
  |  Branch (3320:38): [True: 5.20k, False: 62.9k]
  ------------------
 3321|  11.4k|        has_param = true;
 3322|       |
 3323|  74.4k|    bool skip = false;
 3324|  74.4k|    if (m_obj_list_find(&desc, list, str)) {
  ------------------
  |  Branch (3324:9): [True: 52.1k, False: 22.2k]
  ------------------
 3325|  52.1k|        if (desc.replaced_name)
  ------------------
  |  Branch (3325:13): [True: 11.4k, False: 40.7k]
  ------------------
 3326|  11.4k|            mp_warn(log, "Driver '%s' has been replaced with '%s'!\n",
  ------------------
  |  |   73|  11.4k|#define mp_warn(log, ...)       mp_msg(log, MSGL_WARN, __VA_ARGS__)
  ------------------
 3327|  52.1k|                   desc.replaced_name, desc.name);
 3328|  52.1k|    } else {
 3329|  22.2k|        char name[80];
 3330|  22.2k|        snprintf(name, sizeof(name), "%.*s", BSTR_P(str));
  ------------------
  |  |  283|  22.2k|#define BSTR_P(bstr) (int)((bstr).len), ((bstr).start ? (char*)(bstr).start : "")
  |  |  ------------------
  |  |  |  Branch (283:42): [True: 22.2k, False: 0]
  |  |  ------------------
  ------------------
 3331|  22.2k|        if (list->check_unknown_entry && !list->check_unknown_entry(name)) {
  ------------------
  |  Branch (3331:13): [True: 197, False: 22.0k]
  |  Branch (3331:42): [True: 197, False: 0]
  ------------------
 3332|    197|            mp_err(log, "Option %.*s: '%.*s' isn't supported.\n",
  ------------------
  |  |   72|    788|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 197, False: 0]
  |  |  |  Branch (72:55): [True: 197, False: 0]
  |  |  ------------------
  ------------------
 3333|    197|                   BSTR_P(opt), BSTR_P(str));
 3334|    197|            return M_OPT_INVALID;
  ------------------
  |  |  523|    197|#define M_OPT_INVALID           -3
  ------------------
 3335|    197|        }
 3336|  22.0k|        desc = (struct m_obj_desc){0};
 3337|  22.0k|        skip = true;
 3338|  22.0k|    }
 3339|       |
 3340|  74.2k|    if (has_param) {
  ------------------
  |  Branch (3340:9): [True: 11.4k, False: 62.7k]
  ------------------
 3341|  11.4k|        struct m_config *config = NULL;
 3342|  11.4k|        if (!skip)
  ------------------
  |  Branch (3342:13): [True: 11.1k, False: 286]
  ------------------
 3343|  11.1k|            config = m_config_from_obj_desc_noalloc(NULL, log, &desc);
 3344|  11.4k|        r = m_obj_parse_sub_config(log, opt, str, pstr, config,
 3345|  11.4k|                                   M_SETOPT_CHECK_ONLY, nopos, &desc, list,
 3346|  11.4k|                                   _ret ? &plist : NULL);
  ------------------
  |  Branch (3346:36): [True: 11.4k, False: 0]
  ------------------
 3347|  11.4k|        talloc_free(config);
  ------------------
  |  |   47|  11.4k|#define talloc_free                     ta_free
  ------------------
 3348|  11.4k|        if (r < 0)
  ------------------
  |  Branch (3348:13): [True: 627, False: 10.8k]
  ------------------
 3349|    627|            return r;
 3350|  11.4k|    }
 3351|  73.5k|    if (!_ret)
  ------------------
  |  Branch (3351:9): [True: 0, False: 73.5k]
  ------------------
 3352|      0|        return 1;
 3353|       |
 3354|  74.4k|done: ;
 3355|  74.4k|    m_obj_settings_t item = {
 3356|  74.4k|        .name = bstrto0(NULL, str),
 3357|  74.4k|        .label = bstrdup0(NULL, label),
 3358|  74.4k|        .enabled = enabled,
 3359|  74.4k|        .attribs = plist,
 3360|  74.4k|    };
 3361|  74.4k|    if (!obj_settings_list_insert_at(log, _ret, -1, &item))
  ------------------
  |  Branch (3361:9): [True: 1.46k, False: 72.9k]
  ------------------
 3362|  1.46k|        obj_setting_free(&item);
 3363|  74.4k|    return 1;
 3364|  73.5k|}
m_option.c:m_obj_parse_sub_config:
 3194|  11.4k|{
 3195|  11.4k|    int nold = 0;
 3196|  11.4k|    char **args = NULL;
 3197|  11.4k|    int num_args = 0;
 3198|  11.4k|    int r = 1;
 3199|  11.4k|    char tmp[80];
 3200|       |
 3201|  11.4k|    if (ret) {
  ------------------
  |  Branch (3201:9): [True: 11.4k, False: 0]
  ------------------
 3202|  11.4k|        args = *ret;
 3203|  11.4k|        while (args && args[num_args])
  ------------------
  |  Branch (3203:16): [True: 0, False: 11.4k]
  |  Branch (3203:24): [True: 0, False: 0]
  ------------------
 3204|      0|            num_args++;
 3205|  11.4k|    }
 3206|       |
 3207|  17.1k|    while (pstr->len > 0) {
  ------------------
  |  Branch (3207:12): [True: 10.0k, False: 7.05k]
  ------------------
 3208|  10.0k|        bstr fname, fval;
 3209|  10.0k|        r = split_subconf(log, opt_name, pstr, &fname, &fval);
 3210|  10.0k|        if (r < 0)
  ------------------
  |  Branch (3210:13): [True: 29, False: 10.0k]
  ------------------
 3211|     29|            goto exit;
 3212|       |
 3213|  10.0k|        if (list->use_global_options) {
  ------------------
  |  Branch (3213:13): [True: 33, False: 10.0k]
  ------------------
 3214|     33|            mp_err(log, "Option %.*s: this option does not accept sub-options.\n",
  ------------------
  |  |   72|     66|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 33, False: 0]
  |  |  ------------------
  ------------------
 3215|     33|                   BSTR_P(opt_name));
 3216|     33|            mp_err(log, "Sub-options for --vo and --ao were removed from mpv in "
  ------------------
  |  |   72|     33|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
 3217|     33|                   "release 0.23.0.\nSee https://0x0.st/uM for details.\n");
 3218|     33|            r = M_OPT_INVALID;
  ------------------
  |  |  523|     33|#define M_OPT_INVALID           -3
  ------------------
 3219|     33|            goto exit;
 3220|     33|        }
 3221|       |
 3222|  10.0k|        if (bstr_equals0(fname, "help"))
  ------------------
  |  Branch (3222:13): [True: 5, False: 10.0k]
  ------------------
 3223|      5|            goto print_help;
 3224|  10.0k|        r = get_obj_param(log, opt_name, name, config, fname, fval, flags,
 3225|  10.0k|                          nopos, &nold, &fname, &fval, tmp, sizeof(tmp));
 3226|  10.0k|        if (r < 0)
  ------------------
  |  Branch (3226:13): [True: 560, False: 9.44k]
  ------------------
 3227|    560|            goto exit;
 3228|       |
 3229|  9.44k|        if (r > 0 && ret) {
  ------------------
  |  Branch (3229:13): [True: 5.06k, False: 4.37k]
  |  Branch (3229:22): [True: 5.06k, False: 0]
  ------------------
 3230|  5.06k|            MP_TARRAY_APPEND(NULL, args, num_args, bstrto0(NULL, fname));
  ------------------
  |  |  105|  5.06k|    do {                                            \
  |  |  106|  5.06k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  5.06k|    do {                                            \
  |  |  |  |   97|  5.06k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  5.06k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  5.06k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  5.06k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 3.78k, False: 1.27k]
  |  |  |  |  ------------------
  |  |  |  |   99|  5.06k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  3.78k|    do {                                                        \
  |  |  |  |  |  |   89|  3.78k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  3.78k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  3.78k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  3.78k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  3.78k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  3.78k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  3.78k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  5.06k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  5.06k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  5.06k|        (idxvar)++;                                 \
  |  |  109|  5.06k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 3231|  5.06k|            MP_TARRAY_APPEND(NULL, args, num_args, bstrto0(NULL, fval));
  ------------------
  |  |  105|  5.06k|    do {                                            \
  |  |  106|  5.06k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  5.06k|    do {                                            \
  |  |  |  |   97|  5.06k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  5.06k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  5.06k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  5.06k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 5.06k]
  |  |  |  |  ------------------
  |  |  |  |   99|  5.06k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  5.06k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  5.06k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  5.06k|        (idxvar)++;                                 \
  |  |  109|  5.06k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 3232|  5.06k|            MP_TARRAY_APPEND(NULL, args, num_args, NULL);
  ------------------
  |  |  105|  5.06k|    do {                                            \
  |  |  106|  5.06k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  5.06k|    do {                                            \
  |  |  |  |   97|  5.06k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  5.06k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  5.06k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  5.06k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 3.91k, False: 1.14k]
  |  |  |  |  ------------------
  |  |  |  |   99|  5.06k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  3.91k|    do {                                                        \
  |  |  |  |  |  |   89|  3.91k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  3.91k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  3.91k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  3.91k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  3.91k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  3.91k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  3.91k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  5.06k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  5.06k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  5.06k|        (idxvar)++;                                 \
  |  |  109|  5.06k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 3233|  5.06k|            MP_TARRAY_APPEND(NULL, args, num_args, NULL);
  ------------------
  |  |  105|  5.06k|    do {                                            \
  |  |  106|  5.06k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  5.06k|    do {                                            \
  |  |  |  |   97|  5.06k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  5.06k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  5.06k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  5.06k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 5.06k]
  |  |  |  |  ------------------
  |  |  |  |   99|  5.06k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  5.06k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  5.06k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  5.06k|        (idxvar)++;                                 \
  |  |  109|  5.06k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 3234|  5.06k|            num_args -= 2;
 3235|  5.06k|        }
 3236|       |
 3237|  9.44k|        if (!bstr_eatstart0(pstr, ":"))
  ------------------
  |  Branch (3237:13): [True: 3.74k, False: 5.69k]
  ------------------
 3238|  3.74k|            break;
 3239|  9.44k|    }
 3240|       |
 3241|  10.8k|    if (ret) {
  ------------------
  |  Branch (3241:9): [True: 10.8k, False: 0]
  ------------------
 3242|  10.8k|        if (num_args > 0) {
  ------------------
  |  Branch (3242:13): [True: 3.75k, False: 7.04k]
  ------------------
 3243|  3.75k|            *ret = args;
 3244|  3.75k|            args = NULL;
 3245|  7.04k|        } else {
 3246|  7.04k|            *ret = NULL;
 3247|  7.04k|        }
 3248|  10.8k|    }
 3249|       |
 3250|  10.8k|    goto exit;
 3251|       |
 3252|      5|print_help: ;
 3253|      5|    if (config) {
  ------------------
  |  Branch (3253:9): [True: 5, False: 0]
  ------------------
 3254|      5|        if (desc->print_help)
  ------------------
  |  Branch (3254:13): [True: 2, False: 3]
  ------------------
 3255|      2|            desc->print_help(log);
 3256|      5|        m_config_print_option_list(config, "*");
 3257|      5|    } else if (list->print_unknown_entry_help) {
  ------------------
  |  Branch (3257:16): [True: 0, False: 0]
  ------------------
 3258|      0|        list->print_unknown_entry_help(log, mp_tprintf(80, "%.*s", BSTR_P(name)));
  ------------------
  |  |  165|      0|    mp_tprintf_buf((char[SIZE]){0}, (SIZE), (format), __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (165:55): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 3259|      0|    } else {
 3260|      0|        mp_warn(log, "Option %.*s: item '%.*s' isn't supported.\n",
  ------------------
  |  |   73|      0|#define mp_warn(log, ...)       mp_msg(log, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (73:56): [True: 0, False: 0]
  |  |  |  Branch (73:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 3261|      0|               BSTR_P(opt_name), BSTR_P(name));
 3262|      0|    }
 3263|      5|    r = M_OPT_EXIT;
  ------------------
  |  |  533|      5|#define M_OPT_EXIT              -6
  ------------------
 3264|       |
 3265|  11.4k|exit:
 3266|  11.4k|    free_str_list(&args);
 3267|  11.4k|    return r;
 3268|      5|}
m_option.c:split_subconf:
 2041|  10.0k|{
 2042|  10.0k|    bstr p = *str;
 2043|  10.0k|    bstr subparam = {0};
 2044|  10.0k|    bstr subopt;
 2045|  10.0k|    int r = read_subparam(log, optname, ":=,\\%\"'[]", &p, &subopt);
 2046|  10.0k|    if (r < 0)
  ------------------
  |  Branch (2046:9): [True: 26, False: 10.0k]
  ------------------
 2047|     26|        return r;
 2048|  10.0k|    if (bstr_eatstart0(&p, "=")) {
  ------------------
  |  Branch (2048:9): [True: 1.60k, False: 8.43k]
  ------------------
 2049|  1.60k|        r = read_subparam(log, subopt, ":=,\\%\"'[]", &p, &subparam);
 2050|  1.60k|        if (r < 0)
  ------------------
  |  Branch (2050:13): [True: 3, False: 1.60k]
  ------------------
 2051|      3|            return r;
 2052|  1.60k|    }
 2053|  10.0k|    *str = p;
 2054|  10.0k|    *out_name = subopt;
 2055|  10.0k|    *out_val = subparam;
 2056|  10.0k|    return 0;
 2057|  10.0k|}
m_option.c:get_obj_param:
 3108|  10.0k|{
 3109|  10.0k|    int r;
 3110|       |
 3111|  10.0k|    if (!config) {
  ------------------
  |  Branch (3111:9): [True: 0, False: 10.0k]
  ------------------
 3112|       |        // Duplicates the logic below, but with unknown parameter types/names.
 3113|      0|        if (val.start || nopos) {
  ------------------
  |  Branch (3113:13): [True: 0, False: 0]
  |  Branch (3113:26): [True: 0, False: 0]
  ------------------
 3114|      0|            *out_name = name;
 3115|      0|            *out_val = val;
 3116|      0|        } else {
 3117|      0|            val = name;
 3118|       |            // positional fields
 3119|      0|            if (val.len == 0) { // Empty field, count it and go on
  ------------------
  |  Branch (3119:17): [True: 0, False: 0]
  ------------------
 3120|      0|                (*nold)++;
 3121|      0|                return 0;
 3122|      0|            }
 3123|       |            // Positional naming convention for/followed by mp_set_avopts().
 3124|      0|            snprintf(tmp, tmp_size, "@%d", *nold);
 3125|      0|            *out_name = bstr0(tmp);
 3126|      0|            *out_val = val;
 3127|      0|            (*nold)++;
 3128|      0|        }
 3129|      0|        return 1;
 3130|      0|    }
 3131|       |
 3132|       |    // val.start != NULL => of the form name=val (not positional)
 3133|       |    // If it's just "name", and the associated option exists and is a flag,
 3134|       |    // don't accept it as positional argument.
 3135|  10.0k|    if (val.start || m_config_option_requires_param(config, name) == 0 || nopos) {
  ------------------
  |  Branch (3135:9): [True: 1.60k, False: 8.40k]
  |  Branch (3135:22): [True: 74, False: 8.33k]
  |  Branch (3135:75): [True: 0, False: 8.33k]
  ------------------
 3136|  1.67k|        r = m_config_set_option_cli(config, name, val, flags);
 3137|  1.67k|        if (r < 0) {
  ------------------
  |  Branch (3137:13): [True: 8, False: 1.66k]
  ------------------
 3138|      8|            if (r == M_OPT_UNKNOWN) {
  ------------------
  |  |  517|      8|#define M_OPT_UNKNOWN           -1
  ------------------
  |  Branch (3138:17): [True: 0, False: 8]
  ------------------
 3139|      0|                mp_err(log, "Option %.*s: %.*s doesn't have a %.*s parameter.\n",
  ------------------
  |  |   72|      0|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 0, False: 0]
  |  |  |  Branch (72:55): [True: 0, False: 0]
  |  |  |  Branch (72:55): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 3140|      0|                       BSTR_P(opt_name), BSTR_P(obj_name), BSTR_P(name));
 3141|      0|                return M_OPT_UNKNOWN;
  ------------------
  |  |  517|      0|#define M_OPT_UNKNOWN           -1
  ------------------
 3142|      0|            }
 3143|      8|            if (r != M_OPT_EXIT)
  ------------------
  |  |  533|      8|#define M_OPT_EXIT              -6
  ------------------
  |  Branch (3143:17): [True: 7, False: 1]
  ------------------
 3144|      7|                mp_err(log, "Option %.*s: "
  ------------------
  |  |   72|     56|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 7, False: 0]
  |  |  |  Branch (72:55): [True: 7, False: 0]
  |  |  |  Branch (72:55): [True: 7, False: 0]
  |  |  |  Branch (72:55): [True: 7, False: 0]
  |  |  ------------------
  ------------------
 3145|      8|                       "Error while parsing %.*s parameter %.*s (%.*s)\n",
 3146|      8|                       BSTR_P(opt_name), BSTR_P(obj_name), BSTR_P(name),
 3147|      8|                       BSTR_P(val));
 3148|      8|            return r;
 3149|      8|        }
 3150|  1.66k|        *out_name = name;
 3151|  1.66k|        *out_val = val;
 3152|  1.66k|        return 1;
 3153|  8.33k|    } else {
 3154|  8.33k|        val = name;
 3155|       |        // positional fields
 3156|  8.33k|        if (val.len == 0) { // Empty field, count it and go on
  ------------------
  |  Branch (3156:13): [True: 4.37k, False: 3.95k]
  ------------------
 3157|  4.37k|            (*nold)++;
 3158|  4.37k|            return 0;
 3159|  4.37k|        }
 3160|  3.95k|        const char *opt = m_config_get_positional_option(config, *nold);
 3161|  3.95k|        if (!opt) {
  ------------------
  |  Branch (3161:13): [True: 14, False: 3.93k]
  ------------------
 3162|     14|            mp_err(log, "Option %.*s: %.*s has only %d "
  ------------------
  |  |   72|     56|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 14, False: 0]
  |  |  |  Branch (72:55): [True: 14, False: 0]
  |  |  ------------------
  ------------------
 3163|     14|                   "params, so you can't give more than %d unnamed params.\n",
 3164|     14|                   BSTR_P(opt_name), BSTR_P(obj_name), *nold, *nold);
 3165|     14|            return M_OPT_OUT_OF_RANGE;
  ------------------
  |  |  527|     14|#define M_OPT_OUT_OF_RANGE      -4
  ------------------
 3166|     14|        }
 3167|  3.93k|        r = m_config_set_option_cli(config, bstr0(opt), val, flags);
 3168|  3.93k|        if (r < 0) {
  ------------------
  |  Branch (3168:13): [True: 538, False: 3.39k]
  ------------------
 3169|    538|            if (r != M_OPT_EXIT)
  ------------------
  |  |  533|    538|#define M_OPT_EXIT              -6
  ------------------
  |  Branch (3169:17): [True: 538, False: 0]
  ------------------
 3170|    538|                mp_err(log, "Option %.*s: "
  ------------------
  |  |   72|  3.22k|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (72:55): [True: 538, False: 0]
  |  |  |  Branch (72:55): [True: 538, False: 0]
  |  |  |  Branch (72:55): [True: 538, False: 0]
  |  |  ------------------
  ------------------
 3171|    538|                       "Error while parsing %.*s parameter %s (%.*s)\n",
 3172|    538|                       BSTR_P(opt_name), BSTR_P(obj_name), opt, BSTR_P(val));
 3173|    538|            return r;
 3174|    538|        }
 3175|  3.39k|        *out_name = bstr0(opt);
 3176|  3.39k|        *out_val = val;
 3177|  3.39k|        (*nold)++;
 3178|  3.39k|        return 1;
 3179|  3.93k|    }
 3180|  10.0k|}
m_option.c:obj_settings_list_insert_at:
 3006|  85.7k|{
 3007|  85.7k|    int num = obj_settings_list_num_items(*p_obj_list);
 3008|       |    // Limit list entries to 100. obj_settings_list is not designed to hold more
 3009|       |    // items, and it quickly starts taking ages to add all items.
 3010|  85.7k|    if (num > 100) {
  ------------------
  |  Branch (3010:9): [True: 3.25k, False: 82.4k]
  ------------------
 3011|  3.25k|        mp_warn(log, "Object settings list capacity exceeded: "
  ------------------
  |  |   73|  3.25k|#define mp_warn(log, ...)       mp_msg(log, MSGL_WARN, __VA_ARGS__)
  ------------------
 3012|  3.25k|                     "a maximum of 100 elements is allowed.\n");
 3013|  3.25k|        return false;
 3014|  3.25k|    }
 3015|  82.4k|    if (idx < 0)
  ------------------
  |  Branch (3015:9): [True: 80.5k, False: 1.93k]
  ------------------
 3016|  80.5k|        idx = num + idx + 1;
 3017|  82.4k|    mp_assert(idx >= 0 && idx <= num);
  ------------------
  |  |   41|  82.4k|#define mp_assert assert
  ------------------
 3018|  82.4k|    *p_obj_list = talloc_realloc(NULL, *p_obj_list, struct m_obj_settings,
  ------------------
  |  |   33|  82.4k|#define talloc_realloc                  ta_xrealloc
  |  |  ------------------
  |  |  |  |  144|  82.4k|    (type *)ta_xrealloc_size(ta_parent, ptr, ta_calc_array_size(sizeof(type), count))
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|  82.4k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|  82.4k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|  82.4k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|  82.4k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3019|  82.4k|                                 num + 2);
 3020|  82.4k|    memmove(*p_obj_list + idx + 1, *p_obj_list + idx,
 3021|  82.4k|            (num - idx) * sizeof(m_obj_settings_t));
 3022|  82.4k|    (*p_obj_list)[idx] = *item;
 3023|  82.4k|    (*p_obj_list)[num + 1] = (m_obj_settings_t){0};
 3024|  82.4k|    return true;
 3025|  82.4k|}
m_option.c:obj_setting_free:
 2960|   562k|{
 2961|   562k|    talloc_free(item->name);
  ------------------
  |  |   47|   562k|#define talloc_free                     ta_free
  ------------------
 2962|   562k|    talloc_free(item->label);
  ------------------
  |  |   47|   562k|#define talloc_free                     ta_free
  ------------------
 2963|   562k|    free_str_list(&(item->attribs));
 2964|   562k|}
m_option.c:obj_settings_list_find_by_label0:
 3039|  9.40k|{
 3040|  9.40k|    return obj_settings_list_find_by_label(obj_list, bstr0(label));
 3041|  9.40k|}
m_option.c:obj_settings_find_by_content:
 3045|  4.33k|{
 3046|  34.7k|    for (int n = 0; obj_list && obj_list[n].name; n++) {
  ------------------
  |  Branch (3046:21): [True: 33.6k, False: 1.06k]
  |  Branch (3046:33): [True: 31.6k, False: 1.99k]
  ------------------
 3047|  31.6k|        if (obj_setting_match(&obj_list[n], item))
  ------------------
  |  Branch (3047:13): [True: 1.27k, False: 30.4k]
  ------------------
 3048|  1.27k|            return n;
 3049|  31.6k|    }
 3050|  3.05k|    return -1;
 3051|  4.33k|}
m_option.c:obj_setting_match:
 2968|  31.6k|{
 2969|  31.6k|    bstr la = bstr0(a->label), lb = bstr0(b->label);
 2970|  31.6k|    if (la.len || lb.len)
  ------------------
  |  Branch (2970:9): [True: 2.42k, False: 29.2k]
  |  Branch (2970:19): [True: 325, False: 28.9k]
  ------------------
 2971|  2.75k|        return bstr_equals(la, lb);
 2972|       |
 2973|  28.9k|    return m_obj_settings_equal(a, b);
 2974|  31.6k|}
m_option.c:obj_settings_list_del_at:
 2985|  1.34k|{
 2986|  1.34k|    m_obj_settings_t *obj_list = *p_obj_list;
 2987|  1.34k|    int num = obj_settings_list_num_items(obj_list);
 2988|       |
 2989|  1.34k|    mp_assert(idx >= 0 && idx < num);
  ------------------
  |  |   41|  1.34k|#define mp_assert assert
  ------------------
 2990|       |
 2991|  1.34k|    obj_setting_free(&obj_list[idx]);
 2992|       |
 2993|       |    // Note: the NULL-terminating element is moved down as part of this
 2994|  1.34k|    memmove(&obj_list[idx], &obj_list[idx + 1],
 2995|  1.34k|            sizeof(m_obj_settings_t) * (num - idx));
 2996|       |
 2997|  1.34k|    *p_obj_list = talloc_realloc(NULL, obj_list, struct m_obj_settings, num);
  ------------------
  |  |   33|  1.34k|#define talloc_realloc                  ta_xrealloc
  |  |  ------------------
  |  |  |  |  144|  1.34k|    (type *)ta_xrealloc_size(ta_parent, ptr, ta_calc_array_size(sizeof(type), count))
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|  1.34k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|  1.34k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|  1.34k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|  1.34k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2998|  1.34k|}
m_option.c:print_obj_settings_list:
 3626|    421|{
 3627|    421|    m_obj_settings_t *list = VAL(val);
  ------------------
  |  | 2936|    421|#define VAL(x) (*(m_obj_settings_t **)(x))
  ------------------
 3628|    421|    char *res = talloc_strdup(NULL, "");
  ------------------
  |  |   50|    421|#define talloc_strdup                   ta_xstrdup
  ------------------
 3629|  1.66k|    for (int n = 0; list && list[n].name; n++) {
  ------------------
  |  Branch (3629:21): [True: 1.45k, False: 208]
  |  Branch (3629:29): [True: 1.24k, False: 213]
  ------------------
 3630|  1.24k|        m_obj_settings_t *entry = &list[n];
 3631|  1.24k|        if (n > 0)
  ------------------
  |  Branch (3631:13): [True: 1.03k, False: 212]
  ------------------
 3632|  1.03k|            res = talloc_strdup_append(res, ",");
  ------------------
  |  |   57|  1.03k|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
 3633|       |        // Assume labels and names don't need escaping
 3634|  1.24k|        if (entry->label && entry->label[0])
  ------------------
  |  Branch (3634:13): [True: 74, False: 1.17k]
  |  Branch (3634:29): [True: 74, False: 0]
  ------------------
 3635|     74|            res = talloc_asprintf_append(res, "@%s:", entry->label);
  ------------------
  |  |   63|     74|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 3636|  1.24k|        if (!entry->enabled)
  ------------------
  |  Branch (3636:13): [True: 201, False: 1.04k]
  ------------------
 3637|    201|            res = talloc_strdup_append(res, "!");
  ------------------
  |  |   57|    201|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
 3638|  1.24k|        res = talloc_strdup_append(res, entry->name);
  ------------------
  |  |   57|  1.24k|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
 3639|  1.24k|        if (entry->attribs && entry->attribs[0]) {
  ------------------
  |  Branch (3639:13): [True: 103, False: 1.14k]
  |  Branch (3639:31): [True: 103, False: 0]
  ------------------
 3640|    103|            res = talloc_strdup_append(res, "=");
  ------------------
  |  |   57|    103|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
 3641|    280|            for (int i = 0; entry->attribs[i * 2 + 0]; i++) {
  ------------------
  |  Branch (3641:29): [True: 177, False: 103]
  ------------------
 3642|    177|                if (i > 0)
  ------------------
  |  Branch (3642:21): [True: 74, False: 103]
  ------------------
 3643|     74|                    res = talloc_strdup_append(res, ":");
  ------------------
  |  |   57|     74|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
 3644|    177|                append_param(&res, entry->attribs[i * 2 + 0]);
 3645|    177|                res = talloc_strdup_append(res, "=");
  ------------------
  |  |   57|    177|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
 3646|    177|                append_param(&res, entry->attribs[i * 2 + 1]);
 3647|    177|            }
 3648|    103|        }
 3649|  1.24k|    }
 3650|    421|    return res;
 3651|    421|}
m_option.c:append_param:
 3616|    354|{
 3617|    354|    if (strspn(param, NAMECH) == strlen(param)) {
  ------------------
  |  | 3271|    354|#define NAMECH "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
  ------------------
  |  Branch (3617:9): [True: 284, False: 70]
  ------------------
 3618|    284|        *res = talloc_strdup_append(*res, param);
  ------------------
  |  |   57|    284|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
 3619|    284|    } else {
 3620|       |        // Simple escaping: %BYTECOUNT%STRING
 3621|     70|        *res = talloc_asprintf_append(*res, "%%%zd%%%s", strlen(param), param);
  ------------------
  |  |   63|     70|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 3622|     70|    }
 3623|    354|}
m_option.c:copy_obj_settings_list:
 3070|   509k|{
 3071|   509k|    m_obj_settings_t *d, *s;
 3072|   509k|    int n;
 3073|       |
 3074|   509k|    if (!(dst && src))
  ------------------
  |  Branch (3074:11): [True: 509k, False: 0]
  |  Branch (3074:18): [True: 509k, False: 0]
  ------------------
 3075|      0|        return;
 3076|       |
 3077|   509k|    s = VAL(src);
  ------------------
  |  | 2936|   509k|#define VAL(x) (*(m_obj_settings_t **)(x))
  ------------------
 3078|       |
 3079|   509k|    if (VAL(dst))
  ------------------
  |  | 2936|   509k|#define VAL(x) (*(m_obj_settings_t **)(x))
  |  |  ------------------
  |  |  |  Branch (2936:16): [True: 19.9k, False: 489k]
  |  |  ------------------
  ------------------
 3080|  19.9k|        free_obj_settings_list(dst);
 3081|   509k|    if (!s)
  ------------------
  |  Branch (3081:9): [True: 392k, False: 117k]
  ------------------
 3082|   392k|        return;
 3083|       |
 3084|   604k|    for (n = 0; s[n].name; n++)
  ------------------
  |  Branch (3084:17): [True: 487k, False: 117k]
  ------------------
 3085|   487k|        /* NOP */;
 3086|   117k|    d = talloc_array(NULL, struct m_obj_settings, n + 1);
  ------------------
  |  |   29|   117k|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|   117k|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|   117k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3087|   604k|    for (n = 0; s[n].name; n++) {
  ------------------
  |  Branch (3087:17): [True: 487k, False: 117k]
  ------------------
 3088|   487k|        d[n].name = talloc_strdup(NULL, s[n].name);
  ------------------
  |  |   50|   487k|#define talloc_strdup                   ta_xstrdup
  ------------------
 3089|   487k|        d[n].label = talloc_strdup(NULL, s[n].label);
  ------------------
  |  |   50|   487k|#define talloc_strdup                   ta_xstrdup
  ------------------
 3090|   487k|        d[n].enabled = s[n].enabled;
 3091|   487k|        d[n].attribs = NULL;
 3092|   487k|        copy_str_list(NULL, &(d[n].attribs), &(s[n].attribs));
 3093|   487k|    }
 3094|   117k|    d[n].name = NULL;
 3095|   117k|    d[n].label = NULL;
 3096|   117k|    d[n].attribs = NULL;
 3097|   117k|    VAL(dst) = d;
  ------------------
  |  | 2936|   117k|#define VAL(x) (*(m_obj_settings_t **)(x))
  ------------------
 3098|   117k|}
m_option.c:free_obj_settings_list:
 3054|   554k|{
 3055|   554k|    int n;
 3056|   554k|    m_obj_settings_t *d;
 3057|       |
 3058|   554k|    if (!dst || !VAL(dst))
  ------------------
  |  | 2936|   554k|#define VAL(x) (*(m_obj_settings_t **)(x))
  ------------------
  |  Branch (3058:9): [True: 0, False: 554k]
  |  Branch (3058:17): [True: 386k, False: 167k]
  ------------------
 3059|   386k|        return;
 3060|       |
 3061|   167k|    d = VAL(dst);
  ------------------
  |  | 2936|   167k|#define VAL(x) (*(m_obj_settings_t **)(x))
  ------------------
 3062|   723k|    for (n = 0; d[n].name; n++)
  ------------------
  |  Branch (3062:17): [True: 556k, False: 167k]
  ------------------
 3063|   556k|        obj_setting_free(&d[n]);
 3064|   167k|    talloc_free(d);
  ------------------
  |  |   47|   167k|#define talloc_free                     ta_free
  ------------------
 3065|   167k|    VAL(dst) = NULL;
  ------------------
  |  | 2936|   167k|#define VAL(x) (*(m_obj_settings_t **)(x))
  ------------------
 3066|   167k|}
m_option.c:obj_settings_list_equal:
 3761|  20.9k|{
 3762|  20.9k|    struct m_obj_settings *a = VAL(pa);
  ------------------
  |  | 2936|  20.9k|#define VAL(x) (*(m_obj_settings_t **)(x))
  ------------------
 3763|  20.9k|    struct m_obj_settings *b = VAL(pb);
  ------------------
  |  | 2936|  20.9k|#define VAL(x) (*(m_obj_settings_t **)(x))
  ------------------
 3764|       |
 3765|  20.9k|    if (a == b || !a || !b)
  ------------------
  |  Branch (3765:9): [True: 1.98k, False: 19.0k]
  |  Branch (3765:19): [True: 3.38k, False: 15.6k]
  |  Branch (3765:25): [True: 573, False: 15.0k]
  ------------------
 3766|  5.94k|        return a == b || (!a && !b[0].name) || (!b && !a[0].name);
  ------------------
  |  Branch (3766:16): [True: 1.98k, False: 3.96k]
  |  Branch (3766:27): [True: 3.38k, False: 573]
  |  Branch (3766:33): [True: 137, False: 3.25k]
  |  Branch (3766:49): [True: 573, False: 3.25k]
  |  Branch (3766:55): [True: 0, False: 573]
  ------------------
 3767|       |
 3768|  54.3k|    for (int n = 0; a[n].name || b[n].name; n++) {
  ------------------
  |  Branch (3768:21): [True: 41.9k, False: 12.4k]
  |  Branch (3768:34): [True: 1.01k, False: 11.4k]
  ------------------
 3769|  42.9k|        if (!a[n].name || !b[n].name)
  ------------------
  |  Branch (3769:13): [True: 1.01k, False: 41.9k]
  |  Branch (3769:27): [True: 274, False: 41.6k]
  ------------------
 3770|  1.29k|            return false;
 3771|  41.6k|        if (!m_obj_settings_equal(&a[n], &b[n]))
  ------------------
  |  Branch (3771:13): [True: 2.34k, False: 39.3k]
  ------------------
 3772|  2.34k|            return false;
 3773|  41.6k|    }
 3774|       |
 3775|  11.4k|    return true;
 3776|  15.0k|}
m_option.c:print_node:
 3827|  1.05k|{
 3828|  1.05k|    char *t = talloc_strdup(NULL, "");
  ------------------
  |  |   50|  1.05k|#define talloc_strdup                   ta_xstrdup
  ------------------
 3829|  1.05k|    if (json_write(&t, &VAL(val)) < 0) {
  ------------------
  |  | 3816|  1.05k|#define VAL(x) (*(struct mpv_node *)(x))
  ------------------
  |  Branch (3829:9): [True: 0, False: 1.05k]
  ------------------
 3830|      0|        talloc_free(t);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 3831|      0|        t = NULL;
 3832|      0|    }
 3833|  1.05k|    return t;
 3834|  1.05k|}
m_option.c:pretty_print_node:
 3837|    675|{
 3838|    675|    char *t = talloc_strdup(NULL, "");
  ------------------
  |  |   50|    675|#define talloc_strdup                   ta_xstrdup
  ------------------
 3839|    675|    if (json_write_pretty(&t, &VAL(val)) < 0) {
  ------------------
  |  | 3816|    675|#define VAL(x) (*(struct mpv_node *)(x))
  ------------------
  |  Branch (3839:9): [True: 0, False: 675]
  ------------------
 3840|      0|        talloc_free(t);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 3841|      0|        t = NULL;
 3842|      0|    }
 3843|    675|    return t;
 3844|    675|}
m_option.c:dup_node:
 3847|  2.07M|{
 3848|  2.07M|    switch (node->format) {
 3849|  1.53M|    case MPV_FORMAT_STRING:
  ------------------
  |  Branch (3849:5): [True: 1.53M, False: 542k]
  ------------------
 3850|  1.53M|        node->u.string = talloc_strdup(ta_parent, node->u.string);
  ------------------
  |  |   50|  1.53M|#define talloc_strdup                   ta_xstrdup
  ------------------
 3851|  1.53M|        break;
 3852|      0|    case MPV_FORMAT_NODE_ARRAY:
  ------------------
  |  Branch (3852:5): [True: 0, False: 2.07M]
  ------------------
 3853|   524k|    case MPV_FORMAT_NODE_MAP: {
  ------------------
  |  Branch (3853:5): [True: 524k, False: 1.55M]
  ------------------
 3854|   524k|        struct mpv_node_list *oldlist = node->u.list;
 3855|   524k|        struct mpv_node_list *new = talloc_zero(ta_parent, struct mpv_node_list);
  ------------------
  |  |   27|   524k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|   524k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|   524k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3856|   524k|        node->u.list = new;
 3857|   524k|        if (oldlist->num > 0) {
  ------------------
  |  Branch (3857:13): [True: 524k, False: 0]
  ------------------
 3858|   524k|            *new = *oldlist;
 3859|   524k|            new->values = talloc_array(new, struct mpv_node, new->num);
  ------------------
  |  |   29|   524k|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|   524k|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|   524k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3860|  2.07M|            for (int n = 0; n < new->num; n++) {
  ------------------
  |  Branch (3860:29): [True: 1.55M, False: 524k]
  ------------------
 3861|  1.55M|                new->values[n] = oldlist->values[n];
 3862|  1.55M|                dup_node(new, &new->values[n]);
 3863|  1.55M|            }
 3864|   524k|            if (node->format == MPV_FORMAT_NODE_MAP) {
  ------------------
  |  Branch (3864:17): [True: 524k, False: 0]
  ------------------
 3865|   524k|                new->keys = talloc_array(new, char*, new->num);
  ------------------
  |  |   29|   524k|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|   524k|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|   524k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3866|  2.07M|                for (int n = 0; n < new->num; n++)
  ------------------
  |  Branch (3866:33): [True: 1.55M, False: 524k]
  ------------------
 3867|  1.55M|                    new->keys[n] = talloc_strdup(new, oldlist->keys[n]);
  ------------------
  |  |   50|  1.55M|#define talloc_strdup                   ta_xstrdup
  ------------------
 3868|   524k|            }
 3869|   524k|        }
 3870|   524k|        break;
 3871|      0|    }
 3872|      0|    case MPV_FORMAT_BYTE_ARRAY: {
  ------------------
  |  Branch (3872:5): [True: 0, False: 2.07M]
  ------------------
 3873|      0|        struct mpv_byte_array *old = node->u.ba;
 3874|      0|        struct mpv_byte_array *new = talloc_zero(ta_parent, struct mpv_byte_array);
  ------------------
  |  |   27|      0|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|      0|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3875|      0|        node->u.ba = new;
 3876|      0|        if (old->size > 0) {
  ------------------
  |  Branch (3876:13): [True: 0, False: 0]
  ------------------
 3877|      0|            *new = *old;
 3878|      0|            new->data = talloc_memdup(new, old->data, old->size);
  ------------------
  |  |   49|      0|#define talloc_memdup                   ta_xmemdup
  |  |  ------------------
  |  |  |  |  157|      0|#define ta_xmemdup(...)         ta_dbg_set_loc(ta_xmemdup(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3879|      0|        }
 3880|      0|        break;
 3881|      0|    }
 3882|      0|    case MPV_FORMAT_NONE:
  ------------------
  |  Branch (3882:5): [True: 0, False: 2.07M]
  ------------------
 3883|      2|    case MPV_FORMAT_FLAG:
  ------------------
  |  Branch (3883:5): [True: 2, False: 2.07M]
  ------------------
 3884|  18.1k|    case MPV_FORMAT_INT64:
  ------------------
  |  Branch (3884:5): [True: 18.1k, False: 2.06M]
  ------------------
 3885|  18.1k|    case MPV_FORMAT_DOUBLE:
  ------------------
  |  Branch (3885:5): [True: 0, False: 2.07M]
  ------------------
 3886|  18.1k|        break;
 3887|      0|    default:
  ------------------
  |  Branch (3887:5): [True: 0, False: 2.07M]
  ------------------
 3888|       |        // unknown entry - mark as invalid
 3889|      0|        node->format = (mpv_format)-1;
 3890|  2.07M|    }
 3891|  2.07M|}
m_option.c:free_node:
 3921|   538k|{
 3922|   538k|    if (src) {
  ------------------
  |  Branch (3922:9): [True: 538k, False: 0]
  ------------------
 3923|   538k|        struct mpv_node *node = &VAL(src);
  ------------------
  |  | 3816|   538k|#define VAL(x) (*(struct mpv_node *)(x))
  ------------------
 3924|   538k|        talloc_free(node_get_alloc(node));
  ------------------
  |  |   47|   538k|#define talloc_free                     ta_free
  ------------------
 3925|   538k|        *node = (struct mpv_node){{0}};
 3926|   538k|    }
 3927|   538k|}
m_option.c:node_get:
 3938|   524k|{
 3939|   524k|    *dst = VAL(src);
  ------------------
  |  | 3816|   524k|#define VAL(x) (*(struct mpv_node *)(x))
  ------------------
 3940|   524k|    dup_node(ta_parent, dst);
 3941|   524k|    return 1;
 3942|   524k|}
m_option.c:parse_cycle_dir:
 3964|  12.1k|{
 3965|  12.1k|    double val;
 3966|  12.1k|    if (bstrcmp0(param, "up") == 0) {
  ------------------
  |  Branch (3966:9): [True: 0, False: 12.1k]
  ------------------
 3967|      0|        val = +1;
 3968|  12.1k|    } else if (bstrcmp0(param, "down") == 0) {
  ------------------
  |  Branch (3968:16): [True: 12.1k, False: 0]
  ------------------
 3969|  12.1k|        val = -1;
 3970|  12.1k|    } else {
 3971|      0|        return m_option_type_double.parse(log, opt, name, param, dst);
 3972|      0|    }
 3973|  12.1k|    *(double *)dst = val;
 3974|  12.1k|    return 1;
 3975|  12.1k|}

f_lavfi.c:ra_hwdec_validate_drivers_only_opt_str:
  205|     71|                                            struct bstr name, void *value) { \
  206|     71|    return OPT_FUNC(func)(log, opt, name, value); \
  ------------------
  |  |  199|     71|#define OPT_FUNC(name) name
  ------------------
  207|     71|} \
cmd.c:m_option_free:
  577|  5.07M|{
  578|  5.07M|    if (opt->type->free)
  ------------------
  |  Branch (578:9): [True: 2.69M, False: 2.37M]
  ------------------
  579|  2.69M|        opt->type->free(dst);
  580|  5.07M|}
cmd.c:m_option_copy:
  570|   765k|{
  571|   765k|    if (opt->type->copy)
  ------------------
  |  Branch (571:9): [True: 765k, False: 0]
  ------------------
  572|   765k|        opt->type->copy(opt, dst, src);
  573|   765k|}
cmd.c:m_option_print:
  547|  12.1k|{
  548|  12.1k|    if (opt->type->print)
  ------------------
  |  Branch (548:9): [True: 12.1k, False: 0]
  ------------------
  549|  12.1k|        return opt->type->print(opt, val_ptr);
  550|      0|    else
  551|      0|        return NULL;
  552|  12.1k|}
m_config_core.c:m_option_free:
  577|  33.7M|{
  578|  33.7M|    if (opt->type->free)
  ------------------
  |  Branch (578:9): [True: 6.38M, False: 27.4M]
  ------------------
  579|  6.38M|        opt->type->free(dst);
  580|  33.7M|}
m_config_core.c:m_option_equal:
  605|   621k|{
  606|       |    // Handle trivial equivalence.
  607|       |    // If not implemented, assume this type has no actual values => always equal.
  608|   621k|    if (a == b || !opt->type->equal)
  ------------------
  |  Branch (608:9): [True: 0, False: 621k]
  |  Branch (608:19): [True: 0, False: 621k]
  ------------------
  609|      0|        return true;
  610|   621k|    return opt->type->equal(opt, a, b);
  611|   621k|}
m_config_core.c:m_option_copy:
  570|  6.65M|{
  571|  6.65M|    if (opt->type->copy)
  ------------------
  |  Branch (571:9): [True: 6.65M, False: 0]
  ------------------
  572|  6.65M|        opt->type->copy(opt, dst, src);
  573|  6.65M|}
m_config_frontend.c:m_option_copy:
  570|  10.0M|{
  571|  10.0M|    if (opt->type->copy)
  ------------------
  |  Branch (571:9): [True: 10.0M, False: 0]
  ------------------
  572|  10.0M|        opt->type->copy(opt, dst, src);
  573|  10.0M|}
m_config_frontend.c:m_option_free:
  577|  9.78M|{
  578|  9.78M|    if (opt->type->free)
  ------------------
  |  Branch (578:9): [True: 1.90M, False: 7.87M]
  ------------------
  579|  1.90M|        opt->type->free(dst);
  580|  9.78M|}
m_config_frontend.c:m_option_pretty_print:
  557|  26.7k|{
  558|  26.7k|    m_option_t o = *opt;
  559|  26.7k|    if (fixed_len)
  ------------------
  |  Branch (559:9): [True: 0, False: 26.7k]
  ------------------
  560|      0|        o.flags |= M_OPT_FIXED_LEN_PRINT;
  ------------------
  |  |  482|      0|#define M_OPT_FIXED_LEN_PRINT   (UINT64_C(1) << 55)
  ------------------
  561|  26.7k|    if (opt->type->pretty_print)
  ------------------
  |  Branch (561:9): [True: 6.09k, False: 20.6k]
  ------------------
  562|  6.09k|        return opt->type->pretty_print(&o, val_ptr);
  563|  20.6k|    else
  564|  20.6k|        return m_option_print(&o, val_ptr);
  565|  26.7k|}
m_config_frontend.c:m_option_print:
  547|  20.6k|{
  548|  20.6k|    if (opt->type->print)
  ------------------
  |  Branch (548:9): [True: 19.2k, False: 1.44k]
  ------------------
  549|  19.2k|        return opt->type->print(opt, val_ptr);
  550|  1.44k|    else
  551|  1.44k|        return NULL;
  552|  20.6k|}
m_property.c:m_option_pretty_print:
  557|  6.95k|{
  558|  6.95k|    m_option_t o = *opt;
  559|  6.95k|    if (fixed_len)
  ------------------
  |  Branch (559:9): [True: 1.10k, False: 5.85k]
  ------------------
  560|  1.10k|        o.flags |= M_OPT_FIXED_LEN_PRINT;
  ------------------
  |  |  482|  1.10k|#define M_OPT_FIXED_LEN_PRINT   (UINT64_C(1) << 55)
  ------------------
  561|  6.95k|    if (opt->type->pretty_print)
  ------------------
  |  Branch (561:9): [True: 782, False: 6.17k]
  ------------------
  562|    782|        return opt->type->pretty_print(&o, val_ptr);
  563|  6.17k|    else
  564|  6.17k|        return m_option_print(&o, val_ptr);
  565|  6.95k|}
m_property.c:m_option_free:
  577|   532k|{
  578|   532k|    if (opt->type->free)
  ------------------
  |  Branch (578:9): [True: 532k, False: 743]
  ------------------
  579|   532k|        opt->type->free(dst);
  580|   532k|}
m_property.c:m_option_print:
  547|   120k|{
  548|   120k|    if (opt->type->print)
  ------------------
  |  Branch (548:9): [True: 120k, False: 0]
  ------------------
  549|   120k|        return opt->type->print(opt, val_ptr);
  550|      0|    else
  551|      0|        return NULL;
  552|   120k|}
m_property.c:m_option_get_node:
  598|  2.07M|{
  599|  2.07M|    if (opt->type->get)
  ------------------
  |  Branch (599:9): [True: 2.07M, False: 0]
  ------------------
  600|  2.07M|        return opt->type->get(opt, ta_parent, dst, src);
  601|      0|    return M_OPT_UNKNOWN;
  ------------------
  |  |  517|      0|#define M_OPT_UNKNOWN           -1
  ------------------
  602|  2.07M|}
m_property.c:m_option_copy:
  570|     74|{
  571|     74|    if (opt->type->copy)
  ------------------
  |  Branch (571:9): [True: 74, False: 0]
  ------------------
  572|     74|        opt->type->copy(opt, dst, src);
  573|     74|}
client.c:m_option_free:
  577|  12.1k|{
  578|  12.1k|    if (opt->type->free)
  ------------------
  |  Branch (578:9): [True: 12.1k, False: 0]
  ------------------
  579|  12.1k|        opt->type->free(dst);
  580|  12.1k|}
command.c:m_option_copy:
  570|    821|{
  571|    821|    if (opt->type->copy)
  ------------------
  |  Branch (571:9): [True: 821, False: 0]
  ------------------
  572|    821|        opt->type->copy(opt, dst, src);
  573|    821|}
command.c:m_option_free:
  577|  17.0k|{
  578|  17.0k|    if (opt->type->free)
  ------------------
  |  Branch (578:9): [True: 17.0k, False: 0]
  ------------------
  579|  17.0k|        opt->type->free(dst);
  580|  17.0k|}
lcms.c:validate_3dlut_size_opt_str:
  205|     35|                                            struct bstr name, void *value) { \
  206|     35|    return OPT_FUNC(func)(log, opt, name, value); \
  ------------------
  |  |  199|     35|#define OPT_FUNC(name) name
  ------------------
  207|     35|} \
video.c:validate_error_diffusion_opt_str:
  205|    313|                                            struct bstr name, void *value) { \
  206|    313|    return OPT_FUNC(func)(log, opt, name, value); \
  ------------------
  |  |  199|    313|#define OPT_FUNC(name) name
  ------------------
  207|    313|} \
video.c:ra_hwdec_validate_opt_str:
  205|    334|                                            struct bstr name, void *value) { \
  206|    334|    return OPT_FUNC(func)(log, opt, name, value); \
  ------------------
  |  |  199|    334|#define OPT_FUNC(name) name
  ------------------
  207|    334|} \

m_property_list_find:
   65|  29.3k|{
   66|  5.74M|    for (int n = 0; list && list[n].name; n++) {
  ------------------
  |  Branch (66:21): [True: 5.74M, False: 0]
  |  Branch (66:29): [True: 5.74M, False: 1.57k]
  ------------------
   67|  5.74M|        if (strcmp(list[n].name, name) == 0)
  ------------------
  |  Branch (67:13): [True: 27.8k, False: 5.72M]
  ------------------
   68|  27.8k|            return (struct m_property *)&list[n];
   69|  5.74M|    }
   70|  1.57k|    return NULL;
   71|  29.3k|}
m_property_do:
  100|  12.8k|{
  101|  12.8k|    union m_option_value val = m_option_value_default;
  102|  12.8k|    int r;
  103|       |
  104|  12.8k|    struct m_option opt = {0};
  105|  12.8k|    r = do_action(prop_list, name, M_PROPERTY_GET_TYPE, &opt, ctx);
  106|  12.8k|    if (r <= 0)
  ------------------
  |  Branch (106:9): [True: 3.26k, False: 9.55k]
  ------------------
  107|  3.26k|        return r;
  108|  9.55k|    mp_assert(opt.type);
  ------------------
  |  |   41|  9.55k|#define mp_assert assert
  ------------------
  109|       |
  110|  9.55k|    switch (action) {
  111|  1.17k|    case M_PROPERTY_FIXED_LEN_PRINT:
  ------------------
  |  Branch (111:5): [True: 1.17k, False: 8.38k]
  ------------------
  112|  7.92k|    case M_PROPERTY_PRINT: {
  ------------------
  |  Branch (112:5): [True: 6.75k, False: 2.80k]
  ------------------
  113|  7.92k|        if ((r = do_action(prop_list, name, action, arg, ctx)) >= 0)
  ------------------
  |  Branch (113:13): [True: 915, False: 7.01k]
  ------------------
  114|    915|            return r;
  115|       |        // Fallback to m_option
  116|  7.01k|        if ((r = do_action(prop_list, name, M_PROPERTY_GET, &val, ctx)) <= 0)
  ------------------
  |  Branch (116:13): [True: 56, False: 6.95k]
  ------------------
  117|     56|            return r;
  118|  6.95k|        char *str = m_option_pretty_print(&opt, &val, action == M_PROPERTY_FIXED_LEN_PRINT);
  119|  6.95k|        m_option_free(&opt, &val);
  120|  6.95k|        *(char **)arg = str;
  121|  6.95k|        return str != NULL;
  122|  7.01k|    }
  123|  1.38k|    case M_PROPERTY_GET_STRING: {
  ------------------
  |  Branch (123:5): [True: 1.38k, False: 8.16k]
  ------------------
  124|  1.38k|        if ((r = do_action(prop_list, name, M_PROPERTY_GET, &val, ctx)) <= 0)
  ------------------
  |  Branch (124:13): [True: 19, False: 1.37k]
  ------------------
  125|     19|            return r;
  126|  1.37k|        char *str = m_option_print(&opt, &val);
  127|  1.37k|        m_option_free(&opt, &val);
  128|  1.37k|        *(char **)arg = str;
  129|  1.37k|        return str != NULL;
  130|  1.38k|    }
  131|      0|    case M_PROPERTY_SET_STRING: {
  ------------------
  |  Branch (131:5): [True: 0, False: 9.55k]
  ------------------
  132|      0|        struct mpv_node node = { .format = MPV_FORMAT_STRING, .u.string = arg };
  133|      0|        return m_property_do(log, prop_list, name, M_PROPERTY_SET_NODE, &node, ctx);
  134|  1.38k|    }
  135|      0|    case M_PROPERTY_MULTIPLY: {
  ------------------
  |  Branch (135:5): [True: 0, False: 9.55k]
  ------------------
  136|      0|        return m_property_multiply(log, prop_list, name, *(double *)arg, ctx);
  137|  1.38k|    }
  138|      0|    case M_PROPERTY_SWITCH: {
  ------------------
  |  Branch (138:5): [True: 0, False: 9.55k]
  ------------------
  139|      0|        if (!log)
  ------------------
  |  Branch (139:13): [True: 0, False: 0]
  ------------------
  140|      0|            return M_PROPERTY_ERROR;
  141|      0|        struct m_property_switch_arg *sarg = arg;
  142|      0|        if ((r = do_action(prop_list, name, M_PROPERTY_SWITCH, arg, ctx)) !=
  ------------------
  |  Branch (142:13): [True: 0, False: 0]
  ------------------
  143|      0|            M_PROPERTY_NOT_IMPLEMENTED)
  144|      0|            return r;
  145|       |        // Fallback to m_option
  146|      0|        r = m_property_do(log, prop_list, name, M_PROPERTY_GET_CONSTRICTED_TYPE,
  147|      0|                          &opt, ctx);
  148|      0|        if (r <= 0)
  ------------------
  |  Branch (148:13): [True: 0, False: 0]
  ------------------
  149|      0|            return r;
  150|      0|        mp_assert(opt.type);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  151|      0|        if (!opt.type->add)
  ------------------
  |  Branch (151:13): [True: 0, False: 0]
  ------------------
  152|      0|            return M_PROPERTY_NOT_IMPLEMENTED;
  153|      0|        if ((r = do_action(prop_list, name, M_PROPERTY_GET, &val, ctx)) <= 0)
  ------------------
  |  Branch (153:13): [True: 0, False: 0]
  ------------------
  154|      0|            return r;
  155|      0|        opt.type->add(&opt, &val, sarg->inc, sarg->wrap);
  156|      0|        r = do_action(prop_list, name, M_PROPERTY_SET, &val, ctx);
  157|      0|        m_option_free(&opt, &val);
  158|      0|        return r;
  159|      0|    }
  160|      0|    case M_PROPERTY_GET_CONSTRICTED_TYPE: {
  ------------------
  |  Branch (160:5): [True: 0, False: 9.55k]
  ------------------
  161|      0|        r = do_action(prop_list, name, action, arg, ctx);
  162|      0|        if (r >= 0 || r == M_PROPERTY_UNAVAILABLE)
  ------------------
  |  Branch (162:13): [True: 0, False: 0]
  |  Branch (162:23): [True: 0, False: 0]
  ------------------
  163|      0|            return r;
  164|      0|        if ((r = do_action(prop_list, name, M_PROPERTY_GET_TYPE, arg, ctx)) >= 0)
  ------------------
  |  Branch (164:13): [True: 0, False: 0]
  ------------------
  165|      0|            return r;
  166|      0|        return M_PROPERTY_NOT_IMPLEMENTED;
  167|      0|    }
  168|      0|    case M_PROPERTY_SET: {
  ------------------
  |  Branch (168:5): [True: 0, False: 9.55k]
  ------------------
  169|      0|        return do_action(prop_list, name, M_PROPERTY_SET, arg, ctx);
  170|      0|    }
  171|      0|    case M_PROPERTY_GET_NODE: {
  ------------------
  |  Branch (171:5): [True: 0, False: 9.55k]
  ------------------
  172|      0|        if ((r = do_action(prop_list, name, M_PROPERTY_GET_NODE, arg, ctx)) !=
  ------------------
  |  Branch (172:13): [True: 0, False: 0]
  ------------------
  173|      0|            M_PROPERTY_NOT_IMPLEMENTED)
  174|      0|            return r;
  175|      0|        if ((r = do_action(prop_list, name, M_PROPERTY_GET, &val, ctx)) <= 0)
  ------------------
  |  Branch (175:13): [True: 0, False: 0]
  ------------------
  176|      0|            return r;
  177|      0|        struct mpv_node *node = arg;
  178|      0|        int err = m_option_get_node(&opt, NULL, node, &val);
  179|      0|        if (err == M_OPT_UNKNOWN) {
  ------------------
  |  |  517|      0|#define M_OPT_UNKNOWN           -1
  ------------------
  |  Branch (179:13): [True: 0, False: 0]
  ------------------
  180|      0|            r = M_PROPERTY_NOT_IMPLEMENTED;
  181|      0|        } else if (err < 0) {
  ------------------
  |  Branch (181:20): [True: 0, False: 0]
  ------------------
  182|      0|            r = M_PROPERTY_INVALID_FORMAT;
  183|      0|        } else {
  184|      0|            r = M_PROPERTY_OK;
  185|      0|        }
  186|      0|        m_option_free(&opt, &val);
  187|      0|        return r;
  188|      0|    }
  189|      0|    case M_PROPERTY_SET_NODE: {
  ------------------
  |  Branch (189:5): [True: 0, False: 9.55k]
  ------------------
  190|      0|        if (!log)
  ------------------
  |  Branch (190:13): [True: 0, False: 0]
  ------------------
  191|      0|            return M_PROPERTY_ERROR;
  192|      0|        if ((r = do_action(prop_list, name, M_PROPERTY_SET_NODE, arg, ctx)) !=
  ------------------
  |  Branch (192:13): [True: 0, False: 0]
  ------------------
  193|      0|            M_PROPERTY_NOT_IMPLEMENTED)
  194|      0|            return r;
  195|      0|        int err = m_option_set_node_or_string(log, &opt, name, &val, arg);
  196|      0|        if (err == M_OPT_UNKNOWN) {
  ------------------
  |  |  517|      0|#define M_OPT_UNKNOWN           -1
  ------------------
  |  Branch (196:13): [True: 0, False: 0]
  ------------------
  197|      0|            r = M_PROPERTY_NOT_IMPLEMENTED;
  198|      0|        } else if (err < 0) {
  ------------------
  |  Branch (198:20): [True: 0, False: 0]
  ------------------
  199|      0|            r = M_PROPERTY_INVALID_FORMAT;
  200|      0|        } else {
  201|      0|            r = do_action(prop_list, name, M_PROPERTY_SET, &val, ctx);
  202|      0|        }
  203|      0|        m_option_free(&opt, &val);
  204|      0|        return r;
  205|      0|    }
  206|    241|    default:
  ------------------
  |  Branch (206:5): [True: 241, False: 9.31k]
  ------------------
  207|    241|        return do_action(prop_list, name, action, arg, ctx);
  208|  9.55k|    }
  209|  9.55k|}
m_property_split_path:
  212|     57|{
  213|     57|    char *next = strchr(path, '/');
  214|     57|    if (next) {
  ------------------
  |  Branch (214:9): [True: 24, False: 33]
  ------------------
  215|     24|        *prefix = bstr_splice(bstr0(path), 0, next - path);
  216|     24|        *rem = next + 1;
  217|     24|        return true;
  218|     33|    } else {
  219|     33|        *prefix = bstr0(path);
  220|     33|        *rem = "";
  221|     33|        return false;
  222|     33|    }
  223|     57|}
m_properties_expand_string:
  290|  8.45k|{
  291|  8.45k|    char *ret = NULL;
  292|  8.45k|    int ret_len = 0;
  293|  8.45k|    bool skip = false;
  294|  8.45k|    int level = 0, skip_level = 0;
  295|  8.45k|    bstr str = bstr0(str0);
  296|  8.45k|#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  297|  8.45k|    int n = 0;
  298|  8.45k|#endif
  299|       |
  300|   196k|    while (str.len) {
  ------------------
  |  Branch (300:12): [True: 188k, False: 8.40k]
  ------------------
  301|   188k|        if (level > 0 && bstr_eatstart0(&str, "}")) {
  ------------------
  |  Branch (301:13): [True: 54.7k, False: 133k]
  |  Branch (301:26): [True: 12.1k, False: 42.6k]
  ------------------
  302|  12.1k|            if (skip && level <= skip_level)
  ------------------
  |  Branch (302:17): [True: 9.10k, False: 3.05k]
  |  Branch (302:25): [True: 9.04k, False: 64]
  ------------------
  303|  9.04k|                skip = false;
  304|  12.1k|            level--;
  305|   176k|        } else if (bstr_startswith0(str, "${") && bstr_find0(str, "}") >= 0) {
  ------------------
  |  Branch (305:20): [True: 14.5k, False: 161k]
  |  Branch (305:51): [True: 12.5k, False: 1.99k]
  ------------------
  306|  12.5k|            str = bstr_cut(str, 2);
  307|  12.5k|            level++;
  308|       |
  309|       |            // Assume ":" and "}" can't be part of the property name
  310|       |            // => if ":" comes before "}", it must be for the fallback
  311|  12.5k|            int term_pos = bstrcspn(str, ":}");
  312|  12.5k|            bstr name = bstr_splice(str, 0, term_pos < 0 ? str.len : term_pos);
  ------------------
  |  Branch (312:45): [True: 0, False: 12.5k]
  ------------------
  313|  12.5k|            str = bstr_cut(str, term_pos);
  314|  12.5k|            bool have_fallback = bstr_eatstart0(&str, ":");
  315|       |
  316|  12.5k|#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  317|  12.5k|            if (n++ > 10)
  ------------------
  |  Branch (317:17): [True: 27, False: 12.5k]
  ------------------
  318|     27|                break;
  319|  12.5k|#endif
  320|       |
  321|  12.5k|            if (!skip) {
  ------------------
  |  Branch (321:17): [True: 12.4k, False: 69]
  ------------------
  322|  12.4k|                skip = expand_property(prop_list, &ret, &ret_len, name,
  323|  12.4k|                                       have_fallback, ctx);
  324|  12.4k|                if (skip)
  ------------------
  |  Branch (324:21): [True: 9.07k, False: 3.37k]
  ------------------
  325|  9.07k|                    skip_level = level;
  326|  12.4k|            }
  327|   163k|        } else if (level == 0 && bstr_eatstart0(&str, "$>")) {
  ------------------
  |  Branch (327:20): [True: 121k, False: 42.1k]
  |  Branch (327:34): [True: 24, False: 121k]
  ------------------
  328|     24|            append_str(&ret, &ret_len, str);
  329|     24|            break;
  330|   163k|        } else {
  331|   163k|            char c;
  332|       |
  333|       |            // Other combinations, e.g. "$x", are added verbatim
  334|   163k|            if (bstr_eatstart0(&str, "$$")) {
  ------------------
  |  Branch (334:17): [True: 284, False: 163k]
  ------------------
  335|    284|                c = '$';
  336|   163k|            } else if (bstr_eatstart0(&str, "$}")) {
  ------------------
  |  Branch (336:24): [True: 805, False: 162k]
  ------------------
  337|    805|                c = '}';
  338|   162k|            } else {
  339|   162k|                c = str.start[0];
  340|   162k|                str = bstr_cut(str, 1);
  341|   162k|            }
  342|       |
  343|   163k|            if (!skip)
  ------------------
  |  Branch (343:17): [True: 128k, False: 35.4k]
  ------------------
  344|   128k|                MP_TARRAY_APPEND(NULL, ret, ret_len, c);
  ------------------
  |  |  105|   128k|    do {                                            \
  |  |  106|   128k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|   128k|    do {                                            \
  |  |  |  |   97|   128k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|   128k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|   128k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|   128k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 9.97k, False: 118k]
  |  |  |  |  ------------------
  |  |  |  |   99|   128k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  9.97k|    do {                                                        \
  |  |  |  |  |  |   89|  9.97k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  9.97k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  9.97k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  9.97k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  9.97k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  9.97k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  9.97k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|   128k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|   128k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|   128k|        (idxvar)++;                                 \
  |  |  109|   128k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  345|   163k|        }
  346|   188k|    }
  347|       |
  348|  8.45k|    MP_TARRAY_APPEND(NULL, ret, ret_len, '\0');
  ------------------
  |  |  105|  8.45k|    do {                                            \
  |  |  106|  8.45k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  8.45k|    do {                                            \
  |  |  |  |   97|  8.45k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  8.45k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  8.45k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  8.45k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 3.82k, False: 4.62k]
  |  |  |  |  ------------------
  |  |  |  |   99|  8.45k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  3.82k|    do {                                                        \
  |  |  |  |  |  |   89|  3.82k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  3.82k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  3.82k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  3.82k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  3.82k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  3.82k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  3.82k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  8.45k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  8.45k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  8.45k|        (idxvar)++;                                 \
  |  |  109|  8.45k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  349|  8.45k|    return ret;
  350|  8.45k|}
m_property_bool_ro:
  367|    218|{
  368|    218|    switch (action) {
  ------------------
  |  Branch (368:13): [True: 66, False: 152]
  ------------------
  369|     76|    case M_PROPERTY_GET:
  ------------------
  |  Branch (369:5): [True: 76, False: 142]
  ------------------
  370|     76|        *(bool *)arg = !!var;
  371|     76|        return M_PROPERTY_OK;
  372|     76|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (372:5): [True: 76, False: 142]
  ------------------
  373|     76|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_BOOL};
  ------------------
  |  |  227|     76|#define CONF_TYPE_BOOL          (&m_option_type_bool)
  ------------------
  374|     76|        return M_PROPERTY_OK;
  375|    218|    }
  376|     66|    return M_PROPERTY_NOT_IMPLEMENTED;
  377|    218|}
m_property_int_ro:
  380|    180|{
  381|    180|    switch (action) {
  ------------------
  |  Branch (381:13): [True: 60, False: 120]
  ------------------
  382|     60|    case M_PROPERTY_GET:
  ------------------
  |  Branch (382:5): [True: 60, False: 120]
  ------------------
  383|     60|        *(int *)arg = var;
  384|     60|        return M_PROPERTY_OK;
  385|     60|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (385:5): [True: 60, False: 120]
  ------------------
  386|     60|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_INT};
  ------------------
  |  |  229|     60|#define CONF_TYPE_INT           (&m_option_type_int)
  ------------------
  387|     60|        return M_PROPERTY_OK;
  388|    180|    }
  389|     60|    return M_PROPERTY_NOT_IMPLEMENTED;
  390|    180|}
m_property_int64_ro:
  393|    180|{
  394|    180|    switch (action) {
  ------------------
  |  Branch (394:13): [True: 60, False: 120]
  ------------------
  395|     60|    case M_PROPERTY_GET:
  ------------------
  |  Branch (395:5): [True: 60, False: 120]
  ------------------
  396|     60|        *(int64_t *)arg = var;
  397|     60|        return M_PROPERTY_OK;
  398|     60|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (398:5): [True: 60, False: 120]
  ------------------
  399|     60|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_INT64};
  ------------------
  |  |  230|     60|#define CONF_TYPE_INT64         (&m_option_type_int64)
  ------------------
  400|     60|        return M_PROPERTY_OK;
  401|    180|    }
  402|     60|    return M_PROPERTY_NOT_IMPLEMENTED;
  403|    180|}
m_property_strdup_ro:
  432|    325|{
  433|    325|    if (!var)
  ------------------
  |  Branch (433:9): [True: 20, False: 305]
  ------------------
  434|     20|        return M_PROPERTY_UNAVAILABLE;
  435|    305|    switch (action) {
  ------------------
  |  Branch (435:13): [True: 73, False: 232]
  ------------------
  436|    116|    case M_PROPERTY_GET:
  ------------------
  |  Branch (436:5): [True: 116, False: 189]
  ------------------
  437|    116|        *(char **)arg = talloc_strdup(NULL, var);
  ------------------
  |  |   50|    116|#define talloc_strdup                   ta_xstrdup
  ------------------
  438|    116|        return M_PROPERTY_OK;
  439|    116|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (439:5): [True: 116, False: 189]
  ------------------
  440|    116|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_STRING};
  ------------------
  |  |  233|    116|#define CONF_TYPE_STRING        (&m_option_type_string)
  ------------------
  441|    116|        return M_PROPERTY_OK;
  442|    305|    }
  443|     73|    return M_PROPERTY_NOT_IMPLEMENTED;
  444|    305|}
m_property_read_sub:
  468|  1.61M|{
  469|  1.61M|    m_property_unkey(&action, &arg);
  470|  1.61M|    switch (action) {
  ------------------
  |  Branch (470:13): [True: 524k, False: 1.08M]
  ------------------
  471|   524k|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (471:5): [True: 524k, False: 1.08M]
  ------------------
  472|   524k|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_NODE};
  ------------------
  |  |  241|   524k|#define CONF_TYPE_NODE          (&m_option_type_node)
  ------------------
  473|   524k|        return M_PROPERTY_OK;
  474|   524k|    case M_PROPERTY_GET: {
  ------------------
  |  Branch (474:5): [True: 524k, False: 1.08M]
  ------------------
  475|   524k|        struct mpv_node node;
  476|   524k|        node.format = MPV_FORMAT_NODE_MAP;
  477|   524k|        node.u.list = talloc_zero(NULL, mpv_node_list);
  ------------------
  |  |   27|   524k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|   524k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|   524k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  478|   524k|        mpv_node_list *list = node.u.list;
  479|  2.15M|        for (int n = 0; props && props[n].name; n++) {
  ------------------
  |  Branch (479:25): [True: 2.15M, False: 0]
  |  Branch (479:34): [True: 1.62M, False: 524k]
  ------------------
  480|  1.62M|            const struct m_sub_property *prop = &props[n];
  481|  1.62M|            if (prop->unavailable)
  ------------------
  |  Branch (481:17): [True: 72.8k, False: 1.55M]
  ------------------
  482|  72.8k|                continue;
  483|  1.55M|            MP_TARRAY_GROW(list, list->values, list->num);
  ------------------
  |  |   96|  1.55M|    do {                                            \
  |  |   97|  1.55M|        size_t nextidx_ = (nextidx);                \
  |  |   98|  1.55M|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  ------------------
  |  |  |  |   84|  1.55M|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  ------------------
  |  |  |  |  |  |   45|  1.55M|#define talloc_get_size                 ta_get_size
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  |  Branch (98:13): [True: 1.03M, False: 524k]
  |  |  ------------------
  |  |   99|  1.55M|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  ------------------
  |  |  |  |   88|  1.03M|    do {                                                        \
  |  |  |  |   89|  1.03M|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|  1.03M|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|  1.03M|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|  1.03M|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|  1.03M|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   90|  1.03M|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |   91|  1.03M|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  100|  1.55M|    } while (0)
  |  |  ------------------
  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  484|  1.55M|            MP_TARRAY_GROW(list, list->keys, list->num);
  ------------------
  |  |   96|  1.55M|    do {                                            \
  |  |   97|  1.55M|        size_t nextidx_ = (nextidx);                \
  |  |   98|  1.55M|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  ------------------
  |  |  |  |   84|  1.55M|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  ------------------
  |  |  |  |  |  |   45|  1.55M|#define talloc_get_size                 ta_get_size
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  |  Branch (98:13): [True: 1.03M, False: 524k]
  |  |  ------------------
  |  |   99|  1.55M|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  ------------------
  |  |  |  |   88|  1.03M|    do {                                                        \
  |  |  |  |   89|  1.03M|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|  1.03M|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|  1.03M|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|  1.03M|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|  1.03M|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   90|  1.03M|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |   91|  1.03M|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  100|  1.55M|    } while (0)
  |  |  ------------------
  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  485|  1.55M|            mpv_node *val = &list->values[list->num];
  486|  1.55M|            if (m_option_get_node(&prop->type, list, val, (void*)&prop->value) < 0)
  ------------------
  |  Branch (486:17): [True: 0, False: 1.55M]
  ------------------
  487|      0|            {
  488|      0|                char *s = m_option_print(&prop->type, &prop->value);
  489|      0|                val->format = MPV_FORMAT_STRING;
  490|      0|                val->u.string = talloc_steal(list, s);
  ------------------
  |  |   38|      0|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  491|      0|            }
  492|  1.55M|            list->keys[list->num] = (char *)prop->name;
  493|  1.55M|            list->num++;
  494|  1.55M|        }
  495|   524k|        *(struct mpv_node *)arg = node;
  496|   524k|        return M_PROPERTY_OK;
  497|      0|    }
  498|  37.6k|    case M_PROPERTY_PRINT: {
  ------------------
  |  Branch (498:5): [True: 37.6k, False: 1.57M]
  ------------------
  499|       |        // Output "something" - what it really should return is not yet decided.
  500|       |        // It should probably be something that is easy to consume by slave
  501|       |        // mode clients. (M_PROPERTY_PRINT on the other hand can return this
  502|       |        // as human readable version just fine).
  503|  37.6k|        char *res = NULL;
  504|   150k|        for (int n = 0; props && props[n].name; n++) {
  ------------------
  |  Branch (504:25): [True: 150k, False: 0]
  |  Branch (504:34): [True: 112k, False: 37.6k]
  ------------------
  505|   112k|            const struct m_sub_property *prop = &props[n];
  506|   112k|            if (prop->unavailable)
  ------------------
  |  Branch (506:17): [True: 76, False: 112k]
  ------------------
  507|     76|                continue;
  508|   112k|            char *s = m_option_print(&prop->type, &prop->value);
  509|   112k|            ta_xasprintf_append(&res, "%s=%s\n", prop->name, s);
  ------------------
  |  |  129|   112k|#define ta_xasprintf_append(...)        ta_oom_b(ta_asprintf_append(__VA_ARGS__))
  ------------------
  510|   112k|            talloc_free(s);
  ------------------
  |  |   47|   112k|#define talloc_free                     ta_free
  ------------------
  511|   112k|        }
  512|  37.6k|        *(char **)arg = res;
  513|  37.6k|        return M_PROPERTY_OK;
  514|      0|    }
  515|    395|    case M_PROPERTY_KEY_ACTION: {
  ------------------
  |  Branch (515:5): [True: 395, False: 1.61M]
  ------------------
  516|    395|        struct m_property_action_arg *ka = arg;
  517|    395|        const struct m_sub_property *prop = NULL;
  518|  1.61k|        for (int n = 0; props && props[n].name; n++) {
  ------------------
  |  Branch (518:25): [True: 1.61k, False: 0]
  |  Branch (518:34): [True: 1.51k, False: 106]
  ------------------
  519|  1.51k|            if (strcmp(props[n].name, ka->key) == 0) {
  ------------------
  |  Branch (519:17): [True: 289, False: 1.22k]
  ------------------
  520|    289|                prop = &props[n];
  521|    289|                break;
  522|    289|            }
  523|  1.51k|        }
  524|    395|        if (!prop)
  ------------------
  |  Branch (524:13): [True: 106, False: 289]
  ------------------
  525|    106|            return M_PROPERTY_UNKNOWN;
  526|    289|        if (prop->unavailable)
  ------------------
  |  Branch (526:13): [True: 22, False: 267]
  ------------------
  527|     22|            return M_PROPERTY_UNAVAILABLE;
  528|    267|        switch (ka->action) {
  ------------------
  |  Branch (528:17): [True: 32, False: 235]
  ------------------
  529|     74|        case M_PROPERTY_GET: {
  ------------------
  |  Branch (529:9): [True: 74, False: 193]
  ------------------
  530|     74|            memset(ka->arg, 0, prop->type.type->size);
  531|     74|            m_option_copy(&prop->type, ka->arg, &prop->value);
  532|     74|            return M_PROPERTY_OK;
  533|      0|        }
  534|    161|        case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (534:9): [True: 161, False: 106]
  ------------------
  535|    161|            *(struct m_option *)ka->arg = prop->type;
  536|    161|            return M_PROPERTY_OK;
  537|    267|        }
  538|    267|    }
  539|  1.61M|    }
  540|   524k|    return M_PROPERTY_NOT_IMPLEMENTED;
  541|  1.61M|}
m_property_read_list:
  554|  5.02k|{
  555|  5.02k|    m_property_unkey(&action, &arg);
  556|  5.02k|    switch (action) {
  ------------------
  |  Branch (556:13): [True: 537, False: 4.49k]
  ------------------
  557|  1.91k|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (557:5): [True: 1.91k, False: 3.11k]
  ------------------
  558|  1.91k|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_NODE};
  ------------------
  |  |  241|  1.91k|#define CONF_TYPE_NODE          (&m_option_type_node)
  ------------------
  559|  1.91k|        return M_PROPERTY_OK;
  560|  1.55k|    case M_PROPERTY_GET: {
  ------------------
  |  Branch (560:5): [True: 1.55k, False: 3.47k]
  ------------------
  561|  1.55k|        struct mpv_node node;
  562|  1.55k|        node.format = MPV_FORMAT_NODE_ARRAY;
  563|  1.55k|        node.u.list = talloc_zero(NULL, mpv_node_list);
  ------------------
  |  |   27|  1.55k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  1.55k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  1.55k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  564|  1.55k|        node.u.list->num = count;
  565|  1.55k|        node.u.list->values = talloc_array(node.u.list, mpv_node, count);
  ------------------
  |  |   29|  1.55k|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|  1.55k|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  1.55k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  566|   525k|        for (int n = 0; n < count; n++) {
  ------------------
  |  Branch (566:25): [True: 524k, False: 1.55k]
  ------------------
  567|   524k|            struct mpv_node *sub = &node.u.list->values[n];
  568|   524k|            sub->format = MPV_FORMAT_NONE;
  569|   524k|            int r;
  570|   524k|            r = get_item(n, M_PROPERTY_GET_NODE, sub, ctx);
  571|   524k|            if (r == M_PROPERTY_NOT_IMPLEMENTED) {
  ------------------
  |  Branch (571:17): [True: 524k, False: 0]
  ------------------
  572|   524k|                struct m_option opt = {0};
  573|   524k|                r = get_item(n, M_PROPERTY_GET_TYPE, &opt, ctx);
  574|   524k|                if (r != M_PROPERTY_OK)
  ------------------
  |  Branch (574:21): [True: 0, False: 524k]
  ------------------
  575|      0|                    goto err;
  576|   524k|                union m_option_value val = m_option_value_default;
  577|   524k|                r = get_item(n, M_PROPERTY_GET, &val, ctx);
  578|   524k|                if (r != M_PROPERTY_OK)
  ------------------
  |  Branch (578:21): [True: 0, False: 524k]
  ------------------
  579|      0|                    goto err;
  580|   524k|                m_option_get_node(&opt, node.u.list, sub, &val);
  581|   524k|                m_option_free(&opt, &val);
  582|   524k|            err: ;
  583|   524k|            }
  584|   524k|        }
  585|  1.55k|        *(struct mpv_node *)arg = node;
  586|  1.55k|        return M_PROPERTY_OK;
  587|  1.55k|    }
  588|    118|    case M_PROPERTY_PRINT: {
  ------------------
  |  Branch (588:5): [True: 118, False: 4.90k]
  ------------------
  589|       |        // See m_property_read_sub() remarks.
  590|    118|        char *res = NULL;
  591|  37.7k|        for (int n = 0; n < count; n++) {
  ------------------
  |  Branch (591:25): [True: 37.6k, False: 118]
  ------------------
  592|  37.6k|            char *s = NULL;
  593|  37.6k|            int r = get_item(n, M_PROPERTY_PRINT, &s, ctx);
  594|  37.6k|            if (r != M_PROPERTY_OK) {
  ------------------
  |  Branch (594:17): [True: 0, False: 37.6k]
  ------------------
  595|      0|                talloc_free(res);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  596|      0|                return r;
  597|      0|            }
  598|  37.6k|            ta_xasprintf_append(&res, "%d: %s\n", n, s);
  ------------------
  |  |  129|  37.6k|#define ta_xasprintf_append(...)        ta_oom_b(ta_asprintf_append(__VA_ARGS__))
  ------------------
  599|  37.6k|            talloc_free(s);
  ------------------
  |  |   47|  37.6k|#define talloc_free                     ta_free
  ------------------
  600|  37.6k|        }
  601|    118|        *(char **)arg = res;
  602|    118|        return M_PROPERTY_OK;
  603|    118|    }
  604|    908|    case M_PROPERTY_KEY_ACTION: {
  ------------------
  |  Branch (604:5): [True: 908, False: 4.11k]
  ------------------
  605|    908|        struct m_property_action_arg *ka = arg;
  606|    908|        if (strcmp(ka->key, "count") == 0) {
  ------------------
  |  Branch (606:13): [True: 80, False: 828]
  ------------------
  607|     80|            switch (ka->action) {
  ------------------
  |  Branch (607:21): [True: 26, False: 54]
  ------------------
  608|     28|            case M_PROPERTY_GET_TYPE: {
  ------------------
  |  Branch (608:13): [True: 28, False: 52]
  ------------------
  609|     28|                struct m_option opt = {.type = CONF_TYPE_INT};
  ------------------
  |  |  229|     28|#define CONF_TYPE_INT           (&m_option_type_int)
  ------------------
  610|     28|                *(struct m_option *)ka->arg = opt;
  611|     28|                return M_PROPERTY_OK;
  612|      0|            }
  613|     26|            case M_PROPERTY_GET:
  ------------------
  |  Branch (613:13): [True: 26, False: 54]
  ------------------
  614|     26|                *(int *)ka->arg = MPMAX(0, count);
  ------------------
  |  |   43|     26|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 26]
  |  |  ------------------
  ------------------
  615|     26|                return M_PROPERTY_OK;
  616|     80|            }
  617|     26|            return M_PROPERTY_NOT_IMPLEMENTED;
  618|     80|        }
  619|       |        // This is expected of the form "123" or "123/rest"
  620|    828|        char *end;
  621|    828|        long int item = strtol(ka->key, &end, 10);
  622|       |        // not a number, trailing characters, etc.
  623|    828|        if (end == ka->key || (end[0] == '/' && !end[1]))
  ------------------
  |  Branch (623:13): [True: 150, False: 678]
  |  Branch (623:32): [True: 39, False: 639]
  |  Branch (623:49): [True: 18, False: 21]
  ------------------
  624|    168|            return M_PROPERTY_UNKNOWN;
  625|    660|        if (item < 0 || item >= count)
  ------------------
  |  Branch (625:13): [True: 85, False: 575]
  |  Branch (625:25): [True: 127, False: 448]
  ------------------
  626|    212|            return M_PROPERTY_UNKNOWN;
  627|    448|        if (*end) {
  ------------------
  |  Branch (627:13): [True: 321, False: 127]
  ------------------
  628|       |            // Sub-path
  629|    321|            struct m_property_action_arg n_ka = *ka;
  630|    321|            n_ka.key = end + 1;
  631|    321|            return get_item(item, M_PROPERTY_KEY_ACTION, &n_ka, ctx);
  632|    321|        } else {
  633|       |            // Direct query
  634|    127|            return get_item(item, ka->action, ka->arg, ctx);
  635|    127|        }
  636|    448|    }
  637|  5.02k|    }
  638|    537|    return M_PROPERTY_NOT_IMPLEMENTED;
  639|  5.02k|}
m_property.c:do_action:
   75|  29.3k|{
   76|  29.3k|    struct m_property *prop;
   77|  29.3k|    struct m_property_action_arg ka;
   78|  29.3k|    const char *sep = strchr(name, '/');
   79|  29.3k|    if (sep && sep[1]) {
  ------------------
  |  Branch (79:9): [True: 1.95k, False: 27.4k]
  |  Branch (79:16): [True: 1.90k, False: 56]
  ------------------
   80|  1.90k|        char base[128];
   81|  1.90k|        snprintf(base, sizeof(base), "%.*s", (int)(sep - name), name);
   82|  1.90k|        prop = m_property_list_find(prop_list, base);
   83|  1.90k|        ka = (struct m_property_action_arg) {
   84|  1.90k|            .key = sep + 1,
   85|  1.90k|            .action = action,
   86|  1.90k|            .arg = arg,
   87|  1.90k|        };
   88|  1.90k|        action = M_PROPERTY_KEY_ACTION;
   89|  1.90k|        arg = &ka;
   90|  1.90k|    } else
   91|  27.4k|        prop = m_property_list_find(prop_list, name);
   92|  29.3k|    if (!prop)
  ------------------
  |  Branch (92:9): [True: 1.57k, False: 27.8k]
  ------------------
   93|  1.57k|        return M_PROPERTY_UNKNOWN;
   94|  27.8k|    return prop->call(ctx, prop, action, arg);
   95|  29.3k|}
m_property.c:expand_property:
  257|  12.4k|{
  258|  12.4k|    bool cond_yes = bstr_eatstart0(&prop, "?");
  259|  12.4k|    bool cond_no = !cond_yes && bstr_eatstart0(&prop, "!");
  ------------------
  |  Branch (259:20): [True: 12.0k, False: 374]
  |  Branch (259:33): [True: 80, False: 11.9k]
  ------------------
  260|  12.4k|    bool test = cond_yes || cond_no;
  ------------------
  |  Branch (260:17): [True: 374, False: 12.0k]
  |  Branch (260:29): [True: 80, False: 11.9k]
  ------------------
  261|  12.4k|    bool raw = bstr_eatstart0(&prop, "=");
  262|  12.4k|    bool fixed_len = !raw && bstr_eatstart0(&prop, ">");
  ------------------
  |  Branch (262:22): [True: 10.9k, False: 1.47k]
  |  Branch (262:30): [True: 1.77k, False: 9.19k]
  ------------------
  263|  12.4k|    bstr comp_with = {0};
  264|  12.4k|    bool comp = test && bstr_split_tok(prop, "==", &prop, &comp_with);
  ------------------
  |  Branch (264:17): [True: 454, False: 11.9k]
  |  Branch (264:25): [True: 172, False: 282]
  ------------------
  265|  12.4k|    if (test && !comp)
  ------------------
  |  Branch (265:9): [True: 454, False: 11.9k]
  |  Branch (265:17): [True: 282, False: 172]
  ------------------
  266|    282|        raw = true;
  267|  12.4k|    int method = raw ? M_PROPERTY_GET_STRING : M_PROPERTY_PRINT;
  ------------------
  |  Branch (267:18): [True: 1.76k, False: 10.6k]
  ------------------
  268|  12.4k|    method = fixed_len ? M_PROPERTY_FIXED_LEN_PRINT : method;
  ------------------
  |  Branch (268:14): [True: 1.77k, False: 10.6k]
  ------------------
  269|       |
  270|  12.4k|    char *s = NULL;
  271|  12.4k|    int r = m_property_do_bstr(prop_list, prop, method, &s, ctx);
  272|  12.4k|    bool skip;
  273|  12.4k|    if (comp) {
  ------------------
  |  Branch (273:9): [True: 172, False: 12.2k]
  ------------------
  274|    172|        skip = ((s && bstr_equals0(comp_with, s)) != cond_yes);
  ------------------
  |  Branch (274:18): [True: 129, False: 43]
  |  Branch (274:23): [True: 0, False: 129]
  ------------------
  275|  12.2k|    } else if (test) {
  ------------------
  |  Branch (275:16): [True: 282, False: 11.9k]
  ------------------
  276|    282|        skip = (!!s != cond_yes);
  277|  11.9k|    } else {
  278|  11.9k|        skip = !!s;
  279|  11.9k|        char *append = s;
  280|  11.9k|        if (!s && !silent_error && !raw)
  ------------------
  |  Branch (280:13): [True: 3.18k, False: 8.81k]
  |  Branch (280:19): [True: 2.50k, False: 673]
  |  Branch (280:36): [True: 2.31k, False: 191]
  ------------------
  281|  2.31k|            append = (r == M_PROPERTY_UNAVAILABLE) ? "(unavailable)" : "(error)";
  ------------------
  |  Branch (281:22): [True: 735, False: 1.58k]
  ------------------
  282|  11.9k|        append_str(ret, ret_len, bstr0(append));
  283|  11.9k|    }
  284|  12.4k|    talloc_free(s);
  ------------------
  |  |   47|  12.4k|#define talloc_free                     ta_free
  ------------------
  285|  12.4k|    return skip;
  286|  12.4k|}
m_property.c:m_property_do_bstr:
  240|  12.4k|{
  241|  12.4k|    char *name0 = bstrdup0(NULL, name);
  242|  12.4k|    int ret = m_property_do(NULL, prop_list, name0, action, arg, ctx);
  243|  12.4k|    talloc_free(name0);
  ------------------
  |  |   47|  12.4k|#define talloc_free                     ta_free
  ------------------
  244|  12.4k|    return ret;
  245|  12.4k|}
m_property.c:append_str:
  248|  12.0k|{
  249|  12.0k|    MP_TARRAY_GROW(NULL, *s, *len + append.len);
  ------------------
  |  |   96|  12.0k|    do {                                            \
  |  |   97|  12.0k|        size_t nextidx_ = (nextidx);                \
  |  |   98|  12.0k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  ------------------
  |  |  |  |   84|  12.0k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  ------------------
  |  |  |  |  |  |   45|  12.0k|#define talloc_get_size                 ta_get_size
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  |  Branch (98:13): [True: 6.26k, False: 5.75k]
  |  |  ------------------
  |  |   99|  12.0k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  ------------------
  |  |  |  |   88|  6.26k|    do {                                                        \
  |  |  |  |   89|  6.26k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|  6.26k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|  6.26k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|  6.26k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|  6.26k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   90|  6.26k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |   91|  6.26k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  100|  12.0k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  250|  12.0k|    if (append.len)
  ------------------
  |  Branch (250:9): [True: 10.9k, False: 1.06k]
  ------------------
  251|  10.9k|        memcpy(*s + *len, append.start, append.len);
  252|  12.0k|    *len = *len + append.len;
  253|  12.0k|}
m_property.c:m_property_unkey:
  228|  1.61M|{
  229|  1.61M|    if (*action == M_PROPERTY_KEY_ACTION) {
  ------------------
  |  Branch (229:9): [True: 1.40k, False: 1.61M]
  ------------------
  230|  1.40k|        struct m_property_action_arg *ka = *arg;
  231|  1.40k|        if (!ka->key[0]) {
  ------------------
  |  Branch (231:13): [True: 100, False: 1.30k]
  ------------------
  232|    100|            *action = ka->action;
  233|    100|            *arg = ka->arg;
  234|    100|        }
  235|  1.40k|    }
  236|  1.61M|}

options.c:print_version:
   56|    912|{
   57|    912|    mp_print_version(log, true);
   58|    912|}

m_config_parse_mp_command_line:
  123|  17.0k|{
  124|  17.0k|    int ret = M_OPT_UNKNOWN;
  ------------------
  |  |  517|  17.0k|#define M_OPT_UNKNOWN           -1
  ------------------
  125|  17.0k|    int mode = 0;
  126|  17.0k|    struct playlist_entry *local_start = NULL;
  127|       |
  128|  17.0k|    int local_params_count = 0;
  129|  17.0k|    struct playlist_param *local_params = 0;
  130|       |
  131|  17.0k|    mp_assert(config != NULL);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  132|       |
  133|  17.0k|    mode = GLOBAL;
  ------------------
  |  |   34|  17.0k|#define GLOBAL 0
  ------------------
  134|       |
  135|  17.0k|    struct parse_state p = {config, argv, config->log};
  136|   198k|    while (split_opt(&p)) {
  ------------------
  |  Branch (136:12): [True: 185k, False: 12.2k]
  ------------------
  137|   185k|        if (p.is_opt) {
  ------------------
  |  Branch (137:13): [True: 90.4k, False: 95.4k]
  ------------------
  138|  90.4k|            int flags = M_SETOPT_FROM_CMDLINE;
  139|  90.4k|            if (mode == LOCAL)
  ------------------
  |  |   35|  90.4k|#define LOCAL 1
  ------------------
  |  Branch (139:17): [True: 5.78k, False: 84.7k]
  ------------------
  140|  5.78k|                flags |= M_SETOPT_BACKUP | M_SETOPT_CHECK_ONLY;
  141|  90.4k|            int r = m_config_set_option_cli(config, p.arg, p.param, flags);
  142|  90.4k|            if (r == M_OPT_EXIT) {
  ------------------
  |  |  533|  90.4k|#define M_OPT_EXIT              -6
  ------------------
  |  Branch (142:17): [True: 385, False: 90.1k]
  ------------------
  143|    385|                ret = r;
  144|    385|                goto err_out;
  145|  90.1k|            } else if (r < 0) {
  ------------------
  |  Branch (145:24): [True: 4.36k, False: 85.7k]
  ------------------
  146|  4.36k|                MP_FATAL(config, "Setting commandline option --%.*s=%.*s failed.\n",
  ------------------
  |  |   84|  4.36k|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  17.4k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 4.36k, False: 0]
  |  |  |  |  |  Branch (82:57): [True: 4.36k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  147|  4.36k|                         BSTR_P(p.arg), BSTR_P(p.param));
  148|  4.36k|                goto err_out;
  149|  4.36k|            }
  150|       |
  151|       |            // Handle some special arguments outside option parser.
  152|       |
  153|  85.7k|            if (!bstrcmp0(p.arg, "{")) {
  ------------------
  |  Branch (153:17): [True: 1.08k, False: 84.6k]
  ------------------
  154|  1.08k|                if (mode != GLOBAL) {
  ------------------
  |  |   34|  1.08k|#define GLOBAL 0
  ------------------
  |  Branch (154:21): [True: 2, False: 1.08k]
  ------------------
  155|      2|                    MP_ERR(config, "'--{' can not be nested.\n");
  ------------------
  |  |   85|      2|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      2|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  156|      2|                    goto err_out;
  157|      2|                }
  158|  1.08k|                mode = LOCAL;
  ------------------
  |  |   35|  1.08k|#define LOCAL 1
  ------------------
  159|  1.08k|                mp_assert(!local_start);
  ------------------
  |  |   41|  1.08k|#define mp_assert assert
  ------------------
  160|  1.08k|                local_start = playlist_get_last(files);
  161|  1.08k|                continue;
  162|  1.08k|            }
  163|       |
  164|  84.6k|            if (!bstrcmp0(p.arg, "}")) {
  ------------------
  |  Branch (164:17): [True: 989, False: 83.6k]
  ------------------
  165|    989|                if (mode != LOCAL) {
  ------------------
  |  |   35|    989|#define LOCAL 1
  ------------------
  |  Branch (165:21): [True: 18, False: 971]
  ------------------
  166|     18|                    MP_ERR(config, "Too many closing '--}'.\n");
  ------------------
  |  |   85|     18|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     18|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  167|     18|                    goto err_out;
  168|     18|                }
  169|    971|                if (local_params_count) {
  ------------------
  |  Branch (169:21): [True: 286, False: 685]
  ------------------
  170|       |                    // The files added between '{' and '}' are the entries from
  171|       |                    // the entry _after_ local_start, until the end of the list.
  172|       |                    // If local_start is NULL, the list was empty on '{', and we
  173|       |                    // want all files in the list.
  174|    286|                    struct playlist_entry *cur = local_start
  ------------------
  |  Branch (174:50): [True: 136, False: 150]
  ------------------
  175|    286|                        ? playlist_entry_get_rel(local_start, 1)
  176|    286|                        : playlist_get_first(files);
  177|    286|                    if (!cur)
  ------------------
  |  Branch (177:25): [True: 166, False: 120]
  ------------------
  178|    286|                        MP_WARN(config, "Ignored options!\n");
  ------------------
  |  |   86|    166|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    166|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  179|  2.10k|                    while (cur) {
  ------------------
  |  Branch (179:28): [True: 1.81k, False: 286]
  ------------------
  180|  1.81k|                        playlist_entry_add_params(cur, local_params,
  181|  1.81k|                                                local_params_count);
  182|  1.81k|                        cur = playlist_entry_get_rel(cur, 1);
  183|  1.81k|                    }
  184|    286|                }
  185|    971|                local_params_count = 0;
  186|    971|                mode = GLOBAL;
  ------------------
  |  |   34|    971|#define GLOBAL 0
  ------------------
  187|    971|                m_config_restore_backups(config);
  188|    971|                local_start = NULL;
  189|    971|                continue;
  190|    989|            }
  191|       |
  192|  83.6k|            if (bstrcmp0(p.arg, "playlist") == 0) {
  ------------------
  |  Branch (192:17): [True: 0, False: 83.6k]
  ------------------
  193|       |                // append the playlist to the local args
  194|      0|                char *param0 = bstrdup0(NULL, p.param);
  195|      0|                struct playlist *pl = playlist_parse_file(param0, NULL, global);
  196|      0|                if (!pl) {
  ------------------
  |  Branch (196:21): [True: 0, False: 0]
  ------------------
  197|      0|                    MP_FATAL(config, "Error reading playlist '%.*s'\n",
  ------------------
  |  |   84|      0|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  198|      0|                             BSTR_P(p.param));
  199|      0|                    talloc_free(param0);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  200|      0|                    goto err_out;
  201|      0|                }
  202|      0|                playlist_transfer_entries(files, pl);
  203|      0|                talloc_free(param0);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  204|      0|                talloc_free(pl);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  205|      0|                continue;
  206|      0|            }
  207|       |
  208|  83.6k|            if (mode == LOCAL) {
  ------------------
  |  |   35|  83.6k|#define LOCAL 1
  ------------------
  |  Branch (208:17): [True: 4.78k, False: 78.8k]
  ------------------
  209|  4.78k|                MP_TARRAY_APPEND(NULL, local_params, local_params_count,
  ------------------
  |  |  105|  4.78k|    do {                                            \
  |  |  106|  4.78k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  4.78k|    do {                                            \
  |  |  |  |   97|  4.78k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  4.78k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  4.78k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  4.78k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 458, False: 4.33k]
  |  |  |  |  ------------------
  |  |  |  |   99|  4.78k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|    458|    do {                                                        \
  |  |  |  |  |  |   89|    458|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|    458|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|    458|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|    458|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|    458|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|    458|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|    458|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  4.78k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  4.78k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  4.78k|        (idxvar)++;                                 \
  |  |  109|  4.78k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  210|  4.78k|                                 (struct playlist_param) {p.arg, p.param});
  211|  4.78k|            }
  212|  95.4k|        } else {
  213|       |            // filename
  214|  95.4k|            void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|  95.4k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  95.4k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  215|  95.4k|            char *file0 = bstrdup0(tmp, p.arg);
  216|  95.4k|            process_non_option(files, file0);
  217|  95.4k|            talloc_free(tmp);
  ------------------
  |  |   47|  95.4k|#define talloc_free                     ta_free
  ------------------
  218|  95.4k|        }
  219|   185k|    }
  220|       |
  221|  12.2k|    if (p.error)
  ------------------
  |  Branch (221:9): [True: 61, False: 12.2k]
  ------------------
  222|     61|        goto err_out;
  223|       |
  224|  12.2k|    if (mode != GLOBAL) {
  ------------------
  |  |   34|  12.2k|#define GLOBAL 0
  ------------------
  |  Branch (224:9): [True: 90, False: 12.1k]
  ------------------
  225|     90|        MP_ERR(config, "Missing closing --} on command line.\n");
  ------------------
  |  |   85|     90|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     90|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  226|     90|        goto err_out;
  227|     90|    }
  228|       |
  229|  12.1k|    ret = 0; // success
  230|       |
  231|  17.0k|err_out:
  232|  17.0k|    talloc_free(local_params);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  233|  17.0k|    m_config_restore_backups(config);
  234|  17.0k|    return ret;
  235|  12.1k|}
m_config_preparse_command_line:
  244|  17.0k|{
  245|  17.0k|    struct parse_state p = {config, argv, mp_null_log};
  246|   216k|    while (split_opt(&p)) {
  ------------------
  |  Branch (246:12): [True: 199k, False: 17.0k]
  ------------------
  247|   199k|        if (p.is_opt) {
  ------------------
  |  Branch (247:13): [True: 101k, False: 98.2k]
  ------------------
  248|       |            // Ignore non-pre-parse options. They will be set later.
  249|       |            // Option parsing errors will be handled later as well.
  250|   101k|            int flags = M_SETOPT_FROM_CMDLINE | M_SETOPT_PRE_PARSE_ONLY;
  251|   101k|            m_config_set_option_cli(config, p.arg, p.param, flags);
  252|   101k|            if (bstrcmp0(p.arg, "v") == 0)
  ------------------
  |  Branch (252:17): [True: 11.2k, False: 90.0k]
  ------------------
  253|  11.2k|                (*verbose)++;
  254|   101k|        }
  255|   199k|    }
  256|       |
  257|  12.7M|    for (int n = 0; n < config->num_opts; n++)
  ------------------
  |  Branch (257:21): [True: 12.7M, False: 17.0k]
  ------------------
  258|  12.7M|        config->opts[n].warning_was_printed = false;
  259|  17.0k|}
parse_commandline.c:split_opt:
   52|   414k|{
   53|   414k|    mp_assert(!p->error);
  ------------------
  |  |   41|   414k|#define mp_assert assert
  ------------------
   54|       |
   55|   414k|    if (!p->argv || !p->argv[0])
  ------------------
  |  Branch (55:9): [True: 0, False: 414k]
  |  Branch (55:21): [True: 29.2k, False: 385k]
  ------------------
   56|  29.2k|        return false;
   57|       |
   58|   385k|    p->is_opt = false;
   59|   385k|    p->arg = bstr0(p->argv[0]);
   60|   385k|    p->param = bstr0(NULL);
   61|       |
   62|   385k|    p->argv++;
   63|       |
   64|   385k|    if (p->no_more_opts || !bstr_startswith0(p->arg, "-") || p->arg.len == 1)
  ------------------
  |  Branch (64:9): [True: 2.06k, False: 383k]
  |  Branch (64:28): [True: 186k, False: 197k]
  |  Branch (64:62): [True: 5.09k, False: 192k]
  ------------------
   65|   193k|        return true;
   66|       |
   67|   192k|    if (bstrcmp0(p->arg, "--") == 0) {
  ------------------
  |  Branch (67:9): [True: 55, False: 191k]
  ------------------
   68|     55|        p->no_more_opts = true;
   69|     55|        return split_opt(p);
   70|     55|    }
   71|       |
   72|   191k|    p->is_opt = true;
   73|       |
   74|   191k|    bool new_opt = bstr_eatstart0(&p->arg, "--");
   75|   191k|    if (!new_opt)
  ------------------
  |  Branch (75:9): [True: 188k, False: 3.50k]
  ------------------
   76|   188k|        bstr_eatstart0(&p->arg, "-");
   77|       |
   78|   191k|    bool ambiguous = !bstr_split_tok(p->arg, "=", &p->arg, &p->param);
   79|       |
   80|   191k|    bool need_param = m_config_option_requires_param(p->config, p->arg) > 0;
   81|       |
   82|   191k|    if (ambiguous && need_param) {
  ------------------
  |  Branch (82:9): [True: 173k, False: 18.1k]
  |  Branch (82:22): [True: 118k, False: 55.3k]
  ------------------
   83|   118k|        if (!p->argv[0] || new_opt) {
  ------------------
  |  Branch (83:13): [True: 150, False: 118k]
  |  Branch (83:28): [True: 11, False: 118k]
  ------------------
   84|    161|            p->error = true;
   85|    161|            MP_FATAL(p, "Error parsing commandline option %.*s: %s\n",
  ------------------
  |  |   84|    161|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    322|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 161, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   86|    161|                     BSTR_P(p->arg), m_option_strerror(M_OPT_MISSING_PARAM));
   87|    161|            MP_WARN(p, "Make sure you're using e.g. '--%.*s=value' instead "
  ------------------
  |  |   86|    161|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    644|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 161, False: 0]
  |  |  |  |  |  Branch (82:57): [True: 161, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   88|    161|                    "of '--%.*s value'.\n", BSTR_P(p->arg), BSTR_P(p->arg));
   89|    161|            return false;
   90|    161|        }
   91|   118k|        p->param = bstr0(p->argv[0]);
   92|   118k|        p->argv++;
   93|   118k|    }
   94|       |
   95|   191k|    return true;
   96|   191k|}
parse_commandline.c:process_non_option:
  115|  95.4k|{
  116|  95.4k|    playlist_append_file(files, arg);
  117|  95.4k|}

m_config_parse:
   45|  17.0k|{
   46|  17.0k|    m_profile_t *profile = m_config_add_profile(config, initial_section);
   47|  17.0k|    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|  17.0k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  17.0k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
   48|  17.0k|    int line_no = 0;
   49|  17.0k|    int errors = 0;
   50|       |
   51|  17.0k|    bstr_eatstart0(&data, "\xEF\xBB\xBF"); // skip BOM
   52|       |
   53|  1.67M|    while (data.len) {
  ------------------
  |  Branch (53:12): [True: 1.65M, False: 17.0k]
  ------------------
   54|  1.65M|        talloc_free_children(tmp);
  ------------------
  |  |   46|  1.65M|#define talloc_free_children            ta_free_children
  ------------------
   55|  1.65M|        bool ok = false;
   56|       |
   57|  1.65M|        line_no++;
   58|  1.65M|        char loc[512];
   59|  1.65M|        snprintf(loc, sizeof(loc), "%s:%d:", location, line_no);
   60|       |
   61|  1.65M|        bstr line = bstr_strip_linebreaks(bstr_getline(data, &data));
   62|  1.65M|        if (!skip_ws(&line))
  ------------------
  |  Branch (62:13): [True: 426k, False: 1.22M]
  ------------------
   63|   426k|            continue;
   64|       |
   65|       |        // Profile declaration
   66|  1.22M|        if (bstr_eatstart0(&line, "[")) {
  ------------------
  |  Branch (66:13): [True: 204k, False: 1.02M]
  ------------------
   67|   204k|            bstr profilename;
   68|   204k|            if (!bstr_split_tok(line, "]", &profilename, &line)) {
  ------------------
  |  Branch (68:17): [True: 0, False: 204k]
  ------------------
   69|      0|                MP_ERR(config, "%s missing closing ]\n", loc);
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
   70|      0|                goto error;
   71|      0|            }
   72|   204k|            if (skip_ws(&line)) {
  ------------------
  |  Branch (72:17): [True: 0, False: 204k]
  ------------------
   73|      0|                MP_ERR(config, "%s unparsable extra characters: '%.*s'\n",
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   74|      0|                       loc, BSTR_P(line));
   75|      0|                goto error;
   76|      0|            }
   77|   204k|            profile = m_config_add_profile(config, bstrto0(tmp, profilename));
   78|   204k|            continue;
   79|   204k|        }
   80|       |
   81|  1.02M|        bstr_eatstart0(&line, "--");
   82|       |
   83|  1.02M|        bstr option = line;
   84|  13.8M|        while (line.len && (mp_isalnum(line.start[0]) || line.start[0] == '_' ||
  ------------------
  |  Branch (84:16): [True: 13.8M, False: 0]
  |  Branch (84:29): [True: 11.7M, False: 2.13M]
  |  Branch (84:58): [True: 0, False: 2.13M]
  ------------------
   85|  13.8M|                            line.start[0] == '-'))
  ------------------
  |  Branch (85:29): [True: 1.10M, False: 1.02M]
  ------------------
   86|  12.8M|            line = bstr_cut(line, 1);
   87|  1.02M|        option.len = option.len - line.len;
   88|  1.02M|        skip_ws(&line);
   89|       |
   90|  1.02M|        bstr value = {0};
   91|  1.02M|        if (bstr_eatstart0(&line, "=")) {
  ------------------
  |  Branch (91:13): [True: 1.02M, False: 0]
  ------------------
   92|  1.02M|            skip_ws(&line);
   93|  1.02M|            if (line.len && (line.start[0] == '"' || line.start[0] == '\'')) {
  ------------------
  |  Branch (93:17): [True: 1.02M, False: 0]
  |  Branch (93:30): [True: 0, False: 1.02M]
  |  Branch (93:54): [True: 0, False: 1.02M]
  ------------------
   94|       |                // Simple quoting, like "value"
   95|      0|                char term[2] = {line.start[0], 0};
   96|      0|                line = bstr_cut(line, 1);
   97|      0|                if (!bstr_split_tok(line, term, &value, &line)) {
  ------------------
  |  Branch (97:21): [True: 0, False: 0]
  ------------------
   98|      0|                    MP_ERR(config, "%s unterminated quote\n", loc);
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
   99|      0|                    goto error;
  100|      0|                }
  101|  1.02M|            } else if (bstr_eatstart0(&line, "%")) {
  ------------------
  |  Branch (101:24): [True: 0, False: 1.02M]
  ------------------
  102|       |                // Quoting with length, like %5%value
  103|      0|                bstr rest;
  104|      0|                long long len = bstrtoll(line, &rest, 10);
  105|      0|                if (rest.len == line.len || !bstr_eatstart0(&rest, "%") ||
  ------------------
  |  Branch (105:21): [True: 0, False: 0]
  |  Branch (105:45): [True: 0, False: 0]
  ------------------
  106|      0|                    len > rest.len)
  ------------------
  |  Branch (106:21): [True: 0, False: 0]
  ------------------
  107|      0|                {
  108|      0|                    MP_ERR(config, "%s fixed-length quoting expected - put "
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  109|      0|                           "\"quotes\" around the option value if you did not "
  110|      0|                           "intend to use this, but your option value starts "
  111|      0|                           "with '%%'\n", loc);
  112|      0|                    goto error;
  113|      0|                }
  114|      0|                value = bstr_splice(rest, 0, len);
  115|      0|                line = bstr_cut(rest, len);
  116|  1.02M|            } else {
  117|       |                // No quoting; take everything until the comment or end of line
  118|  1.02M|                int end = bstrchr(line, '#');
  119|  1.02M|                value = bstr_strip(end < 0 ? line : bstr_splice(line, 0, end));
  ------------------
  |  Branch (119:36): [True: 853k, False: 170k]
  ------------------
  120|  1.02M|                line.len = 0;
  121|  1.02M|            }
  122|  1.02M|        }
  123|  1.02M|        if (skip_ws(&line)) {
  ------------------
  |  Branch (123:13): [True: 0, False: 1.02M]
  ------------------
  124|      0|            MP_ERR(config, "%s unparsable extra characters: '%.*s'\n",
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  125|      0|                   loc, BSTR_P(line));
  126|      0|            goto error;
  127|      0|        }
  128|       |
  129|  1.02M|        int res = m_config_set_profile_option(config, profile, option, value);
  130|  1.02M|        if (res < 0) {
  ------------------
  |  Branch (130:13): [True: 68.2k, False: 955k]
  ------------------
  131|  68.2k|            MP_ERR(config, "%s setting option %.*s='%.*s' failed.\n",
  ------------------
  |  |   85|  68.2k|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|   273k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 68.2k, False: 0]
  |  |  |  |  |  Branch (82:57): [True: 68.2k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  132|  68.2k|                   loc, BSTR_P(option), BSTR_P(value));
  133|  68.2k|            goto error;
  134|  68.2k|        }
  135|       |
  136|   955k|        ok = true;
  137|  1.02M|    error:
  138|  1.02M|        if (!ok)
  ------------------
  |  Branch (138:13): [True: 68.2k, False: 955k]
  ------------------
  139|  68.2k|            errors++;
  140|  1.02M|        if (errors > 16) {
  ------------------
  |  Branch (140:13): [True: 0, False: 1.02M]
  ------------------
  141|      0|            MP_ERR(config, "%s: too many errors, stopping.\n", location);
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  142|      0|            break;
  143|      0|        }
  144|  1.02M|    }
  145|       |
  146|  17.0k|    if (config->recursion_depth == 0)
  ------------------
  |  Branch (146:9): [True: 17.0k, False: 0]
  ------------------
  147|  17.0k|        m_config_finish_default_profile(config, flags);
  148|       |
  149|  17.0k|    talloc_free(tmp);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  150|  17.0k|    return 1;
  151|  17.0k|}
parse_configfile.c:skip_ws:
   36|  4.93M|{
   37|  4.93M|    *s = bstr_lstrip(*s);
   38|  4.93M|    if (bstr_startswith0(*s, "#"))
  ------------------
  |  Branch (38:9): [True: 204k, False: 4.72M]
  ------------------
   39|   204k|        s->len = 0;
   40|  4.93M|    return s->len;
   41|  4.93M|}

mp_init_paths:
  109|  17.0k|{
  110|  17.0k|    TA_FREEP(&global->configdir);
  ------------------
  |  |   81|  17.0k|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|  17.0k|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  111|       |
  112|  17.0k|    const char *force_configdir = getenv("MPV_HOME");
  113|  17.0k|    if (opts->force_configdir && opts->force_configdir[0])
  ------------------
  |  Branch (113:9): [True: 119, False: 16.9k]
  |  Branch (113:34): [True: 118, False: 1]
  ------------------
  114|    118|        force_configdir = opts->force_configdir;
  115|  17.0k|    if (!opts->load_config)
  ------------------
  |  Branch (115:9): [True: 16.3k, False: 721]
  ------------------
  116|  16.3k|        force_configdir = "";
  117|       |
  118|  17.0k|    global->configdir = mp_get_user_path(global, global, force_configdir);
  119|  17.0k|}
mp_find_user_file:
  123|  73.4k|{
  124|  73.4k|    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|  73.4k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  73.4k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  125|  73.4k|    char *res = (char *)mp_get_platform_path(tmp, global, type);
  126|  73.4k|    if (res)
  ------------------
  |  Branch (126:9): [True: 18.7k, False: 54.6k]
  ------------------
  127|  18.7k|        res = mp_path_join(talloc_ctx, res, filename);
  128|  73.4k|    talloc_free(tmp);
  ------------------
  |  |   47|  73.4k|#define talloc_free                     ta_free
  ------------------
  129|  73.4k|    MP_DBG(global, "%s path: '%s' -> '%s'\n", type, filename, res ? res : "-");
  ------------------
  |  |   89|  73.4k|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|   146k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 18.7k, False: 54.6k]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  130|  73.4k|    return res;
  131|  73.4k|}
mp_find_all_config_files:
  170|  57.1k|{
  171|  57.1k|    return mp_find_all_config_files_limited(talloc_ctx, global, 64, filename);
  172|  57.1k|}
mp_find_config_file:
  176|  7.41k|{
  177|  7.41k|    char **l = mp_find_all_config_files_limited(talloc_ctx, global, 1, filename);
  178|  7.41k|    char *r = l && l[0] ? talloc_steal(talloc_ctx, l[0]) : NULL;
  ------------------
  |  |   38|  1.48k|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|  1.48k|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  |  Branch (178:15): [True: 7.41k, False: 0]
  |  Branch (178:20): [True: 1.48k, False: 5.93k]
  ------------------
  179|  7.41k|    talloc_free(l);
  ------------------
  |  |   47|  7.41k|#define talloc_free                     ta_free
  ------------------
  180|  7.41k|    return r;
  181|  7.41k|}
mp_get_user_path:
  185|   149k|{
  186|   149k|    if (!path)
  ------------------
  |  Branch (186:9): [True: 71.1k, False: 77.9k]
  ------------------
  187|  71.1k|        return NULL;
  188|  77.9k|    char *res = NULL;
  189|  77.9k|    bstr bpath = bstr0(path);
  190|  77.9k|    if (bstr_eatstart0(&bpath, "~")) {
  ------------------
  |  Branch (190:9): [True: 45.0k, False: 32.8k]
  ------------------
  191|       |        // parse to "~" <prefix> "/" <rest>
  192|  45.0k|        bstr prefix, rest;
  193|  45.0k|        if (bstr_split_tok(bpath, "/", &prefix, &rest)) {
  ------------------
  |  Branch (193:13): [True: 43.8k, False: 1.25k]
  ------------------
  194|  43.8k|            const char *rest0 = rest.start; // ok in this case
  195|  43.8k|            if (bstr_equals0(prefix, "~")) {
  ------------------
  |  Branch (195:17): [True: 7.31k, False: 36.5k]
  ------------------
  196|  7.31k|                res = mp_find_config_file(talloc_ctx, global, rest0);
  197|  7.31k|                if (!res) {
  ------------------
  |  Branch (197:21): [True: 5.82k, False: 1.48k]
  ------------------
  198|  5.82k|                    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|  5.82k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  5.82k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  199|  5.82k|                    const char *p = mp_get_platform_path(tmp, global, "home");
  200|  5.82k|                    res = mp_path_join_bstr(talloc_ctx, bstr0(p), rest);
  201|  5.82k|                    talloc_free(tmp);
  ------------------
  |  |   47|  5.82k|#define talloc_free                     ta_free
  ------------------
  202|  5.82k|                }
  203|  36.5k|            } else if (bstr_equals0(prefix, "")) {
  ------------------
  |  Branch (203:24): [True: 591, False: 35.9k]
  ------------------
  204|    591|                char *home = getenv("HOME");
  205|    591|                if (!home)
  ------------------
  |  Branch (205:21): [True: 0, False: 591]
  ------------------
  206|      0|                    home = getenv("USERPROFILE");
  207|    591|                res = mp_path_join_bstr(talloc_ctx, bstr0(home), rest);
  208|  35.9k|            } else if (bstr_eatstart0(&prefix, "~")) {
  ------------------
  |  Branch (208:24): [True: 35.4k, False: 524]
  ------------------
  209|  35.4k|                void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|  35.4k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  35.4k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  210|  35.4k|                char type[80];
  211|  35.4k|                snprintf(type, sizeof(type), "%.*s", BSTR_P(prefix));
  ------------------
  |  |  283|  35.4k|#define BSTR_P(bstr) (int)((bstr).len), ((bstr).start ? (char*)(bstr).start : "")
  |  |  ------------------
  |  |  |  Branch (283:42): [True: 35.4k, False: 0]
  |  |  ------------------
  ------------------
  212|  35.4k|                const char *p = mp_get_platform_path(tmp, global, type);
  213|  35.4k|                res = mp_path_join_bstr(talloc_ctx, bstr0(p), rest);
  214|  35.4k|                talloc_free(tmp);
  ------------------
  |  |   47|  35.4k|#define talloc_free                     ta_free
  ------------------
  215|  35.4k|            }
  216|  43.8k|        }
  217|  45.0k|    }
  218|  77.9k|    if (!res) {
  ------------------
  |  Branch (218:9): [True: 34.6k, False: 43.3k]
  ------------------
  219|  34.6k|        res = talloc_strdup(talloc_ctx, path);
  ------------------
  |  |   50|  34.6k|#define talloc_strdup                   ta_xstrdup
  ------------------
  220|  43.3k|    } else {
  221|  43.3k|        MP_DBG(global, "user path: '%s' -> '%s'\n", path, res);
  ------------------
  |  |   89|  43.3k|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  43.3k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  222|  43.3k|    }
  223|  77.9k|    return res;
  224|   149k|}
mp_mk_user_dir:
  236|  17.0k|{
  237|  17.0k|    char *dir = mp_find_user_file(NULL, global, type, subdir);
  238|  17.0k|    if (dir)
  ------------------
  |  Branch (238:9): [True: 720, False: 16.3k]
  ------------------
  239|    720|        mp_mkdirp(dir);
  240|  17.0k|    talloc_free(dir);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  241|  17.0k|}
path.c:mp_get_platform_path:
   74|   437k|{
   75|   437k|    mp_assert(talloc_ctx);
  ------------------
  |  |   41|   437k|#define mp_assert assert
  ------------------
   76|       |
   77|   437k|    if (global->configdir) {
  ------------------
  |  Branch (77:9): [True: 384k, False: 52.5k]
  ------------------
   78|       |        // Return NULL for all platform paths if --no-config is passed
   79|   384k|        if (!global->configdir[0])
  ------------------
  |  Branch (79:13): [True: 372k, False: 12.2k]
  ------------------
   80|   372k|            return NULL;
   81|       |
   82|       |        // force all others to NULL, only first returns the path
   83|  36.9k|        for (int n = 0; n < MP_ARRAY_SIZE(config_dirs); n++) {
  ------------------
  |  |   48|  36.9k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (83:25): [True: 36.1k, False: 789]
  ------------------
   84|  36.1k|            if (strcmp(config_dirs[n], type) == 0)
  ------------------
  |  Branch (84:17): [True: 11.4k, False: 24.6k]
  ------------------
   85|  11.4k|                return (n == 0) ? global->configdir : NULL;
  ------------------
  |  Branch (85:24): [True: 3.13k, False: 8.34k]
  ------------------
   86|  36.1k|        }
   87|  12.2k|    }
   88|       |
   89|       |    // Return the native config path if the platform doesn't support the
   90|       |    // type we are trying to fetch.
   91|  53.3k|    const char *fallback_type = NULL;
   92|  53.3k|    if (!strcmp(type, "cache") || !strcmp(type, "state"))
  ------------------
  |  Branch (92:9): [True: 245, False: 53.0k]
  |  Branch (92:35): [True: 18.0k, False: 35.0k]
  ------------------
   93|  18.2k|        fallback_type = "home";
   94|       |
   95|  65.7k|    for (int n = 0; n < MP_ARRAY_SIZE(path_resolvers); n++) {
  ------------------
  |  |   48|  65.7k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (95:21): [True: 53.3k, False: 12.4k]
  ------------------
   96|  53.3k|        const char *path = path_resolvers[n](talloc_ctx, type);
   97|  53.3k|        if (path && path[0])
  ------------------
  |  Branch (97:13): [True: 40.8k, False: 12.4k]
  |  Branch (97:21): [True: 40.8k, False: 0]
  ------------------
   98|  40.8k|            return path;
   99|  53.3k|    }
  100|       |
  101|  12.4k|    if (fallback_type) {
  ------------------
  |  Branch (101:9): [True: 0, False: 12.4k]
  ------------------
  102|      0|        mp_assert(strcmp(fallback_type, type) != 0);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  103|      0|        return mp_get_platform_path(talloc_ctx, global, fallback_type);
  104|      0|    }
  105|  12.4k|    return NULL;
  106|  12.4k|}
path.c:mp_find_all_config_files_limited:
  137|  64.5k|{
  138|  64.5k|    char **ret = talloc_array(talloc_ctx, char*, 2); // 2 preallocated
  ------------------
  |  |   29|  64.5k|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|  64.5k|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  64.5k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  139|  64.5k|    int num_ret = 0;
  140|       |
  141|   387k|    for (int i = 0; i < MP_ARRAY_SIZE(config_dirs); i++) {
  ------------------
  |  |   48|   387k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (141:21): [True: 322k, False: 64.5k]
  ------------------
  142|   322k|        const char *dir = mp_get_platform_path(ret, global, config_dirs[i]);
  143|   322k|        bstr s = bstr0(filename);
  144|   345k|        while (dir && num_ret < max_files && s.len) {
  ------------------
  |  Branch (144:16): [True: 42.9k, False: 302k]
  |  Branch (144:23): [True: 39.9k, False: 2.95k]
  |  Branch (144:46): [True: 22.9k, False: 16.9k]
  ------------------
  145|  22.9k|            bstr fn;
  146|  22.9k|            bstr_split_tok(s, "|", &fn, &s);
  147|       |
  148|  22.9k|            char *file = mp_path_join_bstr(ret, bstr0(dir), fn);
  149|  22.9k|            if (mp_path_exists(file)) {
  ------------------
  |  Branch (149:17): [True: 1.48k, False: 21.5k]
  ------------------
  150|  1.48k|                MP_DBG(global, "config path: '%.*s' -> '%s'\n",
  ------------------
  |  |   89|  1.48k|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  2.97k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 1.48k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  151|  1.48k|                        BSTR_P(fn), file);
  152|  1.48k|                MP_TARRAY_APPEND(NULL, ret, num_ret, file);
  ------------------
  |  |  105|  1.48k|    do {                                            \
  |  |  106|  1.48k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  1.48k|    do {                                            \
  |  |  |  |   97|  1.48k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  1.48k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  1.48k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  1.48k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 1.48k]
  |  |  |  |  ------------------
  |  |  |  |   99|  1.48k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  1.48k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  1.48k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  1.48k|        (idxvar)++;                                 \
  |  |  109|  1.48k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  153|  21.5k|            } else {
  154|  21.5k|                MP_DBG(global, "config path: '%.*s' -/-> '%s'\n",
  ------------------
  |  |   89|  21.5k|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  43.0k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 21.5k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  155|  21.5k|                        BSTR_P(fn), file);
  156|  21.5k|            }
  157|  22.9k|        }
  158|   322k|    }
  159|       |
  160|  64.5k|    MP_TARRAY_GROW(NULL, ret, num_ret);
  ------------------
  |  |   96|  64.5k|    do {                                            \
  |  |   97|  64.5k|        size_t nextidx_ = (nextidx);                \
  |  |   98|  64.5k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  ------------------
  |  |  |  |   84|  64.5k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  ------------------
  |  |  |  |  |  |   45|  64.5k|#define talloc_get_size                 ta_get_size
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  |  Branch (98:13): [True: 0, False: 64.5k]
  |  |  ------------------
  |  |   99|  64.5k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  ------------------
  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  100|  64.5k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  161|  64.5k|    ret[num_ret] = NULL;
  162|       |
  163|  64.5k|    for (int n = 0; n < num_ret / 2; n++)
  ------------------
  |  Branch (163:21): [True: 0, False: 64.5k]
  ------------------
  164|      0|        MPSWAP(char*, ret[n], ret[num_ret - n - 1]);
  ------------------
  |  |   47|      0|    do { type SWAP_tmp = b; b = a; a = SWAP_tmp; } while (0)
  |  |  ------------------
  |  |  |  Branch (47:59): [Folded - Ignored]
  |  |  ------------------
  ------------------
  165|  64.5k|    return ret;
  166|  64.5k|}

mp_set_cloexec:
   52|  23.5k|{
   53|  23.5k|#if defined(F_SETFD)
   54|  23.5k|    if (fd >= 0) {
  ------------------
  |  Branch (54:9): [True: 23.5k, False: 0]
  ------------------
   55|  23.5k|        int flags = fcntl(fd, F_GETFD);
   56|  23.5k|        if (flags == -1)
  ------------------
  |  Branch (56:13): [True: 0, False: 23.5k]
  ------------------
   57|      0|            return false;
   58|  23.5k|        if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
  ------------------
  |  Branch (58:13): [True: 0, False: 23.5k]
  ------------------
   59|      0|            return false;
   60|  23.5k|    }
   61|  23.5k|#endif
   62|  23.5k|    return true;
   63|  23.5k|}
mp_make_cloexec_pipe:
   67|  7.44k|{
   68|  7.44k|    if (pipe(pipes) != 0) {
  ------------------
  |  Branch (68:9): [True: 0, False: 7.44k]
  ------------------
   69|      0|        pipes[0] = pipes[1] = -1;
   70|      0|        return -1;
   71|      0|    }
   72|       |
   73|  22.3k|    for (int i = 0; i < 2; i++)
  ------------------
  |  Branch (73:21): [True: 14.8k, False: 7.44k]
  ------------------
   74|  14.8k|        mp_set_cloexec(pipes[i]);
   75|  7.44k|    return 0;
   76|  7.44k|}
mp_make_wakeup_pipe:
   80|  7.44k|{
   81|  7.44k|    if (mp_make_cloexec_pipe(pipes) < 0)
  ------------------
  |  Branch (81:9): [True: 0, False: 7.44k]
  ------------------
   82|      0|        return -1;
   83|       |
   84|  22.3k|    for (int i = 0; i < 2; i++) {
  ------------------
  |  Branch (84:21): [True: 14.8k, False: 7.44k]
  ------------------
   85|  14.8k|        int val = fcntl(pipes[i], F_GETFL) | O_NONBLOCK;
   86|  14.8k|        fcntl(pipes[i], F_SETFL, val);
   87|  14.8k|    }
   88|  7.44k|    return 0;
   89|  7.44k|}
mp_flush_wakeup_pipe:
   92|  4.32k|{
   93|  4.32k|    char buf[100];
   94|  4.32k|    (void)read(pipe_end, buf, sizeof(buf));
   95|  4.32k|}

mp_get_platform_path_unix:
   85|  53.3k|{
   86|  53.3k|    mp_exec_once(&path_init_once, path_init);
  ------------------
  |  |  206|  53.3k|#define mp_exec_once pthread_once
  ------------------
   87|  53.3k|    if (strcmp(type, "home") == 0)
  ------------------
  |  Branch (87:9): [True: 9.99k, False: 43.3k]
  ------------------
   88|  9.99k|        return mpv_home;
   89|  43.3k|    if (strcmp(type, "old_home") == 0)
  ------------------
  |  Branch (89:9): [True: 6.56k, False: 36.7k]
  ------------------
   90|  6.56k|        return old_home;
   91|  36.7k|    if (strcmp(type, "cache") == 0)
  ------------------
  |  Branch (91:9): [True: 245, False: 36.5k]
  ------------------
   92|    245|        return mpv_cache;
   93|  36.5k|    if (strcmp(type, "state") == 0)
  ------------------
  |  Branch (93:9): [True: 18.0k, False: 18.4k]
  ------------------
   94|  18.0k|        return mpv_state;
   95|  18.4k|    if (strcmp(type, "global") == 0)
  ------------------
  |  Branch (95:9): [True: 5.96k, False: 12.5k]
  ------------------
   96|  5.96k|        return MPV_CONFDIR;
  ------------------
  |  |  264|  5.96k|#define MPV_CONFDIR "/usr/local/etc/mpv"
  ------------------
   97|  12.5k|    if (strcmp(type, "desktop") == 0)
  ------------------
  |  Branch (97:9): [True: 87, False: 12.4k]
  ------------------
   98|     87|        return getenv("HOME");
   99|  12.4k|    return NULL;
  100|  12.5k|}
path-unix.c:path_init:
   37|      1|{
   38|      1|    char *home = getenv("HOME");
   39|      1|    char *xdg_cache = getenv("XDG_CACHE_HOME");
   40|      1|    char *xdg_config = getenv("XDG_CONFIG_HOME");
   41|      1|    char *xdg_state = getenv("XDG_STATE_HOME");
   42|       |
   43|      1|    bool err = false;
   44|      1|    if (xdg_config && xdg_config[0]) {
  ------------------
  |  Branch (44:9): [True: 0, False: 1]
  |  Branch (44:23): [True: 0, False: 0]
  ------------------
   45|      0|        err = err || MKPATH(mpv_home, "%s/mpv", xdg_config);
  ------------------
  |  |   34|      0|#define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      0|#define CONF_MAX 512
  |  |  ------------------
  |  |               #define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      0|#define CONF_MAX 512
  |  |  ------------------
  |  |  |  Branch (34:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (45:15): [True: 0, False: 0]
  ------------------
   46|      1|    } else if (home && home[0]) {
  ------------------
  |  Branch (46:16): [True: 1, False: 0]
  |  Branch (46:24): [True: 1, False: 0]
  ------------------
   47|      1|        err = err || MKPATH(mpv_home, "%s/.config/mpv", home);
  ------------------
  |  |   34|      2|#define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      1|#define CONF_MAX 512
  |  |  ------------------
  |  |               #define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      1|#define CONF_MAX 512
  |  |  ------------------
  |  |  |  Branch (34:26): [True: 0, False: 1]
  |  |  ------------------
  ------------------
  |  Branch (47:15): [True: 0, False: 1]
  ------------------
   48|      1|    }
   49|       |
   50|       |    // Maintain compatibility with old ~/.mpv
   51|      1|    if (home && home[0]) {
  ------------------
  |  Branch (51:9): [True: 1, False: 0]
  |  Branch (51:17): [True: 1, False: 0]
  ------------------
   52|      1|        err = err || MKPATH(old_home, "%s/.mpv", home);
  ------------------
  |  |   34|      2|#define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      1|#define CONF_MAX 512
  |  |  ------------------
  |  |               #define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      1|#define CONF_MAX 512
  |  |  ------------------
  |  |  |  Branch (34:26): [True: 0, False: 1]
  |  |  ------------------
  ------------------
  |  Branch (52:15): [True: 0, False: 1]
  ------------------
   53|      1|        err = err || MKPATH(old_cache, "%s/.mpv/cache", home);
  ------------------
  |  |   34|      2|#define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      1|#define CONF_MAX 512
  |  |  ------------------
  |  |               #define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      1|#define CONF_MAX 512
  |  |  ------------------
  |  |  |  Branch (34:26): [True: 0, False: 1]
  |  |  ------------------
  ------------------
  |  Branch (53:15): [True: 0, False: 1]
  ------------------
   54|      1|    }
   55|       |
   56|      1|    if (xdg_cache && xdg_cache[0]) {
  ------------------
  |  Branch (56:9): [True: 0, False: 1]
  |  Branch (56:22): [True: 0, False: 0]
  ------------------
   57|      0|        err = err || MKPATH(mpv_cache, "%s/mpv", xdg_cache);
  ------------------
  |  |   34|      0|#define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      0|#define CONF_MAX 512
  |  |  ------------------
  |  |               #define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      0|#define CONF_MAX 512
  |  |  ------------------
  |  |  |  Branch (34:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (57:15): [True: 0, False: 0]
  ------------------
   58|      1|    } else if (home && home[0]) {
  ------------------
  |  Branch (58:16): [True: 1, False: 0]
  |  Branch (58:24): [True: 1, False: 0]
  ------------------
   59|      1|        err = err || MKPATH(mpv_cache, "%s/.cache/mpv", home);
  ------------------
  |  |   34|      2|#define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      1|#define CONF_MAX 512
  |  |  ------------------
  |  |               #define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      1|#define CONF_MAX 512
  |  |  ------------------
  |  |  |  Branch (34:26): [True: 0, False: 1]
  |  |  ------------------
  ------------------
  |  Branch (59:15): [True: 0, False: 1]
  ------------------
   60|      1|    }
   61|       |
   62|      1|    if (xdg_state && xdg_state[0]) {
  ------------------
  |  Branch (62:9): [True: 0, False: 1]
  |  Branch (62:22): [True: 0, False: 0]
  ------------------
   63|      0|        err = err || MKPATH(mpv_state, "%s/mpv", xdg_state);
  ------------------
  |  |   34|      0|#define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      0|#define CONF_MAX 512
  |  |  ------------------
  |  |               #define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      0|#define CONF_MAX 512
  |  |  ------------------
  |  |  |  Branch (34:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (63:15): [True: 0, False: 0]
  ------------------
   64|      1|    } else if (home && home[0]) {
  ------------------
  |  Branch (64:16): [True: 1, False: 0]
  |  Branch (64:24): [True: 1, False: 0]
  ------------------
   65|      1|        err = err || MKPATH(mpv_state, "%s/.local/state/mpv", home);
  ------------------
  |  |   34|      2|#define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      1|#define CONF_MAX 512
  |  |  ------------------
  |  |               #define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      1|#define CONF_MAX 512
  |  |  ------------------
  |  |  |  Branch (34:26): [True: 0, False: 1]
  |  |  ------------------
  ------------------
  |  Branch (65:15): [True: 0, False: 1]
  ------------------
   66|      1|    }
   67|       |
   68|       |    // If the old ~/.mpv exists, and the XDG config dir doesn't, use the old
   69|       |    // config dir only. Also do not use any other XDG directories.
   70|      1|    if (mp_path_exists(old_home) && !mp_path_exists(mpv_home)) {
  ------------------
  |  Branch (70:9): [True: 0, False: 1]
  |  Branch (70:37): [True: 0, False: 0]
  ------------------
   71|      0|        err = err || MKPATH(mpv_home, "%s", old_home);
  ------------------
  |  |   34|      0|#define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      0|#define CONF_MAX 512
  |  |  ------------------
  |  |               #define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      0|#define CONF_MAX 512
  |  |  ------------------
  |  |  |  Branch (34:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (71:15): [True: 0, False: 0]
  ------------------
   72|      0|        err = err || MKPATH(mpv_cache, "%s", old_cache);
  ------------------
  |  |   34|      0|#define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      0|#define CONF_MAX 512
  |  |  ------------------
  |  |               #define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      0|#define CONF_MAX 512
  |  |  ------------------
  |  |  |  Branch (34:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (72:15): [True: 0, False: 0]
  ------------------
   73|      0|        err = err || MKPATH(mpv_state, "%s", old_home);
  ------------------
  |  |   34|      0|#define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      0|#define CONF_MAX 512
  |  |  ------------------
  |  |               #define MKPATH(BUF, ...) (snprintf((BUF), CONF_MAX, __VA_ARGS__) >= CONF_MAX)
  |  |  ------------------
  |  |  |  |   28|      0|#define CONF_MAX 512
  |  |  ------------------
  |  |  |  Branch (34:26): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (73:15): [True: 0, False: 0]
  ------------------
   74|      0|        old_home[0] = '\0';
   75|      0|        old_cache[0] = '\0';
   76|      0|    }
   77|       |
   78|      1|    if (err) {
  ------------------
  |  Branch (78:9): [True: 0, False: 1]
  ------------------
   79|      0|        fprintf(stderr, "Config dir exceeds %d bytes\n", CONF_MAX);
  ------------------
  |  |   28|      0|#define CONF_MAX 512
  ------------------
   80|      0|        abort();
   81|      0|    }
   82|      1|}

polldev:
   48|  1.29k|{
   49|       |#ifdef __APPLE__
   50|       |    int maxfd = 0;
   51|       |    fd_set readfds, writefds;
   52|       |    FD_ZERO(&readfds);
   53|       |    FD_ZERO(&writefds);
   54|       |    for (size_t i = 0; i < nfds; ++i) {
   55|       |        struct pollfd *fd = &fds[i];
   56|       |        if (fd->fd > maxfd) {
   57|       |            maxfd = fd->fd;
   58|       |        }
   59|       |        if ((fd->events & POLLIN)) {
   60|       |            FD_SET(fd->fd, &readfds);
   61|       |        }
   62|       |        if ((fd->events & POLLOUT)) {
   63|       |            FD_SET(fd->fd, &writefds);
   64|       |        }
   65|       |    }
   66|       |    struct timeval _timeout = {
   67|       |        .tv_sec = timeout / 1000,
   68|       |        .tv_usec = (timeout % 1000) * 1000
   69|       |    };
   70|       |    int n = select(maxfd + 1, &readfds, &writefds, NULL,
   71|       |        timeout != -1 ? &_timeout : NULL);
   72|       |    if (n < 0) {
   73|       |        return n;
   74|       |    }
   75|       |    for (size_t i = 0; i < nfds; ++i) {
   76|       |        struct pollfd *fd = &fds[i];
   77|       |        fd->revents = 0;
   78|       |        if (FD_ISSET(fd->fd, &readfds)) {
   79|       |            fd->revents |= POLLIN;
   80|       |        }
   81|       |        if (FD_ISSET(fd->fd, &writefds)) {
   82|       |            fd->revents |= POLLOUT;
   83|       |        }
   84|       |    }
   85|       |    return n;
   86|       |#else
   87|  1.29k|    return poll(fds, nfds, timeout);
   88|  1.29k|#endif
   89|  1.29k|}

mp_subprocess2:
    5|  4.32k|{
    6|  4.32k|    *res = (struct mp_subprocess_result){.error = MP_SUBPROCESS_EUNSUPPORTED};
  ------------------
  |  |   77|  4.32k|#define MP_SUBPROCESS_EUNSUPPORTED      -4  // API not supported
  ------------------
    7|  4.32k|}

mp_subprocess_err_str:
   25|  4.32k|{
   26|       |    // Note: these are visible to the public client API
   27|  4.32k|    switch (num) {
   28|      0|    case MP_SUBPROCESS_OK:              return "success";
  ------------------
  |  |   73|      0|#define MP_SUBPROCESS_OK                0   // no error
  ------------------
  |  Branch (28:5): [True: 0, False: 4.32k]
  ------------------
   29|      0|    case MP_SUBPROCESS_EKILLED_BY_US:   return "killed";
  ------------------
  |  |   75|      0|#define MP_SUBPROCESS_EKILLED_BY_US     -2  // mp_cancel was triggered
  ------------------
  |  Branch (29:5): [True: 0, False: 4.32k]
  ------------------
   30|      0|    case MP_SUBPROCESS_EINIT:           return "init";
  ------------------
  |  |   76|      0|#define MP_SUBPROCESS_EINIT             -3  // error during initialization
  ------------------
  |  Branch (30:5): [True: 0, False: 4.32k]
  ------------------
   31|  4.32k|    case MP_SUBPROCESS_EUNSUPPORTED:    return "unsupported";
  ------------------
  |  |   77|  4.32k|#define MP_SUBPROCESS_EUNSUPPORTED      -4  // API not supported
  ------------------
  |  Branch (31:5): [True: 4.32k, False: 0]
  ------------------
   32|      0|    case MP_SUBPROCESS_EGENERIC:        // fall through
  ------------------
  |  |   74|      0|#define MP_SUBPROCESS_EGENERIC          -1  // unknown error
  ------------------
  |  Branch (32:5): [True: 0, False: 4.32k]
  ------------------
   33|      0|    default:                            return "unknown";
  ------------------
  |  Branch (33:5): [True: 0, False: 4.32k]
  ------------------
   34|  4.32k|    }
   35|  4.32k|}
mp_subprocess:
   40|  4.32k|{
   41|  4.32k|    mp_verbose(log, "Starting subprocess: [%s", opts->args[0]);
  ------------------
  |  |   75|  4.32k|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
   42|  4.32k|    char **arg = &opts->args[1];
   43|  8.64k|    while (*arg)
  ------------------
  |  Branch (43:12): [True: 4.32k, False: 4.32k]
  ------------------
   44|  4.32k|        mp_verbose(log, ", %s", *arg++);
  ------------------
  |  |   75|  4.32k|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
   45|  4.32k|    mp_verbose(log, "]\n");
  ------------------
  |  |   75|  4.32k|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
   46|  4.32k|    mp_subprocess2(opts, res);
   47|  4.32k|    if (res->error < 0) {
  ------------------
  |  Branch (47:9): [True: 4.32k, False: 0]
  ------------------
   48|  4.32k|        int lev = res->error == MP_SUBPROCESS_EKILLED_BY_US ? MSGL_V : MSGL_ERR;
  ------------------
  |  |   75|  4.32k|#define MP_SUBPROCESS_EKILLED_BY_US     -2  // mp_cancel was triggered
  ------------------
  |  Branch (48:19): [True: 0, False: 4.32k]
  ------------------
   49|  4.32k|        mp_msg(log, lev, "Subprocess failed: %s\n", mp_subprocess_err_str(res->error));
   50|  4.32k|    }
   51|  4.32k|}

terminal_setup_getch:
  509|     12|{
  510|     12|    if (!getch2_enabled || input_ctx)
  ------------------
  |  Branch (510:9): [True: 1, False: 11]
  |  Branch (510:28): [True: 0, False: 11]
  ------------------
  511|      1|        return;
  512|       |
  513|     11|    if (mp_make_wakeup_pipe(death_pipe) < 0)
  ------------------
  |  Branch (513:9): [True: 0, False: 11]
  ------------------
  514|      0|        return;
  515|       |
  516|       |    // Disable reading from the terminal even if stdout is not a tty, to make
  517|       |    //   mpv ... | less
  518|       |    // do the right thing.
  519|     11|    read_terminal = isatty(tty_in) && isatty(STDOUT_FILENO);
  ------------------
  |  Branch (519:21): [True: 0, False: 11]
  |  Branch (519:39): [True: 0, False: 0]
  ------------------
  520|       |
  521|     11|    input_ctx = ictx;
  522|       |
  523|     11|    if (mp_thread_create(&input_thread, terminal_thread, NULL)) {
  ------------------
  |  |  211|     11|#define mp_thread_create(t, f, a) pthread_create(t, NULL, f, a)
  |  |  ------------------
  |  |  |  Branch (211:35): [True: 0, False: 11]
  |  |  ------------------
  ------------------
  524|      0|        input_ctx = NULL;
  525|      0|        close_sig_pipes();
  526|      0|        close_tty();
  527|      0|        return;
  528|      0|    }
  529|       |
  530|     11|    setsigaction(SIGINT,  quit_request_sighandler, SA_RESETHAND, false);
  531|     11|    setsigaction(SIGQUIT, quit_request_sighandler, 0, true);
  532|     11|    setsigaction(SIGTERM, quit_request_sighandler, 0, true);
  533|     11|}
terminal_uninit:
  536|  3.11k|{
  537|  3.11k|    if (!getch2_enabled)
  ------------------
  |  Branch (537:9): [True: 0, False: 3.11k]
  ------------------
  538|      0|        return;
  539|       |
  540|       |    // restore signals
  541|  3.11k|    setsigaction(SIGCONT, SIG_DFL, 0, false);
  542|  3.11k|    setsigaction(SIGTSTP, SIG_DFL, 0, false);
  543|  3.11k|    setsigaction(SIGINT,  SIG_DFL, 0, false);
  544|  3.11k|    setsigaction(SIGQUIT, SIG_DFL, 0, false);
  545|  3.11k|    setsigaction(SIGTERM, SIG_DFL, 0, false);
  546|  3.11k|    setsigaction(SIGTTIN, SIG_DFL, 0, false);
  547|  3.11k|    setsigaction(SIGTTOU, SIG_DFL, 0, false);
  548|       |
  549|  3.11k|    if (input_ctx) {
  ------------------
  |  Branch (549:9): [True: 11, False: 3.10k]
  ------------------
  550|     11|        (void)write(death_pipe[1], &(char){0}, 1);
  551|     11|        mp_thread_join(input_thread);
  ------------------
  |  |  212|     11|#define mp_thread_join(t)         pthread_join(t, NULL)
  ------------------
  552|     11|    }
  553|       |
  554|  3.11k|    close_sig_pipes();
  555|  3.11k|    input_ctx = NULL;
  556|       |
  557|  3.11k|    do_deactivate_getch2();
  558|  3.11k|    close_tty();
  559|       |
  560|  3.11k|    getch2_enabled = 0;
  561|  3.11k|    read_terminal = false;
  562|  3.11k|}
terminal_in_background:
  565|  6.97k|{
  566|  6.97k|    return read_terminal && tcgetpgrp(STDERR_FILENO) != getpgrp();
  ------------------
  |  Branch (566:12): [True: 0, False: 6.97k]
  |  Branch (566:29): [True: 0, False: 0]
  ------------------
  567|  6.97k|}
terminal_get_size:
  570|    166|{
  571|    166|    struct winsize ws;
  572|    166|    if (ioctl(tty_in, TIOCGWINSZ, &ws) < 0 || !ws.ws_row || !ws.ws_col)
  ------------------
  |  Branch (572:9): [True: 166, False: 0]
  |  Branch (572:47): [True: 0, False: 0]
  |  Branch (572:61): [True: 0, False: 0]
  ------------------
  573|    166|        return;
  574|       |
  575|      0|    *w = ws.ws_col;
  576|      0|    *h = ws.ws_row;
  577|      0|}
terminal_get_size2:
  580|     39|{
  581|     39|    struct winsize ws;
  582|     39|    if (ioctl(tty_in, TIOCGWINSZ, &ws) < 0 || !ws.ws_row || !ws.ws_col
  ------------------
  |  Branch (582:9): [True: 39, False: 0]
  |  Branch (582:47): [True: 0, False: 0]
  |  Branch (582:61): [True: 0, False: 0]
  ------------------
  583|     39|                                           || !ws.ws_xpixel || !ws.ws_ypixel)
  ------------------
  |  Branch (583:47): [True: 0, False: 0]
  |  Branch (583:64): [True: 0, False: 0]
  ------------------
  584|     39|        return;
  585|       |
  586|      0|    *rows = ws.ws_row;
  587|      0|    *cols = ws.ws_col;
  588|      0|    *px_width = ws.ws_xpixel;
  589|      0|    *px_height = ws.ws_ypixel;
  590|      0|}
terminal_set_mouse_input:
  593|     78|{
  594|     78|    printf(enable ? TERM_ESC_ENABLE_MOUSE : TERM_ESC_DISABLE_MOUSE);
  ------------------
  |  |   38|     39|#define TERM_ESC_ENABLE_MOUSE       "\033[?1003h"
  ------------------
                  printf(enable ? TERM_ESC_ENABLE_MOUSE : TERM_ESC_DISABLE_MOUSE);
  ------------------
  |  |   39|    117|#define TERM_ESC_DISABLE_MOUSE      "\033[?1003l"
  ------------------
  |  Branch (594:12): [True: 39, False: 39]
  ------------------
  595|     78|    fflush(stdout);
  596|     78|}
terminal_init:
  599|  3.11k|{
  600|  3.11k|    mp_assert(!getch2_enabled);
  ------------------
  |  |   41|  3.11k|#define mp_assert assert
  ------------------
  601|  3.11k|    getch2_enabled = 1;
  602|       |
  603|  3.11k|    if (mp_make_wakeup_pipe(stop_cont_pipe) < 0) {
  ------------------
  |  Branch (603:9): [True: 0, False: 3.11k]
  ------------------
  604|      0|        getch2_enabled = 0;
  605|      0|        return;
  606|      0|    }
  607|       |
  608|  3.11k|    tty_in = tty_out = open("/dev/tty", O_RDWR | O_CLOEXEC);
  609|  3.11k|    if (tty_in < 0) {
  ------------------
  |  Branch (609:9): [True: 3.11k, False: 0]
  ------------------
  610|  3.11k|        tty_in = STDIN_FILENO;
  611|  3.11k|        tty_out = STDOUT_FILENO;
  612|  3.11k|    }
  613|       |
  614|  3.11k|    tcgetattr(tty_in, &tio_orig);
  615|       |
  616|       |    // handlers to fix terminal settings
  617|  3.11k|    setsigaction(SIGCONT, stop_cont_sighandler, 0, true);
  618|  3.11k|    setsigaction(SIGTSTP, stop_cont_sighandler, 0, true);
  619|  3.11k|    setsigaction(SIGTTIN, SIG_IGN, 0, true);
  620|  3.11k|    setsigaction(SIGTTOU, SIG_IGN, 0, true);
  621|       |
  622|  3.11k|    getch2_poll();
  623|  3.11k|}
terminal-unix.c:terminal_thread:
  441|     11|{
  442|     11|    mp_thread_set_name("terminal/input");
  443|     11|    bool stdin_ok = read_terminal; // if false, we still wait for SIGTERM
  444|  1.29k|    while (1) {
  ------------------
  |  Branch (444:12): [Folded - Ignored]
  ------------------
  445|  1.29k|        getch2_poll();
  446|  1.29k|        struct pollfd fds[3] = {
  447|  1.29k|            { .events = POLLIN, .fd = death_pipe[0] },
  448|  1.29k|            { .events = POLLIN, .fd = stop_cont_pipe[0] },
  449|  1.29k|            { .events = POLLIN, .fd = tty_in }
  450|  1.29k|        };
  451|       |        /*
  452|       |         * if the process isn't in foreground process group, then on macos
  453|       |         * polldev() doesn't rest and gets into 100% cpu usage (see issue #11795)
  454|       |         * with read() returning EIO. but we shouldn't quit on EIO either since
  455|       |         * the process might be foregrounded later.
  456|       |         *
  457|       |         * so just avoid poll-ing tty_in when we know the process is not in the
  458|       |         * foreground. there's a small race window, but the timeout will take
  459|       |         * care of it so it's fine.
  460|       |         */
  461|  1.29k|        bool is_fg = tcgetpgrp(tty_in) == getpgrp();
  462|  1.29k|        int r = polldev(fds, stdin_ok && is_fg ? 3 : 2, buf.len ? ESC_TIMEOUT : INPUT_TIMEOUT);
  ------------------
  |  |   43|      0|#define ESC_TIMEOUT 100
  ------------------
                      int r = polldev(fds, stdin_ok && is_fg ? 3 : 2, buf.len ? ESC_TIMEOUT : INPUT_TIMEOUT);
  ------------------
  |  |   51|  1.29k|#define INPUT_TIMEOUT 1000
  ------------------
  |  Branch (462:30): [True: 0, False: 1.29k]
  |  Branch (462:42): [True: 0, False: 0]
  |  Branch (462:57): [True: 0, False: 1.29k]
  ------------------
  463|  1.29k|        if (fds[0].revents) {
  ------------------
  |  Branch (463:13): [True: 11, False: 1.27k]
  ------------------
  464|     11|            do_deactivate_getch2();
  465|     11|            break;
  466|     11|        }
  467|  1.27k|        if (fds[1].revents & POLLIN) {
  ------------------
  |  Branch (467:13): [True: 1.13k, False: 141]
  ------------------
  468|  1.13k|            int8_t c = -1;
  469|  1.13k|            (void)read(stop_cont_pipe[0], &c, 1);
  470|  1.13k|            if (c == PIPE_STOP) {
  ------------------
  |  Branch (470:17): [True: 0, False: 1.13k]
  ------------------
  471|      0|                do_deactivate_getch2();
  472|      0|                if (isatty(STDERR_FILENO)) {
  ------------------
  |  Branch (472:21): [True: 0, False: 0]
  ------------------
  473|      0|                    (void)write(STDERR_FILENO, TERM_ESC_RESTORE_CURSOR,
  ------------------
  |  |   30|      0|#define TERM_ESC_RESTORE_CURSOR     "\033[?25h"
  ------------------
  474|      0|                                sizeof(TERM_ESC_RESTORE_CURSOR) - 1);
  ------------------
  |  |   30|      0|#define TERM_ESC_RESTORE_CURSOR     "\033[?25h"
  ------------------
  475|      0|                }
  476|       |                // trying to reset SIGTSTP handler to default and raise it will
  477|       |                // result in a race and there's no other way to invoke the
  478|       |                // default handler. so just invoke SIGSTOP since it's
  479|       |                // effectively the same thing.
  480|      0|                raise(SIGSTOP);
  481|  1.13k|            } else if (c == PIPE_CONT) {
  ------------------
  |  Branch (481:24): [True: 82, False: 1.05k]
  ------------------
  482|     82|                getch2_poll();
  483|     82|            }
  484|  1.13k|        }
  485|  1.27k|        if (fds[2].revents) {
  ------------------
  |  Branch (485:13): [True: 0, False: 1.27k]
  ------------------
  486|      0|            int retval = read(tty_in, &buf.b[buf.len], BUF_LEN - buf.len);
  ------------------
  |  |  188|      0|#define BUF_LEN 256
  ------------------
  487|      0|            if (!retval || (retval == -1 && errno != EINTR && errno != EAGAIN && errno != EIO))
  ------------------
  |  Branch (487:17): [True: 0, False: 0]
  |  Branch (487:29): [True: 0, False: 0]
  |  Branch (487:45): [True: 0, False: 0]
  |  Branch (487:63): [True: 0, False: 0]
  |  Branch (487:82): [True: 0, False: 0]
  ------------------
  488|      0|                break; // EOF/closed
  489|      0|            if (retval > 0) {
  ------------------
  |  Branch (489:17): [True: 0, False: 0]
  ------------------
  490|      0|                buf.len += retval;
  491|      0|                process_input(input_ctx, false);
  492|      0|            }
  493|      0|        }
  494|  1.27k|        if (r == 0)
  ------------------
  |  Branch (494:13): [True: 0, False: 1.27k]
  ------------------
  495|      0|            process_input(input_ctx, true);
  496|  1.27k|    }
  497|     11|    char c;
  498|     11|    bool quit = read(death_pipe[0], &c, 1) == 1 && c == 1;
  ------------------
  |  Branch (498:17): [True: 11, False: 0]
  |  Branch (498:52): [True: 0, False: 11]
  ------------------
  499|       |    // Important if we received SIGTERM, rather than regular quit.
  500|     11|    if (quit) {
  ------------------
  |  Branch (500:9): [True: 0, False: 11]
  ------------------
  501|      0|        struct mp_cmd *cmd = mp_input_parse_cmd(input_ctx, bstr0("quit 4"), "");
  502|      0|        if (cmd)
  ------------------
  |  Branch (502:13): [True: 0, False: 0]
  ------------------
  503|      0|            mp_input_queue_cmd(input_ctx, cmd);
  504|      0|    }
  505|     11|    MP_THREAD_RETURN();
  ------------------
  |  |  209|     11|#define MP_THREAD_RETURN() return NULL
  ------------------
  506|     11|}
terminal-unix.c:close_sig_pipes:
  418|  3.11k|{
  419|  9.33k|    for (int n = 0; n < 2; n++) {
  ------------------
  |  Branch (419:21): [True: 6.22k, False: 3.11k]
  ------------------
  420|  6.22k|        safe_close(&death_pipe[n]);
  421|  6.22k|        safe_close(&stop_cont_pipe[n]);
  422|  6.22k|    }
  423|  3.11k|}
terminal-unix.c:safe_close:
  411|  12.4k|{
  412|  12.4k|    if (*p >= 0)
  ------------------
  |  Branch (412:9): [True: 6.24k, False: 6.20k]
  ------------------
  413|  6.24k|        close(*p);
  414|  12.4k|    *p = -1;
  415|  12.4k|}
terminal-unix.c:close_tty:
  426|  3.11k|{
  427|  3.11k|    if (tty_in >= 0 && tty_in != STDIN_FILENO)
  ------------------
  |  Branch (427:9): [True: 3.11k, False: 0]
  |  Branch (427:24): [True: 0, False: 3.11k]
  ------------------
  428|      0|        close(tty_in);
  429|       |
  430|  3.11k|    tty_in = tty_out = -1;
  431|  3.11k|}
terminal-unix.c:setsigaction:
  368|  34.2k|{
  369|  34.2k|    struct sigaction sa;
  370|  34.2k|    sa.sa_handler = handler;
  371|       |
  372|  34.2k|    if (do_mask)
  ------------------
  |  Branch (372:9): [True: 12.4k, False: 21.7k]
  ------------------
  373|  12.4k|        sigfillset(&sa.sa_mask);
  374|  21.7k|    else
  375|  21.7k|        sigemptyset(&sa.sa_mask);
  376|       |
  377|  34.2k|    sa.sa_flags = flags | SA_RESTART;
  378|  34.2k|    return sigaction(signo, &sa, NULL);
  379|  34.2k|}
terminal-unix.c:do_deactivate_getch2:
  355|  7.60k|{
  356|  7.60k|    if (!getch2_active)
  ------------------
  |  Branch (356:9): [True: 7.60k, False: 0]
  ------------------
  357|  7.60k|        return;
  358|       |
  359|      0|    enable_kx(false);
  360|      0|    tcsetattr(tty_in, TCSANOW, &tio_orig);
  361|       |
  362|      0|    getch2_active = 0;
  363|      0|}
terminal-unix.c:getch2_poll:
  382|  4.48k|{
  383|  4.48k|    if (!getch2_enabled)
  ------------------
  |  Branch (383:9): [True: 0, False: 4.48k]
  ------------------
  384|      0|        return;
  385|       |
  386|       |    // check if stdin is in the foreground process group
  387|  4.48k|    int newstatus = (tcgetpgrp(tty_in) == getpgrp());
  388|       |
  389|       |    // and activate getch2 if it is, deactivate otherwise
  390|  4.48k|    if (newstatus)
  ------------------
  |  Branch (390:9): [True: 0, False: 4.48k]
  ------------------
  391|      0|        do_activate_getch2();
  392|  4.48k|    else
  393|  4.48k|        do_deactivate_getch2();
  394|  4.48k|}

encode_lavc.c:mp_mutex_init:
  110|    309|{
  111|    309|#ifndef NDEBUG
  112|    309|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|    309|    int ret = 0;
  118|    309|    pthread_mutexattr_t attr;
  119|    309|    ret = pthread_mutexattr_init(&attr);
  120|    309|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 309]
  ------------------
  121|      0|        return ret;
  122|       |
  123|    309|    pthread_mutexattr_settype(&attr, mutex_type);
  124|    309|    ret = pthread_mutex_init(mutex, &attr);
  125|    309|    pthread_mutexattr_destroy(&attr);
  126|    309|    mp_assert(!ret);
  ------------------
  |  |   41|    309|#define mp_assert assert
  ------------------
  127|    309|    return ret;
  128|    309|}
msg.c:mp_mutex_init:
  110|  68.2k|{
  111|  68.2k|#ifndef NDEBUG
  112|  68.2k|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|  68.2k|    int ret = 0;
  118|  68.2k|    pthread_mutexattr_t attr;
  119|  68.2k|    ret = pthread_mutexattr_init(&attr);
  120|  68.2k|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 68.2k]
  ------------------
  121|      0|        return ret;
  122|       |
  123|  68.2k|    pthread_mutexattr_settype(&attr, mutex_type);
  124|  68.2k|    ret = pthread_mutex_init(mutex, &attr);
  125|  68.2k|    pthread_mutexattr_destroy(&attr);
  126|  68.2k|    mp_assert(!ret);
  ------------------
  |  |   41|  68.2k|#define mp_assert assert
  ------------------
  127|  68.2k|    return ret;
  128|  68.2k|}
msg.c:mp_cond_init:
  136|  17.0k|{
  137|  17.0k|    mp_assert(cond);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  138|       |
  139|  17.0k|    int ret = 0;
  140|  17.0k|    pthread_condattr_t attr;
  141|  17.0k|    ret = pthread_condattr_init(&attr);
  142|  17.0k|    if (ret)
  ------------------
  |  Branch (142:9): [True: 0, False: 17.0k]
  ------------------
  143|      0|        return ret;
  144|       |
  145|  17.0k|    cond->clk_id = CLOCK_REALTIME;
  146|  17.0k|#if HAVE_PTHREAD_CONDATTR_SETCLOCK
  147|  17.0k|    if (!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
  ------------------
  |  Branch (147:9): [True: 17.0k, False: 0]
  ------------------
  148|  17.0k|        cond->clk_id = CLOCK_MONOTONIC;
  149|  17.0k|#endif
  150|       |
  151|  17.0k|    ret = pthread_cond_init(&cond->cond, &attr);
  152|  17.0k|    pthread_condattr_destroy(&attr);
  153|  17.0k|    return ret;
  154|  17.0k|}
msg.c:mp_cond_destroy:
  157|  17.0k|{
  158|  17.0k|    mp_assert(cond);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  159|  17.0k|    return pthread_cond_destroy(&cond->cond);
  160|  17.0k|}
stats.c:mp_mutex_init:
  110|  17.0k|{
  111|  17.0k|#ifndef NDEBUG
  112|  17.0k|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|  17.0k|    int ret = 0;
  118|  17.0k|    pthread_mutexattr_t attr;
  119|  17.0k|    ret = pthread_mutexattr_init(&attr);
  120|  17.0k|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 17.0k]
  ------------------
  121|      0|        return ret;
  122|       |
  123|  17.0k|    pthread_mutexattr_settype(&attr, mutex_type);
  124|  17.0k|    ret = pthread_mutex_init(mutex, &attr);
  125|  17.0k|    pthread_mutexattr_destroy(&attr);
  126|  17.0k|    mp_assert(!ret);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  127|  17.0k|    return ret;
  128|  17.0k|}
demux.c:mp_cond_destroy:
  157|  2.81k|{
  158|  2.81k|    mp_assert(cond);
  ------------------
  |  |   41|  2.81k|#define mp_assert assert
  ------------------
  159|  2.81k|    return pthread_cond_destroy(&cond->cond);
  160|  2.81k|}
demux.c:mp_cond_signal:
  169|     81|{
  170|     81|    mp_assert(cond);
  ------------------
  |  |   41|     81|#define mp_assert assert
  ------------------
  171|     81|    return pthread_cond_signal(&cond->cond);
  172|     81|}
demux.c:mp_mutex_init:
  110|  2.81k|{
  111|  2.81k|#ifndef NDEBUG
  112|  2.81k|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|  2.81k|    int ret = 0;
  118|  2.81k|    pthread_mutexattr_t attr;
  119|  2.81k|    ret = pthread_mutexattr_init(&attr);
  120|  2.81k|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 2.81k]
  ------------------
  121|      0|        return ret;
  122|       |
  123|  2.81k|    pthread_mutexattr_settype(&attr, mutex_type);
  124|  2.81k|    ret = pthread_mutex_init(mutex, &attr);
  125|  2.81k|    pthread_mutexattr_destroy(&attr);
  126|  2.81k|    mp_assert(!ret);
  ------------------
  |  |   41|  2.81k|#define mp_assert assert
  ------------------
  127|  2.81k|    return ret;
  128|  2.81k|}
demux.c:mp_cond_init:
  136|  2.81k|{
  137|  2.81k|    mp_assert(cond);
  ------------------
  |  |   41|  2.81k|#define mp_assert assert
  ------------------
  138|       |
  139|  2.81k|    int ret = 0;
  140|  2.81k|    pthread_condattr_t attr;
  141|  2.81k|    ret = pthread_condattr_init(&attr);
  142|  2.81k|    if (ret)
  ------------------
  |  Branch (142:9): [True: 0, False: 2.81k]
  ------------------
  143|      0|        return ret;
  144|       |
  145|  2.81k|    cond->clk_id = CLOCK_REALTIME;
  146|  2.81k|#if HAVE_PTHREAD_CONDATTR_SETCLOCK
  147|  2.81k|    if (!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
  ------------------
  |  Branch (147:9): [True: 2.81k, False: 0]
  ------------------
  148|  2.81k|        cond->clk_id = CLOCK_MONOTONIC;
  149|  2.81k|#endif
  150|       |
  151|  2.81k|    ret = pthread_cond_init(&cond->cond, &attr);
  152|  2.81k|    pthread_condattr_destroy(&attr);
  153|  2.81k|    return ret;
  154|  2.81k|}
packet_pool.c:mp_mutex_init:
  110|  17.0k|{
  111|  17.0k|#ifndef NDEBUG
  112|  17.0k|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|  17.0k|    int ret = 0;
  118|  17.0k|    pthread_mutexattr_t attr;
  119|  17.0k|    ret = pthread_mutexattr_init(&attr);
  120|  17.0k|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 17.0k]
  ------------------
  121|      0|        return ret;
  122|       |
  123|  17.0k|    pthread_mutexattr_settype(&attr, mutex_type);
  124|  17.0k|    ret = pthread_mutex_init(mutex, &attr);
  125|  17.0k|    pthread_mutexattr_destroy(&attr);
  126|  17.0k|    mp_assert(!ret);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  127|  17.0k|    return ret;
  128|  17.0k|}
filter.c:mp_mutex_init:
  110|  3.93k|{
  111|  3.93k|#ifndef NDEBUG
  112|  3.93k|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|  3.93k|    int ret = 0;
  118|  3.93k|    pthread_mutexattr_t attr;
  119|  3.93k|    ret = pthread_mutexattr_init(&attr);
  120|  3.93k|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 3.93k]
  ------------------
  121|      0|        return ret;
  122|       |
  123|  3.93k|    pthread_mutexattr_settype(&attr, mutex_type);
  124|  3.93k|    ret = pthread_mutex_init(mutex, &attr);
  125|  3.93k|    pthread_mutexattr_destroy(&attr);
  126|  3.93k|    mp_assert(!ret);
  ------------------
  |  |   41|  3.93k|#define mp_assert assert
  ------------------
  127|  3.93k|    return ret;
  128|  3.93k|}
input.c:mp_mutex_init:
  110|  17.0k|{
  111|  17.0k|#ifndef NDEBUG
  112|  17.0k|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|  17.0k|    int ret = 0;
  118|  17.0k|    pthread_mutexattr_t attr;
  119|  17.0k|    ret = pthread_mutexattr_init(&attr);
  120|  17.0k|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 17.0k]
  ------------------
  121|      0|        return ret;
  122|       |
  123|  17.0k|    pthread_mutexattr_settype(&attr, mutex_type);
  124|  17.0k|    ret = pthread_mutex_init(mutex, &attr);
  125|  17.0k|    pthread_mutexattr_destroy(&attr);
  126|  17.0k|    mp_assert(!ret);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  127|  17.0k|    return ret;
  128|  17.0k|}
dispatch.c:mp_cond_destroy:
  157|  17.1k|{
  158|  17.1k|    mp_assert(cond);
  ------------------
  |  |   41|  17.1k|#define mp_assert assert
  ------------------
  159|  17.1k|    return pthread_cond_destroy(&cond->cond);
  160|  17.1k|}
dispatch.c:mp_mutex_init:
  110|  17.1k|{
  111|  17.1k|#ifndef NDEBUG
  112|  17.1k|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|  17.1k|    int ret = 0;
  118|  17.1k|    pthread_mutexattr_t attr;
  119|  17.1k|    ret = pthread_mutexattr_init(&attr);
  120|  17.1k|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 17.1k]
  ------------------
  121|      0|        return ret;
  122|       |
  123|  17.1k|    pthread_mutexattr_settype(&attr, mutex_type);
  124|  17.1k|    ret = pthread_mutex_init(mutex, &attr);
  125|  17.1k|    pthread_mutexattr_destroy(&attr);
  126|  17.1k|    mp_assert(!ret);
  ------------------
  |  |   41|  17.1k|#define mp_assert assert
  ------------------
  127|  17.1k|    return ret;
  128|  17.1k|}
dispatch.c:mp_cond_init:
  136|  17.1k|{
  137|  17.1k|    mp_assert(cond);
  ------------------
  |  |   41|  17.1k|#define mp_assert assert
  ------------------
  138|       |
  139|  17.1k|    int ret = 0;
  140|  17.1k|    pthread_condattr_t attr;
  141|  17.1k|    ret = pthread_condattr_init(&attr);
  142|  17.1k|    if (ret)
  ------------------
  |  Branch (142:9): [True: 0, False: 17.1k]
  ------------------
  143|      0|        return ret;
  144|       |
  145|  17.1k|    cond->clk_id = CLOCK_REALTIME;
  146|  17.1k|#if HAVE_PTHREAD_CONDATTR_SETCLOCK
  147|  17.1k|    if (!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
  ------------------
  |  Branch (147:9): [True: 17.1k, False: 0]
  ------------------
  148|  17.1k|        cond->clk_id = CLOCK_MONOTONIC;
  149|  17.1k|#endif
  150|       |
  151|  17.1k|    ret = pthread_cond_init(&cond->cond, &attr);
  152|  17.1k|    pthread_condattr_destroy(&attr);
  153|  17.1k|    return ret;
  154|  17.1k|}
dispatch.c:mp_cond_wait:
  175|  44.2k|{
  176|  44.2k|    mp_assert(cond);
  ------------------
  |  |   41|  44.2k|#define mp_assert assert
  ------------------
  177|  44.2k|    return pthread_cond_wait(&cond->cond, mutex);
  178|  44.2k|}
dispatch.c:mp_cond_broadcast:
  163|   152k|{
  164|   152k|    mp_assert(cond);
  ------------------
  |  |   41|   152k|#define mp_assert assert
  ------------------
  165|   152k|    return pthread_cond_broadcast(&cond->cond);
  166|   152k|}
dispatch.c:mp_cond_timedwait_until:
  202|    956|{
  203|    956|    return mp_cond_timedwait(cond, mutex, until - mp_time_ns());
  204|    956|}
dispatch.c:mp_cond_timedwait:
  181|    956|{
  182|    956|    mp_assert(cond);
  ------------------
  |  |   41|    956|#define mp_assert assert
  ------------------
  183|       |
  184|    956|    timeout = MPMAX(0, timeout);
  ------------------
  |  |   43|    956|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 956]
  |  |  ------------------
  ------------------
  185|       |    // consider anything above 1000 days as infinity
  186|    956|    if (timeout > MP_TIME_S_TO_NS(1000 * 24 * 60 * 60))
  ------------------
  |  |   59|    956|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  |  Branch (186:9): [True: 764, False: 192]
  ------------------
  187|    764|        return pthread_cond_wait(&cond->cond, mutex);
  188|       |
  189|    192|    struct timespec ts;
  190|    192|    clock_gettime(cond->clk_id, &ts);
  191|    192|    ts.tv_sec  += timeout / MP_TIME_S_TO_NS(1);
  ------------------
  |  |   59|    192|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  192|    192|    ts.tv_nsec += timeout % MP_TIME_S_TO_NS(1);
  ------------------
  |  |   59|    192|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  193|    192|    if (ts.tv_nsec >= MP_TIME_S_TO_NS(1)) {
  ------------------
  |  |   59|    192|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  |  Branch (193:9): [True: 159, False: 33]
  ------------------
  194|    159|        ts.tv_nsec -= MP_TIME_S_TO_NS(1);
  ------------------
  |  |   59|    159|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  195|    159|        ts.tv_sec++;
  196|    159|    }
  197|       |
  198|    192|    return pthread_cond_timedwait(&cond->cond, mutex, &ts);
  199|    956|}
rendezvous.c:mp_cond_broadcast:
  163|     76|{
  164|     76|    mp_assert(cond);
  ------------------
  |  |   41|     76|#define mp_assert assert
  ------------------
  165|     76|    return pthread_cond_broadcast(&cond->cond);
  166|     76|}
rendezvous.c:mp_cond_wait:
  175|     76|{
  176|     76|    mp_assert(cond);
  ------------------
  |  |   41|     76|#define mp_assert assert
  ------------------
  177|     76|    return pthread_cond_wait(&cond->cond, mutex);
  178|     76|}
thread_pool.c:mp_cond_broadcast:
  163|  17.0k|{
  164|  17.0k|    mp_assert(cond);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  165|  17.0k|    return pthread_cond_broadcast(&cond->cond);
  166|  17.0k|}
thread_pool.c:mp_cond_destroy:
  157|  17.0k|{
  158|  17.0k|    mp_assert(cond);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  159|  17.0k|    return pthread_cond_destroy(&cond->cond);
  160|  17.0k|}
thread_pool.c:mp_mutex_init:
  110|  17.0k|{
  111|  17.0k|#ifndef NDEBUG
  112|  17.0k|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|  17.0k|    int ret = 0;
  118|  17.0k|    pthread_mutexattr_t attr;
  119|  17.0k|    ret = pthread_mutexattr_init(&attr);
  120|  17.0k|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 17.0k]
  ------------------
  121|      0|        return ret;
  122|       |
  123|  17.0k|    pthread_mutexattr_settype(&attr, mutex_type);
  124|  17.0k|    ret = pthread_mutex_init(mutex, &attr);
  125|  17.0k|    pthread_mutexattr_destroy(&attr);
  126|  17.0k|    mp_assert(!ret);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  127|  17.0k|    return ret;
  128|  17.0k|}
thread_pool.c:mp_cond_init:
  136|  17.0k|{
  137|  17.0k|    mp_assert(cond);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  138|       |
  139|  17.0k|    int ret = 0;
  140|  17.0k|    pthread_condattr_t attr;
  141|  17.0k|    ret = pthread_condattr_init(&attr);
  142|  17.0k|    if (ret)
  ------------------
  |  Branch (142:9): [True: 0, False: 17.0k]
  ------------------
  143|      0|        return ret;
  144|       |
  145|  17.0k|    cond->clk_id = CLOCK_REALTIME;
  146|  17.0k|#if HAVE_PTHREAD_CONDATTR_SETCLOCK
  147|  17.0k|    if (!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
  ------------------
  |  Branch (147:9): [True: 17.0k, False: 0]
  ------------------
  148|  17.0k|        cond->clk_id = CLOCK_MONOTONIC;
  149|  17.0k|#endif
  150|       |
  151|  17.0k|    ret = pthread_cond_init(&cond->cond, &attr);
  152|  17.0k|    pthread_condattr_destroy(&attr);
  153|  17.0k|    return ret;
  154|  17.0k|}
thread_tools.c:mp_cond_destroy:
  157|  30.2k|{
  158|  30.2k|    mp_assert(cond);
  ------------------
  |  |   41|  30.2k|#define mp_assert assert
  ------------------
  159|  30.2k|    return pthread_cond_destroy(&cond->cond);
  160|  30.2k|}
thread_tools.c:mp_cond_signal:
  169|  12.1k|{
  170|  12.1k|    mp_assert(cond);
  ------------------
  |  |   41|  12.1k|#define mp_assert assert
  ------------------
  171|  12.1k|    return pthread_cond_signal(&cond->cond);
  172|  12.1k|}
thread_tools.c:mp_mutex_init:
  110|  18.1k|{
  111|  18.1k|#ifndef NDEBUG
  112|  18.1k|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|  18.1k|    int ret = 0;
  118|  18.1k|    pthread_mutexattr_t attr;
  119|  18.1k|    ret = pthread_mutexattr_init(&attr);
  120|  18.1k|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 18.1k]
  ------------------
  121|      0|        return ret;
  122|       |
  123|  18.1k|    pthread_mutexattr_settype(&attr, mutex_type);
  124|  18.1k|    ret = pthread_mutex_init(mutex, &attr);
  125|  18.1k|    pthread_mutexattr_destroy(&attr);
  126|  18.1k|    mp_assert(!ret);
  ------------------
  |  |   41|  18.1k|#define mp_assert assert
  ------------------
  127|  18.1k|    return ret;
  128|  18.1k|}
thread_tools.c:mp_cond_init:
  136|  18.1k|{
  137|  18.1k|    mp_assert(cond);
  ------------------
  |  |   41|  18.1k|#define mp_assert assert
  ------------------
  138|       |
  139|  18.1k|    int ret = 0;
  140|  18.1k|    pthread_condattr_t attr;
  141|  18.1k|    ret = pthread_condattr_init(&attr);
  142|  18.1k|    if (ret)
  ------------------
  |  Branch (142:9): [True: 0, False: 18.1k]
  ------------------
  143|      0|        return ret;
  144|       |
  145|  18.1k|    cond->clk_id = CLOCK_REALTIME;
  146|  18.1k|#if HAVE_PTHREAD_CONDATTR_SETCLOCK
  147|  18.1k|    if (!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
  ------------------
  |  Branch (147:9): [True: 18.1k, False: 0]
  ------------------
  148|  18.1k|        cond->clk_id = CLOCK_MONOTONIC;
  149|  18.1k|#endif
  150|       |
  151|  18.1k|    ret = pthread_cond_init(&cond->cond, &attr);
  152|  18.1k|    pthread_condattr_destroy(&attr);
  153|  18.1k|    return ret;
  154|  18.1k|}
thread_tools.c:mp_cond_broadcast:
  163|  24.5k|{
  164|  24.5k|    mp_assert(cond);
  ------------------
  |  |   41|  24.5k|#define mp_assert assert
  ------------------
  165|  24.5k|    return pthread_cond_broadcast(&cond->cond);
  166|  24.5k|}
m_config_core.c:mp_mutex_init:
  110|  28.2k|{
  111|  28.2k|#ifndef NDEBUG
  112|  28.2k|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|  28.2k|    int ret = 0;
  118|  28.2k|    pthread_mutexattr_t attr;
  119|  28.2k|    ret = pthread_mutexattr_init(&attr);
  120|  28.2k|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 28.2k]
  ------------------
  121|      0|        return ret;
  122|       |
  123|  28.2k|    pthread_mutexattr_settype(&attr, mutex_type);
  124|  28.2k|    ret = pthread_mutex_init(mutex, &attr);
  125|  28.2k|    pthread_mutexattr_destroy(&attr);
  126|  28.2k|    mp_assert(!ret);
  ------------------
  |  |   41|  28.2k|#define mp_assert assert
  ------------------
  127|  28.2k|    return ret;
  128|  28.2k|}
client.c:mp_mutex_init:
  110|  61.6k|{
  111|  61.6k|#ifndef NDEBUG
  112|  61.6k|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|  61.6k|    int ret = 0;
  118|  61.6k|    pthread_mutexattr_t attr;
  119|  61.6k|    ret = pthread_mutexattr_init(&attr);
  120|  61.6k|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 61.6k]
  ------------------
  121|      0|        return ret;
  122|       |
  123|  61.6k|    pthread_mutexattr_settype(&attr, mutex_type);
  124|  61.6k|    ret = pthread_mutex_init(mutex, &attr);
  125|  61.6k|    pthread_mutexattr_destroy(&attr);
  126|  61.6k|    mp_assert(!ret);
  ------------------
  |  |   41|  61.6k|#define mp_assert assert
  ------------------
  127|  61.6k|    return ret;
  128|  61.6k|}
client.c:mp_cond_init:
  136|  22.2k|{
  137|  22.2k|    mp_assert(cond);
  ------------------
  |  |   41|  22.2k|#define mp_assert assert
  ------------------
  138|       |
  139|  22.2k|    int ret = 0;
  140|  22.2k|    pthread_condattr_t attr;
  141|  22.2k|    ret = pthread_condattr_init(&attr);
  142|  22.2k|    if (ret)
  ------------------
  |  Branch (142:9): [True: 0, False: 22.2k]
  ------------------
  143|      0|        return ret;
  144|       |
  145|  22.2k|    cond->clk_id = CLOCK_REALTIME;
  146|  22.2k|#if HAVE_PTHREAD_CONDATTR_SETCLOCK
  147|  22.2k|    if (!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
  ------------------
  |  Branch (147:9): [True: 22.2k, False: 0]
  ------------------
  148|  22.2k|        cond->clk_id = CLOCK_MONOTONIC;
  149|  22.2k|#endif
  150|       |
  151|  22.2k|    ret = pthread_cond_init(&cond->cond, &attr);
  152|  22.2k|    pthread_condattr_destroy(&attr);
  153|  22.2k|    return ret;
  154|  22.2k|}
client.c:mp_cond_timedwait_until:
  202|  4.32k|{
  203|  4.32k|    return mp_cond_timedwait(cond, mutex, until - mp_time_ns());
  204|  4.32k|}
client.c:mp_cond_timedwait:
  181|  4.32k|{
  182|  4.32k|    mp_assert(cond);
  ------------------
  |  |   41|  4.32k|#define mp_assert assert
  ------------------
  183|       |
  184|  4.32k|    timeout = MPMAX(0, timeout);
  ------------------
  |  |   43|  4.32k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 4.32k, False: 0]
  |  |  ------------------
  ------------------
  185|       |    // consider anything above 1000 days as infinity
  186|  4.32k|    if (timeout > MP_TIME_S_TO_NS(1000 * 24 * 60 * 60))
  ------------------
  |  |   59|  4.32k|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  |  Branch (186:9): [True: 0, False: 4.32k]
  ------------------
  187|      0|        return pthread_cond_wait(&cond->cond, mutex);
  188|       |
  189|  4.32k|    struct timespec ts;
  190|  4.32k|    clock_gettime(cond->clk_id, &ts);
  191|  4.32k|    ts.tv_sec  += timeout / MP_TIME_S_TO_NS(1);
  ------------------
  |  |   59|  4.32k|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  192|  4.32k|    ts.tv_nsec += timeout % MP_TIME_S_TO_NS(1);
  ------------------
  |  |   59|  4.32k|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  193|  4.32k|    if (ts.tv_nsec >= MP_TIME_S_TO_NS(1)) {
  ------------------
  |  |   59|  4.32k|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  |  Branch (193:9): [True: 0, False: 4.32k]
  ------------------
  194|      0|        ts.tv_nsec -= MP_TIME_S_TO_NS(1);
  ------------------
  |  |   59|      0|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  195|      0|        ts.tv_sec++;
  196|      0|    }
  197|       |
  198|  4.32k|    return pthread_cond_timedwait(&cond->cond, mutex, &ts);
  199|  4.32k|}
client.c:mp_cond_destroy:
  157|  22.2k|{
  158|  22.2k|    mp_assert(cond);
  ------------------
  |  |   41|  22.2k|#define mp_assert assert
  ------------------
  159|  22.2k|    return pthread_cond_destroy(&cond->cond);
  160|  22.2k|}
client.c:mp_thread_set_name:
  219|  17.0k|{
  220|  17.0k|#if HAVE_GLIBC_THREAD_NAME
  221|  17.0k|    if (pthread_setname_np(pthread_self(), name) == ERANGE) {
  ------------------
  |  Branch (221:9): [True: 0, False: 17.0k]
  ------------------
  222|      0|        char tname[16] = {0}; // glibc-checked kernel limit
  223|      0|        strncpy(tname, name, sizeof(tname) - 1);
  224|      0|        pthread_setname_np(pthread_self(), tname);
  225|      0|    }
  226|       |#elif HAVE_BSD_THREAD_NAME
  227|       |    pthread_set_name_np(pthread_self(), name);
  228|       |#elif HAVE_MAC_THREAD_NAME
  229|       |    pthread_setname_np(name);
  230|       |#endif
  231|  17.0k|}
client.c:mp_cond_broadcast:
  163|    687|{
  164|    687|    mp_assert(cond);
  ------------------
  |  |   41|    687|#define mp_assert assert
  ------------------
  165|    687|    return pthread_cond_broadcast(&cond->cond);
  166|    687|}
loadfile.c:mp_thread_set_name:
  219|    405|{
  220|    405|#if HAVE_GLIBC_THREAD_NAME
  221|    405|    if (pthread_setname_np(pthread_self(), name) == ERANGE) {
  ------------------
  |  Branch (221:9): [True: 0, False: 405]
  ------------------
  222|      0|        char tname[16] = {0}; // glibc-checked kernel limit
  223|      0|        strncpy(tname, name, sizeof(tname) - 1);
  224|      0|        pthread_setname_np(pthread_self(), tname);
  225|      0|    }
  226|       |#elif HAVE_BSD_THREAD_NAME
  227|       |    pthread_set_name_np(pthread_self(), name);
  228|       |#elif HAVE_MAC_THREAD_NAME
  229|       |    pthread_setname_np(name);
  230|       |#endif
  231|    405|}
main.c:mp_mutex_init:
  110|  17.0k|{
  111|  17.0k|#ifndef NDEBUG
  112|  17.0k|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|  17.0k|    int ret = 0;
  118|  17.0k|    pthread_mutexattr_t attr;
  119|  17.0k|    ret = pthread_mutexattr_init(&attr);
  120|  17.0k|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 17.0k]
  ------------------
  121|      0|        return ret;
  122|       |
  123|  17.0k|    pthread_mutexattr_settype(&attr, mutex_type);
  124|  17.0k|    ret = pthread_mutex_init(mutex, &attr);
  125|  17.0k|    pthread_mutexattr_destroy(&attr);
  126|  17.0k|    mp_assert(!ret);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  127|  17.0k|    return ret;
  128|  17.0k|}
osd.c:mp_mutex_init:
  110|  17.0k|{
  111|  17.0k|#ifndef NDEBUG
  112|  17.0k|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|  17.0k|    int ret = 0;
  118|  17.0k|    pthread_mutexattr_t attr;
  119|  17.0k|    ret = pthread_mutexattr_init(&attr);
  120|  17.0k|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 17.0k]
  ------------------
  121|      0|        return ret;
  122|       |
  123|  17.0k|    pthread_mutexattr_settype(&attr, mutex_type);
  124|  17.0k|    ret = pthread_mutex_init(mutex, &attr);
  125|  17.0k|    pthread_mutexattr_destroy(&attr);
  126|  17.0k|    mp_assert(!ret);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  127|  17.0k|    return ret;
  128|  17.0k|}
scripting.c:mp_thread_set_name:
  219|  5.22k|{
  220|  5.22k|#if HAVE_GLIBC_THREAD_NAME
  221|  5.22k|    if (pthread_setname_np(pthread_self(), name) == ERANGE) {
  ------------------
  |  Branch (221:9): [True: 2.59k, False: 2.63k]
  ------------------
  222|  2.59k|        char tname[16] = {0}; // glibc-checked kernel limit
  223|  2.59k|        strncpy(tname, name, sizeof(tname) - 1);
  224|  2.59k|        pthread_setname_np(pthread_self(), tname);
  225|  2.59k|    }
  226|       |#elif HAVE_BSD_THREAD_NAME
  227|       |    pthread_set_name_np(pthread_self(), name);
  228|       |#elif HAVE_MAC_THREAD_NAME
  229|       |    pthread_setname_np(name);
  230|       |#endif
  231|  5.22k|}
dr_helper.c:mp_mutex_init:
  110|     17|{
  111|     17|#ifndef NDEBUG
  112|     17|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|     17|    int ret = 0;
  118|     17|    pthread_mutexattr_t attr;
  119|     17|    ret = pthread_mutexattr_init(&attr);
  120|     17|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 17]
  ------------------
  121|      0|        return ret;
  122|       |
  123|     17|    pthread_mutexattr_settype(&attr, mutex_type);
  124|     17|    ret = pthread_mutex_init(mutex, &attr);
  125|     17|    pthread_mutexattr_destroy(&attr);
  126|     17|    mp_assert(!ret);
  ------------------
  |  |   41|     17|#define mp_assert assert
  ------------------
  127|     17|    return ret;
  128|     17|}
vo.c:mp_mutex_init:
  110|    152|{
  111|    152|#ifndef NDEBUG
  112|    152|    int mutex_type = PTHREAD_MUTEX_ERRORCHECK;
  113|       |#else
  114|       |    int mutex_type = PTHREAD_MUTEX_DEFAULT;
  115|       |#endif
  116|       |
  117|    152|    int ret = 0;
  118|    152|    pthread_mutexattr_t attr;
  119|    152|    ret = pthread_mutexattr_init(&attr);
  120|    152|    if (ret != 0)
  ------------------
  |  Branch (120:9): [True: 0, False: 152]
  ------------------
  121|      0|        return ret;
  122|       |
  123|    152|    pthread_mutexattr_settype(&attr, mutex_type);
  124|    152|    ret = pthread_mutex_init(mutex, &attr);
  125|    152|    pthread_mutexattr_destroy(&attr);
  126|    152|    mp_assert(!ret);
  ------------------
  |  |   41|    152|#define mp_assert assert
  ------------------
  127|    152|    return ret;
  128|    152|}
vo.c:mp_cond_init:
  136|     76|{
  137|     76|    mp_assert(cond);
  ------------------
  |  |   41|     76|#define mp_assert assert
  ------------------
  138|       |
  139|     76|    int ret = 0;
  140|     76|    pthread_condattr_t attr;
  141|     76|    ret = pthread_condattr_init(&attr);
  142|     76|    if (ret)
  ------------------
  |  Branch (142:9): [True: 0, False: 76]
  ------------------
  143|      0|        return ret;
  144|       |
  145|     76|    cond->clk_id = CLOCK_REALTIME;
  146|     76|#if HAVE_PTHREAD_CONDATTR_SETCLOCK
  147|     76|    if (!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
  ------------------
  |  Branch (147:9): [True: 76, False: 0]
  ------------------
  148|     76|        cond->clk_id = CLOCK_MONOTONIC;
  149|     76|#endif
  150|       |
  151|     76|    ret = pthread_cond_init(&cond->cond, &attr);
  152|     76|    pthread_condattr_destroy(&attr);
  153|     76|    return ret;
  154|     76|}
vo.c:mp_thread_set_name:
  219|     76|{
  220|     76|#if HAVE_GLIBC_THREAD_NAME
  221|     76|    if (pthread_setname_np(pthread_self(), name) == ERANGE) {
  ------------------
  |  Branch (221:9): [True: 0, False: 76]
  ------------------
  222|      0|        char tname[16] = {0}; // glibc-checked kernel limit
  223|      0|        strncpy(tname, name, sizeof(tname) - 1);
  224|      0|        pthread_setname_np(pthread_self(), tname);
  225|      0|    }
  226|       |#elif HAVE_BSD_THREAD_NAME
  227|       |    pthread_set_name_np(pthread_self(), name);
  228|       |#elif HAVE_MAC_THREAD_NAME
  229|       |    pthread_setname_np(name);
  230|       |#endif
  231|     76|}
vo.c:mp_cond_broadcast:
  163|    412|{
  164|    412|    mp_assert(cond);
  ------------------
  |  |   41|    412|#define mp_assert assert
  ------------------
  165|    412|    return pthread_cond_broadcast(&cond->cond);
  166|    412|}
vo.c:mp_cond_destroy:
  157|     76|{
  158|     76|    mp_assert(cond);
  ------------------
  |  |   41|     76|#define mp_assert assert
  ------------------
  159|     76|    return pthread_cond_destroy(&cond->cond);
  160|     76|}
vo.c:mp_cond_timedwait_until:
  202|    215|{
  203|    215|    return mp_cond_timedwait(cond, mutex, until - mp_time_ns());
  204|    215|}
vo.c:mp_cond_timedwait:
  181|    215|{
  182|    215|    mp_assert(cond);
  ------------------
  |  |   41|    215|#define mp_assert assert
  ------------------
  183|       |
  184|    215|    timeout = MPMAX(0, timeout);
  ------------------
  |  |   43|    215|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 215]
  |  |  ------------------
  ------------------
  185|       |    // consider anything above 1000 days as infinity
  186|    215|    if (timeout > MP_TIME_S_TO_NS(1000 * 24 * 60 * 60))
  ------------------
  |  |   59|    215|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  |  Branch (186:9): [True: 0, False: 215]
  ------------------
  187|      0|        return pthread_cond_wait(&cond->cond, mutex);
  188|       |
  189|    215|    struct timespec ts;
  190|    215|    clock_gettime(cond->clk_id, &ts);
  191|    215|    ts.tv_sec  += timeout / MP_TIME_S_TO_NS(1);
  ------------------
  |  |   59|    215|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  192|    215|    ts.tv_nsec += timeout % MP_TIME_S_TO_NS(1);
  ------------------
  |  |   59|    215|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  193|    215|    if (ts.tv_nsec >= MP_TIME_S_TO_NS(1)) {
  ------------------
  |  |   59|    215|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  |  Branch (193:9): [True: 215, False: 0]
  ------------------
  194|    215|        ts.tv_nsec -= MP_TIME_S_TO_NS(1);
  ------------------
  |  |   59|    215|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  195|    215|        ts.tv_sec++;
  196|    215|    }
  197|       |
  198|    215|    return pthread_cond_timedwait(&cond->cond, mutex, &ts);
  199|    215|}
ipc-unix.c:mp_thread_set_name:
  219|  4.32k|{
  220|  4.32k|#if HAVE_GLIBC_THREAD_NAME
  221|  4.32k|    if (pthread_setname_np(pthread_self(), name) == ERANGE) {
  ------------------
  |  Branch (221:9): [True: 2.45k, False: 1.87k]
  ------------------
  222|  2.45k|        char tname[16] = {0}; // glibc-checked kernel limit
  223|  2.45k|        strncpy(tname, name, sizeof(tname) - 1);
  224|  2.45k|        pthread_setname_np(pthread_self(), tname);
  225|  2.45k|    }
  226|       |#elif HAVE_BSD_THREAD_NAME
  227|       |    pthread_set_name_np(pthread_self(), name);
  228|       |#elif HAVE_MAC_THREAD_NAME
  229|       |    pthread_setname_np(name);
  230|       |#endif
  231|  4.32k|}
terminal-unix.c:mp_thread_set_name:
  219|     11|{
  220|     11|#if HAVE_GLIBC_THREAD_NAME
  221|     11|    if (pthread_setname_np(pthread_self(), name) == ERANGE) {
  ------------------
  |  Branch (221:9): [True: 0, False: 11]
  ------------------
  222|      0|        char tname[16] = {0}; // glibc-checked kernel limit
  223|      0|        strncpy(tname, name, sizeof(tname) - 1);
  224|      0|        pthread_setname_np(pthread_self(), tname);
  225|      0|    }
  226|       |#elif HAVE_BSD_THREAD_NAME
  227|       |    pthread_set_name_np(pthread_self(), name);
  228|       |#elif HAVE_MAC_THREAD_NAME
  229|       |    pthread_setname_np(name);
  230|       |#endif
  231|     11|}

mp_raw_time_ns:
   41|   104k|{
   42|   104k|    struct timespec tp = {0};
   43|   104k|    clock_gettime(clk_id, &tp);
   44|   104k|    return MP_TIME_S_TO_NS(tp.tv_sec) + tp.tv_nsec;
  ------------------
  |  |   59|   104k|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
   45|   104k|}
mp_raw_time_init:
   48|      1|{
   49|      1|    static const clockid_t clock_ids[] = {
   50|      1|#ifdef CLOCK_MONOTONIC_RAW
   51|      1|        CLOCK_MONOTONIC_RAW,
   52|      1|#endif
   53|      1|        CLOCK_MONOTONIC,
   54|      1|    };
   55|       |
   56|      1|    struct timespec tp;
   57|      1|    for (int i = 0; i < MP_ARRAY_SIZE(clock_ids); ++i) {
  ------------------
  |  |   48|      1|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (57:21): [True: 1, False: 0]
  ------------------
   58|      1|        clk_id = clock_ids[i];
   59|      1|        if (!clock_gettime(clk_id, &tp))
  ------------------
  |  Branch (59:13): [True: 1, False: 0]
  ------------------
   60|      1|            return;
   61|      1|    }
   62|      0|    fputs("No clock source available!\n", stderr);
   63|      0|    abort();
   64|      1|}

mp_time_init:
   39|  17.0k|{
   40|  17.0k|    mp_exec_once(&timer_init_once, do_timer_init);
  ------------------
  |  |  206|  17.0k|#define mp_exec_once pthread_once
  ------------------
   41|  17.0k|}
mp_time_ns:
   44|   104k|{
   45|   104k|    return mp_time_ns_from_raw_time(mp_raw_time_ns());
   46|   104k|}
mp_time_ns_from_raw_time:
   49|   104k|{
   50|   104k|    return raw_time - raw_time_offset;
   51|   104k|}
mp_time_sec:
   54|  89.8k|{
   55|  89.8k|    return mp_time_ns() / 1e9;
   56|  89.8k|}
mp_time_ns_add:
   59|  6.97k|{
   60|  6.97k|    mp_assert(time_ns > 0); // mp_time_ns() returns strictly positive values
  ------------------
  |  |   41|  6.97k|#define mp_assert assert
  ------------------
   61|  6.97k|    double t = MPCLAMP(timeout_sec * 1e9, -0x1p63, 0x1p63);
  ------------------
  |  |   45|  6.97k|#define MPCLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
  |  |  ------------------
  |  |  |  Branch (45:31): [True: 0, False: 6.97k]
  |  |  |  Branch (45:56): [True: 1.33k, False: 5.64k]
  |  |  ------------------
  ------------------
   62|  6.97k|    int64_t ti = t == 0x1p63 ? INT64_MAX : (int64_t)t;
  ------------------
  |  Branch (62:18): [True: 1.33k, False: 5.64k]
  ------------------
   63|  6.97k|    if (ti > INT64_MAX - time_ns)
  ------------------
  |  Branch (63:9): [True: 1.33k, False: 5.64k]
  ------------------
   64|  1.33k|        return INT64_MAX;
   65|  5.64k|    if (ti <= -time_ns)
  ------------------
  |  Branch (65:9): [True: 0, False: 5.64k]
  ------------------
   66|      0|        return 1;
   67|  5.64k|    return time_ns + ti;
   68|  5.64k|}
timer.c:do_timer_init:
   32|      1|{
   33|      1|    mp_raw_time_init();
   34|      1|    raw_time_offset = mp_raw_time_ns();
   35|      1|    mp_assert(raw_time_offset > 0);
  ------------------
  |  |   41|      1|#define mp_assert assert
  ------------------
   36|      1|}

audio_update_volume:
  187|  12.1k|{
  188|  12.1k|    struct ao_chain *ao_c = mpctx->ao_chain;
  189|  12.1k|    if (!ao_c || !ao_c->ao)
  ------------------
  |  Branch (189:9): [True: 12.1k, False: 0]
  |  Branch (189:18): [True: 0, False: 0]
  ------------------
  190|  12.1k|        return;
  191|       |
  192|      0|    float gain = audio_get_gain(mpctx);
  193|      0|    ao_set_gain(ao_c->ao, gain);
  194|      0|}
reset_audio_state:
  231|  3.93k|{
  232|  3.93k|    if (mpctx->ao_chain) {
  ------------------
  |  Branch (232:9): [True: 0, False: 3.93k]
  ------------------
  233|      0|        ao_chain_reset_state(mpctx->ao_chain);
  234|      0|        struct track *t = mpctx->ao_chain->track;
  235|      0|        if (t && t->dec)
  ------------------
  |  Branch (235:13): [True: 0, False: 0]
  |  Branch (235:18): [True: 0, False: 0]
  ------------------
  236|      0|            mp_decoder_wrapper_set_play_dir(t->dec, mpctx->play_dir);
  237|      0|    }
  238|  3.93k|    mpctx->audio_status = mpctx->ao_chain ? STATUS_SYNCING : STATUS_EOF;
  ------------------
  |  Branch (238:27): [True: 0, False: 3.93k]
  ------------------
  239|  3.93k|    mpctx->delay = 0;
  240|  3.93k|    mpctx->logged_async_diff = -1;
  241|  3.93k|}
uninit_audio_out:
  244|  17.1k|{
  245|  17.1k|    struct ao_chain *ao_c = mpctx->ao_chain;
  246|  17.1k|    if (ao_c) {
  ------------------
  |  Branch (246:9): [True: 0, False: 17.1k]
  ------------------
  247|      0|        ao_c->ao_queue = NULL;
  248|      0|        TA_FREEP(&ao_c->queue_filter);
  ------------------
  |  |   81|      0|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|      0|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  249|      0|        ao_c->ao = NULL;
  250|      0|    }
  251|  17.1k|    if (mpctx->ao) {
  ------------------
  |  Branch (251:9): [True: 0, False: 17.1k]
  ------------------
  252|       |        // Note: with gapless_audio, stop_play is not correctly set
  253|      0|        if ((mpctx->opts->gapless_audio || mpctx->stop_play == AT_END_OF_FILE) &&
  ------------------
  |  Branch (253:14): [True: 0, False: 0]
  |  Branch (253:44): [True: 0, False: 0]
  ------------------
  254|      0|            ao_is_playing(mpctx->ao) && !get_internal_paused(mpctx))
  ------------------
  |  Branch (254:13): [True: 0, False: 0]
  |  Branch (254:41): [True: 0, False: 0]
  ------------------
  255|      0|        {
  256|      0|            MP_VERBOSE(mpctx, "draining left over audio\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  257|      0|            ao_drain(mpctx->ao);
  258|      0|        }
  259|      0|        ao_uninit(mpctx->ao);
  260|       |
  261|      0|        mp_notify(mpctx, MPV_EVENT_AUDIO_RECONFIG, NULL);
  262|      0|    }
  263|  17.1k|    mpctx->ao = NULL;
  264|  17.1k|    TA_FREEP(&mpctx->ao_filter_fmt);
  ------------------
  |  |   81|  17.1k|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|  17.1k|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  265|  17.1k|}
uninit_audio_chain:
  288|  3.93k|{
  289|  3.93k|    if (mpctx->ao_chain) {
  ------------------
  |  Branch (289:9): [True: 0, False: 3.93k]
  ------------------
  290|      0|        ao_chain_uninit(mpctx->ao_chain);
  291|      0|        mpctx->ao_chain = NULL;
  292|       |
  293|      0|        mpctx->audio_status = STATUS_EOF;
  294|       |
  295|      0|        mp_notify(mpctx, MPV_EVENT_AUDIO_RECONFIG, NULL);
  296|      0|    }
  297|  3.93k|}
reload_audio_output:
  766|  12.1k|{
  767|  12.1k|    if (!mpctx->ao)
  ------------------
  |  Branch (767:9): [True: 12.1k, False: 0]
  ------------------
  768|  12.1k|        return;
  769|       |
  770|      0|    ao_reset(mpctx->ao);
  771|      0|    uninit_audio_out(mpctx);
  772|      0|    reinit_audio_filters(mpctx); // mostly to issue refresh seek
  773|       |
  774|      0|    struct ao_chain *ao_c = mpctx->ao_chain;
  775|       |
  776|      0|    if (ao_c) {
  ------------------
  |  Branch (776:9): [True: 0, False: 0]
  ------------------
  777|      0|        reset_audio_state(mpctx);
  778|      0|        mp_output_chain_reset_harder(ao_c->filter);
  779|      0|    }
  780|       |
  781|       |    // Whether we can use spdif might have changed. If we failed to use spdif
  782|       |    // in the previous initialization, try it with spdif again (we'll fallback
  783|       |    // to PCM again if necessary).
  784|      0|    if (ao_c && ao_c->track) {
  ------------------
  |  Branch (784:9): [True: 0, False: 0]
  |  Branch (784:17): [True: 0, False: 0]
  ------------------
  785|      0|        struct mp_decoder_wrapper *dec = ao_c->track->dec;
  786|      0|        if (dec && ao_c->spdif_failed) {
  ------------------
  |  Branch (786:13): [True: 0, False: 0]
  |  Branch (786:20): [True: 0, False: 0]
  ------------------
  787|      0|            ao_c->spdif_passthrough = true;
  788|      0|            ao_c->spdif_failed = false;
  789|      0|            mp_decoder_wrapper_set_spdif_flag(ao_c->track->dec, true);
  790|      0|            if (!mp_decoder_wrapper_reinit(dec)) {
  ------------------
  |  Branch (790:17): [True: 0, False: 0]
  ------------------
  791|      0|                MP_ERR(mpctx, "Error reinitializing audio.\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  792|      0|                error_on_track(mpctx, ao_c->track);
  793|      0|            }
  794|      0|        }
  795|      0|    }
  796|       |
  797|      0|    mp_wakeup_core(mpctx);
  798|      0|}
clear_audio_output_buffers:
  992|  3.93k|{
  993|  3.93k|    if (mpctx->ao)
  ------------------
  |  Branch (993:9): [True: 0, False: 3.93k]
  ------------------
  994|      0|        ao_reset(mpctx->ao);
  995|  3.93k|}

mp_clients_init:
  180|  17.0k|{
  181|  17.0k|    mpctx->clients = talloc_ptrtype(NULL, mpctx->clients);
  ------------------
  |  |   34|  17.0k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  17.0k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  182|  17.0k|    *mpctx->clients = (struct mp_client_api) {
  183|  17.0k|        .mpctx = mpctx,
  184|  17.0k|    };
  185|  17.0k|    mpctx->global->client_api = mpctx->clients;
  186|  17.0k|    mp_mutex_init(&mpctx->clients->lock);
  187|  17.0k|}
mp_clients_destroy:
  190|  17.0k|{
  191|  17.0k|    if (!mpctx->clients)
  ------------------
  |  Branch (191:9): [True: 0, False: 17.0k]
  ------------------
  192|      0|        return;
  193|  17.0k|    mp_assert(mpctx->clients->num_clients == 0);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  194|       |
  195|       |    // The API user is supposed to call mpv_render_context_free(). It's simply
  196|       |    // not allowed not to do this.
  197|  17.0k|    if (mpctx->clients->render_context) {
  ------------------
  |  Branch (197:9): [True: 0, False: 17.0k]
  ------------------
  198|      0|        MP_FATAL(mpctx, "Broken API use: mpv_render_context_free() not called.\n");
  ------------------
  |  |   84|      0|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  199|      0|        abort();
  200|      0|    }
  201|       |
  202|  17.0k|    mp_mutex_destroy(&mpctx->clients->lock);
  ------------------
  |  |  130|  17.0k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
  203|  17.0k|    talloc_free(mpctx->clients);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  204|  17.0k|    mpctx->clients = NULL;
  205|  17.0k|}
mp_clients_all_initialized:
  210|  12.8k|{
  211|  12.8k|    bool all_ok = true;
  212|  12.8k|    mp_mutex_lock(&mpctx->clients->lock);
  ------------------
  |  |  131|  12.8k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  213|  17.4k|    for (int n = 0; n < mpctx->clients->num_clients; n++) {
  ------------------
  |  Branch (213:21): [True: 4.56k, False: 12.8k]
  ------------------
  214|  4.56k|        struct mpv_handle *ctx = mpctx->clients->clients[n];
  215|  4.56k|        mp_mutex_lock(&ctx->lock);
  ------------------
  |  |  131|  4.56k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  216|  4.56k|        all_ok &= ctx->fuzzy_initialized;
  217|  4.56k|        mp_mutex_unlock(&ctx->lock);
  ------------------
  |  |  133|  4.56k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  218|  4.56k|    }
  219|  12.8k|    mp_mutex_unlock(&mpctx->clients->lock);
  ------------------
  |  |  133|  12.8k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  220|  12.8k|    return all_ok;
  221|  12.8k|}
mp_new_client:
  261|  22.3k|{
  262|  22.3k|    mp_mutex_lock(&clients->lock);
  ------------------
  |  |  131|  22.3k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  263|       |
  264|  22.3k|    char nname[MAX_CLIENT_NAME];
  265|  26.8k|    for (int n = 1; n < 1000; n++) {
  ------------------
  |  Branch (265:21): [True: 26.8k, False: 0]
  ------------------
  266|  26.8k|        if (!name)
  ------------------
  |  Branch (266:13): [True: 0, False: 26.8k]
  ------------------
  267|      0|            name = "client";
  268|  26.8k|        snprintf(nname, sizeof(nname) - 3, "%s", name); // - space for number
  269|   209k|        for (int i = 0; nname[i]; i++)
  ------------------
  |  Branch (269:25): [True: 183k, False: 26.8k]
  ------------------
  270|   183k|            nname[i] = mp_isalnum(nname[i]) ? nname[i] : '_';
  ------------------
  |  Branch (270:24): [True: 132k, False: 50.6k]
  ------------------
  271|  26.8k|        if (n > 1)
  ------------------
  |  Branch (271:13): [True: 4.49k, False: 22.3k]
  ------------------
  272|  4.49k|            mp_snprintf_cat(nname, sizeof(nname), "%d", n);
  273|  26.8k|        if (!find_client(clients, nname))
  ------------------
  |  Branch (273:13): [True: 22.3k, False: 4.49k]
  ------------------
  274|  22.3k|            break;
  275|  4.49k|        nname[0] = '\0';
  276|  4.49k|    }
  277|       |
  278|  22.3k|    if (!nname[0] || clients->shutting_down) {
  ------------------
  |  Branch (278:9): [True: 68, False: 22.2k]
  |  Branch (278:22): [True: 0, False: 22.2k]
  ------------------
  279|     68|        mp_mutex_unlock(&clients->lock);
  ------------------
  |  |  133|     68|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  280|     68|        return NULL;
  281|     68|    }
  282|       |
  283|  22.2k|    int num_events = 1000;
  284|       |
  285|  22.2k|    struct mpv_handle *client = talloc_ptrtype(NULL, client);
  ------------------
  |  |   34|  22.2k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  22.2k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  22.2k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  286|  22.2k|    *client = (struct mpv_handle){
  287|  22.2k|        .log = mp_log_new(client, clients->mpctx->log, nname),
  288|  22.2k|        .mpctx = clients->mpctx,
  289|  22.2k|        .clients = clients,
  290|  22.2k|        .id = ++(clients->id_alloc),
  291|  22.2k|        .cur_event = talloc_zero(client, struct mpv_event),
  ------------------
  |  |   27|  22.2k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  22.2k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  22.2k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  292|  22.2k|        .events = talloc_array(client, mpv_event, num_events),
  ------------------
  |  |   29|  22.2k|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|  22.2k|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  22.2k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  293|  22.2k|        .max_events = num_events,
  294|  22.2k|        .event_mask = (1ULL << INTERNAL_EVENT_BASE) - 1, // exclude internal events
  295|  22.2k|        .wakeup_pipe = {-1, -1},
  296|  22.2k|    };
  297|  22.2k|    mp_mutex_init(&client->lock);
  298|  22.2k|    mp_mutex_init(&client->wakeup_lock);
  299|  22.2k|    mp_cond_init(&client->wakeup);
  300|       |
  301|  22.2k|    snprintf(client->name, sizeof(client->name), "%s", nname);
  302|       |
  303|  22.2k|    clients->clients_list_change_ts += 1;
  304|  22.2k|    MP_TARRAY_APPEND(clients, clients->clients, clients->num_clients, client);
  ------------------
  |  |  105|  22.2k|    do {                                            \
  |  |  106|  22.2k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  22.2k|    do {                                            \
  |  |  |  |   97|  22.2k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  22.2k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  22.2k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  22.2k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 17.4k, False: 4.83k]
  |  |  |  |  ------------------
  |  |  |  |   99|  22.2k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  17.4k|    do {                                                        \
  |  |  |  |  |  |   89|  17.4k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  17.4k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  17.4k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  17.4k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  17.4k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  17.4k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  17.4k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  22.2k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  22.2k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  22.2k|        (idxvar)++;                                 \
  |  |  109|  22.2k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  305|       |
  306|  22.2k|    if (clients->num_clients == 1 && !clients->mpctx->is_cli)
  ------------------
  |  Branch (306:9): [True: 17.0k, False: 5.22k]
  |  Branch (306:38): [True: 17.0k, False: 0]
  ------------------
  307|  17.0k|        client->fuzzy_initialized = true;
  308|       |
  309|  22.2k|    mp_mutex_unlock(&clients->lock);
  ------------------
  |  |  133|  22.2k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  310|       |
  311|  22.2k|    mpv_request_event(client, MPV_EVENT_TICK, 0);
  312|       |
  313|  22.2k|    return client;
  314|  22.3k|}
mp_client_set_weak:
  317|  5.22k|{
  318|  5.22k|    mp_mutex_lock(&ctx->lock);
  ------------------
  |  |  131|  5.22k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  319|  5.22k|    ctx->is_weak = true;
  320|  5.22k|    mp_mutex_unlock(&ctx->lock);
  ------------------
  |  |  133|  5.22k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  321|  5.22k|}
mpv_client_name:
  324|  9.55k|{
  325|  9.55k|    return ctx->name;
  326|  9.55k|}
mpv_client_id:
  329|  5.22k|{
  330|  5.22k|    return ctx->id;
  331|  5.22k|}
mp_client_get_log:
  334|  9.55k|{
  335|  9.55k|    return ctx->log;
  336|  9.55k|}
mpv_wait_async_requests:
  393|  22.2k|{
  394|  22.2k|    mp_mutex_lock(&ctx->lock);
  ------------------
  |  |  131|  22.2k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  395|  22.2k|    while (ctx->reserved_events || ctx->async_counter)
  ------------------
  |  Branch (395:12): [True: 0, False: 22.2k]
  |  Branch (395:36): [True: 0, False: 22.2k]
  ------------------
  396|      0|        wait_wakeup(ctx, INT64_MAX);
  397|  22.2k|    mp_mutex_unlock(&ctx->lock);
  ------------------
  |  |  133|  22.2k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  398|  22.2k|}
mpv_destroy:
  532|  9.54k|{
  533|  9.54k|    mp_destroy_client(ctx, false);
  534|  9.54k|}
mpv_terminate_destroy:
  537|  17.0k|{
  538|  17.0k|    mp_destroy_client(ctx, true);
  539|  17.0k|}
mp_shutdown_clients:
  544|  34.1k|{
  545|  34.1k|    struct mp_client_api *clients = mpctx->clients;
  546|       |
  547|       |    // Forcefully abort async work after 2 seconds of waiting.
  548|  34.1k|    double abort_time = mp_time_sec() + 2;
  549|       |
  550|  34.1k|    mp_mutex_lock(&clients->lock);
  ------------------
  |  |  131|  34.1k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  551|       |
  552|       |    // Prevent that new clients can appear.
  553|  34.1k|    clients->shutting_down = true;
  554|       |
  555|       |    // Wait until we can terminate.
  556|  34.7k|    while (clients->num_clients || mpctx->outstanding_async ||
  ------------------
  |  Branch (556:12): [True: 272, False: 34.4k]
  |  Branch (556:36): [True: 0, False: 34.4k]
  ------------------
  557|  34.7k|           !(mpctx->is_cli || clients->terminate_core_thread))
  ------------------
  |  Branch (557:14): [True: 0, False: 34.4k]
  |  Branch (557:31): [True: 34.1k, False: 320]
  ------------------
  558|    592|    {
  559|    592|        mp_mutex_unlock(&clients->lock);
  ------------------
  |  |  133|    592|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  560|       |
  561|    592|        double left = abort_time - mp_time_sec();
  562|    592|        if (left >= 0) {
  ------------------
  |  Branch (562:13): [True: 592, False: 0]
  ------------------
  563|    592|            mp_set_timeout(mpctx, left);
  564|    592|        } else {
  565|       |            // Forcefully abort any ongoing async work. This is quite rude and
  566|       |            // probably not what everyone wants, so it happens only after a
  567|       |            // timeout.
  568|      0|            abort_async(mpctx, NULL, 0, 0);
  569|      0|        }
  570|       |
  571|    592|        mp_client_broadcast_event(mpctx, MPV_EVENT_SHUTDOWN, NULL);
  572|    592|        mp_wait_events(mpctx);
  573|       |
  574|    592|        mp_mutex_lock(&clients->lock);
  ------------------
  |  |  131|    592|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  575|    592|    }
  576|       |
  577|  34.1k|    mp_mutex_unlock(&clients->lock);
  ------------------
  |  |  133|  34.1k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  578|  34.1k|}
mpv_create:
  610|  17.0k|{
  611|  17.0k|    struct MPContext *mpctx = mp_create();
  612|  17.0k|    if (!mpctx)
  ------------------
  |  Branch (612:9): [True: 0, False: 17.0k]
  ------------------
  613|      0|        return NULL;
  614|       |
  615|  17.0k|    m_config_set_profile(mpctx->mconfig, "libmpv", 0);
  616|       |
  617|  17.0k|    mpv_handle *ctx = mp_new_client(mpctx->clients, "main");
  618|  17.0k|    if (!ctx) {
  ------------------
  |  Branch (618:9): [True: 0, False: 17.0k]
  ------------------
  619|      0|        mp_destroy(mpctx);
  620|      0|        return NULL;
  621|      0|    }
  622|       |
  623|  17.0k|    if (mp_thread_create(&mpctx->core_thread, core_thread, mpctx) != 0) {
  ------------------
  |  |  211|  17.0k|#define mp_thread_create(t, f, a) pthread_create(t, NULL, f, a)
  ------------------
  |  Branch (623:9): [True: 0, False: 17.0k]
  ------------------
  624|      0|        ctx->clients->have_terminator = true; // avoid blocking
  625|      0|        mpv_terminate_destroy(ctx);
  626|      0|        mp_destroy(mpctx);
  627|      0|        return NULL;
  628|      0|    }
  629|       |
  630|  17.0k|    return ctx;
  631|  17.0k|}
mpv_initialize_opts:
  657|  17.0k|{
  658|  17.0k|    lock_core(ctx);
  659|  17.0k|    int res = mp_initialize(ctx->mpctx, options) ? MPV_ERROR_INVALID_PARAMETER : 0;
  ------------------
  |  Branch (659:15): [True: 5.23k, False: 11.8k]
  ------------------
  660|  17.0k|    mp_wakeup_core(ctx->mpctx);
  661|  17.0k|    unlock_core(ctx);
  662|  17.0k|    return res;
  663|  17.0k|}
mp_client_broadcast_event:
  768|  29.8k|{
  769|  29.8k|    struct mp_client_api *clients = mpctx->clients;
  770|       |
  771|  29.8k|    mp_mutex_lock(&clients->lock);
  ------------------
  |  |  131|  29.8k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  772|       |
  773|  58.6k|    for (int n = 0; n < clients->num_clients; n++) {
  ------------------
  |  Branch (773:21): [True: 28.8k, False: 29.8k]
  ------------------
  774|  28.8k|        struct mpv_event event_data = {
  775|  28.8k|            .event_id = event,
  776|  28.8k|            .data = data,
  777|  28.8k|        };
  778|  28.8k|        send_event(clients->clients[n], &event_data, true);
  779|  28.8k|    }
  780|       |
  781|  29.8k|    mp_mutex_unlock(&clients->lock);
  ------------------
  |  |  133|  29.8k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  782|  29.8k|}
mp_client_broadcast_event_external:
  788|    195|{
  789|    195|    struct MPContext *mpctx = api->mpctx;
  790|       |
  791|    195|    mp_client_broadcast_event(mpctx, event, data);
  792|    195|    mp_wakeup_core(mpctx);
  793|    195|}
mpv_request_event:
  852|  22.2k|{
  853|  22.2k|    if (!mpv_event_name(event) || enable < 0 || enable > 1)
  ------------------
  |  Branch (853:9): [True: 0, False: 22.2k]
  |  Branch (853:35): [True: 0, False: 22.2k]
  |  Branch (853:49): [True: 0, False: 22.2k]
  ------------------
  854|      0|        return MPV_ERROR_INVALID_PARAMETER;
  855|  22.2k|    if (event == MPV_EVENT_SHUTDOWN && !enable)
  ------------------
  |  Branch (855:9): [True: 0, False: 22.2k]
  |  Branch (855:40): [True: 0, False: 0]
  ------------------
  856|      0|        return MPV_ERROR_INVALID_PARAMETER;
  857|  22.2k|    mp_assert(event < (int)INTERNAL_EVENT_BASE); // excluded above; they have no name
  ------------------
  |  |   41|  22.2k|#define mp_assert assert
  ------------------
  858|  22.2k|    mp_mutex_lock(&ctx->lock);
  ------------------
  |  |  131|  22.2k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  859|  22.2k|    uint64_t bit = 1ULL << event;
  860|  22.2k|    ctx->event_mask = enable ? ctx->event_mask | bit : ctx->event_mask & ~bit;
  ------------------
  |  Branch (860:23): [True: 0, False: 22.2k]
  ------------------
  861|  22.2k|    if (enable && event < MP_ARRAY_SIZE(deprecated_events) &&
  ------------------
  |  |   48|  22.2k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (861:9): [True: 0, False: 22.2k]
  |  Branch (861:19): [True: 0, False: 0]
  ------------------
  862|  22.2k|        deprecated_events[event])
  ------------------
  |  Branch (862:9): [True: 0, False: 0]
  ------------------
  863|      0|    {
  864|      0|        MP_WARN(ctx, "The '%s' event is deprecated and will be removed.\n",
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  865|      0|                mpv_event_name(event));
  866|      0|    }
  867|  22.2k|    mp_mutex_unlock(&ctx->lock);
  ------------------
  |  |  133|  22.2k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  868|  22.2k|    return 0;
  869|  22.2k|}
mpv_wait_event:
  893|  4.32k|{
  894|  4.32k|    mpv_event *event = ctx->cur_event;
  895|       |
  896|  4.32k|    mp_mutex_lock(&ctx->lock);
  ------------------
  |  |  131|  4.32k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  897|       |
  898|  4.32k|    if (!ctx->fuzzy_initialized)
  ------------------
  |  Branch (898:9): [True: 4.32k, False: 0]
  ------------------
  899|  4.32k|        mp_wakeup_core(ctx->clients->mpctx);
  900|  4.32k|    ctx->fuzzy_initialized = true;
  901|       |
  902|  4.32k|    if (timeout < 0)
  ------------------
  |  Branch (902:9): [True: 0, False: 4.32k]
  ------------------
  903|      0|        timeout = 1e20;
  904|       |
  905|  4.32k|    int64_t deadline = mp_time_ns_add(mp_time_ns(), timeout);
  906|       |
  907|  4.32k|    *event = (mpv_event){0};
  908|  4.32k|    talloc_free_children(event);
  ------------------
  |  |   46|  4.32k|#define talloc_free_children            ta_free_children
  ------------------
  909|       |
  910|  4.41k|    while (1) {
  ------------------
  |  Branch (910:12): [Folded - Ignored]
  ------------------
  911|  4.41k|        if (ctx->queued_wakeup)
  ------------------
  |  Branch (911:13): [True: 0, False: 4.41k]
  ------------------
  912|      0|            deadline = 0;
  913|       |        // Recover from overflow.
  914|  4.41k|        if (ctx->choked && !ctx->num_events) {
  ------------------
  |  Branch (914:13): [True: 0, False: 4.41k]
  |  Branch (914:28): [True: 0, False: 0]
  ------------------
  915|      0|            ctx->choked = false;
  916|      0|            event->event_id = MPV_EVENT_QUEUE_OVERFLOW;
  917|      0|            break;
  918|      0|        }
  919|  4.41k|        struct mpv_event *ev =
  920|  4.41k|            ctx->num_events ? &ctx->events[ctx->first_event] : NULL;
  ------------------
  |  Branch (920:13): [True: 89, False: 4.32k]
  ------------------
  921|  4.41k|        if (ev && ev->event_id == MPV_EVENT_HOOK) {
  ------------------
  |  Branch (921:13): [True: 89, False: 4.32k]
  |  Branch (921:19): [True: 0, False: 89]
  ------------------
  922|       |            // Give old property notifications priority over hooks. This is a
  923|       |            // guarantee given to clients to simplify their logic. New property
  924|       |            // changes after this are treated normally, so
  925|      0|            if (!ctx->hook_pending) {
  ------------------
  |  Branch (925:17): [True: 0, False: 0]
  ------------------
  926|      0|                ctx->hook_pending = true;
  927|      0|                set_wait_for_hook_flags(ctx);
  928|      0|            }
  929|      0|            if (check_for_for_hook_flags(ctx)) {
  ------------------
  |  Branch (929:17): [True: 0, False: 0]
  ------------------
  930|      0|                ev = NULL; // delay
  931|      0|            } else {
  932|      0|                ctx->hook_pending = false;
  933|      0|            }
  934|      0|        }
  935|  4.41k|        if (ev) {
  ------------------
  |  Branch (935:13): [True: 89, False: 4.32k]
  ------------------
  936|     89|            *event = *ev;
  937|     89|            ctx->first_event = (ctx->first_event + 1) % ctx->max_events;
  938|     89|            ctx->num_events--;
  939|     89|            talloc_steal(event, event->data);
  ------------------
  |  |   38|     89|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     89|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  940|     89|            break;
  941|     89|        }
  942|       |        // If there's a changed property, generate change event (never queued).
  943|  4.32k|        if (gen_property_change_event(ctx))
  ------------------
  |  Branch (943:13): [True: 0, False: 4.32k]
  ------------------
  944|      0|            break;
  945|       |        // Pop item from message queue, and return as event.
  946|  4.32k|        if (gen_log_message_event(ctx))
  ------------------
  |  Branch (946:13): [True: 0, False: 4.32k]
  ------------------
  947|      0|            break;
  948|  4.32k|        int r = wait_wakeup(ctx, deadline);
  949|  4.32k|        if (r == ETIMEDOUT)
  ------------------
  |  Branch (949:13): [True: 4.23k, False: 89]
  ------------------
  950|  4.23k|            break;
  951|  4.32k|    }
  952|  4.32k|    ctx->queued_wakeup = false;
  953|       |
  954|  4.32k|    mp_mutex_unlock(&ctx->lock);
  ------------------
  |  |  133|  4.32k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  955|       |
  956|  4.32k|    return event;
  957|  4.32k|}
mpv_free_node_contents:
 1018|  12.1k|{
 1019|  12.1k|    static const struct m_option type = { .type = CONF_TYPE_NODE };
  ------------------
  |  |  241|  12.1k|#define CONF_TYPE_NODE          (&m_option_type_node)
  ------------------
 1020|  12.1k|    m_option_free(&type, node);
 1021|  12.1k|}
mpv_command:
 1145|  17.0k|{
 1146|  17.0k|    return run_client_command(ctx, mp_input_parse_cmd_strv(ctx->log, args), NULL);
 1147|  17.0k|}
mpv_command_string:
 1168|    336|{
 1169|    336|    return run_client_command(ctx,
 1170|    336|        mp_input_parse_cmd(ctx->mpctx->input, bstr0((char*)args), ctx->name), NULL);
 1171|    336|}
mp_client_property_change:
 1620|    816|{
 1621|    816|    struct mp_client_api *clients = mpctx->clients;
 1622|    816|    int id = mp_get_property_id(mpctx, name);
 1623|    816|    bool any_pending = false;
 1624|       |
 1625|    816|    mp_mutex_lock(&clients->lock);
  ------------------
  |  |  131|    816|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1626|       |
 1627|  1.63k|    for (int n = 0; n < clients->num_clients; n++) {
  ------------------
  |  Branch (1627:21): [True: 816, False: 816]
  ------------------
 1628|    816|        struct mpv_handle *client = clients->clients[n];
 1629|    816|        mp_mutex_lock(&client->lock);
  ------------------
  |  |  131|    816|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1630|    816|        for (int i = 0; i < client->num_properties; i++) {
  ------------------
  |  Branch (1630:25): [True: 0, False: 816]
  ------------------
 1631|      0|            if (client->properties[i]->id == id &&
  ------------------
  |  Branch (1631:17): [True: 0, False: 0]
  ------------------
 1632|      0|                property_shared_prefix(name, client->properties[i]->name)) {
  ------------------
  |  Branch (1632:17): [True: 0, False: 0]
  ------------------
 1633|      0|                client->properties[i]->change_ts += 1;
 1634|      0|                client->has_pending_properties = true;
 1635|      0|                any_pending = true;
 1636|      0|            }
 1637|      0|        }
 1638|    816|        mp_mutex_unlock(&client->lock);
  ------------------
  |  |  133|    816|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1639|    816|    }
 1640|       |
 1641|    816|    mp_mutex_unlock(&clients->lock);
  ------------------
  |  |  133|    816|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1642|       |
 1643|       |    // If we're inside mp_dispatch_queue_process(), this will cause the playloop
 1644|       |    // to be re-run (to get mp_client_send_property_changes() called). If we're
 1645|       |    // inside the normal playloop, this does nothing, but the latter function
 1646|       |    // will be called at the end of the playloop anyway.
 1647|    816|    if (any_pending)
  ------------------
  |  Branch (1647:9): [True: 0, False: 816]
  ------------------
 1648|      0|        mp_dispatch_adjust_timeout(mpctx->dispatch, 0);
 1649|    816|}
mp_client_send_property_changes:
 1754|  19.0k|{
 1755|  19.0k|    struct mp_client_api *clients = mpctx->clients;
 1756|       |
 1757|  19.0k|    mp_mutex_lock(&clients->lock);
  ------------------
  |  |  131|  19.0k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1758|  19.0k|    uint64_t cur_ts = clients->clients_list_change_ts;
 1759|       |
 1760|  39.9k|    for (int n = 0; n < clients->num_clients; n++) {
  ------------------
  |  Branch (1760:21): [True: 20.9k, False: 19.0k]
  ------------------
 1761|  20.9k|        struct mpv_handle *ctx = clients->clients[n];
 1762|       |
 1763|  20.9k|        mp_mutex_lock(&ctx->lock);
  ------------------
  |  |  131|  20.9k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1764|  20.9k|        if (!ctx->has_pending_properties || ctx->destroying) {
  ------------------
  |  Branch (1764:13): [True: 20.9k, False: 0]
  |  Branch (1764:45): [True: 0, False: 0]
  ------------------
 1765|  20.9k|            mp_mutex_unlock(&ctx->lock);
  ------------------
  |  |  133|  20.9k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1766|  20.9k|            continue;
 1767|  20.9k|        }
 1768|       |        // Keep ctx->lock locked (unlock order does not matter).
 1769|      0|        mp_mutex_unlock(&clients->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1770|      0|        send_client_property_changes(ctx);
 1771|      0|        mp_mutex_unlock(&ctx->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1772|      0|        mp_mutex_lock(&clients->lock);
  ------------------
  |  |  131|      0|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1773|      0|        if (cur_ts != clients->clients_list_change_ts) {
  ------------------
  |  Branch (1773:13): [True: 0, False: 0]
  ------------------
 1774|       |            // List changed; need to start over. Do it in the next iteration.
 1775|      0|            mp_wakeup_core(mpctx);
 1776|      0|            break;
 1777|      0|        }
 1778|      0|    }
 1779|       |
 1780|  19.0k|    mp_mutex_unlock(&clients->lock);
  ------------------
  |  |  133|  19.0k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1781|  19.0k|}
mpv_get_wakeup_pipe:
 1933|  4.32k|{
 1934|  4.32k|    mp_mutex_lock(&ctx->wakeup_lock);
  ------------------
  |  |  131|  4.32k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1935|  4.32k|    if (ctx->wakeup_pipe[0] == -1) {
  ------------------
  |  Branch (1935:9): [True: 4.32k, False: 0]
  ------------------
 1936|  4.32k|        if (mp_make_wakeup_pipe(ctx->wakeup_pipe) >= 0)
  ------------------
  |  Branch (1936:13): [True: 4.32k, False: 0]
  ------------------
 1937|  4.32k|            (void)write(ctx->wakeup_pipe[1], &(char){0}, 1);
 1938|  4.32k|    }
 1939|  4.32k|    int fd = ctx->wakeup_pipe[0];
 1940|  4.32k|    mp_mutex_unlock(&ctx->wakeup_lock);
  ------------------
  |  |  133|  4.32k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1941|  4.32k|    return fd;
 1942|  4.32k|}
mpv_event_to_node:
 1950|      1|{
 1951|      1|    *dst = (mpv_node){0};
 1952|       |
 1953|      1|    node_init(dst, MPV_FORMAT_NODE_MAP, NULL);
 1954|      1|    node_map_add_string(dst, "event", mpv_event_name(event->event_id));
 1955|       |
 1956|      1|    if (event->error < 0)
  ------------------
  |  Branch (1956:9): [True: 0, False: 1]
  ------------------
 1957|      0|        node_map_add_string(dst, "error", mpv_error_string(event->error));
 1958|       |
 1959|      1|    if (event->reply_userdata)
  ------------------
  |  Branch (1959:9): [True: 0, False: 1]
  ------------------
 1960|      0|        node_map_add_int64(dst, "id", event->reply_userdata);
 1961|       |
 1962|      1|    switch (event->event_id) {
  ------------------
  |  Branch (1962:13): [True: 0, False: 1]
  ------------------
 1963|       |
 1964|      1|    case MPV_EVENT_START_FILE: {
  ------------------
  |  Branch (1964:5): [True: 1, False: 0]
  ------------------
 1965|      1|        mpv_event_start_file *esf = event->data;
 1966|       |
 1967|      1|        node_map_add_int64(dst, "playlist_entry_id", esf->playlist_entry_id);
 1968|      1|        break;
 1969|      0|    }
 1970|       |
 1971|      0|    case MPV_EVENT_END_FILE: {
  ------------------
  |  Branch (1971:5): [True: 0, False: 1]
  ------------------
 1972|      0|        mpv_event_end_file *eef = event->data;
 1973|       |
 1974|      0|        const char *reason;
 1975|      0|        switch (eef->reason) {
 1976|      0|        case MPV_END_FILE_REASON_EOF: reason = "eof"; break;
  ------------------
  |  Branch (1976:9): [True: 0, False: 0]
  ------------------
 1977|      0|        case MPV_END_FILE_REASON_STOP: reason = "stop"; break;
  ------------------
  |  Branch (1977:9): [True: 0, False: 0]
  ------------------
 1978|      0|        case MPV_END_FILE_REASON_QUIT: reason = "quit"; break;
  ------------------
  |  Branch (1978:9): [True: 0, False: 0]
  ------------------
 1979|      0|        case MPV_END_FILE_REASON_ERROR: reason = "error"; break;
  ------------------
  |  Branch (1979:9): [True: 0, False: 0]
  ------------------
 1980|      0|        case MPV_END_FILE_REASON_REDIRECT: reason = "redirect"; break;
  ------------------
  |  Branch (1980:9): [True: 0, False: 0]
  ------------------
 1981|      0|        default:
  ------------------
  |  Branch (1981:9): [True: 0, False: 0]
  ------------------
 1982|      0|            reason = "unknown";
 1983|      0|        }
 1984|      0|        node_map_add_string(dst, "reason", reason);
 1985|       |
 1986|      0|        node_map_add_int64(dst, "playlist_entry_id", eef->playlist_entry_id);
 1987|       |
 1988|      0|        if (eef->playlist_insert_id) {
  ------------------
  |  Branch (1988:13): [True: 0, False: 0]
  ------------------
 1989|      0|            node_map_add_int64(dst, "playlist_insert_id", eef->playlist_insert_id);
 1990|      0|            node_map_add_int64(dst, "playlist_insert_num_entries",
 1991|      0|                               eef->playlist_insert_num_entries);
 1992|      0|        }
 1993|       |
 1994|      0|        if (eef->reason == MPV_END_FILE_REASON_ERROR)
  ------------------
  |  Branch (1994:13): [True: 0, False: 0]
  ------------------
 1995|      0|            node_map_add_string(dst, "file_error", mpv_error_string(eef->error));
 1996|      0|        break;
 1997|      0|    }
 1998|       |
 1999|      0|    case MPV_EVENT_LOG_MESSAGE: {
  ------------------
  |  Branch (1999:5): [True: 0, False: 1]
  ------------------
 2000|      0|        mpv_event_log_message *msg = event->data;
 2001|       |
 2002|      0|        node_map_add_string(dst, "prefix", msg->prefix);
 2003|      0|        node_map_add_string(dst, "level",  msg->level);
 2004|      0|        node_map_add_string(dst, "text",   msg->text);
 2005|      0|        break;
 2006|      0|    }
 2007|       |
 2008|      0|    case MPV_EVENT_CLIENT_MESSAGE: {
  ------------------
  |  Branch (2008:5): [True: 0, False: 1]
  ------------------
 2009|      0|        mpv_event_client_message *msg = event->data;
 2010|       |
 2011|      0|        struct mpv_node *args = node_map_add(dst, "args", MPV_FORMAT_NODE_ARRAY);
 2012|      0|        for (int n = 0; n < msg->num_args; n++) {
  ------------------
  |  Branch (2012:25): [True: 0, False: 0]
  ------------------
 2013|      0|            struct mpv_node *sn = node_array_add(args, MPV_FORMAT_NONE);
 2014|      0|            sn->format = MPV_FORMAT_STRING;
 2015|      0|            sn->u.string = (char *)msg->args[n];
 2016|      0|        }
 2017|      0|        break;
 2018|      0|    }
 2019|       |
 2020|      0|    case MPV_EVENT_PROPERTY_CHANGE: {
  ------------------
  |  Branch (2020:5): [True: 0, False: 1]
  ------------------
 2021|      0|        mpv_event_property *prop = event->data;
 2022|       |
 2023|      0|        node_map_add_string(dst, "name", prop->name);
 2024|       |
 2025|      0|        switch (prop->format) {
 2026|      0|        case MPV_FORMAT_NODE:
  ------------------
  |  Branch (2026:9): [True: 0, False: 0]
  ------------------
 2027|      0|            *node_map_add(dst, "data", MPV_FORMAT_NONE) =
 2028|      0|                *(struct mpv_node *)prop->data;
 2029|      0|            break;
 2030|      0|        case MPV_FORMAT_DOUBLE:
  ------------------
  |  Branch (2030:9): [True: 0, False: 0]
  ------------------
 2031|      0|            node_map_add_double(dst, "data", *(double *)prop->data);
 2032|      0|            break;
 2033|      0|        case MPV_FORMAT_FLAG:
  ------------------
  |  Branch (2033:9): [True: 0, False: 0]
  ------------------
 2034|      0|            node_map_add_flag(dst, "data", *(int *)prop->data);
 2035|      0|            break;
 2036|      0|        case MPV_FORMAT_STRING:
  ------------------
  |  Branch (2036:9): [True: 0, False: 0]
  ------------------
 2037|      0|            node_map_add_string(dst, "data", *(char **)prop->data);
 2038|      0|            break;
 2039|      0|        default: ;
  ------------------
  |  Branch (2039:9): [True: 0, False: 0]
  ------------------
 2040|      0|        }
 2041|      0|        break;
 2042|      0|    }
 2043|       |
 2044|      0|    case MPV_EVENT_COMMAND_REPLY: {
  ------------------
  |  Branch (2044:5): [True: 0, False: 1]
  ------------------
 2045|      0|        mpv_event_command *cmd = event->data;
 2046|       |
 2047|      0|        *node_map_add(dst, "result", MPV_FORMAT_NONE) = cmd->result;
 2048|      0|        break;
 2049|      0|    }
 2050|       |
 2051|      0|    case MPV_EVENT_HOOK: {
  ------------------
  |  Branch (2051:5): [True: 0, False: 1]
  ------------------
 2052|      0|        mpv_event_hook *hook = event->data;
 2053|       |
 2054|      0|        node_map_add_int64(dst, "hook_id", hook->id);
 2055|      0|        break;
 2056|      0|    }
 2057|       |
 2058|      1|    }
 2059|      1|    return 0;
 2060|      1|}
mpv_error_string:
 2087|  3.93k|{
 2088|  3.93k|    error = -error;
 2089|  3.93k|    if (error < 0)
  ------------------
  |  Branch (2089:9): [True: 0, False: 3.93k]
  ------------------
 2090|      0|        error = 0;
 2091|  3.93k|    const char *name = NULL;
 2092|  3.93k|    if (error < MP_ARRAY_SIZE(err_table))
  ------------------
  |  |   48|  3.93k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (2092:9): [True: 3.93k, False: 0]
  ------------------
 2093|  3.93k|        name = err_table[error];
 2094|  3.93k|    return name ? name : "unknown error";
  ------------------
  |  Branch (2094:12): [True: 3.93k, False: 0]
  ------------------
 2095|  3.93k|}
mpv_event_name:
 2120|  22.2k|{
 2121|  22.2k|    if ((unsigned)event >= MP_ARRAY_SIZE(event_table))
  ------------------
  |  |   48|  22.2k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (2121:9): [True: 0, False: 22.2k]
  ------------------
 2122|      0|        return NULL;
 2123|  22.2k|    return event_table[event];
 2124|  22.2k|}
mp_client_api_acquire_render_context:
 2182|      1|{
 2183|      1|    struct mpv_render_context *res = NULL;
 2184|      1|    mp_mutex_lock(&ca->lock);
  ------------------
  |  |  131|      1|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 2185|      1|    if (ca->render_context && mp_render_context_acquire(ca->render_context))
  ------------------
  |  Branch (2185:9): [True: 0, False: 1]
  |  Branch (2185:31): [True: 0, False: 0]
  ------------------
 2186|      0|        res = ca->render_context;
 2187|      1|    mp_mutex_unlock(&ca->lock);
  ------------------
  |  |  133|      1|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 2188|      1|    return res;
 2189|      1|}
mp_streamcb_lookup:
 2232|  1.97k|{
 2233|  1.97k|    struct mp_client_api *clients = g->client_api;
 2234|  1.97k|    bool found = false;
 2235|  1.97k|    mp_mutex_lock(&clients->lock);
  ------------------
  |  |  131|  1.97k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 2236|  1.97k|    for (int n = 0; n < clients->num_custom_protocols; n++) {
  ------------------
  |  Branch (2236:21): [True: 0, False: 1.97k]
  ------------------
 2237|      0|        struct mp_custom_protocol *proto = &clients->custom_protocols[n];
 2238|      0|        if (strcmp(proto->protocol, protocol) == 0) {
  ------------------
  |  Branch (2238:13): [True: 0, False: 0]
  ------------------
 2239|      0|            *out_user_data = proto->user_data;
 2240|      0|            *out_fn = proto->open_fn;
 2241|      0|            found = true;
 2242|      0|            break;
 2243|      0|        }
 2244|      0|    }
 2245|  1.97k|    mp_mutex_unlock(&clients->lock);
  ------------------
  |  |  133|  1.97k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 2246|  1.97k|    return found;
 2247|  1.97k|}
client.c:find_client:
  234|  26.8k|{
  235|  26.8k|    if (name[0] == '@') {
  ------------------
  |  Branch (235:9): [True: 0, False: 26.8k]
  ------------------
  236|      0|        char *end;
  237|      0|        errno = 0;
  238|      0|        long long int id = strtoll(name + 1, &end, 10);
  239|      0|        if (errno || end[0])
  ------------------
  |  Branch (239:22): [True: 0, False: 0]
  ------------------
  240|      0|            return NULL;
  241|      0|        return find_client_id(clients, id);
  242|      0|    }
  243|       |
  244|  73.3k|    for (int n = 0; n < clients->num_clients; n++) {
  ------------------
  |  Branch (244:21): [True: 51.0k, False: 22.3k]
  ------------------
  245|  51.0k|        if (strcmp(clients->clients[n]->name, name) == 0)
  ------------------
  |  Branch (245:13): [True: 4.49k, False: 46.5k]
  ------------------
  246|  4.49k|            return clients->clients[n];
  247|  51.0k|    }
  248|       |
  249|  22.3k|    return NULL;
  250|  26.8k|}
client.c:wait_wakeup:
  359|  4.32k|{
  360|  4.32k|    int r = 0;
  361|  4.32k|    mp_mutex_unlock(&ctx->lock);
  ------------------
  |  |  133|  4.32k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  362|  4.32k|    mp_mutex_lock(&ctx->wakeup_lock);
  ------------------
  |  |  131|  4.32k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  363|  4.32k|    if (!ctx->need_wakeup)
  ------------------
  |  Branch (363:9): [True: 4.32k, False: 0]
  ------------------
  364|  4.32k|        r = mp_cond_timedwait_until(&ctx->wakeup, &ctx->wakeup_lock, end);
  365|  4.32k|    if (r == 0)
  ------------------
  |  Branch (365:9): [True: 89, False: 4.23k]
  ------------------
  366|     89|        ctx->need_wakeup = false;
  367|  4.32k|    mp_mutex_unlock(&ctx->wakeup_lock);
  ------------------
  |  |  133|  4.32k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  368|  4.32k|    mp_mutex_lock(&ctx->lock);
  ------------------
  |  |  131|  4.32k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  369|  4.32k|    return r;
  370|  4.32k|}
client.c:mp_destroy_client:
  425|  26.6k|{
  426|  26.6k|    if (!ctx)
  ------------------
  |  Branch (426:9): [True: 4.32k, False: 22.2k]
  ------------------
  427|  4.32k|        return;
  428|       |
  429|  22.2k|    struct MPContext *mpctx = ctx->mpctx;
  430|  22.2k|    struct mp_client_api *clients = ctx->clients;
  431|       |
  432|  22.2k|    MP_DBG(ctx, "Destroying client handle...\n");
  ------------------
  |  |   89|  22.2k|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  22.2k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  433|       |
  434|  22.2k|    if (terminate)
  ------------------
  |  Branch (434:9): [True: 17.0k, False: 5.22k]
  ------------------
  435|  17.0k|        mpv_command(ctx, (const char*[]){"quit", NULL});
  436|       |
  437|  22.2k|    mp_mutex_lock(&ctx->lock);
  ------------------
  |  |  131|  22.2k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  438|       |
  439|  22.2k|    ctx->destroying = true;
  440|       |
  441|  22.2k|    for (int n = 0; n < ctx->num_properties; n++)
  ------------------
  |  Branch (441:21): [True: 0, False: 22.2k]
  ------------------
  442|      0|        prop_unref(ctx->properties[n]);
  443|  22.2k|    ctx->num_properties = 0;
  444|  22.2k|    ctx->properties_change_ts += 1;
  445|       |
  446|  22.2k|    prop_unref(ctx->cur_property);
  447|  22.2k|    ctx->cur_property = NULL;
  448|       |
  449|  22.2k|    mp_mutex_unlock(&ctx->lock);
  ------------------
  |  |  133|  22.2k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  450|       |
  451|  22.2k|    abort_async(mpctx, ctx, 0, 0);
  452|       |
  453|       |    // reserved_events equals the number of asynchronous requests that weren't
  454|       |    // yet replied. In order to avoid that trying to reply to a removed client
  455|       |    // causes a crash, block until all asynchronous requests were served.
  456|  22.2k|    mpv_wait_async_requests(ctx);
  457|       |
  458|  22.2k|    osd_set_external_remove_owner(mpctx->osd, ctx);
  459|  22.2k|    mp_input_remove_sections_by_owner(mpctx->input, ctx->name);
  460|       |
  461|  22.2k|    mp_mutex_lock(&clients->lock);
  ------------------
  |  |  131|  22.2k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  462|       |
  463|  28.5k|    for (int n = 0; n < clients->num_clients; n++) {
  ------------------
  |  Branch (463:21): [True: 28.5k, False: 18.4E]
  ------------------
  464|  28.5k|        if (clients->clients[n] == ctx) {
  ------------------
  |  Branch (464:13): [True: 22.2k, False: 6.25k]
  ------------------
  465|  22.2k|            clients->clients_list_change_ts += 1;
  466|  22.2k|            MP_TARRAY_REMOVE_AT(clients->clients, clients->num_clients, n);
  ------------------
  |  |  143|  22.2k|    do {                                            \
  |  |  144|  22.2k|        size_t at_ = (at);                          \
  |  |  145|  22.2k|        assert(at_ <= (idxvar));                    \
  |  |  146|  22.2k|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|  22.2k|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|  22.2k|        (idxvar)--;                                 \
  |  |  149|  22.2k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  467|  29.8k|            while (ctx->num_events) {
  ------------------
  |  Branch (467:20): [True: 7.59k, False: 22.2k]
  ------------------
  468|  7.59k|                talloc_free(ctx->events[ctx->first_event].data);
  ------------------
  |  |   47|  7.59k|#define talloc_free                     ta_free
  ------------------
  469|  7.59k|                ctx->first_event = (ctx->first_event + 1) % ctx->max_events;
  470|  7.59k|                ctx->num_events--;
  471|  7.59k|            }
  472|  22.2k|            mp_msg_log_buffer_destroy(ctx->messages);
  473|  22.2k|            mp_cond_destroy(&ctx->wakeup);
  474|  22.2k|            mp_mutex_destroy(&ctx->wakeup_lock);
  ------------------
  |  |  130|  22.2k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
  475|  22.2k|            mp_mutex_destroy(&ctx->lock);
  ------------------
  |  |  130|  22.2k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
  476|  22.2k|            if (ctx->wakeup_pipe[0] != -1) {
  ------------------
  |  Branch (476:17): [True: 4.32k, False: 17.9k]
  ------------------
  477|  4.32k|                close(ctx->wakeup_pipe[0]);
  478|  4.32k|                close(ctx->wakeup_pipe[1]);
  479|  4.32k|            }
  480|  22.2k|            talloc_free(ctx);
  ------------------
  |  |   47|  22.2k|#define talloc_free                     ta_free
  ------------------
  481|  22.2k|            ctx = NULL;
  482|  22.2k|            break;
  483|  22.2k|        }
  484|  28.5k|    }
  485|  22.2k|    mp_assert(!ctx);
  ------------------
  |  |   41|  22.2k|#define mp_assert assert
  ------------------
  486|       |
  487|  22.2k|    if (mpctx->is_cli) {
  ------------------
  |  Branch (487:9): [True: 0, False: 22.2k]
  ------------------
  488|      0|        terminate = false;
  489|  22.2k|    } else {
  490|       |        // If the last strong mpv_handle got destroyed, destroy the core.
  491|  22.2k|        bool has_strong_ref = false;
  492|  38.3k|        for (int n = 0; n < clients->num_clients; n++)
  ------------------
  |  Branch (492:25): [True: 16.0k, False: 22.2k]
  ------------------
  493|  16.0k|            has_strong_ref |= !clients->clients[n]->is_weak;
  494|  22.2k|        if (!has_strong_ref)
  ------------------
  |  Branch (494:13): [True: 19.9k, False: 2.37k]
  ------------------
  495|  19.9k|            terminate = true;
  496|       |
  497|       |        // Reserve the right to destroy mpctx for us.
  498|  22.2k|        if (clients->have_terminator)
  ------------------
  |  Branch (498:13): [True: 2.84k, False: 19.4k]
  ------------------
  499|  2.84k|            terminate = false;
  500|  22.2k|        clients->have_terminator |= terminate;
  501|  22.2k|    }
  502|       |
  503|       |    // mp_shutdown_clients() sleeps to avoid wasting CPU.
  504|       |    // mp_hook_test_completion() also relies on this a bit.
  505|  22.2k|    mp_wakeup_core(mpctx);
  506|       |
  507|  22.2k|    mp_mutex_unlock(&clients->lock);
  ------------------
  |  |  133|  22.2k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  508|       |
  509|       |    // Note that even if num_clients==0, having set have_terminator keeps mpctx
  510|       |    // and the core thread alive.
  511|  22.2k|    if (terminate) {
  ------------------
  |  Branch (511:9): [True: 17.0k, False: 5.22k]
  ------------------
  512|       |        // Make sure the core stops playing files etc. Being able to lock the
  513|       |        // dispatch queue requires that the core thread is still active.
  514|  17.0k|        mp_dispatch_lock(mpctx->dispatch);
  515|  17.0k|        mpctx->stop_play = PT_QUIT;
  516|  17.0k|        mp_dispatch_unlock(mpctx->dispatch);
  517|       |
  518|       |        // Ask the core thread to stop.
  519|  17.0k|        mp_mutex_lock(&clients->lock);
  ------------------
  |  |  131|  17.0k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  520|  17.0k|        clients->terminate_core_thread = true;
  521|  17.0k|        mp_mutex_unlock(&clients->lock);
  ------------------
  |  |  133|  17.0k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  522|  17.0k|        mp_wakeup_core(mpctx);
  523|       |
  524|       |        // Blocking wait for all clients and core thread to terminate.
  525|  17.0k|        mp_thread_join(mpctx->core_thread);
  ------------------
  |  |  212|  17.0k|#define mp_thread_join(t)         pthread_join(t, NULL)
  ------------------
  526|       |
  527|  17.0k|        mp_destroy(mpctx);
  528|  17.0k|    }
  529|  22.2k|}
client.c:abort_async:
  405|  22.2k|{
  406|  22.2k|    mp_mutex_lock(&mpctx->abort_lock);
  ------------------
  |  |  131|  22.2k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  407|       |
  408|       |    // Destroy all => ensure any newly appearing work is aborted immediately.
  409|  22.2k|    if (ctx == NULL)
  ------------------
  |  Branch (409:9): [True: 0, False: 22.2k]
  ------------------
  410|      0|        mpctx->abort_all = true;
  411|       |
  412|  22.2k|    for (int n = 0; n < mpctx->num_abort_list; n++) {
  ------------------
  |  Branch (412:21): [True: 0, False: 22.2k]
  ------------------
  413|      0|        struct mp_abort_entry *abort = mpctx->abort_list[n];
  414|      0|        if (!ctx || (abort->client == ctx && (!type ||
  ------------------
  |  Branch (414:13): [True: 0, False: 0]
  |  Branch (414:22): [True: 0, False: 0]
  |  Branch (414:47): [True: 0, False: 0]
  ------------------
  415|      0|            (abort->client_work_type == type && abort->client_work_id == id))))
  ------------------
  |  Branch (415:14): [True: 0, False: 0]
  |  Branch (415:49): [True: 0, False: 0]
  ------------------
  416|      0|        {
  417|      0|            mp_abort_trigger_locked(mpctx, abort);
  418|      0|        }
  419|      0|    }
  420|       |
  421|  22.2k|    mp_mutex_unlock(&mpctx->abort_lock);
  ------------------
  |  |  133|  22.2k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  422|  22.2k|}
client.c:core_thread:
  590|  17.0k|{
  591|  17.0k|    struct MPContext *mpctx = p;
  592|       |
  593|  17.0k|    mp_thread_set_name("core");
  594|       |
  595|  34.1k|    while (!mpctx->initialized && mpctx->stop_play != PT_QUIT)
  ------------------
  |  Branch (595:12): [True: 22.0k, False: 12.1k]
  |  Branch (595:35): [True: 17.0k, False: 4.92k]
  ------------------
  596|  17.0k|        mp_idle(mpctx);
  597|       |
  598|  17.0k|    if (mpctx->initialized)
  ------------------
  |  Branch (598:9): [True: 12.1k, False: 4.92k]
  ------------------
  599|  12.1k|        mp_play_files(mpctx);
  600|       |
  601|       |    // This actually waits until all clients are gone before actually
  602|       |    // destroying mpctx. Actual destruction is done by whatever destroys
  603|       |    // the last mpv_handle.
  604|  17.0k|    mp_shutdown_clients(mpctx);
  605|       |
  606|  17.0k|    MP_THREAD_RETURN();
  ------------------
  |  |  209|  17.0k|#define MP_THREAD_RETURN() return NULL
  ------------------
  607|  17.0k|}
client.c:lock_core:
  383|  29.2k|{
  384|  29.2k|    mp_dispatch_lock(ctx->mpctx->dispatch);
  385|  29.2k|}
client.c:unlock_core:
  388|  29.2k|{
  389|  29.2k|    mp_dispatch_unlock(ctx->mpctx->dispatch);
  390|  29.2k|}
client.c:send_event:
  731|  28.8k|{
  732|  28.8k|    mp_mutex_lock(&ctx->lock);
  ------------------
  |  |  131|  28.8k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  733|  28.8k|    uint64_t mask = 1ULL << event->event_id;
  734|  28.8k|    if (ctx->property_event_masks & mask)
  ------------------
  |  Branch (734:9): [True: 0, False: 28.8k]
  ------------------
  735|      0|        notify_property_events(ctx, event->event_id);
  736|  28.8k|    int r;
  737|  28.8k|    if (!(ctx->event_mask & mask)) {
  ------------------
  |  Branch (737:9): [True: 20.9k, False: 7.82k]
  ------------------
  738|  20.9k|        r = 0;
  739|  20.9k|    } else if (ctx->choked) {
  ------------------
  |  Branch (739:16): [True: 140, False: 7.68k]
  ------------------
  740|    140|        r = -1;
  741|  7.68k|    } else {
  742|  7.68k|        r = append_event(ctx, *event, copy);
  743|  7.68k|        if (r < 0) {
  ------------------
  |  Branch (743:13): [True: 1, False: 7.68k]
  ------------------
  744|      1|            MP_ERR(ctx, "Too many events queued.\n");
  ------------------
  |  |   85|      1|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      1|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  745|      1|            ctx->choked = true;
  746|      1|        }
  747|  7.68k|    }
  748|  28.8k|    mp_mutex_unlock(&ctx->lock);
  ------------------
  |  |  133|  28.8k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  749|  28.8k|    return r;
  750|  28.8k|}
client.c:append_event:
  717|  7.68k|{
  718|  7.68k|    if (ctx->num_events + ctx->reserved_events >= ctx->max_events)
  ------------------
  |  Branch (718:9): [True: 1, False: 7.68k]
  ------------------
  719|      1|        return -1;
  720|  7.68k|    if (copy)
  ------------------
  |  Branch (720:9): [True: 7.68k, False: 0]
  ------------------
  721|  7.68k|        dup_event_data(&event);
  722|  7.68k|    ctx->events[(ctx->first_event + ctx->num_events) % ctx->max_events] = event;
  723|  7.68k|    ctx->num_events++;
  724|  7.68k|    wakeup_client(ctx);
  725|  7.68k|    if (event.event_id == MPV_EVENT_SHUTDOWN)
  ------------------
  |  Branch (725:9): [True: 205, False: 7.48k]
  ------------------
  726|    205|        ctx->event_mask &= ctx->event_mask & ~(1ULL << MPV_EVENT_SHUTDOWN);
  727|  7.68k|    return 0;
  728|  7.68k|}
client.c:dup_event_data:
  673|  7.68k|{
  674|  7.68k|    switch (ev->event_id) {
  675|      0|    case MPV_EVENT_CLIENT_MESSAGE: {
  ------------------
  |  Branch (675:5): [True: 0, False: 7.68k]
  ------------------
  676|      0|        struct mpv_event_client_message *src = ev->data;
  677|      0|        struct mpv_event_client_message *msg =
  678|      0|            talloc_zero(NULL, struct mpv_event_client_message);
  ------------------
  |  |   27|      0|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|      0|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  679|      0|        for (int n = 0; n < src->num_args; n++) {
  ------------------
  |  Branch (679:25): [True: 0, False: 0]
  ------------------
  680|      0|            MP_TARRAY_APPEND(msg, msg->args, msg->num_args,
  ------------------
  |  |  105|      0|    do {                                            \
  |  |  106|      0|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      0|    do {                                            \
  |  |  |  |   97|      0|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      0|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      0|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      0|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      0|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      0|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      0|        (idxvar)++;                                 \
  |  |  109|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  681|      0|                             talloc_strdup(msg, src->args[n]));
  682|      0|        }
  683|      0|        ev->data = msg;
  684|      0|        break;
  685|      0|    }
  686|  3.89k|    case MPV_EVENT_START_FILE:
  ------------------
  |  Branch (686:5): [True: 3.89k, False: 3.79k]
  ------------------
  687|  3.89k|        ev->data = talloc_memdup(NULL, ev->data, sizeof(mpv_event_start_file));
  ------------------
  |  |   49|  3.89k|#define talloc_memdup                   ta_xmemdup
  |  |  ------------------
  |  |  |  |  157|  3.89k|#define ta_xmemdup(...)         ta_dbg_set_loc(ta_xmemdup(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|  3.89k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|  3.89k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|  3.89k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  688|  3.89k|        break;
  689|  3.48k|    case MPV_EVENT_END_FILE:
  ------------------
  |  Branch (689:5): [True: 3.48k, False: 4.20k]
  ------------------
  690|  3.48k|        ev->data = talloc_memdup(NULL, ev->data, sizeof(mpv_event_end_file));
  ------------------
  |  |   49|  3.48k|#define talloc_memdup                   ta_xmemdup
  |  |  ------------------
  |  |  |  |  157|  3.48k|#define ta_xmemdup(...)         ta_dbg_set_loc(ta_xmemdup(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|  3.48k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|  3.48k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|  3.48k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  691|  3.48k|        break;
  692|    313|    default:
  ------------------
  |  Branch (692:5): [True: 313, False: 7.37k]
  ------------------
  693|       |        // Doesn't use events with memory allocation.
  694|    313|        if (ev->data)
  ------------------
  |  Branch (694:13): [True: 0, False: 313]
  ------------------
  695|      0|            abort();
  696|  7.68k|    }
  697|  7.68k|}
client.c:wakeup_client:
  344|  7.68k|{
  345|  7.68k|    mp_mutex_lock(&ctx->wakeup_lock);
  ------------------
  |  |  131|  7.68k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  346|  7.68k|    if (!ctx->need_wakeup) {
  ------------------
  |  Branch (346:9): [True: 687, False: 6.99k]
  ------------------
  347|    687|        ctx->need_wakeup = true;
  348|    687|        mp_cond_broadcast(&ctx->wakeup);
  349|    687|        if (ctx->wakeup_cb)
  ------------------
  |  Branch (349:13): [True: 0, False: 687]
  ------------------
  350|      0|            ctx->wakeup_cb(ctx->wakeup_cb_ctx);
  351|    687|        if (ctx->wakeup_pipe[0] != -1)
  ------------------
  |  Branch (351:13): [True: 213, False: 474]
  ------------------
  352|    213|            (void)write(ctx->wakeup_pipe[1], &(char){0}, 1);
  353|    687|    }
  354|  7.68k|    mp_mutex_unlock(&ctx->wakeup_lock);
  ------------------
  |  |  133|  7.68k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  355|  7.68k|}
client.c:run_client_command:
 1106|  17.4k|{
 1107|  17.4k|    if (!cmd)
  ------------------
  |  Branch (1107:9): [True: 336, False: 17.0k]
  ------------------
 1108|    336|        return MPV_ERROR_INVALID_PARAMETER;
 1109|  17.0k|    if (!ctx->mpctx->initialized) {
  ------------------
  |  Branch (1109:9): [True: 4.92k, False: 12.1k]
  ------------------
 1110|  4.92k|        talloc_free(cmd);
  ------------------
  |  |   47|  4.92k|#define talloc_free                     ta_free
  ------------------
 1111|  4.92k|        return MPV_ERROR_UNINITIALIZED;
 1112|  4.92k|    }
 1113|       |
 1114|  12.1k|    cmd->sender = ctx->name;
 1115|       |
 1116|  12.1k|    struct cmd_request req = {
 1117|  12.1k|        .mpctx = ctx->mpctx,
 1118|  12.1k|        .cmd = cmd,
 1119|  12.1k|        .res = res,
 1120|  12.1k|        .completion = MP_WAITER_INITIALIZER,
  ------------------
  |  |   19|  12.1k|#define MP_WAITER_INITIALIZER { \
  |  |   20|  12.1k|    .lock = MP_STATIC_MUTEX_INITIALIZER, \
  |  |  ------------------
  |  |  |  |  106|  12.1k|#define MP_STATIC_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
  |  |  ------------------
  |  |   21|  12.1k|    .wakeup = MP_STATIC_COND_INITIALIZER, \
  |  |  ------------------
  |  |  |  |  105|  12.1k|#define MP_STATIC_COND_INITIALIZER { .cond = PTHREAD_COND_INITIALIZER, .clk_id = CLOCK_REALTIME }
  |  |  ------------------
  |  |   22|  12.1k|    }
  ------------------
 1121|  12.1k|    };
 1122|       |
 1123|  12.1k|    bool async = cmd->flags & MP_ASYNC_CMD;
 1124|       |
 1125|  12.1k|    lock_core(ctx);
 1126|  12.1k|    if (async) {
  ------------------
  |  Branch (1126:9): [True: 0, False: 12.1k]
  ------------------
 1127|      0|        run_command(ctx->mpctx, cmd, NULL, NULL, NULL);
 1128|  12.1k|    } else {
 1129|  12.1k|        struct mp_abort_entry *abort = NULL;
 1130|  12.1k|        if (cmd->def->can_abort) {
  ------------------
  |  Branch (1130:13): [True: 0, False: 12.1k]
  ------------------
 1131|      0|            abort = talloc_zero(NULL, struct mp_abort_entry);
  ------------------
  |  |   27|      0|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|      0|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1132|      0|            abort->client = ctx;
 1133|      0|        }
 1134|  12.1k|        run_command(ctx->mpctx, cmd, abort, cmd_complete, &req);
 1135|  12.1k|    }
 1136|  12.1k|    unlock_core(ctx);
 1137|       |
 1138|  12.1k|    if (!async)
  ------------------
  |  Branch (1138:9): [True: 12.1k, False: 0]
  ------------------
 1139|  12.1k|        mp_waiter_wait(&req.completion);
 1140|       |
 1141|  12.1k|    return req.status;
 1142|  17.0k|}
client.c:cmd_complete:
 1092|  12.1k|{
 1093|  12.1k|    struct cmd_request *req = cmd->on_completion_priv;
 1094|       |
 1095|  12.1k|    req->status = cmd->success ? 0 : MPV_ERROR_COMMAND;
  ------------------
  |  Branch (1095:19): [True: 12.1k, False: 0]
  ------------------
 1096|  12.1k|    if (req->res) {
  ------------------
  |  Branch (1096:9): [True: 0, False: 12.1k]
  ------------------
 1097|      0|        *req->res = cmd->result;
 1098|      0|        cmd->result = (mpv_node){0};
 1099|      0|    }
 1100|       |
 1101|       |    // Unblock the waiting thread (especially for async commands).
 1102|  12.1k|    mp_waiter_wakeup(&req->completion, 0);
 1103|  12.1k|}
client.c:prop_unref:
  169|  22.2k|{
  170|  22.2k|    if (!prop)
  ------------------
  |  Branch (170:9): [True: 22.2k, False: 0]
  ------------------
  171|  22.2k|        return;
  172|       |
  173|      0|    mp_assert(prop->refcount > 0);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  174|      0|    prop->refcount -= 1;
  175|      0|    if (!prop->refcount)
  ------------------
  |  Branch (175:9): [True: 0, False: 0]
  ------------------
  176|      0|        talloc_free(prop);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  177|      0|}
client.c:gen_property_change_event:
 1786|  4.32k|{
 1787|  4.32k|    if (!ctx->mpctx->initialized)
  ------------------
  |  Branch (1787:9): [True: 0, False: 4.32k]
  ------------------
 1788|      0|        return false;
 1789|       |
 1790|  4.32k|    while (1) {
  ------------------
  |  Branch (1790:12): [Folded - Ignored]
  ------------------
 1791|  4.32k|        if (ctx->cur_property_index >= ctx->num_properties) {
  ------------------
  |  Branch (1791:13): [True: 4.32k, False: 0]
  ------------------
 1792|  4.32k|            ctx->new_property_events &= ctx->num_properties > 0;
 1793|  4.32k|            if (!ctx->new_property_events)
  ------------------
  |  Branch (1793:17): [True: 4.32k, False: 0]
  ------------------
 1794|  4.32k|                break;
 1795|      0|            ctx->new_property_events = false;
 1796|      0|            ctx->cur_property_index = 0;
 1797|      0|        }
 1798|       |
 1799|      0|        struct observe_property *prop = ctx->properties[ctx->cur_property_index++];
 1800|       |
 1801|      0|        if (prop->value_ts == prop->change_ts &&    // not a stale value?
  ------------------
  |  Branch (1801:13): [True: 0, False: 0]
  ------------------
 1802|      0|            prop->value_ret_ts != prop->value_ts)   // other value than last time?
  ------------------
  |  Branch (1802:13): [True: 0, False: 0]
  ------------------
 1803|      0|        {
 1804|      0|            prop->value_ret_ts = prop->value_ts;
 1805|      0|            prop->waiting_for_hook = false;
 1806|      0|            prop_unref(ctx->cur_property);
 1807|      0|            ctx->cur_property = prop;
 1808|      0|            prop->refcount += 1;
 1809|       |
 1810|      0|            if (prop->value_valid)
  ------------------
  |  Branch (1810:17): [True: 0, False: 0]
  ------------------
 1811|      0|                m_option_copy(prop->type, &prop->value_ret, &prop->value);
 1812|       |
 1813|      0|            ctx->cur_property_event = (struct mpv_event_property){
 1814|      0|                .name = prop->name,
 1815|      0|                .format = prop->value_valid ? prop->format : 0,
  ------------------
  |  Branch (1815:27): [True: 0, False: 0]
  ------------------
 1816|      0|                .data = prop->value_valid ? &prop->value_ret : NULL,
  ------------------
  |  Branch (1816:25): [True: 0, False: 0]
  ------------------
 1817|      0|            };
 1818|      0|            *ctx->cur_event = (struct mpv_event){
 1819|      0|                .event_id = MPV_EVENT_PROPERTY_CHANGE,
 1820|      0|                .reply_userdata = prop->reply_id,
 1821|      0|                .data = &ctx->cur_property_event,
 1822|      0|            };
 1823|      0|            return true;
 1824|      0|        }
 1825|      0|    }
 1826|       |
 1827|  4.32k|    return false;
 1828|  4.32k|}
client.c:gen_log_message_event:
 1908|  4.32k|{
 1909|  4.32k|    if (ctx->messages) {
  ------------------
  |  Branch (1909:9): [True: 0, False: 4.32k]
  ------------------
 1910|      0|        struct mp_log_buffer_entry *msg =
 1911|      0|            mp_msg_log_buffer_read(ctx->messages);
 1912|      0|        if (msg) {
  ------------------
  |  Branch (1912:13): [True: 0, False: 0]
  ------------------
 1913|      0|            struct mpv_event_log_message *cmsg =
 1914|      0|                talloc_ptrtype(ctx->cur_event, cmsg);
  ------------------
  |  |   34|      0|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|      0|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1915|      0|            talloc_steal(cmsg, msg);
  ------------------
  |  |   38|      0|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 1916|      0|            *cmsg = (struct mpv_event_log_message){
 1917|      0|                .prefix = msg->prefix,
 1918|      0|                .level = mp_log_levels[msg->level],
 1919|      0|                .log_level = mp_mpv_log_levels[msg->level],
 1920|      0|                .text = msg->text,
 1921|      0|            };
 1922|      0|            *ctx->cur_event = (struct mpv_event){
 1923|      0|                .event_id = MPV_EVENT_LOG_MESSAGE,
 1924|      0|                .data = cmsg,
 1925|      0|            };
 1926|      0|            return true;
 1927|      0|        }
 1928|      0|    }
 1929|  4.32k|    return false;
 1930|  4.32k|}

clipboard-vo.c:init:
   29|  12.1k|{
   30|  12.1k|    struct clipboard_vo_priv *priv = talloc_ptrtype(cl, priv);
  ------------------
  |  |   34|  12.1k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  12.1k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  12.1k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   31|  12.1k|    priv->mpctx = params->mpctx;
   32|  12.1k|    priv->log = mp_log_new(priv, cl->log, "vo"),
   33|  12.1k|    cl->priv = priv;
   34|  12.1k|    return CLIPBOARD_SUCCESS;
   35|  12.1k|}

mp_clipboard_create:
   91|  12.1k|{
   92|  12.1k|    struct clipboard_ctx *cl = talloc_ptrtype(NULL, cl);
  ------------------
  |  |   34|  12.1k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  12.1k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  12.1k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   93|  12.1k|    *cl = (struct clipboard_ctx) {
   94|  12.1k|        .log = mp_log_new(cl, global->log, "clipboard"),
   95|  12.1k|        .monitor = params->flags & CLIPBOARD_INIT_ENABLE_MONITORING,
  ------------------
  |  |   27|  12.1k|#define CLIPBOARD_INIT_ENABLE_MONITORING (1 << 0)
  ------------------
   96|  12.1k|    };
   97|       |
   98|  48.5k|    for (int n = 0; params->backends && params->backends[n].name; n++) {
  ------------------
  |  Branch (98:21): [True: 48.5k, False: 0]
  |  Branch (98:41): [True: 48.5k, False: 0]
  ------------------
   99|  48.5k|        if (!params->backends[n].enabled)
  ------------------
  |  Branch (99:13): [True: 0, False: 48.5k]
  ------------------
  100|      0|            continue;
  101|  85.0k|        for (int i = 0; i < MP_ARRAY_SIZE(clipboard_backend_list); i++) {
  ------------------
  |  |   48|  85.0k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (101:25): [True: 48.5k, False: 36.4k]
  ------------------
  102|  48.5k|            const struct clipboard_backend *backend = clipboard_backend_list[i];
  103|  48.5k|            if (strcmp(params->backends[n].name, backend->name))
  ------------------
  |  Branch (103:17): [True: 36.4k, False: 12.1k]
  ------------------
  104|  36.4k|                continue;
  105|  12.1k|            if (backend->init(cl, params) != CLIPBOARD_SUCCESS)
  ------------------
  |  Branch (105:17): [True: 0, False: 12.1k]
  ------------------
  106|      0|                break;
  107|  12.1k|            cl->backend = backend;
  108|  12.1k|            goto success;
  109|  12.1k|        }
  110|  48.5k|    }
  111|       |
  112|      0|    MP_WARN(cl, "Failed to initialize any clipboard backend.\n");
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  113|      0|    talloc_free(cl);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  114|      0|    return NULL;
  115|  12.1k|success:
  116|  12.1k|    MP_VERBOSE(cl, "Initialized %s clipboard backend.\n", cl->backend->name);
  ------------------
  |  |   88|  12.1k|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  12.1k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  117|  12.1k|    return cl;
  118|  12.1k|}
mp_clipboard_destroy:
  121|  29.2k|{
  122|  29.2k|    if (cl && cl->backend->uninit)
  ------------------
  |  Branch (122:9): [True: 12.1k, False: 17.0k]
  |  Branch (122:15): [True: 0, False: 12.1k]
  ------------------
  123|      0|        cl->backend->uninit(cl);
  124|  29.2k|    talloc_free(cl);
  ------------------
  |  |   47|  29.2k|#define talloc_free                     ta_free
  ------------------
  125|  29.2k|}
mp_clipboard_data_changed:
  128|  18.4k|{
  129|  18.4k|    if (cl && cl->backend->data_changed && cl->monitor)
  ------------------
  |  Branch (129:9): [True: 1.35k, False: 17.0k]
  |  Branch (129:15): [True: 0, False: 1.35k]
  |  Branch (129:44): [True: 0, False: 0]
  ------------------
  130|      0|        return cl->backend->data_changed(cl);
  131|  18.4k|    return false;
  132|  18.4k|}
reinit_clipboard:
  156|  12.1k|{
  157|  12.1k|    mp_clipboard_destroy(mpctx->clipboard);
  158|  12.1k|    mpctx->clipboard = NULL;
  159|       |
  160|  12.1k|    struct clipboard_opts *opts = mp_get_config_group(NULL, mpctx->global, &clipboard_conf);
  161|  12.1k|    if (opts->backends && opts->backends[0].name) {
  ------------------
  |  Branch (161:9): [True: 12.1k, False: 0]
  |  Branch (161:27): [True: 12.1k, False: 0]
  ------------------
  162|  12.1k|        struct clipboard_init_params params = {
  163|  12.1k|            .mpctx = mpctx,
  164|  12.1k|            .flags = opts->monitor ? CLIPBOARD_INIT_ENABLE_MONITORING : 0,
  ------------------
  |  |   27|      0|#define CLIPBOARD_INIT_ENABLE_MONITORING (1 << 0)
  ------------------
  |  Branch (164:22): [True: 0, False: 12.1k]
  ------------------
  165|  12.1k|            .backends = opts->backends,
  166|  12.1k|        };
  167|  12.1k|        mpctx->clipboard = mp_clipboard_create(&params, mpctx->global);
  168|  12.1k|    }
  169|  12.1k|    talloc_free(opts);
  ------------------
  |  |   47|  12.1k|#define talloc_free                     ta_free
  ------------------
  170|  12.1k|}
clipboard.c:get_desc:
   50|  34.1k|{
   51|  34.1k|    if (index >= MP_ARRAY_SIZE(clipboard_backend_list))
  ------------------
  |  |   48|  34.1k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (51:9): [True: 17.0k, False: 17.0k]
  ------------------
   52|  17.0k|        return false;
   53|  17.0k|    const struct clipboard_backend *backend = clipboard_backend_list[index];
   54|  17.0k|    *dst = (struct m_obj_desc) {
   55|  17.0k|        .name = backend->name,
   56|  17.0k|        .description = backend->desc,
   57|  17.0k|    };
   58|  17.0k|    return true;
   59|  34.1k|}

mp_hook_test_completion:
  194|  12.2k|{
  195|  12.2k|    struct command_ctx *cmd = mpctx->command_ctx;
  196|  12.2k|    for (int n = 0; n < cmd->num_hooks; n++) {
  ------------------
  |  Branch (196:21): [True: 0, False: 12.2k]
  ------------------
  197|      0|        struct hook_handler *h = cmd->hooks[n];
  198|      0|        if (h->active && strcmp(h->type, type) == 0) {
  ------------------
  |  Branch (198:13): [True: 0, False: 0]
  |  Branch (198:26): [True: 0, False: 0]
  ------------------
  199|      0|            if (!mp_client_id_exists(mpctx, h->client_id)) {
  ------------------
  |  Branch (199:17): [True: 0, False: 0]
  ------------------
  200|      0|                MP_WARN(mpctx, "client removed during hook handling\n");
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  201|       |                // Trigger completion of this hook and continue with the next one.
  202|      0|                mp_hook_continue(mpctx, h->client_id, h->seq);
  203|      0|                hook_remove(mpctx, h);
  204|      0|            }
  205|      0|            return false;
  206|      0|        }
  207|      0|    }
  208|  12.2k|    return true;
  209|  12.2k|}
mp_hook_start:
  259|  12.2k|{
  260|  12.2k|    run_next_hook_handler(mpctx, type, 0);
  261|  12.2k|}
mp_get_property_id:
 4572|    816|{
 4573|    816|    struct command_ctx *ctx = mpctx->command_ctx;
 4574|  29.5k|    for (int n = 0; ctx->properties[n].name; n++) {
  ------------------
  |  Branch (4574:21): [True: 29.5k, False: 0]
  ------------------
 4575|  29.5k|        if (match_property(ctx->properties[n].name, name))
  ------------------
  |  Branch (4575:13): [True: 816, False: 28.7k]
  ------------------
 4576|    816|            return n;
 4577|  29.5k|    }
 4578|      0|    return -1;
 4579|    816|}
mp_property_do:
 4601|    370|{
 4602|    370|    struct command_ctx *cmd = ctx->command_ctx;
 4603|    370|    int r = m_property_do(ctx->log, cmd->properties, name, action, val, ctx);
 4604|       |
 4605|    370|    if (mp_msg_test(ctx->log, MSGL_V) && is_property_set(action, val)) {
  ------------------
  |  Branch (4605:9): [True: 370, False: 0]
  |  Branch (4605:42): [True: 0, False: 370]
  ------------------
 4606|      0|        struct m_option option_type = {0};
 4607|      0|        void *data = val;
 4608|      0|        switch (action) {
  ------------------
  |  Branch (4608:17): [True: 0, False: 0]
  ------------------
 4609|      0|        case M_PROPERTY_SET_NODE:
  ------------------
  |  Branch (4609:9): [True: 0, False: 0]
  ------------------
 4610|      0|            option_type.type = &m_option_type_node;
 4611|      0|            break;
 4612|      0|        case M_PROPERTY_SET_STRING:
  ------------------
  |  Branch (4612:9): [True: 0, False: 0]
  ------------------
 4613|      0|            option_type.type = &m_option_type_string;
 4614|      0|            data = &val;
 4615|      0|            break;
 4616|      0|        }
 4617|      0|        char *t = option_type.type ? m_option_print(&option_type, data) : NULL;
  ------------------
  |  Branch (4617:19): [True: 0, False: 0]
  ------------------
 4618|      0|        MP_VERBOSE(ctx, "Set property: %s%s%s -> %d\n",
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (82:57): [True: 0, False: 0]
  |  |  |  |  |  Branch (82:57): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 4619|      0|                   name, t ? "=" : "", t ? t : "", r);
 4620|      0|        talloc_free(t);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 4621|      0|    }
 4622|    370|    return r;
 4623|    370|}
mp_property_expand_string:
 4626|  8.45k|{
 4627|  8.45k|    struct command_ctx *ctx = mpctx->command_ctx;
 4628|  8.45k|    return m_properties_expand_string(ctx->properties, str, mpctx);
 4629|  8.45k|}
mp_property_expand_escaped_string:
 4633|  8.54k|{
 4634|  8.54k|    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|  8.54k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  8.54k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
 4635|  8.54k|    bstr strb = bstr0(str);
 4636|  8.54k|    bstr dst = {0};
 4637|  10.1k|    while (strb.len) {
  ------------------
  |  Branch (4637:12): [True: 6.46k, False: 3.66k]
  ------------------
 4638|  6.46k|        if (!mp_append_escaped_string(tmp, &dst, &strb)) {
  ------------------
  |  Branch (4638:13): [True: 101, False: 6.36k]
  ------------------
 4639|    101|            talloc_free(tmp);
  ------------------
  |  |   47|    101|#define talloc_free                     ta_free
  ------------------
 4640|    101|            return talloc_strdup(NULL, "(broken escape sequences)");
  ------------------
  |  |   50|    101|#define talloc_strdup                   ta_xstrdup
  ------------------
 4641|    101|        }
 4642|       |        // pass " through literally
 4643|  6.36k|        if (!bstr_eatstart0(&strb, "\""))
  ------------------
  |  Branch (4643:13): [True: 4.77k, False: 1.59k]
  ------------------
 4644|  4.77k|            break;
 4645|  1.59k|        bstr_xappend(tmp, &dst, bstr0("\""));
 4646|  1.59k|    }
 4647|  8.44k|    char *r = mp_property_expand_string(mpctx, dst.start);
 4648|  8.44k|    talloc_free(tmp);
  ------------------
  |  |   47|  8.44k|#define talloc_free                     ta_free
  ------------------
 4649|  8.44k|    return r;
 4650|  8.54k|}
mp_cmd_ctx_complete:
 5395|  12.1k|{
 5396|  12.1k|    cmd->completed = true;
 5397|  12.1k|    if (!cmd->success)
  ------------------
  |  Branch (5397:9): [True: 0, False: 12.1k]
  ------------------
 5398|      0|        mpv_free_node_contents(&cmd->result);
 5399|  12.1k|    if (cmd->on_completion)
  ------------------
  |  Branch (5399:9): [True: 12.1k, False: 0]
  ------------------
 5400|  12.1k|        cmd->on_completion(cmd);
 5401|  12.1k|    if (cmd->abort)
  ------------------
  |  Branch (5401:9): [True: 0, False: 12.1k]
  ------------------
 5402|      0|        mp_abort_remove(cmd->mpctx, cmd->abort);
 5403|  12.1k|    mpv_free_node_contents(&cmd->result);
 5404|  12.1k|    talloc_free(cmd);
  ------------------
  |  |   47|  12.1k|#define talloc_free                     ta_free
  ------------------
 5405|  12.1k|}
run_command:
 5442|  12.1k|{
 5443|  12.1k|    struct mp_cmd_ctx *ctx = talloc(NULL, struct mp_cmd_ctx);
  ------------------
  |  |   26|  12.1k|#define talloc                          ta_xnew
  |  |  ------------------
  |  |  |  |  133|  12.1k|#define ta_xnew(...)                    ta_oom_g(ta_new(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  12.1k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5444|  12.1k|    *ctx = (struct mp_cmd_ctx){
 5445|  12.1k|        .mpctx = mpctx,
 5446|  12.1k|        .cmd = talloc_steal(ctx, cmd),
  ------------------
  |  |   38|  12.1k|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|  12.1k|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 5447|  12.1k|        .args = cmd->args,
 5448|  12.1k|        .num_args = cmd->nargs,
 5449|  12.1k|        .priv = cmd->def->priv,
 5450|  12.1k|        .abort = talloc_steal(ctx, abort),
  ------------------
  |  |   38|  12.1k|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|  12.1k|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 5451|  12.1k|        .success = true,
 5452|  12.1k|        .completed = true,
 5453|  12.1k|        .on_completion = on_completion,
 5454|  12.1k|        .on_completion_priv = on_completion_priv,
 5455|  12.1k|    };
 5456|       |
 5457|  12.1k|    if (!ctx->abort && cmd->def->can_abort)
  ------------------
  |  Branch (5457:9): [True: 12.1k, False: 0]
  |  Branch (5457:24): [True: 0, False: 12.1k]
  ------------------
 5458|      0|        ctx->abort = talloc_zero(ctx, struct mp_abort_entry);
  ------------------
  |  |   27|      0|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|      0|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 5459|       |
 5460|  12.1k|    mp_assert(cmd->def->can_abort == !!ctx->abort);
  ------------------
  |  |   41|  12.1k|#define mp_assert assert
  ------------------
 5461|       |
 5462|  12.1k|    if (ctx->abort) {
  ------------------
  |  Branch (5462:9): [True: 0, False: 12.1k]
  ------------------
 5463|      0|        ctx->abort->coupled_to_playback |= cmd->def->abort_on_playback_end;
 5464|      0|        mp_abort_add(mpctx, ctx->abort);
 5465|      0|    }
 5466|       |
 5467|  12.1k|    struct MPOpts *opts = mpctx->opts;
 5468|  12.1k|    ctx->on_osd = cmd->flags & MP_ON_OSD_FLAGS;
 5469|  12.1k|    bool auto_osd = ctx->on_osd == MP_ON_OSD_AUTO;
 5470|  12.1k|    ctx->msg_osd = auto_osd || (ctx->on_osd & MP_ON_OSD_MSG);
  ------------------
  |  Branch (5470:20): [True: 0, False: 12.1k]
  |  Branch (5470:32): [True: 0, False: 12.1k]
  ------------------
 5471|  12.1k|    ctx->bar_osd = auto_osd || (ctx->on_osd & MP_ON_OSD_BAR);
  ------------------
  |  Branch (5471:20): [True: 0, False: 12.1k]
  |  Branch (5471:32): [True: 0, False: 12.1k]
  ------------------
 5472|  12.1k|    ctx->seek_msg_osd = auto_osd ? opts->osd_on_seek & 2 : ctx->msg_osd;
  ------------------
  |  Branch (5472:25): [True: 0, False: 12.1k]
  ------------------
 5473|  12.1k|    ctx->seek_bar_osd = auto_osd ? opts->osd_on_seek & 1 : ctx->bar_osd;
  ------------------
  |  Branch (5473:25): [True: 0, False: 12.1k]
  ------------------
 5474|       |
 5475|  12.1k|    bool noise = cmd->def->is_noisy || cmd->mouse_move;
  ------------------
  |  Branch (5475:18): [True: 0, False: 12.1k]
  |  Branch (5475:40): [True: 0, False: 12.1k]
  ------------------
 5476|  12.1k|    mp_cmd_dump(mpctx->log, noise ? MSGL_TRACE : MSGL_DEBUG, "Run command:", cmd);
  ------------------
  |  Branch (5476:29): [True: 0, False: 12.1k]
  ------------------
 5477|       |
 5478|  12.1k|    if (cmd->flags & MP_EXPAND_PROPERTIES) {
  ------------------
  |  Branch (5478:9): [True: 0, False: 12.1k]
  ------------------
 5479|      0|        for (int n = 0; n < cmd->nargs; n++) {
  ------------------
  |  Branch (5479:25): [True: 0, False: 0]
  ------------------
 5480|      0|            if (cmd->args[n].type->type == CONF_TYPE_STRING) {
  ------------------
  |  |  233|      0|#define CONF_TYPE_STRING        (&m_option_type_string)
  ------------------
  |  Branch (5480:17): [True: 0, False: 0]
  ------------------
 5481|      0|                char *s = mp_property_expand_string(mpctx, cmd->args[n].v.s);
 5482|      0|                if (!s) {
  ------------------
  |  Branch (5482:21): [True: 0, False: 0]
  ------------------
 5483|      0|                    ctx->success = false;
 5484|      0|                    mp_cmd_ctx_complete(ctx);
 5485|      0|                    return;
 5486|      0|                }
 5487|      0|                talloc_free(cmd->args[n].v.s);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 5488|      0|                cmd->args[n].v.s = s;
 5489|      0|            }
 5490|      0|        }
 5491|      0|    }
 5492|       |
 5493|  12.1k|    if (cmd->def->spawn_thread) {
  ------------------
  |  Branch (5493:9): [True: 0, False: 12.1k]
  ------------------
 5494|      0|        mpctx->outstanding_async += 1; // prevent that core disappears
 5495|      0|        if (!mp_thread_pool_queue(mpctx->thread_pool,
  ------------------
  |  Branch (5495:13): [True: 0, False: 0]
  ------------------
 5496|      0|                                  run_command_on_worker_thread, ctx))
 5497|      0|        {
 5498|      0|            mpctx->outstanding_async -= 1;
 5499|      0|            ctx->success = false;
 5500|      0|            mp_cmd_ctx_complete(ctx);
 5501|      0|        }
 5502|  12.1k|    } else {
 5503|  12.1k|        bool exec_async = cmd->def->exec_async;
 5504|  12.1k|        cmd->def->handler(ctx);
 5505|  12.1k|        if (!exec_async)
  ------------------
  |  Branch (5505:13): [True: 12.1k, False: 0]
  ------------------
 5506|  12.1k|            mp_cmd_ctx_complete(ctx);
 5507|  12.1k|    }
 5508|  12.1k|}
mp_abort_cache_dumping:
 6926|  3.93k|{
 6927|  3.93k|    struct command_ctx *ctx = mpctx->command_ctx;
 6928|       |
 6929|  3.93k|    if (ctx->cache_dump_cmd)
  ------------------
  |  Branch (6929:9): [True: 0, False: 3.93k]
  ------------------
 6930|      0|        mp_cancel_trigger(ctx->cache_dump_cmd->abort->cancel);
 6931|  3.93k|    cache_dump_poll(mpctx);
 6932|  3.93k|    mp_assert(!ctx->cache_dump_cmd); // synchronous abort, must have worked
  ------------------
  |  |   41|  3.93k|#define mp_assert assert
  ------------------
 6933|  3.93k|}
command_uninit:
 7543|  17.0k|{
 7544|  17.0k|    struct command_ctx *ctx = mpctx->command_ctx;
 7545|       |
 7546|  17.0k|    mp_assert(!ctx->cache_dump_cmd); // closing the demuxer must have aborted it
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
 7547|       |
 7548|  17.0k|    overlay_uninit(mpctx);
 7549|  17.0k|    ao_hotplug_destroy(ctx->hotplug);
 7550|       |
 7551|  17.0k|    m_option_free(&script_props_type, &ctx->script_props);
 7552|       |
 7553|  17.0k|    talloc_free(mpctx->command_ctx);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
 7554|  17.0k|    mpctx->command_ctx = NULL;
 7555|  17.0k|}
command_init:
 7563|  17.0k|{
 7564|  17.0k|    struct command_ctx *ctx = talloc(NULL, struct command_ctx);
  ------------------
  |  |   26|  17.0k|#define talloc                          ta_xnew
  |  |  ------------------
  |  |  |  |  133|  17.0k|#define ta_xnew(...)                    ta_oom_g(ta_new(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 7565|  17.0k|    *ctx = (struct command_ctx){
 7566|  17.0k|        .last_seek_pts = MP_NOPTS_VALUE,
  ------------------
  |  |   38|  17.0k|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
 7567|  17.0k|    };
 7568|  17.0k|    mpctx->command_ctx = ctx;
 7569|       |
 7570|  17.0k|    int num_base = MP_ARRAY_SIZE(mp_properties_base);
  ------------------
  |  |   48|  17.0k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
 7571|  17.0k|    int num_opts = m_config_get_co_count(mpctx->mconfig);
 7572|  17.0k|    ctx->properties =
 7573|  17.0k|        talloc_zero_array(ctx, struct m_property, num_base + num_opts + 1);
  ------------------
  |  |   30|  17.0k|#define talloc_zero_array               ta_xznew_array
  |  |  ------------------
  |  |  |  |  136|  17.0k|#define ta_xznew_array(...)             ta_oom_g(ta_znew_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 7574|  17.0k|    memcpy(ctx->properties, mp_properties_base, sizeof(mp_properties_base));
 7575|       |
 7576|  17.0k|    const char **prop_names = talloc_array(NULL, const char *, num_base);
  ------------------
  |  |   29|  17.0k|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|  17.0k|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 7577|  3.15M|    for (int i = 0; i < num_base; ++i)
  ------------------
  |  Branch (7577:21): [True: 3.14M, False: 17.0k]
  ------------------
 7578|  3.14M|        prop_names[i] = mp_properties_base[i].name;
 7579|  17.0k|    qsort(prop_names, num_base, sizeof(const char *), str_compare);
 7580|       |
 7581|  17.0k|    int count = num_base;
 7582|  12.7M|    for (int n = 0; n < num_opts; n++) {
  ------------------
  |  Branch (7582:21): [True: 12.7M, False: 17.0k]
  ------------------
 7583|  12.7M|        struct m_config_option *co = m_config_get_co_index(mpctx->mconfig, n);
 7584|  12.7M|        mp_assert(co->name[0]);
  ------------------
  |  |   41|  12.7M|#define mp_assert assert
  ------------------
 7585|  12.7M|        if (co->opt->flags & M_OPT_NOPROP)
  ------------------
  |  |  465|  12.7M|#define M_OPT_NOPROP            (UINT64_C(1) << 60)
  ------------------
  |  Branch (7585:13): [True: 477k, False: 12.2M]
  ------------------
 7586|   477k|            continue;
 7587|       |
 7588|  12.2M|        struct m_property prop = {
 7589|  12.2M|            .name = co->name,
 7590|  12.2M|            .call = mp_property_generic_option,
 7591|  12.2M|            .is_option = true,
 7592|  12.2M|        };
 7593|       |
 7594|  12.2M|        if (co->opt->type == &m_option_type_alias) {
  ------------------
  |  Branch (7594:13): [True: 392k, False: 11.8M]
  ------------------
 7595|   392k|            char buf[M_CONFIG_MAX_OPT_NAME_LEN];
 7596|   392k|            const char *alias = m_config_shadow_get_alias_from_opt(mpctx->mconfig->shadow, co->opt_id,
 7597|   392k|                                                                   buf, sizeof(buf));
 7598|   392k|            prop.priv = talloc_strdup(ctx, alias);
  ------------------
  |  |   50|   392k|#define talloc_strdup                   ta_xstrdup
  ------------------
 7599|       |
 7600|   392k|            prop.call = co->opt->deprecation_message ?
  ------------------
  |  Branch (7600:25): [True: 119k, False: 273k]
  ------------------
 7601|   273k|                            mp_property_deprecated_alias : mp_property_alias;
 7602|       |
 7603|       |            // Check whether this eventually arrives at a real option. If not,
 7604|       |            // it's some CLI special handling thing. For example, "nosound" is
 7605|       |            // mapped to "no-audio", which has CLI special-handling, and cannot
 7606|       |            // be set as property.
 7607|   392k|            struct m_config_option *co2 = co;
 7608|   785k|            while (co2 && co2->opt->type == &m_option_type_alias) {
  ------------------
  |  Branch (7608:20): [True: 785k, False: 0]
  |  Branch (7608:27): [True: 392k, False: 392k]
  ------------------
 7609|   392k|                const char *co2_alias = m_config_shadow_get_alias_from_opt(mpctx->mconfig->shadow, co2->opt_id,
 7610|   392k|                                                                           buf, sizeof(buf));
 7611|   392k|                co2 = m_config_get_co_raw(mpctx->mconfig, bstr0(co2_alias));
 7612|   392k|            }
 7613|   392k|            if (!co2)
  ------------------
  |  Branch (7613:17): [True: 0, False: 392k]
  ------------------
 7614|      0|                continue;
 7615|   392k|        }
 7616|       |
 7617|       |        // The option might be covered by a manual property already.
 7618|  12.2M|        if (bsearch(&prop.name, prop_names, num_base, sizeof(const char *), str_compare))
  ------------------
  |  Branch (7618:13): [True: 409k, False: 11.8M]
  ------------------
 7619|   409k|            continue;
 7620|       |
 7621|  11.8M|        ctx->properties[count++] = prop;
 7622|  11.8M|    }
 7623|       |
 7624|  17.0k|    node_init(&ctx->mdata, MPV_FORMAT_NODE_ARRAY, NULL);
 7625|  17.0k|    talloc_steal(ctx, ctx->mdata.u.list);
  ------------------
  |  |   38|  17.0k|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|  17.0k|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 7626|       |
 7627|  17.0k|    node_init(&ctx->udata, MPV_FORMAT_NODE_MAP, NULL);
 7628|  17.0k|    talloc_steal(ctx, ctx->udata.u.list);
  ------------------
  |  |   38|  17.0k|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|  17.0k|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 7629|  17.0k|    talloc_free(prop_names);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
 7630|  17.0k|}
handle_command_updates:
 7678|  18.4k|{
 7679|  18.4k|    struct command_ctx *ctx = mpctx->command_ctx;
 7680|       |
 7681|       |    // This is a bit messy: ao_hotplug wakes up the player, and then we have
 7682|       |    // to recheck the state. Then the client(s) will read the property.
 7683|  18.4k|    if (ctx->hotplug && ao_hotplug_check_update(ctx->hotplug))
  ------------------
  |  Branch (7683:9): [True: 3, False: 18.4k]
  |  Branch (7683:25): [True: 0, False: 3]
  ------------------
 7684|      0|        mp_notify_property(mpctx, "audio-device-list");
 7685|       |
 7686|       |    // Depends on polling demuxer wakeup callback notifications.
 7687|  18.4k|    cache_dump_poll(mpctx);
 7688|  18.4k|}
run_command_opts:
 7691|     69|{
 7692|     69|    struct MPOpts *opts = mpctx->opts;
 7693|     69|    struct command_ctx *ctx = mpctx->command_ctx;
 7694|       |
 7695|     69|    if (!opts->input_commands || ctx->command_opts_processed)
  ------------------
  |  Branch (7695:9): [True: 69, False: 0]
  |  Branch (7695:34): [True: 0, False: 0]
  ------------------
 7696|     69|        return;
 7697|       |
 7698|       |    // Take easy way out and add these to the input queue.
 7699|      0|    for (int i = 0; opts->input_commands[i]; i++) {
  ------------------
  |  Branch (7699:21): [True: 0, False: 0]
  ------------------
 7700|      0|        struct mp_cmd *cmd = mp_input_parse_cmd(mpctx->input, bstr0(opts->input_commands[i]),
 7701|      0|                                                "the command line");
 7702|      0|        cmd->coalesce = true;
 7703|      0|        mp_input_queue_cmd(mpctx->input, cmd);
 7704|      0|    }
 7705|      0|    ctx->command_opts_processed = true;
 7706|      0|}
mp_notify:
 7709|  29.0k|{
 7710|       |    // The OSD can implicitly reference some properties.
 7711|  29.0k|    mpctx->osd_idle_update = true;
 7712|       |
 7713|  29.0k|    command_event(mpctx, event, arg);
 7714|       |
 7715|  29.0k|    mp_client_broadcast_event(mpctx, event, arg);
 7716|  29.0k|}
mp_option_change_callback:
 7748|  12.1k|{
 7749|  12.1k|    struct MPContext *mpctx = ctx;
 7750|  12.1k|    struct MPOpts *opts = mpctx->opts;
 7751|  12.1k|    void *opt_ptr = !co ? NULL : co->data; // NULL on start
  ------------------
  |  Branch (7751:21): [True: 12.1k, False: 6]
  ------------------
 7752|       |
 7753|  12.1k|    if (co)
  ------------------
  |  Branch (7753:9): [True: 6, False: 12.1k]
  ------------------
 7754|      6|        mp_notify_property(mpctx, co->name);
 7755|  12.1k|    if (opt_ptr == &opts->media_title)
  ------------------
  |  Branch (7755:9): [True: 0, False: 12.1k]
  ------------------
 7756|      0|        mp_notify(mpctx, MP_EVENT_METADATA_UPDATE, NULL);
 7757|       |
 7758|  12.1k|    if (self_update)
  ------------------
  |  Branch (7758:9): [True: 6, False: 12.1k]
  ------------------
 7759|      6|        return;
 7760|       |
 7761|       |    // Run these immediately.
 7762|  12.1k|    if (co && !co->coalesce) {
  ------------------
  |  Branch (7762:9): [True: 0, False: 12.1k]
  |  Branch (7762:15): [True: 0, False: 0]
  ------------------
 7763|      0|        struct mp_option_callback callback = {.co = co, .flags = flags};
 7764|      0|        mp_option_run_callback(mpctx, &callback);
 7765|      0|        return;
 7766|      0|    }
 7767|       |
 7768|       |    // Coalesce redundant updates and only keep the newest one.
 7769|  12.1k|    bool drop = false;
 7770|  12.1k|    for (int i = 0; i < mpctx->num_option_callbacks; i++) {
  ------------------
  |  Branch (7770:21): [True: 0, False: 12.1k]
  ------------------
 7771|      0|        if ((mpctx->option_callbacks[i].co && opt_ptr == mpctx->option_callbacks[i].co->data) ||
  ------------------
  |  Branch (7771:14): [True: 0, False: 0]
  |  Branch (7771:47): [True: 0, False: 0]
  ------------------
 7772|      0|            (flags && flags == mpctx->option_callbacks[i].flags))
  ------------------
  |  Branch (7772:14): [True: 0, False: 0]
  |  Branch (7772:23): [True: 0, False: 0]
  ------------------
 7773|      0|            drop = true;
 7774|      0|        if (!drop)
  ------------------
  |  Branch (7774:13): [True: 0, False: 0]
  ------------------
 7775|      0|            continue;
 7776|      0|        if (i < mpctx->num_option_callbacks - 1)
  ------------------
  |  Branch (7776:13): [True: 0, False: 0]
  ------------------
 7777|      0|            mpctx->option_callbacks[i] = mpctx->option_callbacks[i + 1];
 7778|      0|        if (i == mpctx->num_option_callbacks - 1) {
  ------------------
  |  Branch (7778:13): [True: 0, False: 0]
  ------------------
 7779|      0|            mpctx->option_callbacks[i].co = co;
 7780|      0|            mpctx->option_callbacks[i].flags = flags;
 7781|      0|        }
 7782|      0|    }
 7783|       |
 7784|  12.1k|    if (!drop) {
  ------------------
  |  Branch (7784:9): [True: 12.1k, False: 0]
  ------------------
 7785|  12.1k|        struct mp_option_callback callback = {.co = co, .flags = flags};
 7786|  12.1k|        MP_TARRAY_APPEND(mpctx, mpctx->option_callbacks, mpctx->num_option_callbacks, callback);
  ------------------
  |  |  105|  12.1k|    do {                                            \
  |  |  106|  12.1k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  12.1k|    do {                                            \
  |  |  |  |   97|  12.1k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  12.1k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  12.1k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  12.1k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 12.1k, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|  12.1k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  12.1k|    do {                                                        \
  |  |  |  |  |  |   89|  12.1k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  12.1k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  12.1k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  12.1k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  12.1k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  12.1k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  12.1k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  12.1k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  12.1k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  12.1k|        (idxvar)++;                                 \
  |  |  109|  12.1k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 7787|  12.1k|    }
 7788|  12.1k|}
mp_option_run_callback:
 7791|  12.1k|{
 7792|  12.1k|    struct MPOpts *opts = mpctx->opts;
 7793|  12.1k|    struct m_config_option *co = callback->co;
 7794|  12.1k|    void *opt_ptr = co ? co->data : NULL;
  ------------------
  |  Branch (7794:21): [True: 0, False: 12.1k]
  ------------------
 7795|  12.1k|    uint64_t flags = callback->flags;
 7796|       |
 7797|  12.1k|    if (flags & UPDATE_TERM)
  ------------------
  |  |  429|  12.1k|#define UPDATE_TERM             (UINT64_C(1) << 0)   // terminal options
  ------------------
  |  Branch (7797:9): [True: 12.1k, False: 0]
  ------------------
 7798|  12.1k|        mp_update_logging(mpctx, false);
 7799|       |
 7800|  12.1k|    if (flags & (UPDATE_OSD | UPDATE_SUB_FILT | UPDATE_SUB_HARD)) {
  ------------------
  |  |  431|  12.1k|#define UPDATE_OSD              (UINT64_C(1) << 2)   // related to OSD rendering
  ------------------
                  if (flags & (UPDATE_OSD | UPDATE_SUB_FILT | UPDATE_SUB_HARD)) {
  ------------------
  |  |  430|  12.1k|#define UPDATE_SUB_FILT         (UINT64_C(1) << 1)   // subtitle filter options
  ------------------
                  if (flags & (UPDATE_OSD | UPDATE_SUB_FILT | UPDATE_SUB_HARD)) {
  ------------------
  |  |  442|  12.1k|#define UPDATE_SUB_HARD         (UINT64_C(1) << 13)  // subtitle opts. that need full reinit
  ------------------
  |  Branch (7800:9): [True: 12.1k, False: 0]
  ------------------
 7801|  36.4k|        for (int n = 0; n < num_ptracks[STREAM_SUB]; n++) {
  ------------------
  |  Branch (7801:25): [True: 24.2k, False: 12.1k]
  ------------------
 7802|  24.2k|            struct track *track = mpctx->current_track[n][STREAM_SUB];
 7803|  24.2k|            struct dec_sub *sub = track ? track->d_sub : NULL;
  ------------------
  |  Branch (7803:35): [True: 0, False: 24.2k]
  ------------------
 7804|  24.2k|            if (sub) {
  ------------------
  |  Branch (7804:17): [True: 0, False: 24.2k]
  ------------------
 7805|      0|                int ret = sub_control(sub, SD_CTRL_UPDATE_OPTS, &flags);
 7806|      0|                if (ret == CONTROL_OK && flags & (UPDATE_SUB_FILT | UPDATE_SUB_HARD)) {
  ------------------
  |  |   68|      0|#define CONTROL_OK 1
  ------------------
                              if (ret == CONTROL_OK && flags & (UPDATE_SUB_FILT | UPDATE_SUB_HARD)) {
  ------------------
  |  |  430|      0|#define UPDATE_SUB_FILT         (UINT64_C(1) << 1)   // subtitle filter options
  ------------------
                              if (ret == CONTROL_OK && flags & (UPDATE_SUB_FILT | UPDATE_SUB_HARD)) {
  ------------------
  |  |  442|      0|#define UPDATE_SUB_HARD         (UINT64_C(1) << 13)  // subtitle opts. that need full reinit
  ------------------
  |  Branch (7806:21): [True: 0, False: 0]
  |  Branch (7806:42): [True: 0, False: 0]
  ------------------
 7807|      0|                    sub_redecode_cached_packets(sub);
 7808|      0|                    sub_reset(sub);
 7809|      0|                    if (track->selected)
  ------------------
  |  Branch (7809:25): [True: 0, False: 0]
  ------------------
 7810|      0|                        reselect_demux_stream(mpctx, track, true);
 7811|      0|                }
 7812|      0|            }
 7813|  24.2k|        }
 7814|       |        // For subs on a still image.
 7815|  12.1k|        redraw_subs(mpctx);
 7816|  12.1k|        osd_changed(mpctx->osd);
 7817|  12.1k|    }
 7818|       |
 7819|  12.1k|    if (flags & UPDATE_BUILTIN_SCRIPTS)
  ------------------
  |  |  432|  12.1k|#define UPDATE_BUILTIN_SCRIPTS  (UINT64_C(1) << 3)   // osc/ytdl/stats
  ------------------
  |  Branch (7819:9): [True: 12.1k, False: 0]
  ------------------
 7820|  12.1k|        mp_load_builtin_scripts(mpctx);
 7821|       |
 7822|  12.1k|    if (flags & UPDATE_IMGPAR) {
  ------------------
  |  |  433|  12.1k|#define UPDATE_IMGPAR           (UINT64_C(1) << 4)   // video image params overrides
  ------------------
  |  Branch (7822:9): [True: 12.1k, False: 0]
  ------------------
 7823|  12.1k|        struct track *track = mpctx->current_track[0][STREAM_VIDEO];
 7824|  12.1k|        if (track && track->dec) {
  ------------------
  |  Branch (7824:13): [True: 0, False: 12.1k]
  |  Branch (7824:22): [True: 0, False: 0]
  ------------------
 7825|      0|            mp_decoder_wrapper_reset_params(track->dec);
 7826|      0|            mp_force_video_refresh(mpctx);
 7827|      0|        }
 7828|  12.1k|    }
 7829|       |
 7830|  12.1k|    if (flags & UPDATE_INPUT)
  ------------------
  |  |  434|  12.1k|#define UPDATE_INPUT            (UINT64_C(1) << 5)   // mostly --input-* options
  ------------------
  |  Branch (7830:9): [True: 12.1k, False: 0]
  ------------------
 7831|  12.1k|        mp_input_update_opts(mpctx->input);
 7832|       |
 7833|  12.1k|    if (flags & UPDATE_CLIPBOARD)
  ------------------
  |  |  446|  12.1k|#define UPDATE_CLIPBOARD        (UINT64_C(1) << 17)  // reinit the clipboard
  ------------------
  |  Branch (7833:9): [True: 12.1k, False: 0]
  ------------------
 7834|  12.1k|        reinit_clipboard(mpctx);
 7835|       |
 7836|  12.1k|    if (flags & UPDATE_SUB_EXTS)
  ------------------
  |  |  443|  12.1k|#define UPDATE_SUB_EXTS         (UINT64_C(1) << 14)  // update internal list of sub exts
  ------------------
  |  Branch (7836:9): [True: 12.1k, False: 0]
  ------------------
 7837|  12.1k|        mp_update_subtitle_exts(mpctx->opts);
 7838|       |
 7839|  12.1k|    if (opt_ptr == &opts->ipc_path || opt_ptr == &opts->ipc_client) {
  ------------------
  |  Branch (7839:9): [True: 0, False: 12.1k]
  |  Branch (7839:39): [True: 0, False: 12.1k]
  ------------------
 7840|      0|        mp_uninit_ipc(mpctx->ipc_ctx);
 7841|      0|        mpctx->ipc_ctx = mp_init_ipc(mpctx->clients, mpctx->global);
 7842|      0|    }
 7843|       |
 7844|  12.1k|    if (flags & UPDATE_VO && mpctx->video_out) {
  ------------------
  |  |  445|  24.2k|#define UPDATE_VO               (UINT64_C(1) << 16)  // reinit the VO
  ------------------
  |  Branch (7844:9): [True: 12.1k, False: 0]
  |  Branch (7844:30): [True: 0, False: 12.1k]
  ------------------
 7845|      0|        struct track *track = mpctx->current_track[0][STREAM_VIDEO];
 7846|      0|        uninit_video_out(mpctx);
 7847|      0|        handle_force_window(mpctx, true);
 7848|      0|        reinit_video_chain(mpctx);
 7849|      0|        if (track)
  ------------------
  |  Branch (7849:13): [True: 0, False: 0]
  ------------------
 7850|      0|            queue_seek(mpctx, MPSEEK_RELATIVE, 0.0, MPSEEK_EXACT, 0);
 7851|       |
 7852|      0|        mp_wakeup_core(mpctx);
 7853|      0|    }
 7854|       |
 7855|  12.1k|    if (flags & UPDATE_AUDIO)
  ------------------
  |  |  435|  12.1k|#define UPDATE_AUDIO            (UINT64_C(1) << 6)   // --audio-channels etc.
  ------------------
  |  Branch (7855:9): [True: 12.1k, False: 0]
  ------------------
 7856|  12.1k|        reload_audio_output(mpctx);
 7857|       |
 7858|  12.1k|    if (flags & UPDATE_PRIORITY)
  ------------------
  |  |  436|  12.1k|#define UPDATE_PRIORITY         (UINT64_C(1) << 7)   // --priority (Windows-only)
  ------------------
  |  Branch (7858:9): [True: 12.1k, False: 0]
  ------------------
 7859|  12.1k|        update_priority(mpctx);
 7860|       |
 7861|  12.1k|    if (flags & UPDATE_SCREENSAVER)
  ------------------
  |  |  437|  12.1k|#define UPDATE_SCREENSAVER      (UINT64_C(1) << 8)   // --stop-screensaver
  ------------------
  |  Branch (7861:9): [True: 12.1k, False: 0]
  ------------------
 7862|  12.1k|        update_screensaver_state(mpctx);
 7863|       |
 7864|  12.1k|    if (flags & UPDATE_VOL)
  ------------------
  |  |  438|  12.1k|#define UPDATE_VOL              (UINT64_C(1) << 9)   // softvol related options
  ------------------
  |  Branch (7864:9): [True: 12.1k, False: 0]
  ------------------
 7865|  12.1k|        audio_update_volume(mpctx);
 7866|       |
 7867|  12.1k|    if (flags & UPDATE_LAVFI_COMPLEX)
  ------------------
  |  |  439|  12.1k|#define UPDATE_LAVFI_COMPLEX    (UINT64_C(1) << 10)  // --lavfi-complex
  ------------------
  |  Branch (7867:9): [True: 12.1k, False: 0]
  ------------------
 7868|  12.1k|        update_lavfi_complex(mpctx);
 7869|       |
 7870|  12.1k|    if (flags & UPDATE_VIDEO) {
  ------------------
  |  |  444|  12.1k|#define UPDATE_VIDEO            (UINT64_C(1) << 15)  // force redraw if needed
  ------------------
  |  Branch (7870:9): [True: 12.1k, False: 0]
  ------------------
 7871|  12.1k|        if (mpctx->video_out) {
  ------------------
  |  Branch (7871:13): [True: 0, False: 12.1k]
  ------------------
 7872|      0|            vo_control(mpctx->video_out, VOCTRL_UPDATE_RENDER_OPTS, NULL);
 7873|      0|            mp_wakeup_core(mpctx);
 7874|      0|        }
 7875|  12.1k|    }
 7876|       |
 7877|  12.1k|    if (flags & UPDATE_HWDEC) {
  ------------------
  |  |  440|  12.1k|#define UPDATE_HWDEC            (UINT64_C(1) << 11)  // --hwdec
  ------------------
  |  Branch (7877:9): [True: 12.1k, False: 0]
  ------------------
 7878|  12.1k|        struct track *track = mpctx->current_track[0][STREAM_VIDEO];
 7879|  12.1k|        struct mp_decoder_wrapper *dec = track ? track->dec : NULL;
  ------------------
  |  Branch (7879:42): [True: 0, False: 12.1k]
  ------------------
 7880|  12.1k|        if (dec) {
  ------------------
  |  Branch (7880:13): [True: 0, False: 12.1k]
  ------------------
 7881|      0|            mp_decoder_wrapper_control(dec, VDCTRL_REINIT, NULL);
 7882|      0|            double last_pts = mpctx->video_pts;
 7883|      0|            if (last_pts != MP_NOPTS_VALUE)
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (7883:17): [True: 0, False: 0]
  ------------------
 7884|      0|                queue_seek(mpctx, MPSEEK_ABSOLUTE, last_pts, MPSEEK_EXACT, 0);
 7885|      0|        }
 7886|  12.1k|    }
 7887|       |
 7888|  12.1k|    if (flags & UPDATE_DVB_PROG) {
  ------------------
  |  |  441|  12.1k|#define UPDATE_DVB_PROG         (UINT64_C(1) << 12)  // some --dvbin-...
  ------------------
  |  Branch (7888:9): [True: 12.1k, False: 0]
  ------------------
 7889|  12.1k|        if (!mpctx->stop_play)
  ------------------
  |  Branch (7889:13): [True: 0, False: 12.1k]
  ------------------
 7890|      0|            mpctx->stop_play = PT_CURRENT_ENTRY;
 7891|  12.1k|    }
 7892|       |
 7893|  12.1k|    if (flags & UPDATE_DEMUXER)
  ------------------
  |  |  447|  12.1k|#define UPDATE_DEMUXER          (UINT64_C(1) << 18)  // invalidate --prefetch-playlist's data
  ------------------
  |  Branch (7893:9): [True: 12.1k, False: 0]
  ------------------
 7894|  12.1k|        mpctx->demuxer_changed = true;
 7895|       |
 7896|  12.1k|    if (flags & UPDATE_AD && mpctx->ao_chain) {
  ------------------
  |  |  448|  24.2k|#define UPDATE_AD               (UINT64_C(1) << 19)  // reinit audio chain and decoder
  ------------------
  |  Branch (7896:9): [True: 12.1k, False: 0]
  |  Branch (7896:30): [True: 0, False: 12.1k]
  ------------------
 7897|      0|        uninit_audio_chain(mpctx);
 7898|      0|        reinit_audio_chain(mpctx);
 7899|      0|    }
 7900|       |
 7901|  12.1k|    if (flags & UPDATE_VD && mpctx->vo_chain) {
  ------------------
  |  |  449|  24.2k|#define UPDATE_VD               (UINT64_C(1) << 20)  // reinit video chain and decoder
  ------------------
  |  Branch (7901:9): [True: 12.1k, False: 0]
  |  Branch (7901:30): [True: 0, False: 12.1k]
  ------------------
 7902|      0|        struct track *track = mpctx->current_track[0][STREAM_VIDEO];
 7903|      0|        uninit_video_chain(mpctx);
 7904|      0|        reinit_video_chain(mpctx);
 7905|      0|        if (track)
  ------------------
  |  Branch (7905:13): [True: 0, False: 0]
  ------------------
 7906|      0|            queue_seek(mpctx, MPSEEK_RELATIVE, 0.0, MPSEEK_EXACT, 0);
 7907|      0|    }
 7908|       |
 7909|  12.1k|    if (opt_ptr == &opts->vo->android_surface_size) {
  ------------------
  |  Branch (7909:9): [True: 0, False: 12.1k]
  ------------------
 7910|      0|        if (mpctx->video_out)
  ------------------
  |  Branch (7910:13): [True: 0, False: 0]
  ------------------
 7911|      0|            vo_control(mpctx->video_out, VOCTRL_EXTERNAL_RESIZE, NULL);
 7912|      0|    }
 7913|       |
 7914|  12.1k|    if (opt_ptr == &opts->input_commands) {
  ------------------
  |  Branch (7914:9): [True: 0, False: 12.1k]
  ------------------
 7915|      0|        mpctx->command_ctx->command_opts_processed = false;
 7916|      0|        run_command_opts(mpctx);
 7917|      0|    }
 7918|       |
 7919|  12.1k|    if (opt_ptr == &opts->playback_speed || opt_ptr == &opts->playback_pitch) {
  ------------------
  |  Branch (7919:9): [True: 0, False: 12.1k]
  |  Branch (7919:45): [True: 0, False: 12.1k]
  ------------------
 7920|      0|        update_playback_speed(mpctx);
 7921|      0|        mp_wakeup_core(mpctx);
 7922|      0|    }
 7923|       |
 7924|  12.1k|    if (opt_ptr == &opts->play_dir) {
  ------------------
  |  Branch (7924:9): [True: 0, False: 12.1k]
  ------------------
 7925|      0|        if (mpctx->play_dir != opts->play_dir) {
  ------------------
  |  Branch (7925:13): [True: 0, False: 0]
  ------------------
 7926|       |            // The option must be set before we seek if we're at EOF.
 7927|      0|            if (mpctx->stop_play == AT_END_OF_FILE)
  ------------------
  |  Branch (7927:17): [True: 0, False: 0]
  ------------------
 7928|      0|                mpctx->play_dir = opts->play_dir;
 7929|      0|            queue_seek(mpctx, MPSEEK_ABSOLUTE, get_current_time(mpctx),
 7930|      0|                       MPSEEK_EXACT, 0);
 7931|      0|        }
 7932|      0|    }
 7933|       |
 7934|  12.1k|    if (opt_ptr == &opts->edition_id) {
  ------------------
  |  Branch (7934:9): [True: 0, False: 12.1k]
  ------------------
 7935|      0|        struct demuxer *demuxer = mpctx->demuxer;
 7936|      0|        if (mpctx->playback_initialized && demuxer && demuxer->num_editions > 0) {
  ------------------
  |  Branch (7936:13): [True: 0, False: 0]
  |  Branch (7936:44): [True: 0, False: 0]
  |  Branch (7936:55): [True: 0, False: 0]
  ------------------
 7937|      0|            if (opts->edition_id != demuxer->edition) {
  ------------------
  |  Branch (7937:17): [True: 0, False: 0]
  ------------------
 7938|      0|                if (!mpctx->stop_play)
  ------------------
  |  Branch (7938:21): [True: 0, False: 0]
  ------------------
 7939|      0|                    mpctx->stop_play = PT_CURRENT_ENTRY;
 7940|      0|                mp_wakeup_core(mpctx);
 7941|      0|            }
 7942|      0|        }
 7943|      0|    }
 7944|       |
 7945|  12.1k|    if (opt_ptr == &opts->pause)
  ------------------
  |  Branch (7945:9): [True: 0, False: 12.1k]
  ------------------
 7946|      0|        set_pause_state(mpctx, opts->pause);
 7947|       |
 7948|  12.1k|    if (opt_ptr == &opts->audio_delay) {
  ------------------
  |  Branch (7948:9): [True: 0, False: 12.1k]
  ------------------
 7949|      0|        if (mpctx->ao_chain) {
  ------------------
  |  Branch (7949:13): [True: 0, False: 0]
  ------------------
 7950|      0|            mpctx->delay += mpctx->opts->audio_delay - mpctx->ao_chain->delay;
 7951|      0|            mpctx->ao_chain->delay = mpctx->opts->audio_delay;
 7952|      0|        }
 7953|      0|        mp_wakeup_core(mpctx);
 7954|      0|    }
 7955|       |
 7956|  12.1k|    if (opt_ptr == &opts->vo->window_scale)
  ------------------
  |  Branch (7956:9): [True: 0, False: 12.1k]
  ------------------
 7957|      0|        update_window_scale(mpctx);
 7958|       |
 7959|  12.1k|    if (opt_ptr == &opts->vo->hidpi_window_scale)
  ------------------
  |  Branch (7959:9): [True: 0, False: 12.1k]
  ------------------
 7960|      0|        update_hidpi_window_scale(mpctx, opts->vo->hidpi_window_scale);
 7961|       |
 7962|  12.1k|    if (opt_ptr == &opts->cursor_autohide_delay)
  ------------------
  |  Branch (7962:9): [True: 0, False: 12.1k]
  ------------------
 7963|      0|        mpctx->mouse_timer = 0;
 7964|       |
 7965|  12.1k|    if (opt_ptr == &opts->loop_file) {
  ------------------
  |  Branch (7965:9): [True: 0, False: 12.1k]
  ------------------
 7966|      0|        mpctx->remaining_file_loops = opts->loop_file;
 7967|      0|        mp_notify_property(mpctx, "remaining-file-loops");
 7968|      0|    }
 7969|       |
 7970|  12.1k|    if (opt_ptr == &opts->ab_loop[0] || opt_ptr == &opts->ab_loop[1] ||
  ------------------
  |  Branch (7970:9): [True: 0, False: 12.1k]
  |  Branch (7970:41): [True: 0, False: 12.1k]
  ------------------
 7971|  12.1k|        opt_ptr == &opts->ab_loop_count) {
  ------------------
  |  Branch (7971:9): [True: 0, False: 12.1k]
  ------------------
 7972|      0|        mpctx->remaining_ab_loops = opts->ab_loop_count;
 7973|      0|        mp_notify_property(mpctx, "remaining-ab-loops");
 7974|      0|    }
 7975|       |
 7976|  12.1k|    if (opt_ptr == &opts->ab_loop[0] || opt_ptr == &opts->ab_loop[1]) {
  ------------------
  |  Branch (7976:9): [True: 0, False: 12.1k]
  |  Branch (7976:41): [True: 0, False: 12.1k]
  ------------------
 7977|      0|        update_ab_loop_clip(mpctx);
 7978|       |        // Update if visible
 7979|      0|        set_osd_bar_chapters(mpctx, OSD_BAR_SEEK);
 7980|      0|        mp_wakeup_core(mpctx);
 7981|      0|    }
 7982|       |
 7983|  12.1k|    if (opt_ptr == &opts->vf_settings)
  ------------------
  |  Branch (7983:9): [True: 0, False: 12.1k]
  ------------------
 7984|      0|        set_filters(mpctx, STREAM_VIDEO, opts->vf_settings);
 7985|       |
 7986|  12.1k|    if (opt_ptr == &opts->af_settings)
  ------------------
  |  Branch (7986:9): [True: 0, False: 12.1k]
  ------------------
 7987|      0|        set_filters(mpctx, STREAM_AUDIO, opts->af_settings);
 7988|       |
 7989|  48.5k|    for (int type = 0; type < STREAM_TYPE_COUNT; type++) {
  ------------------
  |  Branch (7989:24): [True: 36.4k, False: 12.1k]
  ------------------
 7990|  85.0k|        for (int order = 0; order < num_ptracks[type]; order++) {
  ------------------
  |  Branch (7990:29): [True: 48.5k, False: 36.4k]
  ------------------
 7991|  48.5k|            if (opt_ptr == &opts->stream_id[order][type])
  ------------------
  |  Branch (7991:17): [True: 0, False: 48.5k]
  ------------------
 7992|      0|                update_track_switch(mpctx, order, type);
 7993|  48.5k|        }
 7994|  36.4k|    }
 7995|       |
 7996|  12.1k|    if (opt_ptr == &opts->vo->fullscreen && !opts->vo->fullscreen)
  ------------------
  |  Branch (7996:9): [True: 0, False: 12.1k]
  |  Branch (7996:45): [True: 0, False: 0]
  ------------------
 7997|      0|        mpctx->mouse_event_ts--; // Show mouse cursor
 7998|       |
 7999|  12.1k|    if (opt_ptr == &opts->vo->taskbar_progress)
  ------------------
  |  Branch (7999:9): [True: 0, False: 12.1k]
  ------------------
 8000|      0|        update_vo_playback_state(mpctx);
 8001|       |
 8002|  12.1k|    if (opt_ptr == &opts->image_display_duration && mpctx->vo_chain
  ------------------
  |  Branch (8002:9): [True: 0, False: 12.1k]
  |  Branch (8002:53): [True: 0, False: 0]
  ------------------
 8003|  12.1k|        && mpctx->vo_chain->is_sparse && !mpctx->ao_chain
  ------------------
  |  Branch (8003:12): [True: 0, False: 0]
  |  Branch (8003:42): [True: 0, False: 0]
  ------------------
 8004|  12.1k|        && mpctx->video_status == STATUS_DRAINING)
  ------------------
  |  Branch (8004:12): [True: 0, False: 0]
  ------------------
 8005|      0|        mpctx->time_frame = opts->image_display_duration;
 8006|  12.1k|}
mp_notify_property:
 8009|    816|{
 8010|    816|    mp_client_property_change(mpctx, property);
 8011|    816|}
command.c:run_next_hook_handler:
  236|  12.2k|{
  237|  12.2k|    struct command_ctx *cmd = mpctx->command_ctx;
  238|       |
  239|  12.2k|    for (int n = start; n < cmd->num_hooks; n++) {
  ------------------
  |  Branch (239:25): [True: 0, False: 12.2k]
  ------------------
  240|      0|        struct hook_handler *h = cmd->hooks[n];
  241|      0|        if (strcmp(h->type, type) == 0) {
  ------------------
  |  Branch (241:13): [True: 0, False: 0]
  ------------------
  242|      0|            int ret = invoke_hook_handler(mpctx, h);
  243|       |            // Repeat until the hook is successfully started or none are left.
  244|      0|            if (ret < 0) {
  ------------------
  |  Branch (244:17): [True: 0, False: 0]
  ------------------
  245|      0|                --n;
  246|      0|                continue;
  247|      0|            }
  248|      0|            return ret;
  249|      0|        }
  250|      0|    }
  251|       |
  252|  12.2k|    mp_wakeup_core(mpctx); // finished hook
  253|  12.2k|    return 0;
  254|  12.2k|}
command.c:match_property:
 4541|  29.5k|{
 4542|  29.5k|    if (strcmp(a, "*") == 0)
  ------------------
  |  Branch (4542:9): [True: 0, False: 29.5k]
  ------------------
 4543|      0|        return true;
 4544|       |    // Give options and properties the same ID each, so change notifications
 4545|       |    // work both way.
 4546|  29.5k|    if (strncmp(a, "options/", 8) == 0)
  ------------------
  |  Branch (4546:9): [True: 0, False: 29.5k]
  ------------------
 4547|      0|        a += 8;
 4548|  29.5k|    if (strncmp(b, "options/", 8) == 0)
  ------------------
  |  Branch (4548:9): [True: 0, False: 29.5k]
  ------------------
 4549|      0|        b += 8;
 4550|  29.5k|    int len_a = prefix_len(a);
 4551|  29.5k|    int len_b = prefix_len(b);
 4552|  29.5k|    return strncmp(a, b, MPMIN(len_a, len_b)) == 0;
  ------------------
  |  |   44|  29.5k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 6.01k, False: 23.5k]
  |  |  ------------------
  ------------------
 4553|  29.5k|}
command.c:prefix_len:
 4535|  59.0k|{
 4536|  59.0k|    const char *end = strchr(p, '/');
 4537|  59.0k|    return end ? end - p : strlen(p) + 1;
  ------------------
  |  Branch (4537:12): [True: 0, False: 59.0k]
  ------------------
 4538|  59.0k|}
command.c:is_property_set:
 4582|    407|{
 4583|    407|    switch (action) {
 4584|      0|    case M_PROPERTY_SET:
  ------------------
  |  Branch (4584:5): [True: 0, False: 407]
  ------------------
 4585|      0|    case M_PROPERTY_SWITCH:
  ------------------
  |  Branch (4585:5): [True: 0, False: 407]
  ------------------
 4586|      0|    case M_PROPERTY_SET_STRING:
  ------------------
  |  Branch (4586:5): [True: 0, False: 407]
  ------------------
 4587|      0|    case M_PROPERTY_SET_NODE:
  ------------------
  |  Branch (4587:5): [True: 0, False: 407]
  ------------------
 4588|      0|    case M_PROPERTY_MULTIPLY:
  ------------------
  |  Branch (4588:5): [True: 0, False: 407]
  ------------------
 4589|      0|        return true;
 4590|     37|    case M_PROPERTY_KEY_ACTION: {
  ------------------
  |  Branch (4590:5): [True: 37, False: 370]
  ------------------
 4591|     37|        struct m_property_action_arg *key = val;
 4592|     37|        return is_property_set(key->action, key->arg);
 4593|      0|    }
 4594|    370|    default:
  ------------------
  |  Branch (4594:5): [True: 370, False: 37]
  ------------------
 4595|    370|        return false;
 4596|    407|    }
 4597|    407|}
command.c:cache_dump_poll:
 6894|  22.3k|{
 6895|  22.3k|    struct command_ctx *ctx = mpctx->command_ctx;
 6896|  22.3k|    struct mp_cmd_ctx *cmd = ctx->cache_dump_cmd;
 6897|       |
 6898|  22.3k|    if (!cmd)
  ------------------
  |  Branch (6898:9): [True: 22.3k, False: 0]
  ------------------
 6899|  22.3k|        return;
 6900|       |
 6901|       |    // Can't close demuxer without stopping dumping.
 6902|      0|    mp_assert(mpctx->demuxer);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
 6903|       |
 6904|      0|    if (mp_cancel_test(cmd->abort->cancel)) {
  ------------------
  |  Branch (6904:9): [True: 0, False: 0]
  ------------------
 6905|       |        // Synchronous abort. In particular, the dump command shall not report
 6906|       |        // completion to the user before the dump target file was closed.
 6907|      0|        demux_cache_dump_set(mpctx->demuxer, 0, 0, NULL);
 6908|      0|        mp_assert(demux_cache_dump_get_status(mpctx->demuxer) <= 0);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
 6909|      0|    }
 6910|       |
 6911|      0|    int status = demux_cache_dump_get_status(mpctx->demuxer);
 6912|      0|    if (status <= 0) {
  ------------------
  |  Branch (6912:9): [True: 0, False: 0]
  ------------------
 6913|      0|        if (status < 0) {
  ------------------
  |  Branch (6913:13): [True: 0, False: 0]
  ------------------
 6914|      0|            mp_cmd_msg(cmd, MSGL_ERR, "Cache dumping stopped due to error.");
 6915|      0|            cmd->success = false;
 6916|      0|        } else {
 6917|      0|            mp_cmd_msg(cmd, MSGL_INFO, "Cache dumping successfully ended.");
 6918|      0|            cmd->success = true;
 6919|      0|        }
 6920|      0|        ctx->cache_dump_cmd = NULL;
 6921|      0|        mp_cmd_ctx_complete(cmd);
 6922|      0|    }
 6923|      0|}
command.c:cmd_quit:
 5781|  12.1k|{
 5782|  12.1k|    struct mp_cmd_ctx *cmd = p;
 5783|  12.1k|    struct MPContext *mpctx = cmd->mpctx;
 5784|  12.1k|    bool write_watch_later = *(bool *)cmd->priv;
 5785|  12.1k|    if (write_watch_later || mpctx->opts->position_save_on_quit)
  ------------------
  |  Branch (5785:9): [True: 0, False: 12.1k]
  |  Branch (5785:30): [True: 0, False: 12.1k]
  ------------------
 5786|      0|        mp_write_watch_later_conf(mpctx);
 5787|  12.1k|    mpctx->stop_play = PT_QUIT;
 5788|  12.1k|    mpctx->quit_custom_rc = cmd->args[0].v.i;
 5789|  12.1k|    mpctx->has_quit_custom_rc = true;
 5790|  12.1k|    mp_wakeup_core(mpctx);
 5791|  12.1k|}
command.c:overlay_uninit:
 5114|  17.0k|{
 5115|  17.0k|    struct command_ctx *cmd = mpctx->command_ctx;
 5116|  17.0k|    if (!mpctx->osd)
  ------------------
  |  Branch (5116:9): [True: 0, False: 17.0k]
  ------------------
 5117|      0|        return;
 5118|  17.0k|    for (int id = 0; id < cmd->num_overlays; id++)
  ------------------
  |  Branch (5118:22): [True: 0, False: 17.0k]
  ------------------
 5119|      0|        replace_overlay(mpctx, id, &(struct overlay){0});
 5120|  17.0k|    osd_set_external2(mpctx->osd, NULL);
 5121|  51.2k|    for (int n = 0; n < 2; n++)
  ------------------
  |  Branch (5121:21): [True: 34.1k, False: 17.0k]
  ------------------
 5122|  34.1k|        mp_image_unrefp(&cmd->overlay_osd[n].packed);
 5123|  17.0k|}
command.c:mp_property_pid:
  501|    108|{
  502|       |    // 32 bit on linux/windows - which C99 `int' is not guaranteed to hold
  503|    108|    return m_property_int64_ro(action, arg, mp_getpid());
  ------------------
  |  |   28|    108|#define mp_getpid() getpid()
  ------------------
  504|    108|}
command.c:mp_property_playback_speed:
  448|    130|{
  449|    130|    MPContext *mpctx = ctx;
  450|    130|    if (action == M_PROPERTY_PRINT || action == M_PROPERTY_FIXED_LEN_PRINT) {
  ------------------
  |  Branch (450:9): [True: 22, False: 108]
  |  Branch (450:39): [True: 18, False: 90]
  ------------------
  451|     40|        *(char **)arg = mp_format_double(NULL, mpctx->opts->playback_speed, 2,
  452|     40|                                         false, false, action != M_PROPERTY_FIXED_LEN_PRINT);
  453|     40|        return M_PROPERTY_OK;
  454|     40|    }
  455|     90|    return mp_property_generic_option(mpctx, prop, action, arg);
  456|    130|}
command.c:mp_property_playback_pitch:
  461|    110|{
  462|    110|    MPContext *mpctx = ctx;
  463|    110|    if (action == M_PROPERTY_PRINT || action == M_PROPERTY_FIXED_LEN_PRINT) {
  ------------------
  |  Branch (463:9): [True: 19, False: 91]
  |  Branch (463:39): [True: 18, False: 73]
  ------------------
  464|     37|        *(char **)arg = mp_format_double(NULL, mpctx->opts->playback_pitch, 2,
  465|     37|                                         false, false, action != M_PROPERTY_FIXED_LEN_PRINT);
  466|     37|        return M_PROPERTY_OK;
  467|     37|    }
  468|     73|    return mp_property_generic_option(mpctx, prop, action, arg);
  469|    110|}
command.c:mp_property_display_sync_active:
  494|     38|{
  495|     38|    MPContext *mpctx = ctx;
  496|     38|    return m_property_bool_ro(action, arg, mpctx->display_sync_active);
  497|     38|}
command.c:mp_property_filename:
  521|     49|{
  522|     49|    MPContext *mpctx = ctx;
  523|     49|    if (!mpctx->filename)
  ------------------
  |  Branch (523:9): [True: 49, False: 0]
  ------------------
  524|     49|        return M_PROPERTY_UNAVAILABLE;
  525|      0|    char *filename = talloc_strdup(NULL, mpctx->filename);
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  526|      0|    if (mp_is_url(bstr0(filename)))
  ------------------
  |  Branch (526:9): [True: 0, False: 0]
  ------------------
  527|      0|        mp_url_unescape_inplace(filename);
  528|      0|    char *f = (char *)mp_basename(filename);
  529|      0|    if (!f[0])
  ------------------
  |  Branch (529:9): [True: 0, False: 0]
  ------------------
  530|      0|        f = filename;
  531|      0|    if (action == M_PROPERTY_KEY_ACTION) {
  ------------------
  |  Branch (531:9): [True: 0, False: 0]
  ------------------
  532|      0|        struct m_property_action_arg *ka = arg;
  533|      0|        if (strcmp(ka->key, "no-ext") == 0) {
  ------------------
  |  Branch (533:13): [True: 0, False: 0]
  ------------------
  534|      0|            action = ka->action;
  535|      0|            arg = ka->arg;
  536|      0|            bstr root;
  537|      0|            if (mp_splitext(f, &root))
  ------------------
  |  Branch (537:17): [True: 0, False: 0]
  ------------------
  538|      0|                f = bstrto0(filename, root);
  539|      0|        }
  540|      0|    }
  541|      0|    int r = m_property_strdup_ro(action, arg, f);
  542|      0|    talloc_free(filename);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  543|      0|    return r;
  544|     49|}
command.c:mp_property_file_size:
  570|     37|{
  571|     37|    MPContext *mpctx = ctx;
  572|     37|    if (!mpctx->demuxer)
  ------------------
  |  Branch (572:9): [True: 37, False: 0]
  ------------------
  573|     37|        return M_PROPERTY_UNAVAILABLE;
  574|       |
  575|      0|    int64_t size = mpctx->demuxer->filesize;
  576|      0|    if (size < 0)
  ------------------
  |  Branch (576:9): [True: 0, False: 0]
  ------------------
  577|      0|        return M_PROPERTY_UNAVAILABLE;
  578|       |
  579|      0|    if (action == M_PROPERTY_PRINT) {
  ------------------
  |  Branch (579:9): [True: 0, False: 0]
  ------------------
  580|      0|        *(char **)arg = format_file_size(size);
  581|      0|        return M_PROPERTY_OK;
  582|      0|    }
  583|      0|    return m_property_int64_ro(action, arg, size);
  584|      0|}
command.c:mp_property_path:
  509|     18|{
  510|     18|    MPContext *mpctx = ctx;
  511|     18|    if (!mpctx->filename)
  ------------------
  |  Branch (511:9): [True: 18, False: 0]
  ------------------
  512|     18|        return M_PROPERTY_UNAVAILABLE;
  513|      0|    char *path = mp_normalize_path(NULL, mpctx->filename);
  514|      0|    int r = m_property_strdup_ro(action, arg, path);
  515|      0|    talloc_free(path);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  516|      0|    return r;
  517|     18|}
command.c:mp_property_media_title:
  588|     48|{
  589|     48|    MPContext *mpctx = ctx;
  590|     48|    const char *name = mp_find_non_filename_media_title(mpctx);
  591|     48|    if (name && name[0])
  ------------------
  |  Branch (591:9): [True: 0, False: 48]
  |  Branch (591:17): [True: 0, False: 0]
  ------------------
  592|      0|        return m_property_strdup_ro(action, arg, name);
  593|     48|    return mp_property_filename(ctx, prop, action, arg);
  594|     48|}
command.c:mp_property_stream_path:
  598|     18|{
  599|     18|    MPContext *mpctx = ctx;
  600|     18|    if (!mpctx->demuxer || !mpctx->demuxer->filename)
  ------------------
  |  Branch (600:9): [True: 18, False: 0]
  |  Branch (600:28): [True: 0, False: 0]
  ------------------
  601|     18|        return M_PROPERTY_UNAVAILABLE;
  602|      0|    return m_property_strdup_ro(action, arg, mpctx->demuxer->filename);
  603|     18|}
command.c:mp_property_demuxer:
  608|     18|{
  609|     18|    MPContext *mpctx = ctx;
  610|     18|    struct demuxer *demuxer = mpctx->demuxer;
  611|     18|    if (!demuxer)
  ------------------
  |  Branch (611:9): [True: 18, False: 0]
  ------------------
  612|     18|        return M_PROPERTY_UNAVAILABLE;
  613|      0|    return m_property_strdup_ro(action, arg, demuxer->desc->name);
  614|     18|}
command.c:mp_property_file_format:
  618|     18|{
  619|     18|    MPContext *mpctx = ctx;
  620|     18|    struct demuxer *demuxer = mpctx->demuxer;
  621|     18|    if (!demuxer)
  ------------------
  |  Branch (621:9): [True: 18, False: 0]
  ------------------
  622|     18|        return M_PROPERTY_UNAVAILABLE;
  623|      0|    const char *name = demuxer->filetype ? demuxer->filetype : demuxer->desc->name;
  ------------------
  |  Branch (623:24): [True: 0, False: 0]
  ------------------
  624|      0|    return m_property_strdup_ro(action, arg, name);
  625|     18|}
command.c:mp_property_stream_pos:
  629|     22|{
  630|     22|    MPContext *mpctx = ctx;
  631|     22|    struct demuxer *demuxer = mpctx->demuxer;
  632|     22|    if (!demuxer || demuxer->filepos < 0)
  ------------------
  |  Branch (632:9): [True: 22, False: 0]
  |  Branch (632:21): [True: 0, False: 0]
  ------------------
  633|     22|        return M_PROPERTY_UNAVAILABLE;
  634|      0|    return m_property_int64_ro(action, arg, demuxer->filepos);
  635|     22|}
command.c:mp_property_stream_end:
  640|     18|{
  641|     18|    return mp_property_file_size(ctx, prop, action, arg);
  642|     18|}
command.c:mp_property_duration:
  683|     18|{
  684|     18|    MPContext *mpctx = ctx;
  685|     18|    double len = get_time_length(mpctx);
  686|       |
  687|     18|    if (len < 0)
  ------------------
  |  Branch (687:9): [True: 18, False: 0]
  ------------------
  688|     18|        return M_PROPERTY_UNAVAILABLE;
  689|       |
  690|      0|    return property_time(action, arg, len);
  691|     18|}
command.c:property_time:
  647|     48|{
  648|     48|    if (time == MP_NOPTS_VALUE)
  ------------------
  |  |   38|     48|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (648:9): [True: 18, False: 30]
  ------------------
  649|     18|        return M_PROPERTY_UNAVAILABLE;
  650|       |
  651|     30|    const struct m_option time_type = {.type = CONF_TYPE_TIME};
  ------------------
  |  |  239|     30|#define CONF_TYPE_TIME          (&m_option_type_time)
  ------------------
  652|     30|    switch (action) {
  ------------------
  |  Branch (652:13): [True: 0, False: 30]
  ------------------
  653|      0|    case M_PROPERTY_GET:
  ------------------
  |  Branch (653:5): [True: 0, False: 30]
  ------------------
  654|      0|        *(double *)arg = time;
  655|      0|        return M_PROPERTY_OK;
  656|      0|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (656:5): [True: 0, False: 30]
  ------------------
  657|      0|        *(struct m_option *)arg = time_type;
  658|      0|        return M_PROPERTY_OK;
  659|     30|    case M_PROPERTY_KEY_ACTION: {
  ------------------
  |  Branch (659:5): [True: 30, False: 0]
  ------------------
  660|     30|        struct m_property_action_arg *ka = arg;
  661|       |
  662|     30|        if (strcmp(ka->key, "full") != 0)
  ------------------
  |  Branch (662:13): [True: 30, False: 0]
  ------------------
  663|     30|            return M_PROPERTY_UNKNOWN;
  664|       |
  665|      0|        switch (ka->action) {
  ------------------
  |  Branch (665:17): [True: 0, False: 0]
  ------------------
  666|      0|        case M_PROPERTY_GET:
  ------------------
  |  Branch (666:9): [True: 0, False: 0]
  ------------------
  667|      0|            *(double *)ka->arg = time;
  668|      0|            return M_PROPERTY_OK;
  669|      0|        case M_PROPERTY_PRINT:
  ------------------
  |  Branch (669:9): [True: 0, False: 0]
  ------------------
  670|      0|            *(char **)ka->arg = mp_format_time(time, true);
  671|      0|            return M_PROPERTY_OK;
  672|      0|        case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (672:9): [True: 0, False: 0]
  ------------------
  673|      0|            *(struct m_option *)ka->arg = time_type;
  674|      0|            return M_PROPERTY_OK;
  675|      0|        }
  676|      0|    }
  677|     30|    }
  678|      0|    return M_PROPERTY_NOT_IMPLEMENTED;
  679|     30|}
command.c:mp_property_avsync:
  695|     18|{
  696|     18|    MPContext *mpctx = ctx;
  697|     18|    if (!mpctx->ao_chain || !mpctx->vo_chain)
  ------------------
  |  Branch (697:9): [True: 18, False: 0]
  |  Branch (697:29): [True: 0, False: 0]
  ------------------
  698|     18|        return M_PROPERTY_UNAVAILABLE;
  699|      0|    if (action == M_PROPERTY_PRINT || action == M_PROPERTY_FIXED_LEN_PRINT) {
  ------------------
  |  Branch (699:9): [True: 0, False: 0]
  |  Branch (699:39): [True: 0, False: 0]
  ------------------
  700|      0|        *(char **)arg = mp_format_double(NULL, mpctx->last_av_difference, 4,
  701|      0|                                         true, false, action != M_PROPERTY_FIXED_LEN_PRINT);
  702|      0|        return M_PROPERTY_OK;
  703|      0|    }
  704|      0|    return m_property_double_ro(action, arg, mpctx->last_av_difference);
  705|      0|}
command.c:mp_property_total_avsync_change:
  709|     19|{
  710|     19|    MPContext *mpctx = ctx;
  711|     19|    if (!mpctx->ao_chain || !mpctx->vo_chain)
  ------------------
  |  Branch (711:9): [True: 19, False: 0]
  |  Branch (711:29): [True: 0, False: 0]
  ------------------
  712|     19|        return M_PROPERTY_UNAVAILABLE;
  713|      0|    if (mpctx->total_avsync_change == MP_NOPTS_VALUE)
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (713:9): [True: 0, False: 0]
  ------------------
  714|      0|        return M_PROPERTY_UNAVAILABLE;
  715|      0|    return m_property_double_ro(action, arg, mpctx->total_avsync_change);
  716|      0|}
command.c:mp_property_display_resolution:
 2751|     84|{
 2752|     84|    MPContext *mpctx = ctx;
 2753|     84|    struct vo *vo = mpctx->video_out;
 2754|     84|    if (!vo)
  ------------------
  |  Branch (2754:9): [True: 73, False: 11]
  ------------------
 2755|     73|        return M_PROPERTY_UNAVAILABLE;
 2756|     11|    int res[2];
 2757|     11|    if (vo_control(vo, VOCTRL_GET_DISPLAY_RES, &res) <= 0)
  ------------------
  |  Branch (2757:9): [True: 11, False: 0]
  ------------------
 2758|     11|        return M_PROPERTY_UNAVAILABLE;
 2759|      0|    if (strcmp(prop->name, "display-width") == 0) {
  ------------------
  |  Branch (2759:9): [True: 0, False: 0]
  ------------------
 2760|      0|        return m_property_int_ro(action, arg, res[0]);
 2761|      0|    } else {
 2762|      0|        return m_property_int_ro(action, arg, res[1]);
 2763|      0|    }
 2764|      0|}
command.c:mp_property_time_pos:
  832|     18|{
  833|     18|    MPContext *mpctx = ctx;
  834|     18|    if (!mpctx->playback_initialized)
  ------------------
  |  Branch (834:9): [True: 18, False: 0]
  ------------------
  835|     18|        return M_PROPERTY_UNAVAILABLE;
  836|       |
  837|      0|    if (action == M_PROPERTY_SET) {
  ------------------
  |  Branch (837:9): [True: 0, False: 0]
  ------------------
  838|      0|        queue_seek(mpctx, MPSEEK_ABSOLUTE, *(double *)arg, MPSEEK_DEFAULT, 0);
  839|      0|        return M_PROPERTY_OK;
  840|      0|    }
  841|      0|    return property_time(action, arg, get_playback_time(mpctx));
  842|      0|}
command.c:mp_property_remaining:
  871|     18|{
  872|     18|    double remaining;
  873|     18|    if (!time_remaining(ctx, &remaining))
  ------------------
  |  Branch (873:9): [True: 18, False: 0]
  ------------------
  874|     18|        return M_PROPERTY_UNAVAILABLE;
  875|       |
  876|      0|    return property_time(action, arg, remaining);
  877|     18|}
command.c:time_remaining:
  857|     36|{
  858|     36|    double len = get_time_length(mpctx);
  859|     36|    double playback = get_playback_time(mpctx);
  860|       |
  861|     36|    if (playback == MP_NOPTS_VALUE || len <= 0)
  ------------------
  |  |   38|     72|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (861:9): [True: 36, False: 0]
  |  Branch (861:39): [True: 0, False: 0]
  ------------------
  862|     36|        return false;
  863|       |
  864|      0|    *remaining = len - playback;
  865|       |
  866|      0|    return len >= 0;
  867|     36|}
command.c:mp_property_audio_pts:
  847|     18|{
  848|     18|    MPContext *mpctx = ctx;
  849|     18|    if (!mpctx->playback_initialized || mpctx->audio_status < STATUS_PLAYING ||
  ------------------
  |  Branch (849:9): [True: 18, False: 0]
  |  Branch (849:41): [True: 0, False: 0]
  ------------------
  850|     18|        mpctx->audio_status >= STATUS_EOF)
  ------------------
  |  Branch (850:9): [True: 0, False: 0]
  ------------------
  851|     18|        return M_PROPERTY_UNAVAILABLE;
  852|       |
  853|      0|    return property_time(action, arg, playing_audio_pts(mpctx));
  854|     18|}
command.c:mp_property_playtime_remaining:
  881|     18|{
  882|     18|    MPContext *mpctx = ctx;
  883|     18|    double remaining;
  884|     18|    if (!time_remaining(mpctx, &remaining))
  ------------------
  |  Branch (884:9): [True: 18, False: 0]
  ------------------
  885|     18|        return M_PROPERTY_UNAVAILABLE;
  886|       |
  887|      0|    double speed = mpctx->video_speed;
  888|      0|    return property_time(action, arg, remaining / speed);
  889|     18|}
command.c:mp_property_remaining_file_loops:
  893|     54|{
  894|     54|    MPContext *mpctx = ctx;
  895|     54|    return m_property_int_ro(action, arg, mpctx->remaining_file_loops);
  896|     54|}
command.c:mp_property_remaining_ab_loops:
  900|    108|{
  901|    108|    MPContext *mpctx = ctx;
  902|    108|    return m_property_int_ro(action, arg, mpctx->remaining_ab_loops);
  903|    108|}
command.c:mp_property_chapter:
  908|     18|{
  909|     18|    MPContext *mpctx = ctx;
  910|     18|    if (!mpctx->playback_initialized)
  ------------------
  |  Branch (910:9): [True: 18, False: 0]
  ------------------
  911|     18|        return M_PROPERTY_UNAVAILABLE;
  912|       |
  913|      0|    int chapter = get_current_chapter(mpctx);
  914|      0|    int num = get_chapter_count(mpctx);
  915|      0|    if (chapter < -1)
  ------------------
  |  Branch (915:9): [True: 0, False: 0]
  ------------------
  916|      0|        return M_PROPERTY_UNAVAILABLE;
  917|       |
  918|      0|    switch (action) {
  ------------------
  |  Branch (918:13): [True: 0, False: 0]
  ------------------
  919|      0|    case M_PROPERTY_GET:
  ------------------
  |  Branch (919:5): [True: 0, False: 0]
  ------------------
  920|      0|        *(int *) arg = chapter;
  921|      0|        return M_PROPERTY_OK;
  922|      0|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (922:5): [True: 0, False: 0]
  ------------------
  923|      0|        *(struct m_option *)arg = (struct m_option){
  924|      0|            .type = CONF_TYPE_INT,
  ------------------
  |  |  229|      0|#define CONF_TYPE_INT           (&m_option_type_int)
  ------------------
  925|      0|            .min = -1,
  926|      0|            .max = num - 1,
  927|      0|        };
  928|      0|        return M_PROPERTY_OK;
  929|      0|    case M_PROPERTY_PRINT: {
  ------------------
  |  Branch (929:5): [True: 0, False: 0]
  ------------------
  930|      0|        *(char **) arg = chapter_display_name(mpctx, chapter);
  931|      0|        return M_PROPERTY_OK;
  932|      0|    }
  933|      0|    case M_PROPERTY_SWITCH:
  ------------------
  |  Branch (933:5): [True: 0, False: 0]
  ------------------
  934|      0|    case M_PROPERTY_SET: ;
  ------------------
  |  Branch (934:5): [True: 0, False: 0]
  ------------------
  935|      0|        mark_seek(mpctx);
  936|      0|        int step_all;
  937|      0|        if (action == M_PROPERTY_SWITCH) {
  ------------------
  |  Branch (937:13): [True: 0, False: 0]
  ------------------
  938|      0|            struct m_property_switch_arg *sarg = arg;
  939|      0|            step_all = lrint(sarg->inc);
  940|       |            // Check threshold for relative backward seeks
  941|      0|            if (mpctx->opts->chapter_seek_threshold >= 0 && step_all < 0) {
  ------------------
  |  Branch (941:17): [True: 0, False: 0]
  |  Branch (941:61): [True: 0, False: 0]
  ------------------
  942|      0|                double current_chapter_start =
  943|      0|                    chapter_start_time(mpctx, chapter);
  944|       |                // If we are far enough into a chapter, seek back to the
  945|       |                // beginning of current chapter instead of previous one
  946|      0|                if (current_chapter_start != MP_NOPTS_VALUE &&
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (946:21): [True: 0, False: 0]
  ------------------
  947|      0|                    get_current_time(mpctx) - current_chapter_start >
  ------------------
  |  Branch (947:21): [True: 0, False: 0]
  ------------------
  948|      0|                    mpctx->opts->chapter_seek_threshold)
  949|      0|                {
  950|      0|                    step_all++;
  951|      0|                }
  952|      0|            }
  953|      0|        } else // Absolute set
  954|      0|            step_all = *(int *)arg - chapter;
  955|      0|        chapter += step_all;
  956|      0|        if (chapter < 0) // avoid using -1 if first chapter starts at 0
  ------------------
  |  Branch (956:13): [True: 0, False: 0]
  ------------------
  957|      0|            chapter = (chapter_start_time(mpctx, 0) <= 0) ? 0 : -1;
  ------------------
  |  Branch (957:23): [True: 0, False: 0]
  ------------------
  958|      0|        if (chapter >= num && step_all > 0) {
  ------------------
  |  Branch (958:13): [True: 0, False: 0]
  |  Branch (958:31): [True: 0, False: 0]
  ------------------
  959|      0|            if (mpctx->opts->keep_open) {
  ------------------
  |  Branch (959:17): [True: 0, False: 0]
  ------------------
  960|      0|                seek_to_last_frame(mpctx);
  961|      0|            } else {
  962|       |                // semi-broken file; ignore for user convenience
  963|      0|                if (action == M_PROPERTY_SWITCH && num < 2)
  ------------------
  |  Branch (963:21): [True: 0, False: 0]
  |  Branch (963:52): [True: 0, False: 0]
  ------------------
  964|      0|                    return M_PROPERTY_UNAVAILABLE;
  965|      0|                if (!mpctx->stop_play)
  ------------------
  |  Branch (965:21): [True: 0, False: 0]
  ------------------
  966|      0|                    mpctx->stop_play = PT_NEXT_ENTRY;
  967|      0|                mp_wakeup_core(mpctx);
  968|      0|            }
  969|      0|        } else {
  970|      0|            double pts = chapter_start_time(mpctx, chapter);
  971|      0|            if (pts != MP_NOPTS_VALUE) {
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (971:17): [True: 0, False: 0]
  ------------------
  972|      0|                queue_seek(mpctx, MPSEEK_CHAPTER, pts, MPSEEK_DEFAULT, 0);
  973|      0|                mpctx->last_chapter_seek = chapter;
  974|      0|                mpctx->last_chapter_flag = true;
  975|      0|            }
  976|      0|        }
  977|      0|        return M_PROPERTY_OK;
  978|      0|    }
  979|      0|    return M_PROPERTY_NOT_IMPLEMENTED;
  980|      0|}
command.c:mp_property_edition:
 1109|    120|{
 1110|    120|    MPContext *mpctx = ctx;
 1111|    120|    struct demuxer *demuxer = mpctx->demuxer;
 1112|    120|    char *name = NULL;
 1113|       |
 1114|    120|    if (!demuxer)
  ------------------
  |  Branch (1114:9): [True: 120, False: 0]
  ------------------
 1115|    120|        return mp_property_generic_option(mpctx, prop, action, arg);
 1116|       |
 1117|      0|    int ed = demuxer->edition;
 1118|       |
 1119|      0|    if (demuxer->num_editions <= 1)
  ------------------
  |  Branch (1119:9): [True: 0, False: 0]
  ------------------
 1120|      0|        return M_PROPERTY_UNAVAILABLE;
 1121|       |
 1122|      0|    switch (action) {
 1123|      0|    case M_PROPERTY_GET_CONSTRICTED_TYPE: {
  ------------------
  |  Branch (1123:5): [True: 0, False: 0]
  ------------------
 1124|      0|        *(struct m_option *)arg = (struct m_option){
 1125|      0|            .type = CONF_TYPE_INT,
  ------------------
  |  |  229|      0|#define CONF_TYPE_INT           (&m_option_type_int)
  ------------------
 1126|      0|            .min = 0,
 1127|      0|            .max = demuxer->num_editions - 1,
 1128|      0|        };
 1129|      0|        return M_PROPERTY_OK;
 1130|      0|    }
 1131|      0|    case M_PROPERTY_PRINT: {
  ------------------
  |  Branch (1131:5): [True: 0, False: 0]
  ------------------
 1132|      0|        if (ed < 0)
  ------------------
  |  Branch (1132:13): [True: 0, False: 0]
  ------------------
 1133|      0|            return M_PROPERTY_UNAVAILABLE;
 1134|      0|        name = mp_tags_get_str(demuxer->editions[ed].metadata, "title");
 1135|      0|        if (name) {
  ------------------
  |  Branch (1135:13): [True: 0, False: 0]
  ------------------
 1136|      0|            *(char **) arg = talloc_strdup(NULL, name);
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
 1137|      0|        } else {
 1138|      0|            *(char **) arg = talloc_asprintf(NULL, "%d", ed + 1);
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 1139|      0|        }
 1140|      0|        return M_PROPERTY_OK;
 1141|      0|    }
 1142|      0|    default:
  ------------------
  |  Branch (1142:5): [True: 0, False: 0]
  ------------------
 1143|      0|        return mp_property_generic_option(mpctx, prop, action, arg);
 1144|      0|    }
 1145|      0|}
command.c:mp_property_chapters:
 1208|     18|{
 1209|     18|    MPContext *mpctx = ctx;
 1210|     18|    if (!mpctx->playback_initialized)
  ------------------
  |  Branch (1210:9): [True: 18, False: 0]
  ------------------
 1211|     18|        return M_PROPERTY_UNAVAILABLE;
 1212|      0|    int count = get_chapter_count(mpctx);
 1213|      0|    return m_property_int_ro(action, arg, count);
 1214|     18|}
command.c:mp_property_editions:
 1218|     19|{
 1219|     19|    MPContext *mpctx = ctx;
 1220|     19|    struct demuxer *demuxer = mpctx->demuxer;
 1221|     19|    if (!demuxer)
  ------------------
  |  Branch (1221:9): [True: 19, False: 0]
  ------------------
 1222|     19|        return M_PROPERTY_UNAVAILABLE;
 1223|      0|    if (demuxer->num_editions <= 0)
  ------------------
  |  Branch (1223:9): [True: 0, False: 0]
  ------------------
 1224|      0|        return M_PROPERTY_UNAVAILABLE;
 1225|      0|    return m_property_int_ro(action, arg, demuxer->num_editions);
 1226|      0|}
command.c:mp_property_metadata:
 1316|     18|{
 1317|     18|    MPContext *mpctx = ctx;
 1318|     18|    struct demuxer *demuxer = mpctx->demuxer;
 1319|     18|    if (!demuxer)
  ------------------
  |  Branch (1319:9): [True: 18, False: 0]
  ------------------
 1320|     18|        return M_PROPERTY_UNAVAILABLE;
 1321|       |
 1322|      0|    return tag_property(action, arg, demuxer->metadata);
 1323|     18|}
command.c:mp_property_filter_metadata:
 1347|     75|{
 1348|     75|    MPContext *mpctx = ctx;
 1349|     75|    const char *type = prop->priv;
 1350|       |
 1351|     75|    if (action == M_PROPERTY_KEY_ACTION) {
  ------------------
  |  Branch (1351:9): [True: 57, False: 18]
  ------------------
 1352|     57|        struct m_property_action_arg *ka = arg;
 1353|     57|        bstr key;
 1354|     57|        char *rem;
 1355|     57|        m_property_split_path(ka->key, &key, &rem);
 1356|     57|        struct mp_tags *metadata = NULL;
 1357|     57|        struct mp_output_chain *chain = NULL;
 1358|     57|        if (strcmp(type, "vf") == 0) {
  ------------------
  |  Branch (1358:13): [True: 39, False: 18]
  ------------------
 1359|     39|            chain = mpctx->vo_chain ? mpctx->vo_chain->filter : NULL;
  ------------------
  |  Branch (1359:21): [True: 0, False: 39]
  ------------------
 1360|     39|        } else if (strcmp(type, "af") == 0) {
  ------------------
  |  Branch (1360:20): [True: 18, False: 0]
  ------------------
 1361|     18|            chain = mpctx->ao_chain ? mpctx->ao_chain->filter : NULL;
  ------------------
  |  Branch (1361:21): [True: 0, False: 18]
  ------------------
 1362|     18|        }
 1363|     57|        if (!chain)
  ------------------
  |  Branch (1363:13): [True: 57, False: 0]
  ------------------
 1364|     57|            return M_PROPERTY_UNAVAILABLE;
 1365|       |
 1366|      0|        int remaining = strlen(rem);
 1367|      0|        if (remaining || ka->action != M_PROPERTY_GET_TYPE) {
  ------------------
  |  Branch (1367:13): [True: 0, False: 0]
  |  Branch (1367:26): [True: 0, False: 0]
  ------------------
 1368|      0|            struct mp_filter_command cmd = {
 1369|      0|                .type = MP_FILTER_COMMAND_GET_META,
 1370|      0|                .res = &metadata,
 1371|      0|            };
 1372|      0|            mp_output_chain_command(chain, mp_tprintf(80, "%.*s", BSTR_P(key)),
  ------------------
  |  |  165|      0|    mp_tprintf_buf((char[SIZE]){0}, (SIZE), (format), __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (165:55): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1373|      0|                                    &cmd);
 1374|       |
 1375|      0|            if (!metadata)
  ------------------
  |  Branch (1375:17): [True: 0, False: 0]
  ------------------
 1376|      0|                return M_PROPERTY_ERROR;
 1377|      0|        }
 1378|       |
 1379|      0|        int res;
 1380|      0|        if (remaining) {
  ------------------
  |  Branch (1380:13): [True: 0, False: 0]
  ------------------
 1381|      0|            struct m_property_action_arg next_ka = *ka;
 1382|      0|            next_ka.key = rem;
 1383|      0|            res = tag_property(M_PROPERTY_KEY_ACTION, &next_ka, metadata);
 1384|      0|        } else {
 1385|      0|            res = tag_property(ka->action, ka->arg, metadata);
 1386|      0|        }
 1387|      0|        talloc_free(metadata);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 1388|      0|        return res;
 1389|      0|    }
 1390|     18|    return M_PROPERTY_NOT_IMPLEMENTED;
 1391|     75|}
command.c:mp_property_core_idle:
 1395|      3|{
 1396|      3|    MPContext *mpctx = ctx;
 1397|      3|    return m_property_bool_ro(action, arg, !mpctx->playback_active);
 1398|      3|}
command.c:mp_property_eof_reached:
 1432|     18|{
 1433|     18|    MPContext *mpctx = ctx;
 1434|     18|    if (!mpctx->playback_initialized)
  ------------------
  |  Branch (1434:9): [True: 18, False: 0]
  ------------------
 1435|     18|        return M_PROPERTY_UNAVAILABLE;
 1436|      0|    bool eof = mpctx->video_status == STATUS_EOF &&
  ------------------
  |  Branch (1436:16): [True: 0, False: 0]
  ------------------
 1437|      0|               mpctx->audio_status == STATUS_EOF;
  ------------------
  |  Branch (1437:16): [True: 0, False: 0]
  ------------------
 1438|      0|    return m_property_bool_ro(action, arg, eof);
 1439|     18|}
command.c:mp_property_seeking:
 1443|     26|{
 1444|     26|    MPContext *mpctx = ctx;
 1445|     26|    if (!mpctx->playback_initialized)
  ------------------
  |  Branch (1445:9): [True: 26, False: 0]
  ------------------
 1446|     26|        return M_PROPERTY_UNAVAILABLE;
 1447|      0|    return m_property_bool_ro(action, arg, !mpctx->restart_complete);
 1448|     26|}
command.c:mp_property_playback_abort:
 1452|    177|{
 1453|    177|    MPContext *mpctx = ctx;
 1454|    177|    return m_property_bool_ro(action, arg, !mpctx->playing || mpctx->stop_play);
  ------------------
  |  Branch (1454:44): [True: 177, False: 0]
  |  Branch (1454:63): [True: 0, False: 0]
  ------------------
 1455|    177|}
command.c:mp_property_cache_speed:
 1459|     10|{
 1460|     10|    MPContext *mpctx = ctx;
 1461|     10|    if (!mpctx->demuxer)
  ------------------
  |  Branch (1461:9): [True: 10, False: 0]
  ------------------
 1462|     10|        return M_PROPERTY_UNAVAILABLE;
 1463|       |
 1464|      0|    struct demux_reader_state s;
 1465|      0|    demux_get_reader_state(mpctx->demuxer, &s);
 1466|       |
 1467|      0|    uint64_t val = s.bytes_per_second;
 1468|       |
 1469|      0|    if (action == M_PROPERTY_PRINT) {
  ------------------
  |  Branch (1469:9): [True: 0, False: 0]
  ------------------
 1470|      0|        *(char **)arg = talloc_strdup_append(format_file_size(val), "/s");
  ------------------
  |  |   57|      0|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
 1471|      0|        return M_PROPERTY_OK;
 1472|      0|    }
 1473|      0|    return m_property_int64_ro(action, arg, val);
 1474|      0|}
command.c:mp_property_demuxer_cache_time:
 1494|     18|{
 1495|     18|    MPContext *mpctx = ctx;
 1496|     18|    if (!mpctx->demuxer)
  ------------------
  |  Branch (1496:9): [True: 18, False: 0]
  ------------------
 1497|     18|        return M_PROPERTY_UNAVAILABLE;
 1498|       |
 1499|      0|    struct demux_reader_state s;
 1500|      0|    demux_get_reader_state(mpctx->demuxer, &s);
 1501|       |
 1502|      0|    if (s.ts_info.end == MP_NOPTS_VALUE)
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (1502:9): [True: 0, False: 0]
  ------------------
 1503|      0|        return M_PROPERTY_UNAVAILABLE;
 1504|       |
 1505|      0|    return m_property_double_ro(action, arg, s.ts_info.end);
 1506|      0|}
command.c:mp_property_demuxer_start_time:
 1602|     21|{
 1603|     21|    MPContext *mpctx = ctx;
 1604|     21|    if (!mpctx->demuxer)
  ------------------
  |  Branch (1604:9): [True: 21, False: 0]
  ------------------
 1605|     21|        return M_PROPERTY_UNAVAILABLE;
 1606|       |
 1607|      0|    return m_property_double_ro(action, arg, mpctx->demuxer->start_time);
 1608|     21|}
command.c:mp_property_demuxer_is_network:
 1631|     20|{
 1632|     20|    MPContext *mpctx = ctx;
 1633|     20|    if (!mpctx->demuxer)
  ------------------
  |  Branch (1633:9): [True: 20, False: 0]
  ------------------
 1634|     20|        return M_PROPERTY_UNAVAILABLE;
 1635|       |
 1636|      0|    return m_property_bool_ro(action, arg, mpctx->demuxer->is_network);
 1637|     20|}
command.c:mp_property_clock:
 1642|    122|{
 1643|    122|    char outstr[6];
 1644|    122|    time_t t = time(NULL);
 1645|    122|    struct tm *tmp = localtime(&t);
 1646|       |
 1647|    122|    if ((tmp != NULL) && (strftime(outstr, sizeof(outstr), "%H:%M", tmp) == 5))
  ------------------
  |  Branch (1647:9): [True: 122, False: 0]
  |  Branch (1647:26): [True: 122, False: 0]
  ------------------
 1648|    122|        return m_property_strdup_ro(action, arg, outstr);
 1649|      0|    return M_PROPERTY_UNAVAILABLE;
 1650|    122|}
command.c:mp_property_seekable:
 1654|     18|{
 1655|     18|    MPContext *mpctx = ctx;
 1656|     18|    if (!mpctx->demuxer)
  ------------------
  |  Branch (1656:9): [True: 18, False: 0]
  ------------------
 1657|     18|        return M_PROPERTY_UNAVAILABLE;
 1658|      0|    return m_property_bool_ro(action, arg, mpctx->demuxer->seekable);
 1659|     18|}
command.c:mp_property_window_id:
 1421|     21|{
 1422|     21|    MPContext *mpctx = ctx;
 1423|     21|    struct vo *vo = mpctx->video_out;
 1424|     21|    int64_t wid;
 1425|     21|    if (!vo || vo_control(vo, VOCTRL_GET_WINDOW_ID, &wid) <= 0)
  ------------------
  |  Branch (1425:9): [True: 21, False: 0]
  |  Branch (1425:16): [True: 0, False: 0]
  ------------------
 1426|     21|        return M_PROPERTY_UNAVAILABLE;
 1427|      0|    return m_property_int64_ro(action, arg, wid);
 1428|     21|}
command.c:mp_property_list_chapters:
 1062|     40|{
 1063|     40|    MPContext *mpctx = ctx;
 1064|     40|    int count = get_chapter_count(mpctx);
 1065|     40|    switch (action) {
  ------------------
  |  Branch (1065:13): [True: 21, False: 19]
  ------------------
 1066|     19|    case M_PROPERTY_PRINT: {
  ------------------
  |  Branch (1066:5): [True: 19, False: 21]
  ------------------
 1067|     19|        int cur = mpctx->playback_initialized ? get_current_chapter(mpctx) : -1;
  ------------------
  |  Branch (1067:19): [True: 0, False: 19]
  ------------------
 1068|     19|        char *res = NULL;
 1069|     19|        int n;
 1070|       |
 1071|     19|        if (count < 1) {
  ------------------
  |  Branch (1071:13): [True: 19, False: 0]
  ------------------
 1072|     19|            res = talloc_asprintf_append(res, "No chapters.");
  ------------------
  |  |   63|     19|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 1073|     19|        }
 1074|       |
 1075|     19|        for (n = 0; n < count; n++) {
  ------------------
  |  Branch (1075:21): [True: 0, False: 19]
  ------------------
 1076|      0|            if (n == cur)
  ------------------
  |  Branch (1076:17): [True: 0, False: 0]
  ------------------
 1077|      0|                res = append_selected_style(mpctx, res);
 1078|      0|            char *name = chapter_name(mpctx, n);
 1079|      0|            double t = chapter_start_time(mpctx, n);
 1080|      0|            char* time = mp_format_time(t, false);
 1081|      0|            res = talloc_asprintf_append(res, "%s  %s%s\n", time, name,
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 1082|      0|                                         n == cur ? get_style_reset(mpctx) : "");
  ------------------
  |  Branch (1082:42): [True: 0, False: 0]
  ------------------
 1083|      0|            talloc_free(time);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 1084|      0|        }
 1085|       |
 1086|     19|        *(char **)arg = count ? cut_osd_list(mpctx, "Chapters", res, cur) : res;
  ------------------
  |  Branch (1086:25): [True: 0, False: 19]
  ------------------
 1087|     19|        return M_PROPERTY_OK;
 1088|      0|    }
 1089|      0|    case M_PROPERTY_SET: {
  ------------------
  |  Branch (1089:5): [True: 0, False: 40]
  ------------------
 1090|      0|        struct mpv_node *given_chapters = arg;
 1091|      0|        return parse_node_chapters(mpctx, given_chapters);
 1092|      0|    }
 1093|     40|    }
 1094|     21|    return m_property_read_list(action, arg, count, get_chapter_entry, mpctx);
 1095|     40|}
command.c:append_selected_style:
  319|      3|{
  320|      3|    if (!mpctx->video_out || !mpctx->opts->video_osd)
  ------------------
  |  Branch (320:9): [True: 3, False: 0]
  |  Branch (320:30): [True: 0, False: 0]
  ------------------
  321|      3|        return talloc_strdup_append(str, TERM_ESC_REVERSE_COLORS);
  ------------------
  |  |   57|      3|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
                      return talloc_strdup_append(str, TERM_ESC_REVERSE_COLORS);
  ------------------
  |  |   41|      3|#define TERM_ESC_REVERSE_COLORS     "\033[7m"
  ------------------
  322|       |
  323|      0|    return talloc_asprintf_append(str,
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
  324|      0|               "%s{\\b1\\1c&H%02hhx%02hhx%02hhx&\\1a&H%02hhx&\\3c&H%02hhx%02hhx%02hhx&\\3a&H%02hhx&}%s",
  325|      0|               OSD_ASS_0,
  ------------------
  |  |  136|      0|#define OSD_ASS_0 OSD_ASS_ESCAPE "0"
  |  |  ------------------
  |  |  |  |  134|      0|#define OSD_ASS_ESCAPE "\xC2\x92" "a"
  |  |  ------------------
  ------------------
  326|      0|               mpctx->video_out->osd->opts->osd_selected_color.b,
  327|      0|               mpctx->video_out->osd->opts->osd_selected_color.g,
  328|      0|               mpctx->video_out->osd->opts->osd_selected_color.r,
  329|      0|               255 - mpctx->video_out->osd->opts->osd_selected_color.a,
  330|      0|               mpctx->video_out->osd->opts->osd_selected_outline_color.b,
  331|      0|               mpctx->video_out->osd->opts->osd_selected_outline_color.g,
  332|      0|               mpctx->video_out->osd->opts->osd_selected_outline_color.r,
  333|      0|               255 - mpctx->video_out->osd->opts->osd_selected_outline_color.a,
  334|      0|               OSD_ASS_1);
  ------------------
  |  |  137|      0|#define OSD_ASS_1 OSD_ASS_ESCAPE "1"
  |  |  ------------------
  |  |  |  |  134|      0|#define OSD_ASS_ESCAPE "\xC2\x92" "a"
  |  |  ------------------
  ------------------
  335|      3|}
command.c:get_style_reset:
  338|      3|{
  339|      3|    return mpctx->video_out && mpctx->opts->video_osd
  ------------------
  |  Branch (339:12): [True: 0, False: 3]
  |  Branch (339:32): [True: 0, False: 0]
  ------------------
  340|      3|        ? OSD_ASS_0"{\\r}"OSD_ASS_1
  ------------------
  |  |  136|      0|#define OSD_ASS_0 OSD_ASS_ESCAPE "0"
  |  |  ------------------
  |  |  |  |  134|      0|#define OSD_ASS_ESCAPE "\xC2\x92" "a"
  |  |  ------------------
  ------------------
                      ? OSD_ASS_0"{\\r}"OSD_ASS_1
  ------------------
  |  |  137|      0|#define OSD_ASS_1 OSD_ASS_ESCAPE "1"
  ------------------
  341|      3|        : TERM_ESC_CLEAR_COLORS;
  ------------------
  |  |   42|      6|#define TERM_ESC_CLEAR_COLORS       "\033[0m"
  ------------------
  342|      3|}
command.c:cut_osd_list:
  377|    186|{
  378|    186|    int count = count_lines(text);
  379|    186|    if (!count)
  ------------------
  |  Branch (379:9): [True: 18, False: 168]
  ------------------
  380|     18|        return text;
  381|       |
  382|    168|    int max_lines;
  383|    168|    if (mpctx->video_out && mpctx->opts->video_osd) {
  ------------------
  |  Branch (383:9): [True: 2, False: 166]
  |  Branch (383:29): [True: 2, False: 0]
  ------------------
  384|      2|        int screen_h, font_h;
  385|      2|        osd_get_text_size(mpctx->osd, &screen_h, &font_h);
  386|      2|        max_lines = screen_h / MPMAX(font_h, 1);
  ------------------
  |  |   43|      2|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 2]
  |  |  ------------------
  ------------------
  387|    166|    } else {
  388|    166|        int w = -1;
  389|    166|        max_lines = 24;
  390|    166|        terminal_get_size(&w, &max_lines);
  391|    166|        char *msg = mp_property_expand_escaped_string(mpctx, mpctx->opts->status_msg);
  392|    166|        max_lines -= msg[0] ? count_lines(msg) : 1;
  ------------------
  |  Branch (392:22): [True: 0, False: 166]
  ------------------
  393|    166|        talloc_free(msg);
  ------------------
  |  |   47|    166|#define talloc_free                     ta_free
  ------------------
  394|    166|    }
  395|       |    // Subtract 1 for the header.
  396|    168|    max_lines--;
  397|       |
  398|    168|    char *new = talloc_asprintf(NULL, "%s [%d/%d]:\n", header, pos + 1, count);
  ------------------
  |  |   52|    168|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|    168|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  399|    168|    int start = MPMIN(MPMAX(pos - max_lines / 2, 0), count - max_lines);
  ------------------
  |  |   44|    336|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 105, False: 63]
  |  |  |  Branch (44:23): [True: 0, False: 168]
  |  |  |  Branch (44:41): [True: 0, False: 63]
  |  |  ------------------
  ------------------
  400|    168|    char *head = skip_n_lines(text, start);
  401|    168|    char *tail = skip_n_lines(head, max_lines);
  402|    168|    new = talloc_asprintf_append_buffer(new, "%.*s",
  ------------------
  |  |   64|    168|#define talloc_asprintf_append_buffer   ta_talloc_asprintf_append_buffer
  ------------------
  403|    168|                            (int)(tail ? tail - head : strlen(head)), head);
  ------------------
  |  Branch (403:35): [True: 63, False: 105]
  ------------------
  404|       |    // Strip the final newline to not print it in the terminal.
  405|    168|    new[strlen(new) - 1] = '\0';
  406|       |
  407|    168|    talloc_free(text);
  ------------------
  |  |   47|    168|#define talloc_free                     ta_free
  ------------------
  408|    168|    return new;
  409|    186|}
command.c:count_lines:
  355|    186|{
  356|    186|    if (!text[0])
  ------------------
  |  Branch (356:9): [True: 18, False: 168]
  ------------------
  357|     18|        return 0;
  358|       |
  359|    168|    int count = 0;
  360|  2.97k|    while (text) {
  ------------------
  |  Branch (360:12): [True: 2.97k, False: 0]
  ------------------
  361|  2.97k|        count++;
  362|  2.97k|        char *next = strchr(text, '\n');
  363|  2.97k|        if (!next || (next[0] == '\n' && !next[1]))
  ------------------
  |  Branch (363:13): [True: 0, False: 2.97k]
  |  Branch (363:23): [True: 2.97k, False: 0]
  |  Branch (363:42): [True: 168, False: 2.80k]
  ------------------
  364|    168|            break;
  365|  2.80k|        text = next + 1;
  366|  2.80k|    }
  367|    168|    return count;
  368|    186|}
command.c:skip_n_lines:
  345|    336|{
  346|  2.67k|    while (text && lines > 0) {
  ------------------
  |  Branch (346:12): [True: 2.57k, False: 105]
  |  Branch (346:20): [True: 2.33k, False: 231]
  ------------------
  347|  2.33k|        char *next = strchr(text, '\n');
  348|  2.33k|        text = next ? next + 1 : NULL;
  ------------------
  |  Branch (348:16): [True: 2.23k, False: 105]
  ------------------
  349|  2.33k|        lines--;
  350|  2.33k|    }
  351|    336|    return text;
  352|    336|}
command.c:mp_property_list_tracks:
 2160|    173|{
 2161|    173|    MPContext *mpctx = ctx;
 2162|    173|    if (action == M_PROPERTY_PRINT) {
  ------------------
  |  Branch (2162:9): [True: 37, False: 136]
  ------------------
 2163|     37|        char *res = talloc_strdup(NULL, "");
  ------------------
  |  |   50|     37|#define talloc_strdup                   ta_xstrdup
  ------------------
 2164|       |
 2165|    148|        for (int type = 0; type < STREAM_TYPE_COUNT; type++) {
  ------------------
  |  Branch (2165:28): [True: 111, False: 37]
  ------------------
 2166|    111|            bool found = false;
 2167|       |
 2168|    111|            for (int n = 0; n < mpctx->num_tracks; n++) {
  ------------------
  |  Branch (2168:29): [True: 0, False: 111]
  ------------------
 2169|      0|                struct track *track = mpctx->tracks[n];
 2170|      0|                if (track->type == type) {
  ------------------
  |  Branch (2170:21): [True: 0, False: 0]
  ------------------
 2171|      0|                    res = talloc_asprintf_append(res, "%s: ", track_type_name(track));
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 2172|      0|                    res = append_track_info(res, track);
 2173|      0|                    res = talloc_asprintf_append(res, "\n");
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 2174|      0|                    found = true;
 2175|      0|                }
 2176|      0|            }
 2177|       |
 2178|    111|            if (found && type < STREAM_TYPE_COUNT - 1) {
  ------------------
  |  Branch (2178:17): [True: 0, False: 111]
  |  Branch (2178:26): [True: 0, False: 0]
  ------------------
 2179|      0|                res = talloc_asprintf_append(res, "\n");
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 2180|      0|                found = false;
 2181|      0|            }
 2182|    111|        }
 2183|       |
 2184|     37|        struct demuxer *demuxer = mpctx->demuxer;
 2185|     37|        if (demuxer && demuxer->num_editions > 1) {
  ------------------
  |  Branch (2185:13): [True: 0, False: 37]
  |  Branch (2185:24): [True: 0, False: 0]
  ------------------
 2186|      0|            res = talloc_asprintf_append(res, "\nEdition: %d of %d",
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 2187|      0|                                         demuxer->edition + 1,
 2188|      0|                                         demuxer->num_editions);
 2189|     37|        } else {
 2190|     37|            res[strlen(res) - 1] = '\0';
 2191|     37|        }
 2192|       |
 2193|     37|        *(char **)arg = res;
 2194|     37|        return M_PROPERTY_OK;
 2195|     37|    }
 2196|       |
 2197|    136|    if (action == M_PROPERTY_KEY_ACTION) {
  ------------------
  |  Branch (2197:9): [True: 36, False: 100]
  ------------------
 2198|     36|        struct m_property_action_arg *ka = arg;
 2199|       |
 2200|     36|        int type = -1;
 2201|     36|        if (!strcmp(ka->key, "video")) {
  ------------------
  |  Branch (2201:13): [True: 0, False: 36]
  ------------------
 2202|      0|            type = STREAM_VIDEO;
 2203|     36|        } else if (!strcmp(ka->key, "audio")) {
  ------------------
  |  Branch (2203:20): [True: 0, False: 36]
  ------------------
 2204|      0|            type = STREAM_AUDIO;
 2205|     36|        } else if (!strcmp(ka->key, "sub")) {
  ------------------
  |  Branch (2205:20): [True: 0, False: 36]
  ------------------
 2206|      0|            type = STREAM_SUB;
 2207|      0|        }
 2208|       |
 2209|     36|        if (type != -1) {
  ------------------
  |  Branch (2209:13): [True: 0, False: 36]
  ------------------
 2210|      0|            char *res;
 2211|       |
 2212|      0|            switch (ka->action) {
 2213|      0|                case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (2213:17): [True: 0, False: 0]
  ------------------
 2214|      0|                    *(struct m_option *)ka->arg = (struct m_option){.type = CONF_TYPE_STRING};
  ------------------
  |  |  233|      0|#define CONF_TYPE_STRING        (&m_option_type_string)
  ------------------
 2215|      0|                    return M_PROPERTY_OK;
 2216|      0|                case M_PROPERTY_PRINT:
  ------------------
  |  Branch (2216:17): [True: 0, False: 0]
  ------------------
 2217|      0|                    res = talloc_asprintf(NULL, "Available %s tracks:",
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (127:62): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2218|      0|                              type == STREAM_SUB ? "subtitle" : stream_type_name(type));
 2219|       |
 2220|      0|                    for (int n = 0; n < mpctx->num_tracks; n++) {
  ------------------
  |  Branch (2220:37): [True: 0, False: 0]
  ------------------
 2221|      0|                        if (mpctx->tracks[n]->type == type) {
  ------------------
  |  Branch (2221:29): [True: 0, False: 0]
  ------------------
 2222|      0|                            res = talloc_strdup_append(res, "\n");
  ------------------
  |  |   57|      0|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
 2223|      0|                            res = append_track_info(res, mpctx->tracks[n]);
 2224|      0|                        }
 2225|      0|                    }
 2226|       |
 2227|      0|                    *(char **)ka->arg = res;
 2228|      0|                    return M_PROPERTY_OK;
 2229|      0|                default:
  ------------------
  |  Branch (2229:17): [True: 0, False: 0]
  ------------------
 2230|      0|                    return M_PROPERTY_NOT_IMPLEMENTED;
 2231|      0|            }
 2232|      0|        }
 2233|     36|    }
 2234|       |
 2235|    136|    return m_property_read_list(action, arg, mpctx->num_tracks,
 2236|    136|                                get_track_entry, mpctx);
 2237|    136|}
command.c:property_list_editions:
 1169|     18|{
 1170|     18|    MPContext *mpctx = ctx;
 1171|     18|    struct demuxer *demuxer = mpctx->demuxer;
 1172|     18|    if (!demuxer)
  ------------------
  |  Branch (1172:9): [True: 18, False: 0]
  ------------------
 1173|     18|        return M_PROPERTY_UNAVAILABLE;
 1174|       |
 1175|      0|    if (action == M_PROPERTY_PRINT) {
  ------------------
  |  Branch (1175:9): [True: 0, False: 0]
  ------------------
 1176|      0|        char *res = NULL;
 1177|       |
 1178|      0|        struct demux_edition *editions = demuxer->editions;
 1179|      0|        int num_editions = demuxer->num_editions;
 1180|      0|        int current = demuxer->edition;
 1181|       |
 1182|      0|        if (!num_editions)
  ------------------
  |  Branch (1182:13): [True: 0, False: 0]
  ------------------
 1183|      0|            res = talloc_asprintf_append(res, "No editions.");
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 1184|       |
 1185|      0|        for (int n = 0; n < num_editions; n++) {
  ------------------
  |  Branch (1185:25): [True: 0, False: 0]
  ------------------
 1186|      0|            struct demux_edition *ed = &editions[n];
 1187|       |
 1188|      0|            if (n == current)
  ------------------
  |  Branch (1188:17): [True: 0, False: 0]
  ------------------
 1189|      0|                res = append_selected_style(mpctx, res);
 1190|      0|            res = talloc_asprintf_append(res, "%d: ", n);
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 1191|      0|            char *title = mp_tags_get_str(ed->metadata, "title");
 1192|      0|            if (!title)
  ------------------
  |  Branch (1192:17): [True: 0, False: 0]
  ------------------
 1193|      0|                title = "unnamed";
 1194|      0|            res = talloc_asprintf_append(res, "'%s'%s\n", title,
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 1195|      0|                                         n == current ? get_style_reset(mpctx) : "");
  ------------------
  |  Branch (1195:42): [True: 0, False: 0]
  ------------------
 1196|      0|        }
 1197|       |
 1198|      0|        *(char **)arg = res;
 1199|      0|        return M_PROPERTY_OK;
 1200|      0|    }
 1201|      0|    return m_property_read_list(action, arg, demuxer->num_editions,
 1202|      0|                                get_edition_entry, mpctx);
 1203|      0|}
command.c:mp_property_playlist:
 3409|  2.33k|{
 3410|  2.33k|    MPContext *mpctx = ctx;
 3411|  2.33k|    if (action == M_PROPERTY_PRINT) {
  ------------------
  |  Branch (3411:9): [True: 186, False: 2.14k]
  ------------------
 3412|    186|        struct playlist *pl = mpctx->playlist;
 3413|    186|        char *res = talloc_strdup(NULL, "");
  ------------------
  |  |   50|    186|#define talloc_strdup                   ta_xstrdup
  ------------------
 3414|       |
 3415|  3.15k|        for (int n = 0; n < pl->num_entries; n++) {
  ------------------
  |  Branch (3415:25): [True: 2.97k, False: 186]
  ------------------
 3416|  2.97k|            struct playlist_entry *e = pl->entries[n];
 3417|  2.97k|            if (pl->current == e)
  ------------------
  |  Branch (3417:17): [True: 3, False: 2.96k]
  ------------------
 3418|      3|                res = append_selected_style(mpctx, res);
 3419|  2.97k|            const char *reset = pl->current == e ? get_style_reset(mpctx) : "";
  ------------------
  |  Branch (3419:33): [True: 3, False: 2.96k]
  ------------------
 3420|  2.97k|            char *p = e->title;
 3421|  2.97k|            if (!p || mpctx->opts->playlist_entry_name > 0) {
  ------------------
  |  Branch (3421:17): [True: 2.97k, False: 0]
  |  Branch (3421:23): [True: 0, False: 0]
  ------------------
 3422|  2.97k|                p = e->filename;
 3423|  2.97k|                if (!mp_is_url(bstr0(p))) {
  ------------------
  |  Branch (3423:21): [True: 2.49k, False: 475]
  ------------------
 3424|  2.49k|                    char *s = mp_basename(e->filename);
 3425|  2.49k|                    if (s[0])
  ------------------
  |  Branch (3425:25): [True: 1.85k, False: 646]
  ------------------
 3426|  1.85k|                        p = s;
 3427|  2.49k|                }
 3428|  2.97k|            }
 3429|  2.97k|            if (!e->title || p == e->title || mpctx->opts->playlist_entry_name == 1) {
  ------------------
  |  Branch (3429:17): [True: 2.97k, False: 0]
  |  Branch (3429:30): [True: 0, False: 0]
  |  Branch (3429:47): [True: 0, False: 0]
  ------------------
 3430|  2.97k|                res = talloc_asprintf_append(res, "%s%s\n", p, reset);
  ------------------
  |  |   63|  2.97k|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 3431|  2.97k|            } else {
 3432|      0|                res = talloc_asprintf_append(res, "%s (%s)%s\n", e->title, p, reset);
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 3433|      0|            }
 3434|  2.97k|        }
 3435|       |
 3436|    186|        *(char **)arg = cut_osd_list(mpctx, "Playlist", res,
 3437|    186|                                     playlist_entry_to_index(pl, pl->current));
 3438|    186|        return M_PROPERTY_OK;
 3439|    186|    }
 3440|       |
 3441|  2.14k|    return m_property_read_list(action, arg, playlist_entry_count(mpctx->playlist),
 3442|  2.14k|                                get_playlist_entry, mpctx);
 3443|  2.33k|}
command.c:get_playlist_entry:
 3374|  54.9k|{
 3375|  54.9k|    struct MPContext *mpctx = ctx;
 3376|       |
 3377|  54.9k|    struct playlist_entry *e = playlist_entry_from_index(mpctx->playlist, item);
 3378|  54.9k|    if (!e)
  ------------------
  |  Branch (3378:9): [True: 0, False: 54.9k]
  ------------------
 3379|      0|        return M_PROPERTY_ERROR;
 3380|       |
 3381|  54.9k|    bool current = mpctx->playlist->current == e;
 3382|  54.9k|    bool playing = mpctx->playing == e;
 3383|  54.9k|    struct m_sub_property props[] = {
 3384|  54.9k|        {"filename",      SUB_PROP_STR(e->filename)},
  ------------------
  |  |  216|  54.9k|    .type = {.type = CONF_TYPE_STRING}, .value = {.string = (char *)(s)}
  |  |  ------------------
  |  |  |  |  233|  54.9k|#define CONF_TYPE_STRING        (&m_option_type_string)
  |  |  ------------------
  ------------------
 3385|  54.9k|        {"current",       SUB_PROP_BOOL(1), .unavailable = !current},
  ------------------
  |  |  222|  54.9k|    .type = {.type = CONF_TYPE_BOOL}, .value = {.bool_ = (f)}
  |  |  ------------------
  |  |  |  |  227|  54.9k|#define CONF_TYPE_BOOL          (&m_option_type_bool)
  |  |  ------------------
  ------------------
 3386|  54.9k|        {"playing",       SUB_PROP_BOOL(1), .unavailable = !playing},
  ------------------
  |  |  222|  54.9k|    .type = {.type = CONF_TYPE_BOOL}, .value = {.bool_ = (f)}
  |  |  ------------------
  |  |  |  |  227|  54.9k|#define CONF_TYPE_BOOL          (&m_option_type_bool)
  |  |  ------------------
  ------------------
 3387|  54.9k|        {"title",         SUB_PROP_STR(e->title), .unavailable = !e->title},
  ------------------
  |  |  216|  54.9k|    .type = {.type = CONF_TYPE_STRING}, .value = {.string = (char *)(s)}
  |  |  ------------------
  |  |  |  |  233|  54.9k|#define CONF_TYPE_STRING        (&m_option_type_string)
  |  |  ------------------
  ------------------
 3388|  54.9k|        {"id",            SUB_PROP_INT64(e->id)},
  ------------------
  |  |  214|  54.9k|    .type = {.type = CONF_TYPE_INT64}, .value = {.int64 = (i)}
  |  |  ------------------
  |  |  |  |  230|  54.9k|#define CONF_TYPE_INT64         (&m_option_type_int64)
  |  |  ------------------
  ------------------
 3389|  54.9k|        {"playlist-path", SUB_PROP_STR(e->playlist_path), .unavailable = !e->playlist_path},
  ------------------
  |  |  216|  54.9k|    .type = {.type = CONF_TYPE_STRING}, .value = {.string = (char *)(s)}
  |  |  ------------------
  |  |  |  |  233|  54.9k|#define CONF_TYPE_STRING        (&m_option_type_string)
  |  |  ------------------
  ------------------
 3390|  54.9k|        {0}
 3391|  54.9k|    };
 3392|       |
 3393|  54.9k|    return m_property_read_sub(props, action, arg);
 3394|  54.9k|}
command.c:mp_property_playlist_pos:
 3363|      3|{
 3364|      3|    return mp_property_playlist_pos_x(ctx, prop, action, arg, 0);
 3365|      3|}
command.c:mp_property_playlist_pos_x:
 3328|      3|{
 3329|      3|    MPContext *mpctx = ctx;
 3330|      3|    struct playlist *pl = mpctx->playlist;
 3331|       |
 3332|      3|    switch (action) {
  ------------------
  |  Branch (3332:13): [True: 1, False: 2]
  ------------------
 3333|      1|    case M_PROPERTY_GET: {
  ------------------
  |  Branch (3333:5): [True: 1, False: 2]
  ------------------
 3334|      1|        int pos = playlist_entry_to_index(pl, pl->current);
 3335|      1|        *(int *)arg = pos < 0 ? -1 : pos + base;
  ------------------
  |  Branch (3335:23): [True: 1, False: 0]
  ------------------
 3336|      1|        return M_PROPERTY_OK;
 3337|      0|    }
 3338|      0|    case M_PROPERTY_SET: {
  ------------------
  |  Branch (3338:5): [True: 0, False: 3]
  ------------------
 3339|      0|        int pos = *(int *)arg - base;
 3340|      0|        if (pos >= 0 && playlist_entry_to_index(pl, pl->current) == pos)
  ------------------
  |  Branch (3340:13): [True: 0, False: 0]
  |  Branch (3340:25): [True: 0, False: 0]
  ------------------
 3341|      0|            return M_PROPERTY_OK;
 3342|      0|        mp_set_playlist_entry(mpctx, playlist_entry_from_index(pl, pos));
 3343|      0|        return M_PROPERTY_OK;
 3344|      0|    }
 3345|      1|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (3345:5): [True: 1, False: 2]
  ------------------
 3346|      1|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_INT};
  ------------------
  |  |  229|      1|#define CONF_TYPE_INT           (&m_option_type_int)
  ------------------
 3347|      1|        return M_PROPERTY_OK;
 3348|      0|    case M_PROPERTY_GET_CONSTRICTED_TYPE: {
  ------------------
  |  Branch (3348:5): [True: 0, False: 3]
  ------------------
 3349|      0|        struct m_option opt = {
 3350|      0|            .type = CONF_TYPE_INT,
  ------------------
  |  |  229|      0|#define CONF_TYPE_INT           (&m_option_type_int)
  ------------------
 3351|      0|            .min = base,
 3352|      0|            .max = playlist_entry_count(pl) - 1 + base,
 3353|      0|        };
 3354|      0|        *(struct m_option *)arg = opt;
 3355|      0|        return M_PROPERTY_OK;
 3356|      0|    }
 3357|      3|    }
 3358|      1|    return M_PROPERTY_NOT_IMPLEMENTED;
 3359|      3|}
command.c:mp_property_playlist_playing_pos:
 3319|     18|{
 3320|     18|    MPContext *mpctx = ctx;
 3321|     18|    struct playlist *pl = mpctx->playlist;
 3322|     18|    return m_property_int_ro(action, arg,
 3323|     18|                             playlist_entry_to_index(pl, mpctx->playing));
 3324|     18|}
command.c:mp_property_volume:
 1680|     72|{
 1681|     72|    MPContext *mpctx = ctx;
 1682|     72|    struct MPOpts *opts = mpctx->opts;
 1683|       |
 1684|     72|    switch (action) {
  ------------------
  |  Branch (1684:13): [True: 37, False: 35]
  ------------------
 1685|      0|    case M_PROPERTY_GET_CONSTRICTED_TYPE:
  ------------------
  |  Branch (1685:5): [True: 0, False: 72]
  ------------------
 1686|      0|        *(struct m_option *)arg = (struct m_option){
 1687|      0|            .type = CONF_TYPE_FLOAT,
  ------------------
  |  |  231|      0|#define CONF_TYPE_FLOAT         (&m_option_type_float)
  ------------------
 1688|      0|            .min = 0,
 1689|      0|            .max = opts->softvol_max,
 1690|      0|        };
 1691|      0|        return M_PROPERTY_OK;
 1692|     35|    case M_PROPERTY_PRINT:
  ------------------
  |  Branch (1692:5): [True: 35, False: 37]
  ------------------
 1693|     35|        *(char **)arg = talloc_asprintf(NULL, "%.f", opts->softvol_volume);
  ------------------
  |  |   52|     35|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|     35|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 1694|     35|        return M_PROPERTY_OK;
 1695|     72|    }
 1696|       |
 1697|     37|    return mp_property_generic_option(mpctx, prop, action, arg);
 1698|     72|}
command.c:format_delay:
  412|     18|{
  413|     18|    return talloc_asprintf(NULL, "%.f ms", time * 1000);
  ------------------
  |  |   52|     18|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|     18|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  414|     18|}
command.c:mp_property_switch_track:
 1945|    428|{
 1946|    428|    MPContext *mpctx = ctx;
 1947|    428|    const int *def = prop->priv;
 1948|    428|    int order = def[0];
 1949|    428|    enum stream_type type = def[1];
 1950|       |
 1951|    428|    struct track *track = mpctx->current_track[order][type];
 1952|       |
 1953|    428|    switch (action) {
  ------------------
  |  Branch (1953:13): [True: 304, False: 124]
  ------------------
 1954|     34|    case M_PROPERTY_GET:
  ------------------
  |  Branch (1954:5): [True: 34, False: 394]
  ------------------
 1955|     34|        if (mpctx->playback_initialized) {
  ------------------
  |  Branch (1955:13): [True: 0, False: 34]
  ------------------
 1956|      0|            *(int *)arg = track ? track->user_tid : -2;
  ------------------
  |  Branch (1956:27): [True: 0, False: 0]
  ------------------
 1957|     34|        } else {
 1958|     34|            *(int *)arg = mpctx->opts->stream_id[order][type];
 1959|     34|        }
 1960|     34|        return M_PROPERTY_OK;
 1961|     90|    case M_PROPERTY_PRINT:
  ------------------
  |  Branch (1961:5): [True: 90, False: 338]
  ------------------
 1962|     90|        if (track) {
  ------------------
  |  Branch (1962:13): [True: 0, False: 90]
  ------------------
 1963|      0|            void *talloc_ctx = talloc_new(NULL);
  ------------------
  |  |   40|      0|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|      0|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
 1964|      0|            *(char **)arg = talloc_asprintf(NULL, "(%d) %s", track->user_tid,
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 1965|      0|                mp_format_track_metadata(talloc_ctx, track, true));
 1966|      0|            talloc_free(talloc_ctx);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 1967|     90|        } else {
 1968|     90|            const char *msg = "no";
 1969|     90|            if (!mpctx->playback_initialized &&
  ------------------
  |  Branch (1969:17): [True: 90, False: 0]
  ------------------
 1970|     90|                mpctx->opts->stream_id[order][type] == -1)
  ------------------
  |  Branch (1970:17): [True: 72, False: 18]
  ------------------
 1971|     72|                msg = "auto";
 1972|     90|            *(char **) arg = talloc_strdup(NULL, msg);
  ------------------
  |  |   50|     90|#define talloc_strdup                   ta_xstrdup
  ------------------
 1973|     90|        }
 1974|     90|        return M_PROPERTY_OK;
 1975|       |
 1976|      0|    case M_PROPERTY_SWITCH: {
  ------------------
  |  Branch (1976:5): [True: 0, False: 428]
  ------------------
 1977|      0|        if (mpctx->playback_initialized) {
  ------------------
  |  Branch (1977:13): [True: 0, False: 0]
  ------------------
 1978|      0|            struct m_property_switch_arg *sarg = arg;
 1979|      0|            do {
 1980|      0|                track = track_next(mpctx, type, sarg->inc >= 0 ? +1 : -1, track);
  ------------------
  |  Branch (1980:49): [True: 0, False: 0]
  ------------------
 1981|      0|                mp_switch_track_n(mpctx, order, type, track, FLAG_MARK_SELECTION);
  ------------------
  |  |  535|      0|#define FLAG_MARK_SELECTION 1
  ------------------
 1982|      0|            } while (mpctx->current_track[order][type] != track);
  ------------------
  |  Branch (1982:22): [True: 0, False: 0]
  ------------------
 1983|      0|            print_track_list(mpctx, "Track switched:");
 1984|      0|        } else {
 1985|       |            // Simply cycle between "no" and "auto". It's possible that this does
 1986|       |            // not always do what the user means, but keep the complexity low.
 1987|      0|            mark_track_selection(mpctx, order, type,
 1988|      0|                mpctx->opts->stream_id[order][type] == -1 ? -2 : -1);
  ------------------
  |  Branch (1988:17): [True: 0, False: 0]
  ------------------
 1989|      0|        }
 1990|      0|        return M_PROPERTY_OK;
 1991|      0|    }
 1992|    428|    }
 1993|    304|    return mp_property_generic_option(mpctx, prop, action, arg);
 1994|    428|}
command.c:mp_property_audio_device:
 1816|     89|{
 1817|     89|    struct MPContext *mpctx = ctx;
 1818|     89|    struct command_ctx *cmd = mpctx->command_ctx;
 1819|     89|    if (action == M_PROPERTY_PRINT) {
  ------------------
  |  Branch (1819:9): [True: 38, False: 51]
  ------------------
 1820|     38|        create_hotplug(mpctx);
 1821|       |
 1822|     38|        char *name = NULL;
 1823|     38|        if (mp_property_generic_option(mpctx, prop, M_PROPERTY_GET, &name) < 1)
  ------------------
  |  Branch (1823:13): [True: 0, False: 38]
  ------------------
 1824|      0|            name = NULL;
 1825|       |
 1826|     38|        struct ao_device_list *list = ao_hotplug_get_device_list(cmd->hotplug, mpctx->ao);
 1827|     38|        for (int n = 0; n < list->num_devices; n++) {
  ------------------
  |  Branch (1827:25): [True: 38, False: 0]
  ------------------
 1828|     38|            struct ao_device_desc *dev = &list->devices[n];
 1829|     38|            if (dev->name && name && strcmp(dev->name, name) == 0) {
  ------------------
  |  Branch (1829:17): [True: 38, False: 0]
  |  Branch (1829:30): [True: 38, False: 0]
  |  Branch (1829:38): [True: 38, False: 0]
  ------------------
 1830|     38|                *(char **)arg = talloc_strdup(NULL, dev->desc ? dev->desc : "?");
  ------------------
  |  |   50|     38|#define talloc_strdup                   ta_xstrdup
  ------------------
  |  Branch (1830:53): [True: 38, False: 0]
  ------------------
 1831|     38|                talloc_free(name);
  ------------------
  |  |   47|     38|#define talloc_free                     ta_free
  ------------------
 1832|     38|                return M_PROPERTY_OK;
 1833|     38|            }
 1834|     38|        }
 1835|       |
 1836|      0|        talloc_free(name);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 1837|      0|    }
 1838|     51|    return mp_property_generic_option(mpctx, prop, action, arg);
 1839|     89|}
command.c:create_hotplug:
 1805|    148|{
 1806|    148|    struct command_ctx *cmd = mpctx->command_ctx;
 1807|       |
 1808|    148|    if (!cmd->hotplug) {
  ------------------
  |  Branch (1808:9): [True: 21, False: 127]
  ------------------
 1809|     21|        cmd->hotplug = ao_hotplug_create(mpctx->global, mp_wakeup_core_cb,
 1810|     21|                                         mpctx);
 1811|     21|    }
 1812|    148|}
command.c:mp_property_audio_devices:
 1843|    110|{
 1844|    110|    struct MPContext *mpctx = ctx;
 1845|    110|    struct command_ctx *cmd = mpctx->command_ctx;
 1846|    110|    create_hotplug(mpctx);
 1847|       |
 1848|    110|    struct ao_device_list *list = ao_hotplug_get_device_list(cmd->hotplug, mpctx->ao);
 1849|    110|    return m_property_read_list(action, arg, list->num_devices,
 1850|    110|                                get_device_entry, list);
 1851|    110|}
command.c:get_device_entry:
 1791|     91|{
 1792|     91|    struct ao_device_list *list = ctx;
 1793|     91|    struct ao_device_desc *entry = &list->devices[item];
 1794|       |
 1795|     91|    struct m_sub_property props[] = {
 1796|     91|        {"name",        SUB_PROP_STR(entry->name)},
  ------------------
  |  |  216|     91|    .type = {.type = CONF_TYPE_STRING}, .value = {.string = (char *)(s)}
  |  |  ------------------
  |  |  |  |  233|     91|#define CONF_TYPE_STRING        (&m_option_type_string)
  |  |  ------------------
  ------------------
 1797|     91|        {"description", SUB_PROP_STR(entry->desc)},
  ------------------
  |  |  216|     91|    .type = {.type = CONF_TYPE_STRING}, .value = {.string = (char *)(s)}
  |  |  ------------------
  |  |  |  |  233|     91|#define CONF_TYPE_STRING        (&m_option_type_string)
  |  |  ------------------
  ------------------
 1798|     91|        {0}
 1799|     91|    };
 1800|       |
 1801|     91|    return m_property_read_sub(props, action, arg);
 1802|     91|}
command.c:mp_property_tgt_imgparams:
 2533|     18|{
 2534|     18|    MPContext *mpctx = ctx;
 2535|     18|    struct vo *vo = mpctx->video_out;
 2536|     18|    if (!mpctx->video_out)
  ------------------
  |  Branch (2536:9): [True: 18, False: 0]
  ------------------
 2537|     18|        return M_PROPERTY_UNAVAILABLE;
 2538|       |
 2539|      0|    int valid = m_property_read_sub_validate(ctx, prop, action, arg);
 2540|      0|    if (valid != M_PROPERTY_VALID)
  ------------------
  |  Branch (2540:9): [True: 0, False: 0]
  ------------------
 2541|      0|        return valid;
 2542|       |
 2543|      0|    struct mp_image_params p = vo_get_target_params(vo);
 2544|      0|    return property_imgparams(&p, action, arg);
 2545|      0|}
command.c:mp_property_vo_imgparams:
 2517|     18|{
 2518|     18|    MPContext *mpctx = ctx;
 2519|     18|    struct vo *vo = mpctx->video_out;
 2520|     18|    if (!vo)
  ------------------
  |  Branch (2520:9): [True: 18, False: 0]
  ------------------
 2521|     18|        return M_PROPERTY_UNAVAILABLE;
 2522|       |
 2523|      0|    int valid = m_property_read_sub_validate(ctx, prop, action, arg);
 2524|      0|    if (valid != M_PROPERTY_VALID)
  ------------------
  |  Branch (2524:9): [True: 0, False: 0]
  ------------------
 2525|      0|        return valid;
 2526|       |
 2527|      0|    struct mp_image_params p = vo_get_current_params(vo);
 2528|      0|    return property_imgparams(&p, action, arg);
 2529|      0|}
command.c:mp_property_vd_imgparams:
 2568|     19|{
 2569|     19|    MPContext *mpctx = ctx;
 2570|     19|    struct vo_chain *vo_c = mpctx->vo_chain;
 2571|     19|    if (!vo_c)
  ------------------
  |  Branch (2571:9): [True: 19, False: 0]
  ------------------
 2572|     19|        return M_PROPERTY_UNAVAILABLE;
 2573|      0|    struct track *track = mpctx->current_track[0][STREAM_VIDEO];
 2574|      0|    struct mp_codec_params *c =
 2575|      0|        track && track->stream ? track->stream->codec : NULL;
  ------------------
  |  Branch (2575:9): [True: 0, False: 0]
  |  Branch (2575:18): [True: 0, False: 0]
  ------------------
 2576|      0|    if (vo_c->filter->input_params.imgfmt) {
  ------------------
  |  Branch (2576:9): [True: 0, False: 0]
  ------------------
 2577|      0|        return property_imgparams(&vo_c->filter->input_params, action, arg);
 2578|      0|    } else if (c && c->disp_w && c->disp_h) {
  ------------------
  |  Branch (2578:16): [True: 0, False: 0]
  |  Branch (2578:21): [True: 0, False: 0]
  |  Branch (2578:34): [True: 0, False: 0]
  ------------------
 2579|       |        // Simplistic fallback for stupid scripts querying "width"/"height"
 2580|       |        // before the first frame is decoded.
 2581|      0|        struct m_sub_property props[] = {
 2582|      0|            {"w", SUB_PROP_INT(c->disp_w)},
  ------------------
  |  |  212|      0|    .type = {.type = CONF_TYPE_INT}, .value = {.int_ = (i)}
  |  |  ------------------
  |  |  |  |  229|      0|#define CONF_TYPE_INT           (&m_option_type_int)
  |  |  ------------------
  ------------------
 2583|      0|            {"h", SUB_PROP_INT(c->disp_h)},
  ------------------
  |  |  212|      0|    .type = {.type = CONF_TYPE_INT}, .value = {.int_ = (i)}
  |  |  ------------------
  |  |  |  |  229|      0|#define CONF_TYPE_INT           (&m_option_type_int)
  |  |  ------------------
  ------------------
 2584|      0|            {0}
 2585|      0|        };
 2586|      0|        return m_property_read_sub(props, action, arg);
 2587|      0|    }
 2588|      0|    return M_PROPERTY_UNAVAILABLE;
 2589|      0|}
command.c:mp_property_vo_passes:
 2895|     18|{
 2896|     18|    MPContext *mpctx = ctx;
 2897|     18|    if (!mpctx->video_out)
  ------------------
  |  Branch (2897:9): [True: 18, False: 0]
  ------------------
 2898|     18|        return M_PROPERTY_UNAVAILABLE;
 2899|       |
 2900|       |    // Return early, to avoid having to go through a completely unnecessary VOCTRL
 2901|      0|    switch (action) {
 2902|      0|    case M_PROPERTY_PRINT:
  ------------------
  |  Branch (2902:5): [True: 0, False: 0]
  ------------------
 2903|      0|    case M_PROPERTY_GET:
  ------------------
  |  Branch (2903:5): [True: 0, False: 0]
  ------------------
 2904|      0|        break;
 2905|      0|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (2905:5): [True: 0, False: 0]
  ------------------
 2906|      0|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_NODE};
  ------------------
  |  |  241|      0|#define CONF_TYPE_NODE          (&m_option_type_node)
  ------------------
 2907|      0|        return M_PROPERTY_OK;
 2908|      0|    default:
  ------------------
  |  Branch (2908:5): [True: 0, False: 0]
  ------------------
 2909|      0|        return M_PROPERTY_NOT_IMPLEMENTED;
 2910|      0|    }
 2911|       |
 2912|      0|    struct voctrl_performance_data *data = talloc_ptrtype(NULL, data);
  ------------------
  |  |   34|      0|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|      0|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 2913|      0|    if (vo_control(mpctx->video_out, VOCTRL_PERFORMANCE_DATA, data) <= 0) {
  ------------------
  |  Branch (2913:9): [True: 0, False: 0]
  ------------------
 2914|      0|        talloc_free(data);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 2915|      0|        return M_PROPERTY_UNAVAILABLE;
 2916|      0|    }
 2917|       |
 2918|      0|    switch (action) {
  ------------------
  |  Branch (2918:13): [True: 0, False: 0]
  ------------------
 2919|      0|    case M_PROPERTY_PRINT: {
  ------------------
  |  Branch (2919:5): [True: 0, False: 0]
  ------------------
 2920|      0|        char *res = NULL;
 2921|      0|        res = talloc_asprintf_append(res, "fresh:\n");
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 2922|      0|        res = asprint_perf(res, &data->fresh);
 2923|      0|        res = talloc_asprintf_append(res, "\nredraw:\n");
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 2924|      0|        res = asprint_perf(res, &data->redraw);
 2925|      0|        *(char **)arg = res;
 2926|      0|        break;
 2927|      0|    }
 2928|       |
 2929|      0|    case M_PROPERTY_GET: {
  ------------------
  |  Branch (2929:5): [True: 0, False: 0]
  ------------------
 2930|      0|        struct mpv_node node;
 2931|      0|        node_init(&node, MPV_FORMAT_NODE_MAP, NULL);
 2932|      0|        struct mpv_node *fresh = node_map_add(&node, "fresh", MPV_FORMAT_NODE_ARRAY);
 2933|      0|        struct mpv_node *redraw = node_map_add(&node, "redraw", MPV_FORMAT_NODE_ARRAY);
 2934|      0|        get_frame_perf(fresh, &data->fresh);
 2935|      0|        get_frame_perf(redraw, &data->redraw);
 2936|      0|        *(struct mpv_node *)arg = node;
 2937|      0|        break;
 2938|      0|    }
 2939|      0|    }
 2940|       |
 2941|      0|    talloc_free(data);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 2942|      0|    return M_PROPERTY_OK;
 2943|      0|}
command.c:mp_property_gpu_context:
 2970|     20|{
 2971|     20|    MPContext *mpctx = ctx;
 2972|     20|    return m_property_strdup_ro(action, arg, mpctx->video_out ?
  ------------------
  |  Branch (2972:46): [True: 0, False: 20]
  ------------------
 2973|      0|                                mpctx->video_out->context_name : NULL);
 2974|     20|}
command.c:mp_property_video_aspect_override:
 3127|     92|{
 3128|     92|    MPContext *mpctx = ctx;
 3129|     92|    if (action == M_PROPERTY_PRINT) {
  ------------------
  |  Branch (3129:9): [True: 10, False: 82]
  ------------------
 3130|     10|        double aspect_ratio;
 3131|     10|        mp_property_generic_option(mpctx, prop, M_PROPERTY_GET, &aspect_ratio);
 3132|       |
 3133|     10|        if (doubles_equal(aspect_ratio, 2.35 / 1.0))
  ------------------
  |  | 3123|     10|#define doubles_equal(x, y) (fabs((x) - (y)) <= 0.001)
  |  |  ------------------
  |  |  |  Branch (3123:29): [True: 0, False: 10]
  |  |  ------------------
  ------------------
 3134|      0|            *(char **)arg = talloc_asprintf(NULL, "2.35:1");
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 3135|     10|        else if (doubles_equal(aspect_ratio, 16.0 / 9.0))
  ------------------
  |  | 3123|     10|#define doubles_equal(x, y) (fabs((x) - (y)) <= 0.001)
  |  |  ------------------
  |  |  |  Branch (3123:29): [True: 0, False: 10]
  |  |  ------------------
  ------------------
 3136|      0|            *(char **)arg = talloc_asprintf(NULL, "16:9");
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 3137|     10|        else if (doubles_equal(aspect_ratio, 16.0 / 10.0))
  ------------------
  |  | 3123|     10|#define doubles_equal(x, y) (fabs((x) - (y)) <= 0.001)
  |  |  ------------------
  |  |  |  Branch (3123:29): [True: 0, False: 10]
  |  |  ------------------
  ------------------
 3138|      0|            *(char **)arg = talloc_asprintf(NULL, "16:10");
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 3139|     10|        else if (doubles_equal(aspect_ratio, 4.0 / 3.0))
  ------------------
  |  | 3123|     10|#define doubles_equal(x, y) (fabs((x) - (y)) <= 0.001)
  |  |  ------------------
  |  |  |  Branch (3123:29): [True: 0, False: 10]
  |  |  ------------------
  ------------------
 3140|      0|            *(char **)arg = talloc_asprintf(NULL, "4:3");
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 3141|     10|        else if (aspect_ratio < 0.0)
  ------------------
  |  Branch (3141:18): [True: 10, False: 0]
  ------------------
 3142|     10|            *(char **)arg = talloc_asprintf(NULL, "Original");
  ------------------
  |  |   52|     10|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|     10|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 3143|      0|        else
 3144|      0|            *(char **)arg = talloc_asprintf(NULL, "%.3f", aspect_ratio);
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 3145|       |
 3146|     10|        return M_PROPERTY_OK;
 3147|     10|    }
 3148|     82|    return mp_property_generic_option(mpctx, prop, action, arg);
 3149|     92|}
command.c:mp_property_osd_dim:
 2978|    174|{
 2979|    174|    MPContext *mpctx = ctx;
 2980|    174|    struct mp_osd_res vo_res = osd_get_vo_res(mpctx->osd);
 2981|       |
 2982|    174|    if (!mpctx->video_out || !mpctx->video_out->config_ok)
  ------------------
  |  Branch (2982:9): [True: 174, False: 0]
  |  Branch (2982:30): [True: 0, False: 0]
  ------------------
 2983|    174|        vo_res = (struct mp_osd_res){0};
 2984|       |
 2985|    174|    double aspect = 1.0 * vo_res.w / MPMAX(vo_res.h, 1) /
  ------------------
  |  |   43|    174|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 174]
  |  |  ------------------
  ------------------
 2986|    174|                    (vo_res.display_par ? vo_res.display_par : 1);
  ------------------
  |  Branch (2986:22): [True: 0, False: 174]
  ------------------
 2987|       |
 2988|    174|    struct m_sub_property props[] = {
 2989|    174|        {"w",       SUB_PROP_INT(vo_res.w)},
  ------------------
  |  |  212|    174|    .type = {.type = CONF_TYPE_INT}, .value = {.int_ = (i)}
  |  |  ------------------
  |  |  |  |  229|    174|#define CONF_TYPE_INT           (&m_option_type_int)
  |  |  ------------------
  ------------------
 2990|    174|        {"h",       SUB_PROP_INT(vo_res.h)},
  ------------------
  |  |  212|    174|    .type = {.type = CONF_TYPE_INT}, .value = {.int_ = (i)}
  |  |  ------------------
  |  |  |  |  229|    174|#define CONF_TYPE_INT           (&m_option_type_int)
  |  |  ------------------
  ------------------
 2991|    174|        {"par",     SUB_PROP_DOUBLE(vo_res.display_par)},
  ------------------
  |  |  220|    174|    .type = {.type = CONF_TYPE_DOUBLE}, .value = {.double_ = (f)}
  |  |  ------------------
  |  |  |  |  232|    174|#define CONF_TYPE_DOUBLE        (&m_option_type_double)
  |  |  ------------------
  ------------------
 2992|    174|        {"aspect",  SUB_PROP_DOUBLE(aspect)},
  ------------------
  |  |  220|    174|    .type = {.type = CONF_TYPE_DOUBLE}, .value = {.double_ = (f)}
  |  |  ------------------
  |  |  |  |  232|    174|#define CONF_TYPE_DOUBLE        (&m_option_type_double)
  |  |  ------------------
  ------------------
 2993|    174|        {"mt",      SUB_PROP_INT(vo_res.mt)},
  ------------------
  |  |  212|    174|    .type = {.type = CONF_TYPE_INT}, .value = {.int_ = (i)}
  |  |  ------------------
  |  |  |  |  229|    174|#define CONF_TYPE_INT           (&m_option_type_int)
  |  |  ------------------
  ------------------
 2994|    174|        {"mb",      SUB_PROP_INT(vo_res.mb)},
  ------------------
  |  |  212|    174|    .type = {.type = CONF_TYPE_INT}, .value = {.int_ = (i)}
  |  |  ------------------
  |  |  |  |  229|    174|#define CONF_TYPE_INT           (&m_option_type_int)
  |  |  ------------------
  ------------------
 2995|    174|        {"ml",      SUB_PROP_INT(vo_res.ml)},
  ------------------
  |  |  212|    174|    .type = {.type = CONF_TYPE_INT}, .value = {.int_ = (i)}
  |  |  ------------------
  |  |  |  |  229|    174|#define CONF_TYPE_INT           (&m_option_type_int)
  |  |  ------------------
  ------------------
 2996|    174|        {"mr",      SUB_PROP_INT(vo_res.mr)},
  ------------------
  |  |  212|    174|    .type = {.type = CONF_TYPE_INT}, .value = {.int_ = (i)}
  |  |  ------------------
  |  |  |  |  229|    174|#define CONF_TYPE_INT           (&m_option_type_int)
  |  |  ------------------
  ------------------
 2997|    174|        {0}
 2998|    174|    };
 2999|       |
 3000|    174|    return m_property_read_sub(props, action, arg);
 3001|    174|}
command.c:mp_property_osd_sym:
 3005|     35|{
 3006|     35|    MPContext *mpctx = ctx;
 3007|     35|    char temp[20];
 3008|     35|    get_current_osd_sym(mpctx, temp, sizeof(temp));
 3009|     35|    return m_property_strdup_ro(action, arg, temp);
 3010|     35|}
command.c:mp_property_osd_ass:
 3014|     32|{
 3015|     32|    struct m_sub_property props[] = {
 3016|     32|        {"0",   SUB_PROP_STR(OSD_ASS_0)},
  ------------------
  |  |  216|     32|    .type = {.type = CONF_TYPE_STRING}, .value = {.string = (char *)(s)}
  |  |  ------------------
  |  |  |  |  233|     32|#define CONF_TYPE_STRING        (&m_option_type_string)
  |  |  ------------------
  ------------------
 3017|     32|        {"1",   SUB_PROP_STR(OSD_ASS_1)},
  ------------------
  |  |  216|     32|    .type = {.type = CONF_TYPE_STRING}, .value = {.string = (char *)(s)}
  |  |  ------------------
  |  |  |  |  233|     32|#define CONF_TYPE_STRING        (&m_option_type_string)
  |  |  ------------------
  ------------------
 3018|     32|        {0}
 3019|     32|    };
 3020|     32|    return m_property_read_sub(props, action, arg);
 3021|     32|}
command.c:mp_property_term_clip:
 3025|     36|{
 3026|     36|    return m_property_strdup_ro(action, arg, TERM_MSG_0);
  ------------------
  |  |   30|     36|#define TERM_MSG_0 TERM_MSG_ESCAPE "0"
  |  |  ------------------
  |  |  |  |   29|     36|#define TERM_MSG_ESCAPE "\xC2\x92" "t"
  |  |  ------------------
  ------------------
 3027|     36|}
command.c:mp_property_mouse_pos:
 3048|    163|{
 3049|    163|    MPContext *mpctx = ctx;
 3050|       |
 3051|    163|    switch (action) {
  ------------------
  |  Branch (3051:13): [True: 41, False: 122]
  ------------------
 3052|     61|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (3052:5): [True: 61, False: 102]
  ------------------
 3053|     61|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_NODE};
  ------------------
  |  |  241|     61|#define CONF_TYPE_NODE          (&m_option_type_node)
  ------------------
 3054|     61|        return M_PROPERTY_OK;
 3055|       |
 3056|     61|    case M_PROPERTY_GET: {
  ------------------
  |  Branch (3056:5): [True: 61, False: 102]
  ------------------
 3057|     61|        struct mpv_node node;
 3058|     61|        int x, y, hover;
 3059|     61|        mp_input_get_mouse_pos(mpctx->input, &x, &y, &hover);
 3060|       |
 3061|     61|        node_init(&node, MPV_FORMAT_NODE_MAP, NULL);
 3062|     61|        node_map_add_int64(&node, "x", x);
 3063|     61|        node_map_add_int64(&node, "y", y);
 3064|     61|        node_map_add_flag(&node, "hover", hover);
 3065|     61|        *(struct mpv_node *)arg = node;
 3066|       |
 3067|     61|        return M_PROPERTY_OK;
 3068|      0|    }
 3069|    163|    }
 3070|       |
 3071|     41|    return M_PROPERTY_NOT_IMPLEMENTED;
 3072|    163|}
command.c:mp_property_touch_pos:
 3091|     40|{
 3092|     40|    MPContext *mpctx = ctx;
 3093|     40|    int xs[MAX_TOUCH_POINTS], ys[MAX_TOUCH_POINTS], ids[MAX_TOUCH_POINTS];
 3094|     40|    int count = mp_input_get_touch_pos(mpctx->input, MAX_TOUCH_POINTS, xs, ys, ids);
  ------------------
  |  | 3088|     40|#define MAX_TOUCH_POINTS 10
  ------------------
 3095|     40|    const int *pos[3] = {xs, ys, ids};
 3096|     40|    return m_property_read_list(action, arg, MPMIN(MAX_TOUCH_POINTS, count),
  ------------------
  |  |   44|     40|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 40, False: 0]
  |  |  ------------------
  ------------------
 3097|     40|                                get_touch_pos, (void *)pos);
 3098|     40|}
command.c:mp_property_sub_delay:
 3154|     40|{
 3155|     40|    MPContext *mpctx = ctx;
 3156|     40|    struct MPOpts *opts = mpctx->opts;
 3157|     40|    int track_ind = *(int *)prop->priv;
 3158|     40|    switch (action) {
  ------------------
  |  Branch (3158:13): [True: 22, False: 18]
  ------------------
 3159|     18|    case M_PROPERTY_PRINT:
  ------------------
  |  Branch (3159:5): [True: 18, False: 22]
  ------------------
 3160|     18|        *(char **)arg = format_delay(opts->subs_shared->sub_delay[track_ind]);
 3161|     18|        return M_PROPERTY_OK;
 3162|     40|    }
 3163|     22|    return mp_property_generic_option(mpctx, prop, action, arg);
 3164|     40|}
command.c:mp_property_sub_speed:
 3169|     78|{
 3170|     78|    MPContext *mpctx = ctx;
 3171|     78|    struct MPOpts *opts = mpctx->opts;
 3172|     78|    if (action == M_PROPERTY_PRINT) {
  ------------------
  |  Branch (3172:9): [True: 19, False: 59]
  ------------------
 3173|     19|        *(char **)arg =
 3174|     19|            talloc_asprintf(NULL, "%4.1f%%", 100 * opts->subs_rend->sub_speed);
  ------------------
  |  |   52|     19|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|     19|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 3175|     19|        return M_PROPERTY_OK;
 3176|     19|    }
 3177|     59|    return mp_property_generic_option(mpctx, prop, action, arg);
 3178|     78|}
command.c:mp_property_sub_pos:
 3182|    112|{
 3183|    112|    MPContext *mpctx = ctx;
 3184|    112|    struct MPOpts *opts = mpctx->opts;
 3185|    112|    int track_ind = *(int *)prop->priv;
 3186|    112|    if (action == M_PROPERTY_PRINT || action == M_PROPERTY_FIXED_LEN_PRINT) {
  ------------------
  |  Branch (3186:9): [True: 21, False: 91]
  |  Branch (3186:39): [True: 18, False: 73]
  ------------------
 3187|     39|        *(char **)arg = mp_format_double(NULL, opts->subs_shared->sub_pos[track_ind], 2,
 3188|     39|                                         false, true, action != M_PROPERTY_FIXED_LEN_PRINT);
 3189|     39|        return M_PROPERTY_OK;
 3190|     39|    }
 3191|     73|    return mp_property_generic_option(mpctx, prop, action, arg);
 3192|    112|}
command.c:mp_property_sub_text:
 3219|     71|{
 3220|     71|    MPContext *mpctx = ctx;
 3221|     71|    const int *def = prop->priv;
 3222|     71|    int sub_index = def[0];
 3223|     71|    int type = def[1];
 3224|       |
 3225|     71|    if (action == M_PROPERTY_KEY_ACTION) {
  ------------------
  |  Branch (3225:9): [True: 53, False: 18]
  ------------------
 3226|     53|        struct m_property_action_arg *ka = arg;
 3227|       |
 3228|     53|        if (!strcmp(ka->key, "ass"))
  ------------------
  |  Branch (3228:13): [True: 18, False: 35]
  ------------------
 3229|     18|            type = SD_TEXT_TYPE_ASS;
 3230|     35|        else if (!strcmp(ka->key, "ass-full"))
  ------------------
  |  Branch (3230:18): [True: 0, False: 35]
  ------------------
 3231|      0|            type = SD_TEXT_TYPE_ASS_FULL;
 3232|     35|        else
 3233|     35|            return M_PROPERTY_UNKNOWN;
 3234|       |
 3235|     18|        action = ka->action;
 3236|     18|        arg = ka->arg;
 3237|     18|    }
 3238|       |
 3239|     36|    struct track *track = mpctx->current_track[sub_index][STREAM_SUB];
 3240|     36|    struct dec_sub *sub = track ? track->d_sub : NULL;
  ------------------
  |  Branch (3240:27): [True: 0, False: 36]
  ------------------
 3241|     36|    double pts = mpctx->playback_pts;
 3242|     36|    if (!sub || pts == MP_NOPTS_VALUE)
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (3242:9): [True: 36, False: 0]
  |  Branch (3242:17): [True: 0, False: 0]
  ------------------
 3243|     36|        return M_PROPERTY_UNAVAILABLE;
 3244|       |
 3245|      0|    switch (action) {
  ------------------
  |  Branch (3245:13): [True: 0, False: 0]
  ------------------
 3246|      0|    case M_PROPERTY_GET: {
  ------------------
  |  Branch (3246:5): [True: 0, False: 0]
  ------------------
 3247|      0|        char *text = sub_get_text(sub, pts, type);
 3248|      0|        if (!text)
  ------------------
  |  Branch (3248:13): [True: 0, False: 0]
  ------------------
 3249|      0|            text = talloc_strdup(NULL, "");
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
 3250|      0|        *(char **)arg = text;
 3251|      0|        return M_PROPERTY_OK;
 3252|      0|    }
 3253|      0|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (3253:5): [True: 0, False: 0]
  ------------------
 3254|      0|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_STRING};
  ------------------
  |  |  233|      0|#define CONF_TYPE_STRING        (&m_option_type_string)
  ------------------
 3255|      0|        return M_PROPERTY_OK;
 3256|      0|    }
 3257|      0|    return M_PROPERTY_NOT_IMPLEMENTED;
 3258|      0|}
command.c:mp_property_sub_start:
 3276|     18|{
 3277|     18|    double start = get_times(ctx, prop, action, arg).start;
 3278|     18|    if (start == MP_NOPTS_VALUE)
  ------------------
  |  |   38|     18|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (3278:9): [True: 18, False: 0]
  ------------------
 3279|     18|        return M_PROPERTY_UNAVAILABLE;
 3280|      0|    return property_time(action, arg, start);
 3281|     18|}
command.c:get_times:
 3262|     36|{
 3263|     36|    struct sd_times res = { .start = MP_NOPTS_VALUE, .end = MP_NOPTS_VALUE };
  ------------------
  |  |   38|     36|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
                  struct sd_times res = { .start = MP_NOPTS_VALUE, .end = MP_NOPTS_VALUE };
  ------------------
  |  |   38|     36|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
 3264|     36|    MPContext *mpctx = ctx;
 3265|     36|    int track_ind = *(int *)prop->priv;
 3266|     36|    struct track *track = mpctx->current_track[track_ind][STREAM_SUB];
 3267|     36|    struct dec_sub *sub = track ? track->d_sub : NULL;
  ------------------
  |  Branch (3267:27): [True: 0, False: 36]
  ------------------
 3268|     36|    double pts = mpctx->playback_pts;
 3269|     36|    if (!sub || pts == MP_NOPTS_VALUE)
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (3269:9): [True: 36, False: 0]
  |  Branch (3269:17): [True: 0, False: 0]
  ------------------
 3270|     36|        return res;
 3271|      0|    return sub_get_times(sub, pts);
 3272|     36|}
command.c:mp_property_sub_end:
 3286|     18|{
 3287|     18|    double end = get_times(ctx, prop, action, arg).end;
 3288|     18|    if (end == MP_NOPTS_VALUE)
  ------------------
  |  |   38|     18|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (3288:9): [True: 18, False: 0]
  ------------------
 3289|     18|        return M_PROPERTY_UNAVAILABLE;
 3290|      0|    return property_time(action, arg, end);
 3291|     18|}
command.c:mp_property_vf:
 3479|    243|{
 3480|    243|    return property_filter(prop, action, arg, ctx, STREAM_VIDEO);
 3481|    243|}
command.c:property_filter:
 3467|    585|{
 3468|    585|    if (action == M_PROPERTY_PRINT) {
  ------------------
  |  Branch (3468:9): [True: 104, False: 481]
  ------------------
 3469|    104|        struct m_config_option *opt = m_config_get_co(mpctx->mconfig,
 3470|    104|                                                      bstr0(prop->name));
 3471|    104|        *(char **)arg = print_obj_osd_list(*(struct m_obj_settings **)opt->data);
 3472|    104|        return M_PROPERTY_OK;
 3473|    104|    }
 3474|    481|    return mp_property_generic_option(mpctx, prop, action, arg);
 3475|    585|}
command.c:print_obj_osd_list:
 3446|    104|{
 3447|    104|    char *res = NULL;
 3448|    181|    for (int n = 0; list && list[n].name; n++) {
  ------------------
  |  Branch (3448:21): [True: 154, False: 27]
  |  Branch (3448:29): [True: 77, False: 77]
  ------------------
 3449|     77|        res = talloc_asprintf_append(res, "%s [", list[n].name);
  ------------------
  |  |   63|     77|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 3450|    169|        for (int i = 0; list[n].attribs && list[n].attribs[i]; i += 2) {
  ------------------
  |  Branch (3450:25): [True: 149, False: 20]
  |  Branch (3450:44): [True: 92, False: 57]
  ------------------
 3451|     92|            res = talloc_asprintf_append(res, "%s%s=%s", i > 0 ? " " : "",
  ------------------
  |  |   63|     92|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
  |  Branch (3451:58): [True: 35, False: 57]
  ------------------
 3452|     92|                                         list[n].attribs[i],
 3453|     92|                                         list[n].attribs[i + 1]);
 3454|     92|        }
 3455|     77|        res = talloc_asprintf_append(res, "]");
  ------------------
  |  |   63|     77|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
 3456|     77|        if (!list[n].enabled)
  ------------------
  |  Branch (3456:13): [True: 18, False: 59]
  ------------------
 3457|     18|            res = talloc_strdup_append(res, " (disabled)");
  ------------------
  |  |   57|     18|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
 3458|     77|        res = talloc_strdup_append(res, "\n");
  ------------------
  |  |   57|     77|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
 3459|     77|    }
 3460|    104|    if (!res)
  ------------------
  |  Branch (3460:9): [True: 28, False: 76]
  ------------------
 3461|     28|        res = talloc_strdup(NULL, "(empty)");
  ------------------
  |  |   50|     28|#define talloc_strdup                   ta_xstrdup
  ------------------
 3462|    104|    return res;
 3463|    104|}
command.c:mp_property_af:
 3485|    342|{
 3486|    342|    return property_filter(prop, action, arg, ctx, STREAM_AUDIO);
 3487|    342|}
command.c:mp_property_ab_loop:
 3491|    368|{
 3492|    368|    struct MPContext *mpctx = ctx;
 3493|    368|    if (action == M_PROPERTY_KEY_ACTION) {
  ------------------
  |  Branch (3493:9): [True: 48, False: 320]
  ------------------
 3494|     48|        double val;
 3495|     48|        if (mp_property_generic_option(mpctx, prop, M_PROPERTY_GET, &val) < 1)
  ------------------
  |  Branch (3495:13): [True: 0, False: 48]
  ------------------
 3496|      0|            return M_PROPERTY_ERROR;
 3497|       |
 3498|     48|        return property_time(action, arg, val);
 3499|     48|    }
 3500|    320|    return mp_property_generic_option(mpctx, prop, action, arg);
 3501|    368|}
command.c:mp_property_packet_bitrate:
 3505|     18|{
 3506|     18|    MPContext *mpctx = ctx;
 3507|     18|    int type = *(int *)prop->priv;
 3508|       |
 3509|     18|    struct demuxer *demuxer = NULL;
 3510|     18|    if (mpctx->current_track[0][type])
  ------------------
  |  Branch (3510:9): [True: 0, False: 18]
  ------------------
 3511|      0|        demuxer = mpctx->current_track[0][type]->demuxer;
 3512|     18|    if (!demuxer)
  ------------------
  |  Branch (3512:9): [True: 18, False: 0]
  ------------------
 3513|     18|        demuxer = mpctx->demuxer;
 3514|     18|    if (!demuxer)
  ------------------
  |  Branch (3514:9): [True: 18, False: 0]
  ------------------
 3515|     18|        return M_PROPERTY_UNAVAILABLE;
 3516|       |
 3517|      0|    double r[STREAM_TYPE_COUNT];
 3518|      0|    demux_get_bitrate_stats(demuxer, r);
 3519|      0|    if (r[type] < 0)
  ------------------
  |  Branch (3519:9): [True: 0, False: 0]
  ------------------
 3520|      0|        return M_PROPERTY_UNAVAILABLE;
 3521|       |
 3522|       |    // r[type] is in bytes/second -> bits
 3523|      0|    double rate = r[type] * 8;
 3524|       |
 3525|      0|    if (action == M_PROPERTY_PRINT) {
  ------------------
  |  Branch (3525:9): [True: 0, False: 0]
  ------------------
 3526|      0|        rate /= 1000;
 3527|      0|        if (rate < 1000) {
  ------------------
  |  Branch (3527:13): [True: 0, False: 0]
  ------------------
 3528|      0|            *(char **)arg = talloc_asprintf(NULL, "%.f kbps", rate);
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 3529|      0|        } else {
 3530|      0|            *(char **)arg = talloc_asprintf(NULL, "%.3f Mbps", rate / 1000.0);
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
 3531|      0|        }
 3532|      0|        return M_PROPERTY_OK;
 3533|      0|    }
 3534|      0|    return m_property_int64_ro(action, arg, llrint(rate));
 3535|      0|}
command.c:mp_property_focused:
 2819|     18|{
 2820|     18|    MPContext *mpctx = ctx;
 2821|     18|    struct vo *vo = mpctx->video_out;
 2822|     18|    if (!vo)
  ------------------
  |  Branch (2822:9): [True: 18, False: 0]
  ------------------
 2823|     18|        return M_PROPERTY_UNAVAILABLE;
 2824|       |
 2825|      0|    bool focused;
 2826|      0|    if (vo_control(vo, VOCTRL_GET_FOCUSED, &focused) < 1)
  ------------------
  |  Branch (2826:9): [True: 0, False: 0]
  ------------------
 2827|      0|        return M_PROPERTY_UNAVAILABLE;
 2828|       |
 2829|      0|    return m_property_bool_ro(action, arg, focused);
 2830|      0|}
command.c:mp_property_display_fps:
 2708|    114|{
 2709|    114|    MPContext *mpctx = ctx;
 2710|    114|    double fps = mpctx->video_out ? vo_get_display_fps(mpctx->video_out) : 0;
  ------------------
  |  Branch (2710:18): [True: 0, False: 114]
  ------------------
 2711|    114|    switch (action) {
  ------------------
  |  Branch (2711:13): [True: 38, False: 76]
  ------------------
 2712|     38|    case M_PROPERTY_GET:
  ------------------
  |  Branch (2712:5): [True: 38, False: 76]
  ------------------
 2713|     38|        if (fps <= 0)
  ------------------
  |  Branch (2713:13): [True: 38, False: 0]
  ------------------
 2714|     38|            return M_PROPERTY_UNAVAILABLE;
 2715|      0|        return m_property_double_ro(action, arg, fps);
 2716|     38|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (2716:5): [True: 38, False: 76]
  ------------------
 2717|     38|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_DOUBLE};
  ------------------
  |  |  232|     38|#define CONF_TYPE_DOUBLE        (&m_option_type_double)
  ------------------
 2718|     38|        return M_PROPERTY_OK;
 2719|    114|    }
 2720|     38|    return M_PROPERTY_NOT_IMPLEMENTED;
 2721|    114|}
command.c:mp_property_estimated_display_fps:
 2725|     18|{
 2726|     18|    MPContext *mpctx = ctx;
 2727|     18|    struct vo *vo = mpctx->video_out;
 2728|     18|    if (!vo)
  ------------------
  |  Branch (2728:9): [True: 18, False: 0]
  ------------------
 2729|     18|        return M_PROPERTY_UNAVAILABLE;
 2730|      0|    double interval = vo_get_estimated_vsync_interval(vo) / 1e9;
 2731|      0|    if (interval <= 0)
  ------------------
  |  Branch (2731:9): [True: 0, False: 0]
  ------------------
 2732|      0|        return M_PROPERTY_UNAVAILABLE;
 2733|      0|    return m_property_double_ro(action, arg, 1.0 / interval);
 2734|      0|}
command.c:mp_property_vsync_jitter:
 2738|     19|{
 2739|     19|    MPContext *mpctx = ctx;
 2740|     19|    struct vo *vo = mpctx->video_out;
 2741|     19|    if (!vo)
  ------------------
  |  Branch (2741:9): [True: 19, False: 0]
  ------------------
 2742|     19|        return M_PROPERTY_UNAVAILABLE;
 2743|      0|    double stddev = vo_get_estimated_vsync_jitter(vo);
 2744|      0|    if (stddev < 0)
  ------------------
  |  Branch (2744:9): [True: 0, False: 0]
  ------------------
 2745|      0|        return M_PROPERTY_UNAVAILABLE;
 2746|      0|    return m_property_double_ro(action, arg, stddev);
 2747|      0|}
command.c:mp_property_protocols:
 3564|     60|{
 3565|     60|    switch (action) {
  ------------------
  |  Branch (3565:13): [True: 20, False: 40]
  ------------------
 3566|     20|    case M_PROPERTY_GET:
  ------------------
  |  Branch (3566:5): [True: 20, False: 40]
  ------------------
 3567|     20|        *(char ***)arg = stream_get_proto_list(false);
 3568|     20|        return M_PROPERTY_OK;
 3569|     20|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (3569:5): [True: 20, False: 40]
  ------------------
 3570|     20|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_STRING_LIST};
  ------------------
  |  |  234|     20|#define CONF_TYPE_STRING_LIST   (&m_option_type_string_list)
  ------------------
 3571|     20|        return M_PROPERTY_OK;
 3572|     60|    }
 3573|     20|    return M_PROPERTY_NOT_IMPLEMENTED;
 3574|     60|}
command.c:mp_property_decoders:
 3607|  2.57k|{
 3608|  2.57k|    struct mp_decoder_list *codecs = talloc_zero(NULL, struct mp_decoder_list);
  ------------------
  |  |   27|  2.57k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  2.57k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  2.57k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 3609|  2.57k|    struct mp_decoder_list *v = talloc_steal(codecs, video_decoder_list());
  ------------------
  |  |   38|  2.57k|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|  2.57k|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 3610|  2.57k|    struct mp_decoder_list *a = talloc_steal(codecs, audio_decoder_list());
  ------------------
  |  |   38|  2.57k|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|  2.57k|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 3611|  2.57k|    mp_append_decoders(codecs, v);
 3612|  2.57k|    mp_append_decoders(codecs, a);
 3613|  2.57k|    int r = m_property_read_list(action, arg, codecs->num_entries,
 3614|  2.57k|                                 get_decoder_entry, codecs);
 3615|  2.57k|    talloc_free(codecs);
  ------------------
  |  |   47|  2.57k|#define talloc_free                     ta_free
  ------------------
 3616|  2.57k|    return r;
 3617|  2.57k|}
command.c:get_decoder_entry:
 3591|  1.55M|{
 3592|  1.55M|    struct mp_decoder_list *codecs = ctx;
 3593|  1.55M|    struct mp_decoder_entry *c = &codecs->entries[item];
 3594|       |
 3595|  1.55M|    struct m_sub_property props[] = {
 3596|  1.55M|        {"codec",       SUB_PROP_STR(c->codec)},
  ------------------
  |  |  216|  1.55M|    .type = {.type = CONF_TYPE_STRING}, .value = {.string = (char *)(s)}
  |  |  ------------------
  |  |  |  |  233|  1.55M|#define CONF_TYPE_STRING        (&m_option_type_string)
  |  |  ------------------
  ------------------
 3597|  1.55M|        {"driver" ,     SUB_PROP_STR(c->decoder)},
  ------------------
  |  |  216|  1.55M|    .type = {.type = CONF_TYPE_STRING}, .value = {.string = (char *)(s)}
  |  |  ------------------
  |  |  |  |  233|  1.55M|#define CONF_TYPE_STRING        (&m_option_type_string)
  |  |  ------------------
  ------------------
 3598|  1.55M|        {"description", SUB_PROP_STR(c->desc)},
  ------------------
  |  |  216|  1.55M|    .type = {.type = CONF_TYPE_STRING}, .value = {.string = (char *)(s)}
  |  |  ------------------
  |  |  |  |  233|  1.55M|#define CONF_TYPE_STRING        (&m_option_type_string)
  |  |  ------------------
  ------------------
 3599|  1.55M|        {0}
 3600|  1.55M|    };
 3601|       |
 3602|  1.55M|    return m_property_read_sub(props, action, arg);
 3603|  1.55M|}
command.c:mp_property_lavf_demuxers:
 3632|    198|{
 3633|    198|    switch (action) {
  ------------------
  |  Branch (3633:13): [True: 68, False: 130]
  ------------------
 3634|     65|    case M_PROPERTY_GET:
  ------------------
  |  Branch (3634:5): [True: 65, False: 133]
  ------------------
 3635|     65|        *(char ***)arg = mp_get_lavf_demuxers();
 3636|     65|        return M_PROPERTY_OK;
 3637|     65|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (3637:5): [True: 65, False: 133]
  ------------------
 3638|     65|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_STRING_LIST};
  ------------------
  |  |  234|     65|#define CONF_TYPE_STRING_LIST   (&m_option_type_string_list)
  ------------------
 3639|     65|        return M_PROPERTY_OK;
 3640|    198|    }
 3641|     68|    return M_PROPERTY_NOT_IMPLEMENTED;
 3642|    198|}
command.c:mp_property_keylist:
 3578|    219|{
 3579|    219|    switch (action) {
  ------------------
  |  Branch (3579:13): [True: 75, False: 144]
  ------------------
 3580|     72|    case M_PROPERTY_GET:
  ------------------
  |  Branch (3580:5): [True: 72, False: 147]
  ------------------
 3581|     72|        *(char ***)arg = mp_get_key_list();
 3582|     72|        return M_PROPERTY_OK;
 3583|     72|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (3583:5): [True: 72, False: 147]
  ------------------
 3584|     72|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_STRING_LIST};
  ------------------
  |  |  234|     72|#define CONF_TYPE_STRING_LIST   (&m_option_type_string_list)
  ------------------
 3585|     72|        return M_PROPERTY_OK;
 3586|    219|    }
 3587|     75|    return M_PROPERTY_NOT_IMPLEMENTED;
 3588|    219|}
command.c:mp_property_ffmpeg:
 3658|     72|{
 3659|     72|    return m_property_strdup_ro(action, arg, av_version_info());
 3660|     72|}
command.c:mp_property_libass_version:
 3664|     72|{
 3665|     72|    return m_property_int64_ro(action, arg, ass_library_version());
 3666|     72|}
command.c:mp_property_platform:
 3670|     40|{
 3671|     40|    return m_property_strdup_ro(action, arg, PLATFORM);
  ------------------
  |  |  266|     40|#define PLATFORM "linux"
  ------------------
 3672|     40|}
command.c:mp_property_options:
 3747|  15.9k|{
 3748|  15.9k|    MPContext *mpctx = ctx;
 3749|  15.9k|    return access_option_list(action, arg, false, mpctx);
 3750|  15.9k|}
command.c:access_option_list:
 3730|  15.9k|{
 3731|  15.9k|    switch (action) {
  ------------------
  |  Branch (3731:13): [True: 5.25k, False: 10.6k]
  ------------------
 3732|  5.26k|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (3732:5): [True: 5.26k, False: 10.6k]
  ------------------
 3733|  5.26k|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_STRING_LIST};
  ------------------
  |  |  234|  5.26k|#define CONF_TYPE_STRING_LIST   (&m_option_type_string_list)
  ------------------
 3734|  5.26k|        return M_PROPERTY_OK;
 3735|  5.26k|    case M_PROPERTY_GET:
  ------------------
  |  Branch (3735:5): [True: 5.26k, False: 10.6k]
  ------------------
 3736|  5.26k|        *(char ***)arg = m_config_list_options(NULL, mpctx->mconfig);
 3737|  5.26k|        return M_PROPERTY_OK;
 3738|    148|    case M_PROPERTY_KEY_ACTION:
  ------------------
  |  Branch (3738:5): [True: 148, False: 15.7k]
  ------------------
 3739|    148|        return access_options(arg, local, mpctx);
 3740|  15.9k|    }
 3741|  5.25k|    return M_PROPERTY_NOT_IMPLEMENTED;
 3742|  15.9k|}
command.c:access_options:
 3702|    148|{
 3703|    148|    struct m_config_option *opt = m_config_get_co(mpctx->mconfig,
 3704|    148|                                                  bstr0(ka->key));
 3705|    148|    if (!opt)
  ------------------
  |  Branch (3705:9): [True: 22, False: 126]
  ------------------
 3706|     22|        return M_PROPERTY_UNKNOWN;
 3707|    126|    if (!opt->data)
  ------------------
  |  Branch (3707:9): [True: 18, False: 108]
  ------------------
 3708|     18|        return M_PROPERTY_UNAVAILABLE;
 3709|       |
 3710|    108|    switch (ka->action) {
  ------------------
  |  Branch (3710:13): [True: 36, False: 72]
  ------------------
 3711|     36|    case M_PROPERTY_GET:
  ------------------
  |  Branch (3711:5): [True: 36, False: 72]
  ------------------
 3712|     36|        m_option_copy(opt->opt, ka->arg, opt->data);
 3713|     36|        return M_PROPERTY_OK;
 3714|      0|    case M_PROPERTY_SET: {
  ------------------
  |  Branch (3714:5): [True: 0, False: 108]
  ------------------
 3715|      0|        if (local && !mpctx->playing)
  ------------------
  |  Branch (3715:13): [True: 0, False: 0]
  |  Branch (3715:22): [True: 0, False: 0]
  ------------------
 3716|      0|            return M_PROPERTY_ERROR;
 3717|      0|        int flags = local ? M_SETOPT_BACKUP : 0;
  ------------------
  |  Branch (3717:21): [True: 0, False: 0]
  ------------------
 3718|      0|        int r = m_config_set_option_raw(mpctx->mconfig, opt, ka->arg, flags);
 3719|      0|        mp_wakeup_core(mpctx);
 3720|      0|        return r < 0 ? M_PROPERTY_ERROR : M_PROPERTY_OK;
  ------------------
  |  Branch (3720:16): [True: 0, False: 0]
  ------------------
 3721|      0|    }
 3722|     36|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (3722:5): [True: 36, False: 72]
  ------------------
 3723|     36|        *(struct m_option *)ka->arg = *opt->opt;
 3724|     36|        return M_PROPERTY_OK;
 3725|    108|    }
 3726|     36|    return M_PROPERTY_NOT_IMPLEMENTED;
 3727|    108|}
command.c:mp_profile_list:
 3862|    188|{
 3863|    188|    MPContext *mpctx = ctx;
 3864|    188|    switch (action) {
  ------------------
  |  Branch (3864:13): [True: 62, False: 126]
  ------------------
 3865|     63|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (3865:5): [True: 63, False: 125]
  ------------------
 3866|     63|        *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_NODE};
  ------------------
  |  |  241|     63|#define CONF_TYPE_NODE          (&m_option_type_node)
  ------------------
 3867|     63|        return M_PROPERTY_OK;
 3868|     63|    case M_PROPERTY_GET: {
  ------------------
  |  Branch (3868:5): [True: 63, False: 125]
  ------------------
 3869|     63|        *(struct mpv_node *)arg = m_config_get_profiles(mpctx->mconfig);
 3870|     63|        return M_PROPERTY_OK;
 3871|      0|    }
 3872|    188|    }
 3873|     62|    return M_PROPERTY_NOT_IMPLEMENTED;
 3874|    188|}
command.c:str_compare:
 7558|   111M|{
 7559|   111M|    return strcmp(*(const char **)a, *(const char **)b);
 7560|   111M|}
command.c:mp_property_generic_option:
  419|  2.80k|{
  420|  2.80k|    MPContext *mpctx = ctx;
  421|  2.80k|    struct m_config_option *opt =
  422|  2.80k|        m_config_get_co(mpctx->mconfig, bstr0(prop->name));
  423|       |
  424|  2.80k|    if (!opt)
  ------------------
  |  Branch (424:9): [True: 0, False: 2.80k]
  ------------------
  425|      0|        return M_PROPERTY_UNKNOWN;
  426|       |
  427|  2.80k|    switch (action) {
  ------------------
  |  Branch (427:13): [True: 568, False: 2.23k]
  ------------------
  428|  1.41k|    case M_PROPERTY_GET_TYPE:
  ------------------
  |  Branch (428:5): [True: 1.41k, False: 1.39k]
  ------------------
  429|  1.41k|        *(struct m_option *)arg = *(opt->opt);
  430|  1.41k|        return M_PROPERTY_OK;
  431|    822|    case M_PROPERTY_GET:
  ------------------
  |  Branch (431:5): [True: 822, False: 1.98k]
  ------------------
  432|    822|        if (!opt->data)
  ------------------
  |  Branch (432:13): [True: 37, False: 785]
  ------------------
  433|     37|            return M_PROPERTY_NOT_IMPLEMENTED;
  434|    785|        m_option_copy(opt->opt, arg, opt->data);
  435|    785|        return M_PROPERTY_OK;
  436|      0|    case M_PROPERTY_SET:
  ------------------
  |  Branch (436:5): [True: 0, False: 2.80k]
  ------------------
  437|      0|        opt->coalesce = prop->coalesce;
  438|      0|        if (m_config_set_option_raw(mpctx->mconfig, opt, arg, 0) < 0)
  ------------------
  |  Branch (438:13): [True: 0, False: 0]
  ------------------
  439|      0|            return M_PROPERTY_ERROR;
  440|      0|        return M_PROPERTY_OK;
  441|  2.80k|    }
  442|    568|    return M_PROPERTY_NOT_IMPLEMENTED;
  443|  2.80k|}
command.c:mp_property_deprecated_alias:
 3683|     76|{
 3684|     76|    MPContext *mpctx = ctx;
 3685|     76|    struct command_ctx *cmd = mpctx->command_ctx;
 3686|     76|    const char *real_property = prop->priv;
 3687|     76|    for (int n = 0; n < cmd->num_warned_deprecated; n++) {
  ------------------
  |  Branch (3687:21): [True: 66, False: 10]
  ------------------
 3688|     66|        if (strcmp(cmd->warned_deprecated[n], prop->name) == 0)
  ------------------
  |  Branch (3688:13): [True: 66, False: 0]
  ------------------
 3689|     66|            goto done;
 3690|     66|    }
 3691|     10|    MP_WARN(mpctx, "Warning: property '%s' was replaced with '%s' and "
  ------------------
  |  |   86|     10|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     10|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 3692|     10|            "might be removed in the future.\n", prop->name, real_property);
 3693|     10|    MP_TARRAY_APPEND(cmd, cmd->warned_deprecated, cmd->num_warned_deprecated,
  ------------------
  |  |  105|     10|    do {                                            \
  |  |  106|     10|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|     10|    do {                                            \
  |  |  |  |   97|     10|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|     10|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|     10|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|     10|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 10, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|     10|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|     10|    do {                                                        \
  |  |  |  |  |  |   89|     10|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|     10|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|     10|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|     10|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|     10|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|     10|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|     10|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|     10|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|     10|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|     10|        (idxvar)++;                                 \
  |  |  109|     10|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 3694|     10|                     (char *)prop->name);
 3695|       |
 3696|     76|done:
 3697|     76|    return mp_property_do(real_property, action, arg, ctx);
 3698|     10|}
command.c:mp_property_alias:
 3676|    294|{
 3677|    294|    const char *real_property = prop->priv;
 3678|    294|    return mp_property_do(real_property, action, arg, ctx);
 3679|    294|}
command.c:command_event:
 7633|  29.0k|{
 7634|  29.0k|    struct command_ctx *ctx = mpctx->command_ctx;
 7635|       |
 7636|  29.0k|    if (event == MPV_EVENT_START_FILE) {
  ------------------
  |  Branch (7636:9): [True: 3.93k, False: 25.1k]
  ------------------
 7637|  3.93k|        ctx->last_seek_pts = MP_NOPTS_VALUE;
  ------------------
  |  |   38|  3.93k|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
 7638|  3.93k|        ctx->marked_pts = MP_NOPTS_VALUE;
  ------------------
  |  |   38|  3.93k|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
 7639|  3.93k|        ctx->marked_permanent = false;
 7640|  3.93k|    }
 7641|       |
 7642|  29.0k|    if (event == MPV_EVENT_PLAYBACK_RESTART) {
  ------------------
  |  Branch (7642:9): [True: 0, False: 29.0k]
  ------------------
 7643|      0|        ctx->last_seek_time = mp_time_sec();
 7644|      0|        run_command_opts(mpctx);
 7645|      0|    }
 7646|       |
 7647|  29.0k|    if (event == MPV_EVENT_VIDEO_RECONFIG && ctx->hwdec_osd_mode) {
  ------------------
  |  Branch (7647:9): [True: 78, False: 28.9k]
  |  Branch (7647:46): [True: 0, False: 78]
  ------------------
 7648|      0|        show_property_osd(mpctx, "hwdec", ctx->hwdec_osd_mode);
 7649|      0|        ctx->hwdec_osd_mode = 0;
 7650|      0|    }
 7651|       |
 7652|  29.0k|    if (event == MPV_EVENT_IDLE)
  ------------------
  |  Branch (7652:9): [True: 69, False: 28.9k]
  ------------------
 7653|     69|        run_command_opts(mpctx);
 7654|       |
 7655|  29.0k|    if (event == MPV_EVENT_END_FILE)
  ------------------
  |  Branch (7655:9): [True: 3.93k, False: 25.1k]
  ------------------
 7656|  3.93k|        mp_msg_flush_status_line(mpctx->log, false);
 7657|       |
 7658|  29.0k|    if (event == MPV_EVENT_END_FILE || event == MPV_EVENT_FILE_LOADED) {
  ------------------
  |  Branch (7658:9): [True: 3.93k, False: 25.1k]
  |  Branch (7658:40): [True: 0, False: 25.1k]
  ------------------
 7659|       |        // Update chapters - does nothing if something else is visible.
 7660|  3.93k|        set_osd_bar_chapters(mpctx, OSD_BAR_SEEK);
 7661|  3.93k|    }
 7662|  29.0k|    if (event == MP_EVENT_WIN_STATE2)
  ------------------
  |  Branch (7662:9): [True: 0, False: 29.0k]
  ------------------
 7663|      0|        ctx->cached_window_scale = 0;
 7664|       |
 7665|  29.0k|    if (event == MP_EVENT_METADATA_UPDATE) {
  ------------------
  |  Branch (7665:9): [True: 0, False: 29.0k]
  ------------------
 7666|      0|        struct playlist_entry *const pe = mpctx->playing;
 7667|      0|        if (pe && !pe->title) {
  ------------------
  |  Branch (7667:13): [True: 0, False: 0]
  |  Branch (7667:19): [True: 0, False: 0]
  ------------------
 7668|      0|            const char *const name = mp_find_non_filename_media_title(mpctx);
 7669|      0|            if (name && name[0]) {
  ------------------
  |  Branch (7669:17): [True: 0, False: 0]
  |  Branch (7669:25): [True: 0, False: 0]
  ------------------
 7670|      0|                pe->title = talloc_strdup(pe, name);
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
 7671|      0|                mp_notify_property(mpctx, "playlist");
 7672|      0|            }
 7673|      0|        }
 7674|      0|    }
 7675|  29.0k|}
command.c:update_priority:
 7719|  12.1k|{
 7720|       |#if HAVE_WIN32_DESKTOP
 7721|       |    struct MPOpts *opts = mpctx->opts;
 7722|       |    if (opts->w32_priority > 0)
 7723|       |        SetPriorityClass(GetCurrentProcess(), opts->w32_priority);
 7724|       |#endif
 7725|  12.1k|}

mp_parse_cfgfiles:
   67|  17.0k|{
   68|  17.0k|    struct MPOpts *opts = mpctx->opts;
   69|       |
   70|  17.0k|    mp_mk_user_dir(mpctx->global, "home", "");
   71|       |
   72|  17.0k|    char *p1 = mp_get_user_path(NULL, mpctx->global, "~~home/");
   73|  17.0k|    char *p2 = mp_get_user_path(NULL, mpctx->global, "~~old_home/");
   74|  17.0k|    if (strcmp(p1, p2) != 0 && mp_path_exists(p2)) {
  ------------------
  |  Branch (74:9): [True: 720, False: 16.3k]
  |  Branch (74:32): [True: 0, False: 720]
  ------------------
   75|      0|        MP_WARN(mpctx, "Warning, two config dirs found:\n   %s (main)\n"
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
   76|      0|                "   %s (bogus)\nYou should merge or delete the second one.\n",
   77|      0|                p1, p2);
   78|      0|    }
   79|  17.0k|    talloc_free(p1);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
   80|  17.0k|    talloc_free(p2);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
   81|       |
   82|  17.0k|    char *section = NULL;
   83|  17.0k|    bool encoding = opts->encode_opts->file && opts->encode_opts->file[0];
  ------------------
  |  Branch (83:21): [True: 488, False: 16.5k]
  |  Branch (83:48): [True: 392, False: 96]
  ------------------
   84|       |    // In encoding mode, we don't want to apply normal config options.
   85|       |    // So we "divert" normal options into a separate section, and the diverted
   86|       |    // section is never used - unless maybe it's explicitly referenced from an
   87|       |    // encoding profile.
   88|  17.0k|    if (encoding)
  ------------------
  |  Branch (88:9): [True: 392, False: 16.6k]
  ------------------
   89|    392|        section = "playback-default";
   90|       |
   91|  17.0k|    load_all_cfgfiles(mpctx, NULL, "encoding-profiles.conf");
   92|       |
   93|  17.0k|    load_all_cfgfiles(mpctx, section, "mpv.conf|config");
   94|       |
   95|  17.0k|    if (encoding) {
  ------------------
  |  Branch (95:9): [True: 392, False: 16.6k]
  ------------------
   96|    392|        m_config_set_profile(mpctx->mconfig, SECT_ENCODE, 0);
  ------------------
  |  |   64|    392|#define SECT_ENCODE "encoding"
  ------------------
   97|    392|        mp_input_enable_section(mpctx->input, "encode", MP_INPUT_EXCLUSIVE);
   98|    392|    }
   99|  17.0k|}
mp_load_auto_profiles:
  163|    405|{
  164|    405|    mp_auto_load_profile(mpctx, "protocol",
  165|    405|                         mp_split_proto(bstr0(mpctx->filename), NULL));
  166|    405|    mp_auto_load_profile(mpctx, "extension",
  167|    405|                         bstr0(mp_splitext(mpctx->filename, NULL)));
  168|       |
  169|    405|    mp_load_per_file_config(mpctx);
  170|    405|}
mp_get_playback_resume_dir:
  201|  66.5k|{
  202|  66.5k|    char *wl_dir = mpctx->opts->watch_later_dir;
  203|  66.5k|    if (wl_dir && wl_dir[0]) {
  ------------------
  |  Branch (203:9): [True: 10.3k, False: 56.1k]
  |  Branch (203:19): [True: 10.1k, False: 194]
  ------------------
  204|  10.1k|        wl_dir = mp_get_user_path(mpctx, mpctx->global, wl_dir);
  205|  56.3k|    } else {
  206|  56.3k|        wl_dir = mp_find_user_file(mpctx, mpctx->global, "state", MP_WATCH_LATER_CONF);
  ------------------
  |  |  172|  56.3k|#define MP_WATCH_LATER_CONF "watch_later"
  ------------------
  207|  56.3k|    }
  208|  66.5k|    return wl_dir;
  209|  66.5k|}
mp_load_playback_resume:
  433|    405|{
  434|    405|    bool resume = false;
  435|    405|    if (!mpctx->opts->position_resume)
  ------------------
  |  Branch (435:9): [True: 0, False: 405]
  ------------------
  436|      0|        return resume;
  437|    405|    char *fname = mp_get_playback_resume_config_filename(mpctx, file);
  438|    405|    if (fname && mp_path_exists(fname)) {
  ------------------
  |  Branch (438:9): [True: 5, False: 400]
  |  Branch (438:18): [True: 0, False: 5]
  ------------------
  439|      0|        if (mpctx->opts->position_check_mtime &&
  ------------------
  |  Branch (439:13): [True: 0, False: 0]
  ------------------
  440|      0|            !mp_is_url(bstr0(file)) && !check_mtime(file, fname))
  ------------------
  |  Branch (440:13): [True: 0, False: 0]
  |  Branch (440:40): [True: 0, False: 0]
  ------------------
  441|      0|        {
  442|      0|            talloc_free(fname);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  443|      0|            return resume;
  444|      0|        }
  445|       |
  446|       |        // Never apply the saved start position to following files
  447|      0|        m_config_backup_opt(mpctx->mconfig, "start");
  448|      0|        MP_INFO(mpctx, "Resuming playback. This behavior can "
  ------------------
  |  |   87|      0|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  449|      0|               "be disabled with --no-resume-playback.\n");
  450|      0|        try_load_config(mpctx, fname, M_SETOPT_PRESERVE_CMDLINE, MSGL_V);
  451|      0|        resume = true;
  452|      0|    }
  453|    405|    talloc_free(fname);
  ------------------
  |  |   47|    405|#define talloc_free                     ta_free
  ------------------
  454|    405|    return resume;
  455|    405|}
mp_check_playlist_resume:
  464|  12.1k|{
  465|  12.1k|    if (!mpctx->opts->position_resume)
  ------------------
  |  Branch (465:9): [True: 311, False: 11.8k]
  ------------------
  466|    311|        return NULL;
  467|  78.1k|    for (int n = 0; n < playlist->num_entries; n++) {
  ------------------
  |  Branch (467:21): [True: 66.3k, False: 11.8k]
  ------------------
  468|  66.3k|        struct playlist_entry *e = playlist->entries[n];
  469|  66.3k|        char *conf = mp_get_playback_resume_config_filename(mpctx, e->filename);
  470|  66.3k|        bool exists = conf && mp_path_exists(conf);
  ------------------
  |  Branch (470:23): [True: 26.0k, False: 40.2k]
  |  Branch (470:31): [True: 0, False: 26.0k]
  ------------------
  471|  66.3k|        talloc_free(conf);
  ------------------
  |  |   47|  66.3k|#define talloc_free                     ta_free
  ------------------
  472|  66.3k|        if (exists)
  ------------------
  |  Branch (472:13): [True: 0, False: 66.3k]
  ------------------
  473|      0|            return e;
  474|  66.3k|    }
  475|  11.8k|    return NULL;
  476|  11.8k|}
configfiles.c:load_all_cfgfiles:
   56|  34.1k|{
   57|  34.1k|    char **cf = mp_find_all_config_files(NULL, mpctx->global, filename);
   58|  34.1k|    for (int i = 0; cf && cf[i]; i++)
  ------------------
  |  Branch (58:21): [True: 34.1k, False: 0]
  |  Branch (58:27): [True: 0, False: 34.1k]
  ------------------
   59|      0|        m_config_parse_config_file(mpctx->mconfig, mpctx->global, cf[i], section, 0);
   60|  34.1k|    talloc_free(cf);
  ------------------
  |  |   47|  34.1k|#define talloc_free                     ta_free
  ------------------
   61|  34.1k|}
configfiles.c:mp_auto_load_profile:
  149|    810|{
  150|    810|    if (!item.len)
  ------------------
  |  Branch (150:9): [True: 293, False: 517]
  ------------------
  151|    293|        return;
  152|       |
  153|    517|    char t[512];
  154|    517|    snprintf(t, sizeof(t), "%s.%.*s", category, BSTR_P(item));
  ------------------
  |  |  283|    517|#define BSTR_P(bstr) (int)((bstr).len), ((bstr).start ? (char*)(bstr).start : "")
  |  |  ------------------
  |  |  |  Branch (283:42): [True: 517, False: 0]
  |  |  ------------------
  ------------------
  155|    517|    m_profile_t *p = m_config_get_profile0(mpctx->mconfig, t);
  156|    517|    if (p) {
  ------------------
  |  Branch (156:9): [True: 0, False: 517]
  ------------------
  157|      0|        MP_INFO(mpctx, "Auto-loading profile '%s'\n", t);
  ------------------
  |  |   87|      0|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  158|      0|        m_config_set_profile(mpctx->mconfig, t, FILE_LOCAL_FLAGS);
  ------------------
  |  |  113|      0|#define FILE_LOCAL_FLAGS (M_SETOPT_BACKUP | M_SETOPT_PRESERVE_CMDLINE)
  ------------------
  159|      0|    }
  160|    517|}
configfiles.c:mp_load_per_file_config:
  116|    405|{
  117|    405|    struct MPOpts *opts = mpctx->opts;
  118|    405|    char *confpath;
  119|    405|    char cfg[512];
  120|    405|    const char *file = mpctx->filename;
  121|       |
  122|    405|    if (opts->use_filedir_conf) {
  ------------------
  |  Branch (122:9): [True: 0, False: 405]
  ------------------
  123|      0|        if (snprintf(cfg, sizeof(cfg), "%s.conf", file) >= sizeof(cfg)) {
  ------------------
  |  Branch (123:13): [True: 0, False: 0]
  ------------------
  124|      0|            MP_VERBOSE(mpctx, "Filename is too long, can not load file or "
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  125|      0|                              "directory specific config files\n");
  126|      0|            return;
  127|      0|        }
  128|       |
  129|      0|        char *name = mp_basename(cfg);
  130|       |
  131|      0|        bstr dir = mp_dirname(cfg);
  132|      0|        char *dircfg = mp_path_join_bstr(NULL, dir, bstr0("mpv.conf"));
  133|      0|        try_load_config(mpctx, dircfg, FILE_LOCAL_FLAGS, MSGL_INFO);
  ------------------
  |  |  113|      0|#define FILE_LOCAL_FLAGS (M_SETOPT_BACKUP | M_SETOPT_PRESERVE_CMDLINE)
  ------------------
  134|      0|        talloc_free(dircfg);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  135|       |
  136|      0|        if (try_load_config(mpctx, cfg, FILE_LOCAL_FLAGS, MSGL_INFO))
  ------------------
  |  |  113|      0|#define FILE_LOCAL_FLAGS (M_SETOPT_BACKUP | M_SETOPT_PRESERVE_CMDLINE)
  ------------------
  |  Branch (136:13): [True: 0, False: 0]
  ------------------
  137|      0|            return;
  138|       |
  139|      0|        if ((confpath = mp_find_config_file(NULL, mpctx->global, name))) {
  ------------------
  |  Branch (139:13): [True: 0, False: 0]
  ------------------
  140|      0|            try_load_config(mpctx, confpath, FILE_LOCAL_FLAGS, MSGL_INFO);
  ------------------
  |  |  113|      0|#define FILE_LOCAL_FLAGS (M_SETOPT_BACKUP | M_SETOPT_PRESERVE_CMDLINE)
  ------------------
  141|       |
  142|      0|            talloc_free(confpath);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  143|      0|        }
  144|      0|    }
  145|    405|}
configfiles.c:mp_get_playback_resume_config_filename:
  213|  66.7k|{
  214|  66.7k|    struct MPOpts *opts = mpctx->opts;
  215|  66.7k|    char *res = NULL;
  216|  66.7k|    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|  66.7k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  66.7k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  217|  66.7k|    const char *path = NULL;
  218|  66.7k|    if (mp_is_url(bstr0(fname))) {
  ------------------
  |  Branch (218:9): [True: 3.34k, False: 63.3k]
  ------------------
  219|  3.34k|        path = fname;
  220|  63.3k|    } else if (opts->ignore_path_in_watch_later_config) {
  ------------------
  |  Branch (220:16): [True: 0, False: 63.3k]
  ------------------
  221|      0|        path = mp_basename(fname);
  222|  63.3k|    } else {
  223|  63.3k|        path = mp_normalize_path(tmp, fname);
  224|  63.3k|        if (!path)
  ------------------
  |  Branch (224:13): [True: 201, False: 63.1k]
  ------------------
  225|    201|            goto exit;
  226|  63.3k|    }
  227|  66.5k|    uint8_t md5[16];
  228|  66.5k|    av_md5_sum(md5, path, strlen(path));
  229|  66.5k|    char *conf = talloc_strdup(tmp, "");
  ------------------
  |  |   50|  66.5k|#define talloc_strdup                   ta_xstrdup
  ------------------
  230|  1.13M|    for (int i = 0; i < 16; i++)
  ------------------
  |  Branch (230:21): [True: 1.06M, False: 66.5k]
  ------------------
  231|  1.06M|        conf = talloc_asprintf_append(conf, "%02X", md5[i]);
  ------------------
  |  |   63|  1.06M|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
  232|       |
  233|  66.5k|    char *wl_dir = mp_get_playback_resume_dir(mpctx);
  234|  66.5k|    if (wl_dir && wl_dir[0])
  ------------------
  |  Branch (234:9): [True: 28.2k, False: 38.3k]
  |  Branch (234:19): [True: 26.0k, False: 2.18k]
  ------------------
  235|  26.0k|        res = mp_path_join(NULL, wl_dir, conf);
  236|       |
  237|  66.7k|exit:
  238|  66.7k|    talloc_free(tmp);
  ------------------
  |  |   47|  66.7k|#define talloc_free                     ta_free
  ------------------
  239|  66.7k|    return res;
  240|  66.5k|}

mp_update_subtitle_exts:
   66|  12.1k|{
   67|  12.1k|    sub_exts = opts->sub_auto_exts;
   68|  12.1k|}

mp_abort_playback_async:
   73|  4.72k|{
   74|  4.72k|    mp_cancel_trigger(mpctx->playback_abort);
   75|       |
   76|  4.72k|    mp_mutex_lock(&mpctx->abort_lock);
  ------------------
  |  |  131|  4.72k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
   77|       |
   78|  4.72k|    for (int n = 0; n < mpctx->num_abort_list; n++) {
  ------------------
  |  Branch (78:21): [True: 0, False: 4.72k]
  ------------------
   79|      0|        struct mp_abort_entry *abort = mpctx->abort_list[n];
   80|      0|        if (abort->coupled_to_playback)
  ------------------
  |  Branch (80:13): [True: 0, False: 0]
  ------------------
   81|      0|            mp_abort_trigger_locked(mpctx, abort);
   82|      0|    }
   83|       |
   84|  4.72k|    mp_mutex_unlock(&mpctx->abort_lock);
  ------------------
  |  |  133|  4.72k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
   85|  4.72k|}
prepare_playlist:
 1013|  12.1k|{
 1014|  12.1k|    struct MPOpts *opts = mpctx->opts;
 1015|       |
 1016|  12.1k|    pl->current = NULL;
 1017|  12.1k|    pl->playlist_completed = false;
 1018|  12.1k|    pl->playlist_started = false;
 1019|       |
 1020|  12.1k|    if (opts->playlist_pos >= 0)
  ------------------
  |  Branch (1020:9): [True: 29, False: 12.1k]
  ------------------
 1021|     29|        pl->current = playlist_entry_from_index(pl, opts->playlist_pos);
 1022|       |
 1023|  12.1k|    if (pl->playlist_dir)
  ------------------
  |  Branch (1023:9): [True: 0, False: 12.1k]
  ------------------
 1024|      0|        playlist_set_current(pl);
 1025|       |
 1026|  12.1k|    if (opts->shuffle)
  ------------------
  |  Branch (1026:9): [True: 173, False: 11.9k]
  ------------------
 1027|    173|        playlist_shuffle(pl);
 1028|       |
 1029|  12.1k|    if (opts->merge_files)
  ------------------
  |  Branch (1029:9): [True: 791, False: 11.3k]
  ------------------
 1030|    791|        merge_playlist_files(pl);
 1031|       |
 1032|  12.1k|    if (!pl->current)
  ------------------
  |  Branch (1032:9): [True: 12.1k, False: 1]
  ------------------
 1033|  12.1k|        pl->current = mp_check_playlist_resume(mpctx, pl);
 1034|       |
 1035|  12.1k|    if (!pl->current)
  ------------------
  |  Branch (1035:9): [True: 12.1k, False: 1]
  ------------------
 1036|  12.1k|        pl->current = playlist_get_first(pl);
 1037|  12.1k|}
update_lavfi_complex:
 1491|  12.1k|{
 1492|  12.1k|    if (mpctx->playback_initialized) {
  ------------------
  |  Branch (1492:9): [True: 0, False: 12.1k]
  ------------------
 1493|      0|        if (reinit_complex_filters(mpctx, false) != 0)
  ------------------
  |  Branch (1493:13): [True: 0, False: 0]
  ------------------
 1494|      0|            issue_refresh_seek(mpctx, MPSEEK_EXACT);
 1495|      0|    }
 1496|  12.1k|}
mp_next_file:
 2038|  3.52k|{
 2039|  3.52k|    struct playlist_entry *next = playlist_get_next(mpctx->playlist, direction);
 2040|  3.52k|    if (next && direction < 0 && !force)
  ------------------
  |  Branch (2040:9): [True: 3.46k, False: 65]
  |  Branch (2040:17): [True: 0, False: 3.46k]
  |  Branch (2040:34): [True: 0, False: 0]
  ------------------
 2041|      0|        next->playlist_prev_attempt = true;
 2042|  3.52k|    if (!next && mpctx->opts->loop_times != 1) {
  ------------------
  |  Branch (2042:9): [True: 65, False: 3.46k]
  |  Branch (2042:18): [True: 0, False: 65]
  ------------------
 2043|      0|        if (direction > 0) {
  ------------------
  |  Branch (2043:13): [True: 0, False: 0]
  ------------------
 2044|      0|            if (mpctx->opts->shuffle) {
  ------------------
  |  Branch (2044:17): [True: 0, False: 0]
  ------------------
 2045|      0|                if (!update_loop)
  ------------------
  |  Branch (2045:21): [True: 0, False: 0]
  ------------------
 2046|      0|                    return NULL;
 2047|      0|                playlist_shuffle(mpctx->playlist);
 2048|      0|            }
 2049|      0|            next = playlist_get_first(mpctx->playlist);
 2050|      0|            if (next && mpctx->opts->loop_times > 1 && update_loop) {
  ------------------
  |  Branch (2050:17): [True: 0, False: 0]
  |  Branch (2050:25): [True: 0, False: 0]
  |  Branch (2050:56): [True: 0, False: 0]
  ------------------
 2051|      0|                mpctx->opts->loop_times--;
 2052|      0|                m_config_notify_change_opt_ptr(mpctx->mconfig,
 2053|      0|                                               &mpctx->opts->loop_times);
 2054|      0|            }
 2055|      0|        } else {
 2056|      0|            next = playlist_get_last(mpctx->playlist);
 2057|      0|        }
 2058|      0|        bool ignore_failures = mpctx->opts->loop_times == -2;
 2059|      0|        if (!force && next && next->init_failed && !ignore_failures) {
  ------------------
  |  Branch (2059:13): [True: 0, False: 0]
  |  Branch (2059:23): [True: 0, False: 0]
  |  Branch (2059:31): [True: 0, False: 0]
  |  Branch (2059:52): [True: 0, False: 0]
  ------------------
 2060|       |            // Don't endless loop if no file in playlist is playable
 2061|      0|            bool all_failed = true;
 2062|      0|            for (int n = 0; n < mpctx->playlist->num_entries; n++) {
  ------------------
  |  Branch (2062:29): [True: 0, False: 0]
  ------------------
 2063|      0|                all_failed &= mpctx->playlist->entries[n]->init_failed;
 2064|      0|                if (!all_failed)
  ------------------
  |  Branch (2064:21): [True: 0, False: 0]
  ------------------
 2065|      0|                    break;
 2066|      0|            }
 2067|      0|            if (all_failed)
  ------------------
  |  Branch (2067:17): [True: 0, False: 0]
  ------------------
 2068|      0|                next = NULL;
 2069|      0|        }
 2070|      0|    }
 2071|  3.52k|    return next;
 2072|  3.52k|}
mp_play_files:
 2077|  12.1k|{
 2078|  12.1k|    stats_register_thread_cputime(mpctx->stats, "thread");
 2079|       |
 2080|       |    // Wait for all scripts to load before possibly starting playback.
 2081|  12.1k|    if (!mp_clients_all_initialized(mpctx)) {
  ------------------
  |  Branch (2081:9): [True: 187, False: 11.9k]
  ------------------
 2082|    187|        MP_VERBOSE(mpctx, "Waiting for scripts...\n");
  ------------------
  |  |   88|    187|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    187|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2083|    686|        while (!mp_clients_all_initialized(mpctx))
  ------------------
  |  Branch (2083:16): [True: 499, False: 187]
  ------------------
 2084|    499|            mp_idle(mpctx);
 2085|    187|        mp_wakeup_core(mpctx); // avoid lost wakeups during waiting
 2086|    187|        MP_VERBOSE(mpctx, "Done loading scripts.\n");
  ------------------
  |  |   88|    187|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    187|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2087|    187|    }
 2088|       |    // After above is finished; but even if it's skipped.
 2089|  12.1k|    mp_msg_set_early_logging(mpctx->global, false);
 2090|       |
 2091|  12.1k|    prepare_playlist(mpctx, mpctx->playlist);
 2092|       |
 2093|  15.6k|    for (;;) {
 2094|  15.6k|        idle_loop(mpctx);
 2095|       |
 2096|  15.6k|        if (mpctx->stop_play == PT_QUIT)
  ------------------
  |  Branch (2096:13): [True: 11.7k, False: 3.93k]
  ------------------
 2097|  11.7k|            break;
 2098|       |
 2099|  3.93k|        if (mpctx->playlist->current)
  ------------------
  |  Branch (2099:13): [True: 3.93k, False: 0]
  ------------------
 2100|  3.93k|            play_current_file(mpctx);
 2101|       |
 2102|  3.93k|        if (mpctx->stop_play == PT_QUIT)
  ------------------
  |  Branch (2102:13): [True: 405, False: 3.52k]
  ------------------
 2103|    405|            break;
 2104|       |
 2105|  3.52k|        struct playlist_entry *new_entry = NULL;
 2106|  3.52k|        if (mpctx->stop_play == PT_NEXT_ENTRY || mpctx->stop_play == PT_ERROR ||
  ------------------
  |  Branch (2106:13): [True: 0, False: 3.52k]
  |  Branch (2106:50): [True: 3.52k, False: 0]
  ------------------
 2107|  3.52k|            mpctx->stop_play == AT_END_OF_FILE)
  ------------------
  |  Branch (2107:13): [True: 0, False: 0]
  ------------------
 2108|  3.52k|        {
 2109|  3.52k|            new_entry = mp_next_file(mpctx, +1, false, true);
 2110|  3.52k|        } else if (mpctx->stop_play == PT_CURRENT_ENTRY) {
  ------------------
  |  Branch (2110:20): [True: 0, False: 0]
  ------------------
 2111|      0|            new_entry = mpctx->playlist->current;
 2112|      0|        }
 2113|       |
 2114|  3.52k|        if (!new_entry)
  ------------------
  |  Branch (2114:13): [True: 65, False: 3.46k]
  ------------------
 2115|     65|            mpctx->playlist->playlist_completed = true;
 2116|       |
 2117|  3.52k|        mpctx->playlist->current = new_entry;
 2118|  3.52k|        mpctx->playlist->current_was_replaced = false;
 2119|  3.52k|        mpctx->stop_play = new_entry ? PT_NEXT_ENTRY : PT_STOP;
  ------------------
  |  Branch (2119:28): [True: 3.46k, False: 65]
  ------------------
 2120|       |
 2121|  3.52k|        if (!mpctx->playlist->current && mpctx->opts->player_idle_mode < 2)
  ------------------
  |  Branch (2121:13): [True: 65, False: 3.46k]
  |  Branch (2121:42): [True: 0, False: 65]
  ------------------
 2122|      0|            break;
 2123|  3.52k|    }
 2124|       |
 2125|  12.1k|    cancel_open(mpctx);
 2126|       |
 2127|  12.1k|    if (mpctx->encode_lavc_ctx) {
  ------------------
  |  Branch (2127:9): [True: 21, False: 12.1k]
  ------------------
 2128|       |        // Make sure all streams get finished.
 2129|     21|        uninit_audio_out(mpctx);
 2130|     21|        uninit_video_out(mpctx);
 2131|       |
 2132|     21|        if (!encode_lavc_free(mpctx->encode_lavc_ctx))
  ------------------
  |  Branch (2132:13): [True: 21, False: 0]
  ------------------
 2133|     21|            mpctx->files_errored += 1;
 2134|       |
 2135|     21|        mpctx->encode_lavc_ctx = NULL;
 2136|     21|    }
 2137|  12.1k|}
loadfile.c:start_open:
 1189|    405|{
 1190|    405|    cancel_open(mpctx);
 1191|       |
 1192|    405|    mp_assert(!mpctx->open_active);
  ------------------
  |  |   41|    405|#define mp_assert assert
  ------------------
 1193|    405|    mp_assert(!mpctx->open_cancel);
  ------------------
  |  |   41|    405|#define mp_assert assert
  ------------------
 1194|    405|    mp_assert(!mpctx->open_res_demuxer);
  ------------------
  |  |   41|    405|#define mp_assert assert
  ------------------
 1195|    405|    mp_assert(!atomic_load(&mpctx->open_done));
  ------------------
  |  |   41|    405|#define mp_assert assert
  ------------------
 1196|       |
 1197|    405|    mpctx->open_cancel = mp_cancel_new(NULL);
 1198|    405|    mpctx->open_url = talloc_strdup(NULL, url);
  ------------------
  |  |   50|    405|#define talloc_strdup                   ta_xstrdup
  ------------------
 1199|    405|    mpctx->open_format = talloc_strdup(NULL, mpctx->opts->demuxer_name);
  ------------------
  |  |   50|    405|#define talloc_strdup                   ta_xstrdup
  ------------------
 1200|    405|    mpctx->open_url_flags = url_flags;
 1201|    405|    mpctx->open_for_prefetch = for_prefetch && mpctx->opts->demuxer_thread;
  ------------------
  |  Branch (1201:32): [True: 0, False: 405]
  |  Branch (1201:48): [True: 0, False: 0]
  ------------------
 1202|    405|    mpctx->demuxer_changed = false;
 1203|       |
 1204|    405|    if (mp_thread_create(&mpctx->open_thread, open_demux_thread, mpctx)) {
  ------------------
  |  |  211|    405|#define mp_thread_create(t, f, a) pthread_create(t, NULL, f, a)
  |  |  ------------------
  |  |  |  Branch (211:35): [True: 0, False: 405]
  |  |  ------------------
  ------------------
 1205|      0|        cancel_open(mpctx);
 1206|      0|        return;
 1207|      0|    }
 1208|       |
 1209|    405|    mpctx->open_active = true;
 1210|    405|}
loadfile.c:open_demux_thread:
 1120|    405|{
 1121|    405|    struct MPContext *mpctx = ctx;
 1122|       |
 1123|    405|    mp_thread_set_name("opener");
 1124|       |
 1125|    405|    struct demuxer_params p = {
 1126|    405|        .force_format = mpctx->open_format,
 1127|    405|        .stream_flags = mpctx->open_url_flags,
 1128|    405|        .stream_record = true,
 1129|    405|        .is_top_level = true,
 1130|    405|        .allow_playlist_create = mpctx->playlist->num_entries <= 1 &&
  ------------------
  |  Branch (1130:34): [True: 146, False: 259]
  ------------------
 1131|    405|                                 !mpctx->playlist->playlist_dir,
  ------------------
  |  Branch (1131:34): [True: 146, False: 0]
  ------------------
 1132|    405|    };
 1133|    405|    struct demuxer *demux =
 1134|    405|        demux_open_url(mpctx->open_url, &p, mpctx->open_cancel, mpctx->global);
 1135|    405|    mpctx->open_res_demuxer = demux;
 1136|       |
 1137|    405|    if (demux) {
  ------------------
  |  Branch (1137:9): [True: 161, False: 244]
  ------------------
 1138|    161|        MP_VERBOSE(mpctx, "Opening done: %s\n", mpctx->open_url);
  ------------------
  |  |   88|    161|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    161|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1139|       |
 1140|    161|        if (mpctx->open_for_prefetch && !demux->fully_read) {
  ------------------
  |  Branch (1140:13): [True: 0, False: 161]
  |  Branch (1140:41): [True: 0, False: 0]
  ------------------
 1141|      0|            int num_streams = demux_get_num_stream(demux);
 1142|      0|            for (int n = 0; n < num_streams; n++) {
  ------------------
  |  Branch (1142:29): [True: 0, False: 0]
  ------------------
 1143|      0|                struct sh_stream *sh = demux_get_stream(demux, n);
 1144|      0|                demuxer_select_track(demux, sh, MP_NOPTS_VALUE, true);
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
 1145|      0|            }
 1146|       |
 1147|      0|            demux_set_wakeup_cb(demux, wakeup_demux, mpctx);
 1148|      0|            demux_start_thread(demux);
 1149|      0|            demux_start_prefetch(demux);
 1150|      0|        }
 1151|    244|    } else {
 1152|    244|        MP_VERBOSE(mpctx, "Opening failed or was aborted: %s\n", mpctx->open_url);
  ------------------
  |  |   88|    244|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    244|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1153|       |
 1154|    244|        if (p.demuxer_failed) {
  ------------------
  |  Branch (1154:13): [True: 223, False: 21]
  ------------------
 1155|    223|            mpctx->open_res_error = MPV_ERROR_UNKNOWN_FORMAT;
 1156|    223|        } else {
 1157|     21|            mpctx->open_res_error = MPV_ERROR_LOADING_FAILED;
 1158|     21|        }
 1159|    244|    }
 1160|       |
 1161|    405|    atomic_store(&mpctx->open_done, true);
 1162|    405|    mp_wakeup_core(mpctx);
 1163|    405|    MP_THREAD_RETURN();
  ------------------
  |  |  209|    405|#define MP_THREAD_RETURN() return NULL
  ------------------
 1164|    405|}
loadfile.c:reinit_complex_filters:
 1360|  3.93k|{
 1361|  3.93k|    char *graph = mpctx->opts->lavfi_complex;
 1362|  3.93k|    bool have_graph = graph && graph[0] && !force_uninit;
  ------------------
  |  Branch (1362:23): [True: 0, False: 3.93k]
  |  Branch (1362:32): [True: 0, False: 0]
  |  Branch (1362:44): [True: 0, False: 0]
  ------------------
 1363|  3.93k|    if (have_graph && mpctx->lavfi &&
  ------------------
  |  Branch (1363:9): [True: 0, False: 3.93k]
  |  Branch (1363:23): [True: 0, False: 0]
  ------------------
 1364|  3.93k|        strcmp(graph, mpctx->lavfi_graph) == 0 &&
  ------------------
  |  Branch (1364:9): [True: 0, False: 0]
  ------------------
 1365|  3.93k|        !mp_filter_has_failed(mpctx->lavfi))
  ------------------
  |  Branch (1365:9): [True: 0, False: 0]
  ------------------
 1366|      0|        return 0;
 1367|  3.93k|    if (!mpctx->lavfi && !have_graph)
  ------------------
  |  Branch (1367:9): [True: 3.93k, False: 0]
  |  Branch (1367:26): [True: 3.93k, False: 0]
  ------------------
 1368|  3.93k|        return 0;
 1369|       |
 1370|       |    // Deassociate the old filter pads. We leave both sources (tracks) and
 1371|       |    // sinks (AO/VO) "dangling", connected to neither track or filter pad.
 1372|       |    // Later, we either reassociate them with new pads, or uninit them if
 1373|       |    // they are still dangling. This avoids too interruptive actions like
 1374|       |    // recreating the VO.
 1375|      0|    deassociate_complex_filters(mpctx);
 1376|       |
 1377|      0|    bool success = false;
 1378|      0|    if (!have_graph) {
  ------------------
  |  Branch (1378:9): [True: 0, False: 0]
  ------------------
 1379|      0|        success = true; // normal full removal of graph
 1380|      0|        goto done;
 1381|      0|    }
 1382|       |
 1383|      0|    struct mp_lavfi *l =
 1384|      0|        mp_lavfi_create_graph(mpctx->filter_root, 0, false, NULL, NULL, graph);
 1385|      0|    if (!l)
  ------------------
  |  Branch (1385:9): [True: 0, False: 0]
  ------------------
 1386|      0|        goto done;
 1387|      0|    mpctx->lavfi = l->f;
 1388|      0|    mpctx->lavfi_graph = talloc_strdup(NULL, graph);
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
 1389|       |
 1390|      0|    mp_filter_set_error_handler(mpctx->lavfi, mpctx->filter_root);
 1391|       |
 1392|      0|    for (int n = 0; n < mpctx->lavfi->num_pins; n++)
  ------------------
  |  Branch (1392:21): [True: 0, False: 0]
  ------------------
 1393|      0|        mp_pin_disconnect(mpctx->lavfi->pins[n]);
 1394|       |
 1395|      0|    struct mp_pin *pad = mp_filter_get_named_pin(mpctx->lavfi, "vo");
 1396|      0|    if (pad && mp_pin_get_dir(pad) == MP_PIN_OUT) {
  ------------------
  |  Branch (1396:9): [True: 0, False: 0]
  |  Branch (1396:16): [True: 0, False: 0]
  ------------------
 1397|      0|        if (mpctx->vo_chain && mpctx->vo_chain->track)
  ------------------
  |  Branch (1397:13): [True: 0, False: 0]
  |  Branch (1397:32): [True: 0, False: 0]
  ------------------
 1398|      0|            kill_outputs(mpctx, mpctx->vo_chain->track);
 1399|      0|        if (!mpctx->vo_chain) {
  ------------------
  |  Branch (1399:13): [True: 0, False: 0]
  ------------------
 1400|      0|            reinit_video_chain_src(mpctx, NULL);
 1401|      0|            if (!mpctx->vo_chain)
  ------------------
  |  Branch (1401:17): [True: 0, False: 0]
  ------------------
 1402|      0|                goto done;
 1403|      0|        }
 1404|      0|        struct vo_chain *vo_c = mpctx->vo_chain;
 1405|      0|        mp_assert(!vo_c->track);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
 1406|      0|        vo_c->filter_src = pad;
 1407|      0|        mp_pin_connect(vo_c->filter->f->pins[0], vo_c->filter_src);
 1408|      0|    }
 1409|       |
 1410|      0|    pad = mp_filter_get_named_pin(mpctx->lavfi, "ao");
 1411|      0|    if (pad && mp_pin_get_dir(pad) == MP_PIN_OUT) {
  ------------------
  |  Branch (1411:9): [True: 0, False: 0]
  |  Branch (1411:16): [True: 0, False: 0]
  ------------------
 1412|      0|        if (mpctx->ao_chain && mpctx->ao_chain->track)
  ------------------
  |  Branch (1412:13): [True: 0, False: 0]
  |  Branch (1412:32): [True: 0, False: 0]
  ------------------
 1413|      0|            kill_outputs(mpctx, mpctx->ao_chain->track);
 1414|      0|        if (!mpctx->ao_chain) {
  ------------------
  |  Branch (1414:13): [True: 0, False: 0]
  ------------------
 1415|      0|            reinit_audio_chain_src(mpctx, NULL);
 1416|      0|            if (!mpctx->ao_chain)
  ------------------
  |  Branch (1416:17): [True: 0, False: 0]
  ------------------
 1417|      0|                goto done;
 1418|      0|        }
 1419|      0|        struct ao_chain *ao_c = mpctx->ao_chain;
 1420|      0|        mp_assert(!ao_c->track);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
 1421|      0|        ao_c->filter_src = pad;
 1422|      0|        mp_pin_connect(ao_c->filter->f->pins[0], ao_c->filter_src);
 1423|      0|    }
 1424|       |
 1425|      0|    for (int n = 0; n < mpctx->num_tracks; n++) {
  ------------------
  |  Branch (1425:21): [True: 0, False: 0]
  ------------------
 1426|      0|        struct track *track = mpctx->tracks[n];
 1427|       |
 1428|      0|        char label[32];
 1429|      0|        char prefix;
 1430|      0|        switch (track->type) {
 1431|      0|        case STREAM_VIDEO: prefix = 'v'; break;
  ------------------
  |  Branch (1431:9): [True: 0, False: 0]
  ------------------
 1432|      0|        case STREAM_AUDIO: prefix = 'a'; break;
  ------------------
  |  Branch (1432:9): [True: 0, False: 0]
  ------------------
 1433|      0|        default: continue;
  ------------------
  |  Branch (1433:9): [True: 0, False: 0]
  ------------------
 1434|      0|        }
 1435|      0|        snprintf(label, sizeof(label), "%cid%d", prefix, track->user_tid);
 1436|       |
 1437|      0|        pad = mp_filter_get_named_pin(mpctx->lavfi, label);
 1438|      0|        if (!pad)
  ------------------
  |  Branch (1438:13): [True: 0, False: 0]
  ------------------
 1439|      0|            continue;
 1440|      0|        if (mp_pin_get_dir(pad) != MP_PIN_IN)
  ------------------
  |  Branch (1440:13): [True: 0, False: 0]
  ------------------
 1441|      0|            continue;
 1442|      0|        mp_assert(!mp_pin_is_connected(pad));
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
 1443|       |
 1444|      0|        mp_assert(!track->sink);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
 1445|       |
 1446|      0|        kill_outputs(mpctx, track);
 1447|       |
 1448|      0|        track->sink = pad;
 1449|      0|        track->selected = true;
 1450|       |
 1451|      0|        if (!track->dec) {
  ------------------
  |  Branch (1451:13): [True: 0, False: 0]
  ------------------
 1452|      0|            if (track->type == STREAM_VIDEO && !init_video_decoder(mpctx, track))
  ------------------
  |  Branch (1452:17): [True: 0, False: 0]
  |  Branch (1452:48): [True: 0, False: 0]
  ------------------
 1453|      0|                goto done;
 1454|      0|            if (track->type == STREAM_AUDIO && !init_audio_decoder(mpctx, track))
  ------------------
  |  Branch (1454:17): [True: 0, False: 0]
  |  Branch (1454:48): [True: 0, False: 0]
  ------------------
 1455|      0|                goto done;
 1456|      0|        }
 1457|       |
 1458|      0|        mp_pin_connect(track->sink, track->dec->f->pins[0]);
 1459|      0|    }
 1460|       |
 1461|       |    // Don't allow unconnected pins. Libavfilter would make the data flow a
 1462|       |    // real pain anyway.
 1463|      0|    for (int n = 0; n < mpctx->lavfi->num_pins; n++) {
  ------------------
  |  Branch (1463:21): [True: 0, False: 0]
  ------------------
 1464|      0|        struct mp_pin *pin = mpctx->lavfi->pins[n];
 1465|      0|        if (!mp_pin_is_connected(pin)) {
  ------------------
  |  Branch (1465:13): [True: 0, False: 0]
  ------------------
 1466|      0|            MP_ERR(mpctx, "Pad %s is not connected to anything.\n",
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1467|      0|                   mp_pin_get_name(pin));
 1468|      0|            goto done;
 1469|      0|        }
 1470|      0|    }
 1471|       |
 1472|      0|    success = true;
 1473|      0|done:
 1474|       |
 1475|      0|    if (!success)
  ------------------
  |  Branch (1475:9): [True: 0, False: 0]
  ------------------
 1476|      0|        deassociate_complex_filters(mpctx);
 1477|       |
 1478|      0|    cleanup_deassociated_complex_filters(mpctx);
 1479|       |
 1480|      0|    if (mpctx->playback_initialized) {
  ------------------
  |  Branch (1480:9): [True: 0, False: 0]
  ------------------
 1481|      0|        for (int n = 0; n < mpctx->num_tracks; n++)
  ------------------
  |  Branch (1481:25): [True: 0, False: 0]
  ------------------
 1482|      0|            reselect_demux_stream(mpctx, mpctx->tracks[n], false);
 1483|      0|    }
 1484|       |
 1485|      0|    mp_notify(mpctx, MP_EVENT_TRACKS_CHANGED, NULL);
 1486|       |
 1487|      0|    return success ? 1 : -1;
  ------------------
  |  Branch (1487:12): [True: 0, False: 0]
  ------------------
 1488|      0|}
loadfile.c:play_current_file:
 1627|  3.93k|{
 1628|  3.93k|    struct MPOpts *opts = mpctx->opts;
 1629|       |
 1630|  3.93k|    mp_assert(mpctx->stop_play);
  ------------------
  |  |   41|  3.93k|#define mp_assert assert
  ------------------
 1631|  3.93k|    mpctx->stop_play = 0;
 1632|       |
 1633|  3.93k|    process_hooks(mpctx, "on_before_start_file");
 1634|  3.93k|    if (mpctx->stop_play || !mpctx->playlist->current)
  ------------------
  |  Branch (1634:9): [True: 0, False: 3.93k]
  |  Branch (1634:29): [True: 0, False: 3.93k]
  ------------------
 1635|      0|        return;
 1636|       |
 1637|  3.93k|    mpv_event_start_file start_event = {
 1638|  3.93k|        .playlist_entry_id = mpctx->playlist->current->id,
 1639|  3.93k|    };
 1640|  3.93k|    mpv_event_end_file end_event = {
 1641|  3.93k|        .playlist_entry_id = start_event.playlist_entry_id,
 1642|  3.93k|    };
 1643|       |
 1644|  3.93k|    mp_notify(mpctx, MPV_EVENT_START_FILE, &start_event);
 1645|       |
 1646|  3.93k|    mp_cancel_reset(mpctx->playback_abort);
 1647|       |
 1648|  3.93k|    mpctx->error_playing = MPV_ERROR_LOADING_FAILED;
 1649|  3.93k|    mpctx->filename = NULL;
 1650|  3.93k|    mpctx->shown_aframes = 0;
 1651|  3.93k|    mpctx->shown_vframes = 0;
 1652|  3.93k|    mpctx->last_chapter_seek = -2;
 1653|  3.93k|    mpctx->last_chapter_flag = false;
 1654|  3.93k|    mpctx->last_chapter = -2;
 1655|  3.93k|    mpctx->paused = false;
 1656|  3.93k|    mpctx->playing_msg_shown = false;
 1657|  3.93k|    mpctx->max_frames = -1;
 1658|  3.93k|    mpctx->video_speed = mpctx->audio_speed = opts->playback_speed;
 1659|  3.93k|    mpctx->speed_factor_a = mpctx->speed_factor_v = 1.0;
 1660|  3.93k|    mpctx->display_sync_error = 0.0;
 1661|  3.93k|    mpctx->display_sync_active = false;
 1662|       |    // let get_current_time() show 0 as start time (before playback_pts is set)
 1663|  3.93k|    mpctx->last_seek_pts = 0.0;
 1664|  3.93k|    mpctx->seek = (struct seek_params){ 0 };
 1665|  3.93k|    mpctx->filter_root = mp_filter_create_root(mpctx->global);
 1666|  3.93k|    mp_filter_graph_set_wakeup_cb(mpctx->filter_root, mp_wakeup_core_cb, mpctx);
 1667|  3.93k|    mp_filter_graph_set_max_run_time(mpctx->filter_root, 0.1);
 1668|       |
 1669|  3.93k|    reset_playback_state(mpctx);
 1670|       |
 1671|  3.93k|#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 1672|  3.93k|    if (mpctx->playlist->num_entries > 10)
  ------------------
  |  Branch (1672:9): [True: 3.52k, False: 405]
  ------------------
 1673|  3.52k|        goto terminate_playback;
 1674|    405|#endif
 1675|       |
 1676|    405|    mpctx->playing = mpctx->playlist->current;
 1677|    405|    mp_assert(mpctx->playing);
  ------------------
  |  |   41|    405|#define mp_assert assert
  ------------------
 1678|    405|    mp_assert(mpctx->playing->filename);
  ------------------
  |  |   41|    405|#define mp_assert assert
  ------------------
 1679|    405|    mpctx->playing->reserved += 1;
 1680|       |
 1681|    405|    mpctx->filename = talloc_strdup(NULL, mpctx->playing->filename);
  ------------------
  |  |   50|    405|#define talloc_strdup                   ta_xstrdup
  ------------------
 1682|    405|    mpctx->stream_open_filename = mpctx->filename;
 1683|       |
 1684|    405|    mpctx->add_osd_seek_info &= OSD_SEEK_INFO_CURRENT_FILE;
 1685|       |
 1686|    405|    if (opts->reset_options) {
  ------------------
  |  Branch (1686:9): [True: 0, False: 405]
  ------------------
 1687|      0|        for (int n = 0; opts->reset_options[n]; n++) {
  ------------------
  |  Branch (1687:25): [True: 0, False: 0]
  ------------------
 1688|      0|            const char *opt = opts->reset_options[n];
 1689|      0|            if (opt[0]) {
  ------------------
  |  Branch (1689:17): [True: 0, False: 0]
  ------------------
 1690|      0|                if (strcmp(opt, "all") == 0) {
  ------------------
  |  Branch (1690:21): [True: 0, False: 0]
  ------------------
 1691|      0|                    m_config_backup_all_opts(mpctx->mconfig);
 1692|      0|                } else {
 1693|      0|                    m_config_backup_opt(mpctx->mconfig, opt);
 1694|      0|                }
 1695|      0|            }
 1696|      0|        }
 1697|      0|    }
 1698|       |
 1699|    405|    mp_load_auto_profiles(mpctx);
 1700|       |
 1701|    405|    bool watch_later = mp_load_playback_resume(mpctx, mpctx->filename);
 1702|       |
 1703|    405|    load_per_file_options(mpctx->mconfig, mpctx->playing->params,
 1704|    405|                          mpctx->playing->num_params);
 1705|       |
 1706|    405|    mpctx->remaining_file_loops = mpctx->opts->loop_file;
 1707|    405|    mp_notify_property(mpctx, "remaining-file-loops");
 1708|    405|    mpctx->remaining_ab_loops = mpctx->opts->ab_loop_count;
 1709|    405|    mp_notify_property(mpctx, "remaining-ab-loops");
 1710|       |
 1711|    405|    mpctx->max_frames = opts->play_frames;
 1712|       |
 1713|    405|    handle_force_window(mpctx, false);
 1714|       |
 1715|    405|    if (mpctx->playlist->num_entries > 1 ||
  ------------------
  |  Branch (1715:9): [True: 259, False: 146]
  ------------------
 1716|    405|        mpctx->playing->playlist_path)
  ------------------
  |  Branch (1716:9): [True: 0, False: 146]
  ------------------
 1717|    405|        MP_INFO(mpctx, "Playing: %s\n", mpctx->filename);
  ------------------
  |  |   87|    259|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    259|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1718|       |
 1719|    405|    mp_assert(mpctx->demuxer == NULL);
  ------------------
  |  |   41|    405|#define mp_assert assert
  ------------------
 1720|       |
 1721|    405|    process_hooks(mpctx, "on_load");
 1722|    405|    if (mpctx->stop_play)
  ------------------
  |  Branch (1722:9): [True: 0, False: 405]
  ------------------
 1723|      0|        goto terminate_playback;
 1724|       |
 1725|    405|    if (opts->stream_dump && opts->stream_dump[0]) {
  ------------------
  |  Branch (1725:9): [True: 0, False: 405]
  |  Branch (1725:30): [True: 0, False: 0]
  ------------------
 1726|      0|        if (stream_dump(mpctx, mpctx->stream_open_filename) >= 0)
  ------------------
  |  Branch (1726:13): [True: 0, False: 0]
  ------------------
 1727|      0|            mpctx->error_playing = 1;
 1728|      0|        goto terminate_playback;
 1729|      0|    }
 1730|       |
 1731|    405|    open_demux_reentrant(mpctx);
 1732|    405|    if (!mpctx->stop_play && !mpctx->demuxer) {
  ------------------
  |  Branch (1732:9): [True: 0, False: 405]
  |  Branch (1732:30): [True: 0, False: 0]
  ------------------
 1733|      0|        process_hooks(mpctx, "on_load_fail");
 1734|      0|        if (strcmp(mpctx->stream_open_filename, mpctx->filename) != 0 &&
  ------------------
  |  Branch (1734:13): [True: 0, False: 0]
  ------------------
 1735|      0|            !mpctx->stop_play)
  ------------------
  |  Branch (1735:13): [True: 0, False: 0]
  ------------------
 1736|      0|        {
 1737|      0|            mpctx->error_playing = MPV_ERROR_LOADING_FAILED;
 1738|      0|            open_demux_reentrant(mpctx);
 1739|      0|        }
 1740|      0|    }
 1741|    405|    if (!mpctx->demuxer || mpctx->stop_play)
  ------------------
  |  Branch (1741:9): [True: 244, False: 161]
  |  Branch (1741:28): [True: 161, False: 0]
  ------------------
 1742|    405|        goto terminate_playback;
 1743|       |
 1744|      0|    struct playlist *pl = mpctx->demuxer->playlist;
 1745|      0|    if (pl) {
  ------------------
  |  Branch (1745:9): [True: 0, False: 0]
  ------------------
 1746|       |        // pl->playlist_dir indicates that the playlist was auto-created from
 1747|       |        // the parent file. In this case, mpctx->filename points to real file.
 1748|      0|        if (watch_later && !pl->playlist_dir)
  ------------------
  |  Branch (1748:13): [True: 0, False: 0]
  |  Branch (1748:28): [True: 0, False: 0]
  ------------------
 1749|      0|            mp_delete_watch_later_conf(mpctx, mpctx->filename);
 1750|      0|        playlist_populate_playlist_path(pl, mpctx->filename);
 1751|      0|        if (infinite_playlist_loading_loop(mpctx, pl)) {
  ------------------
  |  Branch (1751:13): [True: 0, False: 0]
  ------------------
 1752|      0|            mpctx->stop_play = PT_STOP;
 1753|      0|            MP_ERR(mpctx, "Infinite playlist loading loop detected.\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1754|      0|            goto terminate_playback;
 1755|      0|        }
 1756|      0|        transfer_playlist(mpctx, pl, &end_event.playlist_insert_id,
 1757|      0|                          &end_event.playlist_insert_num_entries);
 1758|      0|        mp_notify_property(mpctx, "playlist");
 1759|      0|        mpctx->error_playing = 2;
 1760|      0|        goto terminate_playback;
 1761|      0|    }
 1762|       |
 1763|      0|    if (mpctx->opts->rebase_start_time)
  ------------------
  |  Branch (1763:9): [True: 0, False: 0]
  ------------------
 1764|      0|        demux_set_ts_offset(mpctx->demuxer, -mpctx->demuxer->start_time);
 1765|      0|    enable_demux_thread(mpctx, mpctx->demuxer);
 1766|       |
 1767|      0|    add_demuxer_tracks(mpctx, mpctx->demuxer);
 1768|       |
 1769|      0|    load_external_opts(mpctx);
 1770|      0|    if (mpctx->stop_play)
  ------------------
  |  Branch (1770:9): [True: 0, False: 0]
  ------------------
 1771|      0|        goto terminate_playback;
 1772|       |
 1773|      0|    check_previous_track_selection(mpctx);
 1774|       |
 1775|      0|    process_hooks(mpctx, "on_preloaded");
 1776|      0|    if (mpctx->stop_play)
  ------------------
  |  Branch (1776:9): [True: 0, False: 0]
  ------------------
 1777|      0|        goto terminate_playback;
 1778|       |
 1779|      0|    if (reinit_complex_filters(mpctx, false) < 0)
  ------------------
  |  Branch (1779:9): [True: 0, False: 0]
  ------------------
 1780|      0|        goto terminate_playback;
 1781|       |
 1782|      0|    for (int t = 0; t < STREAM_TYPE_COUNT; t++) {
  ------------------
  |  Branch (1782:21): [True: 0, False: 0]
  ------------------
 1783|      0|        for (int i = 0; i < num_ptracks[t]; i++) {
  ------------------
  |  Branch (1783:25): [True: 0, False: 0]
  ------------------
 1784|      0|            struct track *sel = NULL;
 1785|      0|            bool taken = (t == STREAM_VIDEO && mpctx->vo_chain) ||
  ------------------
  |  Branch (1785:27): [True: 0, False: 0]
  |  Branch (1785:48): [True: 0, False: 0]
  ------------------
 1786|      0|                         (t == STREAM_AUDIO && mpctx->ao_chain);
  ------------------
  |  Branch (1786:27): [True: 0, False: 0]
  |  Branch (1786:48): [True: 0, False: 0]
  ------------------
 1787|      0|            if (!taken && opts->stream_auto_sel)
  ------------------
  |  Branch (1787:17): [True: 0, False: 0]
  |  Branch (1787:27): [True: 0, False: 0]
  ------------------
 1788|      0|                sel = select_default_track(mpctx, i, t);
 1789|      0|            mpctx->current_track[i][t] = sel;
 1790|      0|        }
 1791|      0|    }
 1792|      0|    for (int t = 0; t < STREAM_TYPE_COUNT; t++) {
  ------------------
  |  Branch (1792:21): [True: 0, False: 0]
  ------------------
 1793|      0|        for (int i = 0; i < num_ptracks[t]; i++) {
  ------------------
  |  Branch (1793:25): [True: 0, False: 0]
  ------------------
 1794|       |            // One track can strictly feed at most 1 decoder
 1795|      0|            struct track *track = mpctx->current_track[i][t];
 1796|      0|            if (track) {
  ------------------
  |  Branch (1796:17): [True: 0, False: 0]
  ------------------
 1797|      0|                if (track->type != STREAM_SUB &&
  ------------------
  |  Branch (1797:21): [True: 0, False: 0]
  ------------------
 1798|      0|                    mpctx->encode_lavc_ctx &&
  ------------------
  |  Branch (1798:21): [True: 0, False: 0]
  ------------------
 1799|      0|                    !encode_lavc_stream_type_ok(mpctx->encode_lavc_ctx,
  ------------------
  |  Branch (1799:21): [True: 0, False: 0]
  ------------------
 1800|      0|                                                track->type))
 1801|      0|                {
 1802|      0|                    MP_WARN(mpctx, "Disabling %s (not supported by target "
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1803|      0|                            "format).\n", stream_type_name(track->type));
 1804|      0|                    mpctx->current_track[i][t] = NULL;
 1805|      0|                    mark_track_selection(mpctx, i, t, -2); // disable
 1806|      0|                } else if (track->selected) {
  ------------------
  |  Branch (1806:28): [True: 0, False: 0]
  ------------------
 1807|      0|                    MP_ERR(mpctx, "Track %d can't be selected twice.\n",
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1808|      0|                           track->user_tid);
 1809|      0|                    mpctx->current_track[i][t] = NULL;
 1810|      0|                    mark_track_selection(mpctx, i, t, -2); // disable
 1811|      0|                } else {
 1812|      0|                    track->selected = true;
 1813|      0|                }
 1814|      0|            }
 1815|       |
 1816|       |            // Revert selection of unselected tracks to default. This is needed
 1817|       |            // because track properties have inconsistent behavior.
 1818|      0|            if (!track && opts->stream_id[i][t] >= 0)
  ------------------
  |  Branch (1818:17): [True: 0, False: 0]
  |  Branch (1818:27): [True: 0, False: 0]
  ------------------
 1819|      0|                mark_track_selection(mpctx, i, t, -1); // default
 1820|      0|        }
 1821|      0|    }
 1822|       |
 1823|      0|    for (int t = 0; t < STREAM_TYPE_COUNT; t++)
  ------------------
  |  Branch (1823:21): [True: 0, False: 0]
  ------------------
 1824|      0|        for (int n = 0; n < mpctx->num_tracks; n++)
  ------------------
  |  Branch (1824:25): [True: 0, False: 0]
  ------------------
 1825|      0|            if (mpctx->tracks[n]->type == t)
  ------------------
  |  Branch (1825:17): [True: 0, False: 0]
  ------------------
 1826|      0|                reselect_demux_stream(mpctx, mpctx->tracks[n], false);
 1827|       |
 1828|      0|    update_demuxer_properties(mpctx);
 1829|       |
 1830|      0|    update_playback_speed(mpctx);
 1831|       |
 1832|      0|    reinit_video_chain(mpctx);
 1833|      0|    reinit_audio_chain(mpctx);
 1834|      0|    reinit_sub_all(mpctx);
 1835|       |
 1836|      0|    if (mpctx->encode_lavc_ctx) {
  ------------------
  |  Branch (1836:9): [True: 0, False: 0]
  ------------------
 1837|      0|        if (mpctx->vo_chain)
  ------------------
  |  Branch (1837:13): [True: 0, False: 0]
  ------------------
 1838|      0|            encode_lavc_expect_stream(mpctx->encode_lavc_ctx, STREAM_VIDEO);
 1839|      0|        if (mpctx->ao_chain)
  ------------------
  |  Branch (1839:13): [True: 0, False: 0]
  ------------------
 1840|      0|            encode_lavc_expect_stream(mpctx->encode_lavc_ctx, STREAM_AUDIO);
 1841|      0|        encode_lavc_set_metadata(mpctx->encode_lavc_ctx,
 1842|      0|                                 mpctx->demuxer->metadata);
 1843|      0|    }
 1844|       |
 1845|      0|    if (!mpctx->vo_chain && !mpctx->ao_chain && opts->stream_auto_sel) {
  ------------------
  |  Branch (1845:9): [True: 0, False: 0]
  |  Branch (1845:29): [True: 0, False: 0]
  |  Branch (1845:49): [True: 0, False: 0]
  ------------------
 1846|      0|        MP_FATAL(mpctx, "No video or audio streams selected.\n");
  ------------------
  |  |   84|      0|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1847|      0|        mpctx->error_playing = MPV_ERROR_NOTHING_TO_PLAY;
 1848|      0|        goto terminate_playback;
 1849|      0|    }
 1850|       |
 1851|      0|    if (mpctx->vo_chain && mpctx->vo_chain->is_coverart) {
  ------------------
  |  Branch (1851:9): [True: 0, False: 0]
  |  Branch (1851:28): [True: 0, False: 0]
  ------------------
 1852|      0|        MP_INFO(mpctx,
  ------------------
  |  |   87|      0|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1853|      0|            "Displaying cover art. Use --no-audio-display to prevent this.\n");
 1854|      0|    }
 1855|       |
 1856|      0|    if (!mpctx->vo_chain)
  ------------------
  |  Branch (1856:9): [True: 0, False: 0]
  ------------------
 1857|      0|        handle_force_window(mpctx, true);
 1858|       |
 1859|      0|    MP_VERBOSE(mpctx, "Starting playback...\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1860|       |
 1861|      0|    mpctx->playback_initialized = true;
 1862|      0|    mpctx->playing->playlist_prev_attempt = false;
 1863|      0|    mpctx->playlist->playlist_completed = false;
 1864|      0|    mpctx->playlist->playlist_started = true;
 1865|      0|    mp_notify(mpctx, MPV_EVENT_FILE_LOADED, NULL);
 1866|      0|    update_screensaver_state(mpctx);
 1867|      0|    clear_playlist_paths(mpctx);
 1868|       |
 1869|       |    // Clear out subs from the previous file if the video track is a still image.
 1870|      0|    redraw_subs(mpctx);
 1871|       |
 1872|      0|    if (watch_later)
  ------------------
  |  Branch (1872:9): [True: 0, False: 0]
  ------------------
 1873|      0|        mp_delete_watch_later_conf(mpctx, mpctx->filename);
 1874|       |
 1875|      0|    append_to_watch_history(mpctx);
 1876|       |
 1877|      0|    if (mpctx->max_frames == 0) {
  ------------------
  |  Branch (1877:9): [True: 0, False: 0]
  ------------------
 1878|      0|        if (!mpctx->stop_play)
  ------------------
  |  Branch (1878:13): [True: 0, False: 0]
  ------------------
 1879|      0|            mpctx->stop_play = PT_NEXT_ENTRY;
 1880|      0|        mpctx->error_playing = 0;
 1881|      0|        goto terminate_playback;
 1882|      0|    }
 1883|       |
 1884|      0|    if (opts->demuxer_cache_wait) {
  ------------------
  |  Branch (1884:9): [True: 0, False: 0]
  ------------------
 1885|      0|        demux_start_prefetch(mpctx->demuxer);
 1886|       |
 1887|      0|        while (!mpctx->stop_play) {
  ------------------
  |  Branch (1887:16): [True: 0, False: 0]
  ------------------
 1888|      0|            struct demux_reader_state s;
 1889|      0|            demux_get_reader_state(mpctx->demuxer, &s);
 1890|      0|            if (s.idle)
  ------------------
  |  Branch (1890:17): [True: 0, False: 0]
  ------------------
 1891|      0|                break;
 1892|       |
 1893|      0|            mp_idle(mpctx);
 1894|      0|        }
 1895|      0|    }
 1896|       |
 1897|       |    // (Not get_play_start_pts(), which would always trigger a seek.)
 1898|      0|    double play_start_pts = rel_time_to_abs(mpctx, opts->play_start);
 1899|       |
 1900|       |    // Backward playback -> start from end by default.
 1901|      0|    if (play_start_pts == MP_NOPTS_VALUE && opts->play_dir < 0)
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (1901:9): [True: 0, False: 0]
  |  Branch (1901:45): [True: 0, False: 0]
  ------------------
 1902|      0|        play_start_pts = get_start_time(mpctx, -1);
 1903|       |
 1904|      0|    if (play_start_pts != MP_NOPTS_VALUE) {
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (1904:9): [True: 0, False: 0]
  ------------------
 1905|      0|        queue_seek(mpctx, MPSEEK_ABSOLUTE, play_start_pts, MPSEEK_DEFAULT, 0);
 1906|      0|        execute_queued_seek(mpctx);
 1907|      0|    }
 1908|       |
 1909|      0|    update_internal_pause_state(mpctx);
 1910|       |
 1911|      0|    mpctx->error_playing = 0;
 1912|      0|    mpctx->in_playloop = true;
 1913|      0|    while (!mpctx->stop_play)
  ------------------
  |  Branch (1913:12): [True: 0, False: 0]
  ------------------
 1914|      0|        run_playloop(mpctx);
 1915|      0|    mpctx->in_playloop = false;
 1916|       |
 1917|      0|    MP_VERBOSE(mpctx, "EOF code: %d  \n", mpctx->stop_play);
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1918|       |
 1919|  3.93k|terminate_playback:
 1920|       |
 1921|  3.93k|    if (!mpctx->stop_play)
  ------------------
  |  Branch (1921:9): [True: 3.52k, False: 405]
  ------------------
 1922|  3.52k|        mpctx->stop_play = PT_ERROR;
 1923|       |
 1924|  3.93k|    if (mpctx->stop_play != AT_END_OF_FILE)
  ------------------
  |  Branch (1924:9): [True: 3.93k, False: 0]
  ------------------
 1925|  3.93k|        clear_audio_output_buffers(mpctx);
 1926|       |
 1927|  3.93k|    update_core_idle_state(mpctx);
 1928|       |
 1929|  3.93k|    if (mpctx->step_frames) {
  ------------------
  |  Branch (1929:9): [True: 0, False: 3.93k]
  ------------------
 1930|      0|        opts->pause = true;
 1931|      0|        m_config_notify_change_opt_ptr(mpctx->mconfig, &opts->pause);
 1932|      0|    }
 1933|       |
 1934|  3.93k|    process_hooks(mpctx, "on_unload");
 1935|       |
 1936|       |    // time to uninit all, except global stuff:
 1937|  3.93k|    reinit_complex_filters(mpctx, true);
 1938|  3.93k|    uninit_audio_chain(mpctx);
 1939|  3.93k|    uninit_video_chain(mpctx);
 1940|  3.93k|    uninit_sub_all(mpctx);
 1941|  3.93k|    if (!opts->gapless_audio && !mpctx->encode_lavc_ctx)
  ------------------
  |  Branch (1941:9): [True: 0, False: 3.93k]
  |  Branch (1941:33): [True: 0, False: 0]
  ------------------
 1942|      0|        uninit_audio_out(mpctx);
 1943|       |
 1944|  3.93k|    mpctx->playback_initialized = false;
 1945|       |
 1946|  3.93k|    uninit_demuxer(mpctx);
 1947|       |
 1948|       |    // Possibly stop ongoing async commands.
 1949|  3.93k|    mp_abort_playback_async(mpctx);
 1950|       |
 1951|  3.93k|    m_config_restore_backups(mpctx->mconfig);
 1952|       |
 1953|  3.93k|    TA_FREEP(&mpctx->filter_root);
  ------------------
  |  |   81|  3.93k|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|  3.93k|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1954|  3.93k|    talloc_free(mpctx->filtered_tags);
  ------------------
  |  |   47|  3.93k|#define talloc_free                     ta_free
  ------------------
 1955|  3.93k|    mpctx->filtered_tags = NULL;
 1956|       |
 1957|  3.93k|    mp_notify(mpctx, MP_EVENT_TRACKS_CHANGED, NULL);
 1958|       |
 1959|  3.93k|    if (encode_lavc_didfail(mpctx->encode_lavc_ctx))
  ------------------
  |  Branch (1959:9): [True: 0, False: 3.93k]
  ------------------
 1960|      0|        mpctx->stop_play = PT_ERROR;
 1961|       |
 1962|  3.93k|    if (mpctx->stop_play == PT_ERROR && !mpctx->error_playing)
  ------------------
  |  Branch (1962:9): [True: 3.52k, False: 405]
  |  Branch (1962:41): [True: 0, False: 3.52k]
  ------------------
 1963|      0|        mpctx->error_playing = MPV_ERROR_GENERIC;
 1964|       |
 1965|  3.93k|    bool nothing_played = !mpctx->shown_aframes && !mpctx->shown_vframes &&
  ------------------
  |  Branch (1965:27): [True: 3.93k, False: 0]
  |  Branch (1965:52): [True: 3.93k, False: 0]
  ------------------
 1966|  3.93k|                          mpctx->error_playing <= 0;
  ------------------
  |  Branch (1966:27): [True: 3.93k, False: 0]
  ------------------
 1967|  3.93k|    bool playlist_prev_continue = false;
 1968|  3.93k|    switch (mpctx->stop_play) {
  ------------------
  |  Branch (1968:13): [True: 0, False: 3.93k]
  ------------------
 1969|  3.52k|    case PT_ERROR:
  ------------------
  |  Branch (1969:5): [True: 3.52k, False: 405]
  ------------------
 1970|  3.52k|    case AT_END_OF_FILE:
  ------------------
  |  Branch (1970:5): [True: 0, False: 3.93k]
  ------------------
 1971|  3.52k|    {
 1972|  3.52k|        if (mpctx->error_playing == 0 && nothing_played)
  ------------------
  |  Branch (1972:13): [True: 0, False: 3.52k]
  |  Branch (1972:42): [True: 0, False: 0]
  ------------------
 1973|      0|            mpctx->error_playing = MPV_ERROR_NOTHING_TO_PLAY;
 1974|  3.52k|        if (mpctx->error_playing < 0) {
  ------------------
  |  Branch (1974:13): [True: 3.52k, False: 0]
  ------------------
 1975|  3.52k|            end_event.error = mpctx->error_playing;
 1976|  3.52k|            end_event.reason = MPV_END_FILE_REASON_ERROR;
 1977|  3.52k|        } else if (mpctx->error_playing == 2) {
  ------------------
  |  Branch (1977:20): [True: 0, False: 0]
  ------------------
 1978|      0|            end_event.reason = MPV_END_FILE_REASON_REDIRECT;
 1979|      0|        } else {
 1980|      0|            end_event.reason = MPV_END_FILE_REASON_EOF;
 1981|      0|        }
 1982|  3.52k|        if (mpctx->playing) {
  ------------------
  |  Branch (1982:13): [True: 0, False: 3.52k]
  ------------------
 1983|      0|            mpctx->playing->init_failed = nothing_played;
 1984|      0|            playlist_prev_continue = mpctx->playing->playlist_prev_attempt &&
  ------------------
  |  Branch (1984:38): [True: 0, False: 0]
  ------------------
 1985|      0|                                     nothing_played;
  ------------------
  |  Branch (1985:38): [True: 0, False: 0]
  ------------------
 1986|      0|            mpctx->playing->playlist_prev_attempt = false;
 1987|      0|        }
 1988|  3.52k|        break;
 1989|  3.52k|    }
 1990|       |    // Note that error_playing is meaningless in these cases.
 1991|      0|    case PT_NEXT_ENTRY:
  ------------------
  |  Branch (1991:5): [True: 0, False: 3.93k]
  ------------------
 1992|      0|    case PT_CURRENT_ENTRY:
  ------------------
  |  Branch (1992:5): [True: 0, False: 3.93k]
  ------------------
 1993|      0|    case PT_STOP:           end_event.reason = MPV_END_FILE_REASON_STOP; break;
  ------------------
  |  Branch (1993:5): [True: 0, False: 3.93k]
  ------------------
 1994|    405|    case PT_QUIT:           end_event.reason = MPV_END_FILE_REASON_QUIT; break;
  ------------------
  |  Branch (1994:5): [True: 405, False: 3.52k]
  ------------------
 1995|  3.93k|    };
 1996|  3.93k|    mp_notify(mpctx, MPV_EVENT_END_FILE, &end_event);
 1997|       |
 1998|  3.93k|    MP_VERBOSE(mpctx, "finished playback, %s (reason %d)\n",
  ------------------
  |  |   88|  3.93k|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  3.93k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1999|  3.93k|               mpv_error_string(end_event.error), end_event.reason);
 2000|  3.93k|    if (end_event.error == MPV_ERROR_UNKNOWN_FORMAT)
  ------------------
  |  Branch (2000:9): [True: 0, False: 3.93k]
  ------------------
 2001|  3.93k|        MP_ERR(mpctx, "Failed to recognize file format.\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 2002|       |
 2003|  3.93k|    if (mpctx->playing)
  ------------------
  |  Branch (2003:9): [True: 405, False: 3.52k]
  ------------------
 2004|    405|        playlist_entry_unref(mpctx->playing);
 2005|  3.93k|    mpctx->playing = NULL;
 2006|  3.93k|    talloc_free(mpctx->filename);
  ------------------
  |  |   47|  3.93k|#define talloc_free                     ta_free
  ------------------
 2007|  3.93k|    mpctx->filename = NULL;
 2008|  3.93k|    mpctx->stream_open_filename = NULL;
 2009|       |
 2010|  3.93k|    if (end_event.error < 0 && nothing_played) {
  ------------------
  |  Branch (2010:9): [True: 3.52k, False: 405]
  |  Branch (2010:32): [True: 3.52k, False: 0]
  ------------------
 2011|  3.52k|        mpctx->files_broken++;
 2012|  3.52k|    } else if (end_event.error < 0) {
  ------------------
  |  Branch (2012:16): [True: 0, False: 405]
  ------------------
 2013|      0|        mpctx->files_errored++;
 2014|    405|    } else {
 2015|    405|        mpctx->files_played++;
 2016|    405|    }
 2017|       |
 2018|  3.93k|    mp_assert(mpctx->stop_play);
  ------------------
  |  |   41|  3.93k|#define mp_assert assert
  ------------------
 2019|       |
 2020|  3.93k|    process_hooks(mpctx, "on_after_end_file");
 2021|       |
 2022|  3.93k|    if (playlist_prev_continue) {
  ------------------
  |  Branch (2022:9): [True: 0, False: 3.93k]
  ------------------
 2023|      0|        struct playlist_entry *e = mp_next_file(mpctx, -1, false, true);
 2024|      0|        if (e) {
  ------------------
  |  Branch (2024:13): [True: 0, False: 0]
  ------------------
 2025|      0|            mp_set_playlist_entry(mpctx, e);
 2026|      0|            play_current_file(mpctx);
 2027|      0|        }
 2028|      0|    }
 2029|  3.93k|}
loadfile.c:process_hooks:
 1061|  12.2k|{
 1062|  12.2k|    mp_hook_start(mpctx, name);
 1063|       |
 1064|  12.2k|    while (!mp_hook_test_completion(mpctx, name)) {
  ------------------
  |  Branch (1064:12): [True: 0, False: 12.2k]
  ------------------
 1065|      0|        mp_idle(mpctx);
 1066|       |
 1067|       |        // We have no idea what blocks a hook, so just do a full abort. This
 1068|       |        // does nothing for hooks that happen outside of playback.
 1069|      0|        if (mpctx->stop_play)
  ------------------
  |  Branch (1069:13): [True: 0, False: 0]
  ------------------
 1070|      0|            mp_abort_playback_async(mpctx);
 1071|      0|    }
 1072|  12.2k|}
loadfile.c:load_per_file_options:
 1112|    405|{
 1113|    405|    for (int n = 0; n < params_count; n++) {
  ------------------
  |  Branch (1113:21): [True: 0, False: 405]
  ------------------
 1114|      0|        m_config_set_option_cli(conf, params[n].name, params[n].value,
 1115|      0|                                M_SETOPT_BACKUP);
 1116|      0|    }
 1117|    405|}
loadfile.c:open_demux_reentrant:
 1213|    405|{
 1214|    405|    char *url = mpctx->stream_open_filename;
 1215|       |
 1216|    405|    if (mpctx->open_active) {
  ------------------
  |  Branch (1216:9): [True: 0, False: 405]
  ------------------
 1217|      0|        bool done = atomic_load(&mpctx->open_done);
 1218|      0|        bool failed = done && !mpctx->open_res_demuxer;
  ------------------
  |  Branch (1218:23): [True: 0, False: 0]
  |  Branch (1218:31): [True: 0, False: 0]
  ------------------
 1219|      0|        bool correct_url = strcmp(mpctx->open_url, url) == 0;
 1220|       |
 1221|      0|        if (correct_url && !mpctx->demuxer_changed && !failed) {
  ------------------
  |  Branch (1221:13): [True: 0, False: 0]
  |  Branch (1221:28): [True: 0, False: 0]
  |  Branch (1221:55): [True: 0, False: 0]
  ------------------
 1222|      0|            MP_VERBOSE(mpctx, "Using prefetched/prefetching URL.\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1223|      0|        } else {
 1224|      0|            if (correct_url && failed) {
  ------------------
  |  Branch (1224:17): [True: 0, False: 0]
  |  Branch (1224:32): [True: 0, False: 0]
  ------------------
 1225|      0|                MP_VERBOSE(mpctx, "Prefetched URL failed, retrying.\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1226|      0|            } else if (mpctx->demuxer_changed) {
  ------------------
  |  Branch (1226:24): [True: 0, False: 0]
  ------------------
 1227|      0|                if (done) {
  ------------------
  |  Branch (1227:21): [True: 0, False: 0]
  ------------------
 1228|      0|                    MP_VERBOSE(mpctx, "Dropping finished prefetch because demuxer options changed.\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1229|      0|                } else {
 1230|      0|                    MP_VERBOSE(mpctx, "Aborting ongoing prefetch because demuxer options changed.\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1231|      0|                }
 1232|      0|            } else {
 1233|      0|                if (done) {
  ------------------
  |  Branch (1233:21): [True: 0, False: 0]
  ------------------
 1234|      0|                    MP_VERBOSE(mpctx, "Dropping finished prefetch of wrong URL.\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1235|      0|                } else {
 1236|      0|                    MP_VERBOSE(mpctx, "Aborting ongoing prefetch of wrong URL.\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1237|      0|                }
 1238|      0|            }
 1239|      0|            cancel_open(mpctx);
 1240|      0|        }
 1241|      0|    }
 1242|       |
 1243|    405|    if (!mpctx->open_active)
  ------------------
  |  Branch (1243:9): [True: 405, False: 0]
  ------------------
 1244|    405|        start_open(mpctx, url, mpctx->playing->stream_flags, false);
 1245|       |
 1246|       |    // If thread failed to start, cancel the playback
 1247|    405|    if (!mpctx->open_active)
  ------------------
  |  Branch (1247:9): [True: 0, False: 405]
  ------------------
 1248|      0|        goto cancel;
 1249|       |
 1250|       |    // User abort should cancel the opener now.
 1251|    405|    mp_cancel_set_parent(mpctx->open_cancel, mpctx->playback_abort);
 1252|       |
 1253|  1.19k|    while (!atomic_load(&mpctx->open_done)) {
  ------------------
  |  Branch (1253:12): [True: 790, False: 405]
  ------------------
 1254|    790|        mp_idle(mpctx);
 1255|       |
 1256|    790|        if (mpctx->stop_play)
  ------------------
  |  Branch (1256:13): [True: 789, False: 1]
  ------------------
 1257|    789|            mp_abort_playback_async(mpctx);
 1258|    790|    }
 1259|       |
 1260|    405|    if (mpctx->open_res_demuxer) {
  ------------------
  |  Branch (1260:9): [True: 161, False: 244]
  ------------------
 1261|    161|        mpctx->demuxer = mpctx->open_res_demuxer;
 1262|    161|        mpctx->open_res_demuxer = NULL;
 1263|    161|        mp_cancel_set_parent(mpctx->demuxer->cancel, mpctx->playback_abort);
 1264|    244|    } else {
 1265|    244|        mpctx->error_playing = mpctx->open_res_error;
 1266|    244|    }
 1267|       |
 1268|    405|cancel:
 1269|    405|    cancel_open(mpctx); // cleanup
 1270|    405|}
loadfile.c:uninit_demuxer:
  193|  3.93k|{
  194|  15.7k|    for (int t = 0; t < STREAM_TYPE_COUNT; t++) {
  ------------------
  |  Branch (194:21): [True: 11.7k, False: 3.93k]
  ------------------
  195|  27.5k|        for (int r = 0; r < num_ptracks[t]; r++)
  ------------------
  |  Branch (195:25): [True: 15.7k, False: 11.7k]
  ------------------
  196|  15.7k|            mpctx->current_track[r][t] = NULL;
  197|  11.7k|    }
  198|       |
  199|  3.93k|    talloc_free(mpctx->chapters);
  ------------------
  |  |   47|  3.93k|#define talloc_free                     ta_free
  ------------------
  200|  3.93k|    mpctx->chapters = NULL;
  201|  3.93k|    mpctx->num_chapters = 0;
  202|       |
  203|  3.93k|    mp_abort_cache_dumping(mpctx);
  204|       |
  205|  3.93k|    struct demuxer **demuxers = NULL;
  206|  3.93k|    int num_demuxers = 0;
  207|       |
  208|  3.93k|    if (mpctx->demuxer)
  ------------------
  |  Branch (208:9): [True: 161, False: 3.77k]
  ------------------
  209|    161|        MP_TARRAY_APPEND(NULL, demuxers, num_demuxers, mpctx->demuxer);
  ------------------
  |  |  105|    161|    do {                                            \
  |  |  106|    161|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|    161|    do {                                            \
  |  |  |  |   97|    161|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|    161|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|    161|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|    161|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 161, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|    161|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|    161|    do {                                                        \
  |  |  |  |  |  |   89|    161|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|    161|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|    161|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|    161|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|    161|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|    161|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|    161|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|    161|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|    161|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|    161|        (idxvar)++;                                 \
  |  |  109|    161|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  210|  3.93k|    mpctx->demuxer = NULL;
  211|       |
  212|  3.93k|    for (int i = 0; i < mpctx->num_tracks; i++) {
  ------------------
  |  Branch (212:21): [True: 0, False: 3.93k]
  ------------------
  213|      0|        struct track *track = mpctx->tracks[i];
  214|       |
  215|      0|        mp_assert(!track->dec && !track->d_sub);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  216|      0|        mp_assert(!track->vo_c && !track->ao_c);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  217|      0|        mp_assert(!track->sink);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  218|       |
  219|       |        // Demuxers can be added in any order (if they appear mid-stream), and
  220|       |        // we can't know which tracks uses which, so here's some O(n^2) trash.
  221|      0|        for (int n = 0; n < num_demuxers; n++) {
  ------------------
  |  Branch (221:25): [True: 0, False: 0]
  ------------------
  222|      0|            if (demuxers[n] == track->demuxer) {
  ------------------
  |  Branch (222:17): [True: 0, False: 0]
  ------------------
  223|      0|                track->demuxer = NULL;
  224|      0|                break;
  225|      0|            }
  226|      0|        }
  227|      0|        if (track->demuxer)
  ------------------
  |  Branch (227:13): [True: 0, False: 0]
  ------------------
  228|      0|            MP_TARRAY_APPEND(NULL, demuxers, num_demuxers, track->demuxer);
  ------------------
  |  |  105|      0|    do {                                            \
  |  |  106|      0|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      0|    do {                                            \
  |  |  |  |   97|      0|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      0|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      0|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      0|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      0|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      0|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      0|        (idxvar)++;                                 \
  |  |  109|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  229|       |
  230|      0|        talloc_free(track);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  231|      0|    }
  232|  3.93k|    mpctx->num_tracks = 0;
  233|       |
  234|  3.93k|    kill_demuxers_reentrant(mpctx, demuxers, num_demuxers);
  235|  3.93k|    talloc_free(demuxers);
  ------------------
  |  |   47|  3.93k|#define talloc_free                     ta_free
  ------------------
  236|  3.93k|}
loadfile.c:kill_demuxers_reentrant:
  135|  3.93k|{
  136|  3.93k|    struct demux_free_async_state **items = NULL;
  137|  3.93k|    int num_items = 0;
  138|       |
  139|  4.09k|    for (int n = 0; n < num_demuxers; n++) {
  ------------------
  |  Branch (139:21): [True: 161, False: 3.93k]
  ------------------
  140|    161|        struct demuxer *d = demuxers[n];
  141|       |
  142|    161|        if (!demux_cancel_test(d)) {
  ------------------
  |  Branch (142:13): [True: 0, False: 161]
  ------------------
  143|       |            // Make sure it is set if it wasn't yet.
  144|      0|            demux_set_wakeup_cb(d, wakeup_demux, mpctx);
  145|       |
  146|      0|            struct demux_free_async_state *item = demux_free_async(d);
  147|      0|            if (item) {
  ------------------
  |  Branch (147:17): [True: 0, False: 0]
  ------------------
  148|      0|                MP_TARRAY_APPEND(NULL, items, num_items, item);
  ------------------
  |  |  105|      0|    do {                                            \
  |  |  106|      0|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      0|    do {                                            \
  |  |  |  |   97|      0|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      0|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      0|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      0|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      0|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      0|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      0|        (idxvar)++;                                 \
  |  |  109|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  149|      0|                d = NULL;
  150|      0|            }
  151|      0|        }
  152|       |
  153|    161|        demux_cancel_and_free(d);
  154|    161|    }
  155|       |
  156|  3.93k|    if (!num_items)
  ------------------
  |  Branch (156:9): [True: 3.93k, False: 0]
  ------------------
  157|  3.93k|        return;
  158|       |
  159|      0|    MP_DBG(mpctx, "Terminating demuxers...\n");
  ------------------
  |  |   89|      0|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  160|       |
  161|      0|    double end = mp_time_sec() + mpctx->opts->demux_termination_timeout;
  162|      0|    bool force = false;
  163|      0|    while (num_items) {
  ------------------
  |  Branch (163:12): [True: 0, False: 0]
  ------------------
  164|      0|        double wait = end - mp_time_sec();
  165|       |
  166|      0|        for (int n = 0; n < num_items; n++) {
  ------------------
  |  Branch (166:25): [True: 0, False: 0]
  ------------------
  167|      0|            struct demux_free_async_state *item = items[n];
  168|      0|            if (demux_free_async_finish(item)) {
  ------------------
  |  Branch (168:17): [True: 0, False: 0]
  ------------------
  169|      0|                items[n] = items[num_items - 1];
  170|      0|                num_items -= 1;
  171|      0|                n--;
  172|      0|                goto repeat;
  173|      0|            } else if (wait < 0) {
  ------------------
  |  Branch (173:24): [True: 0, False: 0]
  ------------------
  174|      0|                demux_free_async_force(item);
  175|      0|                if (!force)
  ------------------
  |  Branch (175:21): [True: 0, False: 0]
  ------------------
  176|      0|                    MP_VERBOSE(mpctx, "Forcefully terminating demuxers...\n");
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  177|      0|                force = true;
  178|      0|            }
  179|      0|        }
  180|       |
  181|      0|        if (wait >= 0)
  ------------------
  |  Branch (181:13): [True: 0, False: 0]
  ------------------
  182|      0|            mp_set_timeout(mpctx, wait);
  183|      0|        mp_idle(mpctx);
  184|      0|    repeat:;
  185|      0|    }
  186|       |
  187|      0|    talloc_free(items);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  188|       |
  189|      0|    MP_DBG(mpctx, "Done terminating demuxers.\n");
  ------------------
  |  |   89|      0|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  190|      0|}
loadfile.c:cancel_open:
 1167|  12.9k|{
 1168|  12.9k|    if (mpctx->open_cancel)
  ------------------
  |  Branch (1168:9): [True: 405, False: 12.5k]
  ------------------
 1169|    405|        mp_cancel_trigger(mpctx->open_cancel);
 1170|       |
 1171|  12.9k|    if (mpctx->open_active)
  ------------------
  |  Branch (1171:9): [True: 405, False: 12.5k]
  ------------------
 1172|    405|        mp_thread_join(mpctx->open_thread);
  ------------------
  |  |  212|    405|#define mp_thread_join(t)         pthread_join(t, NULL)
  ------------------
 1173|  12.9k|    mpctx->open_active = false;
 1174|       |
 1175|  12.9k|    if (mpctx->open_res_demuxer)
  ------------------
  |  Branch (1175:9): [True: 0, False: 12.9k]
  ------------------
 1176|      0|        demux_cancel_and_free(mpctx->open_res_demuxer);
 1177|  12.9k|    mpctx->open_res_demuxer = NULL;
 1178|       |
 1179|  12.9k|    TA_FREEP(&mpctx->open_cancel);
  ------------------
  |  |   81|  12.9k|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|  12.9k|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1180|  12.9k|    TA_FREEP(&mpctx->open_url);
  ------------------
  |  |   81|  12.9k|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|  12.9k|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1181|  12.9k|    TA_FREEP(&mpctx->open_format);
  ------------------
  |  |   81|  12.9k|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|  12.9k|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1182|       |
 1183|  12.9k|    atomic_store(&mpctx->open_done, false);
 1184|  12.9k|}

mp_update_logging:
  122|  29.2k|{
  123|  29.2k|    bool had_log_file = mp_msg_has_log_file(mpctx->global);
  124|       |
  125|  29.2k|    mp_msg_update_msglevels(mpctx->global, mpctx->opts);
  126|       |
  127|  29.2k|    bool enable = mpctx->opts->use_terminal;
  128|  29.2k|    bool enabled = cas_terminal_owner(mpctx, mpctx);
  129|  29.2k|    if (enable != enabled) {
  ------------------
  |  Branch (129:9): [True: 3.11k, False: 26.1k]
  ------------------
  130|  3.11k|        if (enable && cas_terminal_owner(NULL, mpctx)) {
  ------------------
  |  Branch (130:13): [True: 3.11k, False: 2]
  |  Branch (130:23): [True: 3.11k, False: 0]
  ------------------
  131|  3.11k|            terminal_init();
  132|  3.11k|            enabled = true;
  133|  3.11k|        } else if (!enable) {
  ------------------
  |  Branch (133:20): [True: 2, False: 0]
  ------------------
  134|      2|            terminal_uninit();
  135|      2|            cas_terminal_owner(mpctx, NULL);
  136|      2|        }
  137|  3.11k|    }
  138|       |
  139|  29.2k|    if (mp_msg_has_log_file(mpctx->global) && !had_log_file) {
  ------------------
  |  Branch (139:9): [True: 0, False: 29.2k]
  |  Branch (139:47): [True: 0, False: 0]
  ------------------
  140|       |        // for log-file=... in config files.
  141|       |        // we did flush earlier messages, but they were in a cyclic buffer, so
  142|       |        // the version might have been overwritten. ensure we have it.
  143|      0|        mp_print_version(mpctx->log, false);
  144|      0|    }
  145|       |
  146|  29.2k|    if (enabled && !preinit && mpctx->opts->consolecontrols)
  ------------------
  |  Branch (146:9): [True: 6.00k, False: 23.2k]
  |  Branch (146:20): [True: 2.89k, False: 3.11k]
  |  Branch (146:32): [True: 12, False: 2.88k]
  ------------------
  147|     12|        terminal_setup_getch(mpctx->input);
  148|       |
  149|  29.2k|    if (enabled)
  ------------------
  |  Branch (149:9): [True: 6.00k, False: 23.2k]
  ------------------
  150|  6.00k|        encoder_update_log(mpctx->global);
  151|  29.2k|}
mp_print_version:
  154|  17.9k|{
  155|  17.9k|    int v = always ? MSGL_INFO : MSGL_V;
  ------------------
  |  Branch (155:13): [True: 916, False: 17.0k]
  ------------------
  156|  17.9k|    mp_msg(log, v, "%s %s\n", mpv_version, mpv_copyright);
  157|  17.9k|    if (strcmp(mpv_builddate, "UNKNOWN"))
  ------------------
  |  Branch (157:9): [True: 17.9k, False: 0]
  ------------------
  158|  17.9k|        mp_msg(log, v, " built on %s\n", mpv_builddate);
  159|  17.9k|    mp_msg(log, v, "libplacebo version: %s\n", PL_VERSION);
  ------------------
  |  |   32|  17.9k|#define PL_VERSION (pl_version())
  ------------------
  160|  17.9k|    check_library_versions(log, v);
  161|       |    // Only in verbose mode.
  162|  17.9k|    if (!always) {
  ------------------
  |  Branch (162:9): [True: 17.0k, False: 916]
  ------------------
  163|  17.0k|        mp_msg(log, MSGL_V, "Configuration: " CONFIGURATION "\n");
  164|  17.0k|        mp_msg(log, MSGL_V, "List of enabled features: " FULLCONFIG "\n");
  165|       |        #ifdef NDEBUG
  166|       |            mp_msg(log, MSGL_V, "Built with NDEBUG.\n");
  167|       |        #endif
  168|  17.0k|    }
  169|  17.9k|}
mp_destroy:
  172|  17.0k|{
  173|  17.0k|    mp_shutdown_clients(mpctx);
  174|       |
  175|  17.0k|    mp_uninit_ipc(mpctx->ipc_ctx);
  176|  17.0k|    mpctx->ipc_ctx = NULL;
  177|       |
  178|  17.0k|    uninit_audio_out(mpctx);
  179|  17.0k|    uninit_video_out(mpctx);
  180|       |
  181|       |    // If it's still set here, it's an error.
  182|  17.0k|    encode_lavc_free(mpctx->encode_lavc_ctx);
  183|  17.0k|    mpctx->encode_lavc_ctx = NULL;
  184|       |
  185|  17.0k|    command_uninit(mpctx);
  186|       |
  187|  17.0k|    mp_clients_destroy(mpctx);
  188|       |
  189|  17.0k|    osd_free(mpctx->osd);
  190|       |
  191|       |#if HAVE_COCOA
  192|       |    cocoa_set_input_context(NULL);
  193|       |#endif
  194|       |
  195|  17.0k|    if (cas_terminal_owner(mpctx, mpctx)) {
  ------------------
  |  Branch (195:9): [True: 3.11k, False: 13.9k]
  ------------------
  196|  3.11k|        terminal_uninit();
  197|  3.11k|        cas_terminal_owner(mpctx, NULL);
  198|  3.11k|    }
  199|       |
  200|  17.0k|    mp_input_uninit(mpctx->input);
  201|  17.0k|    mp_clipboard_destroy(mpctx->clipboard);
  202|       |
  203|  17.0k|    uninit_libav(mpctx->global);
  204|       |
  205|  17.0k|    mp_msg_uninit(mpctx->global);
  206|  17.0k|    mp_assert(!mpctx->num_abort_list);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  207|  17.0k|    talloc_free(mpctx->abort_list);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  208|  17.0k|    mp_mutex_destroy(&mpctx->abort_lock);
  ------------------
  |  |  130|  17.0k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
  209|  17.0k|    talloc_free(mpctx->mconfig); // destroy before dispatch
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  210|  17.0k|    talloc_free(mpctx);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  211|  17.0k|}
mp_create:
  253|  17.0k|{
  254|  17.0k|    if (!check_locale()) {
  ------------------
  |  Branch (254:9): [True: 0, False: 17.0k]
  ------------------
  255|       |        // Normally, we never print anything (except if the "terminal" option
  256|       |        // is enabled), so this is an exception.
  257|      0|        fprintf(stderr, "Non-C locale detected. This is not supported.\n"
  258|      0|                        "Call 'setlocale(LC_NUMERIC, \"C\");' in your code.\n");
  259|      0|        return NULL;
  260|      0|    }
  261|       |
  262|  17.0k|    char *enable_talloc = getenv("MPV_LEAK_REPORT");
  263|  17.0k|    if (enable_talloc && strcmp(enable_talloc, "1") == 0)
  ------------------
  |  Branch (263:9): [True: 0, False: 17.0k]
  |  Branch (263:26): [True: 0, False: 0]
  ------------------
  264|      0|        talloc_enable_leak_report();
  ------------------
  |  |   42|      0|#define talloc_enable_leak_report       ta_enable_leak_report
  ------------------
  265|       |
  266|  17.0k|    mp_time_init();
  267|       |
  268|  17.0k|    struct MPContext *mpctx = talloc(NULL, MPContext);
  ------------------
  |  |   26|  17.0k|#define talloc                          ta_xnew
  |  |  ------------------
  |  |  |  |  133|  17.0k|#define ta_xnew(...)                    ta_oom_g(ta_new(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  269|  17.0k|    *mpctx = (struct MPContext){
  270|  17.0k|        .last_chapter = -2,
  271|  17.0k|        .term_osd_contents = talloc_strdup(mpctx, ""),
  ------------------
  |  |   50|  17.0k|#define talloc_strdup                   ta_xstrdup
  ------------------
  272|  17.0k|        .osd_progbar = { .type = -1 },
  273|  17.0k|        .playlist = talloc_zero(mpctx, struct playlist),
  ------------------
  |  |   27|  17.0k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  17.0k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  274|  17.0k|        .dispatch = mp_dispatch_create(mpctx),
  275|  17.0k|        .playback_abort = mp_cancel_new(mpctx),
  276|  17.0k|        .thread_pool = mp_thread_pool_create(mpctx, 0, 1, 30),
  277|  17.0k|        .stop_play = PT_NEXT_ENTRY,
  278|  17.0k|        .play_dir = 1,
  279|  17.0k|    };
  280|       |
  281|  17.0k|    mp_mutex_init(&mpctx->abort_lock);
  282|       |
  283|  17.0k|    mpctx->global = talloc_zero(mpctx, struct mpv_global);
  ------------------
  |  |   27|  17.0k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  17.0k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  284|       |
  285|  17.0k|    demux_packet_pool_init(mpctx->global);
  286|  17.0k|    stats_global_init(mpctx->global);
  287|       |
  288|       |    // Nothing must call mp_msg*() and related before this
  289|  17.0k|    mp_msg_init(mpctx->global);
  290|  17.0k|    mpctx->log = mp_log_new(mpctx, mpctx->global->log, "!cplayer");
  291|  17.0k|    mpctx->statusline = mp_log_new(mpctx, mpctx->log, "!statusline");
  292|       |
  293|  17.0k|    mpctx->stats = stats_ctx_create(mpctx, mpctx->global, "main");
  294|       |
  295|       |    // Create the config context and register the options
  296|  17.0k|    mpctx->mconfig = m_config_new(mpctx, mpctx->log, &mp_opt_root);
  297|  17.0k|    mpctx->opts = mpctx->mconfig->optstruct;
  298|  17.0k|    mpctx->global->config = mpctx->mconfig->shadow;
  299|  17.0k|    mpctx->mconfig->includefunc = cfg_include;
  300|  17.0k|    mpctx->mconfig->includefunc_ctx = mpctx;
  301|  17.0k|    mpctx->mconfig->use_profiles = true;
  302|  17.0k|    mpctx->mconfig->is_toplevel = true;
  303|  17.0k|    mpctx->mconfig->global = mpctx->global;
  304|  17.0k|    m_config_parse(mpctx->mconfig, "", bstr0(def_config), NULL, 0);
  305|       |
  306|  17.0k|    mpctx->input = mp_input_init(mpctx->global, mp_wakeup_core_cb, mpctx);
  307|  17.0k|    screenshot_init(mpctx);
  308|  17.0k|    command_init(mpctx);
  309|  17.0k|    init_libav(mpctx->global);
  310|  17.0k|    mp_clients_init(mpctx);
  311|  17.0k|    mpctx->osd = osd_create(mpctx->global);
  312|       |
  313|       |#if HAVE_COCOA
  314|       |    cocoa_set_input_context(mpctx->input);
  315|       |#endif
  316|       |
  317|  17.0k|    char *verbose_env = getenv("MPV_VERBOSE");
  318|  17.0k|    if (verbose_env)
  ------------------
  |  Branch (318:9): [True: 0, False: 17.0k]
  ------------------
  319|      0|        mpctx->opts->verbose = atoi(verbose_env);
  320|       |
  321|  17.0k|    mp_cancel_trigger(mpctx->playback_abort);
  322|       |
  323|  17.0k|    return mpctx;
  324|  17.0k|}
mp_initialize:
  332|  17.0k|{
  333|  17.0k|    struct MPOpts *opts = mpctx->opts;
  334|       |
  335|  17.0k|    mp_assert(!mpctx->initialized);
  ------------------
  |  |   41|  17.0k|#define mp_assert assert
  ------------------
  336|       |
  337|       |    // Preparse the command line, so we can init the terminal early.
  338|  17.0k|    if (options) {
  ------------------
  |  Branch (338:9): [True: 17.0k, False: 0]
  ------------------
  339|  17.0k|        m_config_preparse_command_line(mpctx->mconfig, mpctx->global,
  340|  17.0k|                                       &opts->verbose, options);
  341|  17.0k|    }
  342|       |
  343|  17.0k|    mp_init_paths(mpctx->global, opts);
  344|  17.0k|    mp_msg_set_early_logging(mpctx->global, true);
  345|  17.0k|    mp_update_logging(mpctx, true);
  346|       |
  347|  17.0k|    if (options) {
  ------------------
  |  Branch (347:9): [True: 17.0k, False: 0]
  ------------------
  348|  17.0k|        MP_VERBOSE(mpctx, "Command line options:");
  ------------------
  |  |   88|  17.0k|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  17.0k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  349|   276k|        for (int i = 0; options[i]; i++)
  ------------------
  |  Branch (349:25): [True: 259k, False: 17.0k]
  ------------------
  350|   259k|            MP_VERBOSE(mpctx, " '%s'", options[i]);
  ------------------
  |  |   88|   259k|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|   259k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  351|  17.0k|        MP_VERBOSE(mpctx, "\n");
  ------------------
  |  |   88|  17.0k|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  17.0k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  352|  17.0k|    }
  353|       |
  354|  17.0k|    mp_print_version(mpctx->log, false);
  355|       |
  356|  17.0k|    mp_parse_cfgfiles(mpctx);
  357|       |
  358|  17.0k|    if (options) {
  ------------------
  |  Branch (358:9): [True: 17.0k, False: 0]
  ------------------
  359|  17.0k|        int r = m_config_parse_mp_command_line(mpctx->mconfig, mpctx->playlist,
  360|  17.0k|                                               mpctx->global, options);
  361|  17.0k|        if (r < 0)
  ------------------
  |  Branch (361:13): [True: 4.92k, False: 12.1k]
  ------------------
  362|  4.92k|            return r == M_OPT_EXIT ? 1 : -1;
  ------------------
  |  |  533|  4.92k|#define M_OPT_EXIT              -6
  ------------------
  |  Branch (362:20): [True: 385, False: 4.53k]
  ------------------
  363|  17.0k|    }
  364|       |
  365|  12.1k|    if (opts->operation_mode == 1) {
  ------------------
  |  Branch (365:9): [True: 4, False: 12.1k]
  ------------------
  366|      4|        m_config_set_profile(mpctx->mconfig, "builtin-pseudo-gui",
  367|      4|                             M_SETOPT_NO_OVERWRITE);
  368|      4|        m_config_set_profile(mpctx->mconfig, "pseudo-gui", 0);
  369|      4|    }
  370|       |
  371|       |    // Backup the default settings, which should not be stored in the resume
  372|       |    // config files. This explicitly includes values set by config files and
  373|       |    // the command line.
  374|  12.1k|    m_config_backup_watch_later_opts(mpctx->mconfig);
  375|       |
  376|  12.1k|    mp_input_load_config(mpctx->input);
  377|       |
  378|       |    // From this point on, all mpctx members are initialized.
  379|  12.1k|    mpctx->initialized = true;
  380|  12.1k|    mpctx->mconfig->option_change_callback = mp_option_change_callback;
  381|  12.1k|    mpctx->mconfig->option_change_callback_ctx = mpctx;
  382|  12.1k|    m_config_set_update_dispatch_queue(mpctx->mconfig, mpctx->dispatch);
  383|       |    // Run all update handlers.
  384|  12.1k|    mp_option_change_callback(mpctx, NULL, UPDATE_OPTS_MASK, false);
  ------------------
  |  |  453|  12.1k|#define UPDATE_OPTS_MASK        ((UPDATE_OPT_LAST << 1) - 1)
  |  |  ------------------
  |  |  |  |  450|  12.1k|#define UPDATE_OPT_LAST         (UINT64_C(1) << 20)
  |  |  ------------------
  ------------------
  385|  12.1k|    handle_option_callbacks(mpctx);
  386|       |
  387|  12.1k|    if (handle_help_options(mpctx))
  ------------------
  |  Branch (387:9): [True: 19, False: 12.1k]
  ------------------
  388|     19|        return 1; // help
  389|       |
  390|  12.1k|    check_library_versions(mp_null_log, 0);
  391|       |
  392|  12.1k|    if (!mpctx->playlist->num_entries && !opts->player_idle_mode &&
  ------------------
  |  Branch (392:9): [True: 4.96k, False: 7.16k]
  |  Branch (392:42): [True: 4, False: 4.96k]
  ------------------
  393|  12.1k|        options)
  ------------------
  |  Branch (393:9): [True: 4, False: 0]
  ------------------
  394|      4|    {
  395|       |        // nothing to play
  396|      4|        mp_print_version(mpctx->log, true);
  397|      4|        MP_INFO(mpctx, "%s", mp_help_text);
  ------------------
  |  |   87|      4|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      4|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  398|      4|        return 1;
  399|      4|    }
  400|       |
  401|  12.1k|    MP_STATS(mpctx, "start init");
  ------------------
  |  |   95|  12.1k|#define MP_STATS(obj, ...)      MP_MSG(obj, MSGL_STATS, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  12.1k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  402|       |
  403|       |#if HAVE_COCOA
  404|       |    mpv_handle *ctx = mp_new_client(mpctx->clients, "mac");
  405|       |    cocoa_set_mpv_handle(ctx);
  406|       |#endif
  407|       |
  408|       |#if HAVE_WIN32_SMTC
  409|       |    if (opts->media_controls)
  410|       |        mp_smtc_init(mp_new_client(mpctx->clients, "SystemMediaTransportControls"));
  411|       |#endif
  412|       |
  413|  12.1k|    mpctx->ipc_ctx = mp_init_ipc(mpctx->clients, mpctx->global);
  414|       |
  415|  12.1k|    if (opts->encode_opts->file && opts->encode_opts->file[0]) {
  ------------------
  |  Branch (415:9): [True: 357, False: 11.7k]
  |  Branch (415:36): [True: 309, False: 48]
  ------------------
  416|    309|        mpctx->encode_lavc_ctx = encode_lavc_init(mpctx->global);
  417|    309|        if(!mpctx->encode_lavc_ctx) {
  ------------------
  |  Branch (417:12): [True: 288, False: 21]
  ------------------
  418|    288|            MP_INFO(mpctx, "Encoding initialization failed.\n");
  ------------------
  |  |   87|    288|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    288|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  419|    288|            return -1;
  420|    288|        }
  421|    309|    }
  422|       |
  423|  11.8k|    mp_load_scripts(mpctx);
  424|       |
  425|  11.8k|    if (opts->force_vo == 2 && handle_force_window(mpctx, false) < 0)
  ------------------
  |  Branch (425:9): [True: 0, False: 11.8k]
  |  Branch (425:32): [True: 0, False: 0]
  ------------------
  426|      0|        return -1;
  427|       |
  428|       |    // Needed to properly enter _initial_ idle mode if playlist empty.
  429|  11.8k|    if (mpctx->opts->player_idle_mode && !mpctx->playlist->num_entries)
  ------------------
  |  Branch (429:9): [True: 11.8k, False: 3]
  |  Branch (429:42): [True: 4.81k, False: 7.01k]
  ------------------
  430|  4.81k|        mpctx->stop_play = PT_STOP;
  431|       |
  432|  11.8k|    MP_STATS(mpctx, "end init");
  ------------------
  |  |   95|  11.8k|#define MP_STATS(obj, ...)      MP_MSG(obj, MSGL_STATS, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  11.8k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  433|       |
  434|  11.8k|    return 0;
  435|  11.8k|}
main.c:cas_terminal_owner:
  112|  52.5k|{
  113|  52.5k|    mp_mutex_lock(&terminal_owner_lock);
  ------------------
  |  |  131|  52.5k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  114|  52.5k|    bool r = terminal_owner == old;
  115|  52.5k|    if (r)
  ------------------
  |  Branch (115:9): [True: 12.2k, False: 40.2k]
  ------------------
  116|  12.2k|        terminal_owner = new;
  117|  52.5k|    mp_mutex_unlock(&terminal_owner_lock);
  ------------------
  |  |  133|  52.5k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  118|  52.5k|    return r;
  119|  52.5k|}
main.c:check_locale:
  247|  17.0k|{
  248|  17.0k|    char *name = setlocale(LC_NUMERIC, NULL);
  249|  17.0k|    return !name || strcmp(name, "C") == 0 || strcmp(name, "C.UTF-8") == 0;
  ------------------
  |  Branch (249:12): [True: 0, False: 17.0k]
  |  Branch (249:21): [True: 17.0k, False: 0]
  |  Branch (249:47): [True: 0, False: 0]
  ------------------
  250|  17.0k|}
main.c:handle_help_options:
  214|  12.1k|{
  215|  12.1k|    struct MPOpts *opts = mpctx->opts;
  216|  12.1k|    struct mp_log *log = mpctx->log;
  217|  12.1k|    if (opts->ao_opts->audio_device &&
  ------------------
  |  Branch (217:9): [True: 12.1k, False: 0]
  ------------------
  218|  12.1k|        strcmp(opts->ao_opts->audio_device, "help") == 0)
  ------------------
  |  Branch (218:9): [True: 0, False: 12.1k]
  ------------------
  219|      0|    {
  220|      0|        ao_print_devices(mpctx->global, log, mpctx->ao);
  221|      0|        return true;
  222|      0|    }
  223|  12.1k|    if (opts->property_print_help) {
  ------------------
  |  Branch (223:9): [True: 0, False: 12.1k]
  ------------------
  224|      0|        property_print_help(mpctx);
  225|      0|        return true;
  226|      0|    }
  227|  12.1k|    if (encode_lavc_showhelp(log, opts->encode_opts))
  ------------------
  |  Branch (227:9): [True: 19, False: 12.1k]
  ------------------
  228|     19|        return true;
  229|  12.1k|    return false;
  230|  12.1k|}

update_content_type:
  178|     39|{
  179|     39|    enum mp_content_type content_type;
  180|     39|    if (!track || !track->vo_c) {
  ------------------
  |  Branch (180:9): [True: 39, False: 0]
  |  Branch (180:19): [True: 0, False: 0]
  ------------------
  181|     39|        content_type = MP_CONTENT_NONE;
  182|     39|    } else if (track->image) {
  ------------------
  |  Branch (182:16): [True: 0, False: 0]
  ------------------
  183|      0|        content_type = MP_CONTENT_IMAGE;
  184|      0|    } else {
  185|      0|        content_type = MP_CONTENT_VIDEO;
  186|      0|    }
  187|     39|    if (mpctx->video_out)
  ------------------
  |  Branch (187:9): [True: 39, False: 0]
  ------------------
  188|     39|        vo_control(mpctx->video_out, VOCTRL_CONTENT_TYPE, &content_type);
  189|     39|}
update_vo_playback_state:
  192|  17.4k|{
  193|  17.4k|    if (mpctx->video_out && mpctx->video_out->config_ok) {
  ------------------
  |  Branch (193:9): [True: 11, False: 17.4k]
  |  Branch (193:29): [True: 11, False: 0]
  ------------------
  194|     11|        struct voctrl_playback_state oldstate = mpctx->vo_playback_state;
  195|     11|        double pos = get_current_pos_ratio(mpctx, false);
  196|     11|        struct voctrl_playback_state newstate = {
  197|     11|            .taskbar_progress = mpctx->opts->vo->taskbar_progress && pos >= 0,
  ------------------
  |  Branch (197:33): [True: 11, False: 0]
  |  Branch (197:70): [True: 0, False: 11]
  ------------------
  198|     11|            .playing = mpctx->playing,
  199|     11|            .paused = mpctx->paused,
  200|     11|            .position = pos > 0 ? lrint(pos * UINT8_MAX) : 0,
  ------------------
  |  Branch (200:25): [True: 0, False: 11]
  ------------------
  201|     11|        };
  202|       |
  203|     11|        if (oldstate.taskbar_progress != newstate.taskbar_progress ||
  ------------------
  |  Branch (203:13): [True: 0, False: 11]
  ------------------
  204|     11|            oldstate.playing != newstate.playing ||
  ------------------
  |  Branch (204:13): [True: 0, False: 11]
  ------------------
  205|     11|            oldstate.paused != newstate.paused ||
  ------------------
  |  Branch (205:13): [True: 11, False: 0]
  ------------------
  206|     11|            oldstate.position != newstate.position)
  ------------------
  |  Branch (206:13): [True: 0, False: 0]
  ------------------
  207|     11|        {
  208|       |            // Don't update progress bar if it was and still is hidden
  209|     11|            if ((oldstate.playing && oldstate.taskbar_progress) ||
  ------------------
  |  Branch (209:18): [True: 0, False: 11]
  |  Branch (209:38): [True: 0, False: 0]
  ------------------
  210|     11|                (newstate.playing && newstate.taskbar_progress))
  ------------------
  |  Branch (210:18): [True: 0, False: 11]
  |  Branch (210:38): [True: 0, False: 0]
  ------------------
  211|      0|            {
  212|      0|                vo_control_async(mpctx->video_out,
  213|      0|                                 VOCTRL_UPDATE_PLAYBACK_STATE, &newstate);
  214|      0|            }
  215|     11|            mpctx->vo_playback_state = newstate;
  216|     11|        }
  217|  17.4k|    } else {
  218|  17.4k|        mpctx->vo_playback_state = (struct voctrl_playback_state){ 0 };
  219|  17.4k|    }
  220|  17.4k|}
update_window_title:
  223|  17.4k|{
  224|  17.4k|    if (!mpctx->video_out && !mpctx->ao) {
  ------------------
  |  Branch (224:9): [True: 17.4k, False: 11]
  |  Branch (224:30): [True: 17.4k, False: 0]
  ------------------
  225|  17.4k|        talloc_free(mpctx->last_window_title);
  ------------------
  |  |   47|  17.4k|#define talloc_free                     ta_free
  ------------------
  226|  17.4k|        mpctx->last_window_title = NULL;
  227|  17.4k|        return;
  228|  17.4k|    }
  229|     11|    char *title = mp_property_expand_string(mpctx, mpctx->opts->wintitle);
  230|     11|    if (!mpctx->last_window_title || force ||
  ------------------
  |  Branch (230:9): [True: 11, False: 0]
  |  Branch (230:38): [True: 0, False: 0]
  ------------------
  231|     11|        strcmp(title, mpctx->last_window_title) != 0)
  ------------------
  |  Branch (231:9): [True: 0, False: 0]
  ------------------
  232|     11|    {
  233|     11|        talloc_free(mpctx->last_window_title);
  ------------------
  |  |   47|     11|#define talloc_free                     ta_free
  ------------------
  234|     11|        mpctx->last_window_title = talloc_steal(mpctx, title);
  ------------------
  |  |   38|     11|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     11|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  235|       |
  236|     11|        if (mpctx->video_out)
  ------------------
  |  Branch (236:13): [True: 11, False: 0]
  ------------------
  237|     11|            vo_control(mpctx->video_out, VOCTRL_UPDATE_WINDOW_TITLE, title);
  238|       |
  239|     11|        if (mpctx->ao) {
  ------------------
  |  Branch (239:13): [True: 0, False: 11]
  ------------------
  240|      0|            ao_control(mpctx->ao, AOCONTROL_UPDATE_STREAM_TITLE, title);
  241|      0|        }
  242|     11|    } else {
  243|      0|        talloc_free(title);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  244|      0|    }
  245|     11|}
merge_playlist_files:
  315|    791|{
  316|    791|    if (!pl->num_entries)
  ------------------
  |  Branch (316:9): [True: 1, False: 790]
  ------------------
  317|      1|        return;
  318|    790|    char *edl = talloc_strdup(NULL, "edl://");
  ------------------
  |  |   50|    790|#define talloc_strdup                   ta_xstrdup
  ------------------
  319|  17.4k|    for (int n = 0; n < pl->num_entries; n++) {
  ------------------
  |  Branch (319:21): [True: 16.6k, False: 790]
  ------------------
  320|  16.6k|        struct playlist_entry *e = pl->entries[n];
  321|  16.6k|        if (n)
  ------------------
  |  Branch (321:13): [True: 15.8k, False: 790]
  ------------------
  322|  15.8k|            edl = talloc_strdup_append_buffer(edl, ";");
  ------------------
  |  |   58|  15.8k|#define talloc_strdup_append_buffer     ta_talloc_strdup_append_buffer
  ------------------
  323|       |        // Escape if needed
  324|  16.6k|        if (e->filename[strcspn(e->filename, "=%,;\n")] ||
  ------------------
  |  Branch (324:13): [True: 6.67k, False: 9.95k]
  ------------------
  325|  16.6k|            bstr_strip(bstr0(e->filename)).len != strlen(e->filename))
  ------------------
  |  Branch (325:13): [True: 76, False: 9.88k]
  ------------------
  326|  6.74k|        {
  327|       |            // %length%
  328|  6.74k|            edl = talloc_asprintf_append_buffer(edl, "%%%zd%%", strlen(e->filename));
  ------------------
  |  |   64|  6.74k|#define talloc_asprintf_append_buffer   ta_talloc_asprintf_append_buffer
  ------------------
  329|  6.74k|        }
  330|  16.6k|        edl = talloc_strdup_append_buffer(edl, e->filename);
  ------------------
  |  |   58|  16.6k|#define talloc_strdup_append_buffer     ta_talloc_strdup_append_buffer
  ------------------
  331|  16.6k|    }
  332|    790|    playlist_clear(pl);
  333|    790|    playlist_append_file(pl, edl);
  334|    790|    talloc_free(edl);
  ------------------
  |  |   47|    790|#define talloc_free                     ta_free
  ------------------
  335|    790|}
str_in_list:
  350|  1.94k|{
  351|  1.94k|    if (!list)
  ------------------
  |  Branch (351:9): [True: 0, False: 1.94k]
  ------------------
  352|      0|        return false;
  353|  5.82k|    while (*list) {
  ------------------
  |  Branch (353:12): [True: 5.82k, False: 0]
  ------------------
  354|  5.82k|        if (!bstrcasecmp0(str, *list++))
  ------------------
  |  Branch (354:13): [True: 1.94k, False: 3.88k]
  ------------------
  355|  1.94k|            return true;
  356|  5.82k|    }
  357|      0|    return false;
  358|  1.94k|}
mp_find_non_filename_media_title:
  421|     48|{
  422|     48|    const char *name = mpctx->opts->media_title;
  423|     48|    if (name && name[0])
  ------------------
  |  Branch (423:9): [True: 0, False: 48]
  |  Branch (423:17): [True: 0, False: 0]
  ------------------
  424|      0|        return name;
  425|     48|    if (mpctx->demuxer) {
  ------------------
  |  Branch (425:9): [True: 0, False: 48]
  ------------------
  426|      0|        name = mp_tags_get_str(mpctx->demuxer->metadata, "service_name");
  427|      0|        if (name && name[0])
  ------------------
  |  Branch (427:13): [True: 0, False: 0]
  |  Branch (427:21): [True: 0, False: 0]
  ------------------
  428|      0|            return name;
  429|      0|        name = mp_tags_get_str(mpctx->demuxer->metadata, "title");
  430|      0|        if (name && name[0])
  ------------------
  |  Branch (430:13): [True: 0, False: 0]
  |  Branch (430:21): [True: 0, False: 0]
  ------------------
  431|      0|            return name;
  432|      0|        name = mp_tags_get_str(mpctx->demuxer->metadata, "icy-title");
  433|      0|        if (name && name[0])
  ------------------
  |  Branch (433:13): [True: 0, False: 0]
  |  Branch (433:21): [True: 0, False: 0]
  ------------------
  434|      0|            return name;
  435|      0|    }
  436|     48|    if (mpctx->playing && mpctx->playing->title)
  ------------------
  |  Branch (436:9): [True: 0, False: 48]
  |  Branch (436:27): [True: 0, False: 0]
  ------------------
  437|      0|        return mpctx->playing->title;
  438|     48|    return NULL;
  439|     48|}

term_osd_clear_subs:
  121|  3.93k|{
  122|  3.93k|    term_osd_set_subs(mpctx, NULL, 0);
  123|  3.93k|    term_osd_set_subs(mpctx, NULL, 1);
  124|  3.93k|}
term_osd_set_subs:
  127|  7.86k|{
  128|  7.86k|    if (mpctx->video_out || !text || !mpctx->opts->subs_shared->sub_visibility[order])
  ------------------
  |  Branch (128:9): [True: 0, False: 7.86k]
  |  Branch (128:29): [True: 7.86k, False: 0]
  |  Branch (128:38): [True: 0, False: 0]
  ------------------
  129|  7.86k|        text = ""; // disable
  130|  7.86k|    if (strcmp(mpctx->term_osd_subs[order] ? mpctx->term_osd_subs[order] : "", text) == 0)
  ------------------
  |  Branch (130:9): [True: 7.86k, False: 0]
  |  Branch (130:16): [True: 0, False: 7.86k]
  ------------------
  131|  7.86k|        return;
  132|      0|    talloc_replace(mpctx, mpctx->term_osd_subs[order], text);
  ------------------
  |  |   54|      0|#define talloc_replace                  ta_replace
  |  |  ------------------
  |  |  |  |  106|      0|    do {                                                \
  |  |  |  |  107|      0|        if (!(str)) {                                   \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (107:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |  108|      0|            (str) = ta_xstrdup((ta_parent), (replace)); \
  |  |  |  |  109|      0|        } else {                                        \
  |  |  |  |  110|      0|            *(str) = '\0';                              \
  |  |  |  |  111|      0|            ta_xstrdup_append(&(str), (replace));       \
  |  |  |  |  ------------------
  |  |  |  |  |  |  123|      0|#define ta_xstrdup_append(...)          ta_oom_b(ta_strdup_append(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  112|      0|        }                                               \
  |  |  |  |  113|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (113:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  133|      0|    term_osd_update(mpctx);
  134|      0|}
set_osd_bar_chapters:
  375|  3.93k|{
  376|  3.93k|    if (mpctx->osd_progbar.type != type)
  ------------------
  |  Branch (376:9): [True: 3.93k, False: 0]
  ------------------
  377|  3.93k|        return;
  378|       |
  379|      0|    mpctx->osd_progbar.num_stops = 0;
  380|      0|    double len = get_time_length(mpctx);
  381|      0|    if (len > 0) {
  ------------------
  |  Branch (381:9): [True: 0, False: 0]
  ------------------
  382|       |        // Always render the loop points, even if they're incomplete.
  383|      0|        double ab[2];
  384|      0|        bool valid = get_ab_loop_times(mpctx, ab);
  385|      0|        for (int n = 0; n < 2; n++) {
  ------------------
  |  Branch (385:25): [True: 0, False: 0]
  ------------------
  386|      0|            if (ab[n] != MP_NOPTS_VALUE) {
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (386:17): [True: 0, False: 0]
  ------------------
  387|      0|                MP_TARRAY_APPEND(mpctx, mpctx->osd_progbar.stops,
  ------------------
  |  |  105|      0|    do {                                            \
  |  |  106|      0|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      0|    do {                                            \
  |  |  |  |   97|      0|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      0|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      0|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      0|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      0|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      0|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      0|        (idxvar)++;                                 \
  |  |  109|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  388|      0|                                 mpctx->osd_progbar.num_stops, ab[n] / len);
  389|      0|            }
  390|      0|        }
  391|      0|        if (!valid) {
  ------------------
  |  Branch (391:13): [True: 0, False: 0]
  ------------------
  392|      0|            int num = get_chapter_count(mpctx);
  393|      0|            for (int n = 0; n < num; n++) {
  ------------------
  |  Branch (393:29): [True: 0, False: 0]
  ------------------
  394|      0|                double time = chapter_start_time(mpctx, n);
  395|      0|                if (time >= 0) {
  ------------------
  |  Branch (395:21): [True: 0, False: 0]
  ------------------
  396|      0|                    float pos = time / len;
  397|      0|                    MP_TARRAY_APPEND(mpctx, mpctx->osd_progbar.stops,
  ------------------
  |  |  105|      0|    do {                                            \
  |  |  106|      0|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      0|    do {                                            \
  |  |  |  |   97|      0|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      0|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      0|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      0|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      0|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      0|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      0|        (idxvar)++;                                 \
  |  |  109|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  398|      0|                                     mpctx->osd_progbar.num_stops, pos);
  399|      0|                }
  400|      0|            }
  401|      0|        }
  402|      0|    }
  403|      0|    osd_set_progbar(mpctx->osd, &mpctx->osd_progbar);
  404|      0|    mp_wakeup_core(mpctx);
  405|      0|}
get_current_osd_sym:
  419|     37|{
  420|     37|    int sym = mpctx->osd_function;
  421|     37|    if (!sym) {
  ------------------
  |  Branch (421:9): [True: 37, False: 0]
  ------------------
  422|     37|        if (is_busy(mpctx) || (mpctx->paused_for_cache && !mpctx->opts->pause)) {
  ------------------
  |  Branch (422:13): [True: 37, False: 0]
  |  Branch (422:32): [True: 0, False: 0]
  |  Branch (422:59): [True: 0, False: 0]
  ------------------
  423|     37|            sym = OSD_CLOCK;
  424|     37|        } else if (mpctx->paused || mpctx->step_frames) {
  ------------------
  |  Branch (424:20): [True: 0, False: 0]
  |  Branch (424:37): [True: 0, False: 0]
  ------------------
  425|      0|            sym = OSD_PAUSE;
  426|      0|        } else if (mpctx->play_dir < 0 ) {
  ------------------
  |  Branch (426:20): [True: 0, False: 0]
  ------------------
  427|      0|            sym = OSD_REV;
  428|      0|        } else {
  429|      0|            sym = OSD_PLAY;
  430|      0|        }
  431|     37|    }
  432|     37|    osd_get_function_sym(buf, buf_size, sym);
  433|     37|}
update_osd_msg:
  501|  18.4k|{
  502|  18.4k|    struct MPOpts *opts = mpctx->opts;
  503|  18.4k|    struct osd_state *osd = mpctx->osd;
  504|       |
  505|  18.4k|    double now = mp_time_sec();
  506|       |
  507|  18.4k|    if (!mpctx->osd_force_update) {
  ------------------
  |  Branch (507:9): [True: 18.0k, False: 383]
  ------------------
  508|       |        // Assume nothing is going on at all.
  509|  18.0k|        if (!mpctx->osd_idle_update)
  ------------------
  |  Branch (509:13): [True: 873, False: 17.1k]
  ------------------
  510|    873|            return;
  511|       |
  512|  17.1k|        double delay = 0.050; // update the OSD at most this often
  513|  17.1k|        double diff = now - mpctx->osd_last_update;
  514|  17.1k|        if (diff < delay) {
  ------------------
  |  Branch (514:13): [True: 131, False: 17.0k]
  ------------------
  515|    131|            mp_set_timeout(mpctx, delay - diff);
  516|    131|            return;
  517|    131|        }
  518|  17.1k|    }
  519|  17.4k|    mpctx->osd_force_update = false;
  520|  17.4k|    mpctx->osd_idle_update = false;
  521|  17.4k|    mpctx->osd_last_update = now;
  522|       |
  523|  17.4k|    if (mpctx->osd_visible) {
  ------------------
  |  Branch (523:9): [True: 0, False: 17.4k]
  ------------------
  524|      0|        double sleep = mpctx->osd_visible - now;
  525|      0|        if (sleep > 0) {
  ------------------
  |  Branch (525:13): [True: 0, False: 0]
  ------------------
  526|      0|            mp_set_timeout(mpctx, sleep);
  527|      0|            mpctx->osd_idle_update = true;
  528|      0|        } else {
  529|      0|            mpctx->osd_visible = 0;
  530|      0|            mpctx->osd_progbar.type = -1; // disable
  531|      0|            osd_set_progbar(mpctx->osd, &mpctx->osd_progbar);
  532|      0|        }
  533|      0|    }
  534|       |
  535|  17.4k|    if (mpctx->osd_function_visible) {
  ------------------
  |  Branch (535:9): [True: 0, False: 17.4k]
  ------------------
  536|      0|        double sleep = mpctx->osd_function_visible - now;
  537|      0|        if (sleep > 0) {
  ------------------
  |  Branch (537:13): [True: 0, False: 0]
  ------------------
  538|      0|            mp_set_timeout(mpctx, sleep);
  539|      0|            mpctx->osd_idle_update = true;
  540|      0|        } else {
  541|      0|            mpctx->osd_function_visible = 0;
  542|      0|            mpctx->osd_function = 0;
  543|      0|        }
  544|      0|    }
  545|       |
  546|  17.4k|    if (mpctx->osd_msg_next_duration > 0) {
  ------------------
  |  Branch (546:9): [True: 0, False: 17.4k]
  ------------------
  547|       |        // This is done to avoid cutting the OSD message short if slow commands
  548|       |        // are executed between setting the OSD message and showing it.
  549|      0|        mpctx->osd_msg_visible = now + mpctx->osd_msg_next_duration;
  550|      0|        mpctx->osd_msg_next_duration = 0;
  551|      0|    }
  552|       |
  553|  17.4k|    if (mpctx->osd_msg_visible) {
  ------------------
  |  Branch (553:9): [True: 0, False: 17.4k]
  ------------------
  554|      0|        double sleep = mpctx->osd_msg_visible - now;
  555|      0|        if (sleep > 0) {
  ------------------
  |  Branch (555:13): [True: 0, False: 0]
  ------------------
  556|      0|            mp_set_timeout(mpctx, sleep);
  557|      0|            mpctx->osd_idle_update = true;
  558|      0|        } else {
  559|      0|            talloc_free(mpctx->osd_msg_text);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  560|      0|            mpctx->osd_msg_text = NULL;
  561|      0|            mpctx->osd_msg_visible = 0;
  562|      0|            mpctx->osd_show_pos = false;
  563|      0|        }
  564|      0|    }
  565|       |
  566|  17.4k|    add_seek_osd_messages(mpctx);
  567|       |
  568|  17.4k|    if (mpctx->osd_progbar.type == OSD_BAR_SEEK) {
  ------------------
  |  Branch (568:9): [True: 0, False: 17.4k]
  ------------------
  569|      0|        double pos = get_current_pos_ratio(mpctx, false);
  570|      0|        update_osd_bar(mpctx, OSD_BAR_SEEK, 0, 1, MPCLAMP(pos, 0, 1));
  ------------------
  |  |   45|      0|#define MPCLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
  |  |  ------------------
  |  |  |  Branch (45:31): [True: 0, False: 0]
  |  |  |  Branch (45:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  571|      0|    }
  572|       |
  573|  17.4k|    term_osd_set_text_lazy(mpctx, mpctx->osd_msg_text);
  574|  17.4k|    term_osd_print_status_lazy(mpctx);
  575|  17.4k|    term_osd_update(mpctx);
  576|       |
  577|  17.4k|    if (!opts->video_osd)
  ------------------
  |  Branch (577:9): [True: 0, False: 17.4k]
  ------------------
  578|      0|        return;
  579|       |
  580|  17.4k|    int osd_level = opts->osd_level;
  581|  17.4k|    if (mpctx->osd_show_pos)
  ------------------
  |  Branch (581:9): [True: 0, False: 17.4k]
  ------------------
  582|      0|        osd_level = 3;
  583|       |
  584|  17.4k|    char *text = NULL;
  585|  17.4k|    sadd_osd_status(&text, mpctx, osd_level);
  586|  17.4k|    if (mpctx->osd_msg_text && mpctx->osd_msg_text[0]) {
  ------------------
  |  Branch (586:9): [True: 0, False: 17.4k]
  |  Branch (586:32): [True: 0, False: 0]
  ------------------
  587|      0|        text = talloc_asprintf_append(text, "%s%s", text ? "\n" : "",
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
  |  Branch (587:53): [True: 0, False: 0]
  ------------------
  588|      0|                                      mpctx->osd_msg_text);
  589|      0|    }
  590|  17.4k|    osd_set_text(osd, text);
  591|  17.4k|    talloc_free(text);
  ------------------
  |  |   47|  17.4k|#define talloc_free                     ta_free
  ------------------
  592|  17.4k|}
osd.c:term_osd_update:
   76|  17.4k|{
   77|  17.4k|    int num_parts = 0;
   78|  17.4k|    char *parts[4] = {0};
   79|       |
   80|  17.4k|    if (!mpctx->opts->use_terminal)
  ------------------
  |  Branch (80:9): [True: 13.9k, False: 3.49k]
  ------------------
   81|  13.9k|        return;
   82|       |
   83|  3.49k|    if (!term_osd_empty(mpctx->term_osd_subs[0]))
  ------------------
  |  Branch (83:9): [True: 0, False: 3.49k]
  ------------------
   84|      0|        parts[num_parts++] = mpctx->term_osd_subs[0];
   85|  3.49k|    if (!term_osd_empty(mpctx->term_osd_subs[1]))
  ------------------
  |  Branch (85:9): [True: 0, False: 3.49k]
  ------------------
   86|      0|        parts[num_parts++] = mpctx->term_osd_subs[1];
   87|  3.49k|    if (!term_osd_empty(mpctx->term_osd_text))
  ------------------
  |  Branch (87:9): [True: 0, False: 3.49k]
  ------------------
   88|      0|        parts[num_parts++] = mpctx->term_osd_text;
   89|  3.49k|    if (!term_osd_empty(mpctx->term_osd_status))
  ------------------
  |  Branch (89:9): [True: 0, False: 3.49k]
  ------------------
   90|      0|        parts[num_parts++] = mpctx->term_osd_status;
   91|       |
   92|  3.49k|    char *s = join_lines(mpctx, parts, num_parts);
   93|       |
   94|  3.49k|    if (strcmp(mpctx->term_osd_contents, s) == 0 &&
  ------------------
  |  Branch (94:9): [True: 3.49k, False: 0]
  ------------------
   95|  3.49k|        mp_msg_has_status_line(mpctx->global))
  ------------------
  |  Branch (95:9): [True: 0, False: 3.49k]
  ------------------
   96|      0|    {
   97|      0|        talloc_free(s);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
   98|  3.49k|    } else {
   99|  3.49k|        talloc_free(mpctx->term_osd_contents);
  ------------------
  |  |   47|  3.49k|#define talloc_free                     ta_free
  ------------------
  100|  3.49k|        mpctx->term_osd_contents = s;
  101|  3.49k|        mp_msg(mpctx->statusline, MSGL_STATUS, "%s", s);
  102|  3.49k|    }
  103|  3.49k|}
osd.c:term_osd_empty:
   71|  13.9k|{
   72|  13.9k|    return !text || !text[0] || !strcmp(text, TERM_MSG_0);
  ------------------
  |  |   30|      0|#define TERM_MSG_0 TERM_MSG_ESCAPE "0"
  |  |  ------------------
  |  |  |  |   29|      0|#define TERM_MSG_ESCAPE "\xC2\x92" "t"
  |  |  ------------------
  ------------------
  |  Branch (72:12): [True: 6.98k, False: 6.98k]
  |  Branch (72:21): [True: 6.98k, False: 0]
  |  Branch (72:33): [True: 0, False: 0]
  ------------------
   73|  13.9k|}
osd.c:join_lines:
   63|  3.49k|{
   64|  3.49k|    char *res = talloc_strdup(ta_ctx, "");
  ------------------
  |  |   50|  3.49k|#define talloc_strdup                   ta_xstrdup
  ------------------
   65|  3.49k|    for (int n = 0; n < num_parts; n++)
  ------------------
  |  Branch (65:21): [True: 0, False: 3.49k]
  ------------------
   66|      0|        res = talloc_asprintf_append(res, "%s%s", n ? "\n" : "", parts[n]);
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
  |  Branch (66:51): [True: 0, False: 0]
  ------------------
   67|  3.49k|    return res;
   68|  3.49k|}
osd.c:is_busy:
  174|     37|{
  175|     37|    return !mpctx->restart_complete && mp_time_sec() - mpctx->start_timestamp > 0.3;
  ------------------
  |  Branch (175:12): [True: 37, False: 0]
  |  Branch (175:40): [True: 37, False: 0]
  ------------------
  176|     37|}
osd.c:add_seek_osd_messages:
  470|  17.4k|{
  471|  17.4k|    if (mpctx->add_osd_seek_info & OSD_SEEK_INFO_BAR) {
  ------------------
  |  Branch (471:9): [True: 0, False: 17.4k]
  ------------------
  472|      0|        double pos = get_current_pos_ratio(mpctx, false);
  473|      0|        set_osd_bar(mpctx, OSD_BAR_SEEK, 0, 1, 0, MPCLAMP(pos, 0, 1));
  ------------------
  |  |   45|      0|#define MPCLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
  |  |  ------------------
  |  |  |  Branch (45:31): [True: 0, False: 0]
  |  |  |  Branch (45:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  474|      0|        set_osd_bar_chapters(mpctx, OSD_BAR_SEEK);
  475|      0|    }
  476|  17.4k|    if (mpctx->add_osd_seek_info & OSD_SEEK_INFO_TEXT) {
  ------------------
  |  Branch (476:9): [True: 0, False: 17.4k]
  ------------------
  477|       |        // Never in term-osd mode
  478|      0|        bool video_osd = mpctx->video_out && mpctx->opts->video_osd;
  ------------------
  |  Branch (478:26): [True: 0, False: 0]
  |  Branch (478:46): [True: 0, False: 0]
  ------------------
  479|      0|        if (video_osd && mpctx->opts->term_osd != 1) {
  ------------------
  |  Branch (479:13): [True: 0, False: 0]
  |  Branch (479:26): [True: 0, False: 0]
  ------------------
  480|      0|            if (set_osd_msg(mpctx, 1, mpctx->opts->osd_duration, ""))
  ------------------
  |  Branch (480:17): [True: 0, False: 0]
  ------------------
  481|      0|                mpctx->osd_show_pos = true;
  482|      0|        }
  483|      0|    }
  484|  17.4k|    if (mpctx->add_osd_seek_info & OSD_SEEK_INFO_CHAPTER_TEXT) {
  ------------------
  |  Branch (484:9): [True: 0, False: 17.4k]
  ------------------
  485|      0|        char *chapter = chapter_display_name(mpctx, get_current_chapter(mpctx));
  486|      0|        set_osd_msg(mpctx, 1, mpctx->opts->osd_duration,
  487|      0|                     "Chapter: %s", chapter);
  488|      0|        talloc_free(chapter);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  489|      0|    }
  490|  17.4k|    if (mpctx->add_osd_seek_info & OSD_SEEK_INFO_CURRENT_FILE) {
  ------------------
  |  Branch (490:9): [True: 0, False: 17.4k]
  ------------------
  491|      0|        if (mpctx->filename) {
  ------------------
  |  Branch (491:13): [True: 0, False: 0]
  ------------------
  492|      0|            set_osd_msg(mpctx, 1, mpctx->opts->osd_duration, "%s",
  493|      0|                        mpctx->filename);
  494|      0|        }
  495|      0|    }
  496|  17.4k|    mpctx->add_osd_seek_info = 0;
  497|  17.4k|}
osd.c:term_osd_set_text_lazy:
  137|  17.4k|{
  138|  17.4k|    bool video_osd = mpctx->video_out && mpctx->opts->video_osd;
  ------------------
  |  Branch (138:22): [True: 11, False: 17.4k]
  |  Branch (138:42): [True: 11, False: 0]
  ------------------
  139|  17.4k|    if ((video_osd && mpctx->opts->term_osd != 1) || !text)
  ------------------
  |  Branch (139:10): [True: 11, False: 17.4k]
  |  Branch (139:23): [True: 11, False: 0]
  |  Branch (139:54): [True: 17.4k, False: 0]
  ------------------
  140|  17.4k|        text = ""; // disable
  141|  17.4k|    talloc_replace(mpctx, mpctx->term_osd_text, text);
  ------------------
  |  |   54|  17.4k|#define talloc_replace                  ta_replace
  |  |  ------------------
  |  |  |  |  106|  17.4k|    do {                                                \
  |  |  |  |  107|  17.4k|        if (!(str)) {                                   \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (107:13): [True: 17.0k, False: 383]
  |  |  |  |  ------------------
  |  |  |  |  108|  17.0k|            (str) = ta_xstrdup((ta_parent), (replace)); \
  |  |  |  |  109|  17.0k|        } else {                                        \
  |  |  |  |  110|    383|            *(str) = '\0';                              \
  |  |  |  |  111|    383|            ta_xstrdup_append(&(str), (replace));       \
  |  |  |  |  ------------------
  |  |  |  |  |  |  123|    383|#define ta_xstrdup_append(...)          ta_oom_b(ta_strdup_append(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  112|    383|        }                                               \
  |  |  |  |  113|  17.4k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (113:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  142|  17.4k|}
osd.c:term_osd_print_status_lazy:
  279|  17.4k|{
  280|  17.4k|    struct MPOpts *opts = mpctx->opts;
  281|       |
  282|  17.4k|    term_osd_update_title(mpctx);
  283|  17.4k|    update_window_title(mpctx, false);
  284|  17.4k|    update_vo_playback_state(mpctx);
  285|       |
  286|  17.4k|    if (!opts->use_terminal)
  ------------------
  |  Branch (286:9): [True: 13.9k, False: 3.49k]
  ------------------
  287|  13.9k|        return;
  288|       |
  289|  3.49k|    if (opts->quiet || !mpctx->playback_initialized || !mpctx->playing_msg_shown)
  ------------------
  |  Branch (289:9): [True: 1, False: 3.49k]
  |  Branch (289:24): [True: 3.49k, False: 0]
  |  Branch (289:56): [True: 0, False: 0]
  ------------------
  290|  3.49k|    {
  291|  3.49k|        if (!mpctx->playing)
  ------------------
  |  Branch (291:13): [True: 3.12k, False: 369]
  ------------------
  292|  3.12k|            term_osd_set_status_lazy(mpctx, "");
  293|  3.49k|        return;
  294|  3.49k|    }
  295|       |
  296|      0|    char *line = get_term_status_msg(mpctx);
  297|       |
  298|      0|    if (opts->term_osd_bar) {
  ------------------
  |  Branch (298:9): [True: 0, False: 0]
  ------------------
  299|      0|        saddf(&line, "\n");
  ------------------
  |  |   47|      0|#define saddf(var, ...) (*(var) = talloc_asprintf_append((*var), __VA_ARGS__))
  |  |  ------------------
  |  |  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  |  |  ------------------
  ------------------
  300|      0|        int w = 80, h = 24;
  301|      0|        terminal_get_size(&w, &h);
  302|      0|        add_term_osd_bar(mpctx, &line, w);
  303|      0|    }
  304|       |
  305|      0|    term_osd_set_status_lazy(mpctx, line);
  306|      0|    talloc_free(line);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  307|      0|}
osd.c:term_osd_update_title:
  106|  17.4k|{
  107|  17.4k|    if (!mpctx->opts->use_terminal)
  ------------------
  |  Branch (107:9): [True: 13.9k, False: 3.49k]
  ------------------
  108|  13.9k|        return;
  109|       |
  110|  3.49k|    char *s = mp_property_expand_escaped_string(mpctx, mpctx->opts->term_title);
  111|  3.49k|    if (bstr_equals(bstr0(s), bstr0(mpctx->term_osd_title))) {
  ------------------
  |  Branch (111:9): [True: 3.47k, False: 15]
  ------------------
  112|  3.47k|        talloc_free(s);
  ------------------
  |  |   47|  3.47k|#define talloc_free                     ta_free
  ------------------
  113|  3.47k|        return;
  114|  3.47k|    }
  115|       |
  116|     15|    mp_msg_set_term_title(mpctx->statusline, s);
  117|     15|    mpctx->term_osd_title = talloc_steal(mpctx, s);
  ------------------
  |  |   38|     15|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     15|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  118|     15|}
osd.c:term_osd_set_status_lazy:
  145|  3.12k|{
  146|  3.12k|    talloc_replace(mpctx, mpctx->term_osd_status, text);
  ------------------
  |  |   54|  3.12k|#define talloc_replace                  ta_replace
  |  |  ------------------
  |  |  |  |  106|  3.12k|    do {                                                \
  |  |  |  |  107|  3.12k|        if (!(str)) {                                   \
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (107:13): [True: 3.11k, False: 14]
  |  |  |  |  ------------------
  |  |  |  |  108|  3.11k|            (str) = ta_xstrdup((ta_parent), (replace)); \
  |  |  |  |  109|  3.11k|        } else {                                        \
  |  |  |  |  110|     14|            *(str) = '\0';                              \
  |  |  |  |  111|     14|            ta_xstrdup_append(&(str), (replace));       \
  |  |  |  |  ------------------
  |  |  |  |  |  |  123|     14|#define ta_xstrdup_append(...)          ta_oom_b(ta_strdup_append(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  112|     14|        }                                               \
  |  |  |  |  113|  3.12k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (113:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  147|  3.12k|}
osd.c:sadd_hhmmssff:
   51|      3|{
   52|      3|    char *s = mp_format_time(time, fractions);
   53|      3|    *buf = talloc_strdup_append(*buf, s);
  ------------------
  |  |   57|      3|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
   54|      3|    talloc_free(s);
  ------------------
  |  |   47|      3|#define talloc_free                     ta_free
  ------------------
   55|      3|}
osd.c:sadd_percentage:
   57|      1|static void sadd_percentage(char **buf, double ratio) {
   58|      1|    if (ratio >= 0)
  ------------------
  |  Branch (58:9): [True: 0, False: 1]
  ------------------
   59|      0|        *buf = talloc_asprintf_append(*buf, " (%.f%%)", ratio * 100);
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
   60|      1|}
osd.c:sadd_osd_status:
  436|  17.4k|{
  437|  17.4k|    mp_assert(level >= 0 && level <= 3);
  ------------------
  |  |   41|  17.4k|#define mp_assert assert
  ------------------
  438|  17.4k|    if (level == 0)
  ------------------
  |  Branch (438:9): [True: 1, False: 17.4k]
  ------------------
  439|      1|        return;
  440|  17.4k|    char *msg = mpctx->opts->osd_msg[level - 1];
  441|       |
  442|  17.4k|    if (msg && msg[0]) {
  ------------------
  |  Branch (442:9): [True: 4.88k, False: 12.5k]
  |  Branch (442:16): [True: 4.88k, False: 3]
  ------------------
  443|  4.88k|        char *text = mp_property_expand_escaped_string(mpctx, msg);
  444|  4.88k|        *buffer = talloc_strdup_append(*buffer, text);
  ------------------
  |  |   57|  4.88k|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
  445|  4.88k|        talloc_free(text);
  ------------------
  |  |   47|  4.88k|#define talloc_free                     ta_free
  ------------------
  446|  12.5k|    } else if (level >= 2) {
  ------------------
  |  Branch (446:16): [True: 2, False: 12.5k]
  ------------------
  447|      2|        bool fractions = mpctx->opts->osd_fractions;
  448|      2|        char sym[10];
  449|      2|        get_current_osd_sym(mpctx, sym, sizeof(sym));
  450|      2|        saddf(buffer, "%s ", sym);
  ------------------
  |  |   47|      2|#define saddf(var, ...) (*(var) = talloc_asprintf_append((*var), __VA_ARGS__))
  |  |  ------------------
  |  |  |  |   63|      2|#define talloc_asprintf_append          ta_talloc_asprintf_append
  |  |  ------------------
  ------------------
  451|      2|        char *custom_msg = mpctx->opts->osd_status_msg;
  452|      2|        if (custom_msg && level == 3) {
  ------------------
  |  Branch (452:13): [True: 0, False: 2]
  |  Branch (452:27): [True: 0, False: 0]
  ------------------
  453|      0|            char *text = mp_property_expand_escaped_string(mpctx, custom_msg);
  454|      0|            *buffer = talloc_strdup_append(*buffer, text);
  ------------------
  |  |   57|      0|#define talloc_strdup_append            ta_talloc_strdup_append
  ------------------
  455|      0|            talloc_free(text);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  456|      2|        } else {
  457|      2|            sadd_hhmmssff(buffer, get_playback_time(mpctx), fractions);
  458|      2|            if (level == 3) {
  ------------------
  |  Branch (458:17): [True: 1, False: 1]
  ------------------
  459|      1|                saddf(buffer, " / ");
  ------------------
  |  |   47|      1|#define saddf(var, ...) (*(var) = talloc_asprintf_append((*var), __VA_ARGS__))
  |  |  ------------------
  |  |  |  |   63|      1|#define talloc_asprintf_append          ta_talloc_asprintf_append
  |  |  ------------------
  ------------------
  460|      1|                sadd_hhmmssff(buffer, get_time_length(mpctx), fractions);
  461|      1|                sadd_percentage(buffer, get_current_pos_ratio(mpctx, false));
  462|      1|            }
  463|      2|        }
  464|      2|    }
  465|  17.4k|}

mp_wait_events:
   54|  19.0k|{
   55|  19.0k|    mp_client_send_property_changes(mpctx);
   56|       |
   57|  19.0k|    stats_event(mpctx->stats, "iterations");
   58|       |
   59|  19.0k|    bool sleeping = mpctx->sleeptime > 0;
   60|  19.0k|    if (sleeping)
  ------------------
  |  Branch (60:9): [True: 1.96k, False: 17.0k]
  ------------------
   61|  19.0k|        MP_STATS(mpctx, "start sleep");
  ------------------
  |  |   95|  1.96k|#define MP_STATS(obj, ...)      MP_MSG(obj, MSGL_STATS, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  1.96k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
   62|       |
   63|  19.0k|    mp_dispatch_queue_process(mpctx->dispatch, mpctx->sleeptime);
   64|       |
   65|  19.0k|    mpctx->sleeptime = INFINITY;
   66|       |
   67|  19.0k|    if (sleeping)
  ------------------
  |  Branch (67:9): [True: 1.96k, False: 17.0k]
  ------------------
   68|  19.0k|        MP_STATS(mpctx, "end sleep");
  ------------------
  |  |   95|  1.96k|#define MP_STATS(obj, ...)      MP_MSG(obj, MSGL_STATS, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  1.96k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
   69|  19.0k|}
mp_set_timeout:
   75|  19.1k|{
   76|  19.1k|    if (mpctx->sleeptime > sleeptime) {
  ------------------
  |  Branch (76:9): [True: 685, False: 18.4k]
  ------------------
   77|    685|        mpctx->sleeptime = sleeptime;
   78|    685|        int64_t abstime = mp_time_ns_add(mp_time_ns(), sleeptime);
   79|    685|        mp_dispatch_adjust_timeout(mpctx->dispatch, abstime);
   80|    685|    }
   81|  19.1k|}
mp_wakeup_core:
   87|  87.5k|{
   88|  87.5k|    mp_dispatch_interrupt(mpctx->dispatch);
   89|  87.5k|}
mp_wakeup_core_cb:
   93|     78|{
   94|     78|    struct MPContext *mpctx = ctx;
   95|     78|    mp_wakeup_core(mpctx);
   96|     78|}
handle_option_callbacks:
  127|  30.5k|{
  128|  42.7k|    for (int i = 0; i < mpctx->num_option_callbacks; i++)
  ------------------
  |  Branch (128:21): [True: 12.1k, False: 30.5k]
  ------------------
  129|  12.1k|        mp_option_run_callback(mpctx, &mpctx->option_callbacks[i]);
  130|  30.5k|    mpctx->num_option_callbacks = 0;
  131|  30.5k|}
get_relative_time:
  134|  1.53k|{
  135|  1.53k|    int64_t new_time = mp_time_ns();
  136|  1.53k|    int64_t delta = new_time - mpctx->last_time;
  137|  1.53k|    mpctx->last_time = new_time;
  138|  1.53k|    return delta * 1e-9;
  139|  1.53k|}
update_core_idle_state:
  142|  11.7k|{
  143|  11.7k|    bool eof = mpctx->video_status == STATUS_EOF &&
  ------------------
  |  Branch (143:16): [True: 11.7k, False: 0]
  ------------------
  144|  11.7k|               mpctx->audio_status == STATUS_EOF;
  ------------------
  |  Branch (144:16): [True: 11.7k, False: 0]
  ------------------
  145|  11.7k|    bool active = !mpctx->paused && mpctx->restart_complete &&
  ------------------
  |  Branch (145:19): [True: 7.20k, False: 4.59k]
  |  Branch (145:37): [True: 0, False: 7.20k]
  ------------------
  146|  11.7k|                  !mpctx->stop_play && mpctx->in_playloop && !eof;
  ------------------
  |  Branch (146:19): [True: 0, False: 0]
  |  Branch (146:40): [True: 0, False: 0]
  |  Branch (146:62): [True: 0, False: 0]
  ------------------
  147|       |
  148|  11.7k|    if (mpctx->playback_active != active) {
  ------------------
  |  Branch (148:9): [True: 0, False: 11.7k]
  ------------------
  149|      0|        mpctx->playback_active = active;
  150|       |
  151|      0|        update_screensaver_state(mpctx);
  152|       |
  153|      0|        mp_notify(mpctx, MP_EVENT_CORE_IDLE, NULL);
  154|      0|    }
  155|  11.7k|}
get_internal_paused:
  158|  3.93k|{
  159|  3.93k|    return mpctx->opts->pause || mpctx->paused_for_cache;
  ------------------
  |  Branch (159:12): [True: 1.53k, False: 2.40k]
  |  Branch (159:34): [True: 0, False: 2.40k]
  ------------------
  160|  3.93k|}
set_pause_state:
  164|  3.93k|{
  165|  3.93k|    struct MPOpts *opts = mpctx->opts;
  166|       |
  167|  3.93k|    opts->pause = user_pause;
  168|       |
  169|  3.93k|    bool internal_paused = get_internal_paused(mpctx);
  170|  3.93k|    if (internal_paused != mpctx->paused) {
  ------------------
  |  Branch (170:9): [True: 1.53k, False: 2.40k]
  ------------------
  171|  1.53k|        mpctx->paused = internal_paused;
  172|       |
  173|  1.53k|        if (mpctx->ao) {
  ------------------
  |  Branch (173:13): [True: 0, False: 1.53k]
  ------------------
  174|      0|            bool eof = mpctx->audio_status == STATUS_EOF;
  175|      0|            ao_set_paused(mpctx->ao, internal_paused, eof);
  176|      0|        }
  177|       |
  178|  1.53k|        if (mpctx->video_out)
  ------------------
  |  Branch (178:13): [True: 0, False: 1.53k]
  ------------------
  179|      0|            vo_set_paused(mpctx->video_out, internal_paused);
  180|       |
  181|  1.53k|        mpctx->osd_function = 0;
  182|  1.53k|        mpctx->osd_force_update = true;
  183|       |
  184|  1.53k|        mp_wakeup_core(mpctx);
  185|       |
  186|  1.53k|        if (internal_paused) {
  ------------------
  |  Branch (186:13): [True: 1.53k, False: 0]
  ------------------
  187|  1.53k|            mpctx->step_frames = 0;
  188|  1.53k|            mpctx->time_frame -= get_relative_time(mpctx);
  189|  1.53k|        } else {
  190|      0|            (void)get_relative_time(mpctx); // ignore time that passed during pause
  191|      0|        }
  192|  1.53k|    }
  193|       |
  194|  3.93k|    update_core_idle_state(mpctx);
  195|       |
  196|  3.93k|    m_config_notify_change_opt_ptr(mpctx->mconfig, &opts->pause);
  197|  3.93k|}
update_internal_pause_state:
  200|  3.93k|{
  201|  3.93k|    set_pause_state(mpctx, mpctx->opts->pause);
  202|  3.93k|}
update_screensaver_state:
  205|  12.1k|{
  206|  12.1k|    if (!mpctx->video_out)
  ------------------
  |  Branch (206:9): [True: 12.1k, False: 39]
  ------------------
  207|  12.1k|        return;
  208|       |
  209|     39|    bool saver_state = (!mpctx->playback_active || !mpctx->opts->stop_screensaver) &&
  ------------------
  |  Branch (209:25): [True: 39, False: 0]
  |  Branch (209:52): [True: 0, False: 0]
  ------------------
  210|     39|                       mpctx->opts->stop_screensaver != 2;
  ------------------
  |  Branch (210:24): [True: 39, False: 0]
  ------------------
  211|     39|    vo_control_async(mpctx->video_out, saver_state ? VOCTRL_RESTORE_SCREENSAVER
  ------------------
  |  Branch (211:40): [True: 39, False: 0]
  ------------------
  212|     39|                                                   : VOCTRL_KILL_SCREENSAVER, NULL);
  213|     39|}
reset_playback_state:
  241|  3.93k|{
  242|  3.93k|    mp_filter_reset(mpctx->filter_root);
  243|       |
  244|  3.93k|    reset_video_state(mpctx);
  245|  3.93k|    reset_audio_state(mpctx);
  246|  3.93k|    reset_subtitle_state(mpctx);
  247|       |
  248|  3.93k|    for (int n = 0; n < mpctx->num_tracks; n++) {
  ------------------
  |  Branch (248:21): [True: 0, False: 3.93k]
  ------------------
  249|      0|        struct track *t = mpctx->tracks[n];
  250|       |        // (Often, but not always, this is redundant and also done elsewhere.)
  251|      0|        if (t->dec)
  ------------------
  |  Branch (251:13): [True: 0, False: 0]
  ------------------
  252|      0|            mp_decoder_wrapper_set_play_dir(t->dec, mpctx->play_dir);
  253|      0|        if (t->d_sub)
  ------------------
  |  Branch (253:13): [True: 0, False: 0]
  ------------------
  254|      0|            sub_set_play_dir(t->d_sub, mpctx->play_dir);
  255|      0|    }
  256|       |
  257|       |    // May need unpause first
  258|  3.93k|    if (mpctx->paused_for_cache)
  ------------------
  |  Branch (258:9): [True: 0, False: 3.93k]
  ------------------
  259|      0|        update_internal_pause_state(mpctx);
  260|       |
  261|  3.93k|    mpctx->hrseek_active = false;
  262|  3.93k|    mpctx->hrseek_lastframe = false;
  263|  3.93k|    mpctx->hrseek_backstep = false;
  264|  3.93k|    mpctx->current_seek = (struct seek_params){0};
  265|  3.93k|    mpctx->playback_pts = MP_NOPTS_VALUE;
  ------------------
  |  |   38|  3.93k|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  266|  3.93k|    mpctx->step_frames = 0;
  267|  3.93k|    mpctx->ab_loop_clip = true;
  268|  3.93k|    mpctx->restart_complete = false;
  269|  3.93k|    mpctx->paused_for_cache = false;
  270|  3.93k|    mpctx->cache_buffer = 100;
  271|  3.93k|    mpctx->cache_update_pts = MP_NOPTS_VALUE;
  ------------------
  |  |   38|  3.93k|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  272|       |
  273|  3.93k|    encode_lavc_discontinuity(mpctx->encode_lavc_ctx);
  274|       |
  275|  3.93k|    update_internal_pause_state(mpctx);
  276|  3.93k|    update_core_idle_state(mpctx);
  277|  3.93k|}
get_time_length:
  523|     55|{
  524|     55|    struct demuxer *demuxer = mpctx->demuxer;
  525|     55|    return demuxer && demuxer->duration >= 0 ? demuxer->duration : MP_NOPTS_VALUE;
  ------------------
  |  |   38|     55|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (525:12): [True: 0, False: 55]
  |  Branch (525:23): [True: 0, False: 0]
  ------------------
  526|     55|}
get_current_time:
  543|     38|{
  544|     38|    if (!mpctx->demuxer)
  ------------------
  |  Branch (544:9): [True: 38, False: 0]
  ------------------
  545|     38|        return MP_NOPTS_VALUE;
  ------------------
  |  |   38|     38|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  546|      0|    if (mpctx->playback_pts != MP_NOPTS_VALUE)
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (546:9): [True: 0, False: 0]
  ------------------
  547|      0|        return mpctx->playback_pts * mpctx->play_dir;
  548|      0|    return mpctx->last_seek_pts;
  549|      0|}
get_playback_time:
  552|     38|{
  553|     38|    double cur = get_current_time(mpctx);
  554|       |    // During seeking, the time corresponds to the last seek time - apply some
  555|       |    // cosmetics to it.
  556|     38|    if (cur != MP_NOPTS_VALUE && mpctx->playback_pts == MP_NOPTS_VALUE) {
  ------------------
  |  |   38|     76|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
                  if (cur != MP_NOPTS_VALUE && mpctx->playback_pts == MP_NOPTS_VALUE) {
  ------------------
  |  |   38|      0|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (556:9): [True: 0, False: 38]
  |  Branch (556:34): [True: 0, False: 0]
  ------------------
  557|      0|        double length = get_time_length(mpctx);
  558|      0|        if (length >= 0)
  ------------------
  |  Branch (558:13): [True: 0, False: 0]
  ------------------
  559|      0|            cur = MPCLAMP(cur, 0, length);
  ------------------
  |  |   45|      0|#define MPCLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
  |  |  ------------------
  |  |  |  Branch (45:31): [True: 0, False: 0]
  |  |  |  Branch (45:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  560|      0|    }
  561|       |    // Force to 0 if this is not MP_NOPTS_VALUE.
  562|     38|    if (cur != MP_NOPTS_VALUE && cur < 0)
  ------------------
  |  |   38|     76|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (562:9): [True: 0, False: 38]
  |  Branch (562:34): [True: 0, False: 0]
  ------------------
  563|      0|        cur = 0.0;
  564|     38|    return cur;
  565|     38|}
get_current_pos_ratio:
  569|     12|{
  570|     12|    struct demuxer *demuxer = mpctx->demuxer;
  571|     12|    if (!demuxer)
  ------------------
  |  Branch (571:9): [True: 12, False: 0]
  ------------------
  572|     12|        return -1;
  573|      0|    double ret = -1;
  574|      0|    double start = 0;
  575|      0|    double len = get_time_length(mpctx);
  576|      0|    if (use_range) {
  ------------------
  |  Branch (576:9): [True: 0, False: 0]
  ------------------
  577|      0|        double startpos = get_play_start_pts(mpctx);
  578|      0|        double endpos = get_play_end_pts(mpctx);
  579|      0|        if (endpos > MPMAX(0, len))
  ------------------
  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (579:13): [True: 0, False: 0]
  ------------------
  580|      0|            endpos = MPMAX(0, len);
  ------------------
  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  581|      0|        if (endpos < startpos)
  ------------------
  |  Branch (581:13): [True: 0, False: 0]
  ------------------
  582|      0|            endpos = startpos;
  583|      0|        start = startpos;
  584|      0|        len = endpos - startpos;
  585|      0|    }
  586|      0|    double pos = get_current_time(mpctx);
  587|      0|    if (len > 0)
  ------------------
  |  Branch (587:9): [True: 0, False: 0]
  ------------------
  588|      0|        ret = MPCLAMP((pos - start) / len, 0, 1);
  ------------------
  |  |   45|      0|#define MPCLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
  |  |  ------------------
  |  |  |  Branch (45:31): [True: 0, False: 0]
  |  |  |  Branch (45:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  589|      0|    if (ret < 0) {
  ------------------
  |  Branch (589:9): [True: 0, False: 0]
  ------------------
  590|      0|        int64_t size = demuxer->filesize;
  591|      0|        if (size > 0 && demuxer->filepos >= 0)
  ------------------
  |  Branch (591:13): [True: 0, False: 0]
  |  Branch (591:25): [True: 0, False: 0]
  ------------------
  592|      0|            ret = MPCLAMP(demuxer->filepos / (double)size, 0, 1);
  ------------------
  |  |   45|      0|#define MPCLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
  |  |  ------------------
  |  |  |  Branch (45:31): [True: 0, False: 0]
  |  |  |  Branch (45:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  593|      0|    }
  594|      0|    if (use_range) {
  ------------------
  |  Branch (594:9): [True: 0, False: 0]
  ------------------
  595|      0|        if (mpctx->opts->play_frames > 0)
  ------------------
  |  Branch (595:13): [True: 0, False: 0]
  ------------------
  596|      0|            ret = MPMAX(ret, 1.0 -
  ------------------
  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  597|      0|                    mpctx->max_frames / (double) mpctx->opts->play_frames);
  598|      0|    }
  599|      0|    return ret;
  600|     12|}
get_chapter_count:
  654|     40|{
  655|     40|    return mpctx->num_chapters;
  656|     40|}
handle_force_window:
 1022|    474|{
 1023|       |    // True if we're either in idle mode, or loading of the file has finished.
 1024|       |    // It's also set via force in some stages during file loading.
 1025|    474|    bool act = mpctx->stop_play || mpctx->playback_initialized || force;
  ------------------
  |  Branch (1025:16): [True: 69, False: 405]
  |  Branch (1025:36): [True: 0, False: 405]
  |  Branch (1025:67): [True: 0, False: 405]
  ------------------
 1026|       |
 1027|       |    // On the other hand, if a video track is selected, but no video is ever
 1028|       |    // decoded on it, then create the window.
 1029|    474|    bool stalled_video = mpctx->playback_initialized && mpctx->restart_complete &&
  ------------------
  |  Branch (1029:26): [True: 0, False: 474]
  |  Branch (1029:57): [True: 0, False: 0]
  ------------------
 1030|    474|                         mpctx->video_status == STATUS_EOF && mpctx->vo_chain &&
  ------------------
  |  Branch (1030:26): [True: 0, False: 0]
  |  Branch (1030:63): [True: 0, False: 0]
  ------------------
 1031|    474|                         !mpctx->video_out->config_ok;
  ------------------
  |  Branch (1031:26): [True: 0, False: 0]
  ------------------
 1032|       |
 1033|       |    // Don't interfere with real video playback
 1034|    474|    if (mpctx->vo_chain && !stalled_video)
  ------------------
  |  Branch (1034:9): [True: 0, False: 474]
  |  Branch (1034:28): [True: 0, False: 0]
  ------------------
 1035|      0|        return 0;
 1036|       |
 1037|    474|    if (!mpctx->opts->force_vo) {
  ------------------
  |  Branch (1037:9): [True: 423, False: 51]
  ------------------
 1038|    423|        if (act && !mpctx->vo_chain)
  ------------------
  |  Branch (1038:13): [True: 24, False: 399]
  |  Branch (1038:20): [True: 24, False: 0]
  ------------------
 1039|     24|            uninit_video_out(mpctx);
 1040|    423|        return 0;
 1041|    423|    }
 1042|       |
 1043|     51|    if (mpctx->opts->force_vo != 2 && !act)
  ------------------
  |  Branch (1043:9): [True: 51, False: 0]
  |  Branch (1043:39): [True: 6, False: 45]
  ------------------
 1044|      6|        return 0;
 1045|       |
 1046|     45|    if (!mpctx->video_out) {
  ------------------
  |  Branch (1046:9): [True: 45, False: 0]
  ------------------
 1047|     45|        struct vo_extra ex = {
 1048|     45|            .input_ctx = mpctx->input,
 1049|     45|            .osd = mpctx->osd,
 1050|     45|            .encode_lavc_ctx = mpctx->encode_lavc_ctx,
 1051|     45|            .wakeup_cb = mp_wakeup_core_cb,
 1052|     45|            .wakeup_ctx = mpctx,
 1053|     45|        };
 1054|     45|        mpctx->video_out = init_best_video_out(mpctx->global, &ex);
 1055|     45|        if (!mpctx->video_out)
  ------------------
  |  Branch (1055:13): [True: 6, False: 39]
  ------------------
 1056|      6|            goto err;
 1057|     39|        mpctx->mouse_cursor_visible = true;
 1058|     39|    }
 1059|       |
 1060|     39|    if (!mpctx->video_out->config_ok || force) {
  ------------------
  |  Branch (1060:9): [True: 39, False: 0]
  |  Branch (1060:41): [True: 0, False: 0]
  ------------------
 1061|     39|        struct vo *vo = mpctx->video_out;
 1062|       |        // Pick whatever works
 1063|     39|        int config_format = 0;
 1064|     39|        uint8_t fmts[IMGFMT_END - IMGFMT_START] = {0};
 1065|     39|        vo_query_formats(vo, fmts);
 1066|    546|        for (int fmt = IMGFMT_START; fmt < IMGFMT_END; fmt++) {
  ------------------
  |  Branch (1066:38): [True: 546, False: 0]
  ------------------
 1067|    546|            if (fmts[fmt - IMGFMT_START]) {
  ------------------
  |  Branch (1067:17): [True: 39, False: 507]
  ------------------
 1068|     39|                config_format = fmt;
 1069|     39|                break;
 1070|     39|            }
 1071|    546|        }
 1072|       |
 1073|       |        // Use a 16:9 aspect ratio so that fullscreen on a 16:9 screen will not
 1074|       |        // have vertical margins, which can lead to a different size or position
 1075|       |        // of subtitles than with 16:9 videos.
 1076|     39|        int w = 960;
 1077|     39|        int h = 540;
 1078|     39|        struct mp_image_params p = {
 1079|     39|            .imgfmt = config_format,
 1080|     39|            .w = w,   .h = h,
 1081|     39|            .p_w = 1, .p_h = 1,
 1082|     39|            .force_window = true,
 1083|     39|        };
 1084|     39|        if (vo_reconfig(vo, &p) < 0)
  ------------------
  |  Branch (1084:13): [True: 0, False: 39]
  ------------------
 1085|      0|            goto err;
 1086|     39|        struct track *track = mpctx->current_track[0][STREAM_VIDEO];
 1087|     39|        update_content_type(mpctx, track);
 1088|     39|        update_screensaver_state(mpctx);
 1089|     39|        vo_set_paused(vo, true);
 1090|     39|        vo_redraw(vo);
 1091|     39|        mp_notify(mpctx, MPV_EVENT_VIDEO_RECONFIG, NULL);
 1092|     39|    }
 1093|       |
 1094|     39|    return 0;
 1095|       |
 1096|      6|err:
 1097|      6|    mpctx->opts->force_vo = 0;
 1098|      6|    m_config_notify_change_opt_ptr(mpctx->mconfig, &mpctx->opts->force_vo);
 1099|      6|    uninit_video_out(mpctx);
 1100|      6|    MP_FATAL(mpctx, "Error opening/initializing the VO window.\n");
  ------------------
  |  |   84|      6|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      6|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1101|      6|    return -1;
 1102|     39|}
mp_idle:
 1318|  18.4k|{
 1319|  18.4k|    handle_dummy_ticks(mpctx);
 1320|  18.4k|    handle_clipboard_updates(mpctx);
 1321|  18.4k|    mp_wait_events(mpctx);
 1322|  18.4k|    mp_process_input(mpctx);
 1323|  18.4k|    handle_option_callbacks(mpctx);
 1324|  18.4k|    handle_command_updates(mpctx);
 1325|  18.4k|    handle_update_cache(mpctx);
 1326|  18.4k|    handle_cursor_autohide(mpctx);
 1327|  18.4k|    handle_vo_events(mpctx);
 1328|  18.4k|    update_osd_msg(mpctx);
 1329|  18.4k|    handle_osd_redraw(mpctx);
 1330|  18.4k|}
idle_loop:
 1334|  15.6k|{
 1335|       |    // ================= idle loop (STOP state) =========================
 1336|  15.6k|    bool need_reinit = true;
 1337|  15.7k|    while (mpctx->opts->player_idle_mode && mpctx->stop_play == PT_STOP) {
  ------------------
  |  Branch (1337:12): [True: 15.7k, False: 7]
  |  Branch (1337:45): [True: 70, False: 15.6k]
  ------------------
 1338|     70|        if (need_reinit) {
  ------------------
  |  Branch (1338:13): [True: 69, False: 1]
  ------------------
 1339|     69|            uninit_audio_out(mpctx);
 1340|     69|            handle_force_window(mpctx, true);
 1341|     69|            mp_wakeup_core(mpctx);
 1342|     69|            mp_notify(mpctx, MPV_EVENT_IDLE, NULL);
 1343|     69|            need_reinit = false;
 1344|     69|        }
 1345|     70|        mp_idle(mpctx);
 1346|     70|    }
 1347|  15.6k|}
playloop.c:handle_cursor_autohide:
  842|  18.4k|{
  843|  18.4k|    struct MPOpts *opts = mpctx->opts;
  844|  18.4k|    struct vo *vo = mpctx->video_out;
  845|       |
  846|  18.4k|    if (!vo)
  ------------------
  |  Branch (846:9): [True: 18.4k, False: 39]
  ------------------
  847|  18.4k|        return;
  848|       |
  849|     39|    bool mouse_cursor_visible = mpctx->mouse_cursor_visible;
  850|     39|    double now = mp_time_sec();
  851|       |
  852|     39|    unsigned mouse_event_ts = mp_input_get_mouse_event_counter(mpctx->input);
  853|     39|    if (mpctx->mouse_event_ts != mouse_event_ts) {
  ------------------
  |  Branch (853:9): [True: 0, False: 39]
  ------------------
  854|      0|        mpctx->mouse_event_ts = mouse_event_ts;
  855|      0|        mpctx->mouse_timer = now + opts->cursor_autohide_delay / 1000.0;
  856|      0|        mouse_cursor_visible = true;
  857|      0|    }
  858|       |
  859|     39|    if (mpctx->mouse_timer > now) {
  ------------------
  |  Branch (859:9): [True: 0, False: 39]
  ------------------
  860|      0|        mp_set_timeout(mpctx, mpctx->mouse_timer - now);
  861|     39|    } else {
  862|     39|        mouse_cursor_visible = false;
  863|     39|    }
  864|       |
  865|     39|    if (opts->cursor_autohide_delay == -1)
  ------------------
  |  Branch (865:9): [True: 0, False: 39]
  ------------------
  866|      0|        mouse_cursor_visible = true;
  867|       |
  868|     39|    if (opts->cursor_autohide_delay == -2)
  ------------------
  |  Branch (868:9): [True: 0, False: 39]
  ------------------
  869|      0|        mouse_cursor_visible = false;
  870|       |
  871|     39|    if (opts->cursor_autohide_fs && !opts->vo->fullscreen)
  ------------------
  |  Branch (871:9): [True: 0, False: 39]
  |  Branch (871:37): [True: 0, False: 0]
  ------------------
  872|      0|        mouse_cursor_visible = true;
  873|       |
  874|     39|    if (mouse_cursor_visible != mpctx->mouse_cursor_visible)
  ------------------
  |  Branch (874:9): [True: 39, False: 0]
  ------------------
  875|     39|        vo_control(vo, VOCTRL_SET_CURSOR_VISIBILITY, &mouse_cursor_visible);
  876|     39|    mpctx->mouse_cursor_visible = mouse_cursor_visible;
  877|     39|}
playloop.c:handle_vo_events:
  880|  18.4k|{
  881|  18.4k|    struct vo *vo = mpctx->video_out;
  882|  18.4k|    int events = vo ? vo_query_and_reset_events(vo, VO_EVENTS_USER) : 0;
  ------------------
  |  Branch (882:18): [True: 39, False: 18.4k]
  ------------------
  883|  18.4k|    if (events & VO_EVENT_RESIZE)
  ------------------
  |  Branch (883:9): [True: 0, False: 18.4k]
  ------------------
  884|      0|        mp_notify(mpctx, MP_EVENT_WIN_RESIZE, NULL);
  885|  18.4k|    if (events & VO_EVENT_WIN_STATE)
  ------------------
  |  Branch (885:9): [True: 39, False: 18.4k]
  ------------------
  886|     39|        mp_notify(mpctx, MP_EVENT_WIN_STATE, NULL);
  887|  18.4k|    if (events & VO_EVENT_DPI)
  ------------------
  |  Branch (887:9): [True: 0, False: 18.4k]
  ------------------
  888|      0|        mp_notify(mpctx, MP_EVENT_WIN_STATE2, NULL);
  889|  18.4k|    if (events & VO_EVENT_FOCUS)
  ------------------
  |  Branch (889:9): [True: 0, False: 18.4k]
  ------------------
  890|      0|        mp_notify(mpctx, MP_EVENT_FOCUS, NULL);
  891|  18.4k|    if (events & VO_EVENT_AMBIENT_LIGHTING_CHANGED)
  ------------------
  |  Branch (891:9): [True: 0, False: 18.4k]
  ------------------
  892|      0|        mp_notify(mpctx, MP_EVENT_AMBIENT_LIGHTING_CHANGED, NULL);
  893|  18.4k|}
playloop.c:handle_dummy_ticks:
 1106|  18.4k|{
 1107|  18.4k|    if ((mpctx->video_status != STATUS_PLAYING &&
  ------------------
  |  Branch (1107:10): [True: 18.4k, False: 0]
  ------------------
 1108|  18.4k|         mpctx->video_status != STATUS_DRAINING) ||
  ------------------
  |  Branch (1108:10): [True: 18.4k, False: 0]
  ------------------
 1109|  18.4k|         mpctx->paused)
  ------------------
  |  Branch (1109:10): [True: 0, False: 0]
  ------------------
 1110|  18.4k|    {
 1111|  18.4k|        if (mp_time_sec() - mpctx->last_idle_tick > 0.050) {
  ------------------
  |  Branch (1111:13): [True: 17.0k, False: 1.38k]
  ------------------
 1112|  17.0k|            mpctx->last_idle_tick = mp_time_sec();
 1113|  17.0k|            mp_notify(mpctx, MPV_EVENT_TICK, NULL);
 1114|  17.0k|        }
 1115|  18.4k|    }
 1116|  18.4k|}
playloop.c:handle_clipboard_updates:
 1246|  18.4k|{
 1247|  18.4k|    if (mp_clipboard_data_changed(mpctx->clipboard))
  ------------------
  |  Branch (1247:9): [True: 0, False: 18.4k]
  ------------------
 1248|      0|        mp_notify_property(mpctx, "clipboard");
 1249|  18.4k|}
playloop.c:handle_osd_redraw:
  671|  18.4k|{
  672|  18.4k|    if (!mpctx->video_out || !mpctx->video_out->config_ok || (mpctx->playing && mpctx->stop_play))
  ------------------
  |  Branch (672:9): [True: 18.4k, False: 39]
  |  Branch (672:30): [True: 0, False: 39]
  |  Branch (672:63): [True: 0, False: 39]
  |  Branch (672:81): [True: 0, False: 0]
  ------------------
  673|  18.4k|        return;
  674|       |    // If we're playing normally, let OSD be redrawn naturally as part of
  675|       |    // video display.
  676|     39|    if (!mpctx->paused) {
  ------------------
  |  Branch (676:9): [True: 28, False: 11]
  ------------------
  677|     28|        if (mpctx->sleeptime < 0.1 && mpctx->video_status == STATUS_PLAYING)
  ------------------
  |  Branch (677:13): [True: 28, False: 0]
  |  Branch (677:39): [True: 0, False: 28]
  ------------------
  678|      0|            return;
  679|     28|    }
  680|       |    // Don't redraw immediately during a seek (makes it significantly slower).
  681|     39|    bool use_video = mpctx->vo_chain && !mpctx->vo_chain->is_sparse;
  ------------------
  |  Branch (681:22): [True: 0, False: 39]
  |  Branch (681:41): [True: 0, False: 0]
  ------------------
  682|     39|    if (use_video && mp_time_sec() - mpctx->start_timestamp < 0.1) {
  ------------------
  |  Branch (682:9): [True: 0, False: 39]
  |  Branch (682:22): [True: 0, False: 0]
  ------------------
  683|      0|        mp_set_timeout(mpctx, 0.1);
  684|      0|        return;
  685|      0|    }
  686|     39|    bool want_redraw = osd_query_and_reset_want_redraw(mpctx->osd) ||
  ------------------
  |  Branch (686:24): [True: 39, False: 0]
  ------------------
  687|     39|                       vo_want_redraw(mpctx->video_out);
  ------------------
  |  Branch (687:24): [True: 0, False: 0]
  ------------------
  688|     39|    if (!want_redraw)
  ------------------
  |  Branch (688:9): [True: 0, False: 39]
  ------------------
  689|      0|        return;
  690|     39|    vo_redraw(mpctx->video_out);
  691|     39|}
playloop.c:handle_update_cache:
  707|  18.4k|{
  708|  18.4k|    bool force_update = false;
  709|  18.4k|    struct MPOpts *opts = mpctx->opts;
  710|       |
  711|  18.4k|    if (!mpctx->demuxer || mpctx->encode_lavc_ctx) {
  ------------------
  |  Branch (711:9): [True: 18.4k, False: 0]
  |  Branch (711:28): [True: 0, False: 0]
  ------------------
  712|  18.4k|        clear_underruns(mpctx);
  713|  18.4k|        return;
  714|  18.4k|    }
  715|       |
  716|      0|    double now = mp_time_sec();
  717|       |
  718|      0|    struct demux_reader_state s;
  719|      0|    demux_get_reader_state(mpctx->demuxer, &s);
  720|       |
  721|      0|    mpctx->demux_underrun |= s.underrun;
  722|       |
  723|      0|    int cache_buffer = 100;
  724|      0|    bool use_pause_on_low_cache = opts->cache_pause && mpctx->play_dir > 0;
  ------------------
  |  Branch (724:35): [True: 0, False: 0]
  |  Branch (724:56): [True: 0, False: 0]
  ------------------
  725|       |
  726|      0|    if (!mpctx->restart_complete) {
  ------------------
  |  Branch (726:9): [True: 0, False: 0]
  ------------------
  727|       |        // Audio or video is restarting, and initial buffering is enabled. Make
  728|       |        // sure we actually restart them in paused mode, so no audio gets
  729|       |        // dropped and video technically doesn't start yet.
  730|      0|        use_pause_on_low_cache &= opts->cache_pause_initial &&
  ------------------
  |  Branch (730:35): [True: 0, False: 0]
  ------------------
  731|      0|                                    (mpctx->video_status == STATUS_READY ||
  ------------------
  |  Branch (731:38): [True: 0, False: 0]
  ------------------
  732|      0|                                     mpctx->audio_status == STATUS_READY);
  ------------------
  |  Branch (732:38): [True: 0, False: 0]
  ------------------
  733|      0|    }
  734|       |
  735|      0|    bool is_low = use_pause_on_low_cache && !s.idle &&
  ------------------
  |  Branch (735:19): [True: 0, False: 0]
  |  Branch (735:45): [True: 0, False: 0]
  ------------------
  736|      0|                  s.ts_info.duration < opts->cache_pause_wait;
  ------------------
  |  Branch (736:19): [True: 0, False: 0]
  ------------------
  737|       |
  738|       |    // Enter buffering state only if there actually was an underrun (or if
  739|       |    // initial caching before playback restart is used).
  740|      0|    bool need_wait = is_low;
  741|      0|    if (is_low && !mpctx->paused_for_cache && mpctx->restart_complete) {
  ------------------
  |  Branch (741:9): [True: 0, False: 0]
  |  Branch (741:19): [True: 0, False: 0]
  |  Branch (741:47): [True: 0, False: 0]
  ------------------
  742|       |        // Wait only if an output underrun was registered. (Or if there is no
  743|       |        // underrun detection.)
  744|      0|        bool output_underrun = false;
  745|       |
  746|      0|        if (mpctx->ao_chain)
  ------------------
  |  Branch (746:13): [True: 0, False: 0]
  ------------------
  747|      0|            output_underrun |= mpctx->ao_chain->underrun;
  748|      0|        if (mpctx->vo_chain)
  ------------------
  |  Branch (748:13): [True: 0, False: 0]
  ------------------
  749|      0|            output_underrun |= mpctx->vo_chain->underrun;
  750|       |
  751|       |        // Output underruns could be sporadic (unrelated to demuxer buffer state
  752|       |        // and for example caused by slow decoding), so use a past demuxer
  753|       |        // underrun as indication that the underrun was possibly due to a
  754|       |        // demuxer underrun.
  755|      0|        need_wait = mpctx->demux_underrun && output_underrun;
  ------------------
  |  Branch (755:21): [True: 0, False: 0]
  |  Branch (755:46): [True: 0, False: 0]
  ------------------
  756|      0|    }
  757|       |
  758|       |    // Let the underrun flag "stick" around until the cache has fully recovered.
  759|       |    // See logic where demux_underrun is used.
  760|      0|    if (!is_low)
  ------------------
  |  Branch (760:9): [True: 0, False: 0]
  ------------------
  761|      0|        mpctx->demux_underrun = false;
  762|       |
  763|      0|    if (mpctx->paused_for_cache != need_wait) {
  ------------------
  |  Branch (763:9): [True: 0, False: 0]
  ------------------
  764|      0|        mpctx->paused_for_cache = need_wait;
  765|      0|        update_internal_pause_state(mpctx);
  766|      0|        force_update = true;
  767|      0|        if (mpctx->paused_for_cache)
  ------------------
  |  Branch (767:13): [True: 0, False: 0]
  ------------------
  768|      0|            mpctx->cache_stop_time = now;
  769|      0|    }
  770|       |
  771|      0|    if (!mpctx->paused_for_cache)
  ------------------
  |  Branch (771:9): [True: 0, False: 0]
  ------------------
  772|      0|        clear_underruns(mpctx);
  773|       |
  774|      0|    if (mpctx->paused_for_cache) {
  ------------------
  |  Branch (774:9): [True: 0, False: 0]
  ------------------
  775|      0|        cache_buffer =
  776|      0|            100 * MPCLAMP(s.ts_info.duration / opts->cache_pause_wait, 0, 0.99);
  ------------------
  |  |   45|      0|#define MPCLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
  |  |  ------------------
  |  |  |  Branch (45:31): [True: 0, False: 0]
  |  |  |  Branch (45:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  777|      0|        mp_set_timeout(mpctx, 0.2);
  778|      0|    }
  779|       |
  780|       |    // Also update cache properties.
  781|      0|    bool busy = !s.idle;
  782|      0|    if (fabs(mpctx->cache_update_pts - mpctx->playback_pts) >= 1.0)
  ------------------
  |  Branch (782:9): [True: 0, False: 0]
  ------------------
  783|      0|        busy = true;
  784|      0|    if (busy || mpctx->next_cache_update > 0) {
  ------------------
  |  Branch (784:9): [True: 0, False: 0]
  |  Branch (784:17): [True: 0, False: 0]
  ------------------
  785|      0|        if (mpctx->next_cache_update <= now) {
  ------------------
  |  Branch (785:13): [True: 0, False: 0]
  ------------------
  786|      0|            mpctx->next_cache_update = busy ? now + 0.25 : 0;
  ------------------
  |  Branch (786:40): [True: 0, False: 0]
  ------------------
  787|      0|            force_update = true;
  788|      0|        }
  789|      0|        if (mpctx->next_cache_update > 0)
  ------------------
  |  Branch (789:13): [True: 0, False: 0]
  ------------------
  790|      0|            mp_set_timeout(mpctx, mpctx->next_cache_update - now);
  791|      0|    }
  792|       |
  793|      0|    if (mpctx->cache_buffer != cache_buffer) {
  ------------------
  |  Branch (793:9): [True: 0, False: 0]
  ------------------
  794|      0|        if ((mpctx->cache_buffer == 100) != (cache_buffer == 100)) {
  ------------------
  |  Branch (794:13): [True: 0, False: 0]
  ------------------
  795|      0|            if (cache_buffer < 100) {
  ------------------
  |  Branch (795:17): [True: 0, False: 0]
  ------------------
  796|      0|                MP_VERBOSE(mpctx, "Enter buffering (buffer went from %d%% -> %d%%) [%fs].\n",
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  797|      0|                           mpctx->cache_buffer, cache_buffer, s.ts_info.duration);
  798|      0|            } else {
  799|      0|                double t = now - mpctx->cache_stop_time;
  800|      0|                MP_VERBOSE(mpctx, "End buffering (waited %f secs) [%fs].\n",
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  801|      0|                           t, s.ts_info.duration);
  802|      0|            }
  803|      0|        } else {
  804|      0|            MP_VERBOSE(mpctx, "Still buffering (buffer went from %d%% -> %d%%) [%fs].\n",
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  805|      0|                       mpctx->cache_buffer, cache_buffer, s.ts_info.duration);
  806|      0|        }
  807|      0|        mpctx->cache_buffer = cache_buffer;
  808|      0|        force_update = true;
  809|      0|    }
  810|       |
  811|      0|    if (s.eof && !busy)
  ------------------
  |  Branch (811:9): [True: 0, False: 0]
  |  Branch (811:18): [True: 0, False: 0]
  ------------------
  812|      0|        prefetch_next(mpctx);
  813|       |
  814|      0|    if (force_update) {
  ------------------
  |  Branch (814:9): [True: 0, False: 0]
  ------------------
  815|      0|        mpctx->cache_update_pts = mpctx->playback_pts;
  816|      0|        mp_notify(mpctx, MP_EVENT_CACHE_UPDATE, NULL);
  817|      0|    }
  818|      0|}
playloop.c:clear_underruns:
  694|  18.4k|{
  695|  18.4k|    if (mpctx->ao_chain && mpctx->ao_chain->underrun) {
  ------------------
  |  Branch (695:9): [True: 0, False: 18.4k]
  |  Branch (695:28): [True: 0, False: 0]
  ------------------
  696|      0|        mpctx->ao_chain->underrun = false;
  697|      0|        mp_wakeup_core(mpctx);
  698|      0|    }
  699|       |
  700|  18.4k|    if (mpctx->vo_chain && mpctx->vo_chain->underrun) {
  ------------------
  |  Branch (700:9): [True: 0, False: 18.4k]
  |  Branch (700:28): [True: 0, False: 0]
  ------------------
  701|      0|        mpctx->vo_chain->underrun = false;
  702|      0|        mp_wakeup_core(mpctx);
  703|      0|    }
  704|  18.4k|}
playloop.c:mp_process_input:
  110|  18.4k|{
  111|  18.4k|    bool notify = false;
  112|  18.4k|    for (;;) {
  113|  18.4k|        mp_cmd_t *cmd = mp_input_read_cmd(mpctx->input);
  114|  18.4k|        if (!cmd)
  ------------------
  |  Branch (114:13): [True: 18.4k, False: 0]
  ------------------
  115|  18.4k|            break;
  116|      0|        if (cmd->notify_event)
  ------------------
  |  Branch (116:13): [True: 0, False: 0]
  ------------------
  117|      0|            notify = true;
  118|      0|        run_command(mpctx, cmd, NULL, NULL, NULL);
  119|      0|    }
  120|  18.4k|    mp_set_timeout(mpctx, mp_input_get_delay(mpctx->input));
  121|  18.4k|    if (notify)
  ------------------
  |  Branch (121:9): [True: 0, False: 18.4k]
  ------------------
  122|      0|        mp_notify(mpctx, MP_EVENT_INPUT_PROCESSED, NULL);
  123|  18.4k|}

screenshot_init:
   61|  17.0k|{
   62|  17.0k|    mpctx->screenshot_ctx = talloc(mpctx, screenshot_ctx);
  ------------------
  |  |   26|  17.0k|#define talloc                          ta_xnew
  |  |  ------------------
  |  |  |  |  133|  17.0k|#define ta_xnew(...)                    ta_oom_g(ta_new(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   63|  17.0k|    *mpctx->screenshot_ctx = (screenshot_ctx) {
   64|  17.0k|        .mpctx = mpctx,
   65|  17.0k|        .frameno = 1,
   66|  17.0k|        .log = mp_log_new(mpctx, mpctx->log, "screenshot")
   67|  17.0k|    };
   68|  17.0k|}

mp_load_user_script:
  204|  14.1k|{
  205|  14.1k|    char *path = mp_get_user_path(NULL, mpctx->global, fname);
  206|  14.1k|    int64_t ret = mp_load_script(mpctx, path);
  207|  14.1k|    talloc_free(path);
  ------------------
  |  |   47|  14.1k|#define talloc_free                     ta_free
  ------------------
  208|  14.1k|    return ret;
  209|  14.1k|}
mp_load_builtin_scripts:
  263|  12.1k|{
  264|  12.1k|    load_builtin_script(mpctx, 0, mpctx->opts->lua_load_osc, "@osc.lua");
  265|  12.1k|    load_builtin_script(mpctx, 1, mpctx->opts->lua_load_ytdl, "@ytdl_hook.lua");
  266|  12.1k|    load_builtin_script(mpctx, 2, mpctx->opts->lua_load_stats, "@stats.lua");
  267|  12.1k|    load_builtin_script(mpctx, 3, mpctx->opts->lua_load_console, "@console.lua");
  268|  12.1k|    load_builtin_script(mpctx, 4, mpctx->opts->lua_load_auto_profiles,
  269|  12.1k|                        "@auto_profiles.lua");
  270|  12.1k|    load_builtin_script(mpctx, 5, mpctx->opts->lua_load_select, "@select.lua");
  271|  12.1k|    load_builtin_script(mpctx, 6, mpctx->opts->lua_load_positioning, "@positioning.lua");
  272|  12.1k|    load_builtin_script(mpctx, 7, mpctx->opts->lua_load_commands, "@commands.lua");
  273|  12.1k|}
mp_load_scripts:
  276|  11.8k|{
  277|  11.8k|    bool ok = true;
  278|       |
  279|       |    // Load scripts from options
  280|  11.8k|    char **files = mpctx->opts->script_files;
  281|  26.1k|    for (int n = 0; files && files[n]; n++) {
  ------------------
  |  Branch (281:21): [True: 17.6k, False: 8.44k]
  |  Branch (281:30): [True: 14.2k, False: 3.39k]
  ------------------
  282|  14.2k|        if (files[n][0])
  ------------------
  |  Branch (282:13): [True: 14.1k, False: 155]
  ------------------
  283|  14.1k|            ok &= mp_load_user_script(mpctx, files[n]) >= 0;
  284|  14.2k|    }
  285|  11.8k|    if (!mpctx->opts->auto_load_scripts)
  ------------------
  |  Branch (285:9): [True: 21, False: 11.8k]
  ------------------
  286|     21|        return ok;
  287|       |
  288|       |    // Load all scripts
  289|  11.8k|    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|  11.8k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  11.8k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  290|  11.8k|    char **scriptsdir = mp_find_all_config_files(tmp, mpctx->global, "scripts");
  291|  11.8k|    for (int i = 0; scriptsdir && scriptsdir[i]; i++) {
  ------------------
  |  Branch (291:21): [True: 11.8k, False: 0]
  |  Branch (291:35): [True: 0, False: 11.8k]
  ------------------
  292|      0|        files = list_script_files(tmp, scriptsdir[i]);
  293|      0|        for (int n = 0; files && files[n]; n++)
  ------------------
  |  Branch (293:25): [True: 0, False: 0]
  |  Branch (293:34): [True: 0, False: 0]
  ------------------
  294|      0|            ok &= mp_load_script(mpctx, files[n]) >= 0;
  295|      0|    }
  296|  11.8k|    talloc_free(tmp);
  ------------------
  |  |   47|  11.8k|#define talloc_free                     ta_free
  ------------------
  297|       |
  298|  11.8k|    return ok;
  299|  11.8k|}
scripting.c:mp_load_script:
  106|  14.1k|{
  107|  14.1k|    char *ext = mp_splitext(fname, NULL);
  108|  14.1k|    if (ext && strcasecmp(ext, "disable") == 0)
  ------------------
  |  Branch (108:9): [True: 6.19k, False: 7.94k]
  |  Branch (108:16): [True: 140, False: 6.05k]
  ------------------
  109|    140|        return 0;
  110|       |
  111|  13.9k|    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|  13.9k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  13.9k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  112|       |
  113|  13.9k|    const char *path = NULL;
  114|  13.9k|    char *script_name = NULL;
  115|  13.9k|    const struct mp_scripting *backend = NULL;
  116|       |
  117|  13.9k|    struct stat s;
  118|  13.9k|    if (!stat(fname, &s) && S_ISDIR(s.st_mode)) {
  ------------------
  |  Branch (118:9): [True: 796, False: 13.1k]
  ------------------
  119|    563|        path = fname;
  120|    563|        fname = NULL;
  121|       |
  122|  1.68k|        for (int n = 0; scripting_backends[n]; n++) {
  ------------------
  |  Branch (122:25): [True: 1.12k, False: 563]
  ------------------
  123|  1.12k|            const struct mp_scripting *b = scripting_backends[n];
  124|  1.12k|            char *filename = mp_tprintf(80, "main.%s", b->file_ext);
  ------------------
  |  |  165|  1.12k|    mp_tprintf_buf((char[SIZE]){0}, (SIZE), (format), __VA_ARGS__)
  ------------------
  125|  1.12k|            fname = mp_path_join(tmp, path, filename);
  126|  1.12k|            if (!stat(fname, &s) && S_ISREG(s.st_mode)) {
  ------------------
  |  Branch (126:17): [True: 0, False: 1.12k]
  ------------------
  127|      0|                backend = b;
  128|      0|                break;
  129|      0|            }
  130|  1.12k|            talloc_free((void *)fname);
  ------------------
  |  |   47|  1.12k|#define talloc_free                     ta_free
  ------------------
  131|  1.12k|            fname = NULL;
  132|  1.12k|        }
  133|       |
  134|    563|        if (!fname) {
  ------------------
  |  Branch (134:13): [True: 563, False: 0]
  ------------------
  135|    563|            MP_ERR(mpctx, "Cannot find main.* for any supported scripting "
  ------------------
  |  |   85|    563|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    563|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  136|    563|                   "backend in: %s\n", path);
  137|    563|            talloc_free(tmp);
  ------------------
  |  |   47|    563|#define talloc_free                     ta_free
  ------------------
  138|    563|            return -1;
  139|    563|        }
  140|       |
  141|      0|        script_name = talloc_strdup(tmp, path);
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  142|      0|        mp_path_strip_trailing_separator(script_name);
  143|      0|        script_name = mp_basename(script_name);
  144|  13.4k|    } else {
  145|  34.0k|        for (int n = 0; scripting_backends[n]; n++) {
  ------------------
  |  Branch (145:25): [True: 25.8k, False: 8.13k]
  ------------------
  146|  25.8k|            const struct mp_scripting *b = scripting_backends[n];
  147|  25.8k|            if (ext && strcasecmp(ext, b->file_ext) == 0) {
  ------------------
  |  Branch (147:17): [True: 11.1k, False: 14.7k]
  |  Branch (147:24): [True: 5.29k, False: 5.83k]
  ------------------
  148|  5.29k|                backend = b;
  149|  5.29k|                break;
  150|  5.29k|            }
  151|  25.8k|        }
  152|  13.4k|        script_name = script_name_from_filename(tmp, fname);
  153|  13.4k|    }
  154|       |
  155|  13.4k|    if (!backend) {
  ------------------
  |  Branch (155:9): [True: 8.13k, False: 5.29k]
  ------------------
  156|  8.13k|        MP_ERR(mpctx, "Can't load unknown script: %s\n", fname);
  ------------------
  |  |   85|  8.13k|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  8.13k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  157|  8.13k|        talloc_free(tmp);
  ------------------
  |  |   47|  8.13k|#define talloc_free                     ta_free
  ------------------
  158|  8.13k|        return -1;
  159|  8.13k|    }
  160|       |
  161|  5.29k|    struct mp_script_args *arg = talloc_ptrtype(NULL, arg);
  ------------------
  |  |   34|  5.29k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  5.29k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  5.29k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  162|  5.29k|    *arg = (struct mp_script_args){
  163|  5.29k|        .mpctx = mpctx,
  164|  5.29k|        .filename = talloc_strdup(arg, fname),
  ------------------
  |  |   50|  5.29k|#define talloc_strdup                   ta_xstrdup
  ------------------
  165|  5.29k|        .path = talloc_strdup(arg, path),
  ------------------
  |  |   50|  5.29k|#define talloc_strdup                   ta_xstrdup
  ------------------
  166|  5.29k|        .backend = backend,
  167|       |        // Create the client before creating the thread; otherwise a race
  168|       |        // condition could happen, where MPContext is destroyed while the
  169|       |        // thread tries to create the client.
  170|  5.29k|        .client = mp_new_client(mpctx->clients, script_name),
  171|  5.29k|    };
  172|       |
  173|  5.29k|    talloc_free(tmp);
  ------------------
  |  |   47|  5.29k|#define talloc_free                     ta_free
  ------------------
  174|  5.29k|    fname = NULL; // might have been freed so don't touch anymore
  175|       |
  176|  5.29k|    if (!arg->client) {
  ------------------
  |  Branch (176:9): [True: 68, False: 5.22k]
  ------------------
  177|     68|        MP_ERR(mpctx, "Failed to create client for script: %s\n", arg->filename);
  ------------------
  |  |   85|     68|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     68|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  178|     68|        talloc_free(arg);
  ------------------
  |  |   47|     68|#define talloc_free                     ta_free
  ------------------
  179|     68|        return -1;
  180|     68|    }
  181|       |
  182|  5.22k|    mp_client_set_weak(arg->client);
  183|  5.22k|    arg->log = mp_client_get_log(arg->client);
  184|  5.22k|    int64_t id = mpv_client_id(arg->client);
  185|       |
  186|  5.22k|    MP_DBG(arg, "Loading %s script %s...\n", backend->name, arg->filename);
  ------------------
  |  |   89|  5.22k|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  5.22k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  187|       |
  188|  5.22k|    if (backend->no_thread) {
  ------------------
  |  Branch (188:9): [True: 4.32k, False: 902]
  ------------------
  189|  4.32k|        run_script(arg);
  190|  4.32k|    } else {
  191|    902|        mp_thread thread;
  192|    902|        if (mp_thread_create(&thread, script_thread, arg)) {
  ------------------
  |  |  211|    902|#define mp_thread_create(t, f, a) pthread_create(t, NULL, f, a)
  |  |  ------------------
  |  |  |  Branch (211:35): [True: 0, False: 902]
  |  |  ------------------
  ------------------
  193|      0|            mpv_destroy(arg->client);
  194|      0|            talloc_free(arg);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  195|      0|            return -1;
  196|      0|        }
  197|    902|        mp_thread_detach(thread);
  ------------------
  |  |  213|    902|#define mp_thread_detach          pthread_detach
  ------------------
  198|    902|    }
  199|       |
  200|  5.22k|    return id;
  201|  5.22k|}
scripting.c:script_name_from_filename:
   62|  13.4k|{
   63|  13.4k|    fname = mp_basename(fname);
   64|  13.4k|    if (fname[0] == '@')
  ------------------
  |  Branch (64:9): [True: 84, False: 13.3k]
  ------------------
   65|     84|        fname += 1;
   66|  13.4k|    char *name = talloc_strdup(talloc_ctx, fname);
  ------------------
  |  |   50|  13.4k|#define talloc_strdup                   ta_xstrdup
  ------------------
   67|       |    // Drop file extension
   68|  13.4k|    char *dot = strrchr(name, '.');
   69|  13.4k|    if (dot)
  ------------------
  |  Branch (69:9): [True: 6.26k, False: 7.17k]
  ------------------
   70|  6.26k|        *dot = '\0';
   71|       |    // Turn it into a safe identifier - this is used with e.g. dispatching
   72|       |    // input via: "send scriptname ..."
   73|   239k|    for (int n = 0; name[n]; n++) {
  ------------------
  |  Branch (73:21): [True: 226k, False: 13.4k]
  ------------------
   74|   226k|        char c = name[n];
   75|   226k|        if (!(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') &&
  ------------------
  |  Branch (75:15): [True: 107k, False: 118k]
  |  Branch (75:27): [True: 19.4k, False: 88.0k]
  |  Branch (75:42): [True: 78.8k, False: 128k]
  |  Branch (75:54): [True: 77.5k, False: 1.27k]
  ------------------
   76|   226k|            !(c >= '0' && c <= '9'))
  ------------------
  |  Branch (76:15): [True: 41.0k, False: 88.3k]
  |  Branch (76:27): [True: 28.5k, False: 12.5k]
  ------------------
   77|   100k|            name[n] = '_';
   78|   226k|    }
   79|  13.4k|    return talloc_asprintf(talloc_ctx, "%s", name);
  ------------------
  |  |   52|  13.4k|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|  13.4k|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
   80|  13.4k|}
scripting.c:run_script:
   83|  5.22k|{
   84|  5.22k|    char *name = talloc_asprintf(NULL, "%s/%s", arg->backend->name,
  ------------------
  |  |   52|  5.22k|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|  5.22k|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
   85|  5.22k|                                 mpv_client_name(arg->client));
   86|  5.22k|    mp_thread_set_name(name);
   87|  5.22k|    talloc_free(name);
  ------------------
  |  |   47|  5.22k|#define talloc_free                     ta_free
  ------------------
   88|       |
   89|  5.22k|    if (arg->backend->load(arg) < 0)
  ------------------
  |  Branch (89:9): [True: 5.22k, False: 0]
  ------------------
   90|  5.22k|        MP_ERR(arg, "Could not load %s script %s\n", arg->backend->name, arg->filename);
  ------------------
  |  |   85|  5.22k|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  5.22k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
   91|       |
   92|  5.22k|    mpv_handle *client = arg->client;
   93|  5.22k|    talloc_free(arg);
  ------------------
  |  |   47|  5.22k|#define talloc_free                     ta_free
  ------------------
   94|  5.22k|    mpv_destroy(client);
   95|  5.22k|}
scripting.c:script_thread:
   98|    902|{
   99|    902|    struct mp_script_args *arg = p;
  100|    902|    run_script(arg);
  101|       |
  102|    902|    MP_THREAD_RETURN();
  ------------------
  |  |  209|    902|#define MP_THREAD_RETURN() return NULL
  ------------------
  103|    902|}
scripting.c:load_builtin_script:
  243|  97.1k|{
  244|  97.1k|    mp_assert(slot < MP_ARRAY_SIZE(mpctx->builtin_script_ids));
  ------------------
  |  |   41|  97.1k|#define mp_assert assert
  ------------------
  245|  97.1k|    int64_t *pid = &mpctx->builtin_script_ids[slot];
  246|  97.1k|    if (*pid > 0 && !mp_client_id_exists(mpctx, *pid)) {
  ------------------
  |  Branch (246:9): [True: 0, False: 97.1k]
  |  Branch (246:21): [True: 0, False: 0]
  ------------------
  247|      0|        MP_DBG(mpctx, "Client for script %s is no longer alive. Marking as unloaded.\n", fname);
  ------------------
  |  |   89|      0|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  248|      0|        *pid = 0; // died
  249|      0|    }
  250|  97.1k|    if ((*pid > 0) != enable) {
  ------------------
  |  Branch (250:9): [True: 0, False: 97.1k]
  ------------------
  251|      0|        if (enable) {
  ------------------
  |  Branch (251:13): [True: 0, False: 0]
  ------------------
  252|      0|            *pid = mp_load_script(mpctx, fname);
  253|      0|        } else {
  254|      0|            char *name = mp_tprintf(22, "@%"PRIi64, *pid);
  ------------------
  |  |  165|      0|    mp_tprintf_buf((char[SIZE]){0}, (SIZE), (format), __VA_ARGS__)
  ------------------
  255|      0|            MP_DBG(mpctx, "Unloading script %s (disabled by option)\n", fname);
  ------------------
  |  |   89|      0|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  256|      0|            mp_client_send_event(mpctx, name, 0, MPV_EVENT_SHUTDOWN, NULL);
  257|       |            // note: there is no synchronization of script exit
  258|      0|        }
  259|      0|    }
  260|  97.1k|}
scripting.c:load_cplugin:
  381|    902|{
  382|    902|    void *lib = dlopen(args->filename, RTLD_NOW | RTLD_LOCAL);
  383|    902|    if (!lib)
  ------------------
  |  Branch (383:9): [True: 902, False: 0]
  ------------------
  384|    902|        goto error;
  385|       |    // Note: once loaded, we never unload, as unloading the libraries linked to
  386|       |    //       the plugin can cause random serious problems.
  387|      0|    mpv_open_cplugin sym = (mpv_open_cplugin)dlsym(lib, MPV_DLOPEN_FN);
  ------------------
  |  |  307|      0|#define MPV_DLOPEN_FN "mpv_open_cplugin"
  ------------------
  388|      0|    if (!sym)
  ------------------
  |  Branch (388:9): [True: 0, False: 0]
  ------------------
  389|      0|        goto error;
  390|       |
  391|      0|    init_sym_table(args, lib);
  392|       |
  393|      0|    return sym(args->client) ? -1 : 0;
  ------------------
  |  Branch (393:12): [True: 0, False: 0]
  ------------------
  394|    902|error: ;
  395|    902|    char *err = dlerror();
  396|    902|    if (err)
  ------------------
  |  Branch (396:9): [True: 902, False: 0]
  ------------------
  397|    902|        MP_ERR(args, "C plugin error: '%s'\n", err);
  ------------------
  |  |   85|    902|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    902|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  398|    902|    return -1;
  399|      0|}
scripting.c:load_run:
  414|  4.32k|{
  415|       |    // The arg->client object might die and with it args->log, so duplicate it.
  416|  4.32k|    args->log = mp_log_new(args, args->log, NULL);
  417|       |
  418|  4.32k|    int fds[2];
  419|  4.32k|    if (!mp_ipc_start_anon_client(args->mpctx->ipc_ctx, args->client, fds))
  ------------------
  |  Branch (419:9): [True: 0, False: 4.32k]
  ------------------
  420|      0|        return -1;
  421|  4.32k|    args->client = NULL; // ownership lost
  422|       |
  423|  4.32k|    char *fdopt = fds[1] >= 0 ? mp_tprintf(80, "--mpv-ipc-fd=%d:%d", fds[0], fds[1])
  ------------------
  |  |  165|      0|    mp_tprintf_buf((char[SIZE]){0}, (SIZE), (format), __VA_ARGS__)
  ------------------
  |  Branch (423:19): [True: 0, False: 4.32k]
  ------------------
  424|  4.32k|                              : mp_tprintf(80, "--mpv-ipc-fd=%d", fds[0]);
  ------------------
  |  |  165|  4.32k|    mp_tprintf_buf((char[SIZE]){0}, (SIZE), (format), __VA_ARGS__)
  ------------------
  425|       |
  426|  4.32k|    struct mp_subprocess_opts opts = {
  427|  4.32k|        .exe = (char *)args->filename,
  428|  4.32k|        .args = (char *[]){(char *)args->filename, fdopt, NULL},
  429|  4.32k|        .fds = {
  430|       |            // Keep terminal stuff
  431|  4.32k|            {.fd = 0, .src_fd = 0,},
  432|  4.32k|            {.fd = 1, .src_fd = 1,},
  433|  4.32k|            {.fd = 2, .src_fd = 2,},
  434|       |            // Just hope these don't step over each other (e.g. fds[1] could be
  435|       |            // below 4, if the std FDs are missing).
  436|  4.32k|            {.fd = fds[0], .src_fd = fds[0], },
  437|  4.32k|            {.fd = fds[1], .src_fd = fds[1], },
  438|  4.32k|        },
  439|  4.32k|        .num_fds = fds[1] >= 0 ? 5 : 4,
  ------------------
  |  Branch (439:20): [True: 0, False: 4.32k]
  ------------------
  440|  4.32k|        .detach = true,
  441|  4.32k|    };
  442|  4.32k|    struct mp_subprocess_result res;
  443|  4.32k|    mp_subprocess(args->log, &opts, &res);
  444|       |
  445|       |    // Closing these will (probably) make the client exit, if it really died.
  446|  4.32k|    close(fds[0]);
  447|  4.32k|    if (fds[1] >= 0)
  ------------------
  |  Branch (447:9): [True: 0, False: 4.32k]
  ------------------
  448|      0|        close(fds[1]);
  449|       |
  450|  4.32k|    return res.error;
  451|  4.32k|}

redraw_subs:
   57|  12.1k|{
   58|  36.4k|    for (int n = 0; n < num_ptracks[STREAM_SUB]; n++) {
  ------------------
  |  Branch (58:21): [True: 24.2k, False: 12.1k]
  ------------------
   59|  24.2k|        if (mpctx->current_track[n][STREAM_SUB] &&
  ------------------
  |  Branch (59:13): [True: 0, False: 24.2k]
  ------------------
   60|  24.2k|            mpctx->current_track[n][STREAM_SUB]->d_sub)
  ------------------
  |  Branch (60:13): [True: 0, False: 0]
  ------------------
   61|      0|        {
   62|      0|            mpctx->current_track[n][STREAM_SUB]->redraw_subs = true;
   63|      0|        }
   64|  24.2k|    }
   65|  12.1k|}
reset_subtitle_state:
   68|  3.93k|{
   69|  3.93k|    for (int n = 0; n < mpctx->num_tracks; n++)
  ------------------
  |  Branch (69:21): [True: 0, False: 3.93k]
  ------------------
   70|      0|        reset_subtitles(mpctx, mpctx->tracks[n]);
   71|  3.93k|    term_osd_clear_subs(mpctx);
   72|  3.93k|}
uninit_sub_all:
   90|  3.93k|{
   91|  3.93k|    for (int n = 0; n < mpctx->num_tracks; n++)
  ------------------
  |  Branch (91:21): [True: 0, False: 3.93k]
  ------------------
   92|      0|        uninit_sub(mpctx, mpctx->tracks[n]);
   93|  3.93k|}

reset_video_state:
   99|  3.93k|{
  100|  3.93k|    if (mpctx->vo_chain) {
  ------------------
  |  Branch (100:9): [True: 0, False: 3.93k]
  ------------------
  101|      0|        vo_chain_reset_state(mpctx->vo_chain);
  102|      0|        struct track *t = mpctx->vo_chain->track;
  103|      0|        if (t && t->dec)
  ------------------
  |  Branch (103:13): [True: 0, False: 0]
  |  Branch (103:18): [True: 0, False: 0]
  ------------------
  104|      0|            mp_decoder_wrapper_set_play_dir(t->dec, mpctx->play_dir);
  105|      0|    }
  106|       |
  107|  3.93k|    for (int n = 0; n < mpctx->num_next_frames; n++)
  ------------------
  |  Branch (107:21): [True: 0, False: 3.93k]
  ------------------
  108|      0|        mp_image_unrefp(&mpctx->next_frames[n]);
  109|  3.93k|    mpctx->num_next_frames = 0;
  110|  3.93k|    mp_image_unrefp(&mpctx->saved_frame);
  111|       |
  112|  3.93k|    mpctx->delay = 0;
  113|  3.93k|    mpctx->time_frame = 0;
  114|  3.93k|    mpctx->video_pts = MP_NOPTS_VALUE;
  ------------------
  |  |   38|  3.93k|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  115|  3.93k|    mpctx->last_frame_duration = 0;
  116|  3.93k|    mpctx->num_past_frames = 0;
  117|  3.93k|    mpctx->total_avsync_change = 0;
  118|  3.93k|    mpctx->last_av_difference = 0;
  119|  3.93k|    mpctx->mistimed_frames_total = 0;
  120|  3.93k|    mpctx->drop_message_shown = 0;
  121|  3.93k|    mpctx->display_sync_drift_dir = 0;
  122|  3.93k|    mpctx->display_sync_error = 0;
  123|  3.93k|    mpctx->display_sync_active = 0;
  124|       |
  125|  3.93k|    mpctx->video_status = mpctx->vo_chain ? STATUS_SYNCING : STATUS_EOF;
  ------------------
  |  Branch (125:27): [True: 0, False: 3.93k]
  ------------------
  126|  3.93k|}
uninit_video_out:
  129|  17.1k|{
  130|  17.1k|    uninit_video_chain(mpctx);
  131|  17.1k|    if (mpctx->video_out) {
  ------------------
  |  Branch (131:9): [True: 39, False: 17.0k]
  ------------------
  132|     39|        vo_destroy(mpctx->video_out);
  133|     39|        mpctx->video_out = NULL;
  134|     39|        mp_notify(mpctx, MPV_EVENT_VIDEO_RECONFIG, NULL);
  135|     39|    }
  136|  17.1k|}
uninit_video_chain:
  159|  21.0k|{
  160|  21.0k|    if (mpctx->vo_chain) {
  ------------------
  |  Branch (160:9): [True: 0, False: 21.0k]
  ------------------
  161|      0|        reset_video_state(mpctx);
  162|      0|        vo_chain_uninit(mpctx->vo_chain);
  163|      0|        mpctx->vo_chain = NULL;
  164|       |
  165|      0|        mpctx->video_status = STATUS_EOF;
  166|       |
  167|      0|        mp_notify(mpctx, MPV_EVENT_VIDEO_RECONFIG, NULL);
  168|      0|    }
  169|  21.0k|}

cookies_lavf:
  119|      1|{
  120|      1|    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|      1|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|      1|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  121|      1|    struct cookie_list_type *list = NULL;
  122|      1|    if (file && file[0])
  ------------------
  |  Branch (122:9): [True: 0, False: 1]
  |  Branch (122:17): [True: 0, False: 0]
  ------------------
  123|      0|        list = load_cookies_from(tmp, global, log, file);
  124|       |
  125|      1|    char *res = talloc_strdup(talloc_ctx, "");
  ------------------
  |  |   50|      1|#define talloc_strdup                   ta_xstrdup
  ------------------
  126|       |
  127|      1|    while (list) {
  ------------------
  |  Branch (127:12): [True: 0, False: 1]
  ------------------
  128|      0|        res = talloc_asprintf_append_buffer(res,
  ------------------
  |  |   64|      0|#define talloc_asprintf_append_buffer   ta_talloc_asprintf_append_buffer
  ------------------
  129|      0|                    "%s=%s; path=%s; domain=%s; %s\n", list->name, list->value,
  130|      0|                    list->path, list->domain, list->secure ? "secure" : "");
  ------------------
  |  Branch (130:47): [True: 0, False: 0]
  ------------------
  131|      0|        list = list->next;
  132|      0|    }
  133|       |
  134|      1|    talloc_free(tmp);
  ------------------
  |  |   47|      1|#define talloc_free                     ta_free
  ------------------
  135|      1|    return res;
  136|      1|}

mp_url_unescape_inplace:
  140|    896|{
  141|  9.44k|    for (int len = strlen(url), i = 0, o = 0; i <= len;) {
  ------------------
  |  Branch (141:47): [True: 8.54k, False: 896]
  ------------------
  142|  8.54k|        if ((url[i] != '%') || (i > len - 3)) {  // %NN can't start after len-3
  ------------------
  |  Branch (142:13): [True: 6.43k, False: 2.11k]
  |  Branch (142:32): [True: 205, False: 1.91k]
  ------------------
  143|  6.63k|            url[o++] = url[i++];
  144|  6.63k|            continue;
  145|  6.63k|        }
  146|       |
  147|  1.91k|        int msd = hex2dec(url[i + 1]),
  148|  1.91k|            lsd = hex2dec(url[i + 2]);
  149|       |
  150|  1.91k|        if (msd >= 0 && lsd >= 0) {
  ------------------
  |  Branch (150:13): [True: 1.01k, False: 893]
  |  Branch (150:25): [True: 663, False: 354]
  ------------------
  151|    663|            url[o++] = 16 * msd + lsd;
  152|    663|            i += 3;
  153|  1.24k|        } else {
  154|  1.24k|            url[o++] = url[i++];
  155|  1.24k|            url[o++] = url[i++];
  156|  1.24k|            url[o++] = url[i++];
  157|  1.24k|        }
  158|  1.91k|    }
  159|    896|}
mp_url_escape:
  184|     41|{
  185|     41|    char *rv = talloc_size(talloc_ctx, strlen(url) * 3 + 1);
  ------------------
  |  |   43|     41|#define talloc_size                     ta_xalloc_size
  |  |  ------------------
  |  |  |  |  120|     41|#define ta_xalloc_size(...)             ta_oom_p(ta_alloc_size(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  153|     41|#define ta_alloc_size(...)      ta_dbg_set_loc(ta_alloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|     41|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|     41|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|     41|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  186|     41|    char *out = rv;
  187|     41|    bool negate = ok && ok[0] == '~';
  ------------------
  |  Branch (187:19): [True: 41, False: 0]
  |  Branch (187:25): [True: 0, False: 41]
  ------------------
  188|       |
  189|  4.43k|    for (char c; (c = *url); url++) {
  ------------------
  |  Branch (189:18): [True: 4.39k, False: 41]
  ------------------
  190|  4.39k|        bool as_is = negate ? !strchr(ok + 1, c)
  ------------------
  |  Branch (190:22): [True: 0, False: 4.39k]
  ------------------
  191|  4.39k|                            : (strchr(url_default_ok, c) || (ok && strchr(ok, c)));
  ------------------
  |  Branch (191:32): [True: 2.68k, False: 1.71k]
  |  Branch (191:62): [True: 1.71k, False: 0]
  |  Branch (191:68): [True: 246, False: 1.46k]
  ------------------
  192|  4.39k|        if (as_is) {
  ------------------
  |  Branch (192:13): [True: 2.92k, False: 1.46k]
  ------------------
  193|  2.92k|            *out++ = c;
  194|  2.92k|        } else {
  195|  1.46k|            unsigned char v = c;
  196|  1.46k|            *out++ = '%';
  197|  1.46k|            *out++ = hex_digits[v / 16];
  198|  1.46k|            *out++ = hex_digits[v % 16];
  199|  1.46k|        }
  200|  4.39k|    }
  201|       |
  202|     41|    *out = 0;
  203|     41|    return rv;
  204|     41|}
stream_create_with_args:
  429|  4.05k|{
  430|  4.05k|    mp_assert(args->url);
  ------------------
  |  |   41|  4.05k|#define mp_assert assert
  ------------------
  431|       |
  432|  4.05k|    int r = STREAM_NO_MATCH;
  ------------------
  |  |   65|  4.05k|#define STREAM_NO_MATCH -2
  ------------------
  433|  4.05k|    *ret = NULL;
  434|       |
  435|       |    // Open stream proper
  436|  4.05k|    if (args->sinfo) {
  ------------------
  |  Branch (436:9): [True: 461, False: 3.59k]
  ------------------
  437|    461|        r = stream_create_instance(args->sinfo, args, ret);
  438|  3.59k|    } else {
  439|  35.0k|        for (int i = 0; i < MP_ARRAY_SIZE(stream_list); i++) {
  ------------------
  |  |   48|  35.0k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (439:25): [True: 35.0k, False: 48]
  ------------------
  440|  35.0k|            r = stream_create_instance(stream_list[i], args, ret);
  441|  35.0k|            if (r == STREAM_OK)
  ------------------
  |  |   68|  35.0k|#define STREAM_OK    1
  ------------------
  |  Branch (441:17): [True: 1.57k, False: 33.4k]
  ------------------
  442|  1.57k|                break;
  443|  33.4k|            if (r == STREAM_NO_MATCH || r == STREAM_UNSUPPORTED)
  ------------------
  |  |   65|  66.8k|#define STREAM_NO_MATCH -2
  ------------------
                          if (r == STREAM_NO_MATCH || r == STREAM_UNSUPPORTED)
  ------------------
  |  |   66|  4.07k|#define STREAM_UNSUPPORTED -1
  ------------------
  |  Branch (443:17): [True: 29.3k, False: 4.07k]
  |  Branch (443:41): [True: 1.97k, False: 2.10k]
  ------------------
  444|  31.3k|                continue;
  445|  2.10k|            if (r == STREAM_UNSAFE)
  ------------------
  |  |   64|  2.10k|#define STREAM_UNSAFE -3
  ------------------
  |  Branch (445:17): [True: 129, False: 1.97k]
  ------------------
  446|    129|                continue;
  447|  1.97k|            break;
  448|  2.10k|        }
  449|  3.59k|    }
  450|       |
  451|  4.05k|    if (!*ret && !(args->flags & STREAM_SILENT) && !mp_cancel_test(args->cancel))
  ------------------
  |  |   44|  2.02k|#define STREAM_SILENT             (1 << 1)
  ------------------
  |  Branch (451:9): [True: 2.02k, False: 2.03k]
  |  Branch (451:18): [True: 2.02k, False: 0]
  |  Branch (451:52): [True: 1.99k, False: 27]
  ------------------
  452|  1.99k|    {
  453|  1.99k|        struct mp_log *log = mp_log_new(NULL, args->global->log, "!stream");
  454|       |
  455|  1.99k|        if (r == STREAM_UNSAFE) {
  ------------------
  |  |   64|  1.99k|#define STREAM_UNSAFE -3
  ------------------
  |  Branch (455:13): [True: 1, False: 1.99k]
  ------------------
  456|      1|            mp_err(log, "\nRefusing to load potentially unsafe URL from a playlist.\n"
  ------------------
  |  |   72|      1|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  457|      1|                   "Use the --load-unsafe-playlists option to load it anyway.\n\n");
  458|  1.99k|        } else if (r == STREAM_NO_MATCH || r == STREAM_UNSUPPORTED) {
  ------------------
  |  |   65|  3.99k|#define STREAM_NO_MATCH -2
  ------------------
                      } else if (r == STREAM_NO_MATCH || r == STREAM_UNSUPPORTED) {
  ------------------
  |  |   66|  1.94k|#define STREAM_UNSUPPORTED -1
  ------------------
  |  Branch (458:20): [True: 46, False: 1.94k]
  |  Branch (458:44): [True: 0, False: 1.94k]
  ------------------
  459|     46|            mp_err(log, "No protocol handler found to open URL %s\n", args->url);
  ------------------
  |  |   72|     46|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  460|     46|            mp_err(log, "The protocol is either unsupported, or was disabled "
  ------------------
  |  |   72|     46|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  461|     46|                        "at compile-time.\n");
  462|  1.94k|        } else {
  463|  1.94k|            mp_err(log, "Failed to open %s.\n", args->url);
  ------------------
  |  |   72|  1.94k|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  464|  1.94k|        }
  465|       |
  466|  1.99k|        talloc_free(log);
  ------------------
  |  |   47|  1.99k|#define talloc_free                     ta_free
  ------------------
  467|  1.99k|    }
  468|       |
  469|  4.05k|    return r;
  470|  4.05k|}
stream_create:
  474|  3.59k|{
  475|  3.59k|    struct stream_open_args args = {
  476|  3.59k|        .global = global,
  477|  3.59k|        .cancel = c,
  478|  3.59k|        .flags = flags,
  479|  3.59k|        .url = url,
  480|  3.59k|    };
  481|  3.59k|    struct stream *s;
  482|  3.59k|    stream_create_with_args(&args, &s);
  483|  3.59k|    return s;
  484|  3.59k|}
stream_read_partial:
  596|  2.29k|{
  597|  2.29k|    mp_assert(s->buf_cur <= s->buf_end);
  ------------------
  |  |   41|  2.29k|#define mp_assert assert
  ------------------
  598|  2.29k|    mp_assert(buf_size >= 0);
  ------------------
  |  |   41|  2.29k|#define mp_assert assert
  ------------------
  599|  2.29k|    if (s->buf_cur == s->buf_end && buf_size > 0) {
  ------------------
  |  Branch (599:9): [True: 2.15k, False: 138]
  |  Branch (599:37): [True: 2.15k, False: 0]
  ------------------
  600|  2.15k|        if (buf_size > (s->buffer_mask + 1) / 2) {
  ------------------
  |  Branch (600:13): [True: 59, False: 2.09k]
  ------------------
  601|       |            // Direct read if the buffer is too small anyway.
  602|     59|            stream_drop_buffers(s);
  603|     59|            return stream_read_unbuffered(s, buf, buf_size);
  604|     59|        }
  605|  2.09k|        stream_read_more(s, 1);
  606|  2.09k|    }
  607|  2.23k|    int res = ring_copy(s, buf, buf_size, s->buf_cur);
  608|  2.23k|    s->buf_cur += res;
  609|  2.23k|    return res;
  610|  2.29k|}
stream_read_char_fallback:
  614|     32|{
  615|     32|    uint8_t c;
  616|     32|    return stream_read_partial(s, &c, 1) ? c : STREAM_EOF;
  ------------------
  |  |   71|     32|#define STREAM_EOF (-256)
  ------------------
  |  Branch (616:12): [True: 0, False: 32]
  ------------------
  617|     32|}
stream_read:
  620|    995|{
  621|    995|    int len = total;
  622|  1.80k|    while (len > 0) {
  ------------------
  |  Branch (622:12): [True: 1.79k, False: 10]
  ------------------
  623|  1.79k|        int read = stream_read_partial(s, mem, len);
  624|  1.79k|        if (read <= 0)
  ------------------
  |  Branch (624:13): [True: 985, False: 813]
  ------------------
  625|    985|            break; // EOF
  626|    813|        mem = (char *)mem + read;
  627|    813|        len -= read;
  628|    813|    }
  629|    995|    total -= len;
  630|    995|    return total;
  631|    995|}
stream_peek:
  636|  2.68k|{
  637|  3.35k|    while (stream_read_more(s, forward_size)) {}
  ------------------
  |  Branch (637:12): [True: 678, False: 2.68k]
  ------------------
  638|  2.68k|    return s->buf_end - s->buf_cur;
  639|  2.68k|}
stream_read_peek:
  644|  2.68k|{
  645|  2.68k|    stream_peek(s, buf_size);
  646|  2.68k|    return ring_copy(s, buf, buf_size, s->buf_cur);
  647|  2.68k|}
stream_drop_buffers:
  688|     59|{
  689|     59|    s->pos = stream_tell(s);
  690|     59|    s->buf_start = s->buf_cur = s->buf_end = 0;
  691|     59|    s->eof = 0;
  692|     59|    stream_resize_buffer(s, 0, 0);
  693|     59|}
stream_seek:
  725|  4.62k|{
  726|  4.62k|    MP_TRACE(s, "seek request from %" PRId64 " to %" PRId64 "\n",
  ------------------
  |  |   90|  4.62k|#define MP_TRACE(obj, ...)      MP_MSG(obj, MSGL_TRACE, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  4.62k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  727|  4.62k|             stream_tell(s), pos);
  728|       |
  729|  4.62k|    s->eof = 0; // eof should be set only on read; seeking always clears it
  730|       |
  731|  4.62k|    if (pos < 0) {
  ------------------
  |  Branch (731:9): [True: 0, False: 4.62k]
  ------------------
  732|      0|        MP_ERR(s, "Invalid seek to negative position %lld!\n", (long long)pos);
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  733|      0|        pos = 0;
  734|      0|    }
  735|       |
  736|  4.62k|    if (pos <= s->pos) {
  ------------------
  |  Branch (736:9): [True: 4.10k, False: 528]
  ------------------
  737|  4.10k|        int64_t x = pos - (s->pos - (int)s->buf_end);
  738|  4.10k|        if (x >= (int)s->buf_start) {
  ------------------
  |  Branch (738:13): [True: 4.10k, False: 0]
  ------------------
  739|  4.10k|            s->buf_cur = x;
  740|  4.10k|            mp_assert(s->buf_cur >= s->buf_start);
  ------------------
  |  |   41|  4.10k|#define mp_assert assert
  ------------------
  741|  4.10k|            mp_assert(s->buf_cur <= s->buf_end);
  ------------------
  |  |   41|  4.10k|#define mp_assert assert
  ------------------
  742|  4.10k|            return true;
  743|  4.10k|        }
  744|  4.10k|    }
  745|       |
  746|    528|    if (s->mode == STREAM_WRITE)
  ------------------
  |  |   42|    528|#define STREAM_WRITE              (1 << 0)
  ------------------
  |  Branch (746:9): [True: 0, False: 528]
  ------------------
  747|      0|        return s->seekable && s->seek(s, pos);
  ------------------
  |  Branch (747:16): [True: 0, False: 0]
  |  Branch (747:31): [True: 0, False: 0]
  ------------------
  748|       |
  749|       |    // Skip data instead of performing a seek in some cases.
  750|    528|    if (pos >= s->pos &&
  ------------------
  |  Branch (750:9): [True: 528, False: 0]
  ------------------
  751|    528|        ((!s->seekable && s->fast_skip) ||
  ------------------
  |  Branch (751:11): [True: 0, False: 528]
  |  Branch (751:27): [True: 0, False: 0]
  ------------------
  752|    528|         pos - s->pos <= s->requested_buffer_size))
  ------------------
  |  Branch (752:10): [True: 0, False: 528]
  ------------------
  753|      0|    {
  754|      0|        return stream_skip_read(s, pos - stream_tell(s));
  755|      0|    }
  756|       |
  757|    528|    return stream_seek_unbuffered(s, pos);
  758|    528|}
stream_seek_skip:
  763|    345|{
  764|    345|    uint64_t cur_pos = stream_tell(s);
  765|       |
  766|    345|    if (cur_pos == pos)
  ------------------
  |  Branch (766:9): [True: 168, False: 177]
  ------------------
  767|    168|        return true;
  768|       |
  769|    177|    return !s->seekable && pos > cur_pos
  ------------------
  |  Branch (769:12): [True: 0, False: 177]
  |  Branch (769:28): [True: 0, False: 0]
  ------------------
  770|    177|        ? stream_skip_read(s, pos - cur_pos)
  771|    177|        : stream_seek(s, pos);
  772|    345|}
stream_control:
  775|    319|{
  776|    319|    return s->control ? s->control(s, cmd, arg) : STREAM_UNSUPPORTED;
  ------------------
  |  |   66|    159|#define STREAM_UNSUPPORTED -1
  ------------------
  |  Branch (776:12): [True: 160, False: 159]
  ------------------
  777|    319|}
stream_get_size:
  781|  2.10k|{
  782|  2.10k|    return s->get_size ? s->get_size(s) : -1;
  ------------------
  |  Branch (782:12): [True: 1.97k, False: 139]
  ------------------
  783|  2.10k|}
free_stream:
  786|  6.63k|{
  787|  6.63k|    if (!s)
  ------------------
  |  Branch (787:9): [True: 4.60k, False: 2.03k]
  ------------------
  788|  4.60k|        return;
  789|       |
  790|  2.03k|    if (s->close)
  ------------------
  |  Branch (790:9): [True: 590, False: 1.44k]
  ------------------
  791|    590|        s->close(s);
  792|  2.03k|    talloc_free(s);
  ------------------
  |  |   47|  2.03k|#define talloc_free                     ta_free
  ------------------
  793|  2.03k|}
stream_skip_bom:
  799|    437|{
  800|    437|    char buf[4];
  801|    437|    int len = stream_read_peek(s, buf, sizeof(buf));
  802|    437|    bstr data = {buf, len};
  803|  1.72k|    for (int n = 0; n < 3; n++) {
  ------------------
  |  Branch (803:21): [True: 1.30k, False: 424]
  ------------------
  804|  1.30k|        if (bstr_startswith0(data, bom[n])) {
  ------------------
  |  Branch (804:13): [True: 13, False: 1.29k]
  ------------------
  805|     13|            stream_seek_skip(s, stream_tell(s) + strlen(bom[n]));
  806|     13|            return n;
  807|     13|        }
  808|  1.30k|    }
  809|    424|    return -1; // default to 8 bit codepages
  810|    437|}
stream_read_complete:
  825|    990|{
  826|    990|    if (max_size < 0 || max_size > STREAM_MAX_READ_SIZE)
  ------------------
  |  |   36|    990|#define STREAM_MAX_READ_SIZE (INT_MAX - 1)
  ------------------
  |  Branch (826:9): [True: 0, False: 990]
  |  Branch (826:25): [True: 0, False: 990]
  ------------------
  827|      0|        abort();
  828|    990|    if (s->is_directory)
  ------------------
  |  Branch (828:9): [True: 0, False: 990]
  ------------------
  829|      0|        return (struct bstr){NULL, 0};
  830|       |
  831|    990|    int bufsize;
  832|    990|    int total_read = 0;
  833|    990|    int padding = 1;
  834|    990|    char *buf = NULL;
  835|    990|    int64_t size = stream_get_size(s) - stream_tell(s);
  836|    990|    if (size > max_size && !s->allow_partial_read)
  ------------------
  |  Branch (836:9): [True: 5, False: 985]
  |  Branch (836:28): [True: 5, False: 0]
  ------------------
  837|      5|        return (struct bstr){NULL, 0};
  838|    985|    if (size > 0)
  ------------------
  |  Branch (838:9): [True: 844, False: 141]
  ------------------
  839|    844|        bufsize = size + padding;
  840|    141|    else
  841|    141|        bufsize = 1000;
  842|    985|    if (s->allow_partial_read)
  ------------------
  |  Branch (842:9): [True: 0, False: 985]
  ------------------
  843|      0|        bufsize = MPMIN(bufsize, max_size + padding);
  ------------------
  |  |   44|      0|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  844|    995|    while (1) {
  ------------------
  |  Branch (844:12): [Folded - Ignored]
  ------------------
  845|    995|        buf = talloc_realloc_size(talloc_ctx, buf, bufsize);
  ------------------
  |  |   39|    995|#define talloc_realloc_size             ta_xrealloc_size
  |  |  ------------------
  |  |  |  |  158|    995|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|    995|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|    995|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|    995|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  846|    995|        int readsize = stream_read(s, buf + total_read, bufsize - total_read);
  847|    995|        total_read += readsize;
  848|    995|        if (total_read >= max_size && s->allow_partial_read) {
  ------------------
  |  Branch (848:13): [True: 0, False: 995]
  |  Branch (848:39): [True: 0, False: 0]
  ------------------
  849|      0|            total_read = max_size;
  850|      0|            break;
  851|      0|        }
  852|    995|        if (total_read < bufsize)
  ------------------
  |  Branch (852:13): [True: 985, False: 10]
  ------------------
  853|    985|            break;
  854|     10|        if (bufsize > max_size) {
  ------------------
  |  Branch (854:13): [True: 0, False: 10]
  ------------------
  855|      0|            talloc_free(buf);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  856|      0|            return (struct bstr){NULL, 0};
  857|      0|        }
  858|     10|        bufsize = MPMIN(bufsize + (bufsize >> 1), max_size + padding);
  ------------------
  |  |   44|     10|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 10]
  |  |  ------------------
  ------------------
  859|     10|    }
  860|    985|    buf = talloc_realloc_size(talloc_ctx, buf, total_read + padding);
  ------------------
  |  |   39|    985|#define talloc_realloc_size             ta_xrealloc_size
  |  |  ------------------
  |  |  |  |  158|    985|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|    985|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|    985|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|    985|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  861|    985|    memset(&buf[total_read], 0, padding);
  862|    985|    return (struct bstr){buf, total_read};
  863|    985|}
stream_read_file2:
  874|  2.94k|{
  875|  2.94k|    struct bstr res = {0};
  876|  2.94k|    stream_t *s = stream_create(filename, flags, NULL, global);
  877|  2.94k|    if (s) {
  ------------------
  |  Branch (877:9): [True: 962, False: 1.97k]
  ------------------
  878|    962|        if (s->is_directory)
  ------------------
  |  Branch (878:13): [True: 0, False: 962]
  ------------------
  879|      0|            mp_err(s->log, "Failed to open %s (not a file).\n", filename);
  ------------------
  |  |   72|      0|#define mp_err(log, ...)        mp_msg(log, MSGL_ERR, __VA_ARGS__)
  ------------------
  880|    962|        else
  881|    962|            res = stream_read_complete(s, talloc_ctx, max_size);
  882|    962|    }
  883|  2.94k|    free_stream(s);
  884|  2.94k|    return res;
  885|  2.94k|}
stream_get_proto_list:
  888|  2.18k|{
  889|  2.18k|    char **list = NULL;
  890|  2.18k|    int num = 0;
  891|  30.5k|    for (int i = 0; i < MP_ARRAY_SIZE(stream_list); i++) {
  ------------------
  |  |   48|  30.5k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (891:21): [True: 28.3k, False: 2.18k]
  ------------------
  892|  28.3k|        const stream_info_t *stream_info = stream_list[i];
  893|  28.3k|        if (safe_only && (stream_info->stream_origin & STREAM_ORIGIN_UNSAFE))
  ------------------
  |  |   50|      0|#define STREAM_ORIGIN_UNSAFE      (4 << 2) // from a grotesque source
  ------------------
  |  Branch (893:13): [True: 0, False: 28.3k]
  |  Branch (893:26): [True: 0, False: 0]
  ------------------
  894|      0|            continue;
  895|       |
  896|  28.3k|        char **get_protocols = stream_info->get_protocols ? stream_info->get_protocols() : NULL;
  ------------------
  |  Branch (896:32): [True: 4.36k, False: 24.0k]
  ------------------
  897|  28.3k|        char **protocols = get_protocols ? get_protocols : (char **)stream_info->protocols;
  ------------------
  |  Branch (897:28): [True: 4.36k, False: 24.0k]
  ------------------
  898|       |
  899|  89.5k|        for (int j = 0; protocols && protocols[j]; j++) {
  ------------------
  |  Branch (899:25): [True: 87.3k, False: 2.18k]
  |  Branch (899:38): [True: 61.1k, False: 26.2k]
  ------------------
  900|  61.1k|            if (*protocols[j] == '\0')
  ------------------
  |  Branch (900:17): [True: 2.18k, False: 58.9k]
  ------------------
  901|  2.18k|                continue;
  902|       |
  903|  58.9k|            MP_TARRAY_APPEND(NULL, list, num, talloc_strdup(list, protocols[j]));
  ------------------
  |  |  105|  58.9k|    do {                                            \
  |  |  106|  58.9k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  58.9k|    do {                                            \
  |  |  |  |   97|  58.9k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  58.9k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  58.9k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  58.9k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 8.73k, False: 50.2k]
  |  |  |  |  ------------------
  |  |  |  |   99|  58.9k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  8.73k|    do {                                                        \
  |  |  |  |  |  |   89|  8.73k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  8.73k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  8.73k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  8.73k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  8.73k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  8.73k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  8.73k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  58.9k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  58.9k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  58.9k|        (idxvar)++;                                 \
  |  |  109|  58.9k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  904|  58.9k|        }
  905|       |
  906|  28.3k|        talloc_free(get_protocols);
  ------------------
  |  |   47|  28.3k|#define talloc_free                     ta_free
  ------------------
  907|  28.3k|    }
  908|  2.18k|    MP_TARRAY_APPEND(NULL, list, num, NULL);
  ------------------
  |  |  105|  2.18k|    do {                                            \
  |  |  106|  2.18k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  2.18k|    do {                                            \
  |  |  |  |   97|  2.18k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  2.18k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  2.18k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  2.18k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 2.18k]
  |  |  |  |  ------------------
  |  |  |  |   99|  2.18k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  2.18k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  2.18k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  2.18k|        (idxvar)++;                                 \
  |  |  109|  2.18k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  909|  2.18k|    return list;
  910|  2.18k|}
stream_print_proto_list:
  913|  2.16k|{
  914|  2.16k|    int count = 0;
  915|       |
  916|  2.16k|    mp_info(log, "Protocols:\n\n");
  ------------------
  |  |   74|  2.16k|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  917|  2.16k|    char **list = stream_get_proto_list(false);
  918|  60.5k|    for (int i = 0; list[i]; i++) {
  ------------------
  |  Branch (918:21): [True: 58.4k, False: 2.16k]
  ------------------
  919|  58.4k|        mp_info(log, " %s://\n", list[i]);
  ------------------
  |  |   74|  58.4k|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  920|  58.4k|        count++;
  921|  58.4k|    }
  922|  2.16k|    talloc_free(list);
  ------------------
  |  |   47|  2.16k|#define talloc_free                     ta_free
  ------------------
  923|  2.16k|    mp_info(log, "\nTotal: %d protocols\n", count);
  ------------------
  |  |   74|  2.16k|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  924|  2.16k|}
stream.c:hex2dec:
  128|  3.82k|{
  129|  3.82k|    if (c >= '0' && c <= '9')
  ------------------
  |  Branch (129:9): [True: 2.70k, False: 1.11k]
  |  Branch (129:21): [True: 654, False: 2.05k]
  ------------------
  130|    654|        return c - '0';
  131|  3.16k|    if (c >= 'A' && c <= 'F')
  ------------------
  |  Branch (131:9): [True: 2.04k, False: 1.12k]
  |  Branch (131:21): [True: 685, False: 1.36k]
  ------------------
  132|    685|        return 10 + c - 'A';
  133|  2.48k|    if (c >= 'a' && c <= 'f')
  ------------------
  |  Branch (133:9): [True: 1.33k, False: 1.14k]
  |  Branch (133:21): [True: 756, False: 581]
  ------------------
  134|    756|        return 10 + c - 'a';
  135|  1.72k|    return -1;
  136|  2.48k|}
stream.c:stream_create_instance:
  325|  35.4k|{
  326|  35.4k|    const char *url = args->url;
  327|  35.4k|    int flags = args->flags;
  328|       |
  329|  35.4k|    *ret = NULL;
  330|       |
  331|  35.4k|    const char *path = url;
  332|       |
  333|  35.4k|    if (flags & STREAM_LOCAL_FS_ONLY) {
  ------------------
  |  |   54|  35.4k|#define STREAM_LOCAL_FS_ONLY      (1 << 5) // stream_file only, no URLs
  ------------------
  |  Branch (333:9): [True: 0, False: 35.4k]
  ------------------
  334|      0|        if (!sinfo->local_fs)
  ------------------
  |  Branch (334:13): [True: 0, False: 0]
  ------------------
  335|      0|            return STREAM_NO_MATCH;
  ------------------
  |  |   65|      0|#define STREAM_NO_MATCH -2
  ------------------
  336|  35.4k|    } else {
  337|  35.4k|        char **get_protocols = sinfo->get_protocols ? sinfo->get_protocols() : NULL;
  ------------------
  |  Branch (337:32): [True: 3.74k, False: 31.7k]
  ------------------
  338|  35.4k|        char **protocols = get_protocols ? get_protocols : (char **)sinfo->protocols;
  ------------------
  |  Branch (338:28): [True: 3.74k, False: 31.7k]
  ------------------
  339|       |
  340|  86.7k|        for (int n = 0; protocols && protocols[n]; n++) {
  ------------------
  |  Branch (340:25): [True: 84.6k, False: 2.09k]
  |  Branch (340:38): [True: 55.3k, False: 29.3k]
  ------------------
  341|  55.3k|            path = match_proto(url, protocols[n]);
  342|  55.3k|            if (path)
  ------------------
  |  Branch (342:17): [True: 4.01k, False: 51.2k]
  ------------------
  343|  4.01k|                break;
  344|  55.3k|        }
  345|       |
  346|  35.4k|        talloc_free(get_protocols);
  ------------------
  |  |   47|  35.4k|#define talloc_free                     ta_free
  ------------------
  347|       |
  348|  35.4k|        if (!path)
  ------------------
  |  Branch (348:13): [True: 29.3k, False: 6.10k]
  ------------------
  349|  29.3k|            return STREAM_NO_MATCH;
  ------------------
  |  |   65|  29.3k|#define STREAM_NO_MATCH -2
  ------------------
  350|  35.4k|    }
  351|       |
  352|  6.10k|    stream_t *s = talloc_zero(NULL, stream_t);
  ------------------
  |  |   27|  6.10k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  6.10k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  6.10k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  353|  6.10k|    s->global = args->global;
  354|  6.10k|    struct stream_opts *opts = mp_get_config_group(s, s->global, &stream_conf);
  355|  6.10k|    if (flags & STREAM_SILENT) {
  ------------------
  |  |   44|  6.10k|#define STREAM_SILENT             (1 << 1)
  ------------------
  |  Branch (355:9): [True: 461, False: 5.64k]
  ------------------
  356|    461|        s->log = mp_null_log;
  357|  5.64k|    } else {
  358|  5.64k|        s->log = mp_log_new(s, s->global->log, sinfo->name);
  359|  5.64k|    }
  360|  6.10k|    s->info = sinfo;
  361|  6.10k|    s->cancel = args->cancel;
  362|  6.10k|    s->url = talloc_strdup(s, url);
  ------------------
  |  |   50|  6.10k|#define talloc_strdup                   ta_xstrdup
  ------------------
  363|  6.10k|    s->path = talloc_strdup(s, path);
  ------------------
  |  |   50|  6.10k|#define talloc_strdup                   ta_xstrdup
  ------------------
  364|  6.10k|    s->mode = flags & (STREAM_READ | STREAM_WRITE);
  ------------------
  |  |   41|  6.10k|#define STREAM_READ               0
  ------------------
                  s->mode = flags & (STREAM_READ | STREAM_WRITE);
  ------------------
  |  |   42|  6.10k|#define STREAM_WRITE              (1 << 0)
  ------------------
  365|  6.10k|    s->requested_buffer_size = opts->buffer_size;
  366|  6.10k|    s->allow_partial_read = flags & STREAM_ALLOW_PARTIAL_READ;
  ------------------
  |  |   56|  6.10k|#define STREAM_ALLOW_PARTIAL_READ (1 << 7) // allows partial read with stream_read_file()
  ------------------
  367|       |
  368|  6.10k|    if (flags & STREAM_LESS_NOISE)
  ------------------
  |  |   55|  6.10k|#define STREAM_LESS_NOISE         (1 << 6) // try to log errors only
  ------------------
  |  Branch (368:9): [True: 0, False: 6.10k]
  ------------------
  369|      0|        mp_msg_set_max_level(s->log, MSGL_WARN);
  370|       |
  371|  6.10k|    struct demux_opts *demux_opts = mp_get_config_group(s, s->global, &demux_conf);
  372|  6.10k|    s->access_references = demux_opts->access_references;
  373|  6.10k|    talloc_free(demux_opts);
  ------------------
  |  |   47|  6.10k|#define talloc_free                     ta_free
  ------------------
  374|       |
  375|  6.10k|    MP_VERBOSE(s, "Opening %s\n", url);
  ------------------
  |  |   88|  6.10k|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  6.10k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  376|       |
  377|  6.10k|    if (strlen(url) > INT_MAX / 8) {
  ------------------
  |  Branch (377:9): [True: 0, False: 6.10k]
  ------------------
  378|      0|        MP_ERR(s, "URL too large.\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  379|      0|        talloc_free(s);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  380|      0|        return STREAM_ERROR;
  ------------------
  |  |   67|      0|#define STREAM_ERROR 0
  ------------------
  381|      0|    }
  382|       |
  383|  6.10k|    if ((s->mode & STREAM_WRITE) && !sinfo->can_write) {
  ------------------
  |  |   42|  6.10k|#define STREAM_WRITE              (1 << 0)
  ------------------
  |  Branch (383:9): [True: 0, False: 6.10k]
  |  Branch (383:37): [True: 0, False: 0]
  ------------------
  384|      0|        MP_DBG(s, "No write access implemented.\n");
  ------------------
  |  |   89|      0|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  385|      0|        talloc_free(s);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  386|      0|        return STREAM_NO_MATCH;
  ------------------
  |  |   65|      0|#define STREAM_NO_MATCH -2
  ------------------
  387|      0|    }
  388|       |
  389|  6.10k|    s->stream_origin = flags & STREAM_ORIGIN_MASK; // pass through by default
  ------------------
  |  |   52|  6.10k|#define STREAM_ORIGIN_MASK        (7 << 2) // for extracting origin value from flags
  ------------------
  390|  6.10k|    if (opts->load_unsafe_playlists) {
  ------------------
  |  Branch (390:9): [True: 0, False: 6.10k]
  ------------------
  391|      0|        s->stream_origin = STREAM_ORIGIN_DIRECT;
  ------------------
  |  |   47|      0|#define STREAM_ORIGIN_DIRECT      (1 << 2) // passed from cmdline or loadfile
  ------------------
  392|  6.10k|    } else if (sinfo->stream_origin) {
  ------------------
  |  Branch (392:16): [True: 4.85k, False: 1.24k]
  ------------------
  393|  4.85k|        s->stream_origin = check_origin(s->stream_origin, sinfo->stream_origin);
  394|  4.85k|    }
  395|       |
  396|  6.10k|    if (!s->stream_origin) {
  ------------------
  |  Branch (396:9): [True: 129, False: 5.97k]
  ------------------
  397|    129|        talloc_free(s);
  ------------------
  |  |   47|    129|#define talloc_free                     ta_free
  ------------------
  398|    129|        return STREAM_UNSAFE;
  ------------------
  |  |   64|    129|#define STREAM_UNSAFE -3
  ------------------
  399|    129|    }
  400|       |
  401|  5.97k|    int r = STREAM_UNSUPPORTED;
  ------------------
  |  |   66|  5.97k|#define STREAM_UNSUPPORTED -1
  ------------------
  402|  5.97k|    if (sinfo->open2) {
  ------------------
  |  Branch (402:9): [True: 1.72k, False: 4.25k]
  ------------------
  403|  1.72k|        r = sinfo->open2(s, args);
  404|  4.25k|    } else if (!args->special_arg) {
  ------------------
  |  Branch (404:16): [True: 4.25k, False: 0]
  ------------------
  405|  4.25k|        r = (sinfo->open)(s);
  406|  4.25k|    }
  407|  5.97k|    if (r != STREAM_OK) {
  ------------------
  |  |   68|  5.97k|#define STREAM_OK    1
  ------------------
  |  Branch (407:9): [True: 3.94k, False: 2.03k]
  ------------------
  408|  3.94k|        talloc_free(s);
  ------------------
  |  |   47|  3.94k|#define talloc_free                     ta_free
  ------------------
  409|  3.94k|        return r;
  410|  3.94k|    }
  411|       |
  412|  2.03k|    if (!stream_resize_buffer(s, 0, 0)) {
  ------------------
  |  Branch (412:9): [True: 0, False: 2.03k]
  ------------------
  413|      0|        free_stream(s);
  414|      0|        return STREAM_ERROR;
  ------------------
  |  |   67|      0|#define STREAM_ERROR 0
  ------------------
  415|      0|    }
  416|       |
  417|  2.03k|    mp_assert(s->seekable == !!s->seek);
  ------------------
  |  |   41|  2.03k|#define mp_assert assert
  ------------------
  418|       |
  419|  2.03k|    if (s->mime_type)
  ------------------
  |  Branch (419:9): [True: 0, False: 2.03k]
  ------------------
  420|  2.03k|        MP_VERBOSE(s, "Mime-type: '%s'\n", s->mime_type);
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  421|       |
  422|  2.03k|    MP_DBG(s, "Stream opened successfully.\n");
  ------------------
  |  |   89|  2.03k|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  2.03k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  423|       |
  424|  2.03k|    *ret = s;
  425|  2.03k|    return STREAM_OK;
  ------------------
  |  |   68|  2.03k|#define STREAM_OK    1
  ------------------
  426|  2.03k|}
stream.c:match_proto:
  207|  55.3k|{
  208|  55.3k|    int l = strlen(proto);
  209|  55.3k|    if (l > 0) {
  ------------------
  |  Branch (209:9): [True: 52.7k, False: 2.57k]
  ------------------
  210|  52.7k|        if (strncasecmp(url, proto, l) == 0 && strncmp("://", url + l, 3) == 0)
  ------------------
  |  Branch (210:13): [True: 3.67k, False: 49.0k]
  |  Branch (210:48): [True: 3.60k, False: 78]
  ------------------
  211|  3.60k|            return url + l + 3;
  212|  52.7k|    } else if (!mp_is_url(bstr0(url))) {
  ------------------
  |  Branch (212:16): [True: 410, False: 2.16k]
  ------------------
  213|    410|        return url; // pure filenames
  214|    410|    }
  215|  51.2k|    return NULL;
  216|  55.3k|}
stream.c:check_origin:
  222|  4.85k|{
  223|  4.85k|    switch (src) {
  ------------------
  |  Branch (223:13): [True: 0, False: 4.85k]
  ------------------
  224|  4.50k|    case STREAM_ORIGIN_DIRECT:
  ------------------
  |  |   47|  4.50k|#define STREAM_ORIGIN_DIRECT      (1 << 2) // passed from cmdline or loadfile
  ------------------
  |  Branch (224:5): [True: 4.50k, False: 357]
  ------------------
  225|  4.50k|    case STREAM_ORIGIN_UNSAFE:
  ------------------
  |  |   50|  4.50k|#define STREAM_ORIGIN_UNSAFE      (4 << 2) // from a grotesque source
  ------------------
  |  Branch (225:5): [True: 0, False: 4.85k]
  ------------------
  226|       |        // Allow anything, but constrain it to the new origin.
  227|  4.50k|        return new;
  228|    357|    case STREAM_ORIGIN_FS:
  ------------------
  |  |   48|    357|#define STREAM_ORIGIN_FS          (2 << 2) // referenced from playlist on unix FS
  ------------------
  |  Branch (228:5): [True: 357, False: 4.50k]
  ------------------
  229|       |        // From unix FS, allow all but unsafe.
  230|    357|        if (new == STREAM_ORIGIN_FS || new == STREAM_ORIGIN_NET)
  ------------------
  |  |   48|    714|#define STREAM_ORIGIN_FS          (2 << 2) // referenced from playlist on unix FS
  ------------------
                      if (new == STREAM_ORIGIN_FS || new == STREAM_ORIGIN_NET)
  ------------------
  |  |   49|    337|#define STREAM_ORIGIN_NET         (3 << 2) // referenced from playlist on network
  ------------------
  |  Branch (230:13): [True: 20, False: 337]
  |  Branch (230:40): [True: 208, False: 129]
  ------------------
  231|    228|            return new;
  232|    129|        break;
  233|    129|    case STREAM_ORIGIN_NET:
  ------------------
  |  |   49|      0|#define STREAM_ORIGIN_NET         (3 << 2) // referenced from playlist on network
  ------------------
  |  Branch (233:5): [True: 0, False: 4.85k]
  ------------------
  234|       |        // Allow only other network links.
  235|      0|        if (new == STREAM_ORIGIN_NET)
  ------------------
  |  |   49|      0|#define STREAM_ORIGIN_NET         (3 << 2) // referenced from playlist on network
  ------------------
  |  Branch (235:13): [True: 0, False: 0]
  ------------------
  236|      0|            return new;
  237|      0|        break;
  238|  4.85k|    }
  239|    129|    return 0;
  240|  4.85k|}
stream.c:stream_read_unbuffered:
  502|  4.55k|{
  503|  4.55k|    mp_assert(len >= 0);
  ------------------
  |  |   41|  4.55k|#define mp_assert assert
  ------------------
  504|  4.55k|    if (len <= 0)
  ------------------
  |  Branch (504:9): [True: 0, False: 4.55k]
  ------------------
  505|      0|        return 0;
  506|       |
  507|  4.55k|    int res = 0;
  508|       |    // we will retry even if we already reached EOF previously.
  509|  4.55k|    if (s->fill_buffer && !mp_cancel_test(s->cancel))
  ------------------
  |  Branch (509:9): [True: 4.53k, False: 14]
  |  Branch (509:27): [True: 4.03k, False: 502]
  ------------------
  510|  4.03k|        res = s->fill_buffer(s, buf, len);
  511|  4.55k|    if (res <= 0) {
  ------------------
  |  Branch (511:9): [True: 3.06k, False: 1.48k]
  ------------------
  512|  3.06k|        s->eof = 1;
  513|  3.06k|        return 0;
  514|  3.06k|    }
  515|  1.48k|    mp_assert(res <= len);
  ------------------
  |  |   41|  1.48k|#define mp_assert assert
  ------------------
  516|       |    // When reading succeeded we are obviously not at eof.
  517|  1.48k|    s->eof = 0;
  518|  1.48k|    s->pos += res;
  519|  1.48k|    s->total_unbuffered_read_bytes += res;
  520|  1.48k|    return res;
  521|  1.48k|}
stream.c:stream_read_more:
  528|  5.45k|{
  529|  5.45k|    mp_assert(forward >= 0);
  ------------------
  |  |   41|  5.45k|#define mp_assert assert
  ------------------
  530|       |
  531|  5.45k|    int forward_avail = s->buf_end - s->buf_cur;
  532|  5.45k|    if (forward_avail >= forward)
  ------------------
  |  Branch (532:9): [True: 963, False: 4.49k]
  ------------------
  533|    963|        return false;
  534|       |
  535|       |    // Avoid that many small reads will lead to many low-level read calls.
  536|  4.49k|    forward = MPMAX(forward, s->requested_buffer_size / 2);
  ------------------
  |  |   43|  4.49k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 4.49k]
  |  |  ------------------
  ------------------
  537|  4.49k|    mp_assert(forward_avail < forward);
  ------------------
  |  |   41|  4.49k|#define mp_assert assert
  ------------------
  538|       |
  539|       |    // Keep guaranteed seek-back.
  540|  4.49k|    int buf_old = MPMIN(s->buf_cur - s->buf_start, s->requested_buffer_size / 2);
  ------------------
  |  |   44|  4.49k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 4.49k]
  |  |  ------------------
  ------------------
  541|       |
  542|  4.49k|    if (!stream_resize_buffer(s, buf_old + forward_avail, buf_old + forward))
  ------------------
  |  Branch (542:9): [True: 0, False: 4.49k]
  ------------------
  543|      0|        return false;
  544|       |
  545|  4.49k|    int buf_alloc = s->buffer_mask + 1;
  546|       |
  547|  4.49k|    mp_assert(s->buf_start <= s->buf_cur);
  ------------------
  |  |   41|  4.49k|#define mp_assert assert
  ------------------
  548|  4.49k|    mp_assert(s->buf_cur <= s->buf_end);
  ------------------
  |  |   41|  4.49k|#define mp_assert assert
  ------------------
  549|  4.49k|    mp_assert(s->buf_cur < buf_alloc * 2);
  ------------------
  |  |   41|  4.49k|#define mp_assert assert
  ------------------
  550|  4.49k|    mp_assert(s->buf_end < buf_alloc * 2);
  ------------------
  |  |   41|  4.49k|#define mp_assert assert
  ------------------
  551|  4.49k|    mp_assert(s->buf_start < buf_alloc);
  ------------------
  |  |   41|  4.49k|#define mp_assert assert
  ------------------
  552|       |
  553|       |    // Note: read as much as possible, even if forward is much smaller. Do
  554|       |    // this because the stream buffer is supposed to set an approx. minimum
  555|       |    // read size on it.
  556|  4.49k|    int read = buf_alloc - (buf_old + forward_avail); // free buffer past end
  557|       |
  558|  4.49k|    int pos = s->buf_end & s->buffer_mask;
  559|  4.49k|    read = MPMIN(read, buf_alloc - pos);
  ------------------
  |  |   44|  4.49k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 4.49k]
  |  |  ------------------
  ------------------
  560|       |
  561|       |    // Note: if wrap-around happens, we need to make two calls. This may
  562|       |    // affect latency (e.g. waiting for new data on a socket), so do only
  563|       |    // 1 read call always.
  564|  4.49k|    read = stream_read_unbuffered(s, &s->buffer[pos], read);
  565|       |
  566|  4.49k|    s->buf_end += read;
  567|       |
  568|       |    // May have overwritten old data.
  569|  4.49k|    if (s->buf_end - s->buf_start >= buf_alloc) {
  ------------------
  |  Branch (569:9): [True: 0, False: 4.49k]
  ------------------
  570|      0|        mp_assert(s->buf_end >= buf_alloc);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  571|       |
  572|      0|        s->buf_start = s->buf_end - buf_alloc;
  573|       |
  574|      0|        mp_assert(s->buf_start <= s->buf_cur);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  575|      0|        mp_assert(s->buf_cur <= s->buf_end);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  576|       |
  577|      0|        if (s->buf_start >= buf_alloc) {
  ------------------
  |  Branch (577:13): [True: 0, False: 0]
  ------------------
  578|      0|            s->buf_start -= buf_alloc;
  579|      0|            s->buf_cur -= buf_alloc;
  580|      0|            s->buf_end -= buf_alloc;
  581|      0|        }
  582|      0|    }
  583|       |
  584|       |    // Must not have overwritten guaranteed old data.
  585|  4.49k|    mp_assert(s->buf_cur - s->buf_start >= buf_old);
  ------------------
  |  |   41|  4.49k|#define mp_assert assert
  ------------------
  586|       |
  587|  4.49k|    if (s->buf_cur < s->buf_end)
  ------------------
  |  Branch (587:9): [True: 2.73k, False: 1.75k]
  ------------------
  588|  2.73k|        s->eof = 0;
  589|       |
  590|  4.49k|    return !!read;
  591|  4.49k|}
stream.c:ring_copy:
  248|  4.91k|{
  249|  4.91k|    mp_assert(len >= 0);
  ------------------
  |  |   41|  4.91k|#define mp_assert assert
  ------------------
  250|       |
  251|  4.91k|    if (pos < s->buf_start || pos > s->buf_end)
  ------------------
  |  Branch (251:9): [True: 0, False: 4.91k]
  |  Branch (251:31): [True: 0, False: 4.91k]
  ------------------
  252|      0|        return 0;
  253|       |
  254|  4.91k|    int copied = 0;
  255|  4.91k|    len = MPMIN(len, s->buf_end - pos);
  ------------------
  |  |   44|  4.91k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 3.94k, False: 973]
  |  |  ------------------
  ------------------
  256|       |
  257|  4.91k|    if (len && pos <= s->buffer_mask) {
  ------------------
  |  Branch (257:9): [True: 3.15k, False: 1.75k]
  |  Branch (257:16): [True: 3.15k, False: 0]
  ------------------
  258|  3.15k|        int copy = MPMIN(len, s->buffer_mask + 1 - pos);
  ------------------
  |  |   44|  3.15k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 3.15k]
  |  |  ------------------
  ------------------
  259|  3.15k|        memcpy(dst, &s->buffer[pos], copy);
  260|  3.15k|        copied += copy;
  261|  3.15k|        len -= copy;
  262|  3.15k|        pos += copy;
  263|  3.15k|    }
  264|       |
  265|  4.91k|    if (len) {
  ------------------
  |  Branch (265:9): [True: 0, False: 4.91k]
  ------------------
  266|      0|        memcpy((char *)dst + copied, &s->buffer[pos & s->buffer_mask], len);
  267|      0|        copied += len;
  268|      0|    }
  269|       |
  270|  4.91k|    return copied;
  271|  4.91k|}
stream.c:stream_resize_buffer:
  281|  6.58k|{
  282|  6.58k|    mp_assert(keep >= s->buf_end - s->buf_cur);
  ------------------
  |  |   41|  6.58k|#define mp_assert assert
  ------------------
  283|  6.58k|    mp_assert(keep <= new);
  ------------------
  |  |   41|  6.58k|#define mp_assert assert
  ------------------
  284|       |
  285|  6.58k|    new = MPMAX(new, s->requested_buffer_size);
  ------------------
  |  |   43|  6.58k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 6.58k]
  |  |  ------------------
  ------------------
  286|  6.58k|    new = MPMIN(new, STREAM_MAX_BUFFER_SIZE);
  ------------------
  |  |   44|  6.58k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 6.58k]
  |  |  ------------------
  ------------------
  287|  6.58k|    new = mp_round_next_power_of_2(new);
  288|       |
  289|  6.58k|    mp_assert(keep <= new); // can't fail (if old buffer size was valid)
  ------------------
  |  |   41|  6.58k|#define mp_assert assert
  ------------------
  290|       |
  291|  6.58k|    if (new == s->buffer_mask + 1)
  ------------------
  |  Branch (291:9): [True: 4.55k, False: 2.03k]
  ------------------
  292|  4.55k|        return true;
  293|       |
  294|  2.03k|    int old_pos = s->buf_cur - s->buf_start;
  295|  2.03k|    int old_used_len = s->buf_end - s->buf_start;
  296|  2.03k|    int skip = old_used_len > new ? old_used_len - new : 0;
  ------------------
  |  Branch (296:16): [True: 0, False: 2.03k]
  ------------------
  297|       |
  298|  2.03k|    MP_DBG(s, "resize stream to %d bytes, drop %d bytes\n", new, skip);
  ------------------
  |  |   89|  2.03k|#define MP_DBG(obj, ...)        MP_MSG(obj, MSGL_DEBUG, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|  2.03k|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  299|       |
  300|  2.03k|    void *nbuf = ta_alloc_size(s, new);
  ------------------
  |  |  153|  2.03k|#define ta_alloc_size(...)      ta_dbg_set_loc(ta_alloc_size(__VA_ARGS__), TA_LOC)
  |  |  ------------------
  |  |  |  |   43|  2.03k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  ------------------
  |  |  |  |  |  |   38|  2.03k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   37|  2.03k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  301|  2.03k|    if (!nbuf)
  ------------------
  |  Branch (301:9): [True: 0, False: 2.03k]
  ------------------
  302|      0|        return false; // oom; tolerate it, caller needs to check if required
  303|       |
  304|  2.03k|    int new_len = 0;
  305|  2.03k|    if (s->buffer)
  ------------------
  |  Branch (305:9): [True: 0, False: 2.03k]
  ------------------
  306|      0|        new_len = ring_copy(s, nbuf, new, s->buf_start + skip);
  307|  2.03k|    mp_assert(new_len == old_used_len - skip);
  ------------------
  |  |   41|  2.03k|#define mp_assert assert
  ------------------
  308|  2.03k|    mp_assert(old_pos >= skip); // "keep" too low
  ------------------
  |  |   41|  2.03k|#define mp_assert assert
  ------------------
  309|  2.03k|    mp_assert(old_pos - skip <= new_len);
  ------------------
  |  |   41|  2.03k|#define mp_assert assert
  ------------------
  310|  2.03k|    s->buf_start = 0;
  311|  2.03k|    s->buf_cur = old_pos - skip;
  312|  2.03k|    s->buf_end = new_len;
  313|       |
  314|  2.03k|    ta_free(s->buffer);
  315|       |
  316|  2.03k|    s->buffer = nbuf;
  317|  2.03k|    s->buffer_mask = new - 1;
  318|       |
  319|  2.03k|    return true;
  320|  2.03k|}
stream.c:stream_seek_unbuffered:
  697|    528|{
  698|    528|    if (newpos != s->pos) {
  ------------------
  |  Branch (698:9): [True: 528, False: 0]
  ------------------
  699|    528|        MP_VERBOSE(s, "stream level seek from %" PRId64 " to %" PRId64 "\n",
  ------------------
  |  |   88|    528|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    528|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  700|    528|                   s->pos, newpos);
  701|       |
  702|    528|        s->total_stream_seeks++;
  703|       |
  704|    528|        if (newpos > s->pos && !s->seekable) {
  ------------------
  |  Branch (704:13): [True: 528, False: 0]
  |  Branch (704:32): [True: 0, False: 528]
  ------------------
  705|      0|            MP_ERR(s, "Cannot seek forward in this stream\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  706|      0|            return false;
  707|      0|        }
  708|    528|        if (newpos < s->pos && !s->seekable) {
  ------------------
  |  Branch (708:13): [True: 0, False: 528]
  |  Branch (708:32): [True: 0, False: 0]
  ------------------
  709|      0|            MP_ERR(s, "Cannot seek backward in linear streams!\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  710|      0|            return false;
  711|      0|        }
  712|    528|        if (s->seek(s, newpos) <= 0) {
  ------------------
  |  Branch (712:13): [True: 528, False: 0]
  ------------------
  713|    528|            int level = mp_cancel_test(s->cancel) ? MSGL_V : MSGL_ERR;
  ------------------
  |  Branch (713:25): [True: 528, False: 0]
  ------------------
  714|    528|            MP_MSG(s, level, "Seek failed (to %lld, size %lld)\n",
  ------------------
  |  |   82|    528|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  ------------------
  715|    528|                   (long long)newpos, (long long)stream_get_size(s));
  716|    528|            return false;
  717|    528|        }
  718|      0|        stream_drop_buffers(s);
  719|      0|        s->pos = newpos;
  720|      0|    }
  721|      0|    return true;
  722|    528|}

demux_lavf.c:stream_tell:
  222|  1.07k|{
  223|  1.07k|    return s->pos + s->buf_cur - s->buf_end;
  224|  1.07k|}
demux_playlist.c:stream_read_char:
  213|  2.36k|{
  214|  2.36k|    return s->buf_cur < s->buf_end
  ------------------
  |  Branch (214:12): [True: 2.33k, False: 32]
  ------------------
  215|  2.36k|        ? s->buffer[(s->buf_cur++) & s->buffer_mask]
  216|  2.36k|        : stream_read_char_fallback(s);
  217|  2.36k|}
demux_playlist.c:stream_tell:
  222|    765|{
  223|    765|    return s->pos + s->buf_cur - s->buf_end;
  224|    765|}
ebml.c:stream_read_char:
  213|    594|{
  214|    594|    return s->buf_cur < s->buf_end
  ------------------
  |  Branch (214:12): [True: 594, False: 0]
  ------------------
  215|    594|        ? s->buffer[(s->buf_cur++) & s->buffer_mask]
  216|    594|        : stream_read_char_fallback(s);
  217|    594|}
stream.c:stream_tell:
  222|  6.03k|{
  223|  6.03k|    return s->pos + s->buf_cur - s->buf_end;
  224|  6.03k|}

stream_avdevice.c:open_f:
   21|      3|{
   22|      3|    stream->demuxer = "lavf";
   23|       |
   24|      3|    return STREAM_OK;
  ------------------
  |  |   68|      3|#define STREAM_OK    1
  ------------------
   25|      3|}

stream_cb.c:open_cb:
   55|  1.97k|{
   56|  1.97k|    struct priv *p = talloc_ptrtype(stream, p);
  ------------------
  |  |   34|  1.97k|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|  1.97k|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  1.97k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   57|  1.97k|    stream->priv = p;
   58|       |
   59|  1.97k|    bstr bproto = mp_split_proto(bstr0(stream->url), NULL);
   60|  1.97k|    char *proto = bstrto0(stream, bproto);
   61|       |
   62|  1.97k|    void *user_data;
   63|  1.97k|    mpv_stream_cb_open_ro_fn open_fn;
   64|       |
   65|  1.97k|    if (!mp_streamcb_lookup(stream->global, proto, &user_data, &open_fn))
  ------------------
  |  Branch (65:9): [True: 1.97k, False: 0]
  ------------------
   66|  1.97k|        return STREAM_UNSUPPORTED;
  ------------------
  |  |   66|  1.97k|#define STREAM_UNSUPPORTED -1
  ------------------
   67|       |
   68|      0|    mpv_stream_cb_info info = {0};
   69|       |
   70|      0|    int r = open_fn(user_data, stream->url, &info);
   71|      0|    if (r < 0) {
  ------------------
  |  Branch (71:9): [True: 0, False: 0]
  ------------------
   72|      0|        if (r != MPV_ERROR_LOADING_FAILED)
  ------------------
  |  Branch (72:13): [True: 0, False: 0]
  ------------------
   73|      0|            MP_WARN(stream, "unknown error from user callback\n");
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
   74|      0|        return STREAM_ERROR;
  ------------------
  |  |   67|      0|#define STREAM_ERROR 0
  ------------------
   75|      0|    }
   76|       |
   77|      0|    if (!info.read_fn || !info.close_fn) {
  ------------------
  |  Branch (77:9): [True: 0, False: 0]
  |  Branch (77:26): [True: 0, False: 0]
  ------------------
   78|      0|        MP_FATAL(stream, "required read_fn or close_fn callbacks not set.\n");
  ------------------
  |  |   84|      0|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
   79|      0|        return STREAM_ERROR;
  ------------------
  |  |   67|      0|#define STREAM_ERROR 0
  ------------------
   80|      0|    }
   81|       |
   82|      0|    p->info = info;
   83|       |
   84|      0|    if (p->info.seek_fn && p->info.seek_fn(p->info.cookie, 0) >= 0) {
  ------------------
  |  Branch (84:9): [True: 0, False: 0]
  |  Branch (84:28): [True: 0, False: 0]
  ------------------
   85|      0|        stream->seek = seek;
   86|      0|        stream->seekable = true;
   87|      0|    }
   88|      0|    stream->fast_skip = true;
   89|      0|    stream->fill_buffer = fill_buffer;
   90|      0|    stream->get_size = get_size;
   91|      0|    stream->close = s_close;
   92|       |
   93|      0|    if (p->info.cancel_fn && stream->cancel) {
  ------------------
  |  Branch (93:9): [True: 0, False: 0]
  |  Branch (93:30): [True: 0, False: 0]
  ------------------
   94|      0|        p->cancel = mp_cancel_new(p);
   95|      0|        mp_cancel_set_parent(p->cancel, stream->cancel);
   96|      0|        mp_cancel_set_cb(p->cancel, p->info.cancel_fn, p->info.cookie);
   97|      0|    }
   98|       |
   99|      0|    return STREAM_OK;
  ------------------
  |  |   68|      0|#define STREAM_OK    1
  ------------------
  100|      0|}

dvb_get_state:
 1044|      1|{
 1045|      1|    dvb_priv_t *priv = stream->priv;
 1046|      1|    if (global_dvb_state)
  ------------------
  |  Branch (1046:9): [True: 0, False: 1]
  ------------------
 1047|      0|        return global_dvb_state;
 1048|       |
 1049|      1|    struct mp_log *log = stream->log;
 1050|      1|    struct mpv_global *global = stream->global;
 1051|       |
 1052|      1|    dvb_state_t *state = talloc_zero(NULL, dvb_state_t);
  ------------------
  |  |   27|      1|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|      1|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      1|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1053|      1|    state->switching_channel = false;
 1054|      1|    state->is_on = false;
 1055|      1|    state->stream_used = true;
 1056|      1|    state->fe_fd = state->dvr_fd = -1;
 1057|       |
 1058|     17|    for (unsigned int i = 0; i < MAX_ADAPTERS; i++) {
  ------------------
  |  |   27|     17|#define MAX_ADAPTERS 16
  ------------------
  |  Branch (1058:30): [True: 16, False: 1]
  ------------------
 1059|     16|        dvb_channels_list_t *list = NULL;
 1060|     16|        unsigned int delsys_mask[MAX_FRONTENDS];
 1061|    144|        for (unsigned int f = 0; f < MAX_FRONTENDS; f++) {
  ------------------
  |  |   28|    144|#define MAX_FRONTENDS 8
  ------------------
  |  Branch (1061:34): [True: 128, False: 16]
  ------------------
 1062|    128|            char filename[100];
 1063|    128|            snprintf(filename, sizeof(filename), "/dev/dvb/adapter%u/frontend%u", i, f);
 1064|    128|            int fd = open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
 1065|    128|            if (fd < 0)
  ------------------
  |  Branch (1065:17): [True: 128, False: 0]
  ------------------
 1066|    128|                continue;
 1067|       |
 1068|      0|            delsys_mask[f] = dvb_get_tuner_delsys_mask(fd, log);
 1069|      0|            delsys_mask[f] &= DELSYS_SUPP_MASK; /* Filter unsupported delivery systems. */
  ------------------
  |  |  126|      0|    (                                                                   \
  |  |  127|      0|        DELSYS_BIT(SYS_DVBC_ANNEX_A) |                                  \
  |  |  ------------------
  |  |  |  |  116|      0|#define DELSYS_BIT(__bit)        (((unsigned int)1) << (__bit))
  |  |  ------------------
  |  |  128|      0|        DELSYS_BIT(SYS_DVBT) |                                          \
  |  |  ------------------
  |  |  |  |  116|      0|#define DELSYS_BIT(__bit)        (((unsigned int)1) << (__bit))
  |  |  ------------------
  |  |  129|      0|        DELSYS_BIT(SYS_DVBS) |                                          \
  |  |  ------------------
  |  |  |  |  116|      0|#define DELSYS_BIT(__bit)        (((unsigned int)1) << (__bit))
  |  |  ------------------
  |  |  130|      0|        DELSYS_BIT(SYS_DVBS2) |                                         \
  |  |  ------------------
  |  |  |  |  116|      0|#define DELSYS_BIT(__bit)        (((unsigned int)1) << (__bit))
  |  |  ------------------
  |  |  131|      0|        DELSYS_BIT(SYS_ATSC) |                                          \
  |  |  ------------------
  |  |  |  |  116|      0|#define DELSYS_BIT(__bit)        (((unsigned int)1) << (__bit))
  |  |  ------------------
  |  |  132|      0|        DELSYS_BIT(SYS_DVBC_ANNEX_B) |                                  \
  |  |  ------------------
  |  |  |  |  116|      0|#define DELSYS_BIT(__bit)        (((unsigned int)1) << (__bit))
  |  |  ------------------
  |  |  133|      0|        DELSYS_BIT(SYS_DVBT2) |                                         \
  |  |  ------------------
  |  |  |  |  116|      0|#define DELSYS_BIT(__bit)        (((unsigned int)1) << (__bit))
  |  |  ------------------
  |  |  134|      0|        DELSYS_BIT(SYS_ISDBT) |                                         \
  |  |  ------------------
  |  |  |  |  116|      0|#define DELSYS_BIT(__bit)        (((unsigned int)1) << (__bit))
  |  |  ------------------
  |  |  135|      0|        DELSYS_BIT(SYS_DVBC_ANNEX_C)                                    \
  |  |  ------------------
  |  |  |  |  116|      0|#define DELSYS_BIT(__bit)        (((unsigned int)1) << (__bit))
  |  |  ------------------
  |  |  136|      0|    )
  ------------------
 1070|      0|            close(fd);
 1071|      0|            if (delsys_mask[f] == 0) {
  ------------------
  |  Branch (1071:17): [True: 0, False: 0]
  ------------------
 1072|      0|                mp_verbose(log, "Frontend device %s has no supported delivery systems.\n",
  ------------------
  |  |   75|      0|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
 1073|      0|                       filename);
 1074|      0|                continue; /* Skip tuner. */
 1075|      0|            }
 1076|       |
 1077|       |            /* Create channel list for adapter. */
 1078|      0|            for (unsigned int delsys = 0; delsys < SYS_DVB__COUNT__; delsys++) {
  ------------------
  |  |  113|      0|#define SYS_DVB__COUNT__            (SYS_DVBC_ANNEX_C + 1)
  ------------------
  |  Branch (1078:43): [True: 0, False: 0]
  ------------------
 1079|      0|                if (!DELSYS_IS_SET(delsys_mask[f], delsys))
  ------------------
  |  |  122|      0|    (0 != ((__mask) & DELSYS_BIT((__bit))))
  |  |  ------------------
  |  |  |  |  116|      0|#define DELSYS_BIT(__bit)        (((unsigned int)1) << (__bit))
  |  |  ------------------
  ------------------
  |  Branch (1079:21): [True: 0, False: 0]
  ------------------
 1080|      0|                    continue; /* Skip unsupported. */
 1081|       |
 1082|      0|                mp_verbose(log, "Searching channel list for delivery system %s\n", get_dvb_delsys(delsys));
  ------------------
  |  |   75|      0|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
 1083|      0|                const char *conf_file_name;
 1084|      0|                switch (delsys) {
 1085|      0|                case SYS_DVBC_ANNEX_A:
  ------------------
  |  Branch (1085:17): [True: 0, False: 0]
  ------------------
 1086|      0|                case SYS_DVBC_ANNEX_C:
  ------------------
  |  Branch (1086:17): [True: 0, False: 0]
  ------------------
 1087|      0|                    conf_file_name = "channels.conf.cbl";
 1088|      0|                    break;
 1089|      0|                case SYS_ATSC:
  ------------------
  |  Branch (1089:17): [True: 0, False: 0]
  ------------------
 1090|      0|                    conf_file_name = "channels.conf.atsc";
 1091|      0|                    break;
 1092|      0|                case SYS_DVBT:
  ------------------
  |  Branch (1092:17): [True: 0, False: 0]
  ------------------
 1093|      0|                    if (DELSYS_IS_SET(delsys_mask[f], SYS_DVBT2))
  ------------------
  |  |  122|      0|    (0 != ((__mask) & DELSYS_BIT((__bit))))
  |  |  ------------------
  |  |  |  |  116|      0|#define DELSYS_BIT(__bit)        (((unsigned int)1) << (__bit))
  |  |  ------------------
  |  |  |  Branch (122:5): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1094|      0|                        continue; /* Add all channels later with T2. */
 1095|      0|                    conf_file_name = "channels.conf.ter";
 1096|      0|                    break;
 1097|      0|                case SYS_DVBT2:
  ------------------
  |  Branch (1097:17): [True: 0, False: 0]
  ------------------
 1098|      0|                    conf_file_name = "channels.conf.ter";
 1099|      0|                    break;
 1100|      0|                case SYS_ISDBT:
  ------------------
  |  Branch (1100:17): [True: 0, False: 0]
  ------------------
 1101|      0|                    conf_file_name = "channels.conf.isdbt";
 1102|      0|                    break;
 1103|      0|                case SYS_DVBS:
  ------------------
  |  Branch (1103:17): [True: 0, False: 0]
  ------------------
 1104|      0|                    if (DELSYS_IS_SET(delsys_mask[f], SYS_DVBS2))
  ------------------
  |  |  122|      0|    (0 != ((__mask) & DELSYS_BIT((__bit))))
  |  |  ------------------
  |  |  |  |  116|      0|#define DELSYS_BIT(__bit)        (((unsigned int)1) << (__bit))
  |  |  ------------------
  |  |  |  Branch (122:5): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1105|      0|                        continue; /* Add all channels later with S2. */
 1106|      0|                    conf_file_name = "channels.conf.sat";
 1107|      0|                    break;
 1108|      0|                case SYS_DVBS2:
  ------------------
  |  Branch (1108:17): [True: 0, False: 0]
  ------------------
 1109|      0|                    conf_file_name = "channels.conf.sat";
 1110|      0|                    break;
 1111|      0|                default:
  ------------------
  |  Branch (1111:17): [True: 0, False: 0]
  ------------------
 1112|      0|                    continue;
 1113|      0|                }
 1114|       |
 1115|      0|                void *talloc_ctx = talloc_new(NULL);
  ------------------
  |  |   40|      0|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|      0|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
 1116|      0|                char *conf_file;
 1117|      0|                if (priv->opts->cfg_file && priv->opts->cfg_file[0]) {
  ------------------
  |  Branch (1117:21): [True: 0, False: 0]
  |  Branch (1117:45): [True: 0, False: 0]
  ------------------
 1118|      0|                    conf_file = mp_get_user_path(talloc_ctx, global, priv->opts->cfg_file);
 1119|      0|                } else {
 1120|      0|                    conf_file = mp_find_config_file(talloc_ctx, global, conf_file_name);
 1121|      0|                    if (conf_file) {
  ------------------
  |  Branch (1121:25): [True: 0, False: 0]
  ------------------
 1122|      0|                        mp_verbose(log, "Ignoring other channels.conf files.\n");
  ------------------
  |  |   75|      0|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
 1123|      0|                    } else {
 1124|      0|                        conf_file = mp_find_config_file(talloc_ctx, global,
 1125|      0|                                        "channels.conf");
 1126|      0|                    }
 1127|      0|                }
 1128|       |
 1129|      0|                list = dvb_get_channels(log, list, priv->opts->cfg_full_transponder,
 1130|      0|                                        conf_file, f, delsys, delsys_mask[f]);
 1131|      0|                talloc_free(talloc_ctx);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 1132|      0|            }
 1133|      0|        }
 1134|       |        /* Add adapter with non zero channel list. */
 1135|     16|        if (!list)
  ------------------
  |  Branch (1135:13): [True: 16, False: 0]
  ------------------
 1136|     16|            continue;
 1137|       |
 1138|      0|        dvb_adapter_config_t tmp = {
 1139|      0|            .devno = i,
 1140|      0|            .list = talloc_steal(state, list),
  ------------------
  |  |   38|      0|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 1141|      0|        };
 1142|      0|        memcpy(&tmp.delsys_mask, delsys_mask, sizeof(delsys_mask));
 1143|       |
 1144|      0|        MP_TARRAY_APPEND(state, state->adapters, state->adapters_count, tmp);
  ------------------
  |  |  105|      0|    do {                                            \
  |  |  106|      0|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      0|    do {                                            \
  |  |  |  |   97|      0|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      0|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      0|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      0|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      0|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      0|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      0|        (idxvar)++;                                 \
  |  |  109|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1145|       |
 1146|      0|        mp_verbose(log, "Added adapter with channels to state list, now %d.\n",
  ------------------
  |  |   75|      0|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
 1147|      0|                   state->adapters_count);
 1148|      0|    }
 1149|       |
 1150|      1|    if (state->adapters_count == 0)
  ------------------
  |  Branch (1150:9): [True: 1, False: 0]
  ------------------
 1151|      1|        TA_FREEP(&state);
  ------------------
  |  |   81|      1|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|      1|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1152|       |
 1153|      1|    global_dvb_state = state;
 1154|      1|    return state;
 1155|      1|}
stream_dvb.c:dvb_open:
  920|      1|{
  921|      1|    dvb_priv_t *priv = NULL;
  922|       |
  923|      1|    mp_mutex_lock(&global_dvb_state_lock);
  ------------------
  |  |  131|      1|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  924|      1|    if (global_dvb_state && global_dvb_state->stream_used) {
  ------------------
  |  Branch (924:9): [True: 0, False: 1]
  |  Branch (924:29): [True: 0, False: 0]
  ------------------
  925|      0|        MP_ERR(stream, "DVB stream already in use, only one DVB stream can exist at a time!\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  926|      0|        mp_mutex_unlock(&global_dvb_state_lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  927|      0|        goto err_out;
  928|      0|    }
  929|       |
  930|       |    // Need to re-get config in any case, not part of global state.
  931|      1|    stream->priv = talloc_zero(stream, dvb_priv_t);
  ------------------
  |  |   27|      1|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|      1|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      1|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  932|      1|    priv = stream->priv;
  933|      1|    priv->opts_cache = m_config_cache_alloc(stream, stream->global, &stream_dvb_conf);
  934|      1|    priv->opts = priv->opts_cache->opts;
  935|       |
  936|      1|    dvb_state_t *state = dvb_get_state(stream);
  937|       |
  938|      1|    priv->state = state;
  939|      1|    priv->log = stream->log;
  940|      1|    if (!state) {
  ------------------
  |  Branch (940:9): [True: 1, False: 0]
  ------------------
  941|      1|        MP_ERR(stream, "DVB configuration is empty\n");
  ------------------
  |  |   85|      1|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      1|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  942|      1|        mp_mutex_unlock(&global_dvb_state_lock);
  ------------------
  |  |  133|      1|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  943|      1|        goto err_out;
  944|      1|    }
  945|       |
  946|      0|    if (!dvb_parse_path(stream)) {
  ------------------
  |  Branch (946:9): [True: 0, False: 0]
  ------------------
  947|      0|        mp_mutex_unlock(&global_dvb_state_lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  948|      0|        goto err_out;
  949|      0|    }
  950|       |
  951|      0|    state->stream_used = true;
  952|      0|    mp_mutex_unlock(&global_dvb_state_lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  953|       |
  954|      0|    if (!state->is_on) {
  ------------------
  |  Branch (954:9): [True: 0, False: 0]
  ------------------
  955|       |        // State could be already initialized, for example, we just did a channel switch.
  956|       |        // The following setup only has to be done once.
  957|       |
  958|      0|        state->cur_frontend = -1;
  959|       |
  960|      0|        if (!dvb_streaming_start(stream, priv->prog))
  ------------------
  |  Branch (960:13): [True: 0, False: 0]
  ------------------
  961|      0|            goto err_out;
  962|      0|    }
  963|       |
  964|      0|    stream->fill_buffer = dvb_streaming_read;
  965|      0|    stream->close = dvbin_close;
  966|      0|    stream->control = dvbin_stream_control;
  967|      0|    stream->streaming = true;
  968|      0|    stream->demuxer = "lavf";
  969|      0|    stream->lavf_type = "mpegts";
  970|       |
  971|      0|    return STREAM_OK;
  ------------------
  |  |   68|      0|#define STREAM_OK    1
  ------------------
  972|       |
  973|      1|err_out:
  974|      1|    talloc_free(priv);
  ------------------
  |  |   47|      1|#define talloc_free                     ta_free
  ------------------
  975|      1|    stream->priv = NULL;
  976|      1|    return STREAM_ERROR;
  ------------------
  |  |   67|      1|#define STREAM_ERROR 0
  ------------------
  977|      0|}

stream_edl.c:s_open:
    7|    138|{
    8|    138|    stream->demuxer = "edl";
    9|       |
   10|    138|    return STREAM_OK;
  ------------------
  |  |   68|    138|#define STREAM_OK    1
  ------------------
   11|    138|}

mp_file_url_to_filename:
  176|  96.8k|{
  177|  96.8k|    bstr proto = mp_split_proto(url, &url);
  178|  96.8k|    if (bstrcasecmp0(proto, "file") != 0)
  ------------------
  |  Branch (178:9): [True: 95.9k, False: 814]
  ------------------
  179|  95.9k|        return NULL;
  180|    814|    char *filename = bstrto0(talloc_ctx, url);
  181|    814|    mp_url_unescape_inplace(filename);
  182|       |#if HAVE_DOS_PATHS
  183|       |    // extract '/' from '/x:/path'
  184|       |    if (filename[0] == '/' && filename[1] && filename[2] == ':')
  185|       |        memmove(filename, filename + 1, strlen(filename)); // including \0
  186|       |#endif
  187|    814|    return filename;
  188|  96.8k|}
stream_file.c:open_f:
  277|    478|{
  278|    478|    struct priv *p = talloc_ptrtype(stream, p);
  ------------------
  |  |   34|    478|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|    478|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    478|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  279|    478|    *p = (struct priv) {
  280|    478|        .fd = -1,
  281|    478|    };
  282|    478|    stream->priv = p;
  283|    478|    stream->is_local_fs = true;
  284|       |
  285|    478|    bool strict_fs = args->flags & STREAM_LOCAL_FS_ONLY;
  ------------------
  |  |   54|    478|#define STREAM_LOCAL_FS_ONLY      (1 << 5) // stream_file only, no URLs
  ------------------
  286|    478|    bool write = stream->mode == STREAM_WRITE;
  ------------------
  |  |   42|    478|#define STREAM_WRITE              (1 << 0)
  ------------------
  287|    478|    int m = O_CLOEXEC | (write ? O_RDWR | O_CREAT | O_TRUNC : O_RDONLY);
  ------------------
  |  Branch (287:26): [True: 0, False: 478]
  ------------------
  288|       |
  289|    478|    char *filename = stream->path;
  290|    478|    char *url = "";
  291|    478|    if (!strict_fs) {
  ------------------
  |  Branch (291:9): [True: 478, False: 0]
  ------------------
  292|    478|        char *fn = mp_file_url_to_filename(stream, bstr0(stream->url));
  293|    478|        if (fn)
  ------------------
  |  Branch (293:13): [True: 1, False: 477]
  ------------------
  294|      1|            filename = stream->path = fn;
  295|    478|        url = stream->url;
  296|    478|    }
  297|       |
  298|    478|    bool is_fdclose = strncmp(url, "fdclose://", 10) == 0;
  299|    478|    if (strncmp(url, "fd://", 5) == 0 || is_fdclose) {
  ------------------
  |  Branch (299:9): [True: 37, False: 441]
  |  Branch (299:42): [True: 29, False: 412]
  ------------------
  300|     66|        stream->is_local_fs = false;
  301|     66|        char *begin = strstr(stream->url, "://") + 3, *end = NULL;
  302|     66|        p->fd = strtol(begin, &end, 0);
  303|     66|        if (!end || end == begin || end[0] || p->fd < 0) {
  ------------------
  |  Branch (303:13): [True: 0, False: 66]
  |  Branch (303:21): [True: 2, False: 64]
  |  Branch (303:37): [True: 2, False: 62]
  |  Branch (303:47): [True: 32, False: 30]
  ------------------
  304|     36|            MP_ERR(stream, "Invalid FD number: %s\n", stream->url);
  ------------------
  |  |   85|     36|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     36|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  305|     36|            return STREAM_ERROR;
  ------------------
  |  |   67|     36|#define STREAM_ERROR 0
  ------------------
  306|     36|        }
  307|     30|#ifdef F_SETFD
  308|     30|        if (fcntl(p->fd, F_GETFD) == -1) {
  ------------------
  |  Branch (308:13): [True: 1, False: 29]
  ------------------
  309|      1|            MP_ERR(stream, "Invalid FD: %d\n", p->fd);
  ------------------
  |  |   85|      1|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      1|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  310|      1|            return STREAM_ERROR;
  ------------------
  |  |   67|      1|#define STREAM_ERROR 0
  ------------------
  311|      1|        }
  312|     29|#endif
  313|     29|        if (is_fdclose)
  ------------------
  |  Branch (313:13): [True: 28, False: 1]
  ------------------
  314|     28|            p->close = true;
  315|    412|    } else if (!strict_fs && !strcmp(filename, "-")) {
  ------------------
  |  Branch (315:16): [True: 412, False: 0]
  |  Branch (315:30): [True: 4, False: 408]
  ------------------
  316|      4|        stream->is_local_fs = false;
  317|      4|        if (!write) {
  ------------------
  |  Branch (317:13): [True: 4, False: 0]
  ------------------
  318|      4|            MP_INFO(stream, "Reading from stdin...\n");
  ------------------
  |  |   87|      4|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      4|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  319|      4|            p->fd = 0;
  320|      4|        } else {
  321|      0|            MP_INFO(stream, "Writing to stdout...\n");
  ------------------
  |  |   87|      0|#define MP_INFO(obj, ...)       MP_MSG(obj, MSGL_INFO, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  322|      0|            p->fd = 1;
  323|      0|        }
  324|    408|    } else {
  325|    408|        if (bstr_startswith0(bstr0(stream->url), "appending://"))
  ------------------
  |  Branch (325:13): [True: 1, False: 407]
  ------------------
  326|      1|            p->appending = true;
  327|       |
  328|    408|        mode_t openmode = S_IRUSR | S_IWUSR;
  329|    408|#ifndef __MINGW32__
  330|    408|        openmode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
  331|    408|        if (!write)
  ------------------
  |  Branch (331:13): [True: 408, False: 0]
  ------------------
  332|    408|            m |= O_NONBLOCK;
  333|    408|#endif
  334|    408|        p->fd = open(filename, m | O_BINARY, openmode);
  ------------------
  |  |   66|    408|#define O_BINARY 0
  ------------------
  335|    408|        if (p->fd < 0) {
  ------------------
  |  Branch (335:13): [True: 406, False: 2]
  ------------------
  336|    406|            MP_ERR(stream, "Cannot open file '%s': %s\n",
  ------------------
  |  |   85|    406|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    406|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  337|    406|                   filename, mp_strerror(errno));
  338|    406|            return STREAM_ERROR;
  ------------------
  |  |   67|    406|#define STREAM_ERROR 0
  ------------------
  339|    406|        }
  340|      2|        p->close = true;
  341|      2|    }
  342|       |
  343|     35|#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  344|     35|    if (p->fd != 42) {
  ------------------
  |  Branch (344:9): [True: 35, False: 0]
  ------------------
  345|     35|        s_close(stream);
  346|     35|        return STREAM_ERROR;
  ------------------
  |  |   67|     35|#define STREAM_ERROR 0
  ------------------
  347|     35|    }
  348|      0|#endif
  349|       |
  350|      0|    struct stat st;
  351|      0|    bool is_sock_or_fifo = false;
  352|      0|    if (fstat(p->fd, &st) == 0) {
  ------------------
  |  Branch (352:9): [True: 0, False: 0]
  ------------------
  353|      0|        if (S_ISDIR(st.st_mode)) {
  354|      0|            stream->is_directory = true;
  355|      0|        } else if (S_ISREG(st.st_mode)) {
  356|      0|            p->regular_file = true;
  357|      0|#ifndef _WIN32
  358|       |            // O_NONBLOCK has weird semantics on file locks; remove it.
  359|      0|            int val = fcntl(p->fd, F_GETFL) & ~(unsigned)O_NONBLOCK;
  360|      0|            fcntl(p->fd, F_SETFL, val);
  361|      0|#endif
  362|      0|        } else {
  363|      0|#ifndef __MINGW32__
  364|      0|            is_sock_or_fifo = S_ISSOCK(st.st_mode) || S_ISFIFO(st.st_mode);
  365|      0|#endif
  366|      0|            p->use_poll = true;
  367|      0|        }
  368|      0|    }
  369|       |
  370|       |#ifdef _WIN32
  371|       |    setmode(p->fd, O_BINARY);
  372|       |#endif
  373|       |
  374|      0|    off_t len = lseek(p->fd, 0, SEEK_END);
  375|      0|    lseek(p->fd, 0, SEEK_SET);
  376|      0|    if (len != (off_t)-1) {
  ------------------
  |  Branch (376:9): [True: 0, False: 0]
  ------------------
  377|      0|        stream->seek = seek;
  378|      0|        stream->seekable = true;
  379|      0|    }
  380|       |
  381|      0|    stream->fast_skip = true;
  382|      0|    stream->fill_buffer = fill_buffer;
  383|      0|    stream->write_buffer = write_buffer;
  384|      0|    stream->get_size = get_size;
  385|      0|    stream->close = s_close;
  386|       |
  387|      0|    if (is_sock_or_fifo || check_stream_network(p->fd)) {
  ------------------
  |  Branch (387:9): [True: 0, False: 0]
  |  Branch (387:28): [True: 0, False: 0]
  ------------------
  388|      0|        stream->streaming = true;
  389|       |#if HAVE_COCOA
  390|       |        if (fcntl(p->fd, F_RDAHEAD, 0) < 0) {
  391|       |            MP_VERBOSE(stream, "Cannot disable read ahead on file '%s': %s\n",
  392|       |                       filename, mp_strerror(errno));
  393|       |        }
  394|       |#endif
  395|      0|    }
  396|       |
  397|      0|    p->orig_size = get_size(stream);
  398|       |
  399|      0|    p->cancel = mp_cancel_new(p);
  400|      0|    if (stream->cancel)
  ------------------
  |  Branch (400:9): [True: 0, False: 0]
  ------------------
  401|      0|        mp_cancel_set_parent(p->cancel, stream->cancel);
  402|       |
  403|      0|    return STREAM_OK;
  ------------------
  |  |   68|      0|#define STREAM_OK    1
  ------------------
  404|     35|}
stream_file.c:s_close:
  168|     35|{
  169|     35|    struct priv *p = s->priv;
  170|     35|    if (p->close)
  ------------------
  |  Branch (170:9): [True: 30, False: 5]
  ------------------
  171|     30|        close(p->fd);
  172|     35|}

mp_setup_av_network_options:
  185|  2.04k|{
  186|  2.04k|    void *temp = talloc_new(NULL);
  ------------------
  |  |   40|  2.04k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  2.04k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  187|  2.04k|    struct stream_lavf_params *opts =
  188|  2.04k|        mp_get_config_group(temp, global, &stream_lavf_conf);
  189|       |
  190|       |    // HTTP specific options (other protocols ignore them)
  191|  2.04k|    if (opts->useragent)
  ------------------
  |  Branch (191:9): [True: 2.04k, False: 0]
  ------------------
  192|  2.04k|        av_dict_set(dict, "user_agent", opts->useragent, 0);
  193|  2.04k|    if (opts->cookies_enabled) {
  ------------------
  |  Branch (193:9): [True: 1, False: 2.04k]
  ------------------
  194|      1|        char *file = opts->cookies_file;
  195|      1|        if (file && file[0])
  ------------------
  |  Branch (195:13): [True: 0, False: 1]
  |  Branch (195:21): [True: 0, False: 0]
  ------------------
  196|      0|            file = mp_get_user_path(temp, global, file);
  197|      1|        char *cookies = cookies_lavf(temp, global, log, file);
  198|      1|        if (cookies && cookies[0])
  ------------------
  |  Branch (198:13): [True: 1, False: 0]
  |  Branch (198:24): [True: 0, False: 1]
  ------------------
  199|      0|            av_dict_set(dict, "cookies", cookies, 0);
  200|      1|    }
  201|  2.04k|    av_dict_set(dict, "tls_verify", opts->tls_verify ? "1" : "0", 0);
  ------------------
  |  Branch (201:37): [True: 0, False: 2.04k]
  ------------------
  202|  2.04k|    if (opts->tls_ca_file) {
  ------------------
  |  Branch (202:9): [True: 0, False: 2.04k]
  ------------------
  203|      0|        char *file = mp_get_user_path(temp, global, opts->tls_ca_file);
  204|      0|        av_dict_set(dict, "ca_file", file, 0);
  205|      0|    }
  206|  2.04k|    if (opts->tls_cert_file) {
  ------------------
  |  Branch (206:9): [True: 0, False: 2.04k]
  ------------------
  207|      0|        char *file = mp_get_user_path(temp, global, opts->tls_cert_file);
  208|      0|        av_dict_set(dict, "cert_file", file, 0);
  209|      0|    }
  210|  2.04k|    if (opts->tls_key_file) {
  ------------------
  |  Branch (210:9): [True: 0, False: 2.04k]
  ------------------
  211|      0|        char *file = mp_get_user_path(temp, global, opts->tls_key_file);
  212|      0|        av_dict_set(dict, "key_file", file, 0);
  213|      0|    }
  214|  2.04k|    char *cust_headers = talloc_strdup(temp, "");
  ------------------
  |  |   50|  2.04k|#define talloc_strdup                   ta_xstrdup
  ------------------
  215|  2.04k|    if (opts->referrer) {
  ------------------
  |  Branch (215:9): [True: 2, False: 2.04k]
  ------------------
  216|      2|        cust_headers = talloc_asprintf_append(cust_headers, "Referer: %s\r\n",
  ------------------
  |  |   63|      2|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
  217|      2|                                              opts->referrer);
  218|      2|    }
  219|  2.04k|    if (opts->http_header_fields) {
  ------------------
  |  Branch (219:9): [True: 0, False: 2.04k]
  ------------------
  220|      0|        for (int n = 0; opts->http_header_fields[n]; n++) {
  ------------------
  |  Branch (220:25): [True: 0, False: 0]
  ------------------
  221|      0|            cust_headers = talloc_asprintf_append(cust_headers, "%s\r\n",
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
  222|      0|                                                  opts->http_header_fields[n]);
  223|      0|        }
  224|      0|    }
  225|  2.04k|    if (strlen(cust_headers))
  ------------------
  |  Branch (225:9): [True: 2, False: 2.04k]
  ------------------
  226|      2|        av_dict_set(dict, "headers", cust_headers, 0);
  227|  2.04k|    av_dict_set(dict, "icy", "1", 0);
  228|       |    // So far, every known protocol uses microseconds for this
  229|       |    // Except rtsp.
  230|  2.04k|    if (opts->timeout > 0) {
  ------------------
  |  Branch (230:9): [True: 2.04k, False: 0]
  ------------------
  231|  2.04k|        if (target_fmt && strcmp(target_fmt, "rtsp") == 0) {
  ------------------
  |  Branch (231:13): [True: 0, False: 2.04k]
  |  Branch (231:27): [True: 0, False: 0]
  ------------------
  232|      0|            mp_verbose(log, "Broken FFmpeg RTSP API => not setting timeout.\n");
  ------------------
  |  |   75|      0|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  233|  2.04k|        } else {
  234|  2.04k|            char buf[80];
  235|  2.04k|            snprintf(buf, sizeof(buf), "%lld", (long long)(opts->timeout * 1e6));
  236|  2.04k|            av_dict_set(dict, "timeout", buf, 0);
  237|  2.04k|        }
  238|  2.04k|    }
  239|  2.04k|    if (opts->http_proxy && opts->http_proxy[0])
  ------------------
  |  Branch (239:9): [True: 0, False: 2.04k]
  |  Branch (239:29): [True: 0, False: 0]
  ------------------
  240|      0|        av_dict_set(dict, "http_proxy", opts->http_proxy, 0);
  241|       |
  242|  2.04k|    mp_set_avdict(dict, opts->avopts);
  243|       |
  244|  2.04k|    talloc_free(temp);
  ------------------
  |  |   47|  2.04k|#define talloc_free                     ta_free
  ------------------
  245|  2.04k|}
stream_lavf.c:open_f:
  357|  2.04k|{
  358|  2.04k|    AVIOContext *avio = NULL;
  359|  2.04k|    int res = STREAM_ERROR;
  ------------------
  |  |   67|  2.04k|#define STREAM_ERROR 0
  ------------------
  360|  2.04k|    AVDictionary *dict = NULL;
  361|  2.04k|    void *temp = talloc_new(NULL);
  ------------------
  |  |   40|  2.04k|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|  2.04k|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
  362|       |
  363|  2.04k|    stream->seek = NULL;
  364|  2.04k|    stream->seekable = false;
  365|       |
  366|  2.04k|    int flags = stream->mode == STREAM_WRITE ? AVIO_FLAG_WRITE : AVIO_FLAG_READ;
  ------------------
  |  |   42|  2.04k|#define STREAM_WRITE              (1 << 0)
  ------------------
  |  Branch (366:17): [True: 0, False: 2.04k]
  ------------------
  367|       |
  368|  2.04k|    const char *filename = stream->url;
  369|  2.04k|    if (!filename) {
  ------------------
  |  Branch (369:9): [True: 0, False: 2.04k]
  ------------------
  370|      0|        MP_ERR(stream, "No URL\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  371|      0|        goto out;
  372|      0|    }
  373|  6.14k|    for (int i = 0; i < MP_ARRAY_SIZE(prefix); i++)
  ------------------
  |  |   48|  6.14k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (373:21): [True: 4.09k, False: 2.04k]
  ------------------
  374|  4.09k|        if (!strncmp(filename, prefix[i], strlen(prefix[i])))
  ------------------
  |  Branch (374:13): [True: 528, False: 3.56k]
  ------------------
  375|    528|            filename += strlen(prefix[i]);
  376|  2.04k|    if (!strncmp(filename, "rtsp:", 5) || !strncmp(filename, "rtsps:", 6)) {
  ------------------
  |  Branch (376:9): [True: 1, False: 2.04k]
  |  Branch (376:43): [True: 2, False: 2.04k]
  ------------------
  377|       |        /* This is handled as a special demuxer, without a separate
  378|       |         * stream layer. demux_lavf will do all the real work. Note
  379|       |         * that libavformat doesn't even provide a protocol entry for
  380|       |         * this (the rtsp demuxer's probe function checks for a "rtsp:"
  381|       |         * filename prefix), so it has to be handled specially here.
  382|       |         */
  383|      3|        stream->demuxer = "lavf";
  384|      3|        stream->lavf_type = "rtsp";
  385|      3|        talloc_free(temp);
  ------------------
  |  |   47|      3|#define talloc_free                     ta_free
  ------------------
  386|      3|        return STREAM_OK;
  ------------------
  |  |   68|      3|#define STREAM_OK    1
  ------------------
  387|      3|    }
  388|       |
  389|       |    // Replace "mms://" with "mmsh://", so that most mms:// URLs just work.
  390|       |    // Replace "dav://" or "webdav://" with "http://" and "davs://" or "webdavs://" with "https://"
  391|  2.04k|    bstr b_filename = bstr0(filename);
  392|  2.04k|    if (bstr_eatstart0(&b_filename, "mms://") ||
  ------------------
  |  Branch (392:9): [True: 18, False: 2.02k]
  ------------------
  393|  2.04k|        bstr_eatstart0(&b_filename, "mmshttp://"))
  ------------------
  |  Branch (393:9): [True: 1, False: 2.02k]
  ------------------
  394|     19|    {
  395|     19|        filename = talloc_asprintf(temp, "mmsh://%.*s", BSTR_P(b_filename));
  ------------------
  |  |   52|     19|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|     38|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (127:62): [True: 19, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  396|  2.02k|    } else if (bstr_eatstart0(&b_filename, "dav://") || bstr_eatstart0(&b_filename, "webdav://"))
  ------------------
  |  Branch (396:16): [True: 19, False: 2.00k]
  |  Branch (396:57): [True: 1, False: 2.00k]
  ------------------
  397|     20|    {
  398|     20|        filename = talloc_asprintf(temp, "http://%.*s", BSTR_P(b_filename));
  ------------------
  |  |   52|     20|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|     40|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (127:62): [True: 20, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  399|  2.00k|    } else if (bstr_eatstart0(&b_filename, "davs://") || bstr_eatstart0(&b_filename, "webdavs://"))
  ------------------
  |  Branch (399:16): [True: 1, False: 2.00k]
  |  Branch (399:58): [True: 1, False: 2.00k]
  ------------------
  400|      2|    {
  401|      2|        filename = talloc_asprintf(temp, "https://%.*s", BSTR_P(b_filename));
  ------------------
  |  |   52|      2|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      4|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (127:62): [True: 2, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  402|      2|    }
  403|       |
  404|  2.04k|    av_dict_set(&dict, "reconnect", "1", 0);
  405|  2.04k|    av_dict_set(&dict, "reconnect_delay_max", "7", 0);
  406|       |
  407|  2.04k|    mp_setup_av_network_options(&dict, NULL, stream->global, stream->log);
  408|       |
  409|  2.04k|    AVIOInterruptCB cb = {
  410|  2.04k|        .callback = interrupt_cb,
  411|  2.04k|        .opaque = stream,
  412|  2.04k|    };
  413|       |
  414|  2.04k|    filename = normalize_url(stream, filename);
  415|       |
  416|  2.04k|    if (strncmp(filename, "rtmp", 4) == 0) {
  ------------------
  |  Branch (416:9): [True: 1, False: 2.04k]
  ------------------
  417|      1|        stream->demuxer = "lavf";
  418|      1|        stream->lavf_type = "flv";
  419|       |        // Setting timeout enables listen mode - force it to disabled.
  420|      1|        av_dict_set(&dict, "timeout", "0", 0);
  421|      1|    }
  422|       |
  423|  2.04k|    int err = avio_open2(&avio, filename, flags, &cb, &dict);
  424|  2.04k|    if (err < 0) {
  ------------------
  |  Branch (424:9): [True: 1.45k, False: 590]
  ------------------
  425|  1.45k|        if (err == AVERROR_PROTOCOL_NOT_FOUND)
  ------------------
  |  Branch (425:13): [True: 119, False: 1.33k]
  ------------------
  426|  1.45k|            MP_ERR(stream, "Protocol not found. Make sure"
  ------------------
  |  |   85|    119|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|    119|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  427|  1.45k|                   " FFmpeg is compiled with networking support.\n");
  428|  1.45k|        goto out;
  429|  1.45k|    }
  430|       |
  431|    590|    mp_avdict_print_unset(stream->log, MSGL_V, dict);
  432|       |
  433|    590|    if (avio->av_class) {
  ------------------
  |  Branch (433:9): [True: 590, False: 0]
  ------------------
  434|    590|        uint8_t *mt = NULL;
  435|    590|        if (av_opt_get(avio, "mime_type", AV_OPT_SEARCH_CHILDREN, &mt) >= 0) {
  ------------------
  |  Branch (435:13): [True: 0, False: 590]
  ------------------
  436|      0|            stream->mime_type = talloc_strdup(stream, mt);
  ------------------
  |  |   50|      0|#define talloc_strdup                   ta_xstrdup
  ------------------
  437|      0|            av_free(mt);
  438|      0|        }
  439|    590|    }
  440|       |
  441|    590|    stream->priv = avio;
  442|    590|    stream->seekable = avio->seekable & AVIO_SEEKABLE_NORMAL;
  443|    590|    stream->seek = stream->seekable ? seek : NULL;
  ------------------
  |  Branch (443:20): [True: 588, False: 2]
  ------------------
  444|    590|    stream->fill_buffer = fill_buffer;
  445|    590|    stream->write_buffer = write_buffer;
  446|    590|    stream->get_size = get_size;
  447|    590|    stream->control = control;
  448|    590|    stream->close = close_f;
  449|       |    // enable cache (should be avoided for files, but no way to detect this)
  450|    590|    stream->streaming = true;
  451|    590|    if (stream->info->stream_origin == STREAM_ORIGIN_NET)
  ------------------
  |  |   49|    590|#define STREAM_ORIGIN_NET         (3 << 2) // referenced from playlist on network
  ------------------
  |  Branch (451:9): [True: 434, False: 156]
  ------------------
  452|    434|        stream->is_network = true;
  453|    590|    res = STREAM_OK;
  ------------------
  |  |   68|    590|#define STREAM_OK    1
  ------------------
  454|       |
  455|  2.04k|out:
  456|  2.04k|    av_dict_free(&dict);
  457|  2.04k|    talloc_free(temp);
  ------------------
  |  |   47|  2.04k|#define talloc_free                     ta_free
  ------------------
  458|  2.04k|    return res;
  459|    590|}
stream_lavf.c:interrupt_cb:
  176|  1.97k|{
  177|  1.97k|    struct stream *stream = ctx;
  178|  1.97k|    return mp_cancel_test(stream->cancel);
  179|  1.97k|}
stream_lavf.c:normalize_url:
  345|  2.04k|{
  346|  2.04k|    bstr proto = mp_split_proto(bstr0(filename), NULL);
  347|  12.1k|    for (int n = 0; http_like[n]; n++) {
  ------------------
  |  Branch (347:21): [True: 10.1k, False: 2.00k]
  ------------------
  348|  10.1k|        if (bstr_equals0(proto, http_like[n]))
  ------------------
  |  Branch (348:13): [True: 41, False: 10.0k]
  ------------------
  349|       |            // Escape everything but reserved characters.
  350|       |            // Also don't double-scape, so include '%'.
  351|     41|            return mp_url_escape(ta_parent, filename, ":/?#[]@!$&'()*+,;=%");
  352|  10.1k|    }
  353|  2.00k|    return (char *)filename;
  354|  2.04k|}
stream_lavf.c:seek:
  102|    528|{
  103|    528|    AVIOContext *avio = s->priv;
  104|    528|    if (avio_seek(avio, newpos, SEEK_SET) < 0) {
  ------------------
  |  Branch (104:9): [True: 528, False: 0]
  ------------------
  105|    528|        return 0;
  106|    528|    }
  107|      0|    return 1;
  108|    528|}
stream_lavf.c:fill_buffer:
   85|  1.39k|{
   86|  1.39k|    AVIOContext *avio = s->priv;
   87|  1.39k|    int r = avio_read_partial(avio, buffer, max_len);
   88|  1.39k|    return (r <= 0) ? -1 : r;
  ------------------
  |  Branch (88:12): [True: 1.05k, False: 337]
  ------------------
   89|  1.39k|}
stream_lavf.c:get_size:
  111|  1.18k|{
  112|  1.18k|    AVIOContext *avio = s->priv;
  113|  1.18k|    return avio_size(avio);
  114|  1.18k|}
stream_lavf.c:control:
  129|    160|{
  130|    160|    AVIOContext *avio = s->priv;
  131|    160|    switch(cmd) {
  ------------------
  |  Branch (131:12): [True: 0, False: 160]
  ------------------
  132|      0|    case STREAM_CTRL_AVSEEK: {
  ------------------
  |  Branch (132:5): [True: 0, False: 160]
  ------------------
  133|      0|        struct stream_avseek *c = arg;
  134|      0|        int64_t r = avio_seek_time(avio, c->stream_index, c->timestamp, c->flags);
  135|      0|        if (r >= 0) {
  ------------------
  |  Branch (135:13): [True: 0, False: 0]
  ------------------
  136|      0|            stream_drop_buffers(s);
  137|      0|            return 1;
  138|      0|        }
  139|      0|        break;
  140|      0|    }
  141|    102|    case STREAM_CTRL_HAS_AVSEEK: {
  ------------------
  |  Branch (141:5): [True: 102, False: 58]
  ------------------
  142|       |        // Starting at some point, read_seek is always available, and runtime
  143|       |        // behavior decides whether it exists or not. FFmpeg's API doesn't
  144|       |        // return anything helpful to determine seekability upfront, so here's
  145|       |        // a hardcoded whitelist. Not our fault.
  146|       |        // In addition we also have to jump through ridiculous hoops just to
  147|       |        // get the fucking protocol name.
  148|    102|        const char *proto = NULL;
  149|    102|        if (avio->av_class && avio->av_class->child_next) {
  ------------------
  |  Branch (149:13): [True: 102, False: 0]
  |  Branch (149:31): [True: 102, False: 0]
  ------------------
  150|       |            // This usually yields the URLContext (why does it even exist?),
  151|       |            // which holds the name of the actual protocol implementation.
  152|    102|            void *child = avio->av_class->child_next(avio, NULL);
  153|    102|            AVClass *cl = *(AVClass **)child;
  154|    102|            if (cl && cl->item_name)
  ------------------
  |  Branch (154:17): [True: 102, False: 0]
  |  Branch (154:23): [True: 102, False: 0]
  ------------------
  155|    102|                proto = cl->item_name(child);
  156|    102|        }
  157|    102|        static const char *const has_read_seek[] = {
  158|    102|            "rtmp", "rtmpt", "rtmpe", "rtmpte", "rtmps", "rtmpts", "mmsh", 0};
  159|    816|        for (int n = 0; has_read_seek[n]; n++) {
  ------------------
  |  Branch (159:25): [True: 714, False: 102]
  ------------------
  160|    714|            if (avio->read_seek && proto && strcmp(proto, has_read_seek[n]) == 0)
  ------------------
  |  Branch (160:17): [True: 0, False: 714]
  |  Branch (160:36): [True: 0, False: 0]
  |  Branch (160:45): [True: 0, False: 0]
  ------------------
  161|      0|                return 1;
  162|    714|        }
  163|    102|        break;
  164|    102|    }
  165|    102|    case STREAM_CTRL_GET_METADATA: {
  ------------------
  |  Branch (165:5): [True: 58, False: 102]
  ------------------
  166|     58|        *(struct mp_tags **)arg = read_icy(s);
  167|     58|        if (!*(struct mp_tags **)arg)
  ------------------
  |  Branch (167:13): [True: 58, False: 0]
  ------------------
  168|     58|            break;
  169|      0|        return 1;
  170|     58|    }
  171|    160|    }
  172|    160|    return STREAM_UNSUPPORTED;
  ------------------
  |  |   66|    160|#define STREAM_UNSUPPORTED -1
  ------------------
  173|    160|}
stream_lavf.c:read_icy:
  462|     58|{
  463|     58|    AVIOContext *avio = s->priv;
  464|       |
  465|     58|    if (!avio->av_class)
  ------------------
  |  Branch (465:9): [True: 0, False: 58]
  ------------------
  466|      0|        return NULL;
  467|       |
  468|     58|    uint8_t *icy_header = NULL;
  469|     58|    if (av_opt_get(avio, "icy_metadata_headers", AV_OPT_SEARCH_CHILDREN,
  ------------------
  |  Branch (469:9): [True: 58, False: 0]
  ------------------
  470|     58|                   &icy_header) < 0)
  471|     58|        icy_header = NULL;
  472|       |
  473|     58|    uint8_t *icy_packet;
  474|     58|    if (av_opt_get(avio, "icy_metadata_packet", AV_OPT_SEARCH_CHILDREN,
  ------------------
  |  Branch (474:9): [True: 58, False: 0]
  ------------------
  475|     58|                   &icy_packet) < 0)
  476|     58|        icy_packet = NULL;
  477|       |
  478|       |    // Send a metadata update only 1. on start, and 2. on a new metadata packet.
  479|       |    // To detect new packages, set the icy_metadata_packet to "-" once we've
  480|       |    // read it (a bit hacky, but works).
  481|       |
  482|     58|    struct mp_tags *res = NULL;
  483|     58|    if ((!icy_header || !icy_header[0]) && (!icy_packet || !icy_packet[0]))
  ------------------
  |  Branch (483:10): [True: 58, False: 0]
  |  Branch (483:25): [True: 0, False: 0]
  |  Branch (483:45): [True: 58, False: 0]
  |  Branch (483:60): [True: 0, False: 0]
  ------------------
  484|     58|        goto done;
  485|       |
  486|      0|    bstr packet = bstr0(icy_packet);
  487|      0|    if (bstr_equals0(packet, "-"))
  ------------------
  |  Branch (487:9): [True: 0, False: 0]
  ------------------
  488|      0|        goto done;
  489|       |
  490|      0|    res = talloc_zero(NULL, struct mp_tags);
  ------------------
  |  |   27|      0|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|      0|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  491|       |
  492|      0|    bstr header = bstr0(icy_header);
  493|      0|    while (header.len) {
  ------------------
  |  Branch (493:12): [True: 0, False: 0]
  ------------------
  494|      0|        bstr line = bstr_strip_linebreaks(bstr_getline(header, &header));
  495|      0|        bstr name, val;
  496|      0|        if (bstr_split_tok(line, ": ", &name, &val))
  ------------------
  |  Branch (496:13): [True: 0, False: 0]
  ------------------
  497|      0|            mp_tags_set_bstr(res, name, val);
  498|      0|    }
  499|       |
  500|      0|    bstr head = bstr0("StreamTitle='");
  501|      0|    int i = bstr_find(packet, head);
  502|      0|    if (i >= 0) {
  ------------------
  |  Branch (502:9): [True: 0, False: 0]
  ------------------
  503|      0|        packet = bstr_cut(packet, i + head.len);
  504|      0|        int end = bstr_find(packet, bstr0("\';"));
  505|      0|        packet = bstr_splice(packet, 0, end);
  506|       |
  507|      0|        bool allocated = false;
  508|      0|        struct demux_opts *opts = mp_get_config_group(NULL, s->global, &demux_conf);
  509|      0|        const char *charset = mp_charset_guess(s, s->log, packet, opts->meta_cp, 0);
  510|      0|        if (charset && !mp_charset_is_utf8(charset)) {
  ------------------
  |  Branch (510:13): [True: 0, False: 0]
  |  Branch (510:24): [True: 0, False: 0]
  ------------------
  511|      0|            bstr conv = mp_iconv_to_utf8(s->log, packet, charset, 0);
  512|      0|            if (conv.start && conv.start != packet.start) {
  ------------------
  |  Branch (512:17): [True: 0, False: 0]
  |  Branch (512:31): [True: 0, False: 0]
  ------------------
  513|      0|                allocated = true;
  514|      0|                packet = conv;
  515|      0|            }
  516|      0|        }
  517|      0|        mp_tags_set_bstr(res, bstr0("icy-title"), packet);
  518|      0|        talloc_free(opts);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  519|      0|        if (allocated)
  ------------------
  |  Branch (519:13): [True: 0, False: 0]
  ------------------
  520|      0|            talloc_free(packet.start);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  521|      0|    }
  522|       |
  523|      0|    av_opt_set(avio, "icy_metadata_packet", "-", AV_OPT_SEARCH_CHILDREN);
  524|       |
  525|     58|done:
  526|     58|    av_free(icy_header);
  527|     58|    av_free(icy_packet);
  528|     58|    return res;
  529|      0|}
stream_lavf.c:close_f:
  117|    590|{
  118|    590|    AVIOContext *avio = stream->priv;
  119|       |    /* NOTE: As of 2011 write streams must be manually flushed before close.
  120|       |     * Currently write_buffer() always flushes them after writing.
  121|       |     * avio_close() could return an error, but we have no way to return that
  122|       |     * with the current stream API.
  123|       |     */
  124|    590|    if (avio)
  ------------------
  |  Branch (124:9): [True: 590, False: 0]
  ------------------
  125|    590|        avio_close(avio);
  126|    590|}
stream_lavf.c:get_safe_protocols:
  275|  8.11k|{
  276|  8.11k|    int num = 0;
  277|  8.11k|    char **protocols = NULL;
  278|  8.11k|    char **ffmpeg_demuxers = mp_get_lavf_demuxers();
  279|  8.11k|    char **ffmpeg_protos = mp_get_lavf_protocols();
  280|       |
  281|  97.3k|    for (int i = 0; ffmpeg_protos[i]; i++) {
  ------------------
  |  Branch (281:21): [True: 89.2k, False: 8.11k]
  ------------------
  282|  1.71M|        for (int j = 0; safe_protos[j]; j++) {
  ------------------
  |  Branch (282:25): [True: 1.63M, False: 81.1k]
  ------------------
  283|  1.63M|            if (strcmp(ffmpeg_protos[i], safe_protos[j][0]) != 0)
  ------------------
  |  Branch (283:17): [True: 1.62M, False: 8.11k]
  ------------------
  284|  1.62M|                continue;
  285|  16.2k|            for (int k = 0; safe_protos[j][k]; k++)
  ------------------
  |  Branch (285:29): [True: 8.11k, False: 8.11k]
  ------------------
  286|  8.11k|                MP_TARRAY_APPEND(NULL, protocols, num, talloc_strdup(protocols, safe_protos[j][k]));
  ------------------
  |  |  105|  16.2k|    do {                                            \
  |  |  106|  8.11k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  8.11k|    do {                                            \
  |  |  |  |   97|  8.11k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  8.11k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  8.11k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  8.11k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 8.11k, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|  8.11k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  8.11k|    do {                                                        \
  |  |  |  |  |  |   89|  8.11k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  8.11k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  8.11k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  8.11k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  8.11k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  8.11k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  8.11k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  8.11k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  8.11k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  8.11k|        (idxvar)++;                                 \
  |  |  109|  8.11k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  287|  8.11k|            break;
  288|  1.63M|        }
  289|  89.2k|    }
  290|       |
  291|       |    // rtsp is a demuxer not protocol in ffmpeg so it is handled separately
  292|  2.88M|    for (int i = 0; ffmpeg_demuxers[i]; i++) {
  ------------------
  |  Branch (292:21): [True: 2.88M, False: 8.11k]
  ------------------
  293|  2.88M|        if (strcmp("rtsp", ffmpeg_demuxers[i]) == 0) {
  ------------------
  |  Branch (293:13): [True: 0, False: 2.88M]
  ------------------
  294|      0|            MP_TARRAY_APPEND(NULL, protocols, num, talloc_strdup(protocols, "rtsp"));
  ------------------
  |  |  105|      0|    do {                                            \
  |  |  106|      0|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      0|    do {                                            \
  |  |  |  |   97|      0|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      0|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      0|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      0|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      0|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      0|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      0|        (idxvar)++;                                 \
  |  |  109|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  295|      0|            MP_TARRAY_APPEND(NULL, protocols, num, talloc_strdup(protocols, "rtsps"));
  ------------------
  |  |  105|      0|    do {                                            \
  |  |  106|      0|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      0|    do {                                            \
  |  |  |  |   97|      0|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      0|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      0|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      0|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      0|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      0|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      0|        (idxvar)++;                                 \
  |  |  109|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  296|      0|            break;
  297|      0|        }
  298|  2.88M|    }
  299|       |
  300|  8.11k|    MP_TARRAY_APPEND(NULL, protocols, num, NULL);
  ------------------
  |  |  105|  8.11k|    do {                                            \
  |  |  106|  8.11k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  8.11k|    do {                                            \
  |  |  |  |   97|  8.11k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  8.11k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  8.11k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  8.11k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 8.11k]
  |  |  |  |  ------------------
  |  |  |  |   99|  8.11k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  8.11k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  8.11k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  8.11k|        (idxvar)++;                                 \
  |  |  109|  8.11k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  301|       |
  302|  8.11k|    talloc_free(ffmpeg_demuxers);
  ------------------
  |  |   47|  8.11k|#define talloc_free                     ta_free
  ------------------
  303|  8.11k|    talloc_free(ffmpeg_protos);
  ------------------
  |  |   47|  8.11k|#define talloc_free                     ta_free
  ------------------
  304|       |
  305|  8.11k|    return protocols;
  306|  8.11k|}
stream_lavf.c:get_unsafe_protocols:
  309|  3.83k|{
  310|  3.83k|    int num = 0;
  311|  3.83k|    char **protocols = NULL;
  312|  3.83k|    char **safe_protocols = get_safe_protocols();
  313|  3.83k|    char **ffmpeg_protos = mp_get_lavf_protocols();
  314|       |
  315|  46.0k|    for (int i = 0; ffmpeg_protos[i]; i++) {
  ------------------
  |  Branch (315:21): [True: 42.1k, False: 3.83k]
  ------------------
  316|  42.1k|        bool safe_protocol = false;
  317|  80.5k|        for (int j = 0; safe_protocols[j]; j++) {
  ------------------
  |  Branch (317:25): [True: 42.1k, False: 38.3k]
  ------------------
  318|  42.1k|            if (strcmp(ffmpeg_protos[i], safe_protocols[j]) == 0) {
  ------------------
  |  Branch (318:17): [True: 3.83k, False: 38.3k]
  ------------------
  319|  3.83k|                safe_protocol = true;
  320|  3.83k|                break;
  321|  3.83k|            }
  322|  42.1k|        }
  323|       |        // Skip to avoid name conflict with builtin mpv protocol.
  324|  42.1k|        if (strcmp(ffmpeg_protos[i], "bluray") == 0 || strcmp(ffmpeg_protos[i], "dvd") == 0)
  ------------------
  |  Branch (324:13): [True: 0, False: 42.1k]
  |  Branch (324:56): [True: 0, False: 42.1k]
  ------------------
  325|      0|            continue;
  326|       |
  327|  42.1k|        if (!safe_protocol)
  ------------------
  |  Branch (327:13): [True: 38.3k, False: 3.83k]
  ------------------
  328|  38.3k|            MP_TARRAY_APPEND(NULL, protocols, num, talloc_strdup(protocols, ffmpeg_protos[i]));
  ------------------
  |  |  105|  38.3k|    do {                                            \
  |  |  106|  38.3k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  38.3k|    do {                                            \
  |  |  |  |   97|  38.3k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  38.3k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  38.3k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  38.3k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 11.5k, False: 26.8k]
  |  |  |  |  ------------------
  |  |  |  |   99|  38.3k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|  11.5k|    do {                                                        \
  |  |  |  |  |  |   89|  11.5k|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|  11.5k|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|  11.5k|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|  11.5k|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|  11.5k|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|  11.5k|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|  11.5k|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  38.3k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  38.3k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  38.3k|        (idxvar)++;                                 \
  |  |  109|  38.3k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  329|  42.1k|    }
  330|       |
  331|  3.83k|    MP_TARRAY_APPEND(NULL, protocols, num, talloc_strdup(protocols, "ffmpeg"));
  ------------------
  |  |  105|  3.83k|    do {                                            \
  |  |  106|  3.83k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  3.83k|    do {                                            \
  |  |  |  |   97|  3.83k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  3.83k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  3.83k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  3.83k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 3.83k]
  |  |  |  |  ------------------
  |  |  |  |   99|  3.83k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  3.83k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  3.83k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  3.83k|        (idxvar)++;                                 \
  |  |  109|  3.83k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  332|  3.83k|    MP_TARRAY_APPEND(NULL, protocols, num, talloc_strdup(protocols, "lavf"));
  ------------------
  |  |  105|  3.83k|    do {                                            \
  |  |  106|  3.83k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  3.83k|    do {                                            \
  |  |  |  |   97|  3.83k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  3.83k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  3.83k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  3.83k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 3.83k]
  |  |  |  |  ------------------
  |  |  |  |   99|  3.83k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  3.83k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  3.83k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  3.83k|        (idxvar)++;                                 \
  |  |  109|  3.83k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  333|       |
  334|  3.83k|    MP_TARRAY_APPEND(NULL, protocols, num, NULL);
  ------------------
  |  |  105|  3.83k|    do {                                            \
  |  |  106|  3.83k|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|  3.83k|    do {                                            \
  |  |  |  |   97|  3.83k|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|  3.83k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|  3.83k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|  3.83k|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 3.83k]
  |  |  |  |  ------------------
  |  |  |  |   99|  3.83k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|  3.83k|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|  3.83k|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|  3.83k|        (idxvar)++;                                 \
  |  |  109|  3.83k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  335|       |
  336|  3.83k|    talloc_free(ffmpeg_protos);
  ------------------
  |  |   47|  3.83k|#define talloc_free                     ta_free
  ------------------
  337|  3.83k|    talloc_free(safe_protocols);
  ------------------
  |  |   47|  3.83k|#define talloc_free                     ta_free
  ------------------
  338|  3.83k|    return protocols;
  339|  3.83k|}

stream_memory_open:
   85|    461|{
   86|    461|    mp_assert(len >= 0);
  ------------------
  |  |   41|    461|#define mp_assert assert
  ------------------
   87|       |
   88|    461|    struct stream_open_args sargs = {
   89|    461|        .global = global,
   90|    461|        .url = "memory://",
   91|    461|        .flags = STREAM_READ | STREAM_SILENT | STREAM_ORIGIN_DIRECT,
  ------------------
  |  |   41|    461|#define STREAM_READ               0
  ------------------
                      .flags = STREAM_READ | STREAM_SILENT | STREAM_ORIGIN_DIRECT,
  ------------------
  |  |   44|    461|#define STREAM_SILENT             (1 << 1)
  ------------------
                      .flags = STREAM_READ | STREAM_SILENT | STREAM_ORIGIN_DIRECT,
  ------------------
  |  |   47|    461|#define STREAM_ORIGIN_DIRECT      (1 << 2) // passed from cmdline or loadfile
  ------------------
   92|    461|        .sinfo = &stream_info_memory,
   93|    461|        .special_arg = &(bstr){data, len},
   94|    461|    };
   95|       |
   96|    461|    struct stream *s = NULL;
   97|    461|    stream_create_with_args(&sargs, &s);
   98|    461|    MP_HANDLE_OOM(s);
  ------------------
  |  |  176|    461|#define MP_HANDLE_OOM(x) do {   \
  |  |  177|    461|        void *oom_p_ = (x);     \
  |  |  178|    461|        if (!oom_p_)            \
  |  |  ------------------
  |  |  |  Branch (178:13): [True: 0, False: 461]
  |  |  ------------------
  |  |  179|    461|            abort();            \
  |  |  180|    461|    } while (0)
  |  |  ------------------
  |  |  |  Branch (180:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
   99|    461|    return s;
  100|    461|}
stream_memory.c:open2:
   48|  1.24k|{
   49|  1.24k|    stream->fill_buffer = fill_buffer;
   50|  1.24k|    stream->seek = seek;
   51|  1.24k|    stream->seekable = true;
   52|  1.24k|    stream->get_size = get_size;
   53|       |
   54|  1.24k|    struct priv *p = talloc_zero(stream, struct priv);
  ------------------
  |  |   27|  1.24k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  1.24k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  1.24k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   55|  1.24k|    stream->priv = p;
   56|       |
   57|       |    // Initial data
   58|  1.24k|    bstr data = bstr0(stream->url);
   59|  1.24k|    bool use_hex = bstr_eatstart0(&data, "hex://");
   60|  1.24k|    if (!use_hex)
  ------------------
  |  Branch (60:9): [True: 496, False: 751]
  ------------------
   61|    496|        bstr_eatstart0(&data, "memory://");
   62|       |
   63|  1.24k|    if (args->special_arg)
  ------------------
  |  Branch (63:9): [True: 461, False: 786]
  ------------------
   64|    461|        data = *(bstr *)args->special_arg;
   65|       |
   66|  1.24k|    p->data = bstrdup(stream, data);
   67|       |
   68|  1.24k|    if (use_hex && !bstr_decode_hex(stream, p->data, &p->data)) {
  ------------------
  |  Branch (68:9): [True: 751, False: 496]
  |  Branch (68:20): [True: 41, False: 710]
  ------------------
   69|     41|        MP_FATAL(stream, "Invalid data.\n");
  ------------------
  |  |   84|     41|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     41|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
   70|     41|        return STREAM_ERROR;
  ------------------
  |  |   67|     41|#define STREAM_ERROR 0
  ------------------
   71|     41|    }
   72|       |
   73|  1.20k|    return STREAM_OK;
  ------------------
  |  |   68|  1.20k|#define STREAM_OK    1
  ------------------
   74|  1.24k|}
stream_memory.c:fill_buffer:
   26|  2.64k|{
   27|  2.64k|    struct priv *p = s->priv;
   28|  2.64k|    bstr data = p->data;
   29|  2.64k|    if (s->pos < 0 || s->pos > data.len)
  ------------------
  |  Branch (29:9): [True: 0, False: 2.64k]
  |  Branch (29:23): [True: 0, False: 2.64k]
  ------------------
   30|      0|        return 0;
   31|  2.64k|    len = MPMIN(len, data.len - s->pos);
  ------------------
  |  |   44|  2.64k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 2.64k, False: 0]
  |  |  ------------------
  ------------------
   32|  2.64k|    memcpy(buffer, data.start + s->pos, len);
   33|  2.64k|    return len;
   34|  2.64k|}
stream_memory.c:get_size:
   42|    782|{
   43|    782|    struct priv *p = s->priv;
   44|    782|    return p->data.len;
   45|    782|}

stream_mf.c:mf_stream_open:
   30|      5|{
   31|      5|    stream->demuxer = "mf";
   32|       |
   33|      5|    return STREAM_OK;
  ------------------
  |  |   68|      5|#define STREAM_OK    1
  ------------------
   34|      5|}

stream_mpv.c:open_mpv:
   24|     85|{
   25|     85|    st->demuxer = "mpv";
   26|     85|    return STREAM_OK;
  ------------------
  |  |   68|     85|#define STREAM_OK    1
  ------------------
   27|     85|}

stream_null.c:open_s:
   26|      2|{
   27|      2|    return 1;
   28|      2|}

mp_ass_set_style:
   46|     44|{
   47|     44|    if (!style)
  ------------------
  |  Branch (47:9): [True: 0, False: 44]
  ------------------
   48|      0|        return;
   49|       |
   50|     44|    if (opts->font) {
  ------------------
  |  Branch (50:9): [True: 44, False: 0]
  ------------------
   51|     44|        if (!style->FontName || strcmp(style->FontName, opts->font) != 0) {
  ------------------
  |  Branch (51:13): [True: 34, False: 10]
  |  Branch (51:33): [True: 0, False: 10]
  ------------------
   52|     34|            free(style->FontName);
   53|     34|            style->FontName = strdup(opts->font);
   54|     34|        }
   55|     44|    }
   56|       |
   57|       |    // libass_font_size = FontSize * (window_height / res_y)
   58|       |    // scale translates parameters from PlayResY=720 to res_y
   59|     44|    double scale = res_y / 720.0;
   60|       |
   61|     44|    style->FontSize = opts->font_size * scale;
   62|     44|    style->PrimaryColour = MP_ASS_COLOR(opts->color);
  ------------------
  |  |   39|     44|#define MP_ASS_COLOR(c) MP_ASS_RGBA((c).r, (c).g, (c).b, (c).a)
  |  |  ------------------
  |  |  |  |   36|     44|    (((unsigned)(r) << 24) | ((g) << 16) | ((b) << 8) | (0xFF - (a)))
  |  |  ------------------
  ------------------
   63|     44|    style->SecondaryColour = style->PrimaryColour;
   64|     44|    style->OutlineColour = MP_ASS_COLOR(opts->outline_color);
  ------------------
  |  |   39|     44|#define MP_ASS_COLOR(c) MP_ASS_RGBA((c).r, (c).g, (c).b, (c).a)
  |  |  ------------------
  |  |  |  |   36|     44|    (((unsigned)(r) << 24) | ((g) << 16) | ((b) << 8) | (0xFF - (a)))
  |  |  ------------------
  ------------------
   65|     44|    style->BackColour = MP_ASS_COLOR(opts->back_color);
  ------------------
  |  |   39|     44|#define MP_ASS_COLOR(c) MP_ASS_RGBA((c).r, (c).g, (c).b, (c).a)
  |  |  ------------------
  |  |  |  |   36|     44|    (((unsigned)(r) << 24) | ((g) << 16) | ((b) << 8) | (0xFF - (a)))
  |  |  ------------------
  ------------------
   66|     44|    style->BorderStyle = opts->border_style;
   67|     44|    style->Outline = opts->outline_size * scale;
   68|     44|    style->Shadow = opts->shadow_offset * scale;
   69|     44|    style->Spacing = opts->spacing * scale;
   70|     44|    style->MarginL = opts->margin_x * scale;
   71|     44|    style->MarginR = style->MarginL;
   72|     44|    style->MarginV = opts->margin_y * scale;
   73|     44|    style->ScaleX = 1.;
   74|     44|    style->ScaleY = 1.;
   75|     44|    style->Alignment = 1 + (opts->align_x + 1) + (opts->align_y + 2) % 3 * 4;
   76|     44|#ifdef ASS_JUSTIFY_LEFT
   77|     44|    style->Justify = opts->justify;
   78|     44|#endif
   79|     44|    style->Blur = opts->blur;
   80|     44|    style->Bold = opts->bold;
   81|     44|    style->Italic = opts->italic;
   82|     44|}
mp_ass_configure_fonts:
   86|     34|{
   87|     34|    void *tmp = talloc_new(NULL);
  ------------------
  |  |   40|     34|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|     34|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
   88|     34|    char *default_font = mp_find_config_file(tmp, global, "subfont.ttf");
   89|     34|    char *config       = mp_find_config_file(tmp, global, "fonts.conf");
   90|       |
   91|     34|    if (default_font && !mp_path_exists(default_font))
  ------------------
  |  Branch (91:9): [True: 0, False: 34]
  |  Branch (91:25): [True: 0, False: 0]
  ------------------
   92|      0|        default_font = NULL;
   93|       |
   94|     34|    int font_provider = ASS_FONTPROVIDER_AUTODETECT;
   95|     34|    if (opts->font_provider == 1)
  ------------------
  |  Branch (95:9): [True: 0, False: 34]
  ------------------
   96|      0|        font_provider = ASS_FONTPROVIDER_NONE;
   97|     34|    if (opts->font_provider == 2)
  ------------------
  |  Branch (97:9): [True: 0, False: 34]
  ------------------
   98|      0|        font_provider = ASS_FONTPROVIDER_FONTCONFIG;
   99|       |
  100|     34|    mp_verbose(log, "Setting up fonts...\n");
  ------------------
  |  |   75|     34|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  101|     34|    ass_set_fonts(priv, default_font, opts->font, font_provider, config, 1);
  102|     34|    mp_verbose(log, "Done.\n");
  ------------------
  |  |   75|     34|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  103|       |
  104|     34|    talloc_free(tmp);
  ------------------
  |  |   47|     34|#define talloc_free                     ta_free
  ------------------
  105|     34|}
mp_ass_init:
  132|     34|{
  133|     34|    char *path = opts->fonts_dir && opts->fonts_dir[0] ?
  ------------------
  |  Branch (133:18): [True: 0, False: 34]
  |  Branch (133:37): [True: 0, False: 0]
  ------------------
  134|      0|                 mp_get_user_path(NULL, global, opts->fonts_dir) :
  135|     34|                 mp_find_config_file(NULL, global, "fonts");
  136|     34|    mp_dbg(log, "ASS library version: 0x%x (runtime 0x%x)\n",
  ------------------
  |  |   76|     34|#define mp_dbg(log, ...)        mp_msg(log, MSGL_DEBUG, __VA_ARGS__)
  ------------------
  137|     34|           (unsigned)LIBASS_VERSION, ass_library_version());
  138|     34|    ASS_Library *priv = ass_library_init();
  139|     34|    if (!priv)
  ------------------
  |  Branch (139:9): [True: 0, False: 34]
  ------------------
  140|      0|        abort();
  141|     34|    ass_set_message_cb(priv, message_callback, log);
  142|     34|    if (path)
  ------------------
  |  Branch (142:9): [True: 0, False: 34]
  ------------------
  143|      0|        ass_set_fonts_dir(priv, path);
  144|     34|    talloc_free(path);
  ------------------
  |  |   47|     34|#define talloc_free                     ta_free
  ------------------
  145|     34|    return priv;
  146|     34|}
mp_ass_packer_alloc:
  206|     78|{
  207|     78|    struct mp_ass_packer *p = talloc_zero(ta_parent, struct mp_ass_packer);
  ------------------
  |  |   27|     78|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|     78|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     78|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  208|     78|    p->packer = talloc_zero(p, struct bitmap_packer);
  ------------------
  |  |   27|     78|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|     78|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     78|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  209|     78|    return p;
  210|     78|}
mp_ass_packer_pack:
  341|    156|{
  342|    156|    int format = preferred_osd_format == SUBBITMAP_BGRA ? SUBBITMAP_BGRA
  ------------------
  |  Branch (342:18): [True: 0, False: 156]
  ------------------
  343|    156|                                                        : SUBBITMAP_LIBASS;
  344|       |
  345|    156|    if (p->cached_subs_valid && !image_lists_changed &&
  ------------------
  |  Branch (345:9): [True: 30, False: 126]
  |  Branch (345:33): [True: 22, False: 8]
  ------------------
  346|    156|        p->cached_subs.format == format)
  ------------------
  |  Branch (346:9): [True: 22, False: 0]
  ------------------
  347|     22|    {
  348|     22|        *out = p->cached_subs;
  349|     22|        return;
  350|     22|    }
  351|       |
  352|    134|    *out = (struct sub_bitmaps){.change_id = 1};
  353|    134|    p->cached_subs_valid = false;
  354|       |
  355|    134|    struct sub_bitmaps res = {
  356|    134|        .change_id = image_lists_changed,
  357|    134|        .format = SUBBITMAP_LIBASS,
  358|    134|        .parts = p->cached_parts,
  359|    134|        .video_color_space = video_color_space,
  360|    134|    };
  361|       |
  362|    268|    for (int n = 0; n < num_image_lists; n++) {
  ------------------
  |  Branch (362:21): [True: 134, False: 134]
  ------------------
  363|  1.67k|        for (struct ass_image *img = image_lists[n]; img; img = img->next) {
  ------------------
  |  Branch (363:54): [True: 1.53k, False: 134]
  ------------------
  364|  1.53k|            if (img->w == 0 || img->h == 0)
  ------------------
  |  Branch (364:17): [True: 0, False: 1.53k]
  |  Branch (364:32): [True: 0, False: 1.53k]
  ------------------
  365|      0|                continue;
  366|  1.53k|            MP_TARRAY_GROW(p, p->cached_parts, res.num_parts);
  ------------------
  |  |   96|  1.53k|    do {                                            \
  |  |   97|  1.53k|        size_t nextidx_ = (nextidx);                \
  |  |   98|  1.53k|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  ------------------
  |  |  |  |   84|  1.53k|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  ------------------
  |  |  |  |  |  |   45|  1.53k|#define talloc_get_size                 ta_get_size
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  |  Branch (98:13): [True: 112, False: 1.42k]
  |  |  ------------------
  |  |   99|  1.53k|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  ------------------
  |  |  |  |   88|    112|    do {                                                        \
  |  |  |  |   89|    112|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|    112|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|    112|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|    112|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|    112|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   90|    112|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |   91|    112|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  100|  1.53k|    } while (0)
  |  |  ------------------
  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  367|  1.53k|            res.parts = p->cached_parts;
  368|  1.53k|            struct sub_bitmap *b = &res.parts[res.num_parts];
  369|  1.53k|            b->bitmap = img->bitmap;
  370|  1.53k|            b->stride = img->stride;
  371|  1.53k|            b->libass.color = img->color;
  372|  1.53k|            b->dw = b->w = img->w;
  373|  1.53k|            b->dh = b->h = img->h;
  374|  1.53k|            b->x = img->dst_x;
  375|  1.53k|            b->y = img->dst_y;
  376|  1.53k|            res.num_parts++;
  377|  1.53k|        }
  378|    134|    }
  379|       |
  380|    134|    bool r = false;
  381|    134|    if (format == SUBBITMAP_BGRA) {
  ------------------
  |  Branch (381:9): [True: 0, False: 134]
  ------------------
  382|      0|        r = pack_rgba(p, &res);
  383|    134|    } else {
  384|    134|        r = pack_libass(p, &res);
  385|    134|    }
  386|       |
  387|    134|    if (!r)
  ------------------
  |  Branch (387:9): [True: 96, False: 38]
  ------------------
  388|     96|        return;
  389|       |
  390|     38|    *out = res;
  391|     38|    p->cached_subs = res;
  392|     38|    p->cached_subs.change_id = 0;
  393|     38|    p->cached_subs_valid = true;
  394|     38|}
ass_mp.c:message_callback:
  120|  8.61k|{
  121|  8.61k|    struct mp_log *log = ctx;
  122|  8.61k|    if (!log)
  ------------------
  |  Branch (122:9): [True: 0, False: 8.61k]
  ------------------
  123|      0|        return;
  124|  8.61k|    level = map_ass_level[level];
  125|  8.61k|    mp_msg_va(log, level, format, va);
  126|       |    // libass messages lack trailing \n
  127|  8.61k|    mp_msg(log, level, "\n");
  128|  8.61k|}
ass_mp.c:pack:
  213|    134|{
  214|    134|    packer_set_size(p->packer, res->num_parts);
  215|       |
  216|  1.67k|    for (int n = 0; n < res->num_parts; n++)
  ------------------
  |  Branch (216:21): [True: 1.53k, False: 134]
  ------------------
  217|  1.53k|        p->packer->in[n] = (struct pos){res->parts[n].w, res->parts[n].h};
  218|       |
  219|    134|    if (p->packer->count == 0 || packer_pack(p->packer) < 0)
  ------------------
  |  Branch (219:9): [True: 96, False: 38]
  |  Branch (219:34): [True: 0, False: 38]
  ------------------
  220|     96|        return false;
  221|       |
  222|     38|    struct pos bb[2];
  223|     38|    packer_get_bb(p->packer, bb);
  224|       |
  225|     38|    res->packed_w = bb[1].x;
  226|     38|    res->packed_h = bb[1].y;
  227|       |
  228|     38|    if (!p->cached_img || p->cached_img->w < res->packed_w ||
  ------------------
  |  Branch (228:9): [True: 30, False: 8]
  |  Branch (228:27): [True: 0, False: 8]
  ------------------
  229|     38|                          p->cached_img->h < res->packed_h ||
  ------------------
  |  Branch (229:27): [True: 0, False: 8]
  ------------------
  230|     38|                          p->cached_img->imgfmt != imgfmt)
  ------------------
  |  Branch (230:27): [True: 0, False: 8]
  ------------------
  231|     30|    {
  232|     30|        talloc_free(p->cached_img);
  ------------------
  |  |   47|     30|#define talloc_free                     ta_free
  ------------------
  233|     30|        p->cached_img = mp_image_alloc(imgfmt, p->packer->w, p->packer->h);
  234|     30|        if (!p->cached_img) {
  ------------------
  |  Branch (234:13): [True: 0, False: 30]
  ------------------
  235|      0|            packer_reset(p->packer);
  236|      0|            return false;
  237|      0|        }
  238|     30|        talloc_steal(p, p->cached_img);
  ------------------
  |  |   38|     30|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     30|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  239|     30|    }
  240|       |
  241|     38|    if (!mp_image_make_writeable(p->cached_img)) {
  ------------------
  |  Branch (241:9): [True: 0, False: 38]
  ------------------
  242|      0|        packer_reset(p->packer);
  243|      0|        return false;
  244|      0|    }
  245|       |
  246|     38|    res->packed = p->cached_img;
  247|       |
  248|  1.57k|    for (int n = 0; n < res->num_parts; n++) {
  ------------------
  |  Branch (248:21): [True: 1.53k, False: 38]
  ------------------
  249|  1.53k|        struct sub_bitmap *b = &res->parts[n];
  250|  1.53k|        struct pos pos = p->packer->result[n];
  251|       |
  252|  1.53k|        b->src_x = pos.x;
  253|  1.53k|        b->src_y = pos.y;
  254|  1.53k|    }
  255|       |
  256|     38|    return true;
  257|     38|}
ass_mp.c:pack_libass:
  260|    134|{
  261|    134|    if (!pack(p, res, IMGFMT_Y8))
  ------------------
  |  Branch (261:9): [True: 96, False: 38]
  ------------------
  262|     96|        return false;
  263|       |
  264|  1.57k|    for (int n = 0; n < res->num_parts; n++) {
  ------------------
  |  Branch (264:21): [True: 1.53k, False: 38]
  ------------------
  265|  1.53k|        struct sub_bitmap *b = &res->parts[n];
  266|       |
  267|  1.53k|        int stride = res->packed->stride[0];
  268|  1.53k|        void *pdata =
  269|  1.53k|            (uint8_t *)res->packed->planes[0] + b->src_y * stride + b->src_x;
  270|  1.53k|        memcpy_pic(pdata, b->bitmap, b->w, b->h, stride, b->stride);
  271|       |
  272|  1.53k|        b->bitmap = pdata;
  273|  1.53k|        b->stride = stride;
  274|  1.53k|    }
  275|       |
  276|     38|    return true;
  277|    134|}

mp_draw_sub_alloc:
  845|     30|{
  846|     30|    struct mp_draw_sub_cache *c = talloc_zero(ta_parent, struct mp_draw_sub_cache);
  ------------------
  |  |   27|     30|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|     30|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     30|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  847|     30|    c->global = g;
  848|     30|    return c;
  849|     30|}
mp_draw_sub_bitmaps:
  861|     60|{
  862|     60|    bool ok = false;
  863|       |
  864|       |    // dst must at least be as large as the bounding box, or you may get memory
  865|       |    // corruption.
  866|     60|    mp_assert(dst->w >= sbs_list->w);
  ------------------
  |  |   41|     60|#define mp_assert assert
  ------------------
  867|     60|    mp_assert(dst->h >= sbs_list->h);
  ------------------
  |  |   41|     60|#define mp_assert assert
  ------------------
  868|       |
  869|     60|    if (!check_reinit(p, &dst->params, true))
  ------------------
  |  Branch (869:9): [True: 0, False: 60]
  ------------------
  870|      0|        return false;
  871|       |
  872|     60|    if (p->change_id != sbs_list->change_id) {
  ------------------
  |  Branch (872:9): [True: 60, False: 0]
  ------------------
  873|     60|        p->change_id = sbs_list->change_id;
  874|       |
  875|     60|        clear_rgba_overlay(p);
  876|       |
  877|    120|        for (int n = 0; n < sbs_list->num_items; n++) {
  ------------------
  |  Branch (877:25): [True: 60, False: 60]
  ------------------
  878|     60|            if (!render_sb(p, sbs_list->items[n]))
  ------------------
  |  Branch (878:17): [True: 0, False: 60]
  ------------------
  879|      0|                goto done;
  880|     60|        }
  881|       |
  882|     60|        if (!convert_to_video_overlay(p))
  ------------------
  |  Branch (882:13): [True: 0, False: 60]
  ------------------
  883|      0|            goto done;
  884|     60|    }
  885|       |
  886|     60|    if (p->any_osd) {
  ------------------
  |  Branch (886:9): [True: 60, False: 0]
  ------------------
  887|     60|        struct mp_image *target = dst;
  888|     60|        if (p->premul_tmp) {
  ------------------
  |  Branch (888:13): [True: 0, False: 60]
  ------------------
  889|      0|            if (mp_sws_scale(p->premul, p->premul_tmp, dst) < 0)
  ------------------
  |  Branch (889:17): [True: 0, False: 0]
  ------------------
  890|      0|                goto done;
  891|      0|            target = p->premul_tmp;
  892|      0|        }
  893|       |
  894|     60|        if (!blend_overlay_with_video(p, target))
  ------------------
  |  Branch (894:13): [True: 0, False: 60]
  ------------------
  895|      0|            goto done;
  896|       |
  897|     60|        if (target != dst) {
  ------------------
  |  Branch (897:13): [True: 0, False: 60]
  ------------------
  898|      0|            if (mp_sws_scale(p->unpremul, dst, p->premul_tmp) < 0)
  ------------------
  |  Branch (898:17): [True: 0, False: 0]
  ------------------
  899|      0|                goto done;
  900|      0|        }
  901|     60|    }
  902|       |
  903|     60|    ok = true;
  904|       |
  905|     60|done:
  906|     60|    return ok;
  907|     60|}
draw_bmp.c:reinit_to_video:
  524|     60|{
  525|     60|    struct mp_image_params *params = &p->params;
  526|     60|    mp_image_params_guess_csp(params);
  527|       |
  528|     60|    bool need_premul = params->repr.alpha != PL_ALPHA_PREMULTIPLIED &&
  ------------------
  |  Branch (528:24): [True: 60, False: 0]
  ------------------
  529|     60|        (mp_imgfmt_get_desc(params->imgfmt).flags & MP_IMGFLAG_ALPHA);
  ------------------
  |  |   52|     60|#define MP_IMGFLAG_ALPHA        (1 << 5)
  ------------------
  |  Branch (529:9): [True: 0, False: 60]
  ------------------
  530|       |
  531|       |    // Intermediate format for video_overlay. Requirements:
  532|       |    //  - same subsampling as video
  533|       |    //  - uses video colorspace
  534|       |    //  - has alpha
  535|       |    //  - repacker support (to the format used in p->blend_line)
  536|       |    //  - probably 8 bit per component rather than something wasteful or strange
  537|     60|    struct mp_regular_imgfmt vfdesc = {0};
  538|       |
  539|     60|    int rflags = REPACK_CREATE_EXPAND_8BIT;
  540|     60|    bool use_shortcut = false;
  541|       |
  542|     60|    p->video_to_f32 = mp_repack_create_planar(params->imgfmt, false, rflags);
  543|     60|    talloc_steal(p, p->video_to_f32);
  ------------------
  |  |   38|     60|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     60|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  544|     60|    if (!p->video_to_f32)
  ------------------
  |  Branch (544:9): [True: 0, False: 60]
  ------------------
  545|      0|        return false;
  546|     60|    mp_get_regular_imgfmt(&vfdesc, mp_repack_get_format_dst(p->video_to_f32));
  547|     60|    mp_assert(vfdesc.num_planes); // must have succeeded
  ------------------
  |  |   41|     60|#define mp_assert assert
  ------------------
  548|       |
  549|     60|    if (params->repr.sys == PL_COLOR_SYSTEM_RGB && vfdesc.num_planes >= 3) {
  ------------------
  |  Branch (549:9): [True: 60, False: 0]
  |  Branch (549:52): [True: 60, False: 0]
  ------------------
  550|     60|        use_shortcut = true;
  551|       |
  552|     60|        if (vfdesc.component_type == MP_COMPONENT_TYPE_UINT &&
  ------------------
  |  Branch (552:13): [True: 60, False: 0]
  ------------------
  553|     60|            vfdesc.component_size == 1 && vfdesc.component_pad == 0)
  ------------------
  |  Branch (553:13): [True: 60, False: 0]
  |  Branch (553:43): [True: 60, False: 0]
  ------------------
  554|     60|            p->blend_line = blend_line_u8;
  555|     60|    }
  556|       |
  557|       |    // If no special blender is available, blend in float.
  558|     60|    if (!p->blend_line) {
  ------------------
  |  Branch (558:9): [True: 0, False: 60]
  ------------------
  559|      0|        TA_FREEP(&p->video_to_f32);
  ------------------
  |  |   81|      0|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|      0|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  560|       |
  561|      0|        rflags |= REPACK_CREATE_PLANAR_F32;
  562|       |
  563|      0|        p->video_to_f32 = mp_repack_create_planar(params->imgfmt, false, rflags);
  564|      0|        talloc_steal(p, p->video_to_f32);
  ------------------
  |  |   38|      0|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  565|      0|        if (!p->video_to_f32)
  ------------------
  |  Branch (565:13): [True: 0, False: 0]
  ------------------
  566|      0|            return false;
  567|       |
  568|      0|        mp_get_regular_imgfmt(&vfdesc, mp_repack_get_format_dst(p->video_to_f32));
  569|      0|        mp_assert(vfdesc.component_type == MP_COMPONENT_TYPE_FLOAT);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  570|       |
  571|      0|        p->blend_line = blend_line_f32;
  572|      0|    }
  573|       |
  574|     60|    p->scale_in_tiles = SCALE_IN_TILES;
  ------------------
  |  |   54|     60|#define SCALE_IN_TILES 1
  ------------------
  575|       |
  576|     60|    int vid_f32_fmt = mp_repack_get_format_dst(p->video_to_f32);
  577|       |
  578|     60|    p->video_from_f32 = mp_repack_create_planar(params->imgfmt, true, rflags);
  579|     60|    talloc_steal(p, p->video_from_f32);
  ------------------
  |  |   38|     60|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     60|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  580|     60|    if (!p->video_from_f32)
  ------------------
  |  Branch (580:9): [True: 0, False: 60]
  ------------------
  581|      0|        return false;
  582|       |
  583|     60|    mp_assert(mp_repack_get_format_dst(p->video_to_f32) ==
  ------------------
  |  |   41|     60|#define mp_assert assert
  ------------------
  584|     60|           mp_repack_get_format_src(p->video_from_f32));
  585|       |
  586|     60|    int overlay_fmt = 0;
  587|     60|    if (use_shortcut) {
  ------------------
  |  Branch (587:9): [True: 60, False: 0]
  ------------------
  588|       |        // No point in doing anything fancy.
  589|     60|        overlay_fmt = IMGFMT_BGRA;
  590|     60|        p->scale_in_tiles = false;
  591|     60|    } else {
  592|      0|        struct mp_regular_imgfmt odesc = vfdesc;
  593|       |        // Just use 8 bit as well (should be fine, may use less memory).
  594|      0|        odesc.component_type = MP_COMPONENT_TYPE_UINT;
  595|      0|        odesc.component_size = 1;
  596|      0|        odesc.component_pad = 0;
  597|       |
  598|       |        // Ensure there's alpha.
  599|      0|        if (odesc.planes[odesc.num_planes - 1].components[0] != 4) {
  ------------------
  |  Branch (599:13): [True: 0, False: 0]
  ------------------
  600|      0|            if (odesc.num_planes >= 4)
  ------------------
  |  Branch (600:17): [True: 0, False: 0]
  ------------------
  601|      0|                return false; // wat
  602|      0|            odesc.planes[odesc.num_planes++] =
  603|      0|                (struct mp_regular_imgfmt_plane){1, {4}};
  604|      0|        }
  605|       |
  606|      0|        overlay_fmt = mp_find_regular_imgfmt(&odesc);
  607|      0|        p->scale_in_tiles = odesc.chroma_xs || odesc.chroma_ys;
  ------------------
  |  Branch (607:29): [True: 0, False: 0]
  |  Branch (607:48): [True: 0, False: 0]
  ------------------
  608|      0|    }
  609|     60|    if (!overlay_fmt)
  ------------------
  |  Branch (609:9): [True: 0, False: 60]
  ------------------
  610|      0|        return false;
  611|       |
  612|     60|    p->overlay_to_f32 = mp_repack_create_planar(overlay_fmt, false, rflags);
  613|     60|    talloc_steal(p, p->overlay_to_f32);
  ------------------
  |  |   38|     60|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     60|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  614|     60|    if (!p->overlay_to_f32)
  ------------------
  |  Branch (614:9): [True: 0, False: 60]
  ------------------
  615|      0|        return false;
  616|       |
  617|     60|    int render_fmt = mp_repack_get_format_dst(p->overlay_to_f32);
  618|       |
  619|     60|    struct mp_regular_imgfmt ofdesc = {0};
  620|     60|    mp_get_regular_imgfmt(&ofdesc, render_fmt);
  621|       |
  622|     60|    if (ofdesc.planes[ofdesc.num_planes - 1].components[0] != 4)
  ------------------
  |  Branch (622:9): [True: 0, False: 60]
  ------------------
  623|      0|        return false;
  624|       |
  625|       |    // The formats must be the same, minus possible lack of alpha in vfdesc.
  626|     60|    if (ofdesc.num_planes != vfdesc.num_planes &&
  ------------------
  |  Branch (626:9): [True: 60, False: 0]
  ------------------
  627|     60|        ofdesc.num_planes - 1 != vfdesc.num_planes)
  ------------------
  |  Branch (627:9): [True: 0, False: 60]
  ------------------
  628|      0|        return false;
  629|    240|    for (int n = 0; n < vfdesc.num_planes; n++) {
  ------------------
  |  Branch (629:21): [True: 180, False: 60]
  ------------------
  630|    180|        if (vfdesc.planes[n].components[0] != ofdesc.planes[n].components[0])
  ------------------
  |  Branch (630:13): [True: 0, False: 180]
  ------------------
  631|      0|            return false;
  632|    180|    }
  633|       |
  634|     60|    p->align_x = mp_repack_get_align_x(p->video_to_f32);
  635|     60|    p->align_y = mp_repack_get_align_y(p->video_to_f32);
  636|       |
  637|     60|    mp_assert(p->align_x >= mp_repack_get_align_x(p->overlay_to_f32));
  ------------------
  |  |   41|     60|#define mp_assert assert
  ------------------
  638|     60|    mp_assert(p->align_y >= mp_repack_get_align_y(p->overlay_to_f32));
  ------------------
  |  |   41|     60|#define mp_assert assert
  ------------------
  639|       |
  640|     60|    if (p->align_x > SLICE_W || p->align_y > TILE_H)
  ------------------
  |  |   48|    120|#define SLICE_W 256u
  ------------------
                  if (p->align_x > SLICE_W || p->align_y > TILE_H)
  ------------------
  |  |   55|     60|#define TILE_H 4u
  ------------------
  |  Branch (640:9): [True: 0, False: 60]
  |  Branch (640:33): [True: 0, False: 60]
  ------------------
  641|      0|        return false;
  642|       |
  643|     60|    p->w = MP_ALIGN_UP(params->w, p->align_x);
  ------------------
  |  |   52|     60|#define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
  ------------------
  644|     60|    int slice_h = p->align_y;
  645|     60|    p->h = MP_ALIGN_UP(params->h, slice_h);
  ------------------
  |  |   52|     60|#define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
  ------------------
  646|       |
  647|       |    // Size of the overlay. If scaling in tiles, round up to tiles, so we don't
  648|       |    // need to reinit the scale for right/bottom tiles.
  649|     60|    int w = p->w;
  650|     60|    int h = p->h;
  651|     60|    if (p->scale_in_tiles) {
  ------------------
  |  Branch (651:9): [True: 0, False: 60]
  ------------------
  652|      0|        w = MP_ALIGN_UP(w, SLICE_W);
  ------------------
  |  |   52|      0|#define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
  ------------------
  653|      0|        h = MP_ALIGN_UP(h, TILE_H);
  ------------------
  |  |   52|      0|#define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
  ------------------
  654|      0|    }
  655|       |
  656|     60|    p->rgba_overlay = talloc_steal(p, mp_image_alloc(IMGFMT_BGRA, w, h));
  ------------------
  |  |   38|     60|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     60|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  657|     60|    p->overlay_tmp = talloc_steal(p, mp_image_alloc(render_fmt, SLICE_W, slice_h));
  ------------------
  |  |   38|     60|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     60|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  658|     60|    p->video_tmp = talloc_steal(p, mp_image_alloc(vid_f32_fmt, SLICE_W, slice_h));
  ------------------
  |  |   38|     60|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     60|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  659|     60|    if (!p->rgba_overlay || !p->overlay_tmp || !p->video_tmp)
  ------------------
  |  Branch (659:9): [True: 0, False: 60]
  |  Branch (659:29): [True: 0, False: 60]
  |  Branch (659:48): [True: 0, False: 60]
  ------------------
  660|      0|        return false;
  661|       |
  662|     60|    mp_image_params_guess_csp(&p->rgba_overlay->params);
  663|     60|    p->rgba_overlay->params.repr.alpha = PL_ALPHA_PREMULTIPLIED;
  664|       |
  665|     60|    p->overlay_tmp->params.repr = params->repr;
  666|     60|    p->overlay_tmp->params.color = params->color;
  667|     60|    p->video_tmp->params.repr = params->repr;
  668|     60|    p->video_tmp->params.color = params->color;
  669|       |
  670|     60|    if (p->rgba_overlay->imgfmt == overlay_fmt) {
  ------------------
  |  Branch (670:9): [True: 60, False: 0]
  ------------------
  671|     60|        if (!repack_config_buffers(p->overlay_to_f32, 0, p->overlay_tmp,
  ------------------
  |  Branch (671:13): [True: 0, False: 60]
  ------------------
  672|     60|                                   0, p->rgba_overlay, NULL))
  673|      0|            return false;
  674|     60|    } else {
  675|       |        // Generally non-RGB.
  676|      0|        p->video_overlay = talloc_steal(p, mp_image_alloc(overlay_fmt, w, h));
  ------------------
  |  |   38|      0|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  677|      0|        if (!p->video_overlay)
  ------------------
  |  Branch (677:13): [True: 0, False: 0]
  ------------------
  678|      0|            return false;
  679|       |
  680|      0|        p->video_overlay->params.repr = params->repr;
  681|      0|        p->video_overlay->params.color = params->color;
  682|      0|        p->video_overlay->params.chroma_location = params->chroma_location;
  683|      0|        p->video_overlay->params.repr.alpha = PL_ALPHA_PREMULTIPLIED;
  684|       |
  685|      0|        if (p->scale_in_tiles)
  ------------------
  |  Branch (685:13): [True: 0, False: 0]
  ------------------
  686|      0|            p->video_overlay->params.chroma_location = PL_CHROMA_CENTER;
  687|       |
  688|      0|        p->rgba_to_overlay = alloc_scaler(p);
  689|      0|        p->rgba_to_overlay->allow_zimg = true;
  690|      0|        if (!mp_sws_supports_formats(p->rgba_to_overlay,
  ------------------
  |  Branch (690:13): [True: 0, False: 0]
  ------------------
  691|      0|                            p->video_overlay->imgfmt, p->rgba_overlay->imgfmt))
  692|      0|            return false;
  693|       |
  694|      0|        if (!repack_config_buffers(p->overlay_to_f32, 0, p->overlay_tmp,
  ------------------
  |  Branch (694:13): [True: 0, False: 0]
  ------------------
  695|      0|                                   0, p->video_overlay, NULL))
  696|      0|            return false;
  697|       |
  698|       |        // Setup a scaled alpha plane if chroma-subsampling is present.
  699|      0|        int xs = p->video_overlay->fmt.chroma_xs;
  700|      0|        int ys = p->video_overlay->fmt.chroma_ys;
  701|      0|        if (xs || ys) {
  ------------------
  |  Branch (701:13): [True: 0, False: 0]
  |  Branch (701:19): [True: 0, False: 0]
  ------------------
  702|       |            // Require float so format selection becomes simpler (maybe).
  703|      0|            mp_assert(rflags & REPACK_CREATE_PLANAR_F32);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  704|       |
  705|       |            // For extracting the alpha plane, construct a gray format that is
  706|       |            // compatible with the alpha one.
  707|      0|            struct mp_regular_imgfmt odesc = {0};
  708|      0|            mp_get_regular_imgfmt(&odesc, overlay_fmt);
  709|      0|            mp_assert(odesc.component_size);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  710|      0|            int aplane = odesc.num_planes - 1;
  711|      0|            mp_assert(odesc.planes[aplane].num_components == 1);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  712|      0|            mp_assert(odesc.planes[aplane].components[0] == 4);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  713|      0|            struct mp_regular_imgfmt cadesc = odesc;
  714|      0|            cadesc.num_planes = 1;
  715|      0|            cadesc.planes[0] = (struct mp_regular_imgfmt_plane){1, {1}};
  716|      0|            cadesc.chroma_xs = cadesc.chroma_ys = 0;
  717|       |
  718|      0|            int calpha_fmt = mp_find_regular_imgfmt(&cadesc);
  719|      0|            if (!calpha_fmt)
  ------------------
  |  Branch (719:17): [True: 0, False: 0]
  ------------------
  720|      0|                return false;
  721|       |
  722|       |            // Unscaled alpha plane from p->video_overlay.
  723|      0|            p->alpha_overlay = talloc_zero(p, struct mp_image);
  ------------------
  |  |   27|      0|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|      0|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  724|      0|            mp_image_setfmt(p->alpha_overlay, calpha_fmt);
  725|      0|            mp_image_set_size(p->alpha_overlay, w, h);
  726|      0|            p->alpha_overlay->planes[0] = p->video_overlay->planes[aplane];
  727|      0|            p->alpha_overlay->stride[0] = p->video_overlay->stride[aplane];
  728|       |
  729|       |            // Full range gray always has the same range as alpha.
  730|      0|            p->alpha_overlay->params.repr.levels = PL_COLOR_LEVELS_FULL;
  731|      0|            mp_image_params_guess_csp(&p->alpha_overlay->params);
  732|       |
  733|      0|            p->calpha_overlay =
  734|      0|                talloc_steal(p, mp_image_alloc(calpha_fmt, w >> xs, h >> ys));
  ------------------
  |  |   38|      0|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  735|      0|            if (!p->calpha_overlay)
  ------------------
  |  Branch (735:17): [True: 0, False: 0]
  ------------------
  736|      0|                return false;
  737|      0|            p->calpha_overlay->params.repr = p->alpha_overlay->params.repr;
  738|      0|            p->calpha_overlay->params.color = p->alpha_overlay->params.color;
  739|       |
  740|      0|            p->calpha_to_f32 = mp_repack_create_planar(calpha_fmt, false, rflags);
  741|      0|            talloc_steal(p, p->calpha_to_f32);
  ------------------
  |  |   38|      0|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  742|      0|            if (!p->calpha_to_f32)
  ------------------
  |  Branch (742:17): [True: 0, False: 0]
  ------------------
  743|      0|                return false;
  744|       |
  745|      0|            int af32_fmt = mp_repack_get_format_dst(p->calpha_to_f32);
  746|      0|            p->calpha_tmp = talloc_steal(p, mp_image_alloc(af32_fmt, SLICE_W, 1));
  ------------------
  |  |   38|      0|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  747|      0|            if (!p->calpha_tmp)
  ------------------
  |  Branch (747:17): [True: 0, False: 0]
  ------------------
  748|      0|                return false;
  749|       |
  750|      0|            if (!repack_config_buffers(p->calpha_to_f32, 0, p->calpha_tmp,
  ------------------
  |  Branch (750:17): [True: 0, False: 0]
  ------------------
  751|      0|                                       0, p->calpha_overlay, NULL))
  752|      0|                return false;
  753|       |
  754|      0|            p->alpha_to_calpha = alloc_scaler(p);
  755|      0|            if (!mp_sws_supports_formats(p->alpha_to_calpha,
  ------------------
  |  Branch (755:17): [True: 0, False: 0]
  ------------------
  756|      0|                                         calpha_fmt, calpha_fmt))
  757|      0|                return false;
  758|      0|        }
  759|      0|    }
  760|       |
  761|     60|    if (need_premul) {
  ------------------
  |  Branch (761:9): [True: 0, False: 60]
  ------------------
  762|      0|        p->premul = alloc_scaler(p);
  763|      0|        p->unpremul = alloc_scaler(p);
  764|      0|        p->premul_tmp = mp_image_alloc(params->imgfmt, params->w, params->h);
  765|      0|        talloc_steal(p, p->premul_tmp);
  ------------------
  |  |   38|      0|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  766|      0|        if (!p->premul_tmp)
  ------------------
  |  Branch (766:13): [True: 0, False: 0]
  ------------------
  767|      0|            return false;
  768|      0|        mp_image_set_params(p->premul_tmp, params);
  769|      0|        p->premul_tmp->params.repr.alpha = PL_ALPHA_PREMULTIPLIED;
  770|       |
  771|       |        // Only zimg supports this.
  772|      0|        p->premul->force_scaler = MP_SWS_ZIMG;
  773|      0|        p->unpremul->force_scaler = MP_SWS_ZIMG;
  774|      0|    }
  775|       |
  776|     60|    init_general(p);
  777|       |
  778|     60|    return true;
  779|     60|}
draw_bmp.c:blend_line_u8:
  120|  21.4k|{
  121|  21.4k|    uint8_t *dst_i = dst;
  122|  21.4k|    uint8_t *src_i = src;
  123|  21.4k|    uint8_t *src_a_i = src_a;
  124|       |
  125|  5.51M|    for (int x = 0; x < w; x++)
  ------------------
  |  Branch (125:21): [True: 5.49M, False: 21.4k]
  ------------------
  126|  5.49M|        dst_i[x] = src_i[x] + dst_i[x] * (255u - src_a_i[x]) / 255u;
  127|  21.4k|}
draw_bmp.c:alloc_scaler:
  505|     60|{
  506|     60|    struct mp_sws_context *s = mp_sws_alloc(p);
  507|     60|    mp_sws_enable_cmdline_opts(s, p->global);
  508|     60|    return s;
  509|     60|}
draw_bmp.c:init_general:
  512|     60|{
  513|     60|    p->sub_scale = alloc_scaler(p);
  514|       |
  515|     60|    p->s_w = MP_ALIGN_UP(p->rgba_overlay->w, SLICE_W) / SLICE_W;
  ------------------
  |  |   52|     60|#define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
  ------------------
                  p->s_w = MP_ALIGN_UP(p->rgba_overlay->w, SLICE_W) / SLICE_W;
  ------------------
  |  |   48|     60|#define SLICE_W 256u
  ------------------
  516|       |
  517|     60|    p->slices = talloc_zero_array(p, struct slice, p->s_w * p->rgba_overlay->h);
  ------------------
  |  |   30|     60|#define talloc_zero_array               ta_xznew_array
  |  |  ------------------
  |  |  |  |  136|     60|#define ta_xznew_array(...)             ta_oom_g(ta_znew_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     60|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  518|       |
  519|     60|    mp_image_clear(p->rgba_overlay, 0, 0, p->w, p->h);
  520|     60|    clear_rgba_overlay(p);
  521|     60|}
draw_bmp.c:check_reinit:
  816|     60|{
  817|     60|    if (!mp_image_params_equal(&p->params, params) || !p->rgba_overlay) {
  ------------------
  |  Branch (817:9): [True: 60, False: 0]
  |  Branch (817:55): [True: 0, False: 0]
  ------------------
  818|     60|        talloc_free_children(p);
  ------------------
  |  |   46|     60|#define talloc_free_children            ta_free_children
  ------------------
  819|     60|        *p = (struct mp_draw_sub_cache){.global = p->global, .params = *params};
  820|     60|        if (!(to_video ? reinit_to_video(p) : reinit_to_overlay(p))) {
  ------------------
  |  Branch (820:13): [True: 0, False: 60]
  |  Branch (820:15): [True: 60, False: 0]
  ------------------
  821|      0|            talloc_free_children(p);
  ------------------
  |  |   46|      0|#define talloc_free_children            ta_free_children
  ------------------
  822|      0|            *p = (struct mp_draw_sub_cache){.global = p->global};
  823|      0|            return false;
  824|      0|        }
  825|     60|    }
  826|     60|    return true;
  827|     60|}
draw_bmp.c:clear_rgba_overlay:
  478|    120|{
  479|    120|    mp_assert(p->rgba_overlay->imgfmt == IMGFMT_BGRA);
  ------------------
  |  |   41|    120|#define mp_assert assert
  ------------------
  480|       |
  481|  21.7k|    for (int y = 0; y < p->rgba_overlay->h; y++) {
  ------------------
  |  Branch (481:21): [True: 21.6k, False: 120]
  ------------------
  482|  21.6k|        uint32_t *px = mp_image_pixel_ptr(p->rgba_overlay, 0, 0, y);
  483|  21.6k|        struct slice *line = &p->slices[y * p->s_w];
  484|       |
  485|  64.8k|        for (int sx = 0; sx < p->s_w; sx++) {
  ------------------
  |  Branch (485:26): [True: 43.2k, False: 21.6k]
  ------------------
  486|  43.2k|            struct slice *s = &line[sx];
  487|       |
  488|       |            // Ensure this final slice doesn't extend beyond the width of p->s_w
  489|  43.2k|            if (s->x1 == SLICE_W && sx == p->s_w - 1 && y == p->rgba_overlay->h - 1)
  ------------------
  |  |   48|  86.4k|#define SLICE_W 256u
  ------------------
  |  Branch (489:17): [True: 0, False: 43.2k]
  |  Branch (489:37): [True: 0, False: 0]
  |  Branch (489:57): [True: 0, False: 0]
  ------------------
  490|      0|                s->x1 = MPMIN(p->w - ((p->s_w - 1) * SLICE_W), s->x1);
  ------------------
  |  |   44|      0|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  491|       |
  492|  43.2k|            if (s->x0 <= s->x1) {
  ------------------
  |  Branch (492:17): [True: 21.6k, False: 21.6k]
  ------------------
  493|  21.6k|                memset(px + s->x0, 0, (s->x1 - s->x0) * 4);
  494|  21.6k|                *s = (struct slice){SLICE_W, 0};
  ------------------
  |  |   48|  21.6k|#define SLICE_W 256u
  ------------------
  495|  21.6k|            }
  496|       |
  497|  43.2k|            px += SLICE_W;
  ------------------
  |  |   48|  43.2k|#define SLICE_W 256u
  ------------------
  498|  43.2k|        }
  499|  21.6k|    }
  500|       |
  501|    120|    p->any_osd = false;
  502|    120|}
draw_bmp.c:render_sb:
  463|     60|{
  464|     60|    struct part *part = &p->parts[sb->render_index];
  465|       |
  466|     60|    switch (sb->format) {
  ------------------
  |  Branch (466:13): [True: 0, False: 60]
  ------------------
  467|     60|    case SUBBITMAP_LIBASS:
  ------------------
  |  Branch (467:5): [True: 60, False: 0]
  ------------------
  468|     60|        render_ass(p, sb);
  469|     60|        return true;
  470|      0|    case SUBBITMAP_BGRA:
  ------------------
  |  Branch (470:5): [True: 0, False: 60]
  ------------------
  471|      0|        return render_rgba(p, part, sb);
  472|     60|    }
  473|       |
  474|      0|    return false;
  475|     60|}
draw_bmp.c:render_ass:
  326|     60|{
  327|     60|    mp_assert(sb->format == SUBBITMAP_LIBASS);
  ------------------
  |  |   41|     60|#define mp_assert assert
  ------------------
  328|       |
  329|  2.19k|    for (int i = 0; i < sb->num_parts; i++) {
  ------------------
  |  Branch (329:21): [True: 2.13k, False: 60]
  ------------------
  330|  2.13k|        struct sub_bitmap *s = &sb->parts[i];
  331|       |
  332|  2.13k|        draw_ass_rgba(mp_image_pixel_ptr(p->rgba_overlay, 0, s->x, s->y),
  333|  2.13k|                      p->rgba_overlay->stride[0], s->bitmap, s->stride,
  334|  2.13k|                      s->w, s->h, s->libass.color);
  335|       |
  336|  2.13k|        mark_rect(p, s->x, s->y, s->x + s->w, s->y + s->h);
  337|  2.13k|    }
  338|     60|}
draw_bmp.c:draw_ass_rgba:
  298|  2.13k|{
  299|  2.13k|    const unsigned int r = (color >> 24) & 0xff;
  300|  2.13k|    const unsigned int g = (color >> 16) & 0xff;
  301|  2.13k|    const unsigned int b = (color >>  8) & 0xff;
  302|  2.13k|    const unsigned int a = 0xff - (color & 0xff);
  303|       |
  304|  36.3k|    for (int y = 0; y < h; y++) {
  ------------------
  |  Branch (304:21): [True: 34.2k, False: 2.13k]
  ------------------
  305|  34.2k|        uint32_t *dstrow = (uint32_t *) dst;
  306|  1.35M|        for (int x = 0; x < w; x++) {
  ------------------
  |  Branch (306:25): [True: 1.32M, False: 34.2k]
  ------------------
  307|  1.32M|            const unsigned int v = src[x];
  308|  1.32M|            unsigned int aa = a * v;
  309|  1.32M|            uint32_t dstpix = dstrow[x];
  310|  1.32M|            unsigned int dstb =  dstpix        & 0xFF;
  311|  1.32M|            unsigned int dstg = (dstpix >>  8) & 0xFF;
  312|  1.32M|            unsigned int dstr = (dstpix >> 16) & 0xFF;
  313|  1.32M|            unsigned int dsta = (dstpix >> 24) & 0xFF;
  314|  1.32M|            dstb = (v * b * a   + dstb * (255 * 255 - aa)) / (255 * 255);
  315|  1.32M|            dstg = (v * g * a   + dstg * (255 * 255 - aa)) / (255 * 255);
  316|  1.32M|            dstr = (v * r * a   + dstr * (255 * 255 - aa)) / (255 * 255);
  317|  1.32M|            dsta = (aa * 255    + dsta * (255 * 255 - aa)) / (255 * 255);
  318|  1.32M|            dstrow[x] = dstb | (dstg << 8) | (dstr << 16) | (dsta << 24);
  319|  1.32M|        }
  320|  34.2k|        dst += dst_stride;
  321|  34.2k|        src += src_stride;
  322|  34.2k|    }
  323|  2.13k|}
draw_bmp.c:mark_rect:
  254|  2.13k|{
  255|  2.13k|    x0 = MP_ALIGN_DOWN(x0, p->align_x);
  ------------------
  |  |   53|  2.13k|#define MP_ALIGN_DOWN(x, align) ((x) & ~((align) - 1))
  ------------------
  256|  2.13k|    y0 = MP_ALIGN_DOWN(y0, p->align_y);
  ------------------
  |  |   53|  2.13k|#define MP_ALIGN_DOWN(x, align) ((x) & ~((align) - 1))
  ------------------
  257|  2.13k|    x1 = MP_ALIGN_UP(x1, p->align_x);
  ------------------
  |  |   52|  2.13k|#define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
  ------------------
  258|  2.13k|    y1 = MP_ALIGN_UP(y1, p->align_y);
  ------------------
  |  |   52|  2.13k|#define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
  ------------------
  259|       |
  260|  2.13k|    mp_assert(x0 >= 0 && x0 <= x1 && x1 <= p->w);
  ------------------
  |  |   41|  2.13k|#define mp_assert assert
  ------------------
  261|  2.13k|    mp_assert(y0 >= 0 && y0 <= y1 && y1 <= p->h);
  ------------------
  |  |   41|  2.13k|#define mp_assert assert
  ------------------
  262|       |
  263|  2.13k|    const int sx0 = x0 / SLICE_W;
  ------------------
  |  |   48|  2.13k|#define SLICE_W 256u
  ------------------
  264|  2.13k|    const int sx1 = MPMIN(x1 / SLICE_W, p->s_w - 1);
  ------------------
  |  |   44|  2.13k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 2.13k]
  |  |  ------------------
  ------------------
  265|       |
  266|  36.3k|    for (int y = y0; y < y1; y++) {
  ------------------
  |  Branch (266:22): [True: 34.2k, False: 2.13k]
  ------------------
  267|  34.2k|        struct slice *line = &p->slices[y * p->s_w];
  268|       |
  269|  34.2k|        struct slice *s0 = &line[sx0];
  270|  34.2k|        struct slice *s1 = &line[sx1];
  271|       |
  272|  34.2k|        s0->x0 = MPMIN(s0->x0, x0 % SLICE_W);
  ------------------
  |  |   44|  34.2k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 8.79k, False: 25.4k]
  |  |  ------------------
  ------------------
  273|  34.2k|        s1->x1 = MPMAX(s1->x1, ((x1 - 1) % SLICE_W) + 1);
  ------------------
  |  |   43|  34.2k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 17.7k, False: 16.4k]
  |  |  ------------------
  ------------------
  274|       |
  275|  34.2k|        if (s0 != s1) {
  ------------------
  |  Branch (275:13): [True: 1.04k, False: 33.1k]
  ------------------
  276|  1.04k|            s0->x1 = SLICE_W;
  ------------------
  |  |   48|  1.04k|#define SLICE_W 256u
  ------------------
  277|  1.04k|            s1->x0 = 0;
  278|       |
  279|  1.04k|            for (int x = sx0 + 1; x < sx1; x++) {
  ------------------
  |  Branch (279:35): [True: 0, False: 1.04k]
  ------------------
  280|      0|                struct slice *s = &line[x];
  281|      0|                s->x0 = 0;
  282|      0|                s->x1 = SLICE_W;
  ------------------
  |  |   48|      0|#define SLICE_W 256u
  ------------------
  283|      0|            }
  284|  1.04k|        }
  285|       |
  286|       |        // Ensure the very last slice does not extend
  287|       |        // beyond the total width.
  288|  34.2k|        struct slice *last_s = &line[p->s_w - 1];
  289|  34.2k|        last_s->x1 = MPMIN(p->w - ((p->s_w - 1) * SLICE_W), last_s->x1);
  ------------------
  |  |   44|  34.2k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 29.3k, False: 4.85k]
  |  |  ------------------
  ------------------
  290|       |
  291|  34.2k|        p->any_osd = true;
  292|  34.2k|    }
  293|  2.13k|}
draw_bmp.c:convert_to_video_overlay:
  219|     60|{
  220|     60|    if (!p->video_overlay)
  ------------------
  |  Branch (220:9): [True: 60, False: 0]
  ------------------
  221|     60|        return true;
  222|       |
  223|      0|    if (p->scale_in_tiles) {
  ------------------
  |  Branch (223:9): [True: 0, False: 0]
  ------------------
  224|      0|        int t_h = p->rgba_overlay->h / TILE_H;
  ------------------
  |  |   55|      0|#define TILE_H 4u
  ------------------
  225|      0|        for (int ty = 0; ty < t_h; ty++) {
  ------------------
  |  Branch (225:26): [True: 0, False: 0]
  ------------------
  226|      0|            for (int sx = 0; sx < p->s_w; sx++) {
  ------------------
  |  Branch (226:30): [True: 0, False: 0]
  ------------------
  227|      0|                struct slice *s = &p->slices[ty * TILE_H * p->s_w + sx];
  ------------------
  |  |   55|      0|#define TILE_H 4u
  ------------------
  228|      0|                bool pixels_set = false;
  229|      0|                for (int y = 0; y < TILE_H; y++) {
  ------------------
  |  |   55|      0|#define TILE_H 4u
  ------------------
  |  Branch (229:33): [True: 0, False: 0]
  ------------------
  230|      0|                    if (s[0].x0 < s[0].x1) {
  ------------------
  |  Branch (230:25): [True: 0, False: 0]
  ------------------
  231|      0|                        pixels_set = true;
  232|      0|                        break;
  233|      0|                    }
  234|      0|                    s += p->s_w;
  235|      0|                }
  236|      0|                if (!pixels_set)
  ------------------
  |  Branch (236:21): [True: 0, False: 0]
  ------------------
  237|      0|                    continue;
  238|      0|                if (!convert_overlay_part(p, sx * SLICE_W, ty * TILE_H,
  ------------------
  |  |   48|      0|#define SLICE_W 256u
  ------------------
                              if (!convert_overlay_part(p, sx * SLICE_W, ty * TILE_H,
  ------------------
  |  |   55|      0|#define TILE_H 4u
  ------------------
  |  Branch (238:21): [True: 0, False: 0]
  ------------------
  239|      0|                                          SLICE_W, TILE_H))
  ------------------
  |  |   48|      0|#define SLICE_W 256u
  ------------------
                                                        SLICE_W, TILE_H))
  ------------------
  |  |   55|      0|#define TILE_H 4u
  ------------------
  240|      0|                    return false;
  241|      0|            }
  242|      0|        }
  243|      0|    } else {
  244|      0|        if (!convert_overlay_part(p, 0, 0, p->rgba_overlay->w, p->rgba_overlay->h))
  ------------------
  |  Branch (244:13): [True: 0, False: 0]
  ------------------
  245|      0|            return false;
  246|      0|    }
  247|       |
  248|      0|    return true;
  249|      0|}
draw_bmp.c:blend_overlay_with_video:
  152|     60|{
  153|     60|    if (!repack_config_buffers(p->video_to_f32, 0, p->video_tmp, 0, dst, NULL))
  ------------------
  |  Branch (153:9): [True: 0, False: 60]
  ------------------
  154|      0|        return false;
  155|     60|    if (!repack_config_buffers(p->video_from_f32, 0, dst, 0, p->video_tmp, NULL))
  ------------------
  |  Branch (155:9): [True: 0, False: 60]
  ------------------
  156|      0|        return false;
  157|       |
  158|     60|    int xs = dst->fmt.chroma_xs;
  159|     60|    int ys = dst->fmt.chroma_ys;
  160|       |
  161|  10.8k|    for (int y = 0; y < dst->h; y += p->align_y) {
  ------------------
  |  Branch (161:21): [True: 10.8k, False: 60]
  ------------------
  162|  10.8k|        struct slice *line = &p->slices[y * p->s_w];
  163|       |
  164|  32.4k|        for (int sx = 0; sx < p->s_w; sx++) {
  ------------------
  |  Branch (164:26): [True: 21.6k, False: 10.8k]
  ------------------
  165|  21.6k|            struct slice *s = &line[sx];
  166|       |
  167|  21.6k|            int w = s->x1 - s->x0;
  168|  21.6k|            if (w <= 0)
  ------------------
  |  Branch (168:17): [True: 14.4k, False: 7.15k]
  ------------------
  169|  14.4k|                continue;
  170|  7.15k|            int x = sx * SLICE_W + s->x0;
  ------------------
  |  |   48|  7.15k|#define SLICE_W 256u
  ------------------
  171|       |
  172|  7.15k|            mp_assert(MP_IS_ALIGNED(x, p->align_x));
  ------------------
  |  |   41|  7.15k|#define mp_assert assert
  ------------------
  173|  7.15k|            mp_assert(MP_IS_ALIGNED(w, p->align_x));
  ------------------
  |  |   41|  7.15k|#define mp_assert assert
  ------------------
  174|  7.15k|            mp_assert(x + w <= p->w);
  ------------------
  |  |   41|  7.15k|#define mp_assert assert
  ------------------
  175|       |
  176|  7.15k|            repack_line(p->overlay_to_f32, 0, 0, x, y, w);
  177|  7.15k|            repack_line(p->video_to_f32, 0, 0, x, y, w);
  178|  7.15k|            if (p->calpha_to_f32)
  ------------------
  |  Branch (178:17): [True: 0, False: 7.15k]
  ------------------
  179|      0|                repack_line(p->calpha_to_f32, 0, 0, x >> xs, y >> ys, w >> xs);
  180|       |
  181|  7.15k|            blend_slice(p);
  182|       |
  183|  7.15k|            repack_line(p->video_from_f32, x, y, 0, 0, w);
  184|  7.15k|        }
  185|  10.8k|    }
  186|       |
  187|     60|    return true;
  188|     60|}
draw_bmp.c:blend_slice:
  130|  7.15k|{
  131|  7.15k|    struct mp_image *ov = p->overlay_tmp;
  132|  7.15k|    struct mp_image *ca = p->calpha_tmp;
  133|  7.15k|    struct mp_image *vid = p->video_tmp;
  134|       |
  135|  28.6k|    for (int plane = 0; plane < vid->num_planes; plane++) {
  ------------------
  |  Branch (135:25): [True: 21.4k, False: 7.15k]
  ------------------
  136|  21.4k|        int xs = vid->fmt.xs[plane];
  137|  21.4k|        int ys = vid->fmt.ys[plane];
  138|  21.4k|        int h = (1 << vid->fmt.chroma_ys) - (1 << ys) + 1;
  139|  21.4k|        int cw = mp_chroma_div_up(vid->w, xs);
  140|  42.9k|        for (int y = 0; y < h; y++) {
  ------------------
  |  Branch (140:25): [True: 21.4k, False: 21.4k]
  ------------------
  141|  21.4k|            p->blend_line(mp_image_pixel_ptr_ny(vid, plane, 0, y),
  142|  21.4k|                          mp_image_pixel_ptr_ny(ov, plane, 0, y),
  143|  21.4k|                          xs || ys ? mp_image_pixel_ptr_ny(ca, 0, 0, y)
  ------------------
  |  Branch (143:27): [True: 0, False: 21.4k]
  |  Branch (143:33): [True: 0, False: 21.4k]
  ------------------
  144|  21.4k|                            : mp_image_pixel_ptr_ny(ov, ov->num_planes - 1, 0, y),
  145|  21.4k|                          cw);
  146|  21.4k|        }
  147|  21.4k|    }
  148|  7.15k|}

osd_res_equals:
  151|    390|{
  152|    390|    return a.w == b.w && a.h == b.h && a.ml == b.ml && a.mt == b.mt
  ------------------
  |  Branch (152:12): [True: 195, False: 195]
  |  Branch (152:26): [True: 195, False: 0]
  |  Branch (152:40): [True: 195, False: 0]
  |  Branch (152:56): [True: 195, False: 0]
  ------------------
  153|    390|        && a.mr == b.mr && a.mb == b.mb
  ------------------
  |  Branch (153:12): [True: 195, False: 0]
  |  Branch (153:28): [True: 195, False: 0]
  ------------------
  154|    390|        && a.display_par == b.display_par;
  ------------------
  |  Branch (154:12): [True: 195, False: 0]
  ------------------
  155|    390|}
osd_create:
  158|  17.0k|{
  159|  17.0k|    static_assert(MAX_OSD_PARTS >= OSDTYPE_COUNT, "");
  160|       |
  161|  17.0k|    struct osd_state *osd = talloc_zero(NULL, struct osd_state);
  ------------------
  |  |   27|  17.0k|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|  17.0k|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  17.0k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  162|  17.0k|    *osd = (struct osd_state) {
  163|  17.0k|        .opts_cache = m_config_cache_alloc(osd, global, &mp_osd_render_sub_opts),
  164|  17.0k|        .global = global,
  165|  17.0k|        .log = mp_log_new(osd, global->log, "osd"),
  166|  17.0k|        .force_video_pts = MP_NOPTS_VALUE,
  ------------------
  |  |   38|  17.0k|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  167|  17.0k|        .stats = stats_ctx_create(osd, global, "osd"),
  168|  17.0k|    };
  169|  17.0k|    mp_mutex_init(&osd->lock);
  170|  17.0k|    osd->opts = osd->opts_cache->opts;
  171|       |
  172|   102k|    for (int n = 0; n < MAX_OSD_PARTS; n++) {
  ------------------
  |  |  109|   102k|#define MAX_OSD_PARTS 5
  ------------------
  |  Branch (172:21): [True: 85.3k, False: 17.0k]
  ------------------
  173|  85.3k|        struct osd_object *obj = talloc(osd, struct osd_object);
  ------------------
  |  |   26|  85.3k|#define talloc                          ta_xnew
  |  |  ------------------
  |  |  |  |  133|  85.3k|#define ta_xnew(...)                    ta_oom_g(ta_new(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|  85.3k|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  174|  85.3k|        *obj = (struct osd_object) {
  175|  85.3k|            .type = n,
  176|  85.3k|            .text = talloc_strdup(obj, ""),
  ------------------
  |  |   50|  85.3k|#define talloc_strdup                   ta_xstrdup
  ------------------
  177|  85.3k|            .progbar_state = {.type = -1},
  178|  85.3k|            .vo_change_id = 1,
  179|  85.3k|        };
  180|  85.3k|        osd->objs[n] = obj;
  181|  85.3k|    }
  182|       |
  183|  17.0k|    osd->objs[OSDTYPE_SUB]->is_sub = true;
  184|  17.0k|    osd->objs[OSDTYPE_SUB2]->is_sub = true;
  185|       |
  186|  17.0k|    return osd;
  187|  17.0k|}
osd_free:
  190|  17.0k|{
  191|  17.0k|    if (!osd)
  ------------------
  |  Branch (191:9): [True: 0, False: 17.0k]
  ------------------
  192|      0|        return;
  193|  17.0k|    osd_destroy_backend(osd);
  194|  17.0k|    talloc_free(osd->objs[OSDTYPE_EXTERNAL2]->external2);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  195|  17.0k|    mp_mutex_destroy(&osd->lock);
  ------------------
  |  |  130|  17.0k|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
  196|  17.0k|    talloc_free(osd);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  197|  17.0k|}
osd_set_text:
  200|  17.4k|{
  201|  17.4k|    mp_mutex_lock(&osd->lock);
  ------------------
  |  |  131|  17.4k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  202|  17.4k|    struct osd_object *osd_obj = osd->objs[OSDTYPE_OSD];
  203|  17.4k|    if (!text)
  ------------------
  |  Branch (203:9): [True: 12.5k, False: 4.88k]
  ------------------
  204|  12.5k|        text = "";
  205|  17.4k|    if (strcmp(osd_obj->text, text) != 0) {
  ------------------
  |  Branch (205:9): [True: 4.47k, False: 12.9k]
  ------------------
  206|  4.47k|        talloc_free(osd_obj->text);
  ------------------
  |  |   47|  4.47k|#define talloc_free                     ta_free
  ------------------
  207|  4.47k|        osd_obj->text = talloc_strdup(osd_obj, text);
  ------------------
  |  |   50|  4.47k|#define talloc_strdup                   ta_xstrdup
  ------------------
  208|  4.47k|        osd_obj->osd_changed = true;
  209|  4.47k|        osd->want_redraw_notification = true;
  210|  4.47k|    }
  211|  17.4k|    mp_mutex_unlock(&osd->lock);
  ------------------
  |  |  133|  17.4k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  212|  17.4k|}
osd_set_external2:
  277|  17.0k|{
  278|  17.0k|    mp_mutex_lock(&osd->lock);
  ------------------
  |  |  131|  17.0k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  279|  17.0k|    struct osd_object *obj = osd->objs[OSDTYPE_EXTERNAL2];
  280|  17.0k|    talloc_free(obj->external2);
  ------------------
  |  |   47|  17.0k|#define talloc_free                     ta_free
  ------------------
  281|  17.0k|    obj->external2 = sub_bitmaps_copy(NULL, imgs);
  282|  17.0k|    obj->vo_change_id += 1;
  283|  17.0k|    osd->want_redraw_notification = true;
  284|  17.0k|    mp_mutex_unlock(&osd->lock);
  ------------------
  |  |  133|  17.0k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  285|  17.0k|}
osd_render:
  364|     78|{
  365|     78|    mp_mutex_lock(&osd->lock);
  ------------------
  |  |  131|     78|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  366|       |
  367|     78|    int64_t start_time = mp_time_ns();
  368|       |
  369|     78|    struct sub_bitmap_list *list = talloc_zero(NULL, struct sub_bitmap_list);
  ------------------
  |  |   27|     78|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|     78|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     78|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  370|     78|    list->change_id = 1;
  371|     78|    list->w = res.w;
  372|     78|    list->h = res.h;
  373|       |
  374|     78|    double force_video_pts = atomic_load(&osd->force_video_pts);
  375|     78|    if (force_video_pts != MP_NOPTS_VALUE)
  ------------------
  |  |   38|     78|#define MP_NOPTS_VALUE (-0x1p+63)
  ------------------
  |  Branch (375:9): [True: 0, False: 78]
  ------------------
  376|      0|        video_pts = force_video_pts;
  377|       |
  378|     78|    if (draw_flags & OSD_DRAW_SUB_FILTER)
  ------------------
  |  Branch (378:9): [True: 0, False: 78]
  ------------------
  379|      0|        draw_flags |= OSD_DRAW_SUB_ONLY;
  380|       |
  381|    468|    for (int n = 0; n < MAX_OSD_PARTS; n++) {
  ------------------
  |  |  109|    468|#define MAX_OSD_PARTS 5
  ------------------
  |  Branch (381:21): [True: 390, False: 78]
  ------------------
  382|    390|        struct osd_object *obj = osd->objs[n];
  383|       |
  384|       |        // Object is drawn into the video frame itself; don't draw twice
  385|    390|        if (osd->render_subs_in_filter && obj->is_sub &&
  ------------------
  |  Branch (385:13): [True: 0, False: 390]
  |  Branch (385:43): [True: 0, False: 0]
  ------------------
  386|    390|            !(draw_flags & OSD_DRAW_SUB_FILTER))
  ------------------
  |  Branch (386:13): [True: 0, False: 0]
  ------------------
  387|      0|            continue;
  388|    390|        if ((draw_flags & OSD_DRAW_SUB_ONLY) && !obj->is_sub)
  ------------------
  |  Branch (388:13): [True: 0, False: 390]
  |  Branch (388:49): [True: 0, False: 0]
  ------------------
  389|      0|            continue;
  390|    390|        if ((draw_flags & OSD_DRAW_OSD_ONLY) && obj->is_sub)
  ------------------
  |  Branch (390:13): [True: 0, False: 390]
  |  Branch (390:49): [True: 0, False: 0]
  ------------------
  391|      0|            continue;
  392|       |
  393|    390|        char *stat_type_render = obj->is_sub ? "sub-render" : "osd-render";
  ------------------
  |  Branch (393:34): [True: 156, False: 234]
  ------------------
  394|    390|        stats_time_start(osd->stats, stat_type_render);
  395|       |
  396|    390|        struct sub_bitmaps *imgs =
  397|    390|            render_object(osd, obj, res, video_pts, formats);
  398|       |
  399|    390|        stats_time_end(osd->stats, stat_type_render);
  400|       |
  401|    390|        if (imgs && imgs->num_parts > 0) {
  ------------------
  |  Branch (401:13): [True: 60, False: 330]
  |  Branch (401:21): [True: 60, False: 0]
  ------------------
  402|     60|            if (formats[imgs->format]) {
  ------------------
  |  Branch (402:17): [True: 60, False: 0]
  ------------------
  403|     60|                talloc_steal(list, imgs);
  ------------------
  |  |   38|     60|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     60|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  404|     60|                MP_TARRAY_APPEND(list, list->items, list->num_items, imgs);
  ------------------
  |  |  105|     60|    do {                                            \
  |  |  106|     60|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|     60|    do {                                            \
  |  |  |  |   97|     60|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|     60|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|     60|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|     60|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 60, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|     60|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|     60|    do {                                                        \
  |  |  |  |  |  |   89|     60|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|     60|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|     60|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|     60|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|     60|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|     60|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|     60|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|     60|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|     60|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|     60|        (idxvar)++;                                 \
  |  |  109|     60|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  405|     60|                imgs = NULL;
  406|     60|            } else {
  407|      0|                MP_ERR(osd, "Can't render OSD part %d (format %d).\n",
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  408|      0|                       obj->type, imgs->format);
  409|      0|            }
  410|     60|        }
  411|       |
  412|    390|        list->change_id += obj->vo_change_id;
  413|       |
  414|    390|        talloc_free(imgs);
  ------------------
  |  |   47|    390|#define talloc_free                     ta_free
  ------------------
  415|    390|    }
  416|       |
  417|     78|    double elapsed = MP_TIME_NS_TO_MS(mp_time_ns() - start_time);
  ------------------
  |  |   65|     78|#define MP_TIME_NS_TO_MS(ns) ((ns) / (double)1000000)
  ------------------
  418|     78|    bool slow = elapsed > 5;
  419|     78|    mp_msg(osd->log, slow ? MSGL_DEBUG : MSGL_TRACE, "Spent %.3f ms in %s%s\n",
  ------------------
  |  Branch (419:22): [True: 22, False: 56]
  ------------------
  420|     78|           elapsed, __func__, slow ? " (slow!)" : "");
  ------------------
  |  Branch (420:31): [True: 22, False: 56]
  ------------------
  421|       |
  422|     78|    mp_mutex_unlock(&osd->lock);
  ------------------
  |  |  133|     78|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  423|     78|    return list;
  424|     78|}
osd_draw_on_image:
  449|     78|{
  450|     78|    osd_draw_on_image_p(osd, res, video_pts, draw_flags, NULL, dest);
  451|     78|}
osd_draw_on_image_p:
  459|     78|{
  460|     78|    struct sub_bitmap_list *list =
  461|     78|        osd_render(osd, res, video_pts, draw_flags, mp_draw_sub_formats);
  462|       |
  463|     78|    if (!list->num_items) {
  ------------------
  |  Branch (463:9): [True: 18, False: 60]
  ------------------
  464|     18|        talloc_free(list);
  ------------------
  |  |   47|     18|#define talloc_free                     ta_free
  ------------------
  465|     18|        return;
  466|     18|    }
  467|       |
  468|     60|    if (!mp_image_pool_make_writeable(pool, dest))
  ------------------
  |  Branch (468:9): [True: 0, False: 60]
  ------------------
  469|      0|        return; // on OOM, skip
  470|       |
  471|       |    // Need to lock for the dumb osd->draw_cache thing.
  472|     60|    mp_mutex_lock(&osd->lock);
  ------------------
  |  |  131|     60|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  473|       |
  474|     60|    if (!osd->draw_cache)
  ------------------
  |  Branch (474:9): [True: 30, False: 30]
  ------------------
  475|     30|        osd->draw_cache = mp_draw_sub_alloc(osd, osd->global);
  476|       |
  477|     60|    stats_time_start(osd->stats, "draw-bmp");
  478|       |
  479|     60|    if (!mp_draw_sub_bitmaps(osd->draw_cache, dest, list))
  ------------------
  |  Branch (479:9): [True: 0, False: 60]
  ------------------
  480|     60|        MP_WARN(osd, "Failed rendering OSD.\n");
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  481|     60|    talloc_steal(osd, osd->draw_cache);
  ------------------
  |  |   38|     60|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     60|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  482|       |
  483|     60|    stats_time_end(osd->stats, "draw-bmp");
  484|       |
  485|     60|    mp_mutex_unlock(&osd->lock);
  ------------------
  |  |  133|     60|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  486|       |
  487|     60|    talloc_free(list);
  ------------------
  |  |   47|     60|#define talloc_free                     ta_free
  ------------------
  488|     60|}
osd_changed:
  504|  12.1k|{
  505|  12.1k|    mp_mutex_lock(&osd->lock);
  ------------------
  |  |  131|  12.1k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  506|  12.1k|    osd->objs[OSDTYPE_OSD]->osd_changed = true;
  507|  12.1k|    osd->want_redraw_notification = true;
  508|       |    // Done here for a lack of a better place.
  509|  12.1k|    m_config_cache_update(osd->opts_cache);
  510|  12.1k|    mp_mutex_unlock(&osd->lock);
  ------------------
  |  |  133|  12.1k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  511|  12.1k|}
osd_query_and_reset_want_redraw:
  514|     39|{
  515|     39|    mp_mutex_lock(&osd->lock);
  ------------------
  |  |  131|     39|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  516|     39|    bool r = osd->want_redraw_notification;
  517|     39|    osd->want_redraw_notification = false;
  518|     39|    mp_mutex_unlock(&osd->lock);
  ------------------
  |  |  133|     39|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  519|     39|    return r;
  520|     39|}
osd_get_vo_res:
  523|    174|{
  524|    174|    mp_mutex_lock(&osd->lock);
  ------------------
  |  |  131|    174|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  525|       |    // Any OSDTYPE is fine; but it mustn't be a subtitle one (can have lower res.)
  526|    174|    struct mp_osd_res res = osd->objs[OSDTYPE_OSD]->vo_res;
  527|    174|    mp_mutex_unlock(&osd->lock);
  ------------------
  |  |  133|    174|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  528|    174|    return res;
  529|    174|}
sub_bitmaps_copy:
  581|  17.2k|{
  582|  17.2k|    if (!in || !in->num_parts)
  ------------------
  |  Branch (582:9): [True: 17.0k, False: 156]
  |  Branch (582:16): [True: 96, False: 60]
  ------------------
  583|  17.1k|        return NULL;
  584|       |
  585|     60|    struct sub_bitmaps *res = talloc(NULL, struct sub_bitmaps);
  ------------------
  |  |   26|     60|#define talloc                          ta_xnew
  |  |  ------------------
  |  |  |  |  133|     60|#define ta_xnew(...)                    ta_oom_g(ta_new(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     60|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  586|     60|    *res = *in;
  587|       |
  588|       |    // Note: the p_cache thing is a lie and unused.
  589|       |
  590|       |    // The bitmaps being refcounted is essential for performance, and for
  591|       |    // not invalidating in->parts[*].bitmap pointers.
  592|     60|    mp_assert(in->packed && in->packed->bufs[0]);
  ------------------
  |  |   41|     60|#define mp_assert assert
  ------------------
  593|       |
  594|     60|    res->packed = mp_image_new_ref(res->packed);
  595|     60|    talloc_steal(res, res->packed);
  ------------------
  |  |   38|     60|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     60|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  596|       |
  597|     60|    res->parts = NULL;
  598|     60|    MP_RESIZE_ARRAY(res, res->parts, res->num_parts);
  ------------------
  |  |   88|     60|    do {                                                        \
  |  |   89|     60|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  ------------------
  |  |  |  |  158|     60|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|     60|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|     60|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|     60|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   90|     60|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |   91|     60|    } while (0)
  |  |  ------------------
  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  599|     60|    memcpy(res->parts, in->parts, sizeof(res->parts[0]) * res->num_parts);
  600|       |
  601|     60|    return res;
  602|     60|}
osd.c:check_obj_resize:
  289|    390|{
  290|    390|    if (!osd_res_equals(res, obj->vo_res)) {
  ------------------
  |  Branch (290:9): [True: 195, False: 195]
  ------------------
  291|    195|        obj->vo_res = res;
  292|    195|        obj->osd_changed = true;
  293|    195|        mp_client_broadcast_event_external(osd->global->client_api,
  294|    195|                                           MP_EVENT_WIN_RESIZE, NULL);
  295|    195|    }
  296|    390|}
osd.c:render_object:
  318|    390|{
  319|    390|    int format = SUBBITMAP_LIBASS;
  320|    390|    if (!sub_formats[format] || osd->opts->force_rgba_osd)
  ------------------
  |  Branch (320:9): [True: 0, False: 390]
  |  Branch (320:33): [True: 0, False: 390]
  ------------------
  321|      0|        format = SUBBITMAP_BGRA;
  322|       |
  323|    390|    struct sub_bitmaps *res = NULL;
  324|       |
  325|    390|    check_obj_resize(osd, osdres, obj);
  326|       |
  327|    390|    if (obj->type == OSDTYPE_SUB) {
  ------------------
  |  Branch (327:9): [True: 78, False: 312]
  ------------------
  328|     78|        if (obj->sub && sub_is_primary_visible(obj->sub))
  ------------------
  |  Branch (328:13): [True: 0, False: 78]
  |  Branch (328:25): [True: 0, False: 0]
  ------------------
  329|      0|            res = sub_get_bitmaps(obj->sub, obj->vo_res, format, video_pts);
  330|    312|    } else if (obj->type == OSDTYPE_SUB2) {
  ------------------
  |  Branch (330:16): [True: 78, False: 234]
  ------------------
  331|     78|        if (obj->sub && sub_is_secondary_visible(obj->sub))
  ------------------
  |  Branch (331:13): [True: 0, False: 78]
  |  Branch (331:25): [True: 0, False: 0]
  ------------------
  332|      0|            res = sub_get_bitmaps(obj->sub, obj->vo_res, format, video_pts);
  333|    234|    } else if (obj->type == OSDTYPE_EXTERNAL2) {
  ------------------
  |  Branch (333:16): [True: 78, False: 156]
  ------------------
  334|     78|        if (obj->external2 && obj->external2->format) {
  ------------------
  |  Branch (334:13): [True: 0, False: 78]
  |  Branch (334:31): [True: 0, False: 0]
  ------------------
  335|      0|            res = sub_bitmaps_copy(NULL, obj->external2); // need to be owner
  336|      0|            obj->external2->change_id = 0;
  337|      0|        }
  338|    156|    } else {
  339|    156|        res = osd_object_get_bitmaps(osd, obj, format);
  340|    156|    }
  341|       |
  342|    390|    if (obj->vo_had_output != !!res) {
  ------------------
  |  Branch (342:9): [True: 30, False: 360]
  ------------------
  343|     30|        obj->vo_had_output = !!res;
  344|     30|        obj->vo_change_id += 1;
  345|     30|    }
  346|       |
  347|    390|    if (res) {
  ------------------
  |  Branch (347:9): [True: 60, False: 330]
  ------------------
  348|     60|        obj->vo_change_id += res->change_id;
  349|       |
  350|     60|        res->render_index = obj->type;
  351|     60|        res->change_id = obj->vo_change_id;
  352|     60|    }
  353|       |
  354|    390|    return res;
  355|    390|}

osd_destroy_backend:
   85|  17.0k|{
   86|   102k|    for (int n = 0; n < MAX_OSD_PARTS; n++) {
  ------------------
  |  |  109|   102k|#define MAX_OSD_PARTS 5
  ------------------
  |  Branch (86:21): [True: 85.3k, False: 17.0k]
  ------------------
   87|  85.3k|        struct osd_object *obj = osd->objs[n];
   88|  85.3k|        destroy_ass_renderer(&obj->ass);
   89|  85.3k|        for (int i = 0; i < obj->num_externals; i++)
  ------------------
  |  Branch (89:25): [True: 0, False: 85.3k]
  ------------------
   90|      0|            destroy_external(obj->externals[i]);
   91|  85.3k|        obj->num_externals = 0;
   92|  85.3k|    }
   93|  17.0k|}
osd_get_function_sym:
  192|     37|{
  193|     37|    snprintf(buffer, buffer_size, OSD_CODEPOINTS_ESCAPE "%c", osd_function);
  ------------------
  |  |  114|     37|#define OSD_CODEPOINTS_ESCAPE "\xC2\x91"
  ------------------
  194|     37|}
osd_mangle_ass:
  197|     42|{
  198|     42|    const char *start = in;
  199|     42|    bool escape_ass = true;
  200|   102k|    while (*in) {
  ------------------
  |  Branch (200:12): [True: 101k, False: 42]
  ------------------
  201|       |        // As used by osd_get_function_sym().
  202|   101k|        size_t len = strlen(OSD_CODEPOINTS_ESCAPE);
  ------------------
  |  |  114|   101k|#define OSD_CODEPOINTS_ESCAPE "\xC2\x91"
  ------------------
  203|   101k|        if (!strncmp(in, OSD_CODEPOINTS_ESCAPE, len) && in[len]) {
  ------------------
  |  |  114|   101k|#define OSD_CODEPOINTS_ESCAPE "\xC2\x91"
  ------------------
  |  Branch (203:13): [True: 19, False: 101k]
  |  Branch (203:57): [True: 19, False: 0]
  ------------------
  204|     19|            bstr_xappend(NULL, dst, bstr0(ASS_USE_OSD_FONT));
  ------------------
  |  |   39|     19|#define ASS_USE_OSD_FONT "{\\fnmpv-osd-symbols}"
  ------------------
  205|     19|            mp_append_utf8_bstr(NULL, dst, OSD_CODEPOINTS + in[len]);
  ------------------
  |  |  112|     19|#define OSD_CODEPOINTS 0xE000
  ------------------
  206|     19|            bstr_xappend(NULL, dst, bstr0("{\\r}"));
  207|     19|            in += len + 1;
  208|     19|            continue;
  209|     19|        }
  210|   101k|        len = strlen(OSD_ASS_0);
  ------------------
  |  |  136|   101k|#define OSD_ASS_0 OSD_ASS_ESCAPE "0"
  |  |  ------------------
  |  |  |  |  134|   101k|#define OSD_ASS_ESCAPE "\xC2\x92" "a"
  |  |  ------------------
  ------------------
  211|   101k|        if (!strncmp(in, OSD_ASS_0, len)) {
  ------------------
  |  |  136|   101k|#define OSD_ASS_0 OSD_ASS_ESCAPE "0"
  |  |  ------------------
  |  |  |  |  134|   101k|#define OSD_ASS_ESCAPE "\xC2\x92" "a"
  |  |  ------------------
  ------------------
  |  Branch (211:13): [True: 30, False: 101k]
  ------------------
  212|     30|            escape_ass = false;
  213|     30|            in += len;
  214|     30|            continue;
  215|     30|        }
  216|   101k|        len = strlen(OSD_ASS_1);
  ------------------
  |  |  137|   101k|#define OSD_ASS_1 OSD_ASS_ESCAPE "1"
  |  |  ------------------
  |  |  |  |  134|   101k|#define OSD_ASS_ESCAPE "\xC2\x92" "a"
  |  |  ------------------
  ------------------
  217|   101k|        if (!strncmp(in, OSD_ASS_1, len)) {
  ------------------
  |  |  137|   101k|#define OSD_ASS_1 OSD_ASS_ESCAPE "1"
  |  |  ------------------
  |  |  |  |  134|   101k|#define OSD_ASS_ESCAPE "\xC2\x92" "a"
  |  |  ------------------
  ------------------
  |  Branch (217:13): [True: 39, False: 101k]
  ------------------
  218|     39|            escape_ass = true;
  219|     39|            in += len;
  220|     39|            continue;
  221|     39|        }
  222|   101k|        len = strlen(TERM_MSG_0);
  ------------------
  |  |   30|   101k|#define TERM_MSG_0 TERM_MSG_ESCAPE "0"
  |  |  ------------------
  |  |  |  |   29|   101k|#define TERM_MSG_ESCAPE "\xC2\x92" "t"
  |  |  ------------------
  ------------------
  223|   101k|        if (!strncmp(in, TERM_MSG_0, len)) {
  ------------------
  |  |   30|   101k|#define TERM_MSG_0 TERM_MSG_ESCAPE "0"
  |  |  ------------------
  |  |  |  |   29|   101k|#define TERM_MSG_ESCAPE "\xC2\x92" "t"
  |  |  ------------------
  ------------------
  |  Branch (223:13): [True: 15, False: 101k]
  ------------------
  224|     15|            in += len;
  225|     15|            continue;
  226|     15|        }
  227|   101k|        if (escape_ass && *in == '{')
  ------------------
  |  Branch (227:13): [True: 71.3k, False: 30.5k]
  |  Branch (227:27): [True: 1.62k, False: 69.7k]
  ------------------
  228|  1.62k|            bstr_xappend(NULL, dst, bstr0("\\"));
  229|       |        // Replace newlines with \N for escape-ass. This is necessary to apply
  230|       |        // ASS tags past newlines and to preserve consecutive newlines with
  231|       |        // osd-overlay because update_external() adds a ASS event per line.
  232|   101k|        if (replace_newlines && *in == '\n') {
  ------------------
  |  Branch (232:13): [True: 0, False: 101k]
  |  Branch (232:33): [True: 0, False: 0]
  ------------------
  233|      0|            bstr_xappend(NULL, dst, bstr0("\\N"));
  234|      0|            in += 1;
  235|      0|            continue;
  236|      0|        }
  237|       |        // Libass will strip leading whitespace
  238|   101k|        if (in[0] == ' ' && (in == start || in[-1] == '\n')) {
  ------------------
  |  Branch (238:13): [True: 13.5k, False: 88.2k]
  |  Branch (238:30): [True: 0, False: 13.5k]
  |  Branch (238:45): [True: 9.06k, False: 4.53k]
  ------------------
  239|  9.06k|            bstr_xappend(NULL, dst, bstr0("\\h"));
  240|  9.06k|            in += 1;
  241|  9.06k|            continue;
  242|  9.06k|        }
  243|  92.8k|        bstr_xappend(NULL, dst, (bstr){(char *)in, 1});
  244|       |        // Break ASS escapes with U+2060 WORD JOINER
  245|  92.8k|        if (escape_ass && *in == '\\')
  ------------------
  |  Branch (245:13): [True: 65.0k, False: 27.7k]
  |  Branch (245:27): [True: 1.68k, False: 63.3k]
  ------------------
  246|  1.68k|            mp_append_utf8_bstr(NULL, dst, 0x2060);
  247|  92.8k|        in++;
  248|  92.8k|    }
  249|     42|}
osd_get_text_size:
  291|      2|{
  292|      2|    mp_mutex_lock(&osd->lock);
  ------------------
  |  |  131|      2|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  293|      2|    struct osd_object *obj = osd->objs[OSDTYPE_OSD];
  294|      2|    ASS_Style *style = prepare_osd_ass(osd, obj);
  295|      2|    *out_screen_h = obj->ass.track->PlayResY - style->MarginV;
  296|      2|    *out_font_h = style->FontSize;
  297|      2|    mp_mutex_unlock(&osd->lock);
  ------------------
  |  |  133|      2|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  298|      2|}
osd_set_external_remove_owner:
  646|  22.2k|{
  647|  22.2k|    mp_mutex_lock(&osd->lock);
  ------------------
  |  |  131|  22.2k|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  648|  22.2k|    struct osd_object *obj = osd->objs[OSDTYPE_EXTERNAL];
  649|  22.2k|    for (int n = obj->num_externals - 1; n >= 0; n--) {
  ------------------
  |  Branch (649:42): [True: 0, False: 22.2k]
  ------------------
  650|      0|        struct osd_external *e = obj->externals[n];
  651|      0|        if (e->ov.owner == owner) {
  ------------------
  |  Branch (651:13): [True: 0, False: 0]
  ------------------
  652|      0|            destroy_external(e);
  653|      0|            MP_TARRAY_REMOVE_AT(obj->externals, obj->num_externals, n);
  ------------------
  |  |  143|      0|    do {                                            \
  |  |  144|      0|        size_t at_ = (at);                          \
  |  |  145|      0|        assert(at_ <= (idxvar));                    \
  |  |  146|      0|        memmove((p) + at_, (p) + at_ + 1,           \
  |  |  147|      0|                ((idxvar) - at_ - 1) * sizeof((p)[0])); \
  |  |  148|      0|        (idxvar)--;                                 \
  |  |  149|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (149:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  654|      0|            obj->changed = true;
  655|      0|            osd->want_redraw_notification = true;
  656|      0|        }
  657|      0|    }
  658|  22.2k|    mp_mutex_unlock(&osd->lock);
  ------------------
  |  |  133|  22.2k|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  659|  22.2k|}
osd_object_get_bitmaps:
  687|    156|{
  688|    156|    if (obj->type == OSDTYPE_OSD) {
  ------------------
  |  Branch (688:9): [True: 78, False: 78]
  ------------------
  689|     78|        if (obj->osd_changed) {
  ------------------
  |  Branch (689:13): [True: 47, False: 31]
  ------------------
  690|     47|            update_osd(osd, obj);
  691|     47|        } else {
  692|     31|            mp_require(obj->ass_packer);
  ------------------
  |  |   42|     31|#define mp_require assert
  ------------------
  693|     31|            goto done;
  694|     31|        }
  695|     78|    }
  696|       |
  697|    125|    if (!obj->ass_packer)
  ------------------
  |  Branch (697:9): [True: 78, False: 47]
  ------------------
  698|     78|        obj->ass_packer = mp_ass_packer_alloc(obj);
  699|       |
  700|    125|    MP_TARRAY_GROW(obj, obj->ass_imgs, obj->num_externals + 1);
  ------------------
  |  |   96|    125|    do {                                            \
  |  |   97|    125|        size_t nextidx_ = (nextidx);                \
  |  |   98|    125|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  ------------------
  |  |  |  |   84|    125|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  ------------------
  |  |  |  |  |  |   45|    125|#define talloc_get_size                 ta_get_size
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  |  Branch (98:13): [True: 78, False: 47]
  |  |  ------------------
  |  |   99|    125|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  ------------------
  |  |  |  |   88|     78|    do {                                                        \
  |  |  |  |   89|     78|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|     78|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|     78|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|     78|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|     78|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |   90|     78|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |   91|     78|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  100|    125|    } while (0)
  |  |  ------------------
  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  701|       |
  702|    125|    append_ass(&obj->ass, &obj->vo_res, &obj->ass_imgs[0], &obj->changed);
  703|    125|    for (int n = 0; n < obj->num_externals; n++) {
  ------------------
  |  Branch (703:21): [True: 0, False: 125]
  ------------------
  704|      0|        if (obj->externals[n]->ov.hidden) {
  ------------------
  |  Branch (704:13): [True: 0, False: 0]
  ------------------
  705|      0|            update_playres(&obj->externals[n]->ass, &obj->vo_res);
  706|      0|            obj->ass_imgs[n + 1] = NULL;
  707|      0|        } else {
  708|      0|            append_ass(&obj->externals[n]->ass, &obj->vo_res,
  709|      0|                       &obj->ass_imgs[n + 1], &obj->changed);
  710|      0|        }
  711|      0|    }
  712|       |
  713|    156|done:;
  714|    156|    struct sub_bitmaps out_imgs = {0};
  715|    156|    mp_ass_packer_pack(obj->ass_packer, obj->ass_imgs, obj->num_externals + 1,
  716|    156|                       obj->changed, false, format, &out_imgs);
  717|       |
  718|    156|    obj->changed = false;
  719|       |
  720|    156|    return sub_bitmaps_copy(&obj->copy_cache, &out_imgs);
  721|    125|}
osd_libass.c:destroy_ass_renderer:
   64|  85.3k|{
   65|  85.3k|    if (ass->track)
  ------------------
  |  Branch (65:9): [True: 34, False: 85.3k]
  ------------------
   66|     34|        ass_free_track(ass->track);
   67|  85.3k|    ass->track = NULL;
   68|  85.3k|    if (ass->render)
  ------------------
  |  Branch (68:9): [True: 34, False: 85.3k]
  ------------------
   69|     34|        ass_renderer_done(ass->render);
   70|  85.3k|    ass->render = NULL;
   71|  85.3k|    if (ass->library)
  ------------------
  |  Branch (71:9): [True: 34, False: 85.3k]
  ------------------
   72|     34|        ass_library_done(ass->library);
   73|  85.3k|    ass->library = NULL;
   74|  85.3k|    talloc_free(ass->log);
  ------------------
  |  |   47|  85.3k|#define talloc_free                     ta_free
  ------------------
   75|  85.3k|    ass->log = NULL;
   76|  85.3k|}
osd_libass.c:prepare_osd_ass:
  262|     44|{
  263|     44|    struct mp_osd_render_opts *opts = osd->opts;
  264|       |
  265|     44|    create_ass_track(osd, obj, &obj->ass);
  266|       |
  267|     44|    struct osd_style_opts font = *opts->osd_style;
  268|     44|    font.font_size *= opts->osd_scale;
  269|       |
  270|     44|    double playresy = obj->ass.track->PlayResY;
  271|       |    // Compensate for libass and mp_ass_set_style scaling the font etc.
  272|     44|    if (!opts->osd_scale_by_window && obj->vo_res.h)
  ------------------
  |  Branch (272:9): [True: 0, False: 44]
  |  Branch (272:39): [True: 0, False: 0]
  ------------------
  273|      0|        playresy *= 720.0 / obj->vo_res.h;
  274|       |
  275|     44|    ASS_Style *style = get_style(&obj->ass, "OSD");
  276|     44|    mp_ass_set_style(style, playresy, &font);
  277|     44|    return style;
  278|     44|}
osd_libass.c:create_ass_track:
  118|     44|{
  119|     44|    create_ass_renderer(osd, ass);
  120|       |
  121|     44|    ASS_Track *track = ass->track;
  122|     44|    struct mp_osd_render_opts *opts = osd->opts;
  123|     44|    if (!track)
  ------------------
  |  Branch (123:9): [True: 34, False: 10]
  ------------------
  124|     34|        track = ass->track = ass_new_track(ass->library);
  125|       |
  126|     44|    track->track_type = TRACK_TYPE_ASS;
  127|     44|    track->Timer = 100.;
  128|     44|    track->WrapStyle = 1; // end-of-line wrapping instead of smart wrapping
  129|     44|    track->Kerning = true;
  130|     44|    track->ScaledBorderAndShadow = true;
  131|     44|    ass_set_shaper(ass->render, opts->osd_shaper);
  132|     44|#if LIBASS_VERSION >= 0x01600010
  133|     44|    ass_track_set_feature(track, ASS_FEATURE_WRAP_UNICODE, 1);
  134|     44|#endif
  135|     44|#if LIBASS_VERSION >= 0x01703010
  136|     44|    ass_configure_prune(track, opts->osd_ass_prune_delay * 1000.0);
  137|     44|#endif
  138|     44|    ass_set_cache_limits(ass->render, opts->osd_glyph_limit, opts->osd_bitmap_max_size);
  139|     44|    update_playres(ass, &obj->vo_res);
  140|     44|}
osd_libass.c:create_ass_renderer:
   45|     44|{
   46|     44|    if (ass->render)
  ------------------
  |  Branch (46:9): [True: 10, False: 34]
  ------------------
   47|     10|        return;
   48|       |
   49|     34|    ass->log = mp_log_new(NULL, osd->log, "libass");
   50|     34|    ass->library = mp_ass_init(osd->global, osd->opts->osd_style, ass->log);
   51|     34|    ass_add_font(ass->library, "mpv-osd-symbols", (void *)osd_font_pfb,
   52|     34|                 sizeof(osd_font_pfb) - 1);
   53|       |
   54|     34|    ass->render = ass_renderer_init(ass->library);
   55|     34|    if (!ass->render)
  ------------------
  |  Branch (55:9): [True: 0, False: 34]
  ------------------
   56|      0|        abort();
   57|       |
   58|     34|    mp_ass_configure_fonts(ass->render, osd->opts->osd_style,
   59|     34|                           osd->global, ass->log);
   60|     34|    ass_set_pixel_aspect(ass->render, 1.0);
   61|     34|}
osd_libass.c:get_style:
  153|     44|{
  154|     44|    ASS_Track *track = ass->track;
  155|     44|    if (!track)
  ------------------
  |  Branch (155:9): [True: 0, False: 44]
  ------------------
  156|      0|        return NULL;
  157|       |
  158|     44|    int sid = find_style(track, name, -1);
  159|     44|    if (sid >= 0)
  ------------------
  |  Branch (159:9): [True: 10, False: 34]
  ------------------
  160|     10|        return &track->styles[sid];
  161|       |
  162|     34|    sid = ass_alloc_style(track);
  163|     34|    ASS_Style *style = &track->styles[sid];
  164|     34|    style->Name = strdup(name);
  165|       |    // Set to neutral base direction, as opposed to VSFilter LTR default
  166|     34|    style->Encoding = -1;
  167|     34|    return style;
  168|     44|}
osd_libass.c:find_style:
  143|     86|{
  144|    172|    for (int n = 0; n < track->n_styles; n++) {
  ------------------
  |  Branch (144:21): [True: 138, False: 34]
  ------------------
  145|    138|        if (track->styles[n].Name && strcmp(track->styles[n].Name, name) == 0)
  ------------------
  |  Branch (145:13): [True: 138, False: 0]
  |  Branch (145:38): [True: 52, False: 86]
  ------------------
  146|     52|            return n;
  147|    138|    }
  148|     34|    return def;
  149|     86|}
osd_libass.c:clear_ass:
  186|     47|{
  187|     47|    if (ass->track)
  ------------------
  |  Branch (187:9): [True: 8, False: 39]
  ------------------
  188|      8|        ass_flush_events(ass->track);
  189|     47|}
osd_libass.c:add_osd_ass_event:
  172|     42|{
  173|     42|    int n = ass_alloc_event(track);
  174|     42|    ASS_Event *event = track->events + n;
  175|     42|    event->Start = 0;
  176|     42|    event->Duration = 100;
  177|     42|    event->Style = find_style(track, style, 0);
  178|     42|    event->ReadOrder = n;
  179|     42|    mp_assert(event->Text == NULL);
  ------------------
  |  |   41|     42|#define mp_assert assert
  ------------------
  180|     42|    if (text)
  ------------------
  |  Branch (180:9): [True: 41, False: 1]
  ------------------
  181|     41|        event->Text = strdup(text);
  182|     42|    return event;
  183|     42|}
osd_libass.c:append_ass:
  663|    125|{
  664|    125|    if (!ass->render || !ass->track) {
  ------------------
  |  Branch (664:9): [True: 83, False: 42]
  |  Branch (664:25): [True: 0, False: 42]
  ------------------
  665|     83|        *img_list = NULL;
  666|     83|        return;
  667|     83|    }
  668|       |
  669|     42|    update_playres(ass, res);
  670|       |
  671|     42|    ass_set_frame_size(ass->render, res->w, res->h);
  672|     42|    ass_set_pixel_aspect(ass->render, res->display_par);
  673|       |
  674|     42|    int ass_changed;
  675|     42|    *img_list = ass_render_frame(ass->render, ass->track, 0, &ass_changed);
  676|       |
  677|     42|    ass->changed |= ass_changed;
  678|       |
  679|     42|    if (changed) {
  ------------------
  |  Branch (679:9): [True: 42, False: 0]
  ------------------
  680|     42|        *changed |= ass->changed;
  681|     42|        ass->changed = false;
  682|     42|    }
  683|     42|}
osd_libass.c:update_osd:
  516|     47|{
  517|     47|    obj->osd_changed = false;
  518|     47|    clear_ass(&obj->ass);
  519|     47|    update_osd_text(osd, obj);
  520|     47|    update_progbar(osd, obj);
  521|     47|}
osd_libass.c:update_osd_text:
  281|     47|{
  282|       |
  283|     47|    if (!obj->text[0])
  ------------------
  |  Branch (283:9): [True: 5, False: 42]
  ------------------
  284|      5|        return;
  285|       |
  286|     42|    prepare_osd_ass(osd, obj);
  287|     42|    add_osd_ass_event_escaped(obj->ass.track, "OSD", obj->text);
  288|     42|}
osd_libass.c:add_osd_ass_event_escaped:
  253|     42|{
  254|     42|    bstr buf = {0};
  255|     42|    osd_mangle_ass(&buf, text, false);
  256|     42|    ASS_Event *e = add_osd_ass_event(track, style, buf.start);
  257|     42|    talloc_free(buf.start);
  ------------------
  |  |   47|     42|#define talloc_free                     ta_free
  ------------------
  258|     42|    return e;
  259|     42|}
osd_libass.c:update_progbar:
  414|     47|{
  415|     47|    if (obj->progbar_state.type < 0)
  ------------------
  |  Branch (415:9): [True: 47, False: 0]
  ------------------
  416|     47|        return;
  417|       |
  418|      0|    float px, py, width, height, border;
  419|      0|    get_osd_bar_box(osd, obj, &px, &py, &width, &height, &border);
  420|       |
  421|      0|    ASS_Track *track = obj->ass.track;
  422|       |
  423|      0|    float sx = px - border * 2 - height / 4; // includes additional spacing
  424|      0|    float sy = py + height / 2;
  425|       |
  426|      0|    bstr buf = bstr0(talloc_asprintf(NULL, "{\\an6\\pos(%f,%f)}", sx, sy));
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  427|       |
  428|      0|    if (obj->progbar_state.type == 0 || obj->progbar_state.type >= 256) {
  ------------------
  |  Branch (428:9): [True: 0, False: 0]
  |  Branch (428:41): [True: 0, False: 0]
  ------------------
  429|       |        // no sym
  430|      0|    } else if (obj->progbar_state.type >= 32) {
  ------------------
  |  Branch (430:16): [True: 0, False: 0]
  ------------------
  431|      0|        mp_append_utf8_bstr(NULL, &buf, obj->progbar_state.type);
  432|      0|    } else {
  433|      0|        bstr_xappend(NULL, &buf, bstr0(ASS_USE_OSD_FONT));
  ------------------
  |  |   39|      0|#define ASS_USE_OSD_FONT "{\\fnmpv-osd-symbols}"
  ------------------
  434|      0|        mp_append_utf8_bstr(NULL, &buf, OSD_CODEPOINTS + obj->progbar_state.type);
  ------------------
  |  |  112|      0|#define OSD_CODEPOINTS 0xE000
  ------------------
  435|      0|        bstr_xappend(NULL, &buf, bstr0("{\\r}"));
  436|      0|    }
  437|       |
  438|      0|    add_osd_ass_event(track, "progbar", buf.start);
  439|      0|    talloc_free(buf.start);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  440|       |
  441|      0|    struct ass_draw *d = &(struct ass_draw) { .scale = 4 };
  442|       |
  443|      0|    if (osd->opts->osd_style->back_color.a && osd->opts->osd_style->border_style != 1) {
  ------------------
  |  Branch (443:9): [True: 0, False: 0]
  |  Branch (443:47): [True: 0, False: 0]
  ------------------
  444|       |        // the bar style always ignores the --osd-back-color config - it messes
  445|       |        // up the bar. draw an artificial box at the original back color.
  446|      0|        struct m_color bc = osd->opts->osd_style->back_color;
  447|      0|        d->text = talloc_asprintf_append(d->text,
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
  448|      0|            "{\\pos(%f,%f)\\bord0\\1a&H%02X\\1c&H%02X%02X%02X&}",
  449|      0|             px, py, 255 - bc.a, (int)bc.b, (int)bc.g, (int)bc.r);
  450|       |
  451|      0|        ass_draw_start(d);
  452|      0|        ass_draw_rect_cw(d, -border, -border, width + border, height + border);
  453|      0|        ass_draw_stop(d);
  454|      0|        add_osd_ass_event(track, "progbar", d->text);
  455|      0|        ass_draw_reset(d);
  456|      0|    }
  457|       |
  458|       |    // filled area
  459|      0|    d->text = talloc_asprintf_append(d->text, "{\\bord0\\pos(%f,%f)}", px, py);
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
  460|      0|    ass_draw_start(d);
  461|      0|    float pos = obj->progbar_state.value * width - border / 2;
  462|      0|    ass_draw_rect_cw(d, 0, 0, pos, height);
  463|      0|    ass_draw_stop(d);
  464|      0|    add_osd_ass_event(track, "progbar", d->text);
  465|      0|    ass_draw_reset(d);
  466|       |
  467|       |    // position marker
  468|      0|    d->text = talloc_asprintf_append(d->text, "{\\bord%f\\pos(%f,%f)}",
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
  469|      0|                                     border / 2, px, py);
  470|      0|    ass_draw_start(d);
  471|      0|    ass_draw_move_to(d, pos + border / 2, 0);
  472|      0|    ass_draw_line_to(d, pos + border / 2, height);
  473|      0|    ass_draw_stop(d);
  474|      0|    add_osd_ass_event(track, "progbar", d->text);
  475|      0|    ass_draw_reset(d);
  476|       |
  477|      0|    d->text = talloc_asprintf_append(d->text, "{\\pos(%f,%f)}", px, py);
  ------------------
  |  |   63|      0|#define talloc_asprintf_append          ta_talloc_asprintf_append
  ------------------
  478|      0|    ass_draw_start(d);
  479|       |
  480|       |    // the box
  481|      0|    ass_draw_rect_cw(d, -border, -border, width + border, height + border);
  482|       |
  483|       |    // the "hole"
  484|      0|    ass_draw_rect_ccw(d, 0, 0, width, height);
  485|       |
  486|      0|    struct osd_bar_style_opts *bar_opts = osd->opts->osd_bar_style;
  487|       |    // chapter marks
  488|      0|    if (bar_opts->marker_style) {
  ------------------
  |  Branch (488:9): [True: 0, False: 0]
  ------------------
  489|      0|        for (int n = 0; n < obj->progbar_state.num_stops; n++) {
  ------------------
  |  Branch (489:25): [True: 0, False: 0]
  ------------------
  490|      0|            float s = obj->progbar_state.stops[n] * width;
  491|      0|            float size = MPMAX(border * bar_opts->marker_scale,
  ------------------
  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  492|      0|                               bar_opts->marker_min_size);
  493|       |
  494|      0|            if (bar_opts->marker_style == 2 &&
  ------------------
  |  Branch (494:17): [True: 0, False: 0]
  ------------------
  495|      0|                s > size / 2 && s < width - size / 2)
  ------------------
  |  Branch (495:17): [True: 0, False: 0]
  |  Branch (495:33): [True: 0, False: 0]
  ------------------
  496|      0|            { // line
  497|      0|                ass_draw_rect_cw(d, s - size / 2, 0, s + size / 2, height);
  498|      0|            } else if (s > size && s < width - size) { //triangle
  ------------------
  |  Branch (498:24): [True: 0, False: 0]
  |  Branch (498:36): [True: 0, False: 0]
  ------------------
  499|      0|                ass_draw_move_to(d, s + size, 0);
  500|      0|                ass_draw_line_to(d, s,        size);
  501|      0|                ass_draw_line_to(d, s - size, 0);
  502|       |
  503|      0|                ass_draw_move_to(d, s - size, height);
  504|      0|                ass_draw_line_to(d, s,        height - size);
  505|      0|                ass_draw_line_to(d, s + size, height);
  506|      0|            }
  507|      0|        }
  508|      0|    }
  509|       |
  510|      0|    ass_draw_stop(d);
  511|      0|    add_osd_ass_event(track, "progbar", d->text);
  512|      0|    ass_draw_reset(d);
  513|      0|}
osd_libass.c:update_playres:
   96|     86|{
   97|     86|    ASS_Track *track = ass->track;
   98|     86|    int old_res_x = track->PlayResX;
   99|     86|    int old_res_y = track->PlayResY;
  100|       |
  101|     86|    ass->vo_res = *vo_res;
  102|       |
  103|     86|    double aspect = 1.0 * vo_res->w / MPMAX(vo_res->h, 1);
  ------------------
  |  |   43|     86|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 86, False: 0]
  |  |  ------------------
  ------------------
  104|     86|    if (vo_res->display_par > 0)
  ------------------
  |  Branch (104:9): [True: 86, False: 0]
  ------------------
  105|     86|        aspect = aspect / vo_res->display_par;
  106|       |
  107|     86|    track->PlayResY = ass->res_y ? ass->res_y : MP_ASS_FONT_PLAYRESY;
  ------------------
  |  |   33|    172|#define MP_ASS_FONT_PLAYRESY 288
  ------------------
  |  Branch (107:23): [True: 0, False: 86]
  ------------------
  108|     86|    track->PlayResX = ass->res_x ? ass->res_x : track->PlayResY * aspect;
  ------------------
  |  Branch (108:23): [True: 0, False: 86]
  ------------------
  109|       |
  110|       |    // Force libass to clear its internal cache - it doesn't check for
  111|       |    // PlayRes changes itself.
  112|     86|    if (old_res_x != track->PlayResX || old_res_y != track->PlayResY)
  ------------------
  |  Branch (112:9): [True: 34, False: 52]
  |  Branch (112:41): [True: 0, False: 52]
  ------------------
  113|     34|        ass_set_frame_size(ass->render, 1, 1);
  114|     86|}

ta_set_parent:
   88|   296M|{
   89|   296M|    struct ta_header *ch = get_header(ptr);
   90|   296M|    if (!ch)
  ------------------
  |  Branch (90:9): [True: 12.5k, False: 296M]
  ------------------
   91|  12.5k|        return;
   92|   296M|    struct ta_header *new_parent = get_header(ta_parent);
   93|       |    // Unlink from previous parent
   94|   296M|    if (ch->prev)
  ------------------
  |  Branch (94:9): [True: 102k, False: 296M]
  ------------------
   95|   102k|        ch->prev->next = ch->next;
   96|   296M|    if (ch->next)
  ------------------
  |  Branch (96:9): [True: 50.5M, False: 246M]
  ------------------
   97|  50.5M|        ch->next->prev = ch->prev;
   98|       |    // If ch was the first child, change child link of old parent
   99|   296M|    if (ch->parent) {
  ------------------
  |  Branch (99:9): [True: 65.8M, False: 230M]
  ------------------
  100|  65.8M|        assert(ch->parent->child == ch);
  101|  65.8M|        ch->parent->child = ch->next;
  102|  65.8M|        if (ch->parent->child) {
  ------------------
  |  Branch (102:13): [True: 50.4M, False: 15.3M]
  ------------------
  103|  50.4M|            assert(!ch->parent->child->parent);
  104|  50.4M|            ch->parent->child->parent = ch->parent;
  105|  50.4M|        }
  106|  65.8M|    }
  107|   296M|    ch->next = ch->prev = ch->parent = NULL;
  108|       |    // Link to new parent - insert at start of list (LIFO destructor order)
  109|   296M|    if (new_parent) {
  ------------------
  |  Branch (109:9): [True: 65.9M, False: 230M]
  ------------------
  110|  65.9M|        ch->next = new_parent->child;
  111|  65.9M|        if (ch->next) {
  ------------------
  |  Branch (111:13): [True: 50.5M, False: 15.3M]
  ------------------
  112|  50.5M|            ch->next->prev = ch;
  113|  50.5M|            ch->next->parent = NULL;
  114|  50.5M|        }
  115|  65.9M|        new_parent->child = ch;
  116|  65.9M|        ch->parent = new_parent;
  117|  65.9M|    }
  118|   296M|}
ta_alloc_size:
  136|  98.4M|{
  137|  98.4M|    if (size >= MAX_ALLOC)
  ------------------
  |  |   66|  98.4M|#define MAX_ALLOC (((size_t)-1) - sizeof(union aligned_header))
  ------------------
  |  Branch (137:9): [True: 0, False: 98.4M]
  ------------------
  138|      0|        return NULL;
  139|  98.4M|    struct ta_header *h = malloc(sizeof(union aligned_header) + size);
  140|  98.4M|    if (!h)
  ------------------
  |  Branch (140:9): [True: 0, False: 98.4M]
  ------------------
  141|      0|        return NULL;
  142|  98.4M|    *h = (struct ta_header) {.size = size};
  143|  98.4M|    ta_dbg_add(h);
  144|  98.4M|    void *ptr = PTR_FROM_HEADER(h);
  ------------------
  |  |   64|  98.4M|#define PTR_FROM_HEADER(h) ((void *)((union aligned_header *)(h) + 1))
  ------------------
  145|  98.4M|    ta_set_parent(ptr, ta_parent);
  146|  98.4M|    return ptr;
  147|  98.4M|}
ta_zalloc_size:
  153|  12.9M|{
  154|  12.9M|    if (size >= MAX_ALLOC)
  ------------------
  |  |   66|  12.9M|#define MAX_ALLOC (((size_t)-1) - sizeof(union aligned_header))
  ------------------
  |  Branch (154:9): [True: 0, False: 12.9M]
  ------------------
  155|      0|        return NULL;
  156|  12.9M|    struct ta_header *h = calloc(1, sizeof(union aligned_header) + size);
  157|  12.9M|    if (!h)
  ------------------
  |  Branch (157:9): [True: 0, False: 12.9M]
  ------------------
  158|      0|        return NULL;
  159|  12.9M|    *h = (struct ta_header) {.size = size};
  160|  12.9M|    ta_dbg_add(h);
  161|  12.9M|    void *ptr = PTR_FROM_HEADER(h);
  ------------------
  |  |   64|  12.9M|#define PTR_FROM_HEADER(h) ((void *)((union aligned_header *)(h) + 1))
  ------------------
  162|  12.9M|    ta_set_parent(ptr, ta_parent);
  163|  12.9M|    return ptr;
  164|  12.9M|}
ta_realloc_size:
  179|  93.5M|{
  180|  93.5M|    if (size >= MAX_ALLOC)
  ------------------
  |  |   66|  93.5M|#define MAX_ALLOC (((size_t)-1) - sizeof(union aligned_header))
  ------------------
  |  Branch (180:9): [True: 0, False: 93.5M]
  ------------------
  181|      0|        return NULL;
  182|  93.5M|    if (!size) {
  ------------------
  |  Branch (182:9): [True: 628, False: 93.5M]
  ------------------
  183|    628|        ta_free(ptr);
  184|    628|        return NULL;
  185|    628|    }
  186|  93.5M|    if (!ptr)
  ------------------
  |  Branch (186:9): [True: 79.9M, False: 13.6M]
  ------------------
  187|  79.9M|        return ta_alloc_size(ta_parent, size);
  188|  13.6M|    struct ta_header *h = get_header(ptr);
  189|  13.6M|    struct ta_header *old_h = h;
  190|  13.6M|    if (h->size == size)
  ------------------
  |  Branch (190:9): [True: 725, False: 13.6M]
  ------------------
  191|    725|        return ptr;
  192|  13.6M|    ta_dbg_remove(h);
  193|  13.6M|    h = realloc(h, sizeof(union aligned_header) + size);
  194|  18.4E|    ta_dbg_add(h ? h : old_h);
  ------------------
  |  Branch (194:16): [True: 13.6M, False: 18.4E]
  ------------------
  195|  13.6M|    if (!h)
  ------------------
  |  Branch (195:9): [True: 0, False: 13.6M]
  ------------------
  196|      0|        return NULL;
  197|  13.6M|    h->size = size;
  198|  13.6M|    if (h != old_h) {
  ------------------
  |  Branch (198:9): [True: 3.20M, False: 10.4M]
  ------------------
  199|       |        // Relink parent
  200|  3.20M|        if (h->parent)
  ------------------
  |  Branch (200:13): [True: 647k, False: 2.55M]
  ------------------
  201|   647k|            h->parent->child = h;
  202|       |        // Relink siblings
  203|  3.20M|        if (h->next)
  ------------------
  |  Branch (203:13): [True: 1.20M, False: 2.00M]
  ------------------
  204|  1.20M|            h->next->prev = h;
  205|  3.20M|        if (h->prev)
  ------------------
  |  Branch (205:13): [True: 1.55M, False: 1.65M]
  ------------------
  206|  1.55M|            h->prev->next = h;
  207|       |        // Relink children
  208|  3.20M|        if (h->child)
  ------------------
  |  Branch (208:13): [True: 142k, False: 3.06M]
  ------------------
  209|   142k|            h->child->parent = h;
  210|  3.20M|    }
  211|  13.6M|    return PTR_FROM_HEADER(h);
  ------------------
  |  |   64|  13.6M|#define PTR_FROM_HEADER(h) ((void *)((union aligned_header *)(h) + 1))
  ------------------
  212|  13.6M|}
ta_get_size:
  219|   235M|{
  220|   235M|    struct ta_header *h = get_header(ptr);
  221|   235M|    return h ? h->size : 0;
  ------------------
  |  Branch (221:12): [True: 81.3M, False: 154M]
  ------------------
  222|   235M|}
ta_free_children:
  228|   113M|{
  229|   113M|    struct ta_header *h = get_header(ptr);
  230|   178M|    while (h && h->child)
  ------------------
  |  Branch (230:12): [True: 178M, False: 645]
  |  Branch (230:17): [True: 65.6M, False: 113M]
  ------------------
  231|  65.6M|        ta_free(PTR_FROM_HEADER(h->child));
  ------------------
  |  |   64|  65.6M|#define PTR_FROM_HEADER(h) ((void *)((union aligned_header *)(h) + 1))
  ------------------
  232|   113M|}
ta_free:
  237|   124M|{
  238|   124M|    struct ta_header *h = get_header(ptr);
  239|   124M|    if (!h)
  ------------------
  |  Branch (239:9): [True: 13.1M, False: 111M]
  ------------------
  240|  13.1M|        return;
  241|   111M|    if (h->destructor)
  ------------------
  |  Branch (241:9): [True: 11.8M, False: 99.5M]
  ------------------
  242|  11.8M|        h->destructor(ptr);
  243|   111M|    ta_free_children(ptr);
  244|   111M|    ta_set_parent(ptr, NULL);
  245|   111M|    ta_dbg_remove(h);
  246|   111M|    free(h);
  247|   111M|}
ta_set_destructor:
  260|  11.8M|{
  261|  11.8M|    struct ta_header *h = get_header(ptr);
  262|  11.8M|    if (h)
  ------------------
  |  Branch (262:9): [True: 11.8M, False: 0]
  ------------------
  263|  11.8M|        h->destructor = destructor;
  264|  11.8M|}
ta_dbg_set_loc:
  379|   122M|{
  380|   122M|    struct ta_header *h = get_header(ptr);
  381|   122M|    if (h)
  ------------------
  |  Branch (381:9): [True: 122M, False: 118k]
  ------------------
  382|   122M|        h->name = loc;
  383|   122M|    return ptr;
  384|   122M|}
ta_dbg_mark_as_string:
  389|  82.8M|{
  390|       |    // Specially handled by leak report code.
  391|  82.8M|    return ta_dbg_set_loc(ptr, &allocation_is_string);
  392|  82.8M|}
ta.c:get_header:
   73|  1.21G|{
   74|  1.21G|    struct ta_header *h = ptr ? PTR_TO_HEADER(ptr) : NULL;
  ------------------
  |  |   63|   816M|#define PTR_TO_HEADER(ptr) (&((union aligned_header *)(ptr) - 1)->ta)
  ------------------
  |  Branch (74:27): [True: 816M, False: 398M]
  ------------------
   75|  1.21G|    ta_dbg_check_header(h);
   76|  1.21G|    return h;
   77|  1.21G|}
ta.c:ta_dbg_check_header:
  289|  1.33G|{
  290|  1.33G|    if (h) {
  ------------------
  |  Branch (290:9): [True: 941M, False: 398M]
  ------------------
  291|   941M|        assert(h->canary == CANARY);
  292|   941M|        if (h->parent) {
  ------------------
  |  Branch (292:13): [True: 260M, False: 680M]
  ------------------
  293|   260M|            assert(!h->prev);
  294|   260M|            assert(h->parent->child == h);
  295|   260M|        }
  296|   941M|    }
  297|  1.33G|}
ta.c:ta_dbg_add:
  276|   125M|{
  277|   125M|    h->canary = CANARY;
  ------------------
  |  |   50|   125M|#define CANARY 0xD3ADB3EF
  ------------------
  278|   125M|    if (enable_leak_check) {
  ------------------
  |  Branch (278:9): [True: 0, False: 125M]
  ------------------
  279|      0|        mp_mutex_lock(&ta_dbg_mutex);
  ------------------
  |  |  131|      0|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  280|      0|        h->leak_next = &leak_node;
  281|      0|        h->leak_prev = leak_node.leak_prev;
  282|      0|        leak_node.leak_prev->leak_next = h;
  283|      0|        leak_node.leak_prev = h;
  284|      0|        mp_mutex_unlock(&ta_dbg_mutex);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  285|      0|    }
  286|   125M|}
ta.c:ta_dbg_remove:
  300|   125M|{
  301|   125M|    ta_dbg_check_header(h);
  302|   125M|    if (h->leak_next) { // assume checking for !=NULL invariant ok without lock
  ------------------
  |  Branch (302:9): [True: 0, False: 125M]
  ------------------
  303|      0|        mp_mutex_lock(&ta_dbg_mutex);
  ------------------
  |  |  131|      0|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  304|      0|        h->leak_next->leak_prev = h->leak_prev;
  305|      0|        h->leak_prev->leak_next = h->leak_next;
  306|      0|        mp_mutex_unlock(&ta_dbg_mutex);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  307|      0|        h->leak_next = h->leak_prev = NULL;
  308|      0|    }
  309|   125M|    h->canary = 0;
  310|   125M|}

ao.c:ta_oom_p:
  162|     42|{
  163|     42|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 42]
  ------------------
  164|      0|        abort();
  165|     42|    return p;
  166|     42|}
encode_lavc.c:ta_oom_p:
  162|    618|{
  163|    618|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 618]
  ------------------
  164|      0|        abort();
  165|    618|    return p;
  166|    618|}
msg.c:ta_oom_p:
  162|  1.63M|{
  163|  1.63M|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 1.63M]
  ------------------
  164|      0|        abort();
  165|  1.63M|    return p;
  166|  1.63M|}
msg.c:ta_oom_s:
  175|   126k|{
  176|   126k|    if (!s)
  ------------------
  |  Branch (176:9): [True: 0, False: 126k]
  ------------------
  177|      0|        abort();
  178|   126k|    return s;
  179|   126k|}
playlist.c:ta_oom_p:
  162|  96.3k|{
  163|  96.3k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 96.3k]
  ------------------
  164|      0|        abort();
  165|  96.3k|    return p;
  166|  96.3k|}
stats.c:ta_oom_p:
  162|  66.2k|{
  163|  66.2k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 66.2k]
  ------------------
  164|      0|        abort();
  165|  66.2k|    return p;
  166|  66.2k|}
stats.c:ta_oom_s:
  175|  12.1k|{
  176|  12.1k|    if (!s)
  ------------------
  |  Branch (176:9): [True: 0, False: 12.1k]
  ------------------
  177|      0|        abort();
  178|  12.1k|    return s;
  179|  12.1k|}
tags.c:ta_oom_p:
  162|    321|{
  163|    321|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 321]
  ------------------
  164|      0|        abort();
  165|    321|    return p;
  166|    321|}
demux.c:ta_oom_p:
  162|  11.9k|{
  163|  11.9k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 11.9k]
  ------------------
  164|      0|        abort();
  165|  11.9k|    return p;
  166|  11.9k|}
demux_disc.c:ta_oom_p:
  162|    304|{
  163|    304|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 304]
  ------------------
  164|      0|        abort();
  165|    304|    return p;
  166|    304|}
demux_edl.c:ta_oom_p:
  162|  1.27k|{
  163|  1.27k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 1.27k]
  ------------------
  164|      0|        abort();
  165|  1.27k|    return p;
  166|  1.27k|}
demux_lavf.c:ta_oom_p:
  162|    373|{
  163|    373|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 373]
  ------------------
  164|      0|        abort();
  165|    373|    return p;
  166|    373|}
demux_mf.c:ta_oom_p:
  162|     55|{
  163|     55|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 55]
  ------------------
  164|      0|        abort();
  165|     55|    return p;
  166|     55|}
demux_mkv.c:ta_oom_p:
  162|    280|{
  163|    280|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 280]
  ------------------
  164|      0|        abort();
  165|    280|    return p;
  166|    280|}
demux_mpv.c:ta_oom_p:
  162|     82|{
  163|     82|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 82]
  ------------------
  164|      0|        abort();
  165|     82|    return p;
  166|     82|}
demux_playlist.c:ta_oom_p:
  162|    866|{
  163|    866|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 866]
  ------------------
  164|      0|        abort();
  165|    866|    return p;
  166|    866|}
demux_timeline.c:ta_oom_p:
  162|     94|{
  163|     94|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 94]
  ------------------
  164|      0|        abort();
  165|     94|    return p;
  166|     94|}
demux_timeline.c:ta_oom_s:
  175|     18|{
  176|     18|    if (!s)
  ------------------
  |  Branch (176:9): [True: 0, False: 18]
  ------------------
  177|      0|        abort();
  178|     18|    return s;
  179|     18|}
packet_pool.c:ta_oom_p:
  162|  17.0k|{
  163|  17.0k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 17.0k]
  ------------------
  164|      0|        abort();
  165|  17.0k|    return p;
  166|  17.0k|}
timeline.c:ta_oom_p:
  162|    130|{
  163|    130|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 130]
  ------------------
  164|      0|        abort();
  165|    130|    return p;
  166|    130|}
f_decoder_wrapper.c:ta_oom_p:
  162|  5.16k|{
  163|  5.16k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 5.16k]
  ------------------
  164|      0|        abort();
  165|  5.16k|    return p;
  166|  5.16k|}
filter.c:ta_oom_p:
  162|  11.7k|{
  163|  11.7k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 11.7k]
  ------------------
  164|      0|        abort();
  165|  11.7k|    return p;
  166|  11.7k|}
cmd.c:ta_oom_p:
  162|  5.26M|{
  163|  5.26M|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 5.26M]
  ------------------
  164|      0|        abort();
  165|  5.26M|    return p;
  166|  5.26M|}
input.c:ta_oom_s:
  175|  2.66M|{
  176|  2.66M|    if (!s)
  ------------------
  |  Branch (176:9): [True: 0, False: 2.66M]
  ------------------
  177|      0|        abort();
  178|  2.66M|    return s;
  179|  2.66M|}
input.c:ta_oom_p:
  162|  94.9k|{
  163|  94.9k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 94.9k]
  ------------------
  164|      0|        abort();
  165|  94.9k|    return p;
  166|  94.9k|}
ipc.c:ta_oom_p:
  162|    337|{
  163|    337|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 337]
  ------------------
  164|      0|        abort();
  165|    337|    return p;
  166|    337|}
bstr.c:ta_oom_p:
  162|    751|{
  163|    751|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 751]
  ------------------
  164|      0|        abort();
  165|    751|    return p;
  166|    751|}
charset_conv.c:ta_oom_p:
  162|    181|{
  163|    181|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 181]
  ------------------
  164|      0|        abort();
  165|    181|    return p;
  166|    181|}
dispatch.c:ta_oom_p:
  162|  17.1k|{
  163|  17.1k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 17.1k]
  ------------------
  164|      0|        abort();
  165|  17.1k|    return p;
  166|  17.1k|}
node.c:ta_oom_p:
  162|  39.4k|{
  163|  39.4k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 39.4k]
  ------------------
  164|      0|        abort();
  165|  39.4k|    return p;
  166|  39.4k|}
path_utils.c:ta_oom_s:
  175|   124k|{
  176|   124k|    if (!s)
  ------------------
  |  Branch (176:9): [True: 0, False: 124k]
  ------------------
  177|      0|        abort();
  178|   124k|    return s;
  179|   124k|}
path_utils.c:ta_oom_p:
  162|  63.3k|{
  163|  63.3k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 63.3k]
  ------------------
  164|      0|        abort();
  165|  63.3k|    return p;
  166|  63.3k|}
thread_pool.c:ta_oom_p:
  162|  17.0k|{
  163|  17.0k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 17.0k]
  ------------------
  164|      0|        abort();
  165|  17.0k|    return p;
  166|  17.0k|}
thread_tools.c:ta_oom_p:
  162|  18.1k|{
  163|  18.1k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 18.1k]
  ------------------
  164|      0|        abort();
  165|  18.1k|    return p;
  166|  18.1k|}
m_config_core.c:ta_oom_p:
  162|  2.68M|{
  163|  2.68M|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 2.68M]
  ------------------
  164|      0|        abort();
  165|  2.68M|    return p;
  166|  2.68M|}
m_config_frontend.c:ta_oom_p:
  162|  17.1M|{
  163|  17.1M|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 17.1M]
  ------------------
  164|      0|        abort();
  165|  17.1M|    return p;
  166|  17.1M|}
m_option.c:ta_oom_s:
  175|  16.0k|{
  176|  16.0k|    if (!s)
  ------------------
  |  Branch (176:9): [True: 0, False: 16.0k]
  ------------------
  177|      0|        abort();
  178|  16.0k|    return s;
  179|  16.0k|}
m_option.c:ta_oom_p:
  162|  2.71M|{
  163|  2.71M|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 2.71M]
  ------------------
  164|      0|        abort();
  165|  2.71M|    return p;
  166|  2.71M|}
m_option.c:ta_oom_b:
  169|  10.9k|{
  170|  10.9k|    if (!b)
  ------------------
  |  Branch (170:9): [True: 0, False: 10.9k]
  ------------------
  171|      0|        abort();
  172|  10.9k|}
m_property.c:ta_oom_p:
  162|   527k|{
  163|   527k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 527k]
  ------------------
  164|      0|        abort();
  165|   527k|    return p;
  166|   527k|}
m_property.c:ta_oom_b:
  169|   150k|{
  170|   150k|    if (!b)
  ------------------
  |  Branch (170:9): [True: 0, False: 150k]
  ------------------
  171|      0|        abort();
  172|   150k|}
parse_commandline.c:ta_oom_p:
  162|  95.4k|{
  163|  95.4k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 95.4k]
  ------------------
  164|      0|        abort();
  165|  95.4k|    return p;
  166|  95.4k|}
parse_configfile.c:ta_oom_p:
  162|  17.0k|{
  163|  17.0k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 17.0k]
  ------------------
  164|      0|        abort();
  165|  17.0k|    return p;
  166|  17.0k|}
path.c:ta_oom_p:
  162|   179k|{
  163|   179k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 179k]
  ------------------
  164|      0|        abort();
  165|   179k|    return p;
  166|   179k|}
client.c:ta_oom_p:
  162|  83.9k|{
  163|  83.9k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 83.9k]
  ------------------
  164|      0|        abort();
  165|  83.9k|    return p;
  166|  83.9k|}
command.c:ta_oom_p:
  162|  74.4k|{
  163|  74.4k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 74.4k]
  ------------------
  164|      0|        abort();
  165|  74.4k|    return p;
  166|  74.4k|}
command.c:ta_oom_s:
  175|    250|{
  176|    250|    if (!s)
  ------------------
  |  Branch (176:9): [True: 0, False: 250]
  ------------------
  177|      0|        abort();
  178|    250|    return s;
  179|    250|}
configfiles.c:ta_oom_p:
  162|  66.7k|{
  163|  66.7k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 66.7k]
  ------------------
  164|      0|        abort();
  165|  66.7k|    return p;
  166|  66.7k|}
main.c:ta_oom_p:
  162|  51.2k|{
  163|  51.2k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 51.2k]
  ------------------
  164|      0|        abort();
  165|  51.2k|    return p;
  166|  51.2k|}
osd.c:ta_oom_b:
  169|    397|{
  170|    397|    if (!b)
  ------------------
  |  Branch (170:9): [True: 0, False: 397]
  ------------------
  171|      0|        abort();
  172|    397|}
osd.c:ta_oom_p:
  162|   102k|{
  163|   102k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 102k]
  ------------------
  164|      0|        abort();
  165|   102k|    return p;
  166|   102k|}
screenshot.c:ta_oom_p:
  162|  17.0k|{
  163|  17.0k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 17.0k]
  ------------------
  164|      0|        abort();
  165|  17.0k|    return p;
  166|  17.0k|}
scripting.c:ta_oom_s:
  175|  18.6k|{
  176|  18.6k|    if (!s)
  ------------------
  |  Branch (176:9): [True: 0, False: 18.6k]
  ------------------
  177|      0|        abort();
  178|  18.6k|    return s;
  179|  18.6k|}
scripting.c:ta_oom_p:
  162|  31.1k|{
  163|  31.1k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 31.1k]
  ------------------
  164|      0|        abort();
  165|  31.1k|    return p;
  166|  31.1k|}
clipboard.c:ta_oom_p:
  162|  12.1k|{
  163|  12.1k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 12.1k]
  ------------------
  164|      0|        abort();
  165|  12.1k|    return p;
  166|  12.1k|}
clipboard-vo.c:ta_oom_p:
  162|  12.1k|{
  163|  12.1k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 12.1k]
  ------------------
  164|      0|        abort();
  165|  12.1k|    return p;
  166|  12.1k|}
cookies.c:ta_oom_p:
  162|      1|{
  163|      1|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 1]
  ------------------
  164|      0|        abort();
  165|      1|    return p;
  166|      1|}
stream.c:ta_oom_p:
  162|  6.14k|{
  163|  6.14k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 6.14k]
  ------------------
  164|      0|        abort();
  165|  6.14k|    return p;
  166|  6.14k|}
stream_cb.c:ta_oom_p:
  162|  1.97k|{
  163|  1.97k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 1.97k]
  ------------------
  164|      0|        abort();
  165|  1.97k|    return p;
  166|  1.97k|}
stream_file.c:ta_oom_p:
  162|    478|{
  163|    478|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 478]
  ------------------
  164|      0|        abort();
  165|    478|    return p;
  166|    478|}
stream_lavf.c:ta_oom_p:
  162|  4.09k|{
  163|  4.09k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 4.09k]
  ------------------
  164|      0|        abort();
  165|  4.09k|    return p;
  166|  4.09k|}
stream_lavf.c:ta_oom_s:
  175|     41|{
  176|     41|    if (!s)
  ------------------
  |  Branch (176:9): [True: 0, False: 41]
  ------------------
  177|      0|        abort();
  178|     41|    return s;
  179|     41|}
stream_memory.c:ta_oom_p:
  162|  1.24k|{
  163|  1.24k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 1.24k]
  ------------------
  164|      0|        abort();
  165|  1.24k|    return p;
  166|  1.24k|}
ass_mp.c:ta_oom_p:
  162|    190|{
  163|    190|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 190]
  ------------------
  164|      0|        abort();
  165|    190|    return p;
  166|    190|}
draw_bmp.c:ta_oom_p:
  162|     90|{
  163|     90|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 90]
  ------------------
  164|      0|        abort();
  165|     90|    return p;
  166|     90|}
mp_image.c:ta_oom_p:
  162|    309|{
  163|    309|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 309]
  ------------------
  164|      0|        abort();
  165|    309|    return p;
  166|    309|}
bitmap_packer.c:ta_oom_p:
  162|     62|{
  163|     62|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 62]
  ------------------
  164|      0|        abort();
  165|     62|    return p;
  166|     62|}
dr_helper.c:ta_oom_p:
  162|     17|{
  163|     17|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 17]
  ------------------
  164|      0|        abort();
  165|     17|    return p;
  166|     17|}
context.c:ta_oom_p:
  162|     33|{
  163|     33|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 33]
  ------------------
  164|      0|        abort();
  165|     33|    return p;
  166|     33|}
vo.c:ta_oom_p:
  162|    191|{
  163|    191|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 191]
  ------------------
  164|      0|        abort();
  165|    191|    return p;
  166|    191|}
vo_kitty.c:ta_oom_p:
  162|     78|{
  163|     78|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 78]
  ------------------
  164|      0|        abort();
  165|     78|    return p;
  166|     78|}
repack.c:ta_oom_p:
  162|    180|{
  163|    180|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 180]
  ------------------
  164|      0|        abort();
  165|    180|    return p;
  166|    180|}
sws_utils.c:ta_oom_p:
  162|    198|{
  163|    198|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 198]
  ------------------
  164|      0|        abort();
  165|    198|    return p;
  166|    198|}
ta_talloc.c:ta_oom_b:
  169|  9.49M|{
  170|  9.49M|    if (!b)
  ------------------
  |  Branch (170:9): [True: 0, False: 9.49M]
  ------------------
  171|      0|        abort();
  172|  9.49M|}
ta_utils.c:ta_oom_b:
  169|  86.9M|{
  170|  86.9M|    if (!b)
  ------------------
  |  Branch (170:9): [True: 0, False: 86.9M]
  ------------------
  171|      0|        abort();
  172|  86.9M|}
ipc-unix.c:ta_oom_p:
  162|  16.4k|{
  163|  16.4k|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 16.4k]
  ------------------
  164|      0|        abort();
  165|  16.4k|    return p;
  166|  16.4k|}
ipc-unix.c:ta_oom_s:
  175|  4.32k|{
  176|  4.32k|    if (!s)
  ------------------
  |  Branch (176:9): [True: 0, False: 4.32k]
  ------------------
  177|      0|        abort();
  178|  4.32k|    return s;
  179|  4.32k|}
stream_dvb.c:ta_oom_p:
  162|      2|{
  163|      2|    if (!p)
  ------------------
  |  Branch (163:9): [True: 0, False: 2]
  ------------------
  164|      0|        abort();
  165|      2|    return p;
  166|      2|}

ta_talloc_strdup_append:
   24|  8.33k|{
   25|  8.33k|    ta_xstrdup_append(&s, a);
  ------------------
  |  |  123|  8.33k|#define ta_xstrdup_append(...)          ta_oom_b(ta_strdup_append(__VA_ARGS__))
  ------------------
   26|  8.33k|    return s;
   27|  8.33k|}
ta_talloc_strdup_append_buffer:
   30|  4.22M|{
   31|  4.22M|    ta_xstrdup_append_buffer(&s, a);
  ------------------
  |  |  124|  4.22M|#define ta_xstrdup_append_buffer(...)   ta_oom_b(ta_strdup_append_buffer(__VA_ARGS__))
  ------------------
   32|  4.22M|    return s;
   33|  4.22M|}
ta_talloc_strndup_append_buffer:
   42|  4.18M|{
   43|  4.18M|    ta_xstrndup_append_buffer(&s, a, n);
  ------------------
  |  |  126|  4.18M|#define ta_xstrndup_append_buffer(...)  ta_oom_b(ta_strndup_append_buffer(__VA_ARGS__))
  ------------------
   44|  4.18M|    return s;
   45|  4.18M|}
ta_talloc_vasprintf_append:
   48|  1.06M|{
   49|  1.06M|    ta_xvasprintf_append(&s, fmt, ap);
  ------------------
  |  |  130|  1.06M|#define ta_xvasprintf_append(...)       ta_oom_b(ta_vasprintf_append(__VA_ARGS__))
  ------------------
   50|  1.06M|    return s;
   51|  1.06M|}
ta_talloc_vasprintf_append_buffer:
   54|  7.15k|{
   55|  7.15k|    ta_xvasprintf_append_buffer(&s, fmt, ap);
  ------------------
  |  |  132|  7.15k|#define ta_xvasprintf_append_buffer(...) ta_oom_b(ta_vasprintf_append_buffer(__VA_ARGS__))
  ------------------
   56|  7.15k|    return s;
   57|  7.15k|}
ta_talloc_asprintf_append:
   60|  1.06M|{
   61|  1.06M|    char *res;
   62|  1.06M|    va_list ap;
   63|  1.06M|    va_start(ap, fmt);
   64|  1.06M|    res = talloc_vasprintf_append(s, fmt, ap);
  ------------------
  |  |   61|  1.06M|#define talloc_vasprintf_append         ta_talloc_vasprintf_append
  ------------------
   65|  1.06M|    va_end(ap);
   66|  1.06M|    return res;
   67|  1.06M|}
ta_talloc_asprintf_append_buffer:
   70|  7.15k|{
   71|  7.15k|    char *res;
   72|  7.15k|    va_list ap;
   73|  7.15k|    va_start(ap, fmt);
   74|  7.15k|    res = talloc_vasprintf_append_buffer(s, fmt, ap);
  ------------------
  |  |   62|  7.15k|#define talloc_vasprintf_append_buffer  ta_talloc_vasprintf_append_buffer
  ------------------
   75|  7.15k|    va_end(ap);
   76|  7.15k|    return res;
   77|  7.15k|}

ta_calc_array_size:
   30|  9.56M|{
   31|  9.56M|    if (count > (((size_t)-1) / element_size))
  ------------------
  |  Branch (31:9): [True: 0, False: 9.56M]
  ------------------
   32|      0|        return (size_t)-1;
   33|  9.56M|    return element_size * count;
   34|  9.56M|}
ta_calc_prealloc_elems:
   41|  6.10M|{
   42|  6.10M|    if (nextidx >= ((size_t)-1) / 2 - 1)
  ------------------
  |  Branch (42:9): [True: 0, False: 6.10M]
  ------------------
   43|      0|        return (size_t)-1;
   44|  6.10M|    return (nextidx + 1) * 2;
   45|  6.10M|}
ta_new_context:
   50|  2.82M|{
   51|  2.82M|    return ta_alloc_size(ta_parent, 0);
   52|  2.82M|}
ta_steal_:
   58|   682k|{
   59|   682k|    ta_set_parent(ptr, ta_parent);
   60|   682k|    return ptr;
   61|   682k|}
ta_memdup:
   66|   513k|{
   67|   513k|    if (!ptr) {
  ------------------
  |  Branch (67:9): [True: 118k, False: 394k]
  ------------------
   68|   118k|        assert(!size);
   69|   118k|        return NULL;
   70|   118k|    }
   71|   394k|    void *res = ta_alloc_size(ta_parent, size);
   72|   394k|    if (!res)
  ------------------
  |  Branch (72:9): [True: 0, False: 394k]
  ------------------
   73|      0|        return NULL;
   74|   394k|    memcpy(res, ptr, size);
   75|   394k|    return res;
   76|   394k|}
ta_strdup:
  113|  57.5M|{
  114|  57.5M|    return ta_strndup(ta_parent, str, str ? strlen(str) : 0);
  ------------------
  |  Branch (114:39): [True: 51.9M, False: 5.55M]
  ------------------
  115|  57.5M|}
ta_strndup:
  123|  75.8M|{
  124|  75.8M|    if (!str)
  ------------------
  |  Branch (124:9): [True: 5.62M, False: 70.2M]
  ------------------
  125|  5.62M|        return NULL;
  126|  70.2M|    char *new = NULL;
  127|  70.2M|    strndup_append_at(&new, 0, str, n);
  128|  70.2M|    ta_set_parent(new, ta_parent);
  129|  70.2M|    return new;
  130|  75.8M|}
ta_strdup_append:
  137|  19.7k|{
  138|  19.7k|    return strndup_append_at(str, *str ? strlen(*str) : 0, a, (size_t)-1);
  ------------------
  |  Branch (138:35): [True: 14.8k, False: 4.88k]
  ------------------
  139|  19.7k|}
ta_strdup_append_buffer:
  145|  4.22M|{
  146|  4.22M|    size_t size = ta_get_size(*str);
  147|  4.22M|    if (size > 0)
  ------------------
  |  Branch (147:9): [True: 4.22M, False: 0]
  ------------------
  148|  4.22M|        size -= 1;
  149|  4.22M|    return strndup_append_at(str, size, a, (size_t)-1);
  150|  4.22M|}
ta_strndup_append_buffer:
  164|  4.18M|{
  165|  4.18M|    size_t size = ta_get_size(*str);
  166|  4.18M|    if (size > 0)
  ------------------
  |  Branch (166:9): [True: 4.18M, False: 0]
  ------------------
  167|  4.18M|        size -= 1;
  168|  4.18M|    return strndup_append_at(str, size, a, n);
  169|  4.18M|}
ta_asprintf:
  204|  2.97M|{
  205|  2.97M|    char *res;
  206|  2.97M|    va_list ap;
  207|  2.97M|    va_start(ap, fmt);
  208|  2.97M|    res = ta_vasprintf(ta_parent, fmt, ap);
  209|  2.97M|    va_end(ap);
  210|  2.97M|    return res;
  211|  2.97M|}
ta_vasprintf:
  214|  2.97M|{
  215|  2.97M|    char *res = NULL;
  216|  2.97M|    ta_vasprintf_append_at(&res, 0, fmt, ap);
  217|  2.97M|    ta_set_parent(res, ta_parent);
  218|  2.97M|    if (!res) {
  ------------------
  |  Branch (218:9): [True: 0, False: 2.97M]
  ------------------
  219|      0|        ta_free(res);
  220|      0|        return NULL;
  221|      0|    }
  222|  2.97M|    return res;
  223|  2.97M|}
ta_asprintf_append:
  230|   150k|{
  231|   150k|    bool res;
  232|   150k|    va_list ap;
  233|   150k|    va_start(ap, fmt);
  234|   150k|    res = ta_vasprintf_append(str, fmt, ap);
  235|   150k|    va_end(ap);
  236|   150k|    return res;
  237|   150k|}
ta_vasprintf_append:
  240|  1.21M|{
  241|  1.21M|    return ta_vasprintf_append_at(str, *str ? strlen(*str) : 0, fmt, ap);
  ------------------
  |  Branch (241:40): [True: 1.18M, False: 37.8k]
  ------------------
  242|  1.21M|}
ta_vasprintf_append_buffer:
  262|  7.15k|{
  263|  7.15k|    size_t size = ta_get_size(*str);
  264|  7.15k|    if (size > 0)
  ------------------
  |  Branch (264:9): [True: 7.15k, False: 0]
  ------------------
  265|  7.15k|        size -= 1;
  266|  7.15k|    return ta_vasprintf_append_at(str, size, fmt, ap);
  267|  7.15k|}
ta_xmemdup:
  270|   355k|{
  271|   355k|    void *new = ta_memdup(ta_parent, ptr, size);
  272|   355k|    ta_oom_b(new || !ptr);
  ------------------
  |  Branch (272:14): [True: 236k, False: 118k]
  |  Branch (272:21): [True: 118k, False: 0]
  ------------------
  273|   355k|    return new;
  274|   355k|}
ta_xrealloc_size:
  277|  10.7M|{
  278|  10.7M|    ptr = ta_realloc_size(ta_parent, ptr, size);
  279|  10.7M|    ta_oom_b(ptr || !size);
  ------------------
  |  Branch (279:14): [True: 10.7M, False: 628]
  |  Branch (279:21): [True: 628, False: 0]
  ------------------
  280|  10.7M|    return ptr;
  281|  10.7M|}
ta_xstrdup:
  284|  57.5M|{
  285|  57.5M|    char *res = ta_strdup(ta_parent, str);
  286|  57.5M|    ta_oom_b(res || !str);
  ------------------
  |  Branch (286:14): [True: 51.9M, False: 5.55M]
  |  Branch (286:21): [True: 5.55M, False: 0]
  ------------------
  287|  57.5M|    return res;
  288|  57.5M|}
ta_xstrndup:
  291|  18.3M|{
  292|  18.3M|    char *res = ta_strndup(ta_parent, str, n);
  293|  18.3M|    ta_oom_b(res || !str);
  ------------------
  |  Branch (293:14): [True: 18.3M, False: 73.8k]
  |  Branch (293:21): [True: 73.8k, False: 0]
  ------------------
  294|  18.3M|    return res;
  295|  18.3M|}
ta_utils.c:strndup_append_at:
   82|  78.6M|{
   83|  78.6M|    assert(ta_get_size(*str) >= at);
   84|       |
   85|  78.6M|    if (!*str && !append)
  ------------------
  |  Branch (85:9): [True: 70.2M, False: 8.42M]
  |  Branch (85:18): [True: 0, False: 70.2M]
  ------------------
   86|      0|        return true; // stays NULL, but not an OOM condition
   87|       |
   88|  18.4E|    size_t real_len = append ? strnlen(append, append_len) : 0;
  ------------------
  |  Branch (88:23): [True: 78.6M, False: 18.4E]
  ------------------
   89|  78.6M|    if (append_len > real_len)
  ------------------
  |  Branch (89:9): [True: 4.25M, False: 74.4M]
  ------------------
   90|  4.25M|        append_len = real_len;
   91|       |
   92|  78.6M|    if (ta_get_size(*str) < at + append_len + 1) {
  ------------------
  |  Branch (92:9): [True: 78.6M, False: 7.54k]
  ------------------
   93|  78.6M|        char *t = ta_realloc_size(NULL, *str, at + append_len + 1);
   94|  78.6M|        if (!t)
  ------------------
  |  Branch (94:13): [True: 0, False: 78.6M]
  ------------------
   95|      0|            return false;
   96|  78.6M|        *str = t;
   97|  78.6M|    }
   98|       |
   99|  78.6M|    if (append_len)
  ------------------
  |  Branch (99:9): [True: 77.9M, False: 772k]
  ------------------
  100|  77.9M|        memcpy(*str + at, append, append_len);
  101|       |
  102|  78.6M|    (*str)[at + append_len] = '\0';
  103|       |
  104|  78.6M|    ta_dbg_mark_as_string(*str);
  105|       |
  106|  78.6M|    return true;
  107|  78.6M|}
ta_utils.c:ta_vasprintf_append_at:
  174|  4.19M|{
  175|  4.19M|    assert(ta_get_size(*str) >= at);
  176|       |
  177|  4.19M|    int size;
  178|  4.19M|    va_list copy;
  179|  4.19M|    va_copy(copy, ap);
  180|  4.19M|    char c;
  181|  4.19M|    size = vsnprintf(&c, 1, fmt, copy);
  182|  4.19M|    va_end(copy);
  183|       |
  184|  4.19M|    if (size < 0)
  ------------------
  |  Branch (184:9): [True: 0, False: 4.19M]
  ------------------
  185|      0|        return false;
  186|       |
  187|  4.19M|    if (ta_get_size(*str) < at + size + 1) {
  ------------------
  |  Branch (187:9): [True: 4.19M, False: 18.4E]
  ------------------
  188|  4.19M|        char *t = ta_realloc_size(NULL, *str, at + size + 1);
  189|  4.19M|        if (!t)
  ------------------
  |  Branch (189:13): [True: 0, False: 4.19M]
  ------------------
  190|      0|            return false;
  191|  4.19M|        *str = t;
  192|  4.19M|    }
  193|  4.19M|    vsnprintf(*str + at, size + 1, fmt, ap);
  194|       |
  195|  4.19M|    ta_dbg_mark_as_string(*str);
  196|       |
  197|  4.19M|    return true;
  198|  4.19M|}

mp_csp_equalizer_create:
  508|      8|{
  509|      8|    struct m_config_cache *c = m_config_cache_alloc(ta_parent, global,
  510|      8|                                                    &mp_csp_equalizer_conf);
  511|       |    // The terrible, terrible truth.
  512|      8|    return (struct mp_csp_equalizer_state *)c;
  513|      8|}

vd_lavc.c:hwdec_opt_help:
  636|      1|{
  637|      1|    struct hwdec_info *hwdecs = NULL;
  638|      1|    int num_hwdecs = 0;
  639|      1|    add_all_hwdec_methods(&hwdecs, &num_hwdecs);
  640|       |
  641|      1|    mp_info(log, "Valid values (with alternative full names):\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  642|       |
  643|     10|    for (int n = 0; n < num_hwdecs; n++) {
  ------------------
  |  Branch (643:21): [True: 9, False: 1]
  ------------------
  644|      9|        struct hwdec_info *hwdec = &hwdecs[n];
  645|       |
  646|      9|        mp_info(log, "  %s (%s)\n", hwdec->method_name, hwdec->name);
  ------------------
  |  |   74|      9|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  647|      9|    }
  648|       |
  649|      1|    talloc_free(hwdecs);
  ------------------
  |  |   47|      1|#define talloc_free                     ta_free
  ------------------
  650|       |
  651|      1|    mp_info(log, "  auto (yes '')\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  652|      1|    mp_info(log, "  no\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  653|      1|    mp_info(log, "  auto-safe\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  654|      1|    mp_info(log, "  auto-copy\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  655|      1|    mp_info(log, "  auto-unsafe\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  656|      1|    mp_info(log, "  auto-copy-safe\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  657|      1|    mp_info(log, "  auto-copy-unsafe\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  658|       |
  659|      1|    return M_OPT_EXIT;
  ------------------
  |  |  533|      1|#define M_OPT_EXIT              -6
  ------------------
  660|      1|}
vd_lavc.c:add_all_hwdec_methods:
  336|      1|{
  337|      1|    const AVCodec *codec = NULL;
  338|      1|    void *iter = NULL;
  339|    487|    while (1) {
  ------------------
  |  Branch (339:12): [Folded - Ignored]
  ------------------
  340|    487|        codec = av_codec_iterate(&iter);
  341|    487|        if (!codec)
  ------------------
  |  Branch (341:13): [True: 1, False: 486]
  ------------------
  342|      1|            break;
  343|    486|        if (codec->type != AVMEDIA_TYPE_VIDEO || !av_codec_is_decoder(codec))
  ------------------
  |  Branch (343:13): [True: 231, False: 255]
  |  Branch (343:50): [True: 0, False: 255]
  ------------------
  344|    231|            continue;
  345|       |
  346|    255|        struct hwdec_info info_template = {
  347|    255|            .pix_fmt = AV_PIX_FMT_NONE,
  348|    255|            .codec = codec,
  349|    255|        };
  350|       |
  351|    255|        const char *wrapper = NULL;
  352|    255|        if (codec->capabilities & (AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_HYBRID))
  ------------------
  |  Branch (352:13): [True: 9, False: 246]
  ------------------
  353|      9|            wrapper = codec->wrapper_name;
  354|       |
  355|       |        // A decoder can provide multiple methods. In particular, hwaccels
  356|       |        // provide various methods (e.g. native h264 with vaapi & d3d11), but
  357|       |        // even wrapper decoders could provide multiple methods.
  358|    255|        bool found_any = false;
  359|    255|        for (int n = 0; ; n++) {
  360|    255|            const AVCodecHWConfig *cfg = avcodec_get_hw_config(codec, n);
  361|    255|            if (!cfg)
  ------------------
  |  Branch (361:17): [True: 255, False: 0]
  ------------------
  362|    255|                break;
  363|       |
  364|      0|            if ((cfg->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX) ||
  ------------------
  |  Branch (364:17): [True: 0, False: 0]
  ------------------
  365|      0|                (cfg->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX))
  ------------------
  |  Branch (365:17): [True: 0, False: 0]
  ------------------
  366|      0|            {
  367|      0|                struct hwdec_info info = info_template;
  368|      0|                info.lavc_device = cfg->device_type;
  369|      0|                info.pix_fmt = cfg->pix_fmt;
  370|       |
  371|      0|                const char *name = av_hwdevice_get_type_name(cfg->device_type);
  372|      0|                mp_assert(name); // API violation by libavcodec
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  373|       |
  374|       |                // nvdec hwaccels and the cuvid full decoder clash with their
  375|       |                // naming, so fix it here; we also prefer nvdec for the hwaccel.
  376|      0|                if (strcmp(name, "cuda") == 0 && !wrapper)
  ------------------
  |  Branch (376:21): [True: 0, False: 0]
  |  Branch (376:50): [True: 0, False: 0]
  ------------------
  377|      0|                    name = "nvdec";
  378|       |
  379|      0|                snprintf(info.method_name, sizeof(info.method_name), "%s", name);
  380|       |
  381|       |                // Usually we want to prefer using hw_frames_ctx for true
  382|       |                // hwaccels only, but we actually don't have any way to detect
  383|       |                // those, so always use hw_frames_ctx if offered.
  384|      0|                if (cfg->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX) {
  ------------------
  |  Branch (384:21): [True: 0, False: 0]
  ------------------
  385|      0|                    info.use_hw_frames = true;
  386|      0|                } else {
  387|      0|                    info.use_hw_device = true;
  388|      0|                }
  389|       |
  390|       |                // Direct variant.
  391|      0|                add_hwdec_item(infos, num_infos, info);
  392|       |
  393|       |                // Copy variant.
  394|      0|                info.copying = true;
  395|      0|                if (cfg->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) {
  ------------------
  |  Branch (395:21): [True: 0, False: 0]
  ------------------
  396|      0|                    info.use_hw_frames = false;
  397|      0|                    info.use_hw_device = true;
  398|      0|                }
  399|      0|                add_hwdec_item(infos, num_infos, info);
  400|       |
  401|      0|                found_any = true;
  402|      0|            } else if (cfg->methods & AV_CODEC_HW_CONFIG_METHOD_INTERNAL) {
  ------------------
  |  Branch (402:24): [True: 0, False: 0]
  ------------------
  403|      0|                struct hwdec_info info = info_template;
  404|      0|                info.pix_fmt = cfg->pix_fmt;
  405|       |
  406|      0|                const char *name = wrapper;
  407|      0|                if (!name)
  ------------------
  |  Branch (407:21): [True: 0, False: 0]
  ------------------
  408|      0|                    name = av_get_pix_fmt_name(info.pix_fmt);
  409|      0|                mp_assert(name); // API violation by libavcodec
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  410|       |
  411|      0|                snprintf(info.method_name, sizeof(info.method_name), "%s", name);
  412|       |
  413|       |                // Direct variant.
  414|      0|                add_hwdec_item(infos, num_infos, info);
  415|       |
  416|       |                // Copy variant.
  417|      0|                info.copying = true;
  418|      0|                info.pix_fmt = AV_PIX_FMT_NONE; // trust it can do sw output
  419|      0|                add_hwdec_item(infos, num_infos, info);
  420|       |
  421|      0|                found_any = true;
  422|      0|            }
  423|      0|        }
  424|       |
  425|    255|        if (!found_any && wrapper) {
  ------------------
  |  Branch (425:13): [True: 255, False: 0]
  |  Branch (425:27): [True: 9, False: 246]
  ------------------
  426|       |            // We _know_ there's something supported here, usually outputting
  427|       |            // sw surfaces. E.g. mediacodec (before hw_device_ctx support).
  428|       |
  429|      9|            struct hwdec_info info = info_template;
  430|      9|            info.copying = true; // probably
  431|       |
  432|      9|            snprintf(info.method_name, sizeof(info.method_name), "%s", wrapper);
  433|      9|            add_hwdec_item(infos, num_infos, info);
  434|      9|        }
  435|    255|    }
  436|       |
  437|      1|    qsort(*infos, *num_infos, sizeof(struct hwdec_info), hwdec_compare);
  438|      1|}
vd_lavc.c:add_hwdec_item:
  311|      9|{
  312|      9|    if (info.copying)
  ------------------
  |  Branch (312:9): [True: 9, False: 0]
  ------------------
  313|      9|        mp_snprintf_cat(info.method_name, sizeof(info.method_name), "-copy");
  314|       |
  315|       |    // (Including the codec name in case this is a wrapper looks pretty dumb,
  316|       |    // but better not have them clash with hwaccels and others.)
  317|      9|    snprintf(info.name, sizeof(info.name), "%s-%s",
  318|      9|             info.codec->name, info.method_name);
  319|       |
  320|      9|    info.rank = *num_infos;
  321|      9|    info.auto_pos = INT_MAX;
  322|       |
  323|    171|    for (int x = 0; hwdec_autoprobe_info[x].method_name; x++) {
  ------------------
  |  Branch (323:21): [True: 162, False: 9]
  ------------------
  324|    162|        const struct autoprobe_info *entry = &hwdec_autoprobe_info[x];
  325|    162|        if (strcmp(entry->method_name, info.method_name) == 0) {
  ------------------
  |  Branch (325:13): [True: 0, False: 162]
  ------------------
  326|      0|            info.flags |= entry->flags;
  327|      0|            if (info.flags & HWDEC_FLAG_AUTO)
  ------------------
  |  Branch (327:17): [True: 0, False: 0]
  ------------------
  328|      0|                info.auto_pos = x;
  329|      0|        }
  330|    162|    }
  331|       |
  332|      9|    MP_TARRAY_APPEND(NULL, *infos, *num_infos, info);
  ------------------
  |  |  105|      9|    do {                                            \
  |  |  106|      9|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      9|    do {                                            \
  |  |  |  |   97|      9|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      9|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      9|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      9|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 3, False: 6]
  |  |  |  |  ------------------
  |  |  |  |   99|      9|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      3|    do {                                                        \
  |  |  |  |  |  |   89|      3|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      3|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      3|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      3|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      3|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      3|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      3|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      9|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      9|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      9|        (idxvar)++;                                 \
  |  |  109|      9|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  333|      9|}
vd_lavc.c:hwdec_compare:
  285|     13|{
  286|     13|    struct hwdec_info *h1 = (void *)p1;
  287|     13|    struct hwdec_info *h2 = (void *)p2;
  288|       |
  289|     13|    if (h1 == h2)
  ------------------
  |  Branch (289:9): [True: 0, False: 13]
  ------------------
  290|      0|        return 0;
  291|       |
  292|       |    // Strictly put non-preferred hwdecs to the end of the list.
  293|     13|    if ((h1->auto_pos == INT_MAX) != (h2->auto_pos == INT_MAX))
  ------------------
  |  Branch (293:9): [True: 0, False: 13]
  ------------------
  294|      0|        return h1->auto_pos == INT_MAX ? 1 : -1;
  ------------------
  |  Branch (294:16): [True: 0, False: 0]
  ------------------
  295|       |    // List non-copying entries first, so --hwdec=auto takes them.
  296|     13|    if (h1->copying != h2->copying)
  ------------------
  |  Branch (296:9): [True: 0, False: 13]
  ------------------
  297|      0|        return h1->copying ? 1 : -1;
  ------------------
  |  Branch (297:16): [True: 0, False: 0]
  ------------------
  298|       |    // Order by autoprobe preference order.
  299|     13|    if (h1->auto_pos != h2->auto_pos)
  ------------------
  |  Branch (299:9): [True: 0, False: 13]
  ------------------
  300|      0|        return h1->auto_pos > h2->auto_pos ? 1 : -1;
  ------------------
  |  Branch (300:16): [True: 0, False: 0]
  ------------------
  301|       |    // Put hwdecs without hw_device_ctx last
  302|     13|    if ((!!h1->lavc_device) != (!!h2->lavc_device))
  ------------------
  |  Branch (302:9): [True: 0, False: 13]
  ------------------
  303|      0|        return h1->lavc_device ? -1 : 1;
  ------------------
  |  Branch (303:16): [True: 0, False: 0]
  ------------------
  304|       |    // Fallback sort order to make sorting stable.
  305|     13|    return h1->rank > h2->rank ? 1 :-1;
  ------------------
  |  Branch (305:12): [True: 0, False: 13]
  ------------------
  306|     13|}
vd_lavc.c:add_decoders:
 1471|  2.57k|{
 1472|  2.57k|    mp_add_lavc_decoders(list, AVMEDIA_TYPE_VIDEO);
 1473|  2.57k|}

imgfmt2pixfmt:
   75|  23.7k|{
   76|  23.7k|    if (fmt == IMGFMT_NONE)
  ------------------
  |  Branch (76:9): [True: 0, False: 23.7k]
  ------------------
   77|      0|        return AV_PIX_FMT_NONE;
   78|       |
   79|  23.7k|    if (fmt >= IMGFMT_AVPIXFMT_START && fmt < IMGFMT_AVPIXFMT_END) {
  ------------------
  |  Branch (79:9): [True: 16.4k, False: 7.35k]
  |  Branch (79:41): [True: 16.4k, False: 0]
  ------------------
   80|  16.4k|        enum AVPixelFormat pixfmt = fmt - IMGFMT_AVPIXFMT_START;
   81|       |        // Avoid duplicate format - each format must be unique.
   82|  16.4k|        int mpfmt = pixfmt2imgfmt(pixfmt);
   83|  16.4k|        if (mpfmt == fmt && av_pix_fmt_desc_get(pixfmt))
  ------------------
  |  Branch (83:13): [True: 13.0k, False: 3.36k]
  |  Branch (83:29): [True: 13.0k, False: 0]
  ------------------
   84|  13.0k|            return pixfmt;
   85|  3.36k|        return AV_PIX_FMT_NONE;
   86|  16.4k|    }
   87|       |
   88|   107k|    for (int i = 0; conversion_map[i].fmt; i++) {
  ------------------
  |  Branch (88:21): [True: 107k, False: 180]
  ------------------
   89|   107k|        if (conversion_map[i].fmt == fmt)
  ------------------
  |  Branch (89:13): [True: 7.17k, False: 100k]
  ------------------
   90|  7.17k|            return conversion_map[i].pix_fmt;
   91|   107k|    }
   92|    180|    return AV_PIX_FMT_NONE;
   93|  7.35k|}
pixfmt2imgfmt:
   96|  17.3k|{
   97|  17.3k|    if (pix_fmt == AV_PIX_FMT_NONE)
  ------------------
  |  Branch (97:9): [True: 318, False: 17.0k]
  ------------------
   98|    318|        return IMGFMT_NONE;
   99|       |
  100|   493k|    for (int i = 0; conversion_map[i].pix_fmt != AV_PIX_FMT_NONE; i++) {
  ------------------
  |  Branch (100:21): [True: 479k, False: 13.3k]
  ------------------
  101|   479k|        if (conversion_map[i].pix_fmt == pix_fmt)
  ------------------
  |  Branch (101:13): [True: 3.64k, False: 476k]
  ------------------
  102|  3.64k|            return conversion_map[i].fmt;
  103|   479k|    }
  104|       |
  105|  13.3k|    int generic = IMGFMT_AVPIXFMT_START + pix_fmt;
  106|  13.3k|    if (generic < IMGFMT_AVPIXFMT_END && av_pix_fmt_desc_get(pix_fmt))
  ------------------
  |  Branch (106:9): [True: 13.3k, False: 0]
  |  Branch (106:42): [True: 13.3k, False: 0]
  ------------------
  107|  13.3k|        return generic;
  108|       |
  109|      0|    return 0;
  110|  13.3k|}

mp_imgfmt_from_name:
  155|    962|{
  156|    962|    if (bstr_equals0(name, "none"))
  ------------------
  |  Branch (156:9): [True: 1, False: 961]
  ------------------
  157|      1|        return 0;
  158|  25.0k|    for (int n = 0; n < MP_ARRAY_SIZE(mp_imgfmt_list); n++) {
  ------------------
  |  |   48|  25.0k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (158:21): [True: 24.2k, False: 886]
  ------------------
  159|  24.2k|        const struct mp_imgfmt_entry *p = &mp_imgfmt_list[n];
  160|  24.2k|        if (p->name && bstr_equals0(name, p->name))
  ------------------
  |  Branch (160:13): [True: 23.2k, False: 961]
  |  Branch (160:24): [True: 75, False: 23.1k]
  ------------------
  161|     75|            return IMGFMT_CUST_BASE + n;
  162|  24.2k|    }
  163|    886|    return pixfmt2imgfmt(av_get_pix_fmt(mp_tprintf(80, "%.*s", BSTR_P(name))));
  ------------------
  |  |  165|  1.77k|    mp_tprintf_buf((char[SIZE]){0}, (SIZE), (format), __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (165:55): [True: 886, False: 0]
  |  |  ------------------
  ------------------
  164|    961|}
mp_imgfmt_to_name_buf:
  167|     39|{
  168|     39|    const struct mp_imgfmt_entry *p = get_mp_desc(fmt);
  169|     39|    const char *name = p ? p->name : NULL;
  ------------------
  |  Branch (169:24): [True: 0, False: 39]
  ------------------
  170|     39|    if (!name) {
  ------------------
  |  Branch (170:9): [True: 39, False: 0]
  ------------------
  171|     39|        const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(imgfmt2pixfmt(fmt));
  172|     39|        if (pixdesc)
  ------------------
  |  Branch (172:13): [True: 39, False: 0]
  ------------------
  173|     39|            name = pixdesc->name;
  174|     39|    }
  175|     39|    if (!name)
  ------------------
  |  Branch (175:9): [True: 0, False: 39]
  ------------------
  176|      0|        name = "unknown";
  177|     39|    snprintf(buf, buf_size, "%s", name);
  178|     39|    int len = strlen(buf);
  179|     39|    if (len > 2 && buf[len - 2] == MP_SELECT_LE_BE('l', 'b') && buf[len - 1] == 'e')
  ------------------
  |  |   38|     78|#define MP_SELECT_LE_BE(LE, BE) LE
  ------------------
  |  Branch (179:9): [True: 39, False: 0]
  |  Branch (179:20): [True: 0, False: 39]
  |  Branch (179:65): [True: 0, False: 0]
  ------------------
  180|      0|        buf[len - 2] = '\0';
  181|     39|    return buf;
  182|     39|}
mp_imgfmt_desc_get_num_comps:
  555|  15.2k|{
  556|  15.2k|    int flags = desc->flags;
  557|  15.2k|    if (!(flags & MP_IMGFLAG_COLOR_MASK))
  ------------------
  |  |   55|  15.2k|#define MP_IMGFLAG_COLOR_MASK   (15 << 6)
  ------------------
  |  Branch (557:9): [True: 0, False: 15.2k]
  ------------------
  558|      0|        return 0;
  559|  15.2k|    return 3 + (flags & MP_IMGFLAG_GRAY ? -2 : 0) + !!(flags & MP_IMGFLAG_ALPHA);
  ------------------
  |  |   75|  15.2k|#define MP_IMGFLAG_GRAY         (1 << 14)
  ------------------
                  return 3 + (flags & MP_IMGFLAG_GRAY ? -2 : 0) + !!(flags & MP_IMGFLAG_ALPHA);
  ------------------
  |  |   52|  15.2k|#define MP_IMGFLAG_ALPHA        (1 << 5)
  ------------------
  |  Branch (559:17): [True: 1.53k, False: 13.7k]
  ------------------
  560|  15.2k|}
mp_imgfmt_get_desc:
  563|  27.8k|{
  564|  27.8k|    struct mp_imgfmt_desc desc;
  565|       |
  566|  27.8k|    if (!get_native_desc(mpfmt, &desc) &&
  ------------------
  |  Branch (566:9): [True: 23.5k, False: 4.32k]
  ------------------
  567|  27.8k|        !mp_imgfmt_get_desc_from_pixdesc(mpfmt, &desc))
  ------------------
  |  Branch (567:9): [True: 3.54k, False: 19.9k]
  ------------------
  568|  3.54k|        return (struct mp_imgfmt_desc){0};
  569|       |
  570|  72.8k|    for (int p = 0; p < desc.num_planes; p++) {
  ------------------
  |  Branch (570:21): [True: 48.5k, False: 24.2k]
  ------------------
  571|  48.5k|        desc.xs[p] = (p == 1 || p == 2) ? desc.chroma_xs : 0;
  ------------------
  |  Branch (571:23): [True: 12.2k, False: 36.2k]
  |  Branch (571:33): [True: 10.9k, False: 25.3k]
  ------------------
  572|  48.5k|        desc.ys[p] = (p == 1 || p == 2) ? desc.chroma_ys : 0;
  ------------------
  |  Branch (572:23): [True: 12.2k, False: 36.2k]
  |  Branch (572:33): [True: 10.9k, False: 25.3k]
  ------------------
  573|  48.5k|    }
  574|       |
  575|  24.2k|    bool is_ba = desc.num_planes > 0;
  576|  72.8k|    for (int p = 0; p < desc.num_planes; p++)
  ------------------
  |  Branch (576:21): [True: 48.5k, False: 24.2k]
  ------------------
  577|  48.5k|        is_ba = !(desc.bpp[p] % 8u);
  578|       |
  579|  24.2k|    if (is_ba)
  ------------------
  |  Branch (579:9): [True: 21.4k, False: 2.88k]
  ------------------
  580|  21.4k|        desc.flags |= MP_IMGFLAG_BYTE_ALIGNED;
  ------------------
  |  |   40|  21.4k|#define MP_IMGFLAG_BYTE_ALIGNED (1 << 2)
  ------------------
  581|       |
  582|  24.2k|    if (desc.flags & MP_IMGFLAG_HAS_COMPS) {
  ------------------
  |  |   34|  24.2k|#define MP_IMGFLAG_HAS_COMPS    (1 << 0)
  ------------------
  |  Branch (582:9): [True: 21.5k, False: 2.76k]
  ------------------
  583|  21.5k|        if (desc.comps[3].size)
  ------------------
  |  Branch (583:13): [True: 5.46k, False: 16.0k]
  ------------------
  584|  5.46k|            desc.flags |= MP_IMGFLAG_ALPHA;
  ------------------
  |  |   52|  5.46k|#define MP_IMGFLAG_ALPHA        (1 << 5)
  ------------------
  585|       |
  586|       |        // Assuming all colors are (CCC+[A]) or (C+[A]), the latter being gray.
  587|  21.5k|        if (!desc.comps[1].size)
  ------------------
  |  Branch (587:13): [True: 2.07k, False: 19.4k]
  ------------------
  588|  2.07k|            desc.flags |= MP_IMGFLAG_GRAY;
  ------------------
  |  |   75|  2.07k|#define MP_IMGFLAG_GRAY         (1 << 14)
  ------------------
  589|       |
  590|  21.5k|        bool bb = true;
  591|   107k|        for (int n = 0; n < MP_NUM_COMPONENTS; n++) {
  ------------------
  |  |   29|   107k|#define MP_NUM_COMPONENTS 4
  ------------------
  |  Branch (591:25): [True: 86.0k, False: 21.5k]
  ------------------
  592|  86.0k|            if (desc.comps[n].offset % 8u || desc.comps[n].size % 8u)
  ------------------
  |  Branch (592:17): [True: 6.12k, False: 79.9k]
  |  Branch (592:46): [True: 4.50k, False: 75.4k]
  ------------------
  593|  10.6k|                bb = false;
  594|  86.0k|        }
  595|  21.5k|        if (bb)
  ------------------
  |  Branch (595:13): [True: 17.7k, False: 3.78k]
  ------------------
  596|  17.7k|            desc.flags |= MP_IMGFLAG_BYTES;
  ------------------
  |  |   37|  17.7k|#define MP_IMGFLAG_BYTES        (1 << 1)
  ------------------
  597|  21.5k|    }
  598|       |
  599|  24.2k|    if ((desc.flags & (MP_IMGFLAG_YUV | MP_IMGFLAG_RGB))
  ------------------
  |  |   67|  24.2k|#define MP_IMGFLAG_YUV          MP_IMGFLAG_COLOR_YUV
  |  |  ------------------
  |  |  |  |   56|  24.2k|#define MP_IMGFLAG_COLOR_YUV    (1 << 6)
  |  |  ------------------
  ------------------
                  if ((desc.flags & (MP_IMGFLAG_YUV | MP_IMGFLAG_RGB))
  ------------------
  |  |   68|  24.2k|#define MP_IMGFLAG_RGB          MP_IMGFLAG_COLOR_RGB
  |  |  ------------------
  |  |  |  |   57|  24.2k|#define MP_IMGFLAG_COLOR_RGB    (2 << 6)
  |  |  ------------------
  ------------------
  |  Branch (599:9): [True: 22.3k, False: 1.92k]
  ------------------
  600|  24.2k|        && (desc.flags & MP_IMGFLAG_HAS_COMPS)
  ------------------
  |  |   34|  22.3k|#define MP_IMGFLAG_HAS_COMPS    (1 << 0)
  ------------------
  |  Branch (600:12): [True: 21.4k, False: 960]
  ------------------
  601|  24.2k|        && (desc.flags & MP_IMGFLAG_BYTES)
  ------------------
  |  |   37|  21.4k|#define MP_IMGFLAG_BYTES        (1 << 1)
  ------------------
  |  Branch (601:12): [True: 17.6k, False: 3.78k]
  ------------------
  602|  24.2k|        && ((desc.flags & MP_IMGFLAG_TYPE_MASK) == MP_IMGFLAG_TYPE_UINT))
  ------------------
  |  |   61|  17.6k|#define MP_IMGFLAG_TYPE_MASK    (15 << 10)
  ------------------
                      && ((desc.flags & MP_IMGFLAG_TYPE_MASK) == MP_IMGFLAG_TYPE_UINT))
  ------------------
  |  |   62|  17.6k|#define MP_IMGFLAG_TYPE_UINT    (1 << 10)
  ------------------
  |  Branch (602:12): [True: 15.2k, False: 2.34k]
  ------------------
  603|  15.2k|    {
  604|  15.2k|        int cnt = mp_imgfmt_desc_get_num_comps(&desc);
  605|  15.2k|        bool same_depth = true;
  606|  51.2k|        for (int p = 0; p < desc.num_planes; p++)
  ------------------
  |  Branch (606:25): [True: 35.9k, False: 15.2k]
  ------------------
  607|  35.9k|            same_depth &= desc.bpp[p] == desc.bpp[0];
  608|  15.2k|        if (same_depth && cnt == desc.num_planes) {
  ------------------
  |  Branch (608:13): [True: 14.5k, False: 720]
  |  Branch (608:27): [True: 10.0k, False: 4.51k]
  ------------------
  609|  10.0k|            if (desc.flags & MP_IMGFLAG_YUV) {
  ------------------
  |  |   67|  10.0k|#define MP_IMGFLAG_YUV          MP_IMGFLAG_COLOR_YUV
  |  |  ------------------
  |  |  |  |   56|  10.0k|#define MP_IMGFLAG_COLOR_YUV    (1 << 6)
  |  |  ------------------
  ------------------
  |  Branch (609:17): [True: 7.11k, False: 2.94k]
  ------------------
  610|  7.11k|                desc.flags |= MP_IMGFLAG_YUV_P;
  ------------------
  |  |   94|  7.11k|#define MP_IMGFLAG_YUV_P        (1 << 16)
  ------------------
  611|  7.11k|            } else {
  612|  2.94k|                desc.flags |= MP_IMGFLAG_RGB_P;
  ------------------
  |  |   98|  2.94k|#define MP_IMGFLAG_RGB_P        (1 << 17)
  ------------------
  613|  2.94k|            }
  614|  10.0k|        }
  615|  15.2k|        if (cnt == 3 && desc.num_planes == 2 &&
  ------------------
  |  Branch (615:13): [True: 10.2k, False: 5.07k]
  |  Branch (615:25): [True: 720, False: 9.49k]
  ------------------
  616|  15.2k|            desc.bpp[1] == desc.bpp[0] * 2 &&
  ------------------
  |  Branch (616:13): [True: 720, False: 0]
  ------------------
  617|  15.2k|            (desc.flags & MP_IMGFLAG_YUV))
  ------------------
  |  |   67|    720|#define MP_IMGFLAG_YUV          MP_IMGFLAG_COLOR_YUV
  |  |  ------------------
  |  |  |  |   56|    720|#define MP_IMGFLAG_COLOR_YUV    (1 << 6)
  |  |  ------------------
  ------------------
  |  Branch (617:13): [True: 720, False: 0]
  ------------------
  618|    720|        {
  619|       |
  620|    720|            desc.flags |= MP_IMGFLAG_YUV_NV;
  ------------------
  |  |  101|    720|#define MP_IMGFLAG_YUV_NV       (1 << 18)
  ------------------
  621|    720|        }
  622|  15.2k|    }
  623|       |
  624|  24.2k|    return desc;
  625|  27.8k|}
mp_imgfmt_get_forced_csp:
  680|    198|{
  681|    198|    return get_forced_csp_from_flags(mp_imgfmt_get_desc(imgfmt).flags);
  682|    198|}
mp_get_regular_imgfmt:
  706|  25.7k|{
  707|  25.7k|    struct mp_regular_imgfmt res = {0};
  708|       |
  709|  25.7k|    struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(imgfmt);
  710|  25.7k|    if (!desc.num_planes)
  ------------------
  |  Branch (710:9): [True: 5.52k, False: 20.2k]
  ------------------
  711|  5.52k|        return false;
  712|  20.2k|    res.num_planes = desc.num_planes;
  713|       |
  714|  20.2k|    if (desc.endian_shift || !(desc.flags & MP_IMGFLAG_HAS_COMPS))
  ------------------
  |  |   34|  15.9k|#define MP_IMGFLAG_HAS_COMPS    (1 << 0)
  ------------------
  |  Branch (714:9): [True: 4.26k, False: 15.9k]
  |  Branch (714:30): [True: 780, False: 15.1k]
  ------------------
  715|  5.04k|        return false;
  716|       |
  717|  15.1k|    res.component_type = get_component_type_from_flags(desc.flags);
  718|  15.1k|    if (!res.component_type)
  ------------------
  |  Branch (718:9): [True: 0, False: 15.1k]
  ------------------
  719|      0|        return false;
  720|       |
  721|  15.1k|    struct mp_imgfmt_comp_desc *comp0 = &desc.comps[0];
  722|  15.1k|    if (comp0->size < 1 || comp0->size > 64 || (comp0->size % 8u))
  ------------------
  |  Branch (722:9): [True: 0, False: 15.1k]
  |  Branch (722:28): [True: 0, False: 15.1k]
  |  Branch (722:48): [True: 2.70k, False: 12.4k]
  ------------------
  723|  2.70k|        return false;
  724|       |
  725|  12.4k|    res.component_size = comp0->size / 8u;
  726|  12.4k|    res.component_pad = comp0->pad;
  727|       |
  728|  43.9k|    for (int n = 0; n < res.num_planes; n++) {
  ------------------
  |  Branch (728:21): [True: 31.5k, False: 12.4k]
  ------------------
  729|  31.5k|        if (desc.bpp[n] % comp0->size)
  ------------------
  |  Branch (729:13): [True: 0, False: 31.5k]
  ------------------
  730|      0|            return false;
  731|  31.5k|        res.planes[n].num_components = desc.bpp[n] / comp0->size;
  732|  31.5k|    }
  733|       |
  734|  62.4k|    for (int n = 0; n < MP_NUM_COMPONENTS; n++) {
  ------------------
  |  |   29|  62.4k|#define MP_NUM_COMPONENTS 4
  ------------------
  |  Branch (734:21): [True: 49.9k, False: 12.4k]
  ------------------
  735|  49.9k|        struct mp_imgfmt_comp_desc *comp = &desc.comps[n];
  736|  49.9k|        if (!comp->size)
  ------------------
  |  Branch (736:13): [True: 11.2k, False: 38.7k]
  ------------------
  737|  11.2k|            continue;
  738|       |
  739|  38.7k|        struct mp_regular_imgfmt_plane *plane = &res.planes[comp->plane];
  740|       |
  741|  38.7k|        res.num_planes = MPMAX(res.num_planes, comp->plane + 1);
  ------------------
  |  |   43|  38.7k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 19.0k, False: 19.6k]
  |  |  ------------------
  ------------------
  742|       |
  743|       |        // We support uniform depth only.
  744|  38.7k|        if (comp->size != comp0->size || comp->pad != comp0->pad)
  ------------------
  |  Branch (744:13): [True: 0, False: 38.7k]
  |  Branch (744:42): [True: 0, False: 38.7k]
  ------------------
  745|      0|            return false;
  746|       |
  747|       |        // Size-aligned only.
  748|  38.7k|        int pos = comp->offset / comp->size;
  749|  38.7k|        if (comp->offset != pos * comp->size || pos >= MP_NUM_COMPONENTS)
  ------------------
  |  |   29|  38.7k|#define MP_NUM_COMPONENTS 4
  ------------------
  |  Branch (749:13): [True: 0, False: 38.7k]
  |  Branch (749:49): [True: 0, False: 38.7k]
  ------------------
  750|      0|            return false;
  751|       |
  752|  38.7k|        if (plane->components[pos])
  ------------------
  |  Branch (752:13): [True: 0, False: 38.7k]
  ------------------
  753|      0|            return false;
  754|  38.7k|        plane->components[pos] = n + 1;
  755|  38.7k|    }
  756|       |
  757|  12.4k|    res.chroma_xs = desc.chroma_xs;
  758|  12.4k|    res.chroma_ys = desc.chroma_ys;
  759|       |
  760|  12.4k|    res.forced_csp = get_forced_csp_from_flags(desc.flags);
  761|       |
  762|  12.4k|    if (!validate_regular_imgfmt(&res))
  ------------------
  |  Branch (762:9): [True: 0, False: 12.4k]
  ------------------
  763|      0|        return false;
  764|       |
  765|  12.4k|    *dst = res;
  766|  12.4k|    return true;
  767|  12.4k|}
mp_find_regular_imgfmt:
  796|    180|{
  797|  25.2k|    for (int n = IMGFMT_START + 1; n < IMGFMT_END; n++) {
  ------------------
  |  Branch (797:36): [True: 25.2k, False: 0]
  ------------------
  798|  25.2k|        struct mp_regular_imgfmt f;
  799|  25.2k|        if (mp_get_regular_imgfmt(&f, n) && regular_imgfmt_equals(src, &f))
  ------------------
  |  Branch (799:13): [True: 12.0k, False: 13.2k]
  |  Branch (799:45): [True: 180, False: 11.8k]
  ------------------
  800|    180|            return n;
  801|  25.2k|    }
  802|      0|    return 0;
  803|    180|}
img_format.c:get_mp_desc:
  131|  27.8k|{
  132|  27.8k|    if (imgfmt < IMGFMT_CUST_BASE)
  ------------------
  |  Branch (132:9): [True: 6.20k, False: 21.6k]
  ------------------
  133|  6.20k|        return NULL;
  134|  21.6k|    int index = imgfmt - IMGFMT_CUST_BASE;
  135|  21.6k|    if (index >= MP_ARRAY_SIZE(mp_imgfmt_list))
  ------------------
  |  |   48|  21.6k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (135:9): [True: 16.8k, False: 4.86k]
  ------------------
  136|  16.8k|        return NULL;
  137|  4.86k|    const struct mp_imgfmt_entry *e = &mp_imgfmt_list[index];
  138|  4.86k|    return e->name ? e : NULL;
  ------------------
  |  Branch (138:12): [True: 4.68k, False: 180]
  ------------------
  139|  21.6k|}
img_format.c:get_native_desc:
  521|  27.8k|{
  522|  27.8k|    const struct mp_imgfmt_entry *p = get_mp_desc(mpfmt);
  523|  27.8k|    if (!p || !p->desc.flags)
  ------------------
  |  Branch (523:9): [True: 23.1k, False: 4.68k]
  |  Branch (523:15): [True: 360, False: 4.32k]
  ------------------
  524|  23.5k|        return false;
  525|       |
  526|  4.32k|    *desc = p->desc;
  527|       |
  528|       |    // Fill in some fields mp_imgfmt_entry.desc is not required to set.
  529|       |
  530|  4.32k|    desc->id = mpfmt;
  531|       |
  532|  21.6k|    for (int n = 0; n < MP_NUM_COMPONENTS; n++) {
  ------------------
  |  |   29|  21.6k|#define MP_NUM_COMPONENTS 4
  ------------------
  |  Branch (532:21): [True: 17.2k, False: 4.32k]
  ------------------
  533|  17.2k|        struct mp_imgfmt_comp_desc *cd = &desc->comps[n];
  534|  17.2k|        if (cd->size)
  ------------------
  |  Branch (534:13): [True: 12.6k, False: 4.68k]
  ------------------
  535|  12.6k|            desc->num_planes = MPMAX(desc->num_planes, cd->plane + 1);
  ------------------
  |  |   43|  12.6k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 2.16k, False: 10.4k]
  |  |  ------------------
  ------------------
  536|  17.2k|        desc->bpp[cd->plane] =
  537|  17.2k|            MPMAX(desc->bpp[cd->plane], MP_ALIGN_UP(cd->offset + cd->size, 8));
  ------------------
  |  |   43|  17.2k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 4.32k, False: 12.9k]
  |  |  ------------------
  ------------------
  538|  17.2k|    }
  539|       |
  540|  4.32k|    if (!desc->align_x && !desc->align_y) {
  ------------------
  |  Branch (540:9): [True: 4.32k, False: 0]
  |  Branch (540:27): [True: 4.32k, False: 0]
  ------------------
  541|  4.32k|        desc->align_x = 1 << desc->chroma_xs;
  542|  4.32k|        desc->align_y = 1 << desc->chroma_ys;
  543|  4.32k|    }
  544|       |
  545|  4.32k|    if (desc->num_planes)
  ------------------
  |  Branch (545:9): [True: 4.14k, False: 180]
  ------------------
  546|  4.14k|        desc->flags |= MP_IMGFLAG_HAS_COMPS | MP_IMGFLAG_NE;
  ------------------
  |  |   34|  4.14k|#define MP_IMGFLAG_HAS_COMPS    (1 << 0)
  ------------------
                      desc->flags |= MP_IMGFLAG_HAS_COMPS | MP_IMGFLAG_NE;
  ------------------
  |  |   49|  4.14k|#define MP_IMGFLAG_NE           MP_SELECT_LE_BE(MP_IMGFLAG_LE, MP_IMGFLAG_BE)
  |  |  ------------------
  |  |  |  |   38|  4.14k|#define MP_SELECT_LE_BE(LE, BE) LE
  |  |  ------------------
  ------------------
  547|       |
  548|  4.32k|    if (!(desc->flags & MP_IMGFLAG_TYPE_MASK))
  ------------------
  |  |   61|  4.32k|#define MP_IMGFLAG_TYPE_MASK    (15 << 10)
  ------------------
  |  Branch (548:9): [True: 1.80k, False: 2.52k]
  ------------------
  549|  1.80k|        desc->flags |= MP_IMGFLAG_TYPE_UINT;
  ------------------
  |  |   62|  1.80k|#define MP_IMGFLAG_TYPE_UINT    (1 << 10)
  ------------------
  550|       |
  551|  4.32k|    return true;
  552|  27.8k|}
img_format.c:mp_imgfmt_get_desc_from_pixdesc:
  411|  23.5k|{
  412|  23.5k|    enum AVPixelFormat fmt = imgfmt2pixfmt(mpfmt);
  413|  23.5k|    const AVPixFmtDescriptor *pd = av_pix_fmt_desc_get(fmt);
  414|  23.5k|    if (!pd || pd->nb_components > 4)
  ------------------
  |  Branch (414:9): [True: 3.54k, False: 19.9k]
  |  Branch (414:16): [True: 0, False: 19.9k]
  ------------------
  415|  3.54k|        return false;
  416|       |
  417|  19.9k|    struct mp_imgfmt_desc desc = {
  418|  19.9k|        .id = mpfmt,
  419|  19.9k|        .chroma_xs = pd->log2_chroma_w,
  420|  19.9k|        .chroma_ys = pd->log2_chroma_h,
  421|  19.9k|    };
  422|       |
  423|  19.9k|    if (pd->flags & AV_PIX_FMT_FLAG_ALPHA)
  ------------------
  |  Branch (423:9): [True: 4.02k, False: 15.9k]
  ------------------
  424|  4.02k|        desc.flags |= MP_IMGFLAG_ALPHA;
  ------------------
  |  |   52|  4.02k|#define MP_IMGFLAG_ALPHA        (1 << 5)
  ------------------
  425|       |
  426|  19.9k|    if (pd->flags & AV_PIX_FMT_FLAG_HWACCEL)
  ------------------
  |  Branch (426:9): [True: 1.80k, False: 18.1k]
  ------------------
  427|  1.80k|        desc.flags |= MP_IMGFLAG_TYPE_HW;
  ------------------
  |  |   65|  1.80k|#define MP_IMGFLAG_TYPE_HW      (8 << 10)
  ------------------
  428|       |
  429|       |    // Pixdesc does not provide a flag for XYZ, so this is the best we can do.
  430|  19.9k|    if (strncmp(pd->name, "xyz", 3) == 0) {
  ------------------
  |  Branch (430:9): [True: 120, False: 19.8k]
  ------------------
  431|    120|        desc.flags |= MP_IMGFLAG_COLOR_XYZ;
  ------------------
  |  |   58|    120|#define MP_IMGFLAG_COLOR_XYZ    (4 << 6)
  ------------------
  432|  19.8k|    } else if (pd->flags & AV_PIX_FMT_FLAG_RGB) {
  ------------------
  |  Branch (432:16): [True: 9.13k, False: 10.7k]
  ------------------
  433|  9.13k|        desc.flags |= MP_IMGFLAG_COLOR_RGB;
  ------------------
  |  |   57|  9.13k|#define MP_IMGFLAG_COLOR_RGB    (2 << 6)
  ------------------
  434|  10.7k|    } else if (fmt == AV_PIX_FMT_MONOBLACK || fmt == AV_PIX_FMT_MONOWHITE) {
  ------------------
  |  Branch (434:16): [True: 180, False: 10.5k]
  |  Branch (434:47): [True: 180, False: 10.3k]
  ------------------
  435|    360|        desc.flags |= MP_IMGFLAG_COLOR_RGB;
  ------------------
  |  |   57|    360|#define MP_IMGFLAG_COLOR_RGB    (2 << 6)
  ------------------
  436|  10.3k|    } else if (fmt == AV_PIX_FMT_PAL8) {
  ------------------
  |  Branch (436:16): [True: 180, False: 10.1k]
  ------------------
  437|    180|        desc.flags |= MP_IMGFLAG_COLOR_RGB | MP_IMGFLAG_TYPE_PAL8;
  ------------------
  |  |   57|    180|#define MP_IMGFLAG_COLOR_RGB    (2 << 6)
  ------------------
                      desc.flags |= MP_IMGFLAG_COLOR_RGB | MP_IMGFLAG_TYPE_PAL8;
  ------------------
  |  |   64|    180|#define MP_IMGFLAG_TYPE_PAL8    (4 << 10)
  ------------------
  438|    180|    }
  439|       |
  440|  19.9k|    if (pd->flags & AV_PIX_FMT_FLAG_FLOAT)
  ------------------
  |  Branch (440:9): [True: 0, False: 19.9k]
  ------------------
  441|      0|        desc.flags |= MP_IMGFLAG_TYPE_FLOAT;
  ------------------
  |  |   63|      0|#define MP_IMGFLAG_TYPE_FLOAT   (2 << 10)
  ------------------
  442|       |
  443|       |    // Educated guess.
  444|  19.9k|    if (!(desc.flags & MP_IMGFLAG_COLOR_MASK) &&
  ------------------
  |  |   55|  19.9k|#define MP_IMGFLAG_COLOR_MASK   (15 << 6)
  ------------------
  |  Branch (444:9): [True: 10.1k, False: 9.79k]
  ------------------
  445|  19.9k|        !(desc.flags & MP_IMGFLAG_TYPE_HW))
  ------------------
  |  |   65|  10.1k|#define MP_IMGFLAG_TYPE_HW      (8 << 10)
  ------------------
  |  Branch (445:9): [True: 8.37k, False: 1.80k]
  ------------------
  446|  8.37k|        desc.flags |= MP_IMGFLAG_COLOR_YUV;
  ------------------
  |  |   56|  8.37k|#define MP_IMGFLAG_COLOR_YUV    (1 << 6)
  ------------------
  447|       |
  448|  19.9k|    desc.align_x = 1 << desc.chroma_xs;
  449|  19.9k|    desc.align_y = 1 << desc.chroma_ys;
  450|       |
  451|  19.9k|    fill_pixdesc_layout(&desc, fmt, pd);
  452|       |
  453|  19.9k|    if (desc.flags & (MP_IMGFLAG_HAS_COMPS | MP_IMGFLAG_PACKED_SS_YUV)) {
  ------------------
  |  |   34|  19.9k|#define MP_IMGFLAG_HAS_COMPS    (1 << 0)
  ------------------
                  if (desc.flags & (MP_IMGFLAG_HAS_COMPS | MP_IMGFLAG_PACKED_SS_YUV)) {
  ------------------
  |  |   86|  19.9k|#define MP_IMGFLAG_PACKED_SS_YUV (1 << 15)
  ------------------
  |  Branch (453:9): [True: 17.9k, False: 1.98k]
  ------------------
  454|  17.9k|        if (!(desc.flags & MP_IMGFLAG_TYPE_MASK))
  ------------------
  |  |   61|  17.9k|#define MP_IMGFLAG_TYPE_MASK    (15 << 10)
  ------------------
  |  Branch (454:13): [True: 17.9k, False: 0]
  ------------------
  455|  17.9k|            desc.flags |= MP_IMGFLAG_TYPE_UINT;
  ------------------
  |  |   62|  17.9k|#define MP_IMGFLAG_TYPE_UINT    (1 << 10)
  ------------------
  456|  17.9k|    }
  457|       |
  458|  19.9k|    if (desc.bpp[0] % 8u && (pd->flags & AV_PIX_FMT_FLAG_BITSTREAM))
  ------------------
  |  Branch (458:9): [True: 900, False: 19.0k]
  |  Branch (458:29): [True: 720, False: 180]
  ------------------
  459|    720|        desc.align_x = 8 / desc.bpp[0]; // expect power of 2
  460|       |
  461|       |    // Very heuristical.
  462|  19.9k|    bool is_ne = !desc.endian_shift;
  463|  19.9k|    bool need_endian = (desc.comps[0].size % 8u && desc.bpp[0] > 8) ||
  ------------------
  |  Branch (463:25): [True: 3.60k, False: 16.3k]
  |  Branch (463:52): [True: 2.16k, False: 1.44k]
  ------------------
  464|  19.9k|                       desc.comps[0].size > 8;
  ------------------
  |  Branch (464:24): [True: 6.66k, False: 11.1k]
  ------------------
  465|       |
  466|  19.9k|    if (need_endian) {
  ------------------
  |  Branch (466:9): [True: 8.82k, False: 11.1k]
  ------------------
  467|  8.82k|        bool is_le = MP_SELECT_LE_BE(is_ne, !is_ne);
  ------------------
  |  |   38|  8.82k|#define MP_SELECT_LE_BE(LE, BE) LE
  ------------------
  468|  8.82k|        desc.flags |= is_le ? MP_IMGFLAG_LE : MP_IMGFLAG_BE;
  ------------------
  |  |   43|  4.56k|#define MP_IMGFLAG_LE           (1 << 3)
  ------------------
                      desc.flags |= is_le ? MP_IMGFLAG_LE : MP_IMGFLAG_BE;
  ------------------
  |  |   46|  13.0k|#define MP_IMGFLAG_BE           (1 << 4)
  ------------------
  |  Branch (468:23): [True: 4.56k, False: 4.26k]
  ------------------
  469|  11.1k|    } else {
  470|  11.1k|        desc.flags |= MP_IMGFLAG_LE | MP_IMGFLAG_BE;
  ------------------
  |  |   43|  11.1k|#define MP_IMGFLAG_LE           (1 << 3)
  ------------------
                      desc.flags |= MP_IMGFLAG_LE | MP_IMGFLAG_BE;
  ------------------
  |  |   46|  11.1k|#define MP_IMGFLAG_BE           (1 << 4)
  ------------------
  471|  11.1k|    }
  472|       |
  473|  19.9k|    *out = desc;
  474|  19.9k|    return true;
  475|  23.5k|}
img_format.c:fill_pixdesc_layout:
  187|  19.9k|{
  188|  19.9k|    if (pd->flags & AV_PIX_FMT_FLAG_PAL ||
  ------------------
  |  Branch (188:9): [True: 180, False: 19.7k]
  ------------------
  189|  19.9k|        pd->flags & AV_PIX_FMT_FLAG_HWACCEL)
  ------------------
  |  Branch (189:9): [True: 1.80k, False: 17.9k]
  ------------------
  190|  1.98k|        goto fail;
  191|       |
  192|  17.9k|    bool has_alpha = pd->flags & AV_PIX_FMT_FLAG_ALPHA;
  193|  17.9k|    if (pd->nb_components != 1 + has_alpha &&
  ------------------
  |  Branch (193:9): [True: 16.6k, False: 1.35k]
  ------------------
  194|  17.9k|        pd->nb_components != 3 + has_alpha)
  ------------------
  |  Branch (194:9): [True: 0, False: 16.6k]
  ------------------
  195|      0|        goto fail;
  196|       |
  197|       |    // Very convenient: we assume we're always on little endian, and FFmpeg
  198|       |    // explicitly marks big endian formats => don't need to guess whether a
  199|       |    // format is little endian, or not affected by byte order.
  200|  17.9k|    bool is_be = pd->flags & AV_PIX_FMT_FLAG_BE;
  201|  17.9k|    bool is_ne = MP_SELECT_LE_BE(false, true) == is_be;
  ------------------
  |  |   38|  17.9k|#define MP_SELECT_LE_BE(LE, BE) LE
  ------------------
  202|       |
  203|       |    // Packed sub-sampled YUV is very... special.
  204|  17.9k|    bool is_packed_ss_yuv = pd->log2_chroma_w && !pd->log2_chroma_h &&
  ------------------
  |  Branch (204:29): [True: 5.34k, False: 12.6k]
  |  Branch (204:50): [True: 2.82k, False: 2.52k]
  ------------------
  205|  17.9k|        pd->comp[1].plane == 0 && pd->comp[2].plane == 0 &&
  ------------------
  |  Branch (205:9): [True: 600, False: 2.22k]
  |  Branch (205:35): [True: 600, False: 0]
  ------------------
  206|  17.9k|        pd->nb_components == 3;
  ------------------
  |  Branch (206:9): [True: 600, False: 0]
  ------------------
  207|       |
  208|  17.9k|    if (is_packed_ss_yuv)
  ------------------
  |  Branch (208:9): [True: 600, False: 17.3k]
  ------------------
  209|    600|        desc->bpp[0] = pd->comp[1].step * 8;
  210|       |
  211|       |    // Determine if there are any byte overlaps => relevant for determining
  212|       |    // access unit for endian, since pixdesc does not expose this, and assumes
  213|       |    // a weird model where you do separate memory fetches for each component.
  214|  17.9k|    bool any_shared_bytes = !!(pd->flags & AV_PIX_FMT_FLAG_BITSTREAM);
  215|  73.0k|    for (int c = 0; c < pd->nb_components; c++) {
  ------------------
  |  Branch (215:21): [True: 55.0k, False: 17.9k]
  ------------------
  216|   115k|        for (int i = 0; i < c; i++) {
  ------------------
  |  Branch (216:25): [True: 60.8k, False: 55.0k]
  ------------------
  217|  60.8k|            const AVComponentDescriptor *d1 = &pd->comp[c];
  218|  60.8k|            const AVComponentDescriptor *d2 = &pd->comp[i];
  219|  60.8k|            if (d1->plane == d2->plane) {
  ------------------
  |  Branch (219:17): [True: 30.3k, False: 30.4k]
  ------------------
  220|  30.3k|                if (d1->offset + (d1->depth + 7) / 8u > d2->offset &&
  ------------------
  |  Branch (220:21): [True: 19.1k, False: 11.2k]
  ------------------
  221|  30.3k|                    d2->offset + (d2->depth + 7) / 8u > d1->offset)
  ------------------
  |  Branch (221:21): [True: 4.32k, False: 14.8k]
  ------------------
  222|  4.32k|                    any_shared_bytes = true;
  223|  30.3k|            }
  224|  60.8k|        }
  225|  55.0k|    }
  226|       |
  227|  17.9k|    int el_bits = (pd->flags & AV_PIX_FMT_FLAG_BITSTREAM) ? 1 : 8;
  ------------------
  |  Branch (227:19): [True: 720, False: 17.2k]
  ------------------
  228|  73.0k|    for (int c = 0; c < pd->nb_components; c++) {
  ------------------
  |  Branch (228:21): [True: 55.0k, False: 17.9k]
  ------------------
  229|  55.0k|        const AVComponentDescriptor *d = &pd->comp[c];
  230|  55.0k|        if (d->plane >= MP_MAX_PLANES)
  ------------------
  |  |   28|  55.0k|#define MP_MAX_PLANES 4
  ------------------
  |  Branch (230:13): [True: 0, False: 55.0k]
  ------------------
  231|      0|            goto fail;
  232|       |
  233|  55.0k|        desc->num_planes = MPMAX(desc->num_planes, d->plane + 1);
  ------------------
  |  |   43|  55.0k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 3.36k, False: 51.7k]
  |  |  ------------------
  ------------------
  234|       |
  235|  55.0k|        int plane_bits = desc->bpp[d->plane];
  236|  55.0k|        int c_bits = d->step * el_bits;
  237|       |
  238|       |        // The first component wins, because either all components result in
  239|       |        // the same value, or luma wins (luma always comes before chroma).
  240|  55.0k|        if (plane_bits) {
  ------------------
  |  Branch (240:13): [True: 19.5k, False: 35.5k]
  ------------------
  241|  19.5k|            if (c_bits > plane_bits)
  ------------------
  |  Branch (241:17): [True: 0, False: 19.5k]
  ------------------
  242|      0|                goto fail; // inconsistent
  243|  35.5k|        } else {
  244|  35.5k|            desc->bpp[d->plane] = plane_bits = c_bits;
  245|  35.5k|        }
  246|       |
  247|  55.0k|        int shift = d->shift;
  248|       |        // What the fuck: for some inexplicable reason, MONOB uses shift=7
  249|       |        // in pixdesc, which is basically out of bounds. Pixdesc bug?
  250|       |        // Make it behave like MONOW. (No, the bit-order is not different.)
  251|  55.0k|        if (fmt == AV_PIX_FMT_MONOBLACK)
  ------------------
  |  Branch (251:13): [True: 180, False: 54.9k]
  ------------------
  252|    180|            shift = 0;
  253|       |
  254|  55.0k|        int offset = d->offset * el_bits;
  255|       |        // The pixdesc logic for reading and endian swapping is as follows
  256|       |        // (reverse engineered from av_read_image_line2()):
  257|       |        // - determine a word size that will include the component fully;
  258|       |        //   this includes the "active" bits and the amount "shifted" away
  259|       |        //   (for example shift=7/depth=18 => 32 bit word reading [31:0])
  260|       |        // - the same format can use different word sizes (e.g. bgr565: the R
  261|       |        //   component at offset 0 is read as 8 bit; BG is read as 16 bits)
  262|       |        // - if BE flag is set, swap the word before proceeding
  263|       |        // - extract via shift and mask derived by depth
  264|  55.0k|        int word = mp_round_next_power_of_2(MPMAX(d->depth + shift, 8));
  ------------------
  |  |   43|  55.0k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 22.0k, False: 33.0k]
  |  |  ------------------
  ------------------
  265|       |        // The purpose of this is unknown. It's an absurdity fished out of
  266|       |        // av_read_image_line2()'s implementation. It seems technically
  267|       |        // unnecessary, and provides no information. On the other hand, it
  268|       |        // compensates for seemingly bogus packed integer pixdescs; this
  269|       |        // is "why" some formats use d->offset = -1.
  270|  55.0k|        if (is_be && el_bits == 8 && word == 8)
  ------------------
  |  Branch (270:13): [True: 13.0k, False: 42.0k]
  |  Branch (270:22): [True: 13.0k, False: 0]
  |  Branch (270:38): [True: 2.52k, False: 10.5k]
  ------------------
  271|  2.52k|            offset += 8;
  272|       |        // Pixdesc's model sometimes requires accesses with varying word-sizes,
  273|       |        // as seen in bgr565 and other formats. Also, it makes you read some
  274|       |        // formats with multiple endian-dependent accesses, where accessing a
  275|       |        // larger unit would make more sense. (Consider X2RGB10BE, for which
  276|       |        // pixdesc wants you to perform 3 * 2 byte accesses, and swap each of
  277|       |        // the read 16 bit words. What you really want is to swap the entire 4
  278|       |        // byte thing, and then extract the components with bit shifts).
  279|       |        // This is complete bullshit, so we transform it into word swaps before
  280|       |        // further processing. Care needs to be taken to not change formats like
  281|       |        // P010 or YA16 (prefer component accesses for them; P010 isn't even
  282|       |        // representable, because endian_shift is for all planes).
  283|       |        // As a heuristic, assume that if any components share a byte, the whole
  284|       |        // pixel is read as a single memory access and endian swapped at once.
  285|  55.0k|        int access_size = 8;
  286|  55.0k|        if (plane_bits > 8) {
  ------------------
  |  Branch (286:13): [True: 40.7k, False: 14.3k]
  ------------------
  287|  40.7k|            if (any_shared_bytes) {
  ------------------
  |  Branch (287:17): [True: 6.48k, False: 34.2k]
  ------------------
  288|  6.48k|                access_size = plane_bits;
  289|  6.48k|                if (is_be && word != access_size) {
  ------------------
  |  Branch (289:21): [True: 3.24k, False: 3.24k]
  |  Branch (289:30): [True: 2.52k, False: 720]
  ------------------
  290|       |                    // Before: offset = 8*byte_offset (with word bits of data)
  291|       |                    // After: offset = bit_offset into swapped endian_size word
  292|  2.52k|                    offset = access_size - word - offset;
  293|  2.52k|                }
  294|  34.2k|            } else {
  295|  34.2k|                access_size = word;
  296|  34.2k|            }
  297|  40.7k|        }
  298|  55.0k|        int endian_size = (access_size && !is_ne) ? access_size : 8;
  ------------------
  |  Branch (298:28): [True: 55.0k, False: 0]
  |  Branch (298:43): [True: 13.0k, False: 42.0k]
  ------------------
  299|  55.0k|        int endian_shift = mp_log2(endian_size) - 3;
  300|  55.0k|        if (!MP_IS_POWER_OF_2(endian_size) || endian_shift < 0 || endian_shift > 3)
  ------------------
  |  |   55|   110k|#define MP_IS_POWER_OF_2(x) ((x) > 0 && !((x) & ((x) - 1)))
  |  |  ------------------
  |  |  |  Branch (55:30): [True: 55.0k, False: 0]
  |  |  |  Branch (55:41): [True: 55.0k, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (300:47): [True: 0, False: 55.0k]
  |  Branch (300:67): [True: 0, False: 55.0k]
  ------------------
  301|      0|            goto fail;
  302|  55.0k|        if (desc->endian_shift && desc->endian_shift != endian_shift)
  ------------------
  |  Branch (302:13): [True: 8.76k, False: 46.3k]
  |  Branch (302:35): [True: 0, False: 8.76k]
  ------------------
  303|      0|            goto fail;
  304|  55.0k|        desc->endian_shift = endian_shift;
  305|       |
  306|       |        // We always use bit offsets; this doesn't lose any information,
  307|       |        // and pixdesc is merely more redundant.
  308|  55.0k|        offset += shift;
  309|  55.0k|        if (offset < 0 || offset >= (1 << 6))
  ------------------
  |  Branch (309:13): [True: 0, False: 55.0k]
  |  Branch (309:27): [True: 0, False: 55.0k]
  ------------------
  310|      0|            goto fail;
  311|  55.0k|        if (offset + d->depth > plane_bits)
  ------------------
  |  Branch (311:13): [True: 0, False: 55.0k]
  ------------------
  312|      0|            goto fail;
  313|  55.0k|        if (d->depth < 0 || d->depth >= (1 << 6))
  ------------------
  |  Branch (313:13): [True: 0, False: 55.0k]
  |  Branch (313:29): [True: 0, False: 55.0k]
  ------------------
  314|      0|            goto fail;
  315|  55.0k|        desc->comps[c] = (struct mp_imgfmt_comp_desc){
  316|  55.0k|            .plane = d->plane,
  317|  55.0k|            .offset = offset,
  318|  55.0k|            .size = d->depth,
  319|  55.0k|        };
  320|  55.0k|    }
  321|       |
  322|  54.0k|    for (int p = 0; p < desc->num_planes; p++) {
  ------------------
  |  Branch (322:21): [True: 36.1k, False: 17.9k]
  ------------------
  323|  36.1k|        if (!desc->bpp[p])
  ------------------
  |  Branch (323:13): [True: 0, False: 36.1k]
  ------------------
  324|      0|            goto fail; // plane doesn't exist
  325|  36.1k|    }
  326|       |
  327|       |    // What the fuck: this is probably a pixdesc bug, so fix it.
  328|  17.9k|    if (fmt == AV_PIX_FMT_RGB8) {
  ------------------
  |  Branch (328:9): [True: 180, False: 17.8k]
  ------------------
  329|    180|        desc->comps[2] = (struct mp_imgfmt_comp_desc){0, 0, 2};
  330|    180|        desc->comps[1] = (struct mp_imgfmt_comp_desc){0, 2, 3};
  331|    180|        desc->comps[0] = (struct mp_imgfmt_comp_desc){0, 5, 3};
  332|    180|    }
  333|       |
  334|       |    // Overlap test. If any shared bits are happening, this is not a format we
  335|       |    // can represent (or it's something like Bayer: components in the same bits,
  336|       |    // but different alternating lines).
  337|  17.9k|    bool any_shared_bits = false;
  338|  73.0k|    for (int c = 0; c < pd->nb_components; c++) {
  ------------------
  |  Branch (338:21): [True: 55.0k, False: 17.9k]
  ------------------
  339|   115k|        for (int i = 0; i < c; i++) {
  ------------------
  |  Branch (339:25): [True: 60.8k, False: 55.0k]
  ------------------
  340|  60.8k|            struct mp_imgfmt_comp_desc *c1 = &desc->comps[c];
  341|  60.8k|            struct mp_imgfmt_comp_desc *c2 = &desc->comps[i];
  342|  60.8k|            if (c1->plane == c2->plane) {
  ------------------
  |  Branch (342:17): [True: 30.3k, False: 30.4k]
  ------------------
  343|  30.3k|                if (c1->offset + c1->size > c2->offset &&
  ------------------
  |  Branch (343:21): [True: 18.0k, False: 12.3k]
  ------------------
  344|  30.3k|                    c2->offset + c2->size > c1->offset)
  ------------------
  |  Branch (344:21): [True: 0, False: 18.0k]
  ------------------
  345|      0|                    any_shared_bits = true;
  346|  30.3k|            }
  347|  60.8k|        }
  348|  55.0k|    }
  349|       |
  350|  17.9k|    if (any_shared_bits) {
  ------------------
  |  Branch (350:9): [True: 0, False: 17.9k]
  ------------------
  351|      0|        for (int c = 0; c < pd->nb_components; c++)
  ------------------
  |  Branch (351:25): [True: 0, False: 0]
  ------------------
  352|      0|            desc->comps[c] = (struct mp_imgfmt_comp_desc){0};
  353|      0|    }
  354|       |
  355|       |    // Many important formats have padding within an access word. For example
  356|       |    // yuv420p10 has the upper 6 bit cleared to 0; P010 has the lower 6 bits
  357|       |    // cleared to 0. Pixdesc cannot represent that these bits are 0. There are
  358|       |    // other formats where padding is not guaranteed to be 0, but they are
  359|       |    // described in the same way.
  360|       |    // Apply a heuristic that is supposed to identify formats which use
  361|       |    // guaranteed 0 padding. This could fail, but nobody said this pixdesc crap
  362|       |    // is robust.
  363|  73.0k|    for (int c = 0; c < pd->nb_components; c++) {
  ------------------
  |  Branch (363:21): [True: 55.0k, False: 17.9k]
  ------------------
  364|  55.0k|        struct mp_imgfmt_comp_desc *cd = &desc->comps[c];
  365|       |        // Note: rgb444 would defeat our heuristic if we checked only per comp.
  366|       |        //       also, exclude "bitstream" formats due to monow/monob
  367|  55.0k|        int fsize = MP_ALIGN_UP(cd->size, 8);
  ------------------
  |  |   52|  55.0k|#define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
  ------------------
  368|  55.0k|        if (!any_shared_bytes && el_bits == 8 && fsize != cd->size &&
  ------------------
  |  Branch (368:13): [True: 45.0k, False: 10.0k]
  |  Branch (368:34): [True: 45.0k, False: 0]
  |  Branch (368:50): [True: 11.3k, False: 33.6k]
  ------------------
  369|  55.0k|            fsize - cd->size <= (1 << 3))
  ------------------
  |  Branch (369:13): [True: 11.3k, False: 0]
  ------------------
  370|  11.3k|        {
  371|  11.3k|            if (!(cd->offset % 8u)) {
  ------------------
  |  Branch (371:17): [True: 10.4k, False: 900]
  ------------------
  372|  10.4k|                cd->pad = -(fsize - cd->size);
  373|  10.4k|                cd->size = fsize;
  374|  10.4k|            } else if (!((cd->offset + cd->size) % 8u)) {
  ------------------
  |  Branch (374:24): [True: 900, False: 0]
  ------------------
  375|    900|                cd->pad = fsize - cd->size;
  376|    900|                cd->size = fsize;
  377|    900|                cd->offset = MP_ALIGN_DOWN(cd->offset, 8);
  ------------------
  |  |   53|    900|#define MP_ALIGN_DOWN(x, align) ((x) & ~((align) - 1))
  ------------------
  378|    900|            }
  379|  11.3k|        }
  380|  55.0k|    }
  381|       |
  382|       |    // The alpha component always has ID 4 (index 3) in our representation, so
  383|       |    // move the alpha component to there.
  384|  17.9k|    if (has_alpha && pd->nb_components < 4) {
  ------------------
  |  Branch (384:9): [True: 3.84k, False: 14.1k]
  |  Branch (384:22): [True: 300, False: 3.54k]
  ------------------
  385|    300|        desc->comps[3] = desc->comps[pd->nb_components - 1];
  386|    300|        desc->comps[pd->nb_components - 1] = (struct mp_imgfmt_comp_desc){0};
  387|    300|    }
  388|       |
  389|  17.9k|    if (is_packed_ss_yuv) {
  ------------------
  |  Branch (389:9): [True: 600, False: 17.3k]
  ------------------
  390|    600|        desc->flags |= MP_IMGFLAG_PACKED_SS_YUV;
  ------------------
  |  |   86|    600|#define MP_IMGFLAG_PACKED_SS_YUV (1 << 15)
  ------------------
  391|    600|        desc->bpp[0] /= 1 << pd->log2_chroma_w;
  392|  17.3k|    } else if (!any_shared_bits) {
  ------------------
  |  Branch (392:16): [True: 17.3k, False: 0]
  ------------------
  393|  17.3k|        desc->flags |= MP_IMGFLAG_HAS_COMPS;
  ------------------
  |  |   34|  17.3k|#define MP_IMGFLAG_HAS_COMPS    (1 << 0)
  ------------------
  394|  17.3k|    }
  395|       |
  396|  17.9k|    return;
  397|       |
  398|  1.98k|fail:
  399|  9.90k|    for (int n = 0; n < 4; n++)
  ------------------
  |  Branch (399:21): [True: 7.92k, False: 1.98k]
  ------------------
  400|  7.92k|        desc->comps[n] = (struct mp_imgfmt_comp_desc){0};
  401|       |    // Average bit size fallback.
  402|  1.98k|    int num_planes = av_pix_fmt_count_planes(fmt);
  403|  1.98k|    desc->num_planes = MPCLAMP(num_planes, 0, MP_MAX_PLANES);
  ------------------
  |  |   45|  1.98k|#define MPCLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
  |  |  ------------------
  |  |  |  Branch (45:31): [True: 0, False: 1.98k]
  |  |  |  Branch (45:56): [True: 0, False: 1.98k]
  |  |  ------------------
  ------------------
  404|  2.16k|    for (int p = 0; p < desc->num_planes; p++) {
  ------------------
  |  Branch (404:21): [True: 180, False: 1.98k]
  ------------------
  405|    180|        int ls = av_image_get_linesize(fmt, 256, p);
  406|    180|        desc->bpp[p] = ls > 0 ? ls * 8 / 256 : 0;
  ------------------
  |  Branch (406:24): [True: 180, False: 0]
  ------------------
  407|    180|    }
  408|  1.98k|}
img_format.c:get_forced_csp_from_flags:
  669|  12.6k|{
  670|  12.6k|    if (flags & MP_IMGFLAG_COLOR_XYZ)
  ------------------
  |  |   58|  12.6k|#define MP_IMGFLAG_COLOR_XYZ    (4 << 6)
  ------------------
  |  Branch (670:9): [True: 60, False: 12.6k]
  ------------------
  671|     60|        return PL_COLOR_SYSTEM_XYZ;
  672|       |
  673|  12.6k|    if (flags & MP_IMGFLAG_COLOR_RGB)
  ------------------
  |  |   57|  12.6k|#define MP_IMGFLAG_COLOR_RGB    (2 << 6)
  ------------------
  |  Branch (673:9): [True: 4.75k, False: 7.86k]
  ------------------
  674|  4.75k|        return PL_COLOR_SYSTEM_RGB;
  675|       |
  676|  7.86k|    return PL_COLOR_SYSTEM_UNKNOWN;
  677|  12.6k|}
img_format.c:get_component_type_from_flags:
  685|  15.1k|{
  686|  15.1k|    if (flags & MP_IMGFLAG_TYPE_UINT)
  ------------------
  |  |   62|  15.1k|#define MP_IMGFLAG_TYPE_UINT    (1 << 10)
  ------------------
  |  Branch (686:9): [True: 12.8k, False: 2.34k]
  ------------------
  687|  12.8k|        return MP_COMPONENT_TYPE_UINT;
  688|       |
  689|  2.34k|    if (flags & MP_IMGFLAG_TYPE_FLOAT)
  ------------------
  |  |   63|  2.34k|#define MP_IMGFLAG_TYPE_FLOAT   (2 << 10)
  ------------------
  |  Branch (689:9): [True: 2.34k, False: 0]
  ------------------
  690|  2.34k|        return MP_COMPONENT_TYPE_FLOAT;
  691|       |
  692|      0|    return MP_COMPONENT_TYPE_UNKNOWN;
  693|  2.34k|}
img_format.c:validate_regular_imgfmt:
  628|  12.4k|{
  629|  12.4k|    bool present[MP_NUM_COMPONENTS] = {0};
  630|  12.4k|    int n_comp = 0;
  631|       |
  632|  43.9k|    for (int n = 0; n < fmt->num_planes; n++) {
  ------------------
  |  Branch (632:21): [True: 31.5k, False: 12.4k]
  ------------------
  633|  31.5k|        const struct mp_regular_imgfmt_plane *plane = &fmt->planes[n];
  634|  31.5k|        n_comp += plane->num_components;
  635|  31.5k|        if (n_comp > MP_NUM_COMPONENTS)
  ------------------
  |  |   29|  31.5k|#define MP_NUM_COMPONENTS 4
  ------------------
  |  Branch (635:13): [True: 0, False: 31.5k]
  ------------------
  636|      0|            return false;
  637|  31.5k|        if (!plane->num_components)
  ------------------
  |  Branch (637:13): [True: 0, False: 31.5k]
  ------------------
  638|      0|            return false; // no empty planes in between allowed
  639|       |
  640|  31.5k|        bool pad_only = true;
  641|  31.5k|        int chroma_luma = 0; // luma: 1, chroma: 2, both: 3
  642|  70.9k|        for (int i = 0; i < plane->num_components; i++) {
  ------------------
  |  Branch (642:25): [True: 39.4k, False: 31.5k]
  ------------------
  643|  39.4k|            int comp = plane->components[i];
  644|  39.4k|            if (comp > MP_NUM_COMPONENTS)
  ------------------
  |  |   29|  39.4k|#define MP_NUM_COMPONENTS 4
  ------------------
  |  Branch (644:17): [True: 0, False: 39.4k]
  ------------------
  645|      0|                return false;
  646|  39.4k|            if (comp == 0)
  ------------------
  |  Branch (646:17): [True: 720, False: 38.7k]
  ------------------
  647|    720|                continue;
  648|  38.7k|            pad_only = false;
  649|  38.7k|            if (present[comp - 1])
  ------------------
  |  Branch (649:17): [True: 0, False: 38.7k]
  ------------------
  650|      0|                return false; // no duplicates
  651|  38.7k|            present[comp - 1] = true;
  652|  38.7k|            chroma_luma |= (comp == 2 || comp == 3) ? 2 : 1;
  ------------------
  |  Branch (652:29): [True: 11.1k, False: 27.5k]
  |  Branch (652:42): [True: 11.1k, False: 16.3k]
  ------------------
  653|  38.7k|        }
  654|  31.5k|        if (pad_only)
  ------------------
  |  Branch (654:13): [True: 0, False: 31.5k]
  ------------------
  655|      0|            return false; // no planes with only padding allowed
  656|  31.5k|        if ((fmt->chroma_xs > 0 || fmt->chroma_ys > 0) && chroma_luma == 3)
  ------------------
  |  Branch (656:14): [True: 14.7k, False: 16.8k]
  |  Branch (656:36): [True: 2.34k, False: 14.4k]
  |  Branch (656:59): [True: 0, False: 17.0k]
  ------------------
  657|      0|            return false; // separate chroma/luma planes required
  658|  31.5k|    }
  659|       |
  660|  12.4k|    if (!(present[0] || present[3]) ||  // at least component 1 or alpha needed
  ------------------
  |  Branch (660:11): [True: 12.4k, False: 0]
  |  Branch (660:25): [True: 0, False: 0]
  ------------------
  661|  12.4k|        (present[1] && !present[0]) ||  // component 2 requires component 1
  ------------------
  |  Branch (661:10): [True: 11.1k, False: 1.32k]
  |  Branch (661:24): [True: 0, False: 11.1k]
  ------------------
  662|  12.4k|        (present[2] && !present[1]))    // component 3 requires component 2
  ------------------
  |  Branch (662:10): [True: 11.1k, False: 1.32k]
  |  Branch (662:24): [True: 0, False: 11.1k]
  ------------------
  663|      0|        return false;
  664|       |
  665|  12.4k|    return true;
  666|  12.4k|}
img_format.c:regular_imgfmt_equals:
  771|  12.0k|{
  772|  12.0k|    if (a->component_type != b->component_type ||
  ------------------
  |  Branch (772:9): [True: 2.34k, False: 9.66k]
  ------------------
  773|  12.0k|        a->component_size != b->component_size ||
  ------------------
  |  Branch (773:9): [True: 3.66k, False: 6.00k]
  ------------------
  774|  12.0k|        a->num_planes     != b->num_planes ||
  ------------------
  |  Branch (774:9): [True: 3.96k, False: 2.04k]
  ------------------
  775|  12.0k|        a->component_pad  != b->component_pad ||
  ------------------
  |  Branch (775:9): [True: 720, False: 1.32k]
  ------------------
  776|  12.0k|        a->forced_csp     != b->forced_csp ||
  ------------------
  |  Branch (776:9): [True: 1.14k, False: 180]
  ------------------
  777|  12.0k|        a->chroma_xs      != b->chroma_xs ||
  ------------------
  |  Branch (777:9): [True: 0, False: 180]
  ------------------
  778|  12.0k|        a->chroma_ys      != b->chroma_ys)
  ------------------
  |  Branch (778:9): [True: 0, False: 180]
  ------------------
  779|  11.8k|        return false;
  780|       |
  781|    780|    for (int n = 0; n < a->num_planes; n++) {
  ------------------
  |  Branch (781:21): [True: 600, False: 180]
  ------------------
  782|    600|        int num_comps = a->planes[n].num_components;
  783|    600|        if (num_comps != b->planes[n].num_components)
  ------------------
  |  Branch (783:13): [True: 0, False: 600]
  ------------------
  784|      0|            return false;
  785|  1.20k|        for (int i = 0; i < num_comps; i++) {
  ------------------
  |  Branch (785:25): [True: 600, False: 600]
  ------------------
  786|    600|            if (a->planes[n].components[i] != b->planes[n].components[i])
  ------------------
  |  Branch (786:17): [True: 0, False: 600]
  ------------------
  787|      0|                return false;
  788|    600|        }
  789|    600|    }
  790|       |
  791|    180|    return true;
  792|    180|}

mp_image_get_alloc_size:
   91|    249|{
   92|    249|    int stride[MP_MAX_PLANES];
   93|    249|    int plane_offset[MP_MAX_PLANES];
   94|    249|    int plane_size[MP_MAX_PLANES];
   95|    249|    return mp_image_layout(imgfmt, w, h, stride_align, stride, plane_offset,
   96|    249|                           plane_size);
   97|    249|}
mp_image_setfmt:
  191|    288|{
  192|    288|    struct mp_imgfmt_desc fmt = mp_imgfmt_get_desc(out_fmt);
  193|    288|    mpi->params.imgfmt = fmt.id;
  194|    288|    mpi->fmt = fmt;
  195|    288|    mpi->imgfmt = fmt.id;
  196|    288|    mpi->num_planes = fmt.num_planes;
  197|    288|    mpi->params.repr.alpha = (fmt.flags & MP_IMGFLAG_ALPHA) ? PL_ALPHA_INDEPENDENT
  ------------------
  |  |   52|    288|#define MP_IMGFLAG_ALPHA        (1 << 5)
  ------------------
  |  Branch (197:30): [True: 120, False: 168]
  ------------------
  198|    288|#if PL_API_VER >= 344
  199|    288|                                                            : PL_ALPHA_NONE;
  200|       |#else
  201|       |                                                            : PL_ALPHA_UNKNOWN;
  202|       |#endif
  203|    288|    mpi->params.repr.bits = (struct pl_bit_encoding) {
  204|    288|        .sample_depth = fmt.comps[0].size,
  205|    288|        .color_depth = fmt.comps[0].size - abs(fmt.comps[0].pad),
  206|    288|        .bit_shift = MPMAX(0, fmt.comps[0].pad),
  ------------------
  |  |   43|    288|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 288]
  |  |  ------------------
  ------------------
  207|    288|    };
  208|    288|}
mp_chroma_div_up:
  226|  23.7k|{
  227|  23.7k|    return (size + (1 << shift) - 1) >> shift;
  228|  23.7k|}
mp_image_plane_w:
  232|    138|{
  233|    138|    return mp_chroma_div_up(mpi->w, mpi->fmt.xs[plane]);
  234|    138|}
mp_image_plane_h:
  238|    138|{
  239|    138|    return mp_chroma_div_up(mpi->h, mpi->fmt.ys[plane]);
  240|    138|}
mp_image_set_size:
  244|    426|{
  245|    426|    mp_assert(w >= 0 && h >= 0);
  ------------------
  |  |   41|    426|#define mp_assert assert
  ------------------
  246|    426|    mpi->w = mpi->params.w = w;
  247|    426|    mpi->h = mpi->params.h = h;
  248|    426|}
mp_image_set_params:
  252|     39|{
  253|       |    // possibly initialize other stuff
  254|     39|    mp_image_setfmt(image, params->imgfmt);
  255|     39|    mp_image_set_size(image, params->w, params->h);
  256|     39|    image->params = *params;
  257|     39|}
mp_image_alloc:
  260|    249|{
  261|    249|    struct mp_image *mpi = talloc_zero(NULL, struct mp_image);
  ------------------
  |  |   27|    249|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    249|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    249|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  262|    249|    talloc_set_destructor(mpi, mp_image_destructor);
  ------------------
  |  |   41|    249|#define talloc_set_destructor           ta_set_destructor
  ------------------
  263|       |
  264|    249|    mp_image_set_size(mpi, w, h);
  265|    249|    mp_image_setfmt(mpi, imgfmt);
  266|    249|    if (!mp_image_alloc_planes(mpi)) {
  ------------------
  |  Branch (266:9): [True: 0, False: 249]
  ------------------
  267|      0|        talloc_free(mpi);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  268|      0|        return NULL;
  269|      0|    }
  270|    249|    return mpi;
  271|    249|}
mp_image_new_ref:
  335|     60|{
  336|     60|    if (!img)
  ------------------
  |  Branch (336:9): [True: 0, False: 60]
  ------------------
  337|      0|        return NULL;
  338|       |
  339|     60|    if (!img->bufs[0])
  ------------------
  |  Branch (339:9): [True: 0, False: 60]
  ------------------
  340|      0|        return mp_image_new_copy(img);
  341|       |
  342|     60|    struct mp_image *new = talloc_ptrtype(NULL, new);
  ------------------
  |  |   34|     60|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|     60|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     60|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  343|     60|    talloc_set_destructor(new, mp_image_destructor);
  ------------------
  |  |   41|     60|#define talloc_set_destructor           ta_set_destructor
  ------------------
  344|     60|    *new = *img;
  345|       |
  346|    300|    for (int p = 0; p < MP_MAX_PLANES; p++)
  ------------------
  |  |   28|    300|#define MP_MAX_PLANES 4
  ------------------
  |  Branch (346:21): [True: 240, False: 60]
  ------------------
  347|    240|        ref_buffer(&new->bufs[p]);
  348|       |
  349|     60|    ref_buffer(&new->hwctx);
  350|     60|    ref_buffer(&new->icc_profile);
  351|     60|    ref_buffer(&new->a53_cc);
  352|     60|    ref_buffer(&new->dovi);
  353|     60|    ref_buffer(&new->film_grain);
  354|       |
  355|     60|    new->ff_side_data = talloc_memdup(NULL, new->ff_side_data,
  ------------------
  |  |   49|     60|#define talloc_memdup                   ta_xmemdup
  |  |  ------------------
  |  |  |  |  157|     60|#define ta_xmemdup(...)         ta_dbg_set_loc(ta_xmemdup(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|     60|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|     60|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|     60|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  356|     60|                        new->num_ff_side_data * sizeof(new->ff_side_data[0]));
  357|     60|    for (int n = 0; n < new->num_ff_side_data; n++)
  ------------------
  |  Branch (357:21): [True: 0, False: 60]
  ------------------
  358|      0|        ref_buffer(&new->ff_side_data[n].buf);
  359|       |
  360|     60|    return new;
  361|     60|}
mp_image_is_writeable:
  418|     98|{
  419|     98|    if (!img->bufs[0])
  ------------------
  |  Branch (419:9): [True: 0, False: 98]
  ------------------
  420|      0|        return true; // not ref-counted => always considered writeable
  421|    196|    for (int p = 0; p < MP_MAX_PLANES; p++) {
  ------------------
  |  |   28|    196|#define MP_MAX_PLANES 4
  ------------------
  |  Branch (421:21): [True: 196, False: 0]
  ------------------
  422|    196|        if (!img->bufs[p])
  ------------------
  |  Branch (422:13): [True: 98, False: 98]
  ------------------
  423|     98|            break;
  424|     98|        if (!av_buffer_is_writable(img->bufs[p]))
  ------------------
  |  Branch (424:13): [True: 0, False: 98]
  ------------------
  425|      0|            return false;
  426|     98|    }
  427|     98|    return true;
  428|     98|}
mp_image_make_writeable:
  435|     38|{
  436|     38|    if (mp_image_is_writeable(img))
  ------------------
  |  Branch (436:9): [True: 38, False: 0]
  ------------------
  437|     38|        return true;
  438|       |
  439|      0|    struct mp_image *new = mp_image_new_copy(img);
  440|      0|    if (!new)
  ------------------
  |  Branch (440:9): [True: 0, False: 0]
  ------------------
  441|      0|        return false;
  442|      0|    mp_image_steal_data(img, new);
  443|      0|    mp_assert(mp_image_is_writeable(img));
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  444|      0|    return true;
  445|      0|}
mp_image_unrefp:
  459|  38.0k|{
  460|  38.0k|    talloc_free(*p_img);
  ------------------
  |  |   47|  38.0k|#define talloc_free                     ta_free
  ------------------
  461|  38.0k|    *p_img = NULL;
  462|  38.0k|}
memcpy_pic:
  466|  1.61k|{
  467|  1.61k|    if (bytesPerLine == dstStride && dstStride == srcStride && height) {
  ------------------
  |  Branch (467:9): [True: 78, False: 1.53k]
  |  Branch (467:38): [True: 78, False: 0]
  |  Branch (467:64): [True: 78, False: 0]
  ------------------
  468|     78|        if (srcStride < 0) {
  ------------------
  |  Branch (468:13): [True: 0, False: 78]
  ------------------
  469|      0|            src = (uint8_t*)src + (height - 1) * srcStride;
  470|      0|            dst = (uint8_t*)dst + (height - 1) * dstStride;
  471|      0|            srcStride = -srcStride;
  472|      0|        }
  473|       |
  474|     78|        memcpy(dst, src, srcStride * (height - 1) + bytesPerLine);
  475|  1.53k|    } else {
  476|  26.4k|        for (int i = 0; i < height; i++) {
  ------------------
  |  Branch (476:25): [True: 24.8k, False: 1.53k]
  ------------------
  477|  24.8k|            memcpy(dst, src, bytesPerLine);
  478|  24.8k|            src = (uint8_t*)src + srcStride;
  479|  24.8k|            dst = (uint8_t*)dst + dstStride;
  480|  24.8k|        }
  481|  1.53k|    }
  482|  1.61k|}
mp_image_crop:
  578|    138|{
  579|    138|    mp_assert(x0 >= 0 && y0 >= 0);
  ------------------
  |  |   41|    138|#define mp_assert assert
  ------------------
  580|    138|    mp_assert(x0 <= x1 && y0 <= y1);
  ------------------
  |  |   41|    138|#define mp_assert assert
  ------------------
  581|    138|    mp_assert(x1 <= img->w && y1 <= img->h);
  ------------------
  |  |   41|    138|#define mp_assert assert
  ------------------
  582|    138|    mp_assert(!(x0 & (img->fmt.align_x - 1)));
  ------------------
  |  |   41|    138|#define mp_assert assert
  ------------------
  583|    138|    mp_assert(!(y0 & (img->fmt.align_y - 1)));
  ------------------
  |  |   41|    138|#define mp_assert assert
  ------------------
  584|       |
  585|    276|    for (int p = 0; p < img->num_planes; ++p) {
  ------------------
  |  Branch (585:21): [True: 138, False: 138]
  ------------------
  586|    138|        img->planes[p] += (y0 >> img->fmt.ys[p]) * img->stride[p] +
  587|    138|                          (x0 >> img->fmt.xs[p]) * img->fmt.bpp[p] / 8;
  588|    138|    }
  589|    138|    mp_image_set_size(img, x1 - x0, y1 - y0);
  590|    138|}
mp_image_clear:
  646|    138|{
  647|    138|    mp_assert(x0 >= 0 && y0 >= 0);
  ------------------
  |  |   41|    138|#define mp_assert assert
  ------------------
  648|    138|    mp_assert(x0 <= x1 && y0 <= y1);
  ------------------
  |  |   41|    138|#define mp_assert assert
  ------------------
  649|    138|    mp_assert(x1 <= img->w && y1 <= img->h);
  ------------------
  |  |   41|    138|#define mp_assert assert
  ------------------
  650|    138|    mp_assert(!(x0 & (img->fmt.align_x - 1)));
  ------------------
  |  |   41|    138|#define mp_assert assert
  ------------------
  651|    138|    mp_assert(!(y0 & (img->fmt.align_y - 1)));
  ------------------
  |  |   41|    138|#define mp_assert assert
  ------------------
  652|       |
  653|    138|    struct mp_image area = *img;
  654|    138|    struct mp_imgfmt_desc *fmt = &area.fmt;
  655|    138|    mp_image_crop(&area, x0, y0, x1, y1);
  656|       |
  657|       |    // "Black" color for each plane.
  658|    138|    uint8_t plane_clear[MP_MAX_PLANES][8] = {0};
  659|    138|    int plane_size[MP_MAX_PLANES] = {0};
  660|    138|    int misery = 1; // pixel group width
  661|       |
  662|       |    // YUV integer chroma needs special consideration, and technically luma is
  663|       |    // usually not 0 either.
  664|    138|    if ((fmt->flags & (MP_IMGFLAG_HAS_COMPS | MP_IMGFLAG_PACKED_SS_YUV)) &&
  ------------------
  |  |   34|    138|#define MP_IMGFLAG_HAS_COMPS    (1 << 0)
  ------------------
                  if ((fmt->flags & (MP_IMGFLAG_HAS_COMPS | MP_IMGFLAG_PACKED_SS_YUV)) &&
  ------------------
  |  |   86|    138|#define MP_IMGFLAG_PACKED_SS_YUV (1 << 15)
  ------------------
  |  Branch (664:9): [True: 138, False: 0]
  ------------------
  665|    138|        (fmt->flags & MP_IMGFLAG_TYPE_MASK) == MP_IMGFLAG_TYPE_UINT &&
  ------------------
  |  |   61|    138|#define MP_IMGFLAG_TYPE_MASK    (15 << 10)
  ------------------
                      (fmt->flags & MP_IMGFLAG_TYPE_MASK) == MP_IMGFLAG_TYPE_UINT &&
  ------------------
  |  |   62|    276|#define MP_IMGFLAG_TYPE_UINT    (1 << 10)
  ------------------
  |  Branch (665:9): [True: 138, False: 0]
  ------------------
  666|    138|        (fmt->flags & MP_IMGFLAG_COLOR_MASK) == MP_IMGFLAG_COLOR_YUV)
  ------------------
  |  |   55|    138|#define MP_IMGFLAG_COLOR_MASK   (15 << 6)
  ------------------
                      (fmt->flags & MP_IMGFLAG_COLOR_MASK) == MP_IMGFLAG_COLOR_YUV)
  ------------------
  |  |   56|    138|#define MP_IMGFLAG_COLOR_YUV    (1 << 6)
  ------------------
  |  Branch (666:9): [True: 0, False: 138]
  ------------------
  667|      0|    {
  668|      0|        uint64_t plane_clear_i[MP_MAX_PLANES] = {0};
  669|       |
  670|       |        // Need to handle "multiple" pixels with packed YUV.
  671|      0|        uint8_t luma_offsets[4] = {0};
  672|      0|        if (fmt->flags & MP_IMGFLAG_PACKED_SS_YUV) {
  ------------------
  |  |   86|      0|#define MP_IMGFLAG_PACKED_SS_YUV (1 << 15)
  ------------------
  |  Branch (672:13): [True: 0, False: 0]
  ------------------
  673|      0|            misery = fmt->align_x;
  674|      0|            if (misery <= MP_ARRAY_SIZE(luma_offsets)) // ignore if out of bounds
  ------------------
  |  |   48|      0|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (674:17): [True: 0, False: 0]
  ------------------
  675|      0|                mp_imgfmt_get_packed_yuv_locations(fmt->id, luma_offsets);
  676|      0|        }
  677|       |
  678|      0|        for (int c = 0; c < 4; c++) {
  ------------------
  |  Branch (678:25): [True: 0, False: 0]
  ------------------
  679|      0|            struct mp_imgfmt_comp_desc *cd = &fmt->comps[c];
  680|      0|            int plane_bits = fmt->bpp[cd->plane] * misery;
  681|      0|            if (plane_bits <= 64 && plane_bits % 8u == 0 && cd->size) {
  ------------------
  |  Branch (681:17): [True: 0, False: 0]
  |  Branch (681:37): [True: 0, False: 0]
  |  Branch (681:61): [True: 0, False: 0]
  ------------------
  682|      0|                plane_size[cd->plane] = plane_bits / 8u;
  683|      0|                int depth = cd->size + MPMIN(cd->pad, 0);
  ------------------
  |  |   44|      0|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  684|      0|                double m, o;
  685|      0|                mp_get_csp_uint_mul(area.params.repr.sys,
  686|      0|                                    area.params.repr.levels,
  687|      0|                                    depth, c + 1, &m, &o);
  688|      0|                uint64_t val = MPCLAMP(lrint((0 - o) / m), 0, 1ull << depth);
  ------------------
  |  |   45|      0|#define MPCLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
  |  |  ------------------
  |  |  |  Branch (45:31): [True: 0, False: 0]
  |  |  |  Branch (45:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  689|      0|                plane_clear_i[cd->plane] |= val << cd->offset;
  690|      0|                for (int x = 1; x < (c ? 0 : misery); x++)
  ------------------
  |  Branch (690:33): [True: 0, False: 0]
  |  Branch (690:38): [True: 0, False: 0]
  ------------------
  691|      0|                    plane_clear_i[cd->plane] |= val << luma_offsets[x];
  692|      0|            }
  693|      0|        }
  694|       |
  695|      0|        for (int p = 0; p < MP_MAX_PLANES; p++) {
  ------------------
  |  |   28|      0|#define MP_MAX_PLANES 4
  ------------------
  |  Branch (695:25): [True: 0, False: 0]
  ------------------
  696|      0|            if (!plane_clear_i[p])
  ------------------
  |  Branch (696:17): [True: 0, False: 0]
  ------------------
  697|      0|                plane_size[p] = 0;
  698|      0|            memcpy(&plane_clear[p][0], &plane_clear_i[p], 8); // endian dependent
  699|       |
  700|      0|            if (fmt->endian_shift) {
  ------------------
  |  Branch (700:17): [True: 0, False: 0]
  ------------------
  701|      0|                endian_swap_bytes(&plane_clear[p][0], plane_size[p],
  702|      0|                                  1 << fmt->endian_shift);
  703|      0|            }
  704|      0|        }
  705|      0|    }
  706|       |
  707|    276|    for (int p = 0; p < area.num_planes; p++) {
  ------------------
  |  Branch (707:21): [True: 138, False: 138]
  ------------------
  708|    138|        int p_h = mp_image_plane_h(&area, p);
  709|    138|        int p_w = mp_image_plane_w(&area, p);
  710|  24.9k|        for (int y = 0; y < p_h; y++) {
  ------------------
  |  Branch (710:25): [True: 24.8k, False: 138]
  ------------------
  711|  24.8k|            void *ptr = area.planes[p] + (ptrdiff_t)area.stride[p] * y;
  712|  24.8k|            if (plane_size[p]) {
  ------------------
  |  Branch (712:17): [True: 0, False: 24.8k]
  ------------------
  713|      0|                memset_pattern(ptr, p_w / misery, plane_clear[p], plane_size[p]);
  714|  24.8k|            } else {
  715|  24.8k|                memset(ptr, 0, mp_image_plane_bytes(&area, p, 0, area.w));
  716|  24.8k|            }
  717|  24.8k|        }
  718|    138|    }
  719|    138|}
mp_image_crop_valid:
  745|    156|{
  746|    156|    return p->crop.x1 > p->crop.x0 && p->crop.y1 > p->crop.y0 &&
  ------------------
  |  Branch (746:12): [True: 0, False: 156]
  |  Branch (746:39): [True: 0, False: 0]
  ------------------
  747|    156|           p->crop.x0 >= 0 && p->crop.y0 >= 0 &&
  ------------------
  |  Branch (747:12): [True: 0, False: 0]
  |  Branch (747:31): [True: 0, False: 0]
  ------------------
  748|    156|           p->crop.x1 <= p->w && p->crop.y1 <= p->h;
  ------------------
  |  Branch (748:12): [True: 0, False: 0]
  |  Branch (748:34): [True: 0, False: 0]
  ------------------
  749|    156|}
mp_image_params_get_dsize:
  754|     78|{
  755|     78|    if (mp_image_crop_valid(p))
  ------------------
  |  Branch (755:9): [True: 0, False: 78]
  ------------------
  756|      0|    {
  757|      0|        *d_w = mp_rect_w(p->crop);
  ------------------
  |  |  128|      0|#define mp_rect_w(r) ((r).x1 - (r).x0)
  ------------------
  758|      0|        *d_h = mp_rect_h(p->crop);
  ------------------
  |  |  129|      0|#define mp_rect_h(r) ((r).y1 - (r).y0)
  ------------------
  759|     78|    } else {
  760|     78|        *d_w = p->w;
  761|     78|        *d_h = p->h;
  762|     78|    }
  763|       |
  764|     78|    if (p->p_w > p->p_h && p->p_h >= 1)
  ------------------
  |  Branch (764:9): [True: 0, False: 78]
  |  Branch (764:28): [True: 0, False: 0]
  ------------------
  765|      0|        *d_w = MPCLAMP(*d_w * (int64_t)p->p_w / p->p_h, 1, INT_MAX);
  ------------------
  |  |   45|      0|#define MPCLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
  |  |  ------------------
  |  |  |  Branch (45:31): [True: 0, False: 0]
  |  |  |  Branch (45:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  766|     78|    if (p->p_h > p->p_w && p->p_w >= 1)
  ------------------
  |  Branch (766:9): [True: 0, False: 78]
  |  Branch (766:28): [True: 0, False: 0]
  ------------------
  767|      0|        *d_h = MPCLAMP(*d_h * (int64_t)p->p_h / p->p_w, 1, INT_MAX);
  ------------------
  |  |   45|      0|#define MPCLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
  |  |  ------------------
  |  |  |  Branch (45:31): [True: 0, False: 0]
  |  |  |  Branch (45:56): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  768|     78|}
mp_image_params_to_str_buf:
  779|     39|{
  780|     39|    if (p && p->imgfmt) {
  ------------------
  |  Branch (780:9): [True: 39, False: 0]
  |  Branch (780:14): [True: 39, False: 0]
  ------------------
  781|     39|        snprintf(b, bs, "%dx%d", p->w, p->h);
  782|     39|        if (p->p_w != p->p_h || !p->p_w)
  ------------------
  |  Branch (782:13): [True: 0, False: 39]
  |  Branch (782:33): [True: 0, False: 39]
  ------------------
  783|      0|            mp_snprintf_cat(b, bs, " [%d:%d]", p->p_w, p->p_h);
  784|     39|        mp_snprintf_cat(b, bs, " %s", mp_imgfmt_to_name(p->imgfmt));
  ------------------
  |  |  331|     39|#define mp_imgfmt_to_name(fmt) mp_imgfmt_to_name_buf((char[16]){0}, 16, (fmt))
  ------------------
  785|     39|        if (p->hw_subfmt)
  ------------------
  |  Branch (785:13): [True: 0, False: 39]
  ------------------
  786|      0|            mp_snprintf_cat(b, bs, "[%s]", mp_imgfmt_to_name(p->hw_subfmt));
  ------------------
  |  |  331|      0|#define mp_imgfmt_to_name(fmt) mp_imgfmt_to_name_buf((char[16]){0}, 16, (fmt))
  ------------------
  787|     39|        mp_snprintf_cat(b, bs, " %s/%s/%s/%s/%s",
  788|     39|                        m_opt_choice_str(pl_csp_names, p->repr.sys),
  789|     39|                        m_opt_choice_str(pl_csp_prim_names, p->color.primaries),
  790|     39|                        m_opt_choice_str(pl_csp_trc_names, p->color.transfer),
  791|     39|                        m_opt_choice_str(pl_csp_levels_names, p->repr.levels),
  792|     39|                        m_opt_choice_str(mp_csp_light_names, p->light));
  793|     39|        mp_snprintf_cat(b, bs, " CL=%s",
  794|     39|                        m_opt_choice_str(pl_chroma_names, p->chroma_location));
  795|     39|        if (mp_image_crop_valid(p)) {
  ------------------
  |  Branch (795:13): [True: 0, False: 39]
  ------------------
  796|      0|            mp_snprintf_cat(b, bs, " crop=%dx%d+%d+%d", mp_rect_w(p->crop),
  ------------------
  |  |  128|      0|#define mp_rect_w(r) ((r).x1 - (r).x0)
  ------------------
  797|      0|                            mp_rect_h(p->crop), p->crop.x0, p->crop.y0);
  ------------------
  |  |  129|      0|#define mp_rect_h(r) ((r).y1 - (r).y0)
  ------------------
  798|      0|        }
  799|     39|        if (p->rotate)
  ------------------
  |  Branch (799:13): [True: 0, False: 39]
  ------------------
  800|      0|            mp_snprintf_cat(b, bs, " rot=%d", p->rotate);
  801|     39|        if (p->stereo3d > 0) {
  ------------------
  |  Branch (801:13): [True: 0, False: 39]
  ------------------
  802|      0|            mp_snprintf_cat(b, bs, " stereo=%s",
  803|      0|                            MP_STEREO3D_NAME_DEF(p->stereo3d, "?"));
  ------------------
  |  |   67|      0|    (MP_STEREO3D_NAME(x) ? MP_STEREO3D_NAME(x) : (def))
  |  |  ------------------
  |  |  |  |   64|      0|#define MP_STEREO3D_NAME(x) m_opt_choice_str(mp_stereo3d_names, x)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (64:29): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |                   (MP_STEREO3D_NAME(x) ? MP_STEREO3D_NAME(x) : (def))
  |  |  ------------------
  |  |  |  |   64|      0|#define MP_STEREO3D_NAME(x) m_opt_choice_str(mp_stereo3d_names, x)
  |  |  ------------------
  ------------------
  804|      0|        }
  805|     39|        if (p->repr.alpha) {
  ------------------
  |  Branch (805:13): [True: 0, False: 39]
  ------------------
  806|      0|            mp_snprintf_cat(b, bs, " A=%s",
  807|      0|                            m_opt_choice_str(pl_alpha_names, p->repr.alpha));
  808|      0|        }
  809|     39|    } else {
  810|      0|        snprintf(b, bs, "???");
  811|      0|    }
  812|     39|    return b;
  813|     39|}
mp_image_params_valid:
  818|    498|{
  819|       |    // av_image_check_size has similar checks and triggers around 16000*16000
  820|       |    // It's mostly needed to deal with the fact that offsets are sometimes
  821|       |    // ints. We also should (for now) do the same as FFmpeg, to be sure large
  822|       |    // images don't crash with libswscale or when wrapping with AVFrame and
  823|       |    // passing the result to filters.
  824|    498|    if (p->w <= 0 || p->h <= 0 || (p->w + 128LL) * (p->h + 128LL) >= INT_MAX / 8)
  ------------------
  |  Branch (824:9): [True: 0, False: 498]
  |  Branch (824:22): [True: 0, False: 498]
  |  Branch (824:35): [True: 0, False: 498]
  ------------------
  825|      0|        return false;
  826|       |
  827|    498|    if (p->p_w < 0 || p->p_h < 0)
  ------------------
  |  Branch (827:9): [True: 0, False: 498]
  |  Branch (827:23): [True: 0, False: 498]
  ------------------
  828|      0|        return false;
  829|       |
  830|    498|    if (p->rotate < 0 || p->rotate >= 360)
  ------------------
  |  Branch (830:9): [True: 0, False: 498]
  |  Branch (830:26): [True: 0, False: 498]
  ------------------
  831|      0|        return false;
  832|       |
  833|    498|    struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(p->imgfmt);
  834|    498|    if (!desc.id)
  ------------------
  |  Branch (834:9): [True: 0, False: 498]
  ------------------
  835|      0|        return false;
  836|       |
  837|    498|    if (p->hw_subfmt && !(desc.flags & MP_IMGFLAG_HWACCEL))
  ------------------
  |  |   70|      0|#define MP_IMGFLAG_HWACCEL      MP_IMGFLAG_TYPE_HW
  |  |  ------------------
  |  |  |  |   65|      0|#define MP_IMGFLAG_TYPE_HW      (8 << 10)
  |  |  ------------------
  ------------------
  |  Branch (837:9): [True: 0, False: 498]
  |  Branch (837:25): [True: 0, False: 0]
  ------------------
  838|      0|        return false;
  839|       |
  840|    498|    return true;
  841|    498|}
mp_image_params_equal:
  845|     60|{
  846|     60|    return p1->imgfmt == p2->imgfmt &&
  ------------------
  |  Branch (846:12): [True: 30, False: 30]
  ------------------
  847|     60|           p1->hw_subfmt == p2->hw_subfmt &&
  ------------------
  |  Branch (847:12): [True: 30, False: 0]
  ------------------
  848|     60|           p1->w == p2->w && p1->h == p2->h &&
  ------------------
  |  Branch (848:12): [True: 30, False: 0]
  |  Branch (848:30): [True: 30, False: 0]
  ------------------
  849|     60|           p1->p_w == p2->p_w && p1->p_h == p2->p_h &&
  ------------------
  |  Branch (849:12): [True: 30, False: 0]
  |  Branch (849:34): [True: 30, False: 0]
  ------------------
  850|     60|           p1->force_window == p2->force_window &&
  ------------------
  |  Branch (850:12): [True: 30, False: 0]
  ------------------
  851|     60|           pl_color_space_equal(&p1->color, &p2->color) &&
  ------------------
  |  Branch (851:12): [True: 0, False: 30]
  ------------------
  852|     60|           pl_color_repr_equal(&p1->repr, &p2->repr) &&
  ------------------
  |  Branch (852:12): [True: 0, False: 0]
  ------------------
  853|     60|           p1->light == p2->light &&
  ------------------
  |  Branch (853:12): [True: 0, False: 0]
  ------------------
  854|     60|           p1->chroma_location == p2->chroma_location &&
  ------------------
  |  Branch (854:12): [True: 0, False: 0]
  ------------------
  855|     60|           p1->vflip == p2->vflip &&
  ------------------
  |  Branch (855:12): [True: 0, False: 0]
  ------------------
  856|     60|           p1->rotate == p2->rotate &&
  ------------------
  |  Branch (856:12): [True: 0, False: 0]
  ------------------
  857|     60|           p1->stereo3d == p2->stereo3d &&
  ------------------
  |  Branch (857:12): [True: 0, False: 0]
  ------------------
  858|     60|           mp_rect_equals(&p1->crop, &p2->crop);
  ------------------
  |  Branch (858:12): [True: 0, False: 0]
  ------------------
  859|     60|}
mp_image_params_guess_csp:
  950|    198|{
  951|    198|    enum pl_color_system forced_csp = mp_image_params_get_forced_csp(params);
  952|    198|    if (forced_csp == PL_COLOR_SYSTEM_UNKNOWN) { // YUV/other
  ------------------
  |  Branch (952:9): [True: 0, False: 198]
  ------------------
  953|      0|        if (params->repr.sys != PL_COLOR_SYSTEM_BT_601 &&
  ------------------
  |  Branch (953:13): [True: 0, False: 0]
  ------------------
  954|      0|            params->repr.sys != PL_COLOR_SYSTEM_BT_709 &&
  ------------------
  |  Branch (954:13): [True: 0, False: 0]
  ------------------
  955|      0|            params->repr.sys != PL_COLOR_SYSTEM_BT_2020_NC &&
  ------------------
  |  Branch (955:13): [True: 0, False: 0]
  ------------------
  956|      0|            params->repr.sys != PL_COLOR_SYSTEM_BT_2020_C &&
  ------------------
  |  Branch (956:13): [True: 0, False: 0]
  ------------------
  957|      0|            params->repr.sys != PL_COLOR_SYSTEM_BT_2100_PQ &&
  ------------------
  |  Branch (957:13): [True: 0, False: 0]
  ------------------
  958|      0|            params->repr.sys != PL_COLOR_SYSTEM_BT_2100_HLG &&
  ------------------
  |  Branch (958:13): [True: 0, False: 0]
  ------------------
  959|      0|            params->repr.sys != PL_COLOR_SYSTEM_DOLBYVISION &&
  ------------------
  |  Branch (959:13): [True: 0, False: 0]
  ------------------
  960|      0|            params->repr.sys != PL_COLOR_SYSTEM_SMPTE_240M &&
  ------------------
  |  Branch (960:13): [True: 0, False: 0]
  ------------------
  961|      0|            params->repr.sys != PL_COLOR_SYSTEM_YCGCO)
  ------------------
  |  Branch (961:13): [True: 0, False: 0]
  ------------------
  962|      0|        {
  963|       |            // Makes no sense, so guess instead
  964|       |            // YCGCO should be separate, but libavcodec disagrees
  965|      0|            params->repr.sys = PL_COLOR_SYSTEM_UNKNOWN;
  966|      0|        }
  967|      0|        if (params->repr.sys == PL_COLOR_SYSTEM_UNKNOWN)
  ------------------
  |  Branch (967:13): [True: 0, False: 0]
  ------------------
  968|      0|            params->repr.sys = mp_csp_guess_colorspace(params->w, params->h);
  969|      0|        if (params->repr.levels == PL_COLOR_LEVELS_UNKNOWN) {
  ------------------
  |  Branch (969:13): [True: 0, False: 0]
  ------------------
  970|      0|            if (params->color.transfer == PL_COLOR_TRC_V_LOG) {
  ------------------
  |  Branch (970:17): [True: 0, False: 0]
  ------------------
  971|      0|                params->repr.levels = PL_COLOR_LEVELS_FULL;
  972|      0|            } else {
  973|      0|                params->repr.levels = infer_levels(params->imgfmt);
  974|      0|            }
  975|      0|        }
  976|      0|        if (params->color.primaries == PL_COLOR_PRIM_UNKNOWN) {
  ------------------
  |  Branch (976:13): [True: 0, False: 0]
  ------------------
  977|       |            // Guess based on the colormatrix as a first priority
  978|      0|            if (params->repr.sys == PL_COLOR_SYSTEM_BT_2020_NC ||
  ------------------
  |  Branch (978:17): [True: 0, False: 0]
  ------------------
  979|      0|                params->repr.sys == PL_COLOR_SYSTEM_BT_2020_C) {
  ------------------
  |  Branch (979:17): [True: 0, False: 0]
  ------------------
  980|      0|                params->color.primaries = PL_COLOR_PRIM_BT_2020;
  981|      0|            } else if (params->repr.sys == PL_COLOR_SYSTEM_BT_709) {
  ------------------
  |  Branch (981:24): [True: 0, False: 0]
  ------------------
  982|      0|                params->color.primaries = PL_COLOR_PRIM_BT_709;
  983|      0|            } else {
  984|       |                // Ambiguous colormatrix for BT.601, guess based on res
  985|      0|                params->color.primaries = mp_csp_guess_primaries(params->w, params->h);
  986|      0|            }
  987|      0|        }
  988|      0|        if (params->color.transfer == PL_COLOR_TRC_UNKNOWN)
  ------------------
  |  Branch (988:13): [True: 0, False: 0]
  ------------------
  989|      0|            params->color.transfer = PL_COLOR_TRC_BT_1886;
  990|    198|    } else if (forced_csp == PL_COLOR_SYSTEM_RGB) {
  ------------------
  |  Branch (990:16): [True: 198, False: 0]
  ------------------
  991|    198|        params->repr.sys = PL_COLOR_SYSTEM_RGB;
  992|    198|        params->repr.levels = PL_COLOR_LEVELS_FULL;
  993|       |
  994|       |        // The majority of RGB content is either sRGB or (rarely) some other
  995|       |        // color space which we don't even handle, like AdobeRGB or
  996|       |        // ProPhotoRGB. The only reasonable thing we can do is assume it's
  997|       |        // sRGB and hope for the best, which should usually just work out fine.
  998|       |        // Note: sRGB primaries = BT.709 primaries
  999|    198|        if (params->color.primaries == PL_COLOR_PRIM_UNKNOWN)
  ------------------
  |  Branch (999:13): [True: 198, False: 0]
  ------------------
 1000|    198|            params->color.primaries = PL_COLOR_PRIM_BT_709;
 1001|    198|        if (params->color.transfer == PL_COLOR_TRC_UNKNOWN)
  ------------------
  |  Branch (1001:13): [True: 198, False: 0]
  ------------------
 1002|    198|            params->color.transfer = PL_COLOR_TRC_SRGB;
 1003|    198|    } else if (forced_csp == PL_COLOR_SYSTEM_XYZ) {
  ------------------
  |  Branch (1003:16): [True: 0, False: 0]
  ------------------
 1004|      0|        params->repr.sys = PL_COLOR_SYSTEM_XYZ;
 1005|      0|        params->repr.levels = PL_COLOR_LEVELS_FULL;
 1006|       |        // Force gamma to ST428 as this is the only correct for DCDM X'Y'Z'
 1007|      0|        params->color.transfer = PL_COLOR_TRC_ST428;
 1008|       |        // Don't care about primaries, they shouldn't be used, or if anything
 1009|       |        // MP_CSP_PRIM_ST428 should be defined.
 1010|      0|    } else {
 1011|       |        // We have no clue.
 1012|      0|        params->repr.sys = PL_COLOR_SYSTEM_UNKNOWN;
 1013|      0|        params->repr.levels = PL_COLOR_LEVELS_UNKNOWN;
 1014|      0|        params->color.primaries = PL_COLOR_PRIM_UNKNOWN;
 1015|      0|        params->color.transfer = PL_COLOR_TRC_UNKNOWN;
 1016|      0|    }
 1017|       |
 1018|    198|    if (!params->color.hdr.max_luma) {
  ------------------
  |  Branch (1018:9): [True: 198, False: 0]
  ------------------
 1019|    198|        if (params->color.transfer == PL_COLOR_TRC_HLG) {
  ------------------
  |  Branch (1019:13): [True: 0, False: 198]
  ------------------
 1020|      0|            params->color.hdr.max_luma = 1000; // reference display
 1021|    198|        } else {
 1022|       |            // If the signal peak is unknown, we're forced to pick the TRC's
 1023|       |            // nominal range as the signal peak to prevent clipping
 1024|    198|            params->color.hdr.max_luma = pl_color_transfer_nominal_peak(params->color.transfer) * MP_REF_WHITE;
  ------------------
  |  |   74|    198|#define MP_REF_WHITE 203.0
  ------------------
 1025|    198|        }
 1026|    198|    }
 1027|       |
 1028|    198|    if (!pl_color_space_is_hdr(&params->color)) {
  ------------------
  |  Branch (1028:9): [True: 198, False: 0]
  ------------------
 1029|       |        // Some clips have leftover HDR metadata after conversion to SDR, so to
 1030|       |        // avoid blowing up the tone mapping code, strip/sanitize it
 1031|    198|        params->color.hdr = pl_hdr_metadata_empty;
 1032|    198|    }
 1033|       |
 1034|    198|    if (params->chroma_location == PL_CHROMA_UNKNOWN) {
  ------------------
  |  Branch (1034:9): [True: 198, False: 0]
  ------------------
 1035|    198|        if (params->repr.levels == PL_COLOR_LEVELS_LIMITED)
  ------------------
  |  Branch (1035:13): [True: 0, False: 198]
  ------------------
 1036|      0|            params->chroma_location = PL_CHROMA_LEFT;
 1037|    198|        if (params->repr.levels == PL_COLOR_LEVELS_FULL)
  ------------------
  |  Branch (1037:13): [True: 198, False: 0]
  ------------------
 1038|    198|            params->chroma_location = PL_CHROMA_CENTER;
 1039|    198|    }
 1040|       |
 1041|    198|    if (params->light == MP_CSP_LIGHT_AUTO) {
  ------------------
  |  Branch (1041:9): [True: 198, False: 0]
  ------------------
 1042|       |        // HLG is always scene-referred (using its own OOTF), everything else
 1043|       |        // we assume is display-referred by default.
 1044|    198|        if (params->color.transfer == PL_COLOR_TRC_HLG) {
  ------------------
  |  Branch (1044:13): [True: 0, False: 198]
  ------------------
 1045|      0|            params->light = MP_CSP_LIGHT_SCENE_HLG;
 1046|    198|        } else {
 1047|    198|            params->light = MP_CSP_LIGHT_DISPLAY;
 1048|    198|        }
 1049|    198|    }
 1050|    198|}
mp_image_pixel_ptr:
 1332|   116k|{
 1333|   116k|    mp_assert(MP_IS_ALIGNED(x, img->fmt.align_x));
  ------------------
  |  |   41|   116k|#define mp_assert assert
  ------------------
 1334|   116k|    mp_assert(MP_IS_ALIGNED(y, img->fmt.align_y));
  ------------------
  |  |   41|   116k|#define mp_assert assert
  ------------------
 1335|   116k|    return mp_image_pixel_ptr_ny(img, plane, x, y);
 1336|   116k|}
mp_image_pixel_ptr_ny:
 1342|   181k|{
 1343|   181k|    mp_assert(MP_IS_ALIGNED(x, img->fmt.align_x));
  ------------------
  |  |   41|   181k|#define mp_assert assert
  ------------------
 1344|   181k|    mp_assert(MP_IS_ALIGNED(y, 1 << img->fmt.ys[plane]));
  ------------------
  |  |   41|   181k|#define mp_assert assert
  ------------------
 1345|   181k|    return img->planes[plane] +
 1346|   181k|           img->stride[plane] * (ptrdiff_t)(y >> img->fmt.ys[plane]) +
 1347|   181k|           (x >> img->fmt.xs[plane]) * (size_t)img->fmt.bpp[plane] / 8;
 1348|   181k|}
mp_image_plane_bytes:
 1355|  24.8k|{
 1356|  24.8k|    int x1 = MP_ALIGN_UP(x0 + w, img->fmt.align_x);
  ------------------
  |  |   52|  24.8k|#define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
  ------------------
 1357|  24.8k|    x0 = MP_ALIGN_DOWN(x0, img->fmt.align_x);
  ------------------
  |  |   53|  24.8k|#define MP_ALIGN_DOWN(x, align) ((x) & ~((align) - 1))
  ------------------
 1358|  24.8k|    size_t bpp = img->fmt.bpp[plane];
 1359|  24.8k|    int xs = img->fmt.xs[plane];
 1360|  24.8k|    return (x1 >> xs) * bpp / 8 - (x0 >> xs) * bpp / 8;
 1361|  24.8k|}
mp_image.c:mp_image_layout:
   52|    498|{
   53|    498|    struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(imgfmt);
   54|       |
   55|    498|    w = MP_ALIGN_UP(w, desc.align_x);
  ------------------
  |  |   52|    498|#define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
  ------------------
   56|    498|    h = MP_ALIGN_UP(h, desc.align_y);
  ------------------
  |  |   52|    498|#define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
  ------------------
   57|       |
   58|    498|    struct mp_image_params params = {.imgfmt = imgfmt, .w = w, .h = h};
   59|       |
   60|    498|    if (!mp_image_params_valid(&params) || desc.flags & MP_IMGFLAG_HWACCEL)
  ------------------
  |  |   70|    498|#define MP_IMGFLAG_HWACCEL      MP_IMGFLAG_TYPE_HW
  |  |  ------------------
  |  |  |  |   65|    498|#define MP_IMGFLAG_TYPE_HW      (8 << 10)
  |  |  ------------------
  ------------------
  |  Branch (60:9): [True: 0, False: 498]
  |  Branch (60:44): [True: 0, False: 498]
  ------------------
   61|      0|        return -1;
   62|       |
   63|       |    // Note: for non-mod-2 4:2:0 YUV frames, we have to allocate an additional
   64|       |    //       top/right border. This is needed for correct handling of such
   65|       |    //       images in filter and VO code (e.g. vo_vdpau or vo_gpu).
   66|       |
   67|  2.49k|    for (int n = 0; n < MP_MAX_PLANES; n++) {
  ------------------
  |  |   28|  2.49k|#define MP_MAX_PLANES 4
  ------------------
  |  Branch (67:21): [True: 1.99k, False: 498]
  ------------------
   68|  1.99k|        int alloc_w = mp_chroma_div_up(w, desc.xs[n]);
   69|  1.99k|        int alloc_h = MP_ALIGN_UP(h, 32) >> desc.ys[n];
  ------------------
  |  |   52|  1.99k|#define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
  ------------------
   70|  1.99k|        int line_bytes = (alloc_w * desc.bpp[n] + 7) / 8;
   71|  1.99k|        out_stride[n] = MP_ALIGN_NPOT(line_bytes, stride_align);
  ------------------
  |  |   58|  1.99k|#define MP_ALIGN_NPOT(x, align) ((align) ? MP_DIV_UP(x, align) * (align) : (x))
  |  |  ------------------
  |  |  |  |   49|  1.99k|#define MP_DIV_UP(x, y) (((x) + (y) - 1) / (y))
  |  |  ------------------
  |  |  |  Branch (58:34): [True: 1.99k, False: 0]
  |  |  ------------------
  ------------------
   72|  1.99k|        out_plane_size[n] = out_stride[n] * alloc_h;
   73|  1.99k|    }
   74|    498|    if (desc.flags & MP_IMGFLAG_PAL)
  ------------------
  |  |   69|    498|#define MP_IMGFLAG_PAL          MP_IMGFLAG_TYPE_PAL8
  |  |  ------------------
  |  |  |  |   64|    498|#define MP_IMGFLAG_TYPE_PAL8    (4 << 10)
  |  |  ------------------
  ------------------
  |  Branch (74:9): [True: 0, False: 498]
  ------------------
   75|      0|        out_plane_size[1] = AVPALETTE_SIZE;
   76|       |
   77|    498|    int sum = 0;
   78|  2.49k|    for (int n = 0; n < MP_MAX_PLANES; n++) {
  ------------------
  |  |   28|  2.49k|#define MP_MAX_PLANES 4
  ------------------
  |  Branch (78:21): [True: 1.99k, False: 498]
  ------------------
   79|  1.99k|        out_plane_offset[n] = out_plane_size[n] ? sum : -1;
  ------------------
  |  Branch (79:31): [True: 1.09k, False: 894]
  ------------------
   80|  1.99k|        sum += out_plane_size[n];
   81|  1.99k|    }
   82|       |
   83|    498|    return sum;
   84|    498|}
mp_image.c:mp_image_fill_alloc:
  107|    249|{
  108|    249|    int stride[MP_MAX_PLANES];
  109|    249|    int plane_offset[MP_MAX_PLANES];
  110|    249|    int plane_size[MP_MAX_PLANES];
  111|    249|    int size = mp_image_layout(mpi->imgfmt, mpi->w, mpi->h, stride_align,
  112|    249|                               stride, plane_offset, plane_size);
  113|    249|    if (size < 0 || size > buffer_size)
  ------------------
  |  Branch (113:9): [True: 0, False: 249]
  |  Branch (113:21): [True: 0, False: 249]
  ------------------
  114|      0|        return false;
  115|       |
  116|    249|    int align = MP_ALIGN_UP((uintptr_t)buffer, stride_align) - (uintptr_t)buffer;
  ------------------
  |  |   52|    249|#define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
  ------------------
  117|    249|    if (buffer_size - size < align)
  ------------------
  |  Branch (117:9): [True: 0, False: 249]
  ------------------
  118|      0|        return false;
  119|    249|    uint8_t *s = buffer;
  120|    249|    s += align;
  121|       |
  122|  1.24k|    for (int n = 0; n < MP_MAX_PLANES; n++) {
  ------------------
  |  |   28|  1.24k|#define MP_MAX_PLANES 4
  ------------------
  |  Branch (122:21): [True: 996, False: 249]
  ------------------
  123|    996|        mpi->planes[n] = plane_offset[n] >= 0 ? s + plane_offset[n] : NULL;
  ------------------
  |  Branch (123:26): [True: 549, False: 447]
  ------------------
  124|    996|        mpi->stride[n] = stride[n];
  125|    996|    }
  126|       |
  127|    249|    return true;
  128|    249|}
mp_image.c:mp_image_destructor:
  211|    309|{
  212|    309|    mp_image_t *mpi = ptr;
  213|  1.54k|    for (int p = 0; p < MP_MAX_PLANES; p++)
  ------------------
  |  |   28|  1.54k|#define MP_MAX_PLANES 4
  ------------------
  |  Branch (213:21): [True: 1.23k, False: 309]
  ------------------
  214|  1.23k|        av_buffer_unref(&mpi->bufs[p]);
  215|    309|    av_buffer_unref(&mpi->hwctx);
  216|    309|    av_buffer_unref(&mpi->icc_profile);
  217|    309|    av_buffer_unref(&mpi->a53_cc);
  218|    309|    av_buffer_unref(&mpi->dovi);
  219|    309|    av_buffer_unref(&mpi->film_grain);
  220|    309|    for (int n = 0; n < mpi->num_ff_side_data; n++)
  ------------------
  |  Branch (220:21): [True: 0, False: 309]
  ------------------
  221|      0|        av_buffer_unref(&mpi->ff_side_data[n].buf);
  222|    309|    talloc_free(mpi->ff_side_data);
  ------------------
  |  |   47|    309|#define talloc_free                     ta_free
  ------------------
  223|    309|}
mp_image.c:mp_image_alloc_planes:
  167|    249|{
  168|    249|    mp_assert(!mpi->planes[0]);
  ------------------
  |  |   41|    249|#define mp_assert assert
  ------------------
  169|    249|    mp_assert(!mpi->bufs[0]);
  ------------------
  |  |   41|    249|#define mp_assert assert
  ------------------
  170|       |
  171|    249|    int align = MP_IMAGE_BYTE_ALIGN;
  ------------------
  |  |   35|    249|#define MP_IMAGE_BYTE_ALIGN 64
  ------------------
  172|       |
  173|    249|    int size = mp_image_get_alloc_size(mpi->imgfmt, mpi->w, mpi->h, align);
  174|    249|    if (size < 0)
  ------------------
  |  Branch (174:9): [True: 0, False: 249]
  ------------------
  175|      0|        return false;
  176|       |
  177|       |    // Note: mp_image_pool assumes this creates only 1 AVBufferRef.
  178|    249|    mpi->bufs[0] = av_buffer_alloc(size + align);
  179|    249|    if (!mpi->bufs[0])
  ------------------
  |  Branch (179:9): [True: 0, False: 249]
  ------------------
  180|      0|        return false;
  181|       |
  182|    249|    if (!mp_image_fill_alloc(mpi, align, mpi->bufs[0]->data, mpi->bufs[0]->size)) {
  ------------------
  |  Branch (182:9): [True: 0, False: 249]
  ------------------
  183|      0|        av_buffer_unref(&mpi->bufs[0]);
  184|      0|        return false;
  185|      0|    }
  186|       |
  187|    249|    return true;
  188|    249|}
mp_image.c:ref_buffer:
  325|    540|{
  326|    540|    if (*dst) {
  ------------------
  |  Branch (326:9): [True: 60, False: 480]
  ------------------
  327|     60|        *dst = av_buffer_ref(*dst);
  328|     60|        MP_HANDLE_OOM(*dst);
  ------------------
  |  |  176|     60|#define MP_HANDLE_OOM(x) do {   \
  |  |  177|     60|        void *oom_p_ = (x);     \
  |  |  178|     60|        if (!oom_p_)            \
  |  |  ------------------
  |  |  |  Branch (178:13): [True: 0, False: 60]
  |  |  ------------------
  |  |  179|     60|            abort();            \
  |  |  180|     60|    } while (0)
  |  |  ------------------
  |  |  |  Branch (180:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
  329|     60|    }
  330|    540|}
mp_image.c:mp_image_params_get_forced_csp:
  500|    198|{
  501|    198|    int imgfmt = params->hw_subfmt ? params->hw_subfmt : params->imgfmt;
  ------------------
  |  Branch (501:18): [True: 0, False: 198]
  ------------------
  502|    198|    enum pl_color_system csp = mp_imgfmt_get_forced_csp(imgfmt);
  503|       |
  504|    198|    if (csp == PL_COLOR_SYSTEM_RGB && params->repr.sys == PL_COLOR_SYSTEM_XYZ)
  ------------------
  |  Branch (504:9): [True: 198, False: 0]
  |  Branch (504:39): [True: 0, False: 198]
  ------------------
  505|      0|        csp = PL_COLOR_SYSTEM_XYZ;
  506|       |
  507|    198|    return csp;
  508|    198|}

mp_image_pool_make_writeable:
  232|     60|{
  233|     60|    if (mp_image_is_writeable(img))
  ------------------
  |  Branch (233:9): [True: 60, False: 0]
  ------------------
  234|     60|        return true;
  235|      0|    struct mp_image *new = mp_image_pool_new_copy(pool, img);
  236|      0|    if (!new)
  ------------------
  |  Branch (236:9): [True: 0, False: 0]
  ------------------
  237|      0|        return false;
  238|      0|    mp_image_steal_data(img, new);
  239|      0|    mp_assert(mp_image_is_writeable(img));
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  240|      0|    return true;
  241|      0|}

mp_get_src_dst_rects:
  134|     39|{
  135|     39|    int src_w = video->w;
  136|     39|    int src_h = video->h;
  137|     39|    int src_dw, src_dh;
  138|       |
  139|     39|    mp_image_params_get_dsize(video, &src_dw, &src_dh);
  140|     39|    window_w = MPMAX(1, window_w);
  ------------------
  |  |   43|     39|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 39]
  |  |  ------------------
  ------------------
  141|     39|    window_h = MPMAX(1, window_h);
  ------------------
  |  |   43|     39|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 39]
  |  |  ------------------
  ------------------
  142|       |
  143|     39|    int margin_x[2] = {0};
  144|     39|    int margin_y[2] = {0};
  145|     39|    if (opts->keepaspect) {
  ------------------
  |  Branch (145:9): [True: 39, False: 0]
  ------------------
  146|     39|        calc_margin(opts->margin_x, margin_x, window_w);
  147|     39|        calc_margin(opts->margin_y, margin_y, window_h);
  148|     39|    }
  149|       |
  150|     39|    int vid_window_w = window_w - margin_x[0] - margin_x[1];
  151|     39|    int vid_window_h = window_h - margin_y[0] - margin_y[1];
  152|       |
  153|     39|    struct mp_rect dst = {0, 0, window_w, window_h};
  154|     39|    struct mp_rect src = {0, 0, src_w,    src_h};
  155|     39|    if (mp_image_crop_valid(video))
  ------------------
  |  Branch (155:9): [True: 0, False: 39]
  ------------------
  156|      0|        src = video->crop;
  157|       |
  158|     39|    if (vo_caps & VO_CAP_ROTATE90) {
  ------------------
  |  Branch (158:9): [True: 0, False: 39]
  ------------------
  159|      0|        if (video->rotate % 180 == 90) {
  ------------------
  |  Branch (159:13): [True: 0, False: 0]
  ------------------
  160|      0|            MPSWAP(int, src_w, src_h);
  ------------------
  |  |   47|      0|    do { type SWAP_tmp = b; b = a; a = SWAP_tmp; } while (0)
  |  |  ------------------
  |  |  |  Branch (47:59): [Folded - Ignored]
  |  |  ------------------
  ------------------
  161|      0|            MPSWAP(int, src_dw, src_dh);
  ------------------
  |  |   47|      0|    do { type SWAP_tmp = b; b = a; a = SWAP_tmp; } while (0)
  |  |  ------------------
  |  |  |  Branch (47:59): [Folded - Ignored]
  |  |  ------------------
  ------------------
  162|      0|        }
  163|      0|        mp_rect_rotate(&src, src_w, src_h, video->rotate);
  164|      0|    }
  165|       |
  166|     39|    struct mp_osd_res osd = {
  167|     39|        .w = window_w,
  168|     39|        .h = window_h,
  169|     39|        .display_par = monitor_par,
  170|     39|    };
  171|       |
  172|     39|    if (opts->keepaspect) {
  ------------------
  |  Branch (172:9): [True: 39, False: 0]
  ------------------
  173|     39|        int scaled_width, scaled_height;
  174|     39|        aspect_calc_panscan(opts, src_w, src_h, src_dw, src_dh, opts->unscaled,
  175|     39|                            vid_window_w, vid_window_h, monitor_par,
  176|     39|                            &scaled_width, &scaled_height);
  177|     39|        src_dst_split_scaling(src_w, vid_window_w, scaled_width,
  178|     39|                              opts->zoom, opts->align_x, opts->pan_x, opts->scale_x,
  179|     39|                              opts->recenter,
  180|     39|                              &src.x0, &src.x1, &dst.x0, &dst.x1,
  181|     39|                              &osd.ml, &osd.mr);
  182|     39|        src_dst_split_scaling(src_h, vid_window_h, scaled_height,
  183|     39|                              opts->zoom, opts->align_y, opts->pan_y, opts->scale_y,
  184|     39|                              opts->recenter,
  185|     39|                              &src.y0, &src.y1, &dst.y0, &dst.y1,
  186|     39|                              &osd.mt, &osd.mb);
  187|     39|    }
  188|       |
  189|     39|    dst.x0 += margin_x[0];
  190|     39|    dst.y0 += margin_y[0];
  191|     39|    dst.x1 += margin_x[0];
  192|     39|    dst.y1 += margin_y[0];
  193|       |
  194|       |    // OSD really uses the full window, but was computed on the margin-cut
  195|       |    // video sub-window. Correct it to the full window.
  196|     39|    osd.ml += margin_x[0];
  197|     39|    osd.mr += margin_x[1];
  198|     39|    osd.mt += margin_y[0];
  199|     39|    osd.mb += margin_y[1];
  200|       |
  201|     39|    *out_src = src;
  202|     39|    *out_dst = dst;
  203|     39|    *out_osd = osd;
  204|       |
  205|     39|    int sw = src.x1 - src.x0, sh = src.y1 - src.y0;
  206|     39|    int dw = dst.x1 - dst.x0, dh = dst.y1 - dst.y0;
  207|       |
  208|     39|    mp_verbose(log, "Window size: %dx%d (Borders: l=%d t=%d r=%d b=%d)\n",
  ------------------
  |  |   75|     39|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  209|     39|               window_w, window_h,
  210|     39|               margin_x[0], margin_y[0], margin_x[1], margin_y[1]);
  211|     39|    mp_verbose(log, "Video source: %dx%d (%d:%d)\n",
  ------------------
  |  |   75|     39|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  212|     39|               video->w, video->h, video->p_w, video->p_h);
  213|     39|    mp_verbose(log, "Video display: (%d, %d) %dx%d -> (%d, %d) %dx%d\n",
  ------------------
  |  |   75|     39|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  214|     39|               src.x0, src.y0, sw, sh, dst.x0, dst.y0, dw, dh);
  215|     39|    mp_verbose(log, "Video scale: %f/%f\n",
  ------------------
  |  |   75|     39|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  216|     39|               (double)dw / sw, (double)dh / sh);
  217|     39|    mp_verbose(log, "OSD borders: l=%d t=%d r=%d b=%d\n",
  ------------------
  |  |   75|     39|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  218|     39|               osd.ml, osd.mt, osd.mr, osd.mb);
  219|     39|    mp_verbose(log, "Video borders: l=%d t=%d r=%d b=%d\n",
  ------------------
  |  |   75|     39|#define mp_verbose(log, ...)    mp_msg(log, MSGL_V, __VA_ARGS__)
  ------------------
  220|     39|               dst.x0, dst.y0, window_w - dst.x1, window_h - dst.y1);
  221|     39|}
aspect.c:calc_margin:
  117|     78|{
  118|     78|    out[0] = MPCLAMP((int)(opts[0] * size), 0, size);
  ------------------
  |  |   45|     78|#define MPCLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
  |  |  ------------------
  |  |  |  Branch (45:31): [True: 0, False: 78]
  |  |  |  Branch (45:56): [True: 0, False: 78]
  |  |  ------------------
  ------------------
  119|     78|    out[1] = MPCLAMP((int)(opts[1] * size), 0, size);
  ------------------
  |  |   45|     78|#define MPCLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a)))
  |  |  ------------------
  |  |  |  Branch (45:31): [True: 0, False: 78]
  |  |  |  Branch (45:56): [True: 0, False: 78]
  |  |  ------------------
  ------------------
  120|       |
  121|     78|    if (out[0] + out[1] >= size) {
  ------------------
  |  Branch (121:9): [True: 0, False: 78]
  ------------------
  122|       |        // This case is not really supported. Show an error by 1 pixel.
  123|      0|        out[0] = 0;
  124|      0|        out[1] = MPMAX(0, size - 1);
  ------------------
  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  125|      0|    }
  126|     78|}
aspect.c:aspect_calc_panscan:
   33|     39|{
   34|     39|    int fwidth = window_w;
   35|     39|    int fheight = (float)window_w / d_w * d_h / monitor_par;
   36|     39|    if (fheight > window_h || fheight < h) {
  ------------------
  |  Branch (36:9): [True: 0, False: 39]
  |  Branch (36:31): [True: 39, False: 0]
  ------------------
   37|     39|        int tmpw = (float)window_h / d_h * d_w * monitor_par;
   38|     39|        if (tmpw <= window_w) {
  ------------------
  |  Branch (38:13): [True: 0, False: 39]
  ------------------
   39|      0|            fheight = window_h;
   40|      0|            fwidth = tmpw;
   41|      0|        }
   42|     39|    }
   43|       |
   44|     39|    int vo_panscan_area = window_h - fheight;
   45|     39|    double f_w = fwidth / (double)MPMAX(fheight, 1);
  ------------------
  |  |   43|     39|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 39, False: 0]
  |  |  ------------------
  ------------------
   46|     39|    double f_h = 1;
   47|     39|    if (vo_panscan_area == 0) {
  ------------------
  |  Branch (47:9): [True: 0, False: 39]
  ------------------
   48|      0|        vo_panscan_area = window_w - fwidth;
   49|      0|        f_w = 1;
   50|      0|        f_h = fheight / (double)MPMAX(fwidth, 1);
  ------------------
  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
   51|      0|    }
   52|       |
   53|     39|    if (unscaled) {
  ------------------
  |  Branch (53:9): [True: 0, False: 39]
  ------------------
   54|      0|        vo_panscan_area = 0;
   55|      0|        if (unscaled != 2 || (d_w <= window_w && d_h <= window_h)) {
  ------------------
  |  Branch (55:13): [True: 0, False: 0]
  |  Branch (55:31): [True: 0, False: 0]
  |  Branch (55:50): [True: 0, False: 0]
  ------------------
   56|      0|            fwidth = d_w * monitor_par;
   57|      0|            fheight = d_h;
   58|      0|        }
   59|      0|    }
   60|       |
   61|     39|    *out_w = fwidth + vo_panscan_area * opts->panscan * f_w;
   62|     39|    *out_h = fheight + vo_panscan_area * opts->panscan * f_h;
   63|     39|}
aspect.c:src_dst_split_scaling:
   83|     78|{
   84|     78|    scaled_src_size *= powf(2, zoom) * scale;
   85|     78|    scaled_src_size = MPMAX(scaled_src_size, 1);
  ------------------
  |  |   43|     78|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 78, False: 0]
  |  |  ------------------
  ------------------
   86|     78|    if (recenter && dst_size >= scaled_src_size)
  ------------------
  |  Branch (86:9): [True: 0, False: 78]
  |  Branch (86:21): [True: 0, False: 0]
  ------------------
   87|      0|        align = 0;
   88|     78|    align = (align + 1) / 2;
   89|       |
   90|     78|    *dst_start = (dst_size - scaled_src_size) * align + pan * scaled_src_size;
   91|     78|    *dst_end = *dst_start + scaled_src_size;
   92|       |
   93|       |    // Distance of screen frame to video
   94|     78|    *osd_margin_a = *dst_start;
   95|     78|    *osd_margin_b = dst_size - *dst_end;
   96|       |
   97|       |    // Clip to screen
   98|     78|    int s_src = *src_end - *src_start;
   99|     78|    int s_dst = *dst_end - *dst_start;
  100|     78|    if (*dst_start < 0) {
  ------------------
  |  Branch (100:9): [True: 0, False: 78]
  ------------------
  101|      0|        int border = -(*dst_start) * s_src / s_dst;
  102|      0|        *src_start += border;
  103|      0|        *dst_start = 0;
  104|      0|    }
  105|     78|    if (*dst_end > dst_size) {
  ------------------
  |  Branch (105:9): [True: 0, False: 78]
  ------------------
  106|      0|        int border = (*dst_end - dst_size) * s_src / s_dst;
  107|      0|        *src_end -= border;
  108|      0|        *dst_end = dst_size;
  109|      0|    }
  110|       |
  111|       |    // For sanity: avoid bothering VOs with corner cases
  112|     78|    clamp_size(src_size, src_start, src_end);
  113|     78|    clamp_size(dst_size, dst_start, dst_end);
  114|     78|}
aspect.c:clamp_size:
   67|    156|{
   68|    156|    *start = MPMAX(0, *start);
  ------------------
  |  |   43|    156|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 156]
  |  |  ------------------
  ------------------
   69|    156|    *end = MPMIN(size, *end);
  ------------------
  |  |   44|    156|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 39, False: 117]
  |  |  ------------------
  ------------------
   70|    156|    if (*start >= *end) {
  ------------------
  |  Branch (70:9): [True: 0, False: 156]
  ------------------
   71|      0|        *start = 0;
   72|      0|        *end = 1;
   73|      0|    }
   74|    156|}

packer_get_bb:
   44|     38|{
   45|     38|    out_bb[0] = (struct pos) {0};
   46|     38|    out_bb[1] = (struct pos) {packer->used_width, packer->used_height};
   47|     38|}
packer_pack:
  128|     38|{
  129|     38|    if (packer->count == 0)
  ------------------
  |  Branch (129:9): [True: 0, False: 38]
  ------------------
  130|      0|        return 0;
  131|     38|    int w_orig = packer->w, h_orig = packer->h;
  132|     38|    struct pos *in = packer->in;
  133|     38|    int xmax = 0, ymax = 0;
  134|  1.57k|    for (int i = 0; i < packer->count; i++) {
  ------------------
  |  Branch (134:21): [True: 1.53k, False: 38]
  ------------------
  135|  1.53k|        if (in[i].x <= 0 || in[i].y <= 0) {
  ------------------
  |  Branch (135:13): [True: 0, False: 1.53k]
  |  Branch (135:29): [True: 0, False: 1.53k]
  ------------------
  136|      0|            in[i] = (struct pos){0, 0};
  137|  1.53k|        } else {
  138|  1.53k|            in[i].x += packer->padding * 2;
  139|  1.53k|            in[i].y += packer->padding * 2;
  140|  1.53k|        }
  141|  1.53k|        if (in[i].x < 0 || in [i].x > 65535 || in[i].y < 0 || in[i].y > 65535) {
  ------------------
  |  Branch (141:13): [True: 0, False: 1.53k]
  |  Branch (141:28): [True: 0, False: 1.53k]
  |  Branch (141:48): [True: 0, False: 1.53k]
  |  Branch (141:63): [True: 0, False: 1.53k]
  ------------------
  142|      0|            fprintf(stderr, "Invalid OSD / subtitle bitmap size\n");
  143|      0|            abort();
  144|      0|        }
  145|  1.53k|        xmax = MPMAX(xmax, in[i].x);
  ------------------
  |  |   43|  1.53k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 1.38k, False: 151]
  |  |  ------------------
  ------------------
  146|  1.53k|        ymax = MPMAX(ymax, in[i].y);
  ------------------
  |  |   43|  1.53k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 931, False: 605]
  |  |  ------------------
  ------------------
  147|  1.53k|    }
  148|     38|    if (xmax > packer->w)
  ------------------
  |  Branch (148:9): [True: 30, False: 8]
  ------------------
  149|     30|        packer->w = 1 << (mp_log2(xmax - 1) + 1);
  150|     38|    if (ymax > packer->h)
  ------------------
  |  Branch (150:9): [True: 30, False: 8]
  ------------------
  151|     30|        packer->h = 1 << (mp_log2(ymax - 1) + 1);
  152|    130|    while (1) {
  ------------------
  |  Branch (152:12): [Folded - Ignored]
  ------------------
  153|    130|        int used_width = 0;
  154|    130|        int y = pack_rectangles(in, packer->result, packer->count,
  155|    130|                                packer->w, packer->h,
  156|    130|                                packer->scratch, &used_width);
  157|    130|        if (y >= 0) {
  ------------------
  |  Branch (157:13): [True: 38, False: 92]
  ------------------
  158|     38|            packer->used_width = MPMIN(used_width, packer->w);
  ------------------
  |  |   44|     38|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 38]
  |  |  ------------------
  ------------------
  159|     38|            packer->used_height = MPMIN(y, packer->h);
  ------------------
  |  |   44|     38|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 38]
  |  |  ------------------
  ------------------
  160|     38|            mp_assert(packer->w == 0 || IS_POWER_OF_2(packer->w));
  ------------------
  |  |   41|     38|#define mp_assert assert
  ------------------
  161|     38|            mp_assert(packer->h == 0 || IS_POWER_OF_2(packer->h));
  ------------------
  |  |   41|     38|#define mp_assert assert
  ------------------
  162|     38|            if (packer->padding) {
  ------------------
  |  Branch (162:17): [True: 0, False: 38]
  ------------------
  163|      0|                for (int i = 0; i < packer->count; i++) {
  ------------------
  |  Branch (163:33): [True: 0, False: 0]
  ------------------
  164|      0|                    packer->result[i].x += packer->padding;
  165|      0|                    packer->result[i].y += packer->padding;
  166|      0|                }
  167|      0|            }
  168|     38|            return packer->w != w_orig || packer->h != h_orig;
  ------------------
  |  Branch (168:20): [True: 30, False: 8]
  |  Branch (168:43): [True: 0, False: 8]
  ------------------
  169|     38|        }
  170|     92|        int w_max = packer->w_max > 0 ? packer->w_max : INT_MAX;
  ------------------
  |  Branch (170:21): [True: 0, False: 92]
  ------------------
  171|     92|        int h_max = packer->h_max > 0 ? packer->h_max : INT_MAX;
  ------------------
  |  Branch (171:21): [True: 0, False: 92]
  ------------------
  172|     92|        if (packer->w <= packer->h && packer->w != w_max)
  ------------------
  |  Branch (172:13): [True: 47, False: 45]
  |  Branch (172:39): [True: 47, False: 0]
  ------------------
  173|     47|            packer->w = MPMIN(packer->w * 2, w_max);
  ------------------
  |  |   44|     47|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 47]
  |  |  ------------------
  ------------------
  174|     45|        else if (packer->h != h_max)
  ------------------
  |  Branch (174:18): [True: 45, False: 0]
  ------------------
  175|     45|            packer->h = MPMIN(packer->h * 2, h_max);
  ------------------
  |  |   44|     45|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 45]
  |  |  ------------------
  ------------------
  176|      0|        else {
  177|      0|            packer->w = w_orig;
  178|      0|            packer->h = h_orig;
  179|      0|            return -1;
  180|      0|        }
  181|     92|    }
  182|     38|}
packer_set_size:
  185|    134|{
  186|    134|    packer->count = size;
  187|    134|    if (size <= packer->asize)
  ------------------
  |  Branch (187:9): [True: 103, False: 31]
  ------------------
  188|    103|        return;
  189|     31|    packer->asize = MPMAX(packer->asize * 2, size);
  ------------------
  |  |   43|     31|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 1, False: 30]
  |  |  ------------------
  ------------------
  190|     31|    talloc_free(packer->result);
  ------------------
  |  |   47|     31|#define talloc_free                     ta_free
  ------------------
  191|     31|    talloc_free(packer->scratch);
  ------------------
  |  |   47|     31|#define talloc_free                     ta_free
  ------------------
  192|     31|    packer->in = talloc_realloc(packer, packer->in, struct pos, packer->asize);
  ------------------
  |  |   33|     31|#define talloc_realloc                  ta_xrealloc
  |  |  ------------------
  |  |  |  |  144|     31|    (type *)ta_xrealloc_size(ta_parent, ptr, ta_calc_array_size(sizeof(type), count))
  |  |  |  |  ------------------
  |  |  |  |  |  |  158|     31|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   43|     31|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   38|     31|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   37|     31|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  193|     31|    packer->result = talloc_array_ptrtype(packer, packer->result,
  ------------------
  |  |   36|     31|#define talloc_array_ptrtype            ta_xnew_array_ptrtype
  |  |  ------------------
  |  |  |  |  140|     31|#define ta_xnew_array_ptrtype(...)      ta_oom_g(ta_new_array_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     31|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  194|     31|                                          packer->asize);
  195|     31|    packer->scratch = talloc_array_ptrtype(packer, packer->scratch,
  ------------------
  |  |   36|     31|#define talloc_array_ptrtype            ta_xnew_array_ptrtype
  |  |  ------------------
  |  |  |  |  140|     31|#define ta_xnew_array_ptrtype(...)      ta_oom_g(ta_new_array_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     31|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  196|     31|                                           packer->asize + 16);
  197|     31|}
bitmap_packer.c:pack_rectangles:
   75|    130|{
   76|    130|    int bins[16 << HEIGHT_SORT_BITS];
   77|    130|    int sizes[16 << HEIGHT_SORT_BITS] = { 0 };
   78|  5.83k|    for (int i = 0; i < num_rects; i++)
  ------------------
  |  Branch (78:21): [True: 5.70k, False: 130]
  ------------------
   79|  5.70k|        sizes[size_index(in[i].y)]++;
   80|    130|    int idx = 0;
   81|  2.21k|    for (int i = 0; i < 16 << HEIGHT_SORT_BITS; i += 1 << HEIGHT_SORT_BITS) {
  ------------------
  |  |   49|  2.21k|#define HEIGHT_SORT_BITS 4
  ------------------
                  for (int i = 0; i < 16 << HEIGHT_SORT_BITS; i += 1 << HEIGHT_SORT_BITS) {
  ------------------
  |  |   49|  2.08k|#define HEIGHT_SORT_BITS 4
  ------------------
  |  Branch (81:21): [True: 2.08k, False: 130]
  ------------------
   82|  35.3k|        for (int j = 0; j < 1 << HEIGHT_SORT_BITS; j++) {
  ------------------
  |  |   49|  35.3k|#define HEIGHT_SORT_BITS 4
  ------------------
  |  Branch (82:25): [True: 33.2k, False: 2.08k]
  ------------------
   83|  33.2k|            bins[i + j] = idx;
   84|  33.2k|            idx += sizes[i + j];
   85|  33.2k|        }
   86|  2.08k|        scratch[idx++] = -1;
   87|  2.08k|    }
   88|  5.83k|    for (int i = 0; i < num_rects; i++)
  ------------------
  |  Branch (88:21): [True: 5.70k, False: 130]
  ------------------
   89|  5.70k|        scratch[bins[size_index(in[i].y)]++] = i;
   90|  2.21k|    for (int i = 0; i < 16; i++)
  ------------------
  |  Branch (90:21): [True: 2.08k, False: 130]
  ------------------
   91|  2.08k|        bins[i] = bins[i << HEIGHT_SORT_BITS] - sizes[i << HEIGHT_SORT_BITS];
  ------------------
  |  |   49|  2.08k|#define HEIGHT_SORT_BITS 4
  ------------------
                      bins[i] = bins[i << HEIGHT_SORT_BITS] - sizes[i << HEIGHT_SORT_BITS];
  ------------------
  |  |   49|  2.08k|#define HEIGHT_SORT_BITS 4
  ------------------
   92|    130|    struct {
   93|    130|        int size, x, bottom;
   94|    130|    } stack[16] = {{15, 0, h}}, s = {0};
   95|    130|    int stackpos = 1;
   96|    130|    int y;
   97|  1.07k|    while (stackpos) {
  ------------------
  |  Branch (97:12): [True: 947, False: 130]
  ------------------
   98|    947|        y = s.bottom;
   99|    947|        s = stack[--stackpos];
  100|    947|        s.size++;
  101|  6.31k|        while (s.size--) {
  ------------------
  |  Branch (101:16): [True: 5.36k, False: 947]
  ------------------
  102|  5.36k|            int maxy = -1;
  103|  5.36k|            int obj;
  104|  8.49k|            while ((obj = scratch[bins[s.size]]) >= 0) {
  ------------------
  |  Branch (104:20): [True: 4.52k, False: 3.97k]
  ------------------
  105|  4.52k|                int bottom = y + in[obj].y;
  106|  4.52k|                if (bottom > s.bottom)
  ------------------
  |  Branch (106:21): [True: 179, False: 4.34k]
  ------------------
  107|    179|                    break;
  108|  4.34k|                int right = s.x + in[obj].x;
  109|  4.34k|                if (right > w)
  ------------------
  |  Branch (109:21): [True: 1.21k, False: 3.13k]
  ------------------
  110|  1.21k|                    break;
  111|  3.13k|                bins[s.size]++;
  112|  3.13k|                out[obj] = (struct pos){s.x, y};
  113|  3.13k|                num_rects--;
  114|  3.13k|                if (maxy < 0)
  ------------------
  |  Branch (114:21): [True: 817, False: 2.31k]
  ------------------
  115|    817|                    stack[stackpos++] = s;
  116|  3.13k|                s.x = right;
  117|  3.13k|                maxy = MPMAX(maxy, bottom);
  ------------------
  |  |   43|  3.13k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 482, False: 2.65k]
  |  |  ------------------
  ------------------
  118|  3.13k|            }
  119|  5.36k|            *used_width = MPMAX(*used_width, s.x);
  ------------------
  |  |   43|  5.36k|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 2.77k, False: 2.58k]
  |  |  ------------------
  ------------------
  120|  5.36k|            if (maxy > 0)
  ------------------
  |  Branch (120:17): [True: 817, False: 4.54k]
  ------------------
  121|    817|                s.bottom = maxy;
  122|  5.36k|        }
  123|    947|    }
  124|    130|    return num_rects ? -1 : y;
  ------------------
  |  Branch (124:12): [True: 92, False: 38]
  ------------------
  125|    130|}
bitmap_packer.c:size_index:
   51|  11.4k|{
   52|  11.4k|    int n = mp_log2(s);
   53|  11.4k|    return (n << HEIGHT_SORT_BITS)
  ------------------
  |  |   49|  11.4k|#define HEIGHT_SORT_BITS 4
  ------------------
   54|  11.4k|       + ((- 1 - (s << HEIGHT_SORT_BITS >> n)) & ((1 << HEIGHT_SORT_BITS) - 1));
  ------------------
  |  |   49|  11.4k|#define HEIGHT_SORT_BITS 4
  ------------------
                     + ((- 1 - (s << HEIGHT_SORT_BITS >> n)) & ((1 << HEIGHT_SORT_BITS) - 1));
  ------------------
  |  |   49|  11.4k|#define HEIGHT_SORT_BITS 4
  ------------------
   55|  11.4k|}

dr_helper_create:
   42|     17|{
   43|     17|    struct dr_helper *dr = talloc_ptrtype(NULL, dr);
  ------------------
  |  |   34|     17|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|     17|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     17|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   44|     17|    talloc_set_destructor(dr, dr_helper_destroy);
  ------------------
  |  |   41|     17|#define talloc_set_destructor           ta_set_destructor
  ------------------
   45|     17|    *dr = (struct dr_helper){
   46|     17|        .dispatch = dispatch,
   47|     17|        .dr_in_flight = 0,
   48|     17|        .get_image = get_image,
   49|     17|        .get_image_ctx = get_image_ctx,
   50|     17|    };
   51|     17|    mp_mutex_init(&dr->thread_lock);
   52|     17|    return dr;
   53|     17|}
dr_helper_acquire_thread:
   56|     17|{
   57|     17|    mp_mutex_lock(&dr->thread_lock);
  ------------------
  |  |  131|     17|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
   58|     17|    mp_assert(!dr->thread_valid); // fails on API user errors
  ------------------
  |  |   41|     17|#define mp_assert assert
  ------------------
   59|     17|    dr->thread_valid = true;
   60|     17|    dr->thread_id = mp_thread_current_id();
  ------------------
  |  |  214|     17|#define mp_thread_current_id      pthread_self
  ------------------
   61|     17|    mp_mutex_unlock(&dr->thread_lock);
  ------------------
  |  |  133|     17|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
   62|     17|}
dr_helper.c:dr_helper_destroy:
   28|     17|{
   29|     17|    struct dr_helper *dr = ptr;
   30|       |
   31|       |    // All references must have been freed on destruction, or we'll have
   32|       |    // dangling pointers.
   33|     17|    mp_assert(atomic_load(&dr->dr_in_flight) == 0);
  ------------------
  |  |   41|     17|#define mp_assert assert
  ------------------
   34|       |
   35|     17|    mp_mutex_destroy(&dr->thread_lock);
  ------------------
  |  |  130|     17|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
   36|     17|}

ra_ctx_create:
  276|     25|{
  277|     25|    bool ctx_auto = !opts.context_list ||
  ------------------
  |  Branch (277:21): [True: 25, False: 0]
  ------------------
  278|     25|                    (opts.context_list[0].name &&
  ------------------
  |  Branch (278:22): [True: 0, False: 0]
  ------------------
  279|      0|                     strcmp(opts.context_list[0].name, "auto") == 0);
  ------------------
  |  Branch (279:22): [True: 0, False: 0]
  ------------------
  280|       |
  281|     25|    if (ctx_auto) {
  ------------------
  |  Branch (281:9): [True: 25, False: 0]
  ------------------
  282|     25|        MP_VERBOSE(vo, "Probing for best GPU context.\n");
  ------------------
  |  |   88|     25|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     25|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  283|     25|        opts.probing = true;
  284|     25|    }
  285|       |
  286|       |    // Hack to silence backend (X11/Wayland/etc.) errors. Kill it once backends
  287|       |    // are separate from `struct vo`
  288|     25|    bool old_probing = vo->probing;
  289|     25|    vo->probing = opts.probing;
  290|       |
  291|     25|    struct ra_ctx *ctx = NULL;
  292|     25|    if (opts.probing) {
  ------------------
  |  Branch (292:9): [True: 25, False: 0]
  ------------------
  293|     25|        struct m_obj_settings context_type_list[2] = {{.name = "auto"}, {0}};
  294|       |
  295|     25|        for (int i = 0;
  296|     50|             opts.context_type_list ? opts.context_type_list[i].name != NULL : i == 0;
  ------------------
  |  Branch (296:14): [True: 0, False: 50]
  |  Branch (296:14): [True: 25, False: 25]
  ------------------
  297|     25|             i++) {
  298|     50|            for (int j = 0; j < MP_ARRAY_SIZE(contexts); j++) {
  ------------------
  |  |   48|     50|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (298:29): [True: 25, False: 25]
  ------------------
  299|     25|                if (opts.context_type_list)
  ------------------
  |  Branch (299:21): [True: 0, False: 25]
  ------------------
  300|      0|                    context_type_list[0].name = opts.context_type_list[i].name;
  301|       |
  302|     25|                ctx = create_in_contexts(vo, contexts[j]->name, context_type_list,
  303|     25|                                         contexts, MP_ARRAY_SIZE(contexts),
  ------------------
  |  |   48|     25|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  304|     25|                                         opts);
  305|     25|                if (ctx)
  ------------------
  |  Branch (305:21): [True: 0, False: 25]
  ------------------
  306|      0|                    goto done;
  307|     25|            }
  308|     25|        }
  309|     25|    }
  310|     25|    for (int i = 0; opts.context_list && opts.context_list[i].name; i++) {
  ------------------
  |  Branch (310:21): [True: 0, False: 25]
  |  Branch (310:42): [True: 0, False: 0]
  ------------------
  311|      0|        ctx = create_in_contexts(vo, opts.context_list[i].name,
  312|      0|                                 opts.context_type_list, contexts,
  313|      0|                                 MP_ARRAY_SIZE(contexts), opts);
  ------------------
  |  |   48|      0|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  314|      0|        if (ctx)
  ------------------
  |  Branch (314:13): [True: 0, False: 0]
  ------------------
  315|      0|            goto done;
  316|      0|    }
  317|       |
  318|     25|done:
  319|     25|    if (ctx) {
  ------------------
  |  Branch (319:9): [True: 0, False: 25]
  ------------------
  320|      0|        vo->probing = old_probing;
  321|      0|        vo->context_name = ctx->fns->name;
  322|      0|        return ctx;
  323|      0|    }
  324|       |
  325|     25|    vo->probing = old_probing;
  326|       |
  327|       |    // If we've reached this point, then none of the contexts matched the name
  328|       |    // requested, or the backend creation failed for all of them.
  329|     25|    if (!vo->probing)
  ------------------
  |  Branch (329:9): [True: 1, False: 24]
  ------------------
  330|     25|        MP_ERR(vo, "Failed initializing any suitable GPU context!\n");
  ------------------
  |  |   85|      1|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      1|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  331|     25|    return NULL;
  332|     25|}
ra_ctx_destroy:
  335|     25|{
  336|     25|    struct ra_ctx *ctx = *ctx_ptr;
  337|     25|    if (!ctx)
  ------------------
  |  Branch (337:9): [True: 25, False: 0]
  ------------------
  338|     25|        return;
  339|       |
  340|      0|    if (ctx->spirv && ctx->spirv->fns->uninit)
  ------------------
  |  Branch (340:9): [True: 0, False: 0]
  |  Branch (340:23): [True: 0, False: 0]
  ------------------
  341|      0|        ctx->spirv->fns->uninit(ctx);
  342|       |
  343|      0|    ctx->fns->uninit(ctx);
  344|      0|    talloc_free(ctx);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  345|       |
  346|      0|    *ctx_ptr = NULL;
  347|      0|}
context.c:get_desc:
  147|  34.1k|{
  148|  34.1k|    if (index >= MP_ARRAY_SIZE(contexts))
  ------------------
  |  |   48|  34.1k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (148:9): [True: 17.0k, False: 17.0k]
  ------------------
  149|  17.0k|        return false;
  150|  17.0k|    const struct ra_ctx_fns *ctx = contexts[index];
  151|  17.0k|    *dst = (struct m_obj_desc) {
  152|  17.0k|        .name = ctx->name,
  153|  17.0k|        .description = ctx->description,
  154|  17.0k|    };
  155|  17.0k|    return true;
  156|  34.1k|}
context.c:check_unknown_entry:
  159|      8|{
  160|      8|    return false;
  161|      8|}
context.c:get_type_desc:
  173|  34.2k|{
  174|  34.2k|    int api_index = 0;
  175|       |
  176|  51.3k|    for (int i = 0; i < MP_ARRAY_SIZE(contexts); i++) {
  ------------------
  |  |   48|  51.3k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (176:21): [True: 34.2k, False: 17.0k]
  ------------------
  177|  34.2k|        if (i && strcmp(contexts[i - 1]->type, contexts[i]->type))
  ------------------
  |  Branch (177:13): [True: 0, False: 34.2k]
  |  Branch (177:18): [True: 0, False: 0]
  ------------------
  178|      0|            api_index++;
  179|       |
  180|  34.2k|        if (api_index == index) {
  ------------------
  |  Branch (180:13): [True: 17.1k, False: 17.0k]
  ------------------
  181|  17.1k|            *dst = (struct m_obj_desc) {
  182|  17.1k|                .name = contexts[i]->type,
  183|  17.1k|                .description = "",
  184|  17.1k|            };
  185|  17.1k|            return true;
  186|  17.1k|        }
  187|  34.2k|    }
  188|       |
  189|  17.0k|    return false;
  190|  34.2k|}
context.c:print_context_apis:
  193|      1|{
  194|      1|    mp_info(log, "Available GPU APIs and contexts:\n");
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  195|      2|    for (int n = 0; n < MP_ARRAY_SIZE(contexts); n++) {
  ------------------
  |  |   48|      2|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (195:21): [True: 1, False: 1]
  ------------------
  196|      1|        mp_info(log, "  %s %s\n", contexts[n]->type, contexts[n]->name);
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  197|      1|    }
  198|      1|}
context.c:create_in_contexts:
  229|     25|{
  230|     50|    for (int i = 0; i < size; i++) {
  ------------------
  |  Branch (230:21): [True: 25, False: 25]
  ------------------
  231|     25|        if (strcmp(name, ctxs[i]->name) != 0)
  ------------------
  |  Branch (231:13): [True: 0, False: 25]
  ------------------
  232|      0|            continue;
  233|     25|        if (context_type_list) {
  ------------------
  |  Branch (233:13): [True: 25, False: 0]
  ------------------
  234|     25|            bool found = false;
  235|     25|            for (int j = 0; context_type_list[j].name; j++) {
  ------------------
  |  Branch (235:29): [True: 25, False: 0]
  ------------------
  236|     25|                if (strcmp(context_type_list[j].name, "auto") == 0 ||
  ------------------
  |  Branch (236:21): [True: 25, False: 0]
  ------------------
  237|     25|                    strcmp(context_type_list[j].name, ctxs[i]->type) == 0) {
  ------------------
  |  Branch (237:21): [True: 0, False: 0]
  ------------------
  238|     25|                    found = true;
  239|     25|                    break;
  240|     25|                }
  241|     25|            }
  242|     25|            if (!found)
  ------------------
  |  Branch (242:17): [True: 0, False: 25]
  ------------------
  243|      0|                continue;
  244|     25|        }
  245|     25|        struct ra_ctx *ctx = talloc_ptrtype(NULL, ctx);
  ------------------
  |  |   34|     25|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|     25|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     25|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  246|     25|        *ctx = (struct ra_ctx) {
  247|     25|            .vo = vo,
  248|     25|            .global = vo->global,
  249|     25|            .log = mp_log_new(ctx, vo->log, ctxs[i]->type),
  250|     25|            .opts = opts,
  251|     25|            .fns = ctxs[i],
  252|     25|        };
  253|       |
  254|     25|        MP_VERBOSE(ctx, "Initializing GPU context '%s'\n", ctx->fns->name);
  ------------------
  |  |   88|     25|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     25|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  255|     25|        if (ctxs[i]->init(ctx))
  ------------------
  |  Branch (255:13): [True: 0, False: 25]
  ------------------
  256|      0|            return ctx;
  257|     25|        talloc_free(ctx);
  ------------------
  |  |   47|     25|#define talloc_free                     ta_free
  ------------------
  258|     25|    }
  259|     25|    return NULL;
  260|     25|}
context.c:dummy_init:
   62|     25|{
   63|     25|    return false;
   64|     25|}

mp_find_error_diffusion_kernel:
   49|    312|{
   50|    312|    if (!name)
  ------------------
  |  Branch (50:9): [True: 0, False: 312]
  ------------------
   51|      0|        return NULL;
   52|    312|    for (const struct error_diffusion_kernel *k = mp_error_diffusion_kernels;
   53|  2.34k|         k->name;
  ------------------
  |  Branch (53:10): [True: 2.21k, False: 135]
  ------------------
   54|  2.21k|         k++) {
   55|  2.21k|        if (strcmp(k->name, name) == 0)
  ------------------
  |  Branch (55:13): [True: 177, False: 2.03k]
  ------------------
   56|    177|            return k;
   57|  2.21k|    }
   58|    135|    return NULL;
   59|    312|}

ra_hwdec_validate_opt:
  215|    334|{
  216|    334|    return ra_hwdec_validate_opt_full(log, true, opt, name, value);
  217|    334|}
ra_hwdec_validate_drivers_only_opt:
  222|     71|{
  223|     71|    return ra_hwdec_validate_opt_full(log, false, opt, name, value);
  224|     71|}
hwdec.c:ra_hwdec_validate_opt_full:
  182|    405|{
  183|    405|    struct bstr param = bstr0(*value);
  184|    405|    bool help = bstr_equals0(param, "help");
  185|    405|    if (help)
  ------------------
  |  Branch (185:9): [True: 2, False: 403]
  ------------------
  186|      2|        mp_info(log, "Available hwdecs:\n");
  ------------------
  |  |   74|      2|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  187|    405|    for (int n = 0; ra_hwdec_drivers[n]; n++) {
  ------------------
  |  Branch (187:21): [True: 0, False: 405]
  ------------------
  188|      0|        const struct ra_hwdec_driver *drv = ra_hwdec_drivers[n];
  189|      0|        if (help) {
  ------------------
  |  Branch (189:13): [True: 0, False: 0]
  ------------------
  190|      0|            mp_info(log, "    %s\n", drv->name);
  ------------------
  |  |   74|      0|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  191|      0|        } else if (bstr_equals0(param, drv->name)) {
  ------------------
  |  Branch (191:20): [True: 0, False: 0]
  ------------------
  192|      0|            return 1;
  193|      0|        }
  194|      0|    }
  195|    405|    if (help) {
  ------------------
  |  Branch (195:9): [True: 2, False: 403]
  ------------------
  196|      2|        if (include_modes) {
  ------------------
  |  Branch (196:13): [True: 1, False: 1]
  ------------------
  197|      1|            mp_info(log, "    auto (behavior depends on context)\n"
  ------------------
  |  |   74|      1|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
  198|      1|                        "    all (load all hwdecs)\n"
  199|      1|                        "    no (do not load any and block loading on demand)\n");
  200|      1|        }
  201|      2|        return M_OPT_EXIT;
  ------------------
  |  |  533|      2|#define M_OPT_EXIT              -6
  ------------------
  202|      2|    }
  203|    403|    if (!param.len)
  ------------------
  |  Branch (203:9): [True: 133, False: 270]
  ------------------
  204|    133|        return 1; // "" is treated specially
  205|    270|    if (include_modes &&
  ------------------
  |  Branch (205:9): [True: 267, False: 3]
  ------------------
  206|    270|       (bstr_equals0(param, "all") || bstr_equals0(param, "auto") ||
  ------------------
  |  Branch (206:9): [True: 68, False: 199]
  |  Branch (206:39): [True: 69, False: 130]
  ------------------
  207|    267|        bstr_equals0(param, "no")))
  ------------------
  |  Branch (207:9): [True: 79, False: 51]
  ------------------
  208|    216|        return 1;
  209|     54|    mp_fatal(log, "No hwdec backend named '%.*s' found!\n", BSTR_P(param));
  ------------------
  |  |   71|    108|#define mp_fatal(log, ...)      mp_msg(log, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  Branch (71:57): [True: 54, False: 0]
  |  |  ------------------
  ------------------
  210|     54|    return M_OPT_INVALID;
  ------------------
  |  |  523|     54|#define M_OPT_INVALID           -3
  ------------------
  211|    270|}

lcms.c:validate_3dlut_size_opt:
  503|     35|{
  504|     35|    int p1, p2, p3;
  505|     35|    return gl_parse_3dlut_size(*value, &p1, &p2, &p3) ? 0 : M_OPT_INVALID;
  ------------------
  |  |  523|     22|#define M_OPT_INVALID           -3
  ------------------
  |  Branch (505:12): [True: 13, False: 22]
  ------------------
  506|     35|}

lcms.c:gl_parse_3dlut_size:
   46|     35|{
   47|     35|    if (!arg)
  ------------------
  |  Branch (47:9): [True: 0, False: 35]
  ------------------
   48|      0|        return false;
   49|     35|    if (!strcmp(arg, "auto")) {
  ------------------
  |  Branch (49:9): [True: 13, False: 22]
  ------------------
   50|     13|        *p1 = *p2 = *p3 = 0;
   51|     13|        return true;
   52|     13|    }
   53|     22|    if (sscanf(arg, "%dx%dx%d", p1, p2, p3) != 3)
  ------------------
  |  Branch (53:9): [True: 22, False: 0]
  ------------------
   54|     22|        return false;
   55|      0|    for (int n = 0; n < 3; n++) {
  ------------------
  |  Branch (55:21): [True: 0, False: 0]
  ------------------
   56|      0|        int s = ((int[]) { *p1, *p2, *p3 })[n];
   57|      0|        if (s < 2 || s > 512)
  ------------------
  |  Branch (57:13): [True: 0, False: 0]
  |  Branch (57:22): [True: 0, False: 0]
  ------------------
   58|      0|            return false;
   59|      0|    }
   60|      0|    return true;
   61|      0|}

gl_video_uninit:
 4060|     17|{
 4061|     17|    if (!p)
  ------------------
  |  Branch (4061:9): [True: 17, False: 0]
  ------------------
 4062|     17|        return;
 4063|       |
 4064|      0|    uninit_video(p);
 4065|      0|    ra_hwdec_ctx_uninit(&p->hwdec_ctx);
 4066|      0|    gl_sc_destroy(p->sc);
 4067|       |
 4068|      0|    ra_tex_free(p->ra, &p->lut_3d_texture);
 4069|      0|    ra_buf_free(p->ra, &p->hdr_peak_ssbo);
 4070|       |
 4071|      0|    timer_pool_destroy(p->upload_timer);
 4072|      0|    timer_pool_destroy(p->blit_timer);
 4073|      0|    timer_pool_destroy(p->osd_timer);
 4074|       |
 4075|      0|    for (int i = 0; i < VO_PASS_PERF_MAX; i++) {
  ------------------
  |  |  172|      0|#define VO_PASS_PERF_MAX 64
  ------------------
  |  Branch (4075:21): [True: 0, False: 0]
  ------------------
 4076|      0|        talloc_free(p->pass_fresh[i].desc.start);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 4077|      0|        talloc_free(p->pass_redraw[i].desc.start);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 4078|      0|    }
 4079|       |
 4080|      0|    mpgl_osd_destroy(p->osd);
 4081|       |
 4082|       |    // Forcibly destroy possibly remaining image references. This should also
 4083|       |    // cause gl_video_dr_free_buffer() to be called for the remaining buffers.
 4084|      0|    gc_pending_dr_fences(p, true);
 4085|       |
 4086|       |    // Should all have been unreffed already.
 4087|      0|    mp_assert(!p->num_dr_buffers);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
 4088|       |
 4089|      0|    talloc_free(p);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 4090|      0|}
video.c:validate_error_diffusion_opt:
 4259|    313|{
 4260|    313|    struct bstr param = bstr0(*value);
 4261|    313|    char s[32] = {0};
 4262|    313|    int r = 1;
 4263|    313|    if (bstr_equals0(param, "help")) {
  ------------------
  |  Branch (4263:9): [True: 1, False: 312]
  ------------------
 4264|      1|        r = M_OPT_EXIT;
  ------------------
  |  |  533|      1|#define M_OPT_EXIT              -6
  ------------------
 4265|    312|    } else {
 4266|    312|        snprintf(s, sizeof(s), "%.*s", BSTR_P(param));
  ------------------
  |  |  283|    312|#define BSTR_P(bstr) (int)((bstr).len), ((bstr).start ? (char*)(bstr).start : "")
  |  |  ------------------
  |  |  |  Branch (283:42): [True: 312, False: 0]
  |  |  ------------------
  ------------------
 4267|    312|        const struct error_diffusion_kernel *k = mp_find_error_diffusion_kernel(s);
 4268|    312|        if (!k)
  ------------------
  |  Branch (4268:13): [True: 135, False: 177]
  ------------------
 4269|    135|            r = M_OPT_INVALID;
  ------------------
  |  |  523|    135|#define M_OPT_INVALID           -3
  ------------------
 4270|    312|    }
 4271|    313|    if (r < 1) {
  ------------------
  |  Branch (4271:9): [True: 136, False: 177]
  ------------------
 4272|    136|        mp_info(log, "Available error diffusion kernels:\n");
  ------------------
  |  |   74|    136|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 4273|  1.49k|        for (int n = 0; mp_error_diffusion_kernels[n].name; n++)
  ------------------
  |  Branch (4273:25): [True: 1.36k, False: 136]
  ------------------
 4274|  1.36k|            mp_info(log, "    %s\n", mp_error_diffusion_kernels[n].name);
  ------------------
  |  |   74|  1.36k|#define mp_info(log, ...)       mp_msg(log, MSGL_INFO, __VA_ARGS__)
  ------------------
 4275|    136|        if (s[0])
  ------------------
  |  Branch (4275:13): [True: 134, False: 2]
  ------------------
 4276|    134|            mp_fatal(log, "No error diffusion kernel named '%s' found!\n", s);
  ------------------
  |  |   71|    134|#define mp_fatal(log, ...)      mp_msg(log, MSGL_FATAL, __VA_ARGS__)
  ------------------
 4277|    136|    }
 4278|    313|    return r;
 4279|    313|}

gpu_ctx_create:
  111|      8|{
  112|      8|    struct gpu_ctx *ctx = talloc_zero(NULL, struct gpu_ctx);
  ------------------
  |  |   27|      8|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|      8|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      8|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  113|      8|    ctx->log = vo->log;
  114|      8|    ctx->ra_ctx = ra_ctx_create(vo, *ctx_opts);
  115|      8|    if (!ctx->ra_ctx)
  ------------------
  |  Branch (115:9): [True: 8, False: 0]
  ------------------
  116|      8|        goto err_out;
  117|       |
  118|       |#if HAVE_VULKAN
  119|       |    struct mpvk_ctx *vkctx = ra_vk_ctx_get(ctx->ra_ctx);
  120|       |    if (vkctx) {
  121|       |        ctx->pllog = vkctx->pllog;
  122|       |        ctx->gpu = vkctx->gpu;
  123|       |        ctx->swapchain = vkctx->swapchain;
  124|       |        return ctx;
  125|       |    }
  126|       |#endif
  127|       |
  128|      0|    ctx->pllog = mppl_log_create(ctx, ctx->log);
  129|      0|    if (!ctx->pllog)
  ------------------
  |  Branch (129:9): [True: 0, False: 0]
  ------------------
  130|      0|        goto err_out;
  131|       |
  132|      0|    mppl_log_set_probing(ctx->pllog, vo->probing);
  133|       |
  134|       |#if HAVE_D3D11
  135|       |    if (ra_is_d3d11(ctx->ra_ctx->ra)) {
  136|       |        if (!d3d11_pl_init(vo, ctx, ctx_opts))
  137|       |            goto err_out;
  138|       |
  139|       |        return ctx;
  140|       |    }
  141|       |#endif
  142|       |
  143|      0|#if HAVE_GL && defined(PL_HAVE_OPENGL)
  144|      0|    if (ra_is_gl(ctx->ra_ctx->ra)) {
  ------------------
  |  Branch (144:9): [True: 0, False: 0]
  ------------------
  145|      0|        struct GL *gl = ra_gl_get(ctx->ra_ctx->ra);
  146|      0|        struct pl_opengl_params params = *pl_opengl_params(
  ------------------
  |  |  101|      0|#define pl_opengl_params(...) (&(struct pl_opengl_params) { __VA_ARGS__ })
  ------------------
  147|      0|            .debug = ctx_opts->debug,
  148|      0|            .allow_software = ctx_opts->allow_sw,
  149|      0|            .get_proc_addr_ex = (void *) gl->get_fn,
  150|      0|            .proc_ctx = gl->fn_ctx,
  151|      0|        );
  152|       |# if HAVE_EGL
  153|       |        params.egl_display = eglGetCurrentDisplay();
  154|       |        params.egl_context = eglGetCurrentContext();
  155|       |# endif
  156|      0|        pl_opengl opengl = pl_opengl_create(ctx->pllog, &params);
  157|      0|        if (!opengl)
  ------------------
  |  Branch (157:13): [True: 0, False: 0]
  ------------------
  158|      0|            goto err_out;
  159|      0|        ctx->gpu = opengl->gpu;
  160|       |
  161|      0|        mppl_log_set_probing(ctx->pllog, false);
  162|       |
  163|      0|        ctx->swapchain = pl_opengl_create_swapchain(opengl, pl_opengl_swapchain_params(
  ------------------
  |  |  157|      0|#define pl_opengl_swapchain_params(...) (&(struct pl_opengl_swapchain_params) { __VA_ARGS__ })
  ------------------
  164|      0|            .max_swapchain_depth = vo->opts->swapchain_depth,
  165|      0|            .framebuffer.flipped = gl->flipped,
  166|      0|        ));
  167|      0|        if (!ctx->swapchain)
  ------------------
  |  Branch (167:13): [True: 0, False: 0]
  ------------------
  168|      0|            goto err_out;
  169|       |
  170|      0|        return ctx;
  171|      0|    }
  172|       |#elif HAVE_GL
  173|       |    if (ra_is_gl(ctx->ra_ctx->ra)) {
  174|       |        MP_MSG(ctx, vo->probing ? MSGL_V : MSGL_ERR,
  175|       |            "libplacebo was built without OpenGL support.\n");
  176|       |    }
  177|       |#endif
  178|       |
  179|      8|err_out:
  180|      8|    gpu_ctx_destroy(&ctx);
  181|      8|    return NULL;
  182|      0|}
gpu_ctx_destroy:
  196|     16|{
  197|     16|    struct gpu_ctx *ctx = *ctxp;
  198|     16|    if (!ctx)
  ------------------
  |  Branch (198:9): [True: 8, False: 8]
  ------------------
  199|      8|        return;
  200|      8|    if (!ctx->ra_ctx)
  ------------------
  |  Branch (200:9): [True: 8, False: 0]
  ------------------
  201|      8|        goto skip_common_pl_cleanup;
  202|       |
  203|       |#if HAVE_VULKAN
  204|       |    if (ra_vk_ctx_get(ctx->ra_ctx))
  205|       |        // vulkan RA context handles pl cleanup by itself,
  206|       |        // skip common local clean-up.
  207|       |        goto skip_common_pl_cleanup;
  208|       |#endif
  209|       |
  210|      0|    if (ctx->swapchain)
  ------------------
  |  Branch (210:9): [True: 0, False: 0]
  ------------------
  211|      0|        pl_swapchain_destroy(&ctx->swapchain);
  212|       |
  213|      0|    if (ctx->gpu) {
  ------------------
  |  Branch (213:9): [True: 0, False: 0]
  ------------------
  214|      0|#if HAVE_GL && defined(PL_HAVE_OPENGL)
  215|      0|        if (ra_is_gl(ctx->ra_ctx->ra)) {
  ------------------
  |  Branch (215:13): [True: 0, False: 0]
  ------------------
  216|      0|            pl_opengl opengl = pl_opengl_get(ctx->gpu);
  217|      0|            pl_opengl_destroy(&opengl);
  218|      0|        }
  219|      0|#endif
  220|       |
  221|       |#if HAVE_D3D11 && defined(PL_HAVE_D3D11)
  222|       |        if (ra_is_d3d11(ctx->ra_ctx->ra)) {
  223|       |            pl_d3d11 d3d11 = pl_d3d11_get(ctx->gpu);
  224|       |            pl_d3d11_destroy(&d3d11);
  225|       |        }
  226|       |#endif
  227|      0|    }
  228|       |
  229|      0|    if (ctx->pllog)
  ------------------
  |  Branch (229:9): [True: 0, False: 0]
  ------------------
  230|      0|        pl_log_destroy(&ctx->pllog);
  231|       |
  232|      8|skip_common_pl_cleanup:
  233|      8|    ra_ctx_destroy(&ctx->ra_ctx);
  234|       |
  235|      8|    talloc_free(ctx);
  ------------------
  |  |   47|      8|#define talloc_free                     ta_free
  ------------------
  236|      8|    *ctxp = NULL;
  237|      8|}

init_best_video_out:
  335|     45|{
  336|     45|    struct mp_vo_opts *opts = mp_get_config_group(NULL, global, &vo_sub_opts);
  337|     45|    struct m_obj_settings *vo_list = opts->video_driver_list;
  338|     45|    struct vo *vo = NULL;
  339|       |    // first try the preferred drivers, with their optional subdevice param:
  340|     45|    if (vo_list && vo_list[0].name) {
  ------------------
  |  Branch (340:9): [True: 43, False: 2]
  |  Branch (340:20): [True: 43, False: 0]
  ------------------
  341|    102|        for (int n = 0; vo_list[n].name; n++) {
  ------------------
  |  Branch (341:25): [True: 98, False: 4]
  ------------------
  342|       |            // Something like "-vo name," allows fallback to autoprobing.
  343|     98|            if (strlen(vo_list[n].name) == 0)
  ------------------
  |  Branch (343:17): [True: 0, False: 98]
  ------------------
  344|      0|                goto autoprobe;
  345|     98|            bool p = !!vo_list[n + 1].name;
  346|     98|            vo = vo_create(p, global, ex, vo_list[n].name);
  347|     98|            if (vo)
  ------------------
  |  Branch (347:17): [True: 39, False: 59]
  ------------------
  348|     39|                goto done;
  349|     98|        }
  350|      4|        goto done;
  351|     43|    }
  352|      2|autoprobe:
  353|       |    // now try the rest...
  354|      8|    for (int i = 0; i < MP_ARRAY_SIZE(video_out_drivers); i++) {
  ------------------
  |  |   48|      8|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (354:21): [True: 8, False: 0]
  ------------------
  355|      8|        const struct vo_driver *driver = video_out_drivers[i];
  356|      8|        if (driver == &video_out_null)
  ------------------
  |  Branch (356:13): [True: 2, False: 6]
  ------------------
  357|      2|            break;
  358|      6|        vo = vo_create(true, global, ex, (char *)driver->name);
  359|      6|        if (vo)
  ------------------
  |  Branch (359:13): [True: 0, False: 6]
  ------------------
  360|      0|            goto done;
  361|      6|    }
  362|     45|done:
  363|     45|    talloc_free(opts);
  ------------------
  |  |   47|     45|#define talloc_free                     ta_free
  ------------------
  364|     45|    return vo;
  365|      2|}
vo_destroy:
  375|     39|{
  376|     39|    struct vo_internal *in = vo->in;
  377|     39|    mp_dispatch_run(in->dispatch, terminate_vo, vo);
  378|     39|    mp_thread_join(vo->in->thread);
  ------------------
  |  |  212|     39|#define mp_thread_join(t)         pthread_join(t, NULL)
  ------------------
  379|     39|    dealloc_vo(vo);
  380|     39|}
vo_reconfig:
  640|     39|{
  641|     39|    int ret;
  642|     39|    struct mp_image dummy = {0};
  643|     39|    mp_image_set_params(&dummy, params);
  644|     39|    void *p[] = {vo, &dummy, &ret};
  645|     39|    mp_dispatch_run(vo->in->dispatch, run_reconfig, p);
  646|     39|    return ret;
  647|     39|}
vo_control:
  670|    100|{
  671|    100|    int ret;
  672|    100|    void *p[] = {vo, (void *)(intptr_t)request, data, &ret};
  673|    100|    mp_dispatch_run(vo->in->dispatch, run_control, p);
  674|    100|    return ret;
  675|    100|}
vo_control_async:
  680|     39|{
  681|     39|    void *p[4] = {vo, (void *)(intptr_t)request, NULL, NULL};
  682|     39|    void **d = talloc_memdup(NULL, p, sizeof(p));
  ------------------
  |  |   49|     39|#define talloc_memdup                   ta_xmemdup
  |  |  ------------------
  |  |  |  |  157|     39|#define ta_xmemdup(...)         ta_dbg_set_loc(ta_xmemdup(__VA_ARGS__), TA_LOC)
  |  |  |  |  ------------------
  |  |  |  |  |  |   43|     39|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   38|     39|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   37|     39|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  683|       |
  684|     39|    switch (request) {
  685|      0|    case VOCTRL_UPDATE_PLAYBACK_STATE:
  ------------------
  |  Branch (685:5): [True: 0, False: 39]
  ------------------
  686|      0|        d[2] = talloc_dup(d, (struct voctrl_playback_state *)data);
  ------------------
  |  |   48|      0|#define talloc_dup                      ta_xdup
  |  |  ------------------
  |  |  |  |  141|      0|#define ta_xdup(...)                    ta_oom_g(ta_dup(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  687|      0|        break;
  688|      0|    case VOCTRL_KILL_SCREENSAVER:
  ------------------
  |  Branch (688:5): [True: 0, False: 39]
  ------------------
  689|     39|    case VOCTRL_RESTORE_SCREENSAVER:
  ------------------
  |  Branch (689:5): [True: 39, False: 0]
  ------------------
  690|     39|        break;
  691|      0|    default:
  ------------------
  |  Branch (691:5): [True: 0, False: 39]
  ------------------
  692|      0|        abort(); // requires explicit support
  693|     39|    }
  694|       |
  695|     39|    mp_dispatch_enqueue_autofree(vo->in->dispatch, run_control, d);
  696|     39|}
vo_wait_default:
  720|    293|{
  721|    293|    struct vo_internal *in = vo->in;
  722|       |
  723|    293|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|    293|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  724|    293|    if (!in->need_wakeup)
  ------------------
  |  Branch (724:9): [True: 215, False: 78]
  ------------------
  725|    215|        mp_cond_timedwait_until(&in->wakeup, &in->lock, until_time);
  726|    293|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|    293|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  727|    293|}
vo_wakeup:
  757|    256|{
  758|    256|    struct vo_internal *in = vo->in;
  759|       |
  760|    256|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|    256|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  761|    256|    wakeup_locked(vo);
  762|    256|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|    256|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  763|    256|}
vo_set_paused:
 1225|     39|{
 1226|     39|    struct vo_internal *in = vo->in;
 1227|     39|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|     39|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1228|     39|    if (in->paused != paused) {
  ------------------
  |  Branch (1228:9): [True: 39, False: 0]
  ------------------
 1229|     39|        in->paused = paused;
 1230|     39|        if (in->paused && in->dropped_frame) {
  ------------------
  |  Branch (1230:13): [True: 39, False: 0]
  |  Branch (1230:27): [True: 0, False: 39]
  ------------------
 1231|      0|            in->request_redraw = true;
 1232|      0|            wakeup_core(vo);
 1233|      0|        }
 1234|     39|        reset_vsync_timings(vo);
 1235|     39|        wakeup_locked(vo);
 1236|     39|    }
 1237|     39|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|     39|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1238|     39|}
vo_redraw:
 1257|     78|{
 1258|     78|    struct vo_internal *in = vo->in;
 1259|     78|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|     78|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1260|     78|    if (!in->request_redraw) {
  ------------------
  |  Branch (1260:9): [True: 78, False: 0]
  ------------------
 1261|     78|        in->request_redraw = true;
 1262|     78|        in->want_redraw = false;
 1263|     78|        wakeup_locked(vo);
 1264|     78|    }
 1265|     78|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|     78|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1266|     78|}
vo_query_formats:
 1306|     39|{
 1307|     39|    void *p[] = {vo, list};
 1308|     39|    mp_dispatch_run(vo->in->dispatch, run_query_format, p);
 1309|     39|}
vo_get_src_dst_rects:
 1319|     39|{
 1320|     39|    if (!vo->params) {
  ------------------
  |  Branch (1320:9): [True: 0, False: 39]
  ------------------
 1321|      0|        *out_src = *out_dst = (struct mp_rect){0};
 1322|      0|        *out_osd = (struct mp_osd_res){0};
 1323|      0|        return;
 1324|      0|    }
 1325|     39|    mp_get_src_dst_rects(vo->log, vo->opts, vo->driver->caps, vo->params,
 1326|     39|                         vo->dwidth, vo->dheight, vo->monitor_par,
 1327|     39|                         out_src, out_dst, out_osd);
 1328|     39|}
vo_event:
 1423|     39|{
 1424|     39|    struct vo_internal *in = vo->in;
 1425|     39|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|     39|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1426|     39|    if ((in->queued_events & event & VO_EVENTS_USER) != (event & VO_EVENTS_USER))
  ------------------
  |  Branch (1426:9): [True: 39, False: 0]
  ------------------
 1427|     39|        wakeup_core(vo);
 1428|     39|    if (event)
  ------------------
  |  Branch (1428:9): [True: 39, False: 0]
  ------------------
 1429|     39|        wakeup_locked(vo);
 1430|     39|    in->queued_events |= event;
 1431|     39|    in->internal_events |= event;
 1432|     39|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|     39|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1433|     39|}
vo_query_and_reset_events:
 1438|     39|{
 1439|     39|    struct vo_internal *in = vo->in;
 1440|     39|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|     39|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1441|     39|    int r = in->queued_events & events;
 1442|     39|    in->queued_events &= ~(unsigned)r;
 1443|     39|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|     39|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1444|     39|    return r;
 1445|     39|}
vo_frame_ref:
 1488|     78|{
 1489|     78|    if (!frame)
  ------------------
  |  Branch (1489:9): [True: 78, False: 0]
  ------------------
 1490|     78|        return NULL;
 1491|       |
 1492|      0|    struct vo_frame *new = talloc_ptrtype(NULL, new);
  ------------------
  |  |   34|      0|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|      0|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1493|      0|    talloc_set_destructor(new, destroy_frame);
  ------------------
  |  |   41|      0|#define talloc_set_destructor           ta_set_destructor
  ------------------
 1494|      0|    *new = *frame;
 1495|      0|    for (int n = 0; n < frame->num_frames; n++)
  ------------------
  |  Branch (1495:21): [True: 0, False: 0]
  ------------------
 1496|      0|        new->frames[n] = mp_image_new_ref(frame->frames[n]);
 1497|      0|    new->current = new->num_frames ? new->frames[0] : NULL;
  ------------------
  |  Branch (1497:20): [True: 0, False: 0]
  ------------------
 1498|      0|    return new;
 1499|     78|}
vo.c:get_desc:
  187|   600k|{
  188|   600k|    if (index >= MP_ARRAY_SIZE(video_out_drivers))
  ------------------
  |  |   48|   600k|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (188:9): [True: 49.6k, False: 551k]
  ------------------
  189|  49.6k|        return false;
  190|   551k|    const struct vo_driver *vo = video_out_drivers[index];
  191|   551k|    *dst = (struct m_obj_desc) {
  192|   551k|        .name = vo->name,
  193|   551k|        .description = vo->description,
  194|   551k|        .priv_size = vo->priv_size,
  195|   551k|        .priv_defaults = vo->priv_defaults,
  196|   551k|        .options = vo->options,
  197|   551k|        .options_prefix = vo->options_prefix,
  198|   551k|        .global_opts = vo->global_opts,
  199|   551k|        .hidden = vo->encode,
  200|   551k|        .p = vo,
  201|   551k|    };
  202|   551k|    return true;
  203|   600k|}
vo.c:vo_create:
  270|    104|{
  271|    104|    mp_assert(ex->wakeup_cb);
  ------------------
  |  |   41|    104|#define mp_assert assert
  ------------------
  272|       |
  273|    104|    struct mp_log *log = mp_log_new(NULL, global->log, "vo");
  274|    104|    struct m_obj_desc desc;
  275|    104|    if (!m_obj_list_find(&desc, &vo_obj_list, bstr0(name))) {
  ------------------
  |  Branch (275:9): [True: 28, False: 76]
  ------------------
  276|     28|        mp_msg(log, MSGL_ERR, "Video output %s not found!\n", name);
  277|     28|        talloc_free(log);
  ------------------
  |  |   47|     28|#define talloc_free                     ta_free
  ------------------
  278|     28|        return NULL;
  279|     76|    };
  280|     76|    struct vo *vo = talloc_ptrtype(NULL, vo);
  ------------------
  |  |   34|     76|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|     76|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     76|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  281|     76|    *vo = (struct vo) {
  282|     76|        .log = mp_log_new(vo, log, name),
  283|     76|        .driver = desc.p,
  284|     76|        .global = global,
  285|     76|        .encode_lavc_ctx = ex->encode_lavc_ctx,
  286|     76|        .input_ctx = ex->input_ctx,
  287|     76|        .osd = ex->osd,
  288|     76|        .monitor_par = 1,
  289|     76|        .extra = *ex,
  290|     76|        .probing = probing,
  291|     76|        .in = talloc(vo, struct vo_internal),
  ------------------
  |  |   26|     76|#define talloc                          ta_xnew
  |  |  ------------------
  |  |  |  |  133|     76|#define ta_xnew(...)                    ta_oom_g(ta_new(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     76|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  292|     76|    };
  293|     76|    mp_mutex_init(&vo->params_mutex);
  294|     76|    talloc_steal(vo, log);
  ------------------
  |  |   38|     76|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|     76|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
  295|     76|    *vo->in = (struct vo_internal) {
  296|     76|        .dispatch = mp_dispatch_create(vo),
  297|     76|        .req_frames = 1,
  298|     76|        .estimated_vsync_jitter = -1,
  299|     76|        .stats = stats_ctx_create(vo, global, "vo"),
  300|     76|    };
  301|     76|    mp_dispatch_set_wakeup_fn(vo->in->dispatch, dispatch_wakeup_cb, vo);
  302|     76|    mp_mutex_init(&vo->in->lock);
  303|     76|    mp_cond_init(&vo->in->wakeup);
  304|       |
  305|     76|    vo->opts_cache = m_config_cache_alloc(NULL, global, &vo_sub_opts);
  306|     76|    vo->opts = vo->opts_cache->opts;
  307|       |
  308|     76|    m_config_cache_set_dispatch_change_cb(vo->opts_cache, vo->in->dispatch,
  309|     76|                                          update_opts, vo);
  310|       |
  311|     76|    vo->gl_opts_cache = m_config_cache_alloc(NULL, global, &gl_video_conf);
  312|     76|    vo->eq_opts_cache = m_config_cache_alloc(NULL, global, &mp_csp_equalizer_conf);
  313|       |
  314|     76|    mp_input_set_mouse_transform(vo->input_ctx, NULL, NULL);
  315|     76|    if (vo->driver->encode != !!vo->encode_lavc_ctx)
  ------------------
  |  Branch (315:9): [True: 0, False: 76]
  ------------------
  316|      0|        goto error;
  317|     76|    vo->priv = m_config_group_from_desc(vo, vo->log, global, &desc, name);
  318|     76|    if (!vo->priv)
  ------------------
  |  Branch (318:9): [True: 0, False: 76]
  ------------------
  319|      0|        goto error;
  320|       |
  321|     76|    if (mp_thread_create(&vo->in->thread, vo_thread, vo))
  ------------------
  |  |  211|     76|#define mp_thread_create(t, f, a) pthread_create(t, NULL, f, a)
  |  |  ------------------
  |  |  |  Branch (211:35): [True: 0, False: 76]
  |  |  ------------------
  ------------------
  322|      0|        goto error;
  323|     76|    if (mp_rendezvous(vo, 0) < 0) { // init barrier
  ------------------
  |  Branch (323:9): [True: 37, False: 39]
  ------------------
  324|     37|        mp_thread_join(vo->in->thread);
  ------------------
  |  |  212|     37|#define mp_thread_join(t)         pthread_join(t, NULL)
  ------------------
  325|     37|        goto error;
  326|     37|    }
  327|     39|    return vo;
  328|       |
  329|     37|error:
  330|     37|    dealloc_vo(vo);
  331|     37|    return NULL;
  332|     76|}
vo.c:dispatch_wakeup_cb:
  222|    256|{
  223|    256|    struct vo *vo = ptr;
  224|    256|    vo_wakeup(vo);
  225|    256|}
vo.c:update_opts:
  238|    178|{
  239|    178|    struct vo *vo = p;
  240|       |
  241|    178|    if (m_config_cache_update(vo->opts_cache)) {
  ------------------
  |  Branch (241:9): [True: 0, False: 178]
  ------------------
  242|      0|        read_opts(vo);
  243|      0|        if (vo->driver->control) {
  ------------------
  |  Branch (243:13): [True: 0, False: 0]
  ------------------
  244|      0|            vo->driver->control(vo, VOCTRL_VO_OPTS_CHANGED, NULL);
  245|       |            // "Legacy" update of video position related options.
  246|       |            // Unlike VOCTRL_VO_OPTS_CHANGED, often not propagated to backends.
  247|      0|            vo->driver->control(vo, VOCTRL_SET_PANSCAN, NULL);
  248|      0|        }
  249|      0|    }
  250|    178|}
vo.c:read_opts:
  229|     39|{
  230|     39|    struct vo_internal *in = vo->in;
  231|       |
  232|     39|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|     39|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  233|     39|    in->timing_offset = (uint64_t)(MP_TIME_S_TO_NS(vo->opts->timing_offset));
  ------------------
  |  |   59|     39|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  ------------------
  234|     39|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|     39|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  235|     39|}
vo.c:vo_thread:
 1125|     76|{
 1126|     76|    struct vo *vo = ptr;
 1127|     76|    struct vo_internal *in = vo->in;
 1128|     76|    bool vo_paused = false;
 1129|       |
 1130|     76|    mp_thread_set_name("vo");
 1131|       |
 1132|     76|    if (vo->driver->get_image) {
  ------------------
  |  Branch (1132:9): [True: 17, False: 59]
  ------------------
 1133|     17|        in->dr_helper = dr_helper_create(in->dispatch, get_image_vo, vo);
 1134|     17|        dr_helper_acquire_thread(in->dr_helper);
 1135|     17|    }
 1136|       |
 1137|     76|    int r = vo->driver->preinit(vo) ? -1 : 0;
  ------------------
  |  Branch (1137:13): [True: 37, False: 39]
  ------------------
 1138|     76|    mp_rendezvous(vo, r); // init barrier
 1139|     76|    if (r < 0)
  ------------------
  |  Branch (1139:9): [True: 37, False: 39]
  ------------------
 1140|     37|        goto done;
 1141|       |
 1142|     39|    read_opts(vo);
 1143|     39|    update_display_fps(vo);
 1144|     39|    vo_event(vo, VO_EVENT_WIN_STATE);
 1145|       |
 1146|    410|    while (1) {
  ------------------
  |  Branch (1146:12): [Folded - Ignored]
  ------------------
 1147|    410|        mp_dispatch_queue_process(vo->in->dispatch, 0);
 1148|    410|        if (in->terminate)
  ------------------
  |  Branch (1148:13): [True: 39, False: 371]
  ------------------
 1149|     39|            break;
 1150|    371|        stats_event(in->stats, "iterations");
 1151|    371|        vo->driver->control(vo, VOCTRL_CHECK_EVENTS, NULL);
 1152|    371|        bool working = render_frame(vo);
 1153|    371|        int64_t now = mp_time_ns();
 1154|    371|        int64_t wait_until = now + MP_TIME_S_TO_NS(working ? 0 : 1000);
  ------------------
  |  |   59|    742|#define MP_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
  |  |  ------------------
  |  |  |  Branch (59:30): [True: 0, False: 371]
  |  |  ------------------
  ------------------
 1155|    371|        bool wakeup_on_done = false;
 1156|    371|        int64_t wakeup_core_after = 0;
 1157|       |
 1158|    371|        mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|    371|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1159|    371|        if (in->wakeup_pts) {
  ------------------
  |  Branch (1159:13): [True: 0, False: 371]
  ------------------
 1160|      0|            if (in->wakeup_pts > now) {
  ------------------
  |  Branch (1160:17): [True: 0, False: 0]
  ------------------
 1161|      0|                wait_until = MPMIN(wait_until, in->wakeup_pts);
  ------------------
  |  |   44|      0|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1162|      0|            } else {
 1163|      0|                in->wakeup_pts = 0;
 1164|      0|                wakeup_core(vo);
 1165|      0|            }
 1166|      0|        }
 1167|    371|        if (vo->want_redraw && !in->want_redraw) {
  ------------------
  |  Branch (1167:13): [True: 39, False: 332]
  |  Branch (1167:32): [True: 39, False: 0]
  ------------------
 1168|     39|            in->want_redraw = true;
 1169|     39|            wakeup_core(vo);
 1170|     39|        }
 1171|    371|        if ((!working && !in->rendering && !in->frame_queued) && in->wakeup_on_done) {
  ------------------
  |  Branch (1171:14): [True: 371, False: 0]
  |  Branch (1171:26): [True: 371, False: 0]
  |  Branch (1171:44): [True: 371, False: 0]
  |  Branch (1171:66): [True: 0, False: 371]
  ------------------
 1172|       |            // At this point we know VO is going to sleep
 1173|      0|            int64_t frame_end = get_current_frame_end(vo);
 1174|      0|            if (frame_end >= 0)
  ------------------
  |  Branch (1174:17): [True: 0, False: 0]
  ------------------
 1175|      0|                wakeup_core_after = frame_end;
 1176|      0|            wakeup_on_done = true;
 1177|      0|            in->wakeup_on_done = false;
 1178|      0|        }
 1179|    371|        vo->want_redraw = false;
 1180|    371|        bool redraw = in->request_redraw;
 1181|    371|        bool send_reset = in->send_reset;
 1182|    371|        in->send_reset = false;
 1183|    371|        bool send_pause = in->paused != vo_paused;
 1184|    371|        vo_paused = in->paused;
 1185|    371|        mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|    371|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1186|       |
 1187|    371|        if (send_reset)
  ------------------
  |  Branch (1187:13): [True: 0, False: 371]
  ------------------
 1188|      0|            vo->driver->control(vo, VOCTRL_RESET, NULL);
 1189|    371|        if (send_pause)
  ------------------
  |  Branch (1189:13): [True: 39, False: 332]
  ------------------
 1190|     39|            vo->driver->control(vo, vo_paused ? VOCTRL_PAUSE : VOCTRL_RESUME, NULL);
  ------------------
  |  Branch (1190:37): [True: 39, False: 0]
  ------------------
 1191|    371|        if (wait_until > now && redraw) {
  ------------------
  |  Branch (1191:13): [True: 371, False: 0]
  |  Branch (1191:33): [True: 78, False: 293]
  ------------------
 1192|     78|            vo->driver->control(vo, VOCTRL_REDRAW, NULL);
 1193|     78|            do_redraw(vo); // now is a good time
 1194|     78|            continue;
 1195|     78|        }
 1196|    293|        if (vo->want_redraw) // might have been set by VOCTRLs
  ------------------
  |  Branch (1196:13): [True: 0, False: 293]
  ------------------
 1197|      0|            wait_until = 0;
 1198|       |
 1199|    293|        if (wait_until <= now)
  ------------------
  |  Branch (1199:13): [True: 0, False: 293]
  ------------------
 1200|      0|            continue;
 1201|       |
 1202|    293|        if (wakeup_on_done) {
  ------------------
  |  Branch (1202:13): [True: 0, False: 293]
  ------------------
 1203|       |            // At this point wait_until should be longer than frame duration
 1204|      0|            if (wakeup_core_after >= 0 && wait_until >= wakeup_core_after) {
  ------------------
  |  Branch (1204:17): [True: 0, False: 0]
  |  Branch (1204:43): [True: 0, False: 0]
  ------------------
 1205|      0|                wait_vo(vo, wakeup_core_after);
 1206|      0|                mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|      0|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1207|      0|                in->need_wakeup = true;
 1208|      0|                mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1209|      0|            }
 1210|      0|            wakeup_core(vo);
 1211|      0|        }
 1212|       |
 1213|    293|        wait_vo(vo, wait_until);
 1214|    293|    }
 1215|     39|    forget_frames(vo); // implicitly synchronized
 1216|     39|    talloc_free(in->current_frame);
  ------------------
  |  |   47|     39|#define talloc_free                     ta_free
  ------------------
 1217|     39|    in->current_frame = NULL;
 1218|     39|    vo->driver->uninit(vo);
 1219|     76|done:
 1220|     76|    TA_FREEP(&in->dr_helper);
  ------------------
  |  |   81|     76|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|     76|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1221|     76|    MP_THREAD_RETURN();
  ------------------
  |  |  209|     76|#define MP_THREAD_RETURN() return NULL
  ------------------
 1222|     39|}
vo.c:update_display_fps:
  540|    449|{
  541|    449|    struct vo_internal *in = vo->in;
  542|    449|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|    449|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  543|    449|    if (in->internal_events & VO_EVENT_WIN_STATE) {
  ------------------
  |  Branch (543:9): [True: 39, False: 410]
  ------------------
  544|     39|        in->internal_events &= ~(unsigned)VO_EVENT_WIN_STATE;
  545|       |
  546|     39|        mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|     39|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  547|       |
  548|     39|        double fps = 0;
  549|     39|        vo->driver->control(vo, VOCTRL_GET_DISPLAY_FPS, &fps);
  550|       |
  551|     39|        mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|     39|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  552|       |
  553|     39|        in->reported_display_fps = fps;
  554|     39|    }
  555|       |
  556|    449|    double display_fps = vo->opts->display_fps_override;
  557|    449|    if (display_fps <= 0)
  ------------------
  |  Branch (557:9): [True: 449, False: 0]
  ------------------
  558|    449|        display_fps = in->reported_display_fps;
  559|       |
  560|    449|    if (in->display_fps != display_fps) {
  ------------------
  |  Branch (560:9): [True: 0, False: 449]
  ------------------
  561|      0|        in->nominal_vsync_interval =  display_fps > 0 ? 1e9 / display_fps : 0;
  ------------------
  |  Branch (561:39): [True: 0, False: 0]
  ------------------
  562|      0|        in->vsync_interval = MPMAX(in->nominal_vsync_interval, 1);
  ------------------
  |  |   43|      0|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  563|      0|        in->display_fps = display_fps;
  564|       |
  565|      0|        MP_VERBOSE(vo, "Assuming %f FPS for display sync.\n", display_fps);
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  566|       |
  567|       |        // make sure to update the player
  568|      0|        in->queued_events |= VO_EVENT_WIN_STATE;
  569|      0|        wakeup_core(vo);
  570|      0|    }
  571|       |
  572|    449|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|    449|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  573|    449|}
vo.c:render_frame:
  924|    371|{
  925|    371|    struct vo_internal *in = vo->in;
  926|    371|    struct vo_frame *frame = NULL;
  927|    371|    bool more_frames = false;
  928|       |
  929|    371|    update_display_fps(vo);
  930|       |
  931|    371|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|    371|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  932|       |
  933|    371|    if (in->frame_queued) {
  ------------------
  |  Branch (933:9): [True: 0, False: 371]
  ------------------
  934|      0|        talloc_free(in->current_frame);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  935|      0|        in->current_frame = in->frame_queued;
  936|      0|        in->frame_queued = NULL;
  937|    371|    } else if (in->paused || !in->current_frame || !in->hasframe ||
  ------------------
  |  Branch (937:16): [True: 178, False: 193]
  |  Branch (937:30): [True: 193, False: 0]
  |  Branch (937:52): [True: 0, False: 0]
  ------------------
  938|    371|               (in->current_frame->display_synced && in->current_frame->num_vsyncs < 1) ||
  ------------------
  |  Branch (938:17): [True: 0, False: 0]
  |  Branch (938:54): [True: 0, False: 0]
  ------------------
  939|    371|               !in->current_frame->display_synced)
  ------------------
  |  Branch (939:16): [True: 0, False: 0]
  ------------------
  940|    371|    {
  941|    371|        goto done;
  942|    371|    }
  943|       |
  944|      0|    frame = vo_frame_ref(in->current_frame);
  945|      0|    mp_assert(frame);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  946|       |
  947|      0|    if (frame->display_synced) {
  ------------------
  |  Branch (947:9): [True: 0, False: 0]
  ------------------
  948|      0|        frame->pts = 0;
  949|      0|        frame->duration = -1;
  950|      0|    }
  951|       |
  952|      0|    int64_t now = mp_time_ns();
  953|      0|    int64_t pts = frame->pts;
  954|      0|    int64_t duration = frame->duration;
  955|      0|    int64_t end_time = pts + duration;
  956|       |
  957|       |    // Time at which we should flip_page on the VO.
  958|      0|    int64_t target = frame->display_synced ? 0 : pts - in->flip_queue_offset;
  ------------------
  |  Branch (958:22): [True: 0, False: 0]
  ------------------
  959|       |
  960|       |    // "normal" strict drop threshold.
  961|      0|    in->dropped_frame = duration >= 0 && end_time < now;
  ------------------
  |  Branch (961:25): [True: 0, False: 0]
  |  Branch (961:42): [True: 0, False: 0]
  ------------------
  962|       |
  963|      0|    in->dropped_frame &= !frame->display_synced;
  964|      0|    in->dropped_frame &= !(vo->driver->caps & VO_CAP_FRAMEDROP);
  965|      0|    in->dropped_frame &= frame->can_drop;
  966|       |    // Even if we're hopelessly behind, rather degrade to 10 FPS playback,
  967|       |    // instead of just freezing the display forever.
  968|      0|    in->dropped_frame &= now - in->prev_vsync < MP_TIME_MS_TO_NS(100);
  ------------------
  |  |   60|      0|#define MP_TIME_MS_TO_NS(ms) ((ms) * INT64_C(1000000))
  ------------------
  969|      0|    in->dropped_frame &= in->hasframe_rendered;
  970|       |
  971|       |    // Setup parameters for the next time this frame is drawn. ("frame" is the
  972|       |    // frame currently drawn, while in->current_frame is the potentially next.)
  973|      0|    in->current_frame->repeat = true;
  974|      0|    if (frame->display_synced) {
  ------------------
  |  Branch (974:9): [True: 0, False: 0]
  ------------------
  975|       |        // Increment the offset only if it's not the last vsync. The current_frame
  976|       |        // can still be reused. This is mostly important for redraws that might
  977|       |        // overshoot the target vsync point.
  978|      0|        if (in->current_frame->num_vsyncs > 1) {
  ------------------
  |  Branch (978:13): [True: 0, False: 0]
  ------------------
  979|      0|            in->current_frame->vsync_offset += in->current_frame->vsync_interval;
  980|      0|            in->current_frame->ideal_frame_vsync += in->current_frame->ideal_frame_vsync_duration;
  981|      0|        }
  982|      0|        in->dropped_frame |= in->current_frame->num_vsyncs < 1;
  983|      0|    }
  984|      0|    if (in->current_frame->num_vsyncs > 0)
  ------------------
  |  Branch (984:9): [True: 0, False: 0]
  ------------------
  985|      0|        in->current_frame->num_vsyncs -= 1;
  986|       |
  987|       |    // Always render when paused (it's typically the last frame for a while).
  988|      0|    in->dropped_frame &= !in->paused;
  989|       |
  990|      0|    bool use_vsync = in->current_frame->display_synced && !in->paused;
  ------------------
  |  Branch (990:22): [True: 0, False: 0]
  |  Branch (990:59): [True: 0, False: 0]
  ------------------
  991|      0|    if (use_vsync && !in->expecting_vsync) // first DS frame in a row
  ------------------
  |  Branch (991:9): [True: 0, False: 0]
  |  Branch (991:22): [True: 0, False: 0]
  ------------------
  992|      0|        in->prev_vsync = now;
  993|      0|    in->expecting_vsync = use_vsync;
  994|       |
  995|       |    // Store the initial value before we unlock.
  996|      0|    bool request_redraw = in->request_redraw;
  997|       |
  998|      0|    if (in->dropped_frame) {
  ------------------
  |  Branch (998:9): [True: 0, False: 0]
  ------------------
  999|      0|        in->drop_count += 1;
 1000|      0|        wakeup_core(vo);
 1001|      0|    } else {
 1002|      0|        in->rendering = true;
 1003|      0|        in->hasframe_rendered = true;
 1004|      0|        int64_t prev_drop_count = vo->in->drop_count;
 1005|       |        // Can the core queue new video now? Non-display-sync uses a separate
 1006|       |        // timer instead, but possibly benefits from preparing a frame early.
 1007|      0|        bool can_queue = !in->frame_queued &&
  ------------------
  |  Branch (1007:26): [True: 0, False: 0]
  ------------------
 1008|      0|            (in->current_frame->num_vsyncs < 1 || !use_vsync);
  ------------------
  |  Branch (1008:14): [True: 0, False: 0]
  |  Branch (1008:51): [True: 0, False: 0]
  ------------------
 1009|      0|        mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1010|       |
 1011|      0|        if (can_queue)
  ------------------
  |  Branch (1011:13): [True: 0, False: 0]
  ------------------
 1012|      0|            wakeup_core(vo);
 1013|       |
 1014|      0|        stats_time_start(in->stats, "video-draw");
 1015|       |
 1016|      0|        in->visible = vo->driver->draw_frame(vo, frame);
 1017|       |
 1018|      0|        stats_time_end(in->stats, "video-draw");
 1019|       |
 1020|      0|        wait_until(vo, target);
 1021|       |
 1022|      0|        stats_time_start(in->stats, "video-flip");
 1023|       |
 1024|      0|        vo->driver->flip_page(vo);
 1025|       |
 1026|      0|        struct vo_vsync_info vsync = {
 1027|      0|            .last_queue_display_time = -1,
 1028|      0|            .skipped_vsyncs = -1,
 1029|      0|        };
 1030|      0|        if (vo->driver->get_vsync)
  ------------------
  |  Branch (1030:13): [True: 0, False: 0]
  ------------------
 1031|      0|            vo->driver->get_vsync(vo, &vsync);
 1032|       |
 1033|       |        // Make up some crap if presentation feedback is missing.
 1034|      0|        if (vsync.last_queue_display_time <= 0)
  ------------------
  |  Branch (1034:13): [True: 0, False: 0]
  ------------------
 1035|      0|            vsync.last_queue_display_time = mp_time_ns();
 1036|       |
 1037|      0|        stats_time_end(in->stats, "video-flip");
 1038|       |
 1039|      0|        mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|      0|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1040|      0|        in->dropped_frame = prev_drop_count < vo->in->drop_count;
 1041|      0|        in->rendering = false;
 1042|       |
 1043|      0|        update_vsync_timing_after_swap(vo, &vsync);
 1044|      0|    }
 1045|       |
 1046|      0|    if (vo->driver->caps & VO_CAP_NORETAIN) {
  ------------------
  |  Branch (1046:9): [True: 0, False: 0]
  ------------------
 1047|      0|        talloc_free(in->current_frame);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 1048|      0|        in->current_frame = NULL;
 1049|      0|    }
 1050|       |
 1051|      0|    if (in->dropped_frame) {
  ------------------
  |  Branch (1051:9): [True: 0, False: 0]
  ------------------
 1052|      0|        MP_STATS(vo, "drop-vo");
  ------------------
  |  |   95|      0|#define MP_STATS(obj, ...)      MP_MSG(obj, MSGL_STATS, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1053|      0|    } else {
 1054|       |        // If the initial redraw request was true or mpv is still playing,
 1055|       |        // then we can clear it here since we just performed a redraw, or the
 1056|       |        // next loop will draw what we need. However if there initially is
 1057|       |        // no redraw request, then something can change this (i.e. the OSD)
 1058|       |        // while the vo was unlocked. If we are paused, don't touch
 1059|       |        // in->request_redraw in that case.
 1060|      0|        if (request_redraw || !in->paused)
  ------------------
  |  Branch (1060:13): [True: 0, False: 0]
  |  Branch (1060:31): [True: 0, False: 0]
  ------------------
 1061|      0|            in->request_redraw = false;
 1062|      0|    }
 1063|       |
 1064|      0|    if (in->current_frame && in->current_frame->num_vsyncs &&
  ------------------
  |  Branch (1064:9): [True: 0, False: 0]
  |  Branch (1064:30): [True: 0, False: 0]
  ------------------
 1065|      0|        in->current_frame->display_synced)
  ------------------
  |  Branch (1065:9): [True: 0, False: 0]
  ------------------
 1066|      0|        more_frames = true;
 1067|       |
 1068|      0|    if (in->frame_queued && in->frame_queued->display_synced)
  ------------------
  |  Branch (1068:9): [True: 0, False: 0]
  |  Branch (1068:29): [True: 0, False: 0]
  ------------------
 1069|      0|        more_frames = true;
 1070|       |
 1071|      0|    mp_cond_broadcast(&in->wakeup); // for vo_wait_frame()
 1072|       |
 1073|    371|done:
 1074|    371|    if (!(vo->driver->caps & VO_CAP_FRAMEOWNER) || in->dropped_frame)
  ------------------
  |  Branch (1074:9): [True: 371, False: 0]
  |  Branch (1074:52): [True: 0, False: 0]
  ------------------
 1075|    371|        talloc_free(frame);
  ------------------
  |  |   47|    371|#define talloc_free                     ta_free
  ------------------
 1076|    371|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|    371|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1077|       |
 1078|    371|    return more_frames;
 1079|      0|}
vo.c:do_redraw:
 1082|     78|{
 1083|     78|    struct vo_internal *in = vo->in;
 1084|       |
 1085|     78|    if (!vo->config_ok)
  ------------------
  |  Branch (1085:9): [True: 0, False: 78]
  ------------------
 1086|      0|        return;
 1087|       |
 1088|     78|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|     78|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
 1089|     78|    in->request_redraw = false;
 1090|       |
 1091|     78|    if (vo->driver->caps & (VO_CAP_NORETAIN | VO_CAP_UNTIMED)) {
  ------------------
  |  Branch (1091:9): [True: 0, False: 78]
  ------------------
 1092|      0|        mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1093|      0|        return;
 1094|      0|    }
 1095|       |
 1096|     78|    bool full_redraw = in->dropped_frame;
 1097|     78|    struct vo_frame *frame = vo_frame_ref(in->current_frame);
 1098|     78|    if (frame)
  ------------------
  |  Branch (1098:9): [True: 0, False: 78]
  ------------------
 1099|      0|        in->dropped_frame = false;
 1100|     78|    struct vo_frame dummy = {0};
 1101|     78|    if (!frame)
  ------------------
  |  Branch (1101:9): [True: 78, False: 0]
  ------------------
 1102|     78|        frame = &dummy;
 1103|     78|    frame->redraw = !full_redraw; // unconditionally redraw if it was dropped
 1104|     78|    frame->repeat = false;
 1105|     78|    frame->still = true;
 1106|     78|    frame->pts = 0;
 1107|     78|    frame->duration = -1;
 1108|     78|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|     78|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
 1109|       |
 1110|     78|    vo->driver->draw_frame(vo, frame);
 1111|     78|    vo->driver->flip_page(vo);
 1112|       |
 1113|     78|    if (frame != &dummy && !(vo->driver->caps & VO_CAP_FRAMEOWNER))
  ------------------
  |  Branch (1113:9): [True: 0, False: 78]
  |  Branch (1113:28): [True: 0, False: 0]
  ------------------
 1114|      0|        talloc_free(frame);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 1115|     78|}
vo.c:wait_vo:
  731|    293|{
  732|    293|    struct vo_internal *in = vo->in;
  733|       |
  734|    293|    if (vo->driver->wait_events) {
  ------------------
  |  Branch (734:9): [True: 0, False: 293]
  ------------------
  735|      0|        vo->driver->wait_events(vo, until_time);
  736|    293|    } else {
  737|    293|        vo_wait_default(vo, until_time);
  738|    293|    }
  739|    293|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|    293|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  740|    293|    in->need_wakeup = false;
  741|    293|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|    293|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  742|    293|}
vo.c:terminate_vo:
  368|     39|{
  369|     39|    struct vo *vo = p;
  370|     39|    struct vo_internal *in = vo->in;
  371|     39|    in->terminate = true;
  372|     39|}
vo.c:dealloc_vo:
  254|     76|{
  255|     76|    forget_frames(vo); // implicitly synchronized
  256|       |
  257|       |    // These must be free'd before vo->in->dispatch.
  258|     76|    talloc_free(vo->opts_cache);
  ------------------
  |  |   47|     76|#define talloc_free                     ta_free
  ------------------
  259|     76|    talloc_free(vo->gl_opts_cache);
  ------------------
  |  |   47|     76|#define talloc_free                     ta_free
  ------------------
  260|     76|    talloc_free(vo->eq_opts_cache);
  ------------------
  |  |   47|     76|#define talloc_free                     ta_free
  ------------------
  261|     76|    mp_mutex_destroy(&vo->params_mutex);
  ------------------
  |  |  130|     76|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
  262|       |
  263|     76|    mp_mutex_destroy(&vo->in->lock);
  ------------------
  |  |  130|     76|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
  264|     76|    mp_cond_destroy(&vo->in->wakeup);
  265|     76|    talloc_free(vo);
  ------------------
  |  |   47|     76|#define talloc_free                     ta_free
  ------------------
  266|     76|}
vo.c:run_reconfig:
  591|     39|{
  592|     39|    void **pp = p;
  593|     39|    struct vo *vo = pp[0];
  594|     39|    struct mp_image *img = pp[1];
  595|     39|    int *ret = pp[2];
  596|       |
  597|     39|    struct mp_image_params *params = &img->params;
  598|       |
  599|     39|    struct vo_internal *in = vo->in;
  600|       |
  601|     39|    MP_VERBOSE(vo, "reconfig to %s\n", mp_image_params_to_str(params));
  ------------------
  |  |   88|     39|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|     39|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  602|       |
  603|     39|    update_opts(vo);
  604|       |
  605|     39|    mp_image_params_get_dsize(params, &vo->dwidth, &vo->dheight);
  606|       |
  607|     39|    mp_mutex_lock(&vo->params_mutex);
  ------------------
  |  |  131|     39|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  608|     39|    talloc_free(vo->params);
  ------------------
  |  |   47|     39|#define talloc_free                     ta_free
  ------------------
  609|     39|    vo->params = talloc_dup(vo, params);
  ------------------
  |  |   48|     39|#define talloc_dup                      ta_xdup
  |  |  ------------------
  |  |  |  |  141|     39|#define ta_xdup(...)                    ta_oom_g(ta_dup(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     39|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  610|     39|    vo->has_peak_detect_values = false;
  611|     39|    mp_mutex_unlock(&vo->params_mutex);
  ------------------
  |  |  133|     39|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  612|       |
  613|     39|    if (vo->driver->reconfig2) {
  ------------------
  |  Branch (613:9): [True: 0, False: 39]
  ------------------
  614|      0|        *ret = vo->driver->reconfig2(vo, img);
  615|     39|    } else {
  616|     39|        *ret = vo->driver->reconfig(vo, vo->params);
  617|     39|    }
  618|     39|    vo->config_ok = *ret >= 0;
  619|     39|    if (vo->config_ok) {
  ------------------
  |  Branch (619:9): [True: 39, False: 0]
  ------------------
  620|     39|        check_vo_caps(vo);
  621|     39|    } else {
  622|      0|        mp_mutex_lock(&vo->params_mutex);
  ------------------
  |  |  131|      0|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  623|      0|        talloc_free(vo->params);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
  624|      0|        vo->params = NULL;
  625|      0|        vo->has_peak_detect_values = false;
  626|      0|        mp_mutex_unlock(&vo->params_mutex);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  627|      0|    }
  628|       |
  629|     39|    mp_mutex_lock(&in->lock);
  ------------------
  |  |  131|     39|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  630|     39|    talloc_free(in->current_frame);
  ------------------
  |  |   47|     39|#define talloc_free                     ta_free
  ------------------
  631|     39|    in->current_frame = NULL;
  632|     39|    forget_frames(vo);
  633|     39|    reset_vsync_timings(vo);
  634|     39|    mp_mutex_unlock(&in->lock);
  ------------------
  |  |  133|     39|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  635|       |
  636|     39|    update_display_fps(vo);
  637|     39|}
vo.c:check_vo_caps:
  576|     39|{
  577|     39|    int rot = vo->params->rotate;
  578|     39|    if (rot) {
  ------------------
  |  Branch (578:9): [True: 0, False: 39]
  ------------------
  579|      0|        bool ok = rot % 90 ? false : (vo->driver->caps & VO_CAP_ROTATE90);
  ------------------
  |  Branch (579:19): [True: 0, False: 0]
  ------------------
  580|      0|        if (!ok) {
  ------------------
  |  Branch (580:13): [True: 0, False: 0]
  ------------------
  581|      0|           MP_WARN(vo, "Video is flagged as rotated by %d degrees, but the "
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  582|      0|                   "video output does not support this.\n", rot);
  583|      0|        }
  584|      0|    }
  585|     39|    if (vo->params->vflip && !(vo->driver->caps & VO_CAP_VFLIP))
  ------------------
  |  Branch (585:9): [True: 0, False: 39]
  |  Branch (585:30): [True: 0, False: 0]
  ------------------
  586|     39|        MP_WARN(vo, "Video is flagged as vertically flipped, but the "
  ------------------
  |  |   86|      0|#define MP_WARN(obj, ...)       MP_MSG(obj, MSGL_WARN, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  587|     39|                    "video output does not support this.\n");
  588|     39|}
vo.c:run_control:
  658|    139|{
  659|    139|    void **pp = p;
  660|    139|    struct vo *vo = pp[0];
  661|    139|    int request = (intptr_t)pp[1];
  662|    139|    void *data = pp[2];
  663|    139|    update_opts(vo);
  664|    139|    int ret = vo->driver->control(vo, request, data);
  665|    139|    if (pp[3])
  ------------------
  |  Branch (665:9): [True: 100, False: 39]
  ------------------
  666|    100|        *(int *)pp[3] = ret;
  667|    139|}
vo.c:wakeup_locked:
  745|    412|{
  746|    412|    struct vo_internal *in = vo->in;
  747|       |
  748|    412|    mp_cond_broadcast(&in->wakeup);
  749|    412|    if (vo->driver->wakeup)
  ------------------
  |  Branch (749:9): [True: 0, False: 412]
  ------------------
  750|      0|        vo->driver->wakeup(vo);
  751|    412|    in->need_wakeup = true;
  752|    412|}
vo.c:wakeup_core:
  384|     78|{
  385|     78|    vo->extra.wakeup_cb(vo->extra.wakeup_ctx);
  386|     78|}
vo.c:reset_vsync_timings:
  391|     78|{
  392|     78|    struct vo_internal *in = vo->in;
  393|     78|    in->drop_point = 0;
  394|     78|    in->base_vsync = 0;
  395|     78|    in->expecting_vsync = false;
  396|     78|    in->num_successive_vsyncs = 0;
  397|     78|}
vo.c:forget_frames:
  700|    154|{
  701|    154|    struct vo_internal *in = vo->in;
  702|    154|    in->hasframe = false;
  703|    154|    in->hasframe_rendered = false;
  704|    154|    in->drop_count = 0;
  705|    154|    in->delayed_count = 0;
  706|    154|    talloc_free(in->frame_queued);
  ------------------
  |  |   47|    154|#define talloc_free                     ta_free
  ------------------
  707|    154|    in->frame_queued = NULL;
  708|    154|    in->current_frame_id += VO_MAX_REQ_FRAMES + 1;
  ------------------
  |  |  218|    154|#define VO_MAX_REQ_FRAMES 10
  ------------------
  709|       |    // don't unref current_frame; we always want to be able to redraw it
  710|    154|    if (in->current_frame) {
  ------------------
  |  Branch (710:9): [True: 0, False: 154]
  ------------------
  711|      0|        in->current_frame->num_vsyncs = 0; // but reset future repeats
  712|      0|        in->current_frame->display_synced = false; // mark discontinuity
  713|      0|    }
  714|    154|}
vo.c:run_query_format:
 1295|     39|{
 1296|     39|    void **pp = p;
 1297|     39|    struct vo *vo = pp[0];
 1298|     39|    uint8_t *list = pp[1];
 1299|  21.7k|    for (int format = IMGFMT_START; format < IMGFMT_END; format++)
  ------------------
  |  Branch (1299:37): [True: 21.7k, False: 39]
  ------------------
 1300|  21.7k|        list[format - IMGFMT_START] = vo->driver->query_format(vo, format);
 1301|     39|}

vo_gpu.c:preinit:
  296|     17|{
  297|     17|    struct gpu_priv *p = vo->priv;
  298|     17|    p->log = vo->log;
  299|       |
  300|     17|    struct ra_ctx_opts *ctx_opts = mp_get_config_group(vo, vo->global, &ra_ctx_conf);
  301|     17|    update_ra_ctx_options(vo, ctx_opts);
  302|     17|    p->ctx = ra_ctx_create(vo, *ctx_opts);
  303|     17|    talloc_free(ctx_opts);
  ------------------
  |  |   47|     17|#define talloc_free                     ta_free
  ------------------
  304|     17|    if (!p->ctx)
  ------------------
  |  Branch (304:9): [True: 17, False: 0]
  ------------------
  305|     17|        goto err_out;
  306|      0|    mp_assert(p->ctx->ra);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  307|      0|    mp_assert(p->ctx->swapchain);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  308|       |
  309|      0|    p->renderer = gl_video_init(p->ctx->ra, vo->log, vo->global);
  310|      0|    gl_video_set_osd_source(p->renderer, vo->osd);
  311|      0|    gl_video_configure_queue(p->renderer, vo);
  312|       |
  313|      0|    get_and_update_icc_profile(p);
  314|       |
  315|      0|    vo->hwdec_devs = hwdec_devices_create();
  316|      0|    hwdec_devices_set_loader(vo->hwdec_devs, call_request_hwdec_api, vo);
  317|       |
  318|      0|    gl_video_init_hwdecs(p->renderer, p->ctx, vo->hwdec_devs, false);
  319|       |
  320|      0|    return 0;
  321|       |
  322|     17|err_out:
  323|     17|    uninit(vo);
  324|     17|    return -1;
  325|      0|}
vo_gpu.c:update_ra_ctx_options:
  179|     17|{
  180|     17|    struct gpu_priv *p = vo->priv;
  181|     17|    struct gl_video_opts *gl_opts = mp_get_config_group(p->ctx, vo->global, &gl_video_conf);
  182|     17|    ctx_opts->want_alpha = (gl_opts->background == BACKGROUND_COLOR &&
  ------------------
  |  Branch (182:29): [True: 0, False: 17]
  ------------------
  183|     17|                            gl_opts->background_color.a != 255) ||
  ------------------
  |  Branch (183:29): [True: 0, False: 0]
  ------------------
  184|     17|                            gl_opts->background == BACKGROUND_NONE;
  ------------------
  |  Branch (184:29): [True: 0, False: 17]
  ------------------
  185|     17|    talloc_free(gl_opts);
  ------------------
  |  |   47|     17|#define talloc_free                     ta_free
  ------------------
  186|     17|}
vo_gpu.c:uninit:
  280|     17|{
  281|     17|    struct gpu_priv *p = vo->priv;
  282|       |
  283|     17|    gl_video_uninit(p->renderer);
  284|     17|    mp_mutex_lock(&vo->params_mutex);
  ------------------
  |  |  131|     17|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  285|     17|    vo->target_params = NULL;
  286|     17|    mp_mutex_unlock(&vo->params_mutex);
  ------------------
  |  |  133|     17|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  287|       |
  288|     17|    if (vo->hwdec_devs) {
  ------------------
  |  Branch (288:9): [True: 0, False: 17]
  ------------------
  289|      0|        hwdec_devices_set_loader(vo->hwdec_devs, NULL, NULL);
  290|      0|        hwdec_devices_destroy(vo->hwdec_devs);
  291|      0|    }
  292|     17|    ra_ctx_destroy(&p->ctx);
  293|     17|}

vo_gpu_next.c:preinit:
 1860|      8|{
 1861|      8|    struct priv *p = vo->priv;
 1862|      8|    p->opts_cache = m_config_cache_alloc(p, vo->global, &gl_video_conf);
 1863|      8|    p->next_opts_cache = m_config_cache_alloc(p, vo->global, &gl_next_conf);
 1864|      8|    p->next_opts = p->next_opts_cache->opts;
 1865|      8|    p->video_eq = mp_csp_equalizer_create(p, vo->global);
 1866|      8|    p->global = vo->global;
 1867|      8|    p->log = vo->log;
 1868|       |
 1869|      8|    struct gl_video_opts *gl_opts = p->opts_cache->opts;
 1870|      8|    struct ra_ctx_opts *ctx_opts = mp_get_config_group(vo, vo->global, &ra_ctx_conf);
 1871|      8|    update_ra_ctx_options(vo, ctx_opts);
 1872|      8|    p->context = gpu_ctx_create(vo, ctx_opts);
 1873|      8|    talloc_free(ctx_opts);
  ------------------
  |  |   47|      8|#define talloc_free                     ta_free
  ------------------
 1874|      8|    if (!p->context)
  ------------------
  |  Branch (1874:9): [True: 8, False: 0]
  ------------------
 1875|      8|        goto err_out;
 1876|       |    // For the time being
 1877|      0|    p->ra_ctx = p->context->ra_ctx;
 1878|      0|    p->pllog = p->context->pllog;
 1879|      0|    p->gpu = p->context->gpu;
 1880|      0|    p->sw = p->context->swapchain;
 1881|      0|    p->hwdec_ctx = (struct ra_hwdec_ctx) {
 1882|      0|        .log = p->log,
 1883|      0|        .global = p->global,
 1884|      0|        .ra_ctx = p->ra_ctx,
 1885|      0|    };
 1886|       |
 1887|      0|    vo->hwdec_devs = hwdec_devices_create();
 1888|      0|    hwdec_devices_set_loader(vo->hwdec_devs, load_hwdec_api, vo);
 1889|      0|    ra_hwdec_ctx_init(&p->hwdec_ctx, vo->hwdec_devs, gl_opts->hwdec_interop, false);
 1890|      0|    mp_mutex_init(&p->dr_lock);
 1891|       |
 1892|      0|    if (gl_opts->shader_cache)
  ------------------
  |  Branch (1892:9): [True: 0, False: 0]
  ------------------
 1893|      0|        cache_init(vo, &p->shader_cache, 10 << 20, gl_opts->shader_cache_dir);
 1894|      0|    if (gl_opts->icc_opts->cache)
  ------------------
  |  Branch (1894:9): [True: 0, False: 0]
  ------------------
 1895|      0|        cache_init(vo, &p->icc_cache, 20 << 20, gl_opts->icc_opts->cache_dir);
 1896|       |
 1897|      0|    pl_gpu_set_cache(p->gpu, p->shader_cache.cache);
 1898|      0|    p->rr = pl_renderer_create(p->pllog, p->gpu);
 1899|      0|    p->queue = pl_queue_create(p->gpu);
 1900|      0|    p->osd_fmt[SUBBITMAP_LIBASS] = pl_find_named_fmt(p->gpu, "r8");
 1901|      0|    p->osd_fmt[SUBBITMAP_BGRA] = pl_find_named_fmt(p->gpu, "bgra8");
 1902|      0|    p->osd_sync = 1;
 1903|       |
 1904|      0|    p->pars = pl_options_alloc(p->pllog);
 1905|      0|    update_render_options(vo);
 1906|      0|    return 0;
 1907|       |
 1908|      8|err_out:
 1909|      8|    uninit(vo);
 1910|      8|    return -1;
 1911|      8|}
vo_gpu_next.c:update_ra_ctx_options:
 1514|      8|{
 1515|      8|    struct priv *p = vo->priv;
 1516|      8|    struct gl_video_opts *gl_opts = p->opts_cache->opts;
 1517|      8|    bool border_alpha = (p->next_opts->border_background == BACKGROUND_COLOR &&
  ------------------
  |  Branch (1517:26): [True: 8, False: 0]
  ------------------
 1518|      8|                         gl_opts->background_color.a != 255) ||
  ------------------
  |  Branch (1518:26): [True: 0, False: 8]
  ------------------
 1519|      8|                         p->next_opts->border_background == BACKGROUND_NONE;
  ------------------
  |  Branch (1519:26): [True: 0, False: 8]
  ------------------
 1520|      8|    ctx_opts->want_alpha = (gl_opts->background == BACKGROUND_COLOR &&
  ------------------
  |  Branch (1520:29): [True: 0, False: 8]
  ------------------
 1521|      8|                            gl_opts->background_color.a != 255) ||
  ------------------
  |  Branch (1521:29): [True: 0, False: 0]
  ------------------
 1522|      8|                            gl_opts->background == BACKGROUND_NONE ||
  ------------------
  |  Branch (1522:29): [True: 0, False: 8]
  ------------------
 1523|      8|                            border_alpha;
  ------------------
  |  Branch (1523:29): [True: 0, False: 8]
  ------------------
 1524|      8|}
vo_gpu_next.c:uninit:
 1810|      8|{
 1811|      8|    struct priv *p = vo->priv;
 1812|      8|    pl_queue_destroy(&p->queue); // destroy this first
 1813|     48|    for (int i = 0; i < MP_ARRAY_SIZE(p->osd_state.entries); i++)
  ------------------
  |  |   48|     48|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (1813:21): [True: 40, False: 8]
  ------------------
 1814|     40|        pl_tex_destroy(p->gpu, &p->osd_state.entries[i].tex);
 1815|      8|    for (int i = 0; i < p->num_sub_tex; i++)
  ------------------
  |  Branch (1815:21): [True: 0, False: 8]
  ------------------
 1816|      0|        pl_tex_destroy(p->gpu, &p->sub_tex[i]);
 1817|      8|    for (int i = 0; i < p->num_user_hooks; i++)
  ------------------
  |  Branch (1817:21): [True: 0, False: 8]
  ------------------
 1818|      0|        pl_mpv_user_shader_destroy(&p->user_hooks[i].hook);
 1819|       |
 1820|      8|    if (vo->hwdec_devs) {
  ------------------
  |  Branch (1820:9): [True: 0, False: 8]
  ------------------
 1821|      0|        ra_hwdec_mapper_free(&p->hwdec_mapper);
 1822|      0|        ra_hwdec_ctx_uninit(&p->hwdec_ctx);
 1823|      0|        hwdec_devices_set_loader(vo->hwdec_devs, NULL, NULL);
 1824|      0|        hwdec_devices_destroy(vo->hwdec_devs);
 1825|      0|    }
 1826|       |
 1827|      8|    mp_assert(p->num_dr_buffers == 0);
  ------------------
  |  |   41|      8|#define mp_assert assert
  ------------------
 1828|      8|    mp_mutex_destroy(&p->dr_lock);
  ------------------
  |  |  130|      8|#define mp_mutex_destroy    pthread_mutex_destroy
  ------------------
 1829|       |
 1830|      8|    cache_uninit(p, &p->shader_cache);
 1831|      8|    cache_uninit(p, &p->icc_cache);
 1832|       |
 1833|      8|    pl_lut_free(&p->next_opts->image_lut.lut);
 1834|      8|    pl_lut_free(&p->next_opts->lut.lut);
 1835|      8|    pl_lut_free(&p->next_opts->target_lut.lut);
 1836|       |
 1837|      8|    pl_icc_close(&p->icc_profile);
 1838|      8|    pl_renderer_destroy(&p->rr);
 1839|       |
 1840|    520|    for (int i = 0; i < VO_PASS_PERF_MAX; ++i) {
  ------------------
  |  |  172|    520|#define VO_PASS_PERF_MAX 64
  ------------------
  |  Branch (1840:21): [True: 512, False: 8]
  ------------------
 1841|    512|        pl_shader_info_deref(&p->perf_fresh.info[i].shader);
 1842|    512|        pl_shader_info_deref(&p->perf_redraw.info[i].shader);
 1843|    512|    }
 1844|       |
 1845|      8|    pl_options_free(&p->pars);
 1846|       |
 1847|      8|    p->ra_ctx = NULL;
 1848|      8|    p->pllog = NULL;
 1849|      8|    p->gpu = NULL;
 1850|      8|    p->sw = NULL;
 1851|      8|    gpu_ctx_destroy(&p->context);
 1852|      8|}
vo_gpu_next.c:cache_uninit:
 1740|     16|{
 1741|     16|    if (!cache->cache)
  ------------------
  |  Branch (1741:9): [True: 16, False: 0]
  ------------------
 1742|     16|        return;
 1743|       |
 1744|      0|    void *ta_ctx = talloc_new(NULL);
  ------------------
  |  |   40|      0|#define talloc_new                      ta_xnew_context
  |  |  ------------------
  |  |  |  |  122|      0|#define ta_xnew_context(...)            ta_oom_p(ta_new_context(__VA_ARGS__))
  |  |  ------------------
  ------------------
 1745|      0|    struct file_entry *files = NULL;
 1746|      0|    size_t num_files = 0;
 1747|      0|    mp_assert(cache->dir);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
 1748|      0|    mp_assert(cache->name);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
 1749|       |
 1750|      0|    DIR *d = opendir(cache->dir);
 1751|      0|    if (!d)
  ------------------
  |  Branch (1751:9): [True: 0, False: 0]
  ------------------
 1752|      0|        goto done;
 1753|       |
 1754|      0|    struct dirent *dir;
 1755|      0|    while ((dir = readdir(d)) != NULL) {
  ------------------
  |  Branch (1755:12): [True: 0, False: 0]
  ------------------
 1756|      0|        char *filepath = mp_path_join(ta_ctx, cache->dir, dir->d_name);
 1757|      0|        if (!filepath)
  ------------------
  |  Branch (1757:13): [True: 0, False: 0]
  ------------------
 1758|      0|            continue;
 1759|      0|        struct stat filestat;
 1760|      0|        if (stat(filepath, &filestat))
  ------------------
  |  Branch (1760:13): [True: 0, False: 0]
  ------------------
 1761|      0|            continue;
 1762|      0|        if (!S_ISREG(filestat.st_mode))
  ------------------
  |  Branch (1762:13): [True: 0, False: 0]
  ------------------
 1763|      0|            continue;
 1764|      0|        bstr fname = bstr0(dir->d_name);
 1765|      0|        if (!bstr_eatstart0(&fname, cache->name))
  ------------------
  |  Branch (1765:13): [True: 0, False: 0]
  ------------------
 1766|      0|            continue;
 1767|      0|        if (!bstr_eatstart0(&fname, "_"))
  ------------------
  |  Branch (1767:13): [True: 0, False: 0]
  ------------------
 1768|      0|            continue;
 1769|      0|        if (fname.len != 16) // %016x
  ------------------
  |  Branch (1769:13): [True: 0, False: 0]
  ------------------
 1770|      0|            continue;
 1771|      0|        MP_TARRAY_APPEND(ta_ctx, files, num_files,
  ------------------
  |  |  105|      0|    do {                                            \
  |  |  106|      0|        MP_TARRAY_GROW(ctx, p, idxvar);             \
  |  |  ------------------
  |  |  |  |   96|      0|    do {                                            \
  |  |  |  |   97|      0|        size_t nextidx_ = (nextidx);                \
  |  |  |  |   98|      0|        if (nextidx_ >= MP_TALLOC_AVAIL(p))         \
  |  |  |  |  ------------------
  |  |  |  |  |  |   84|      0|#define MP_TALLOC_AVAIL(p) (talloc_get_size(p) / sizeof((p)[0]))
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   45|      0|#define talloc_get_size                 ta_get_size
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (98:13): [True: 0, False: 0]
  |  |  |  |  ------------------
  |  |  |  |   99|      0|            MP_RESIZE_ARRAY(ctx, p, ta_calc_prealloc_elems(nextidx_)); \
  |  |  |  |  ------------------
  |  |  |  |  |  |   88|      0|    do {                                                        \
  |  |  |  |  |  |   89|      0|        (p) = ta_xrealloc_size(ctx, p,                          \
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  158|      0|#define ta_xrealloc_size(...)   ta_dbg_set_loc(ta_xrealloc_size(__VA_ARGS__), TA_LOC)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   43|      0|#define TA_LOC __FILE__ ":" TA_STRINGIFY(__LINE__)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   38|      0|#define TA_STRINGIFY(x) TA_STRINGIFY_(x)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  |   37|      0|#define TA_STRINGIFY_(x) # x
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |   90|      0|                    ta_calc_array_size(sizeof((p)[0]), count)); \
  |  |  |  |  |  |   91|      0|    } while (0)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  Branch (91:14): [Folded - Ignored]
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  |  |  100|      0|    } while (0)
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (100:14): [Folded - Ignored]
  |  |  |  |  ------------------
  |  |  ------------------
  |  |  107|      0|        (p)[(idxvar)] = (__VA_ARGS__);              \
  |  |  108|      0|        (idxvar)++;                                 \
  |  |  109|      0|    } while (0)
  |  |  ------------------
  |  |  |  Branch (109:14): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1772|      0|                         (struct file_entry){
 1773|      0|                             .filepath = filepath,
 1774|      0|                             .size     = filestat.st_size,
 1775|      0|                             .atime    = filestat.st_atime,
 1776|      0|                         });
 1777|      0|    }
 1778|      0|    closedir(d);
 1779|       |
 1780|      0|    if (!num_files)
  ------------------
  |  Branch (1780:9): [True: 0, False: 0]
  ------------------
 1781|      0|        goto done;
 1782|       |
 1783|      0|    qsort(files, num_files, sizeof(struct file_entry), compare_atime);
 1784|       |
 1785|      0|    time_t t = time(NULL);
 1786|      0|    size_t cache_size = 0;
 1787|      0|    size_t cache_limit = cache->size_limit ? cache->size_limit : SIZE_MAX;
  ------------------
  |  Branch (1787:26): [True: 0, False: 0]
  ------------------
 1788|      0|    for (int i = 0; i < num_files; i++) {
  ------------------
  |  Branch (1788:21): [True: 0, False: 0]
  ------------------
 1789|       |        // Remove files that exceed the size limit but are older than one day.
 1790|       |        // This allows for temporary maintaining a larger cache size while
 1791|       |        // adjusting the configuration. The cache will be cleared the next day
 1792|       |        // for unused entries. We don't need to be overly aggressive with cache
 1793|       |        // cleaning; in most cases, it will not grow much, and in others, it may
 1794|       |        // actually be useful to cache more.
 1795|      0|        cache_size += files[i].size;
 1796|      0|        double rel_use = difftime(t, files[i].atime);
 1797|      0|        if (cache_size > cache_limit && rel_use > 60 * 60 * 24) {
  ------------------
  |  Branch (1797:13): [True: 0, False: 0]
  |  Branch (1797:41): [True: 0, False: 0]
  ------------------
 1798|      0|            MP_VERBOSE(p, "Removing %s | size: %9zu bytes | last used: %9d seconds ago\n",
  ------------------
  |  |   88|      0|#define MP_VERBOSE(obj, ...)    MP_MSG(obj, MSGL_V, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
 1799|      0|                       files[i].filepath, files[i].size, (int)rel_use);
 1800|      0|            unlink(files[i].filepath);
 1801|      0|        }
 1802|      0|    }
 1803|       |
 1804|      0|done:
 1805|      0|    talloc_free(ta_ctx);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 1806|      0|    pl_cache_destroy(&cache->cache);
 1807|      0|}

vo_kitty.c:preinit:
  406|     39|{
  407|     39|    struct priv *p = vo->priv;
  408|       |
  409|     39|    p->sws = mp_sws_alloc(vo);
  410|     39|    p->sws->log = vo->log;
  411|     39|    mp_sws_enable_cmdline_opts(p->sws, vo->global);
  412|       |
  413|     39|#if HAVE_POSIX
  414|     39|    struct sigaction sa = {
  415|     39|        .sa_handler = handle_winch,
  416|     39|    };
  417|     39|    sigaction(SIGWINCH, &sa, &saved_sigaction);
  418|     39|#endif
  419|       |
  420|       |#if HAVE_POSIX_SHM
  421|       |    if (p->opts.use_shm) {
  422|       |        p->shm_path = talloc_asprintf(vo, "/mpv-kitty-%p", vo);
  423|       |        int p_size = strlen(p->shm_path) - 1;
  424|       |        int b64_size = AV_BASE64_SIZE(p_size);
  425|       |        p->shm_path_b64 = talloc_array(vo, char, b64_size);
  426|       |        av_base64_encode(p->shm_path_b64, b64_size, p->shm_path + 1, p_size);
  427|       |    }
  428|       |#else
  429|     39|    if (p->opts.use_shm) {
  ------------------
  |  Branch (429:9): [True: 0, False: 39]
  ------------------
  430|      0|        MP_ERR(vo, "Shared memory support is not available on this platform.");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  431|      0|        return -1;
  432|      0|    }
  433|     39|#endif
  434|       |
  435|     39|    if (p->opts.auto_multiplexer_passthrough) {
  ------------------
  |  Branch (435:9): [True: 0, False: 39]
  ------------------
  436|      0|        if (getenv("TMUX")) {
  ------------------
  |  Branch (436:13): [True: 0, False: 0]
  ------------------
  437|      0|            p->dcs_prefix = DCS_TMUX_PREFIX;
  438|      0|        } else if (getenv("STY")) {
  ------------------
  |  Branch (438:20): [True: 0, False: 0]
  ------------------
  439|      0|            p->dcs_prefix = DCS_SCREEN_PREFIX;
  440|      0|        }
  441|       |
  442|      0|        if (p->dcs_prefix.len)
  ------------------
  |  Branch (442:13): [True: 0, False: 0]
  ------------------
  443|      0|            p->dcs_suffix = DCS_SUFFIX;
  444|      0|    }
  445|       |
  446|     39|    write_str(TERM_ESC_HIDE_CURSOR);
  ------------------
  |  |   29|     39|#define TERM_ESC_HIDE_CURSOR        "\033[?25l"
  ------------------
  447|     39|    terminal_set_mouse_input(true);
  448|     39|    if (p->opts.alt_screen)
  ------------------
  |  Branch (448:9): [True: 39, False: 0]
  ------------------
  449|     39|        write_str(TERM_ESC_ALT_SCREEN);
  ------------------
  |  |   35|     39|#define TERM_ESC_ALT_SCREEN         "\033[?1049h"
  ------------------
  450|       |
  451|     39|    return 0;
  452|     39|}
vo_kitty.c:write_str:
   76|    195|{
   77|    195|    write_bstr(bstr0(s));
   78|    195|}
vo_kitty.c:write_bstr:
   52|    624|{
   53|       |    // On POSIX platforms, write() is the fastest method. It also is the only
   54|       |    // one that allows atomic writes so mpv’s output will not be interrupted
   55|       |    // by other processes or threads that write to stdout, which would cause
   56|       |    // screen corruption. POSIX does not guarantee atomicity for writes
   57|       |    // exceeding PIPE_BUF, but at least Linux does seem to implement it that
   58|       |    // way.
   59|    624|#if HAVE_POSIX
   60|    624|    size_t remain = bs.len;
   61|    624|    unsigned char *pos = bs.start;
   62|    859|    while (remain > 0) {
  ------------------
  |  Branch (62:12): [True: 427, False: 432]
  ------------------
   63|    427|        ssize_t written = write(STDOUT_FILENO, pos, remain);
   64|    427|        if (written < 0)
  ------------------
  |  Branch (64:13): [True: 192, False: 235]
  ------------------
   65|    192|            return;
   66|    235|        remain -= written;
   67|    235|        pos += written;
   68|    235|    }
   69|       |#else
   70|       |    fwrite(bs.start, 1, bs.len, stdout);
   71|       |    fflush(stdout);
   72|       |#endif
   73|    624|}
vo_kitty.c:query_format:
  455|  21.7k|{
  456|  21.7k|    return format == IMGFMT;
  ------------------
  |  |   44|  21.7k|#define IMGFMT IMGFMT_RGB24
  ------------------
  457|  21.7k|}
vo_kitty.c:reconfig:
  220|     39|{
  221|     39|    struct priv *p = vo->priv;
  222|       |
  223|     39|    vo->want_redraw = true;
  224|       |
  225|     39|    write_bstr_passthrough(p, KITTY_ESC_DELETE_ALL);
  226|     39|    write_bstr_passthrough(p, KITTY_ESC_END);
  227|       |
  228|     39|    if (p->opts.config_clear)
  ------------------
  |  Branch (228:9): [True: 39, False: 0]
  ------------------
  229|     39|        write_str(TERM_ESC_CLEAR_SCREEN);
  ------------------
  |  |   34|     39|#define TERM_ESC_CLEAR_SCREEN       "\033[2J"
  ------------------
  230|       |
  231|     39|    get_win_size(vo, &p->rows, &p->cols, &vo->dwidth, &vo->dheight);
  232|     39|    set_out_params(vo);
  233|     39|    free_bufs(vo);
  234|       |
  235|     39|    p->sws->src = *params;
  236|     39|    p->sws->src.w = mp_rect_w(p->src);
  ------------------
  |  |  128|     39|#define mp_rect_w(r) ((r).x1 - (r).x0)
  ------------------
  237|     39|    p->sws->src.h = mp_rect_h(p->src);
  ------------------
  |  |  129|     39|#define mp_rect_h(r) ((r).y1 - (r).y0)
  ------------------
  238|     39|    p->sws->dst = (struct mp_image_params) {
  239|     39|        .imgfmt = IMGFMT,
  ------------------
  |  |   44|     39|#define IMGFMT IMGFMT_RGB24
  ------------------
  240|     39|        .w = p->width,
  241|     39|        .h = p->height,
  242|     39|        .p_w = 1,
  243|     39|        .p_h = 1,
  244|     39|    };
  245|       |
  246|     39|    p->frame = mp_image_alloc(IMGFMT, p->width, p->height);
  ------------------
  |  |   44|     39|#define IMGFMT IMGFMT_RGB24
  ------------------
  247|     39|    if (!p->frame)
  ------------------
  |  Branch (247:9): [True: 0, False: 39]
  ------------------
  248|      0|        return -1;
  249|       |
  250|     39|    if (mp_sws_reinit(p->sws) < 0)
  ------------------
  |  Branch (250:9): [True: 0, False: 39]
  ------------------
  251|      0|        return -1;
  252|       |
  253|     39|    if (!p->opts.use_shm) {
  ------------------
  |  Branch (253:9): [True: 39, False: 0]
  ------------------
  254|     39|        p->buffer = talloc_array(NULL, uint8_t, p->buffer_size);
  ------------------
  |  |   29|     39|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|     39|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     39|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  255|     39|        p->output = talloc_array(NULL, char, p->output_size);
  ------------------
  |  |   29|     39|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|     39|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     39|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  256|     39|    }
  257|       |
  258|     39|    return 0;
  259|     39|}
vo_kitty.c:write_bstr_passthrough:
  125|    117|{
  126|    117|    write_bstr(p->dcs_prefix);
  127|    117|    write_bstr(bs);
  128|    117|    write_bstr(p->dcs_suffix);
  129|    117|}
vo_kitty.c:get_win_size:
  186|     39|{
  187|     39|    struct priv *p = vo->priv;
  188|     39|    *out_rows = DEFAULT_HEIGHT;
  ------------------
  |  |   49|     39|#define DEFAULT_HEIGHT 25
  ------------------
  189|     39|    *out_cols = DEFAULT_WIDTH;
  ------------------
  |  |   48|     39|#define DEFAULT_WIDTH 80
  ------------------
  190|     39|    *out_width = DEFAULT_WIDTH_PX;
  ------------------
  |  |   46|     39|#define DEFAULT_WIDTH_PX  320
  ------------------
  191|     39|    *out_height = DEFAULT_HEIGHT_PX;
  ------------------
  |  |   47|     39|#define DEFAULT_HEIGHT_PX 240
  ------------------
  192|       |
  193|     39|    terminal_get_size2(out_rows, out_cols, out_width, out_height);
  194|       |
  195|     39|    *out_rows = p->opts.rows > 0 ? p->opts.rows : *out_rows;
  ------------------
  |  Branch (195:17): [True: 0, False: 39]
  ------------------
  196|     39|    *out_cols = p->opts.cols > 0 ? p->opts.cols : *out_cols;
  ------------------
  |  Branch (196:17): [True: 0, False: 39]
  ------------------
  197|     39|    *out_width = p->opts.width > 0 ? p->opts.width : *out_width;
  ------------------
  |  Branch (197:18): [True: 0, False: 39]
  ------------------
  198|     39|    *out_height = p->opts.height > 0 ? p->opts.height : *out_height;
  ------------------
  |  Branch (198:19): [True: 0, False: 39]
  ------------------
  199|     39|}
vo_kitty.c:set_out_params:
  202|     39|{
  203|     39|    struct priv *p = vo->priv;
  204|       |
  205|     39|    vo_get_src_dst_rects(vo, &p->src, &p->dst, &p->osd);
  206|       |
  207|     39|    p->width  = p->dst.x1 - p->dst.x0;
  208|     39|    p->height = p->dst.y1 - p->dst.y0;
  209|     39|    p->top  = p->opts.top > 0 ?
  ------------------
  |  Branch (209:15): [True: 0, False: 39]
  ------------------
  210|     39|        p->opts.top : p->rows * p->dst.y0 / vo->dheight;
  211|     39|    p->left = p->opts.left > 0 ?
  ------------------
  |  Branch (211:15): [True: 0, False: 39]
  ------------------
  212|     39|        p->opts.left : p->cols * p->dst.x0 / vo->dwidth;
  213|     39|    p->display_par = p->osd.display_par;
  214|       |
  215|     39|    p->buffer_size = 3 * p->width * p->height;
  216|     39|    p->output_size = AV_BASE64_SIZE(p->buffer_size);
  217|     39|}
vo_kitty.c:free_bufs:
  167|     78|{
  168|     78|    struct priv* p = vo->priv;
  169|       |
  170|     78|    talloc_free(p->frame);
  ------------------
  |  |   47|     78|#define talloc_free                     ta_free
  ------------------
  171|     78|    talloc_free(p->output);
  ------------------
  |  |   47|     78|#define talloc_free                     ta_free
  ------------------
  172|       |
  173|     78|    if (p->opts.use_shm) {
  ------------------
  |  Branch (173:9): [True: 0, False: 78]
  ------------------
  174|      0|        close_shm(p);
  175|       |#if HAVE_POSIX_SHM
  176|       |        if (p->shm_path)
  177|       |            shm_unlink(p->shm_path);
  178|       |#endif
  179|     78|    } else {
  180|     78|        talloc_free(p->buffer);
  ------------------
  |  |   47|     78|#define talloc_free                     ta_free
  ------------------
  181|     78|    }
  182|     78|}
vo_kitty.c:control:
  460|    666|{
  461|    666|    if (request == VOCTRL_SET_PANSCAN)
  ------------------
  |  Branch (461:9): [True: 0, False: 666]
  ------------------
  462|      0|        return (vo->config_ok && !reconfig(vo, vo->params)) ? VO_TRUE : VO_FALSE;
  ------------------
  |  |  148|      0|#define VO_TRUE         true
  ------------------
                      return (vo->config_ok && !reconfig(vo, vo->params)) ? VO_TRUE : VO_FALSE;
  ------------------
  |  |  149|      0|#define VO_FALSE        false
  ------------------
  |  Branch (462:17): [True: 0, False: 0]
  |  Branch (462:34): [True: 0, False: 0]
  ------------------
  463|    666|    return VO_NOTIMPL;
  ------------------
  |  |  152|    666|#define VO_NOTIMPL      -3
  ------------------
  464|    666|}
vo_kitty.c:draw_frame:
  294|     78|{
  295|     78|    struct priv *p = vo->priv;
  296|     78|    mp_image_t *mpi = NULL;
  297|       |
  298|       |#if !HAVE_POSIX
  299|       |    int prev_height = vo->dheight;
  300|       |    int prev_width = vo->dwidth;
  301|       |    get_win_size(vo, &p->rows, &p->cols, &vo->dwidth, &vo->dheight);
  302|       |    bool resized = (prev_width != vo->dwidth || prev_height != vo->dheight);
  303|       |#endif
  304|       |
  305|     78|    if (resized)
  ------------------
  |  Branch (305:9): [True: 0, False: 78]
  ------------------
  306|      0|        reconfig(vo, vo->params);
  307|       |
  308|     78|    resized = false;
  309|       |
  310|     78|    if (frame->current) {
  ------------------
  |  Branch (310:9): [True: 0, False: 78]
  ------------------
  311|      0|        mpi = mp_image_new_ref(frame->current);
  312|      0|        struct mp_rect src_rc = p->src;
  313|      0|        src_rc.x0 = MP_ALIGN_DOWN(src_rc.x0, mpi->fmt.align_x);
  ------------------
  |  |   53|      0|#define MP_ALIGN_DOWN(x, align) ((x) & ~((align) - 1))
  ------------------
  314|      0|        src_rc.y0 = MP_ALIGN_DOWN(src_rc.y0, mpi->fmt.align_y);
  ------------------
  |  |   53|      0|#define MP_ALIGN_DOWN(x, align) ((x) & ~((align) - 1))
  ------------------
  315|      0|        mp_image_crop_rc(mpi, src_rc);
  316|       |
  317|      0|        mp_sws_scale(p->sws, p->frame, mpi);
  318|     78|    } else {
  319|     78|        mp_image_clear(p->frame, 0, 0, p->width, p->height);
  320|     78|    }
  321|       |
  322|     78|    struct mp_osd_res res = { .w = p->width, .h = p->height, .display_par = p->display_par };
  323|     78|    osd_draw_on_image(vo->osd, res, mpi ? mpi->pts : 0, 0, p->frame);
  ------------------
  |  Branch (323:37): [True: 0, False: 78]
  ------------------
  324|       |
  325|       |
  326|     78|    if (p->opts.use_shm && !create_shm(vo))
  ------------------
  |  Branch (326:9): [True: 0, False: 78]
  |  Branch (326:28): [True: 0, False: 0]
  ------------------
  327|      0|        goto done;
  328|       |
  329|     78|    memcpy_pic(p->buffer, p->frame->planes[0], p->width * BYTES_PER_PX,
  ------------------
  |  |   45|     78|#define BYTES_PER_PX 3
  ------------------
  330|     78|               p->height, p->width * BYTES_PER_PX, p->frame->stride[0]);
  ------------------
  |  |   45|     78|#define BYTES_PER_PX 3
  ------------------
  331|       |
  332|     78|    if (!p->opts.use_shm)
  ------------------
  |  Branch (332:9): [True: 78, False: 0]
  ------------------
  333|     78|        av_base64_encode(p->output, p->output_size, p->buffer, p->buffer_size);
  334|       |
  335|     78|done:
  336|     78|    talloc_free(mpi);
  ------------------
  |  |   47|     78|#define talloc_free                     ta_free
  ------------------
  337|     78|    return VO_TRUE;
  ------------------
  |  |  148|     78|#define VO_TRUE         true
  ------------------
  338|     78|}
vo_kitty.c:flip_page:
  341|     78|{
  342|     78|    struct priv *p = vo->priv;
  343|     78|    if (!p->buffer)
  ------------------
  |  Branch (343:9): [True: 0, False: 78]
  ------------------
  344|      0|        return;
  345|       |
  346|     78|    p->cmd.len = 0;
  347|       |
  348|       |    // Start with ESC to position the cursor
  349|     78|    append_asprintf_passthrough(p, &p->cmd, TERM_ESC_GOTO_YX, p->top, p->left);
  ------------------
  |  |   28|     78|#define TERM_ESC_GOTO_YX            "\033[%d;%df"
  ------------------
  350|       |
  351|     78|    if (p->opts.use_shm) {
  ------------------
  |  Branch (351:9): [True: 0, False: 78]
  ------------------
  352|      0|        append_asprintf_passthrough(p, &p->cmd, KITTY_ESC_IMG_SHM,
  ------------------
  |  |   81|      0|#define KITTY_ESC_IMG_SHM    "\033_Ga=T,t=s,f=24,s=%d,v=%d,C=1,q=2,m=1;%s"
  ------------------
  353|      0|                                    p->width, p->height, p->shm_path_b64);
  354|      0|        append_passthrough(p, &p->cmd, KITTY_ESC_END);
  355|     78|    } else {
  356|     78|        if (!p->output) {
  ------------------
  |  Branch (356:13): [True: 0, False: 78]
  ------------------
  357|      0|            return;
  358|      0|        }
  359|       |
  360|     78|        append_asprintf_passthrough(p, &p->cmd, KITTY_ESC_IMG,
  ------------------
  |  |   80|     78|#define KITTY_ESC_IMG        "\033_Ga=T,f=24,s=%d,v=%d,C=1,q=2,m=1;"
  ------------------
  361|     78|                                    p->width, p->height);
  362|       |
  363|     78|        int output_size = p->output_size - 1;
  364|     78|        int offset = 0;
  365|       |
  366|  4.52k|        for (; offset < output_size; ) {
  ------------------
  |  Branch (366:16): [True: 4.44k, False: 78]
  ------------------
  367|  4.44k|            int chunk = MPMIN(4096, output_size - offset);
  ------------------
  |  |   44|  4.44k|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 78, False: 4.36k]
  |  |  ------------------
  ------------------
  368|       |
  369|  4.44k|            if (offset > 0)
  ------------------
  |  Branch (369:17): [True: 4.36k, False: 78]
  ------------------
  370|  4.36k|                append_asprintf_passthrough(p, &p->cmd, KITTY_ESC_CONTINUE,
  ------------------
  |  |   82|  4.36k|#define KITTY_ESC_CONTINUE   "\033_Gm=%d;"
  ------------------
  371|  4.36k|                                            offset + chunk < output_size);
  372|       |
  373|       |            // Append at max chunk bytes
  374|  4.44k|            bstr_xappend(p, &p->cmd, (bstr){p->output + offset, chunk});
  375|  4.44k|            append_passthrough(p, &p->cmd, KITTY_ESC_END);
  376|  4.44k|            offset += chunk;
  377|  4.44k|        }
  378|       |
  379|       |        // When the data is less than or equal to chunk size the final packet
  380|       |        // isn't sent, i.e. an escape sequence with `m=0`.
  381|       |        // This ensures that an escape sequence with `m=0` is sent and
  382|       |        // terminals stay happy
  383|     78|        if (offset == 0) {
  ------------------
  |  Branch (383:13): [True: 0, False: 78]
  ------------------
  384|      0|            append_asprintf_passthrough(p, &p->cmd, KITTY_ESC_CONTINUE, 0);
  ------------------
  |  |   82|      0|#define KITTY_ESC_CONTINUE   "\033_Gm=%d;"
  ------------------
  385|      0|            append_passthrough(p, &p->cmd, KITTY_ESC_END);
  386|      0|        }
  387|     78|    }
  388|       |
  389|     78|    write_bstr(p->cmd);
  390|       |
  391|     78|#if HAVE_POSIX
  392|     78|    if (p->opts.use_shm)
  ------------------
  |  Branch (392:9): [True: 0, False: 78]
  ------------------
  393|      0|        close_shm(p);
  394|     78|#endif
  395|     78|}
vo_kitty.c:append_asprintf_passthrough:
  141|  4.52k|{
  142|  4.52k|    bstr_xappend(p, bs, p->dcs_prefix);
  143|       |
  144|  4.52k|    va_list ap;
  145|  4.52k|    va_start(ap, fmt);
  146|  4.52k|    bstr_xappend_vasprintf(p, bs, fmt, ap);
  147|  4.52k|    va_end(ap);
  148|       |
  149|  4.52k|    bstr_xappend(p, bs, p->dcs_suffix);
  150|  4.52k|}
vo_kitty.c:append_passthrough:
  132|  4.44k|{
  133|  4.44k|    bstr_xappend(p, bs, p->dcs_prefix);
  134|  4.44k|    bstr_xappend(p, bs, append);
  135|  4.44k|    bstr_xappend(p, bs, p->dcs_suffix);
  136|  4.44k|}
vo_kitty.c:uninit:
  467|     39|{
  468|     39|    struct priv *p = vo->priv;
  469|       |
  470|     39|#if HAVE_POSIX
  471|     39|    sigaction(SIGWINCH, &saved_sigaction, NULL);
  472|     39|#endif
  473|       |
  474|     39|    write_bstr_passthrough(p, KITTY_ESC_DELETE_ALL);
  475|       |
  476|     39|    write_str(TERM_ESC_RESTORE_CURSOR);
  ------------------
  |  |   30|     39|#define TERM_ESC_RESTORE_CURSOR     "\033[?25h"
  ------------------
  477|     39|    terminal_set_mouse_input(false);
  478|       |
  479|     39|    if (p->opts.alt_screen) {
  ------------------
  |  Branch (479:9): [True: 39, False: 0]
  ------------------
  480|     39|        write_str(TERM_ESC_NORMAL_SCREEN);
  ------------------
  |  |   36|     39|#define TERM_ESC_NORMAL_SCREEN      "\033[?1049l"
  ------------------
  481|     39|    } else {
  482|      0|        char *cmd = talloc_asprintf(vo, TERM_ESC_GOTO_YX, p->cols, 0);
  ------------------
  |  |   52|      0|#define talloc_asprintf                 ta_xasprintf
  |  |  ------------------
  |  |  |  |  127|      0|#define ta_xasprintf(...)               ta_oom_s(ta_asprintf(__VA_ARGS__))
  |  |  ------------------
  ------------------
  483|      0|        write_str(cmd);
  484|      0|    }
  485|       |
  486|     39|    free_bufs(vo);
  487|     39|}

vo_libmpv.c:preinit:
  712|     12|{
  713|       |#if HAVE_MACOS_COCOA_CB
  714|       |    cocoa_init_cocoa_cb();
  715|       |#else
  716|     12|    if (vo->probing)
  ------------------
  |  Branch (716:9): [True: 11, False: 1]
  ------------------
  717|     11|        return -1;
  718|      1|#endif
  719|       |
  720|      1|    struct vo_priv *p = vo->priv;
  721|       |
  722|      1|    struct mpv_render_context *ctx =
  723|      1|        mp_client_api_acquire_render_context(vo->global->client_api);
  724|      1|    p->ctx = ctx;
  725|       |
  726|      1|    if (!ctx) {
  ------------------
  |  Branch (726:9): [True: 1, False: 0]
  ------------------
  727|      1|        if (!vo->probing)
  ------------------
  |  Branch (727:13): [True: 1, False: 0]
  ------------------
  728|      1|            MP_FATAL(vo, "No render context set.\n");
  ------------------
  |  |   84|      1|#define MP_FATAL(obj, ...)      MP_MSG(obj, MSGL_FATAL, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      1|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  729|      1|        return -1;
  730|      1|    }
  731|       |
  732|      0|    mp_mutex_lock(&ctx->lock);
  ------------------
  |  |  131|      0|#define mp_mutex_lock       pthread_mutex_lock
  ------------------
  733|      0|    ctx->vo = vo;
  734|      0|    ctx->need_resize = true;
  735|      0|    ctx->need_update_external = true;
  736|      0|    mp_mutex_unlock(&ctx->lock);
  ------------------
  |  |  133|      0|#define mp_mutex_unlock     pthread_mutex_unlock
  ------------------
  737|       |
  738|      0|    vo->hwdec_devs = ctx->hwdec_devs;
  739|      0|    control(vo, VOCTRL_PREINIT, NULL);
  740|       |
  741|      0|    return 0;
  742|      1|}

repack_line:
  874|  21.4k|{
  875|  21.4k|    mp_assert(rp->configured);
  ------------------
  |  |   41|  21.4k|#define mp_assert assert
  ------------------
  876|       |
  877|  21.4k|    struct repack_step *first = &rp->steps[0];
  878|  21.4k|    struct repack_step *last = &rp->steps[rp->num_steps - 1];
  879|       |
  880|  21.4k|    mp_assert(dst_x >= 0 && dst_y >= 0 && src_x >= 0 && src_y >= 0 && w >= 0);
  ------------------
  |  |   41|  21.4k|#define mp_assert assert
  ------------------
  881|  21.4k|    mp_assert(dst_x + w <= MP_ALIGN_UP(last->buf[1]->w, last->fmt[1].align_x));
  ------------------
  |  |   41|  21.4k|#define mp_assert assert
  ------------------
  882|  21.4k|    mp_assert(src_x + w <= MP_ALIGN_UP(first->buf[0]->w, first->fmt[0].align_x));
  ------------------
  |  |   41|  21.4k|#define mp_assert assert
  ------------------
  883|  21.4k|    mp_assert(dst_y < last->buf[1]->h);
  ------------------
  |  |   41|  21.4k|#define mp_assert assert
  ------------------
  884|  21.4k|    mp_assert(src_y < first->buf[0]->h);
  ------------------
  |  |   41|  21.4k|#define mp_assert assert
  ------------------
  885|  21.4k|    mp_assert(!(dst_x & (last->fmt[1].align_x - 1)));
  ------------------
  |  |   41|  21.4k|#define mp_assert assert
  ------------------
  886|  21.4k|    mp_assert(!(src_x & (first->fmt[0].align_x - 1)));
  ------------------
  |  |   41|  21.4k|#define mp_assert assert
  ------------------
  887|  21.4k|    mp_assert(!(w & ((1 << first->fmt[0].chroma_xs) - 1)));
  ------------------
  |  |   41|  21.4k|#define mp_assert assert
  ------------------
  888|  21.4k|    mp_assert(!(dst_y & (last->fmt[1].align_y - 1)));
  ------------------
  |  |   41|  21.4k|#define mp_assert assert
  ------------------
  889|  21.4k|    mp_assert(!(src_y & (first->fmt[0].align_y - 1)));
  ------------------
  |  |   41|  21.4k|#define mp_assert assert
  ------------------
  890|       |
  891|  42.9k|    for (int n = 0; n < rp->num_steps; n++) {
  ------------------
  |  Branch (891:21): [True: 21.4k, False: 21.4k]
  ------------------
  892|  21.4k|        struct repack_step *rs = &rp->steps[n];
  893|       |
  894|       |        // When writing to temporary buffers, always write to the start (maybe
  895|       |        // helps with locality).
  896|  21.4k|        int sx = rs->user_buf[0] ? src_x : 0;
  ------------------
  |  Branch (896:18): [True: 21.4k, False: 0]
  ------------------
  897|  21.4k|        int sy = rs->user_buf[0] ? src_y : 0;
  ------------------
  |  Branch (897:18): [True: 21.4k, False: 0]
  ------------------
  898|  21.4k|        int dx = rs->user_buf[1] ? dst_x : 0;
  ------------------
  |  Branch (898:18): [True: 21.4k, False: 0]
  ------------------
  899|  21.4k|        int dy = rs->user_buf[1] ? dst_y : 0;
  ------------------
  |  Branch (899:18): [True: 21.4k, False: 0]
  ------------------
  900|       |
  901|  21.4k|        struct mp_image *buf_a = rs->buf[rp->pack];
  902|  21.4k|        struct mp_image *buf_b = rs->buf[!rp->pack];
  903|  21.4k|        int a_x = rp->pack ? dx : sx;
  ------------------
  |  Branch (903:19): [True: 7.15k, False: 14.3k]
  ------------------
  904|  21.4k|        int a_y = rp->pack ? dy : sy;
  ------------------
  |  Branch (904:19): [True: 7.15k, False: 14.3k]
  ------------------
  905|  21.4k|        int b_x = rp->pack ? sx : dx;
  ------------------
  |  Branch (905:19): [True: 7.15k, False: 14.3k]
  ------------------
  906|  21.4k|        int b_y = rp->pack ? sy : dy;
  ------------------
  |  Branch (906:19): [True: 7.15k, False: 14.3k]
  ------------------
  907|       |
  908|  21.4k|        switch (rs->type) {
  ------------------
  |  Branch (908:17): [True: 0, False: 21.4k]
  ------------------
  909|  21.4k|        case REPACK_STEP_REPACK: {
  ------------------
  |  Branch (909:9): [True: 21.4k, False: 0]
  ------------------
  910|  21.4k|            if (rp->repack)
  ------------------
  |  Branch (910:17): [True: 21.4k, False: 0]
  ------------------
  911|  21.4k|                rp->repack(rp, buf_a, a_x, a_y, buf_b, b_x, b_y, w);
  912|       |
  913|  57.2k|            for (int p = 0; p < rs->fmt[0].num_planes; p++) {
  ------------------
  |  Branch (913:29): [True: 35.7k, False: 21.4k]
  ------------------
  914|  35.7k|                if (rp->copy_buf[p])
  ------------------
  |  Branch (914:21): [True: 0, False: 35.7k]
  ------------------
  915|      0|                    copy_plane(rs->buf[1], dx, dy, rs->buf[0], sx, sy, w, p);
  916|  35.7k|            }
  917|  21.4k|            break;
  918|      0|        }
  919|      0|        case REPACK_STEP_ENDIAN:
  ------------------
  |  Branch (919:9): [True: 0, False: 21.4k]
  ------------------
  920|      0|            swap_endian(rs->buf[1], dx, dy, rs->buf[0], sx, sy, w,
  921|      0|                        rp->endian_size);
  922|      0|            break;
  923|      0|        case REPACK_STEP_FLOAT:
  ------------------
  |  Branch (923:9): [True: 0, False: 21.4k]
  ------------------
  924|      0|            repack_float(rp, buf_a, a_x, a_y, buf_b, b_x, b_y, w);
  925|      0|            break;
  926|  21.4k|        }
  927|  21.4k|    }
  928|  21.4k|}
mp_repack_create_planar:
 1063|    180|{
 1064|    180|    struct mp_repack *rp = talloc_zero(NULL, struct mp_repack);
  ------------------
  |  |   27|    180|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|    180|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|    180|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1065|    180|    rp->imgfmt_user = imgfmt;
 1066|    180|    rp->pack = pack;
 1067|    180|    rp->flags = flags;
 1068|       |
 1069|    180|    if (!setup_format(rp)) {
  ------------------
  |  Branch (1069:9): [True: 0, False: 180]
  ------------------
 1070|      0|        talloc_free(rp);
  ------------------
  |  |   47|      0|#define talloc_free                     ta_free
  ------------------
 1071|      0|        return NULL;
 1072|      0|    }
 1073|       |
 1074|    180|    return rp;
 1075|    180|}
mp_repack_get_format_src:
 1078|     60|{
 1079|     60|    return rp->steps[0].fmt[0].id;
 1080|     60|}
mp_repack_get_format_dst:
 1083|    240|{
 1084|    240|    return rp->steps[rp->num_steps - 1].fmt[1].id;
 1085|    240|}
mp_repack_get_align_x:
 1088|    120|{
 1089|       |    // We really want the LCM between those, but since only one of them is
 1090|       |    // packed (or they're the same format), and the chroma subsampling is the
 1091|       |    // same for both, only the packed one matters.
 1092|    120|    return rp->fmt_a.align_x;
 1093|    120|}
mp_repack_get_align_y:
 1096|    120|{
 1097|    120|    return rp->fmt_a.align_y; // should be the same for packed/planar formats
 1098|    120|}
repack_config_buffers:
 1112|    180|{
 1113|    180|    struct repack_step *rs_first = &rp->steps[0];
 1114|    180|    struct repack_step *rs_last = &rp->steps[rp->num_steps - 1];
 1115|       |
 1116|    180|    rp->configured = false;
 1117|       |
 1118|    180|    mp_assert(dst && src);
  ------------------
  |  |   41|    180|#define mp_assert assert
  ------------------
 1119|       |
 1120|    180|    int buf_w = MPMAX(dst->w, src->w);
  ------------------
  |  |   43|    180|#define MPMAX(a, b) ((a) > (b) ? (a) : (b))
  |  |  ------------------
  |  |  |  Branch (43:22): [True: 60, False: 120]
  |  |  ------------------
  ------------------
 1121|       |
 1122|    180|    mp_assert(dst->imgfmt == rs_last->fmt[1].id);
  ------------------
  |  |   41|    180|#define mp_assert assert
  ------------------
 1123|    180|    mp_assert(src->imgfmt == rs_first->fmt[0].id);
  ------------------
  |  |   41|    180|#define mp_assert assert
  ------------------
 1124|       |
 1125|       |    // Chain/allocate buffers.
 1126|       |
 1127|    360|    for (int n = 0; n < rp->num_steps; n++)
  ------------------
  |  Branch (1127:21): [True: 180, False: 180]
  ------------------
 1128|    180|        rp->steps[n].buf[0] = rp->steps[n].buf[1] = NULL;
 1129|       |
 1130|    180|    rs_first->buf[0] = src;
 1131|    180|    rs_last->buf[1] = dst;
 1132|       |
 1133|    360|    for (int n = 0; n < rp->num_steps; n++) {
  ------------------
  |  Branch (1133:21): [True: 180, False: 180]
  ------------------
 1134|    180|        struct repack_step *rs = &rp->steps[n];
 1135|       |
 1136|    180|        if (!rs->buf[0]) {
  ------------------
  |  Branch (1136:13): [True: 0, False: 180]
  ------------------
 1137|      0|            mp_assert(n > 0);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
 1138|      0|            rs->buf[0] = rp->steps[n - 1].buf[1];
 1139|      0|        }
 1140|       |
 1141|    180|        if (rs->buf[1])
  ------------------
  |  Branch (1141:13): [True: 180, False: 0]
  ------------------
 1142|    180|            continue;
 1143|       |
 1144|       |        // Note: since repack_line() can have different src/dst offsets, we
 1145|       |        //       can't do true in-place in general.
 1146|      0|        bool can_inplace = rs->type == REPACK_STEP_ENDIAN &&
  ------------------
  |  Branch (1146:28): [True: 0, False: 0]
  ------------------
 1147|      0|                           rs->buf[0] != src && rs->buf[0] != dst;
  ------------------
  |  Branch (1147:28): [True: 0, False: 0]
  |  Branch (1147:49): [True: 0, False: 0]
  ------------------
 1148|      0|        if (can_inplace) {
  ------------------
  |  Branch (1148:13): [True: 0, False: 0]
  ------------------
 1149|      0|            rs->buf[1] = rs->buf[0];
 1150|      0|            continue;
 1151|      0|        }
 1152|       |
 1153|      0|        if (rs != rs_last) {
  ------------------
  |  Branch (1153:13): [True: 0, False: 0]
  ------------------
 1154|      0|            struct repack_step *next = &rp->steps[n + 1];
 1155|      0|            if (next->buf[0]) {
  ------------------
  |  Branch (1155:17): [True: 0, False: 0]
  ------------------
 1156|      0|                rs->buf[1] = next->buf[0];
 1157|      0|                continue;
 1158|      0|            }
 1159|      0|        }
 1160|       |
 1161|      0|        image_realloc(&rs->tmp, rs->fmt[1].id, buf_w, rs->fmt[1].align_y);
 1162|      0|        if (!rs->tmp)
  ------------------
  |  Branch (1162:13): [True: 0, False: 0]
  ------------------
 1163|      0|            return false;
 1164|      0|        talloc_steal(rp, rs->tmp);
  ------------------
  |  |   38|      0|#define talloc_steal                    ta_steal
  |  |  ------------------
  |  |  |  |  100|      0|#define ta_steal(ta_parent, ptr) (TA_TYPEOF(ptr))ta_steal_(ta_parent, ptr)
  |  |  ------------------
  ------------------
 1165|      0|        rs->buf[1] = rs->tmp;
 1166|      0|    }
 1167|       |
 1168|    360|    for (int n = 0; n < rp->num_steps; n++) {
  ------------------
  |  Branch (1168:21): [True: 180, False: 180]
  ------------------
 1169|    180|        struct repack_step *rs = &rp->steps[n];
 1170|    180|        rs->user_buf[0] = rs->buf[0] == src || rs->buf[0] == dst;
  ------------------
  |  Branch (1170:27): [True: 180, False: 0]
  |  Branch (1170:48): [True: 0, False: 0]
  ------------------
 1171|    180|        rs->user_buf[1] = rs->buf[1] == src || rs->buf[1] == dst;
  ------------------
  |  Branch (1171:27): [True: 0, False: 180]
  |  Branch (1171:48): [True: 180, False: 0]
  ------------------
 1172|    180|    }
 1173|       |
 1174|       |    // If repacking is the only operation. It's also responsible for simply
 1175|       |    // copying src to dst if absolutely no filtering is done.
 1176|    180|    bool may_passthrough =
 1177|    180|        rp->num_steps == 1 && rp->steps[0].type == REPACK_STEP_REPACK;
  ------------------
  |  Branch (1177:9): [True: 180, False: 0]
  |  Branch (1177:31): [True: 180, False: 0]
  ------------------
 1178|       |
 1179|    780|    for (int p = 0; p < rp->fmt_b.num_planes; p++) {
  ------------------
  |  Branch (1179:21): [True: 600, False: 180]
  ------------------
 1180|       |        // (All repack callbacks copy, except nv12 does not copy luma.)
 1181|    600|        bool repack_copies_plane = rp->repack && !(rp->passthrough_y && p == 0);
  ------------------
  |  Branch (1181:36): [True: 600, False: 0]
  |  Branch (1181:52): [True: 0, False: 600]
  |  Branch (1181:73): [True: 0, False: 0]
  ------------------
 1182|       |
 1183|    600|        bool can_pt = may_passthrough && !repack_copies_plane &&
  ------------------
  |  Branch (1183:23): [True: 600, False: 0]
  |  Branch (1183:42): [True: 0, False: 600]
  ------------------
 1184|    600|                      enable_passthrough && enable_passthrough[p];
  ------------------
  |  Branch (1184:23): [True: 0, False: 0]
  |  Branch (1184:45): [True: 0, False: 0]
  ------------------
 1185|       |
 1186|       |        // Copy if needed, unless the repack callback does it anyway.
 1187|    600|        rp->copy_buf[p] = !repack_copies_plane && !can_pt;
  ------------------
  |  Branch (1187:27): [True: 0, False: 600]
  |  Branch (1187:51): [True: 0, False: 0]
  ------------------
 1188|       |
 1189|    600|        if (enable_passthrough)
  ------------------
  |  Branch (1189:13): [True: 0, False: 600]
  ------------------
 1190|      0|            enable_passthrough[p] = can_pt && !rp->copy_buf[p];
  ------------------
  |  Branch (1190:37): [True: 0, False: 0]
  |  Branch (1190:47): [True: 0, False: 0]
  ------------------
 1191|    600|    }
 1192|       |
 1193|    180|    if (enable_passthrough) {
  ------------------
  |  Branch (1193:9): [True: 0, False: 180]
  ------------------
 1194|      0|        for (int n = rp->fmt_b.num_planes; n < MP_MAX_PLANES; n++)
  ------------------
  |  |   28|      0|#define MP_MAX_PLANES 4
  ------------------
  |  Branch (1194:44): [True: 0, False: 0]
  ------------------
 1195|      0|            enable_passthrough[n] = false;
 1196|      0|    }
 1197|       |
 1198|    180|    update_repack_float(rp);
 1199|       |
 1200|    180|    rp->configured = true;
 1201|       |
 1202|    180|    return true;
 1203|    180|}
repack.c:setup_format:
 1051|    180|{
 1052|    180|    reset_params(rp);
 1053|    180|    rp->imgfmt_a = rp->imgfmt_user;
 1054|    180|    if (setup_format_ne(rp))
  ------------------
  |  Branch (1054:9): [True: 180, False: 0]
  ------------------
 1055|    180|        return true;
 1056|       |    // Try reverse endian.
 1057|      0|    reset_params(rp);
 1058|      0|    rp->imgfmt_a = mp_find_other_endian(rp->imgfmt_user);
 1059|      0|    return rp->imgfmt_a && setup_format_ne(rp);
  ------------------
  |  Branch (1059:12): [True: 0, False: 0]
  |  Branch (1059:28): [True: 0, False: 0]
  ------------------
 1060|    180|}
repack.c:reset_params:
 1038|    180|{
 1039|    180|    rp->num_steps = 0;
 1040|    180|    rp->imgfmt_b = 0;
 1041|    180|    rp->repack = NULL;
 1042|    180|    rp->passthrough_y = false;
 1043|    180|    rp->endian_size = 0;
 1044|    180|    rp->packed_repack_scanline = NULL;
 1045|    180|    rp->comp_size = 0;
 1046|    180|    talloc_free(rp->comp_lut);
  ------------------
  |  |   47|    180|#define talloc_free                     ta_free
  ------------------
 1047|    180|    rp->comp_lut = NULL;
 1048|    180|}
repack.c:setup_format_ne:
  931|    180|{
  932|    180|    if (!rp->imgfmt_b)
  ------------------
  |  Branch (932:9): [True: 180, False: 0]
  ------------------
  933|    180|        setup_nv_packer(rp);
  934|    180|    if (!rp->imgfmt_b)
  ------------------
  |  Branch (934:9): [True: 180, False: 0]
  ------------------
  935|    180|        setup_misc_packer(rp);
  936|    180|    if (!rp->imgfmt_b)
  ------------------
  |  Branch (936:9): [True: 180, False: 0]
  ------------------
  937|    180|        setup_packed_packer(rp);
  938|    180|    if (!rp->imgfmt_b)
  ------------------
  |  Branch (938:9): [True: 0, False: 180]
  ------------------
  939|      0|        setup_fringe_rgb_packer(rp);
  940|    180|    if (!rp->imgfmt_b)
  ------------------
  |  Branch (940:9): [True: 0, False: 180]
  ------------------
  941|      0|        setup_fringe_yuv_packer(rp);
  942|    180|    if (!rp->imgfmt_b)
  ------------------
  |  Branch (942:9): [True: 0, False: 180]
  ------------------
  943|      0|        rp->imgfmt_b = rp->imgfmt_a; // maybe it was planar after all
  944|       |
  945|    180|    struct mp_regular_imgfmt desc;
  946|    180|    if (!mp_get_regular_imgfmt(&desc, rp->imgfmt_b))
  ------------------
  |  Branch (946:9): [True: 0, False: 180]
  ------------------
  947|      0|        return false;
  948|       |
  949|       |    // no weird stuff
  950|    180|    if (desc.num_planes > 4)
  ------------------
  |  Branch (950:9): [True: 0, False: 180]
  ------------------
  951|      0|        return false;
  952|       |
  953|       |    // Endian swapping.
  954|    180|    if (rp->imgfmt_a != rp->imgfmt_user &&
  ------------------
  |  Branch (954:9): [True: 0, False: 180]
  ------------------
  955|    180|        rp->imgfmt_a == mp_find_other_endian(rp->imgfmt_user))
  ------------------
  |  Branch (955:9): [True: 0, False: 0]
  ------------------
  956|      0|    {
  957|      0|        struct mp_imgfmt_desc desc_a = mp_imgfmt_get_desc(rp->imgfmt_a);
  958|      0|        struct mp_imgfmt_desc desc_u = mp_imgfmt_get_desc(rp->imgfmt_user);
  959|      0|        rp->endian_size = 1 << desc_u.endian_shift;
  960|      0|        if (!desc_a.endian_shift && rp->endian_size != 2 && rp->endian_size != 4)
  ------------------
  |  Branch (960:13): [True: 0, False: 0]
  |  Branch (960:37): [True: 0, False: 0]
  |  Branch (960:61): [True: 0, False: 0]
  ------------------
  961|      0|            return false;
  962|      0|    }
  963|       |
  964|       |    // Accept only true planar formats (with known components and no padding).
  965|    780|    for (int n = 0; n < desc.num_planes; n++) {
  ------------------
  |  Branch (965:21): [True: 600, False: 180]
  ------------------
  966|    600|        if (desc.planes[n].num_components != 1)
  ------------------
  |  Branch (966:13): [True: 0, False: 600]
  ------------------
  967|      0|            return false;
  968|    600|        int c = desc.planes[n].components[0];
  969|    600|        if (c < 1 || c > 4)
  ------------------
  |  Branch (969:13): [True: 0, False: 600]
  |  Branch (969:22): [True: 0, False: 600]
  ------------------
  970|      0|            return false;
  971|    600|    }
  972|       |
  973|    180|    rp->fmt_a = mp_imgfmt_get_desc(rp->imgfmt_a);
  974|    180|    rp->fmt_b = mp_imgfmt_get_desc(rp->imgfmt_b);
  975|       |
  976|       |    // This is if we did a pack step.
  977|       |
  978|    180|    if (rp->flags & REPACK_CREATE_PLANAR_F32) {
  ------------------
  |  Branch (978:9): [True: 0, False: 180]
  ------------------
  979|       |        // imgfmt_b with float32 component type.
  980|      0|        struct mp_regular_imgfmt fdesc = desc;
  981|      0|        fdesc.component_type = MP_COMPONENT_TYPE_FLOAT;
  982|      0|        fdesc.component_size = 4;
  983|      0|        fdesc.component_pad = 0;
  984|      0|        int ffmt = mp_find_regular_imgfmt(&fdesc);
  985|      0|        if (!ffmt)
  ------------------
  |  Branch (985:13): [True: 0, False: 0]
  ------------------
  986|      0|            return false;
  987|      0|        if (ffmt != rp->imgfmt_b) {
  ------------------
  |  Branch (987:13): [True: 0, False: 0]
  ------------------
  988|      0|            if (desc.component_type != MP_COMPONENT_TYPE_UINT ||
  ------------------
  |  Branch (988:17): [True: 0, False: 0]
  ------------------
  989|      0|                (desc.component_size != 1 && desc.component_size != 2))
  ------------------
  |  Branch (989:18): [True: 0, False: 0]
  |  Branch (989:46): [True: 0, False: 0]
  ------------------
  990|      0|                return false;
  991|      0|            rp->f32_comp_size = desc.component_size;
  992|      0|            rp->f32_csp_space = PL_COLOR_SYSTEM_COUNT;
  993|      0|            rp->f32_csp_levels = PL_COLOR_LEVELS_COUNT;
  994|      0|            rp->steps[rp->num_steps++] = (struct repack_step) {
  995|      0|                .type = REPACK_STEP_FLOAT,
  996|      0|                .fmt = {
  997|      0|                    mp_imgfmt_get_desc(ffmt),
  998|      0|                    rp->fmt_b,
  999|      0|                },
 1000|      0|            };
 1001|      0|        }
 1002|      0|    }
 1003|       |
 1004|    180|    rp->steps[rp->num_steps++] = (struct repack_step) {
 1005|    180|        .type = REPACK_STEP_REPACK,
 1006|    180|        .fmt = { rp->fmt_b, rp->fmt_a },
 1007|    180|    };
 1008|       |
 1009|    180|    if (rp->endian_size) {
  ------------------
  |  Branch (1009:9): [True: 0, False: 180]
  ------------------
 1010|      0|        rp->steps[rp->num_steps++] = (struct repack_step) {
 1011|      0|            .type = REPACK_STEP_ENDIAN,
 1012|      0|            .fmt = {
 1013|      0|                rp->fmt_a,
 1014|      0|                mp_imgfmt_get_desc(rp->imgfmt_user),
 1015|      0|            },
 1016|      0|        };
 1017|      0|    }
 1018|       |
 1019|       |    // Reverse if unpack (to reflect actual data flow)
 1020|    180|    if (!rp->pack) {
  ------------------
  |  Branch (1020:9): [True: 120, False: 60]
  ------------------
 1021|    120|        for (int n = 0; n < rp->num_steps / 2; n++) {
  ------------------
  |  Branch (1021:25): [True: 0, False: 120]
  ------------------
 1022|      0|            MPSWAP(struct repack_step, rp->steps[n],
  ------------------
  |  |   47|      0|    do { type SWAP_tmp = b; b = a; a = SWAP_tmp; } while (0)
  |  |  ------------------
  |  |  |  Branch (47:59): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1023|      0|                   rp->steps[rp->num_steps - 1 - n]);
 1024|      0|        }
 1025|    240|        for (int n = 0; n < rp->num_steps; n++) {
  ------------------
  |  Branch (1025:25): [True: 120, False: 120]
  ------------------
 1026|    120|            struct repack_step *rs = &rp->steps[n];
 1027|    120|            MPSWAP(struct mp_imgfmt_desc, rs->fmt[0], rs->fmt[1]);
  ------------------
  |  |   47|    120|    do { type SWAP_tmp = b; b = a; a = SWAP_tmp; } while (0)
  |  |  ------------------
  |  |  |  Branch (47:59): [Folded - Ignored]
  |  |  ------------------
  ------------------
 1028|    120|        }
 1029|    120|    }
 1030|       |
 1031|    180|    for (int n = 0; n < rp->num_steps - 1; n++)
  ------------------
  |  Branch (1031:21): [True: 0, False: 180]
  ------------------
 1032|    180|        mp_assert(rp->steps[n].fmt[1].id == rp->steps[n + 1].fmt[0].id);
  ------------------
  |  |   41|    180|#define mp_assert assert
  ------------------
 1033|       |
 1034|    180|    return true;
 1035|    180|}
repack.c:setup_nv_packer:
  739|    180|{
  740|    180|    struct mp_regular_imgfmt desc;
  741|    180|    if (!mp_get_regular_imgfmt(&desc, rp->imgfmt_a))
  ------------------
  |  Branch (741:9): [True: 0, False: 180]
  ------------------
  742|      0|        return;
  743|       |
  744|       |    // Check for NV.
  745|    180|    if (desc.num_planes != 2)
  ------------------
  |  Branch (745:9): [True: 180, False: 0]
  ------------------
  746|    180|        return;
  747|      0|    if (desc.planes[0].num_components != 1 || desc.planes[0].components[0] != 1)
  ------------------
  |  Branch (747:9): [True: 0, False: 0]
  |  Branch (747:47): [True: 0, False: 0]
  ------------------
  748|      0|        return;
  749|      0|    if (desc.planes[1].num_components != 2)
  ------------------
  |  Branch (749:9): [True: 0, False: 0]
  ------------------
  750|      0|        return;
  751|      0|    int cr0 = desc.planes[1].components[0];
  752|      0|    int cr1 = desc.planes[1].components[1];
  753|      0|    if (cr0 > cr1)
  ------------------
  |  Branch (753:9): [True: 0, False: 0]
  ------------------
  754|      0|        MPSWAP(int, cr0, cr1);
  ------------------
  |  |   47|      0|    do { type SWAP_tmp = b; b = a; a = SWAP_tmp; } while (0)
  |  |  ------------------
  |  |  |  Branch (47:59): [Folded - Ignored]
  |  |  ------------------
  ------------------
  755|      0|    if (cr0 != 2 || cr1 != 3)
  ------------------
  |  Branch (755:9): [True: 0, False: 0]
  |  Branch (755:21): [True: 0, False: 0]
  ------------------
  756|      0|        return;
  757|       |
  758|       |    // Construct equivalent planar format.
  759|      0|    struct mp_regular_imgfmt desc2 = desc;
  760|      0|    desc2.num_planes = 3;
  761|      0|    desc2.planes[1].num_components = 1;
  762|      0|    desc2.planes[1].components[0] = 2;
  763|      0|    desc2.planes[2].num_components = 1;
  764|      0|    desc2.planes[2].components[0] = 3;
  765|       |    // For P010. Strangely this concept exists only for the NV format.
  766|      0|    if (desc2.component_pad > 0)
  ------------------
  |  Branch (766:9): [True: 0, False: 0]
  ------------------
  767|      0|        desc2.component_pad = 0;
  768|       |
  769|      0|    int planar_fmt = mp_find_regular_imgfmt(&desc2);
  770|      0|    if (!planar_fmt)
  ------------------
  |  Branch (770:9): [True: 0, False: 0]
  ------------------
  771|      0|        return;
  772|       |
  773|      0|    for (int i = 0; i < MP_ARRAY_SIZE(regular_repackers); i++) {
  ------------------
  |  |   48|      0|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (773:21): [True: 0, False: 0]
  ------------------
  774|      0|        const struct regular_repacker *pa = &regular_repackers[i];
  775|       |
  776|      0|        void (*repack_cb)(void *restrict pa, void *restrict pb[], int w) =
  777|      0|            rp->pack ? pa->pa_scanline : pa->un_scanline;
  ------------------
  |  Branch (777:13): [True: 0, False: 0]
  ------------------
  778|       |
  779|      0|        if (pa->packed_width != desc.component_size * 2 * 8 ||
  ------------------
  |  Branch (779:13): [True: 0, False: 0]
  ------------------
  780|      0|            pa->component_width != desc.component_size * 8 ||
  ------------------
  |  Branch (780:13): [True: 0, False: 0]
  ------------------
  781|      0|            pa->num_components != 2 ||
  ------------------
  |  Branch (781:13): [True: 0, False: 0]
  ------------------
  782|      0|            pa->prepadding != 0 ||
  ------------------
  |  Branch (782:13): [True: 0, False: 0]
  ------------------
  783|      0|            !repack_cb)
  ------------------
  |  Branch (783:13): [True: 0, False: 0]
  ------------------
  784|      0|            continue;
  785|       |
  786|      0|        rp->repack = repack_nv;
  787|      0|        rp->passthrough_y = true;
  788|      0|        rp->packed_repack_scanline = repack_cb;
  789|      0|        rp->imgfmt_b = planar_fmt;
  790|      0|        rp->components[0] = desc.planes[1].components[0] - 1;
  791|      0|        rp->components[1] = desc.planes[1].components[1] - 1;
  792|      0|        return;
  793|      0|    }
  794|      0|}
repack.c:un_cccc8:
  205|  7.15k|    static void name(void *restrict src, void *restrict dst[], int w) {     \
  206|   242k|        for (int x = 0; x < w; x++) {                                       \
  ------------------
  |  Branch (206:25): [True: 235k, False: 7.15k]
  ------------------
  207|   235k|            packed_t c = ((packed_t *)src)[x];                              \
  208|   235k|            ((plane_t *)dst[0])[x] = (c >> (sh_c0)) & (mask);               \
  209|   235k|            ((plane_t *)dst[1])[x] = (c >> (sh_c1)) & (mask);               \
  210|   235k|            ((plane_t *)dst[2])[x] = (c >> (sh_c2)) & (mask);               \
  211|   235k|            ((plane_t *)dst[3])[x] = (c >> (sh_c3)) & (mask);               \
  212|   235k|        }                                                                   \
  213|  7.15k|    }
repack.c:pa_ccc8:
  275|  7.15k|    static void name(void *restrict dst, void *restrict src[], int w) {     \
  276|  7.15k|        comp_t *r = dst;                                                    \
  277|   242k|        for (int x = 0; x < w; x++) {                                       \
  ------------------
  |  Branch (277:25): [True: 235k, False: 7.15k]
  ------------------
  278|   235k|            *r++ = ((comp_t *)src[0])[x];                                   \
  279|   235k|            *r++ = ((comp_t *)src[1])[x];                                   \
  280|   235k|            *r++ = ((comp_t *)src[2])[x];                                   \
  281|   235k|        }                                                                   \
  282|  7.15k|    }
repack.c:un_ccc8:
  285|  7.15k|    static void name(void *restrict src, void *restrict dst[], int w) {     \
  286|  7.15k|        comp_t *r = src;                                                    \
  287|   242k|        for (int x = 0; x < w; x++) {                                       \
  ------------------
  |  Branch (287:25): [True: 235k, False: 7.15k]
  ------------------
  288|   235k|            ((comp_t *)dst[0])[x] = *r++;                                   \
  289|   235k|            ((comp_t *)dst[1])[x] = *r++;                                   \
  290|   235k|            ((comp_t *)dst[2])[x] = *r++;                                   \
  291|   235k|        }                                                                   \
  292|  7.15k|    }
repack.c:setup_misc_packer:
  570|    180|{
  571|    180|    if (rp->imgfmt_a == IMGFMT_PAL8 && !rp->pack) {
  ------------------
  |  Branch (571:9): [True: 0, False: 180]
  |  Branch (571:40): [True: 0, False: 0]
  ------------------
  572|      0|        int grap_fmt = find_gbrp_format(8, 4);
  573|      0|        if (!grap_fmt)
  ------------------
  |  Branch (573:13): [True: 0, False: 0]
  ------------------
  574|      0|            return;
  575|      0|        rp->imgfmt_b = grap_fmt;
  576|      0|        rp->repack = unpack_pal;
  577|    180|    } else {
  578|    180|        enum AVPixelFormat avfmt = imgfmt2pixfmt(rp->imgfmt_a);
  579|    180|        if (avfmt == AV_PIX_FMT_MONOWHITE || avfmt == AV_PIX_FMT_MONOBLACK) {
  ------------------
  |  Branch (579:13): [True: 0, False: 180]
  |  Branch (579:46): [True: 0, False: 180]
  ------------------
  580|      0|            rp->comp_lut = talloc_array(rp, uint8_t, 256);
  ------------------
  |  |   29|      0|#define talloc_array                    ta_xnew_array
  |  |  ------------------
  |  |  |  |  135|      0|#define ta_xnew_array(...)              ta_oom_g(ta_new_array(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|      0|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  581|      0|            rp->imgfmt_b = IMGFMT_Y1;
  582|      0|            int max = 1;
  583|      0|            if (rp->flags & REPACK_CREATE_EXPAND_8BIT) {
  ------------------
  |  Branch (583:17): [True: 0, False: 0]
  ------------------
  584|      0|                rp->imgfmt_b = IMGFMT_Y8;
  585|      0|                max = 255;
  586|      0|            }
  587|      0|            bool inv = avfmt == AV_PIX_FMT_MONOWHITE;
  588|      0|            for (int n = 0; n < 256; n++) {
  ------------------
  |  Branch (588:29): [True: 0, False: 0]
  ------------------
  589|      0|                rp->comp_lut[n] = rp->pack ? (inv ^ (n >= (max + 1) / 2))
  ------------------
  |  Branch (589:35): [True: 0, False: 0]
  ------------------
  590|      0|                                           : ((inv ^ !!n) ? max : 0);
  ------------------
  |  Branch (590:47): [True: 0, False: 0]
  ------------------
  591|      0|            }
  592|      0|            rp->repack = bitmap_repack;
  593|      0|            return;
  594|      0|        }
  595|    180|    }
  596|    180|}
repack.c:find_gbrp_format:
   93|    180|{
   94|    180|    if (num_planes != 3 && num_planes != 4)
  ------------------
  |  Branch (94:9): [True: 60, False: 120]
  |  Branch (94:28): [True: 0, False: 60]
  ------------------
   95|      0|        return 0;
   96|    180|    struct mp_regular_imgfmt desc = {
   97|    180|        .component_type = MP_COMPONENT_TYPE_UINT,
   98|    180|        .forced_csp = PL_COLOR_SYSTEM_RGB,
   99|    180|        .component_size = depth > 8 ? 2 : 1,
  ------------------
  |  Branch (99:27): [True: 0, False: 180]
  ------------------
  100|    180|        .component_pad = depth - (depth > 8 ? 16 : 8),
  ------------------
  |  Branch (100:35): [True: 0, False: 180]
  ------------------
  101|    180|        .num_planes = num_planes,
  102|    180|        .planes = { {1, {2}}, {1, {3}}, {1, {1}}, {1, {4}} },
  103|    180|    };
  104|    180|    return mp_find_regular_imgfmt(&desc);
  105|    180|}
repack.c:setup_packed_packer:
  339|    180|{
  340|    180|    struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(rp->imgfmt_a);
  341|    180|    if (!(desc.flags & MP_IMGFLAG_HAS_COMPS) ||
  ------------------
  |  |   34|    180|#define MP_IMGFLAG_HAS_COMPS    (1 << 0)
  ------------------
  |  Branch (341:9): [True: 0, False: 180]
  ------------------
  342|    180|        !(desc.flags & MP_IMGFLAG_TYPE_UINT) ||
  ------------------
  |  |   62|    180|#define MP_IMGFLAG_TYPE_UINT    (1 << 10)
  ------------------
  |  Branch (342:9): [True: 0, False: 180]
  ------------------
  343|    180|        !(desc.flags & MP_IMGFLAG_NE) ||
  ------------------
  |  |   49|    180|#define MP_IMGFLAG_NE           MP_SELECT_LE_BE(MP_IMGFLAG_LE, MP_IMGFLAG_BE)
  |  |  ------------------
  |  |  |  |   38|    180|#define MP_SELECT_LE_BE(LE, BE) LE
  |  |  ------------------
  ------------------
  |  Branch (343:9): [True: 0, False: 180]
  ------------------
  344|    180|        desc.num_planes != 1)
  ------------------
  |  Branch (344:9): [True: 0, False: 180]
  ------------------
  345|      0|        return;
  346|       |
  347|    180|    int num_real_components = 0;
  348|    180|    int components[4] = {0};
  349|    900|    for (int n = 0; n < MP_NUM_COMPONENTS; n++) {
  ------------------
  |  |   29|    900|#define MP_NUM_COMPONENTS 4
  ------------------
  |  Branch (349:21): [True: 720, False: 180]
  ------------------
  350|    720|        if (!desc.comps[n].size)
  ------------------
  |  Branch (350:13): [True: 120, False: 600]
  ------------------
  351|    120|            continue;
  352|    600|        if (desc.comps[n].size != desc.comps[0].size ||
  ------------------
  |  Branch (352:13): [True: 0, False: 600]
  ------------------
  353|    600|            desc.comps[n].pad != desc.comps[0].pad ||
  ------------------
  |  Branch (353:13): [True: 0, False: 600]
  ------------------
  354|    600|            desc.comps[n].offset % desc.comps[0].size)
  ------------------
  |  Branch (354:13): [True: 0, False: 600]
  ------------------
  355|      0|            return;
  356|    600|        int item = desc.comps[n].offset / desc.comps[0].size;
  357|    600|        if (item >= 4)
  ------------------
  |  Branch (357:13): [True: 0, False: 600]
  ------------------
  358|      0|            return;
  359|    600|        components[item] = n + 1;
  360|    600|        num_real_components++;
  361|    600|    }
  362|       |
  363|    180|    int depth = desc.comps[0].size + MPMIN(0, desc.comps[0].pad);
  ------------------
  |  |   44|    180|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 180]
  |  |  ------------------
  ------------------
  364|       |
  365|    180|    static const int reorder_gbrp[] = {0, 3, 1, 2, 4};
  366|    180|    static const int reorder_yuv[] = {0, 1, 2, 3, 4};
  367|    180|    int planar_fmt = 0;
  368|    180|    const int *reorder = NULL;
  369|    180|    if (desc.flags & MP_IMGFLAG_COLOR_YUV) {
  ------------------
  |  |   56|    180|#define MP_IMGFLAG_COLOR_YUV    (1 << 6)
  ------------------
  |  Branch (369:9): [True: 0, False: 180]
  ------------------
  370|      0|        planar_fmt = find_yuv_format(depth, num_real_components);
  371|      0|        reorder = reorder_yuv;
  372|    180|    } else {
  373|    180|        planar_fmt = find_gbrp_format(depth, num_real_components);
  374|    180|        reorder = reorder_gbrp;
  375|    180|    }
  376|    180|    if (!planar_fmt)
  ------------------
  |  Branch (376:9): [True: 0, False: 180]
  ------------------
  377|      0|        return;
  378|       |
  379|    900|    for (int i = 0; i < MP_ARRAY_SIZE(regular_repackers); i++) {
  ------------------
  |  |   48|    900|#define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0]))
  ------------------
  |  Branch (379:21): [True: 900, False: 0]
  ------------------
  380|    900|        const struct regular_repacker *pa = &regular_repackers[i];
  381|       |
  382|       |        // The following may assume little endian (because some repack backends
  383|       |        // use word access, while the metadata here uses byte access).
  384|       |
  385|    900|        int prepad = components[0] ? 0 : 8;
  ------------------
  |  Branch (385:22): [True: 900, False: 0]
  ------------------
  386|    900|        int first_comp = components[0] ? 0 : 1;
  ------------------
  |  Branch (386:26): [True: 900, False: 0]
  ------------------
  387|    900|        void (*repack_cb)(void *restrict pa, void *restrict pb[], int w) =
  388|    900|            rp->pack ? pa->pa_scanline : pa->un_scanline;
  ------------------
  |  Branch (388:13): [True: 360, False: 540]
  ------------------
  389|       |
  390|    900|        if (pa->packed_width != desc.bpp[0] ||
  ------------------
  |  Branch (390:13): [True: 600, False: 300]
  ------------------
  391|    900|            pa->component_width != depth ||
  ------------------
  |  Branch (391:13): [True: 0, False: 300]
  ------------------
  392|    900|            pa->num_components != num_real_components ||
  ------------------
  |  Branch (392:13): [True: 120, False: 180]
  ------------------
  393|    900|            pa->prepadding != prepad ||
  ------------------
  |  Branch (393:13): [True: 0, False: 180]
  ------------------
  394|    900|            !repack_cb)
  ------------------
  |  Branch (394:13): [True: 0, False: 180]
  ------------------
  395|    720|            continue;
  396|       |
  397|    180|        rp->repack = packed_repack;
  398|    180|        rp->packed_repack_scanline = repack_cb;
  399|    180|        rp->imgfmt_b = planar_fmt;
  400|    780|        for (int n = 0; n < num_real_components; n++) {
  ------------------
  |  Branch (400:25): [True: 600, False: 180]
  ------------------
  401|       |            // Determine permutation that maps component order between the two
  402|       |            // formats, with has_alpha special case (see above).
  403|    600|            int c = reorder[components[first_comp + n]];
  404|    600|            rp->components[n] = c == 4 ? num_real_components - 1 : c - 1;
  ------------------
  |  Branch (404:33): [True: 60, False: 540]
  ------------------
  405|    600|        }
  406|    180|        return;
  407|    900|    }
  408|    180|}
repack.c:packed_repack:
  325|  21.4k|{
  326|  21.4k|    uint32_t *pa = mp_image_pixel_ptr(a, 0, a_x, a_y);
  327|       |
  328|  21.4k|    void *pb[4] = {0};
  329|  92.9k|    for (int p = 0; p < b->num_planes; p++) {
  ------------------
  |  Branch (329:21): [True: 71.5k, False: 21.4k]
  ------------------
  330|  71.5k|        int s = rp->components[p];
  331|  71.5k|        pb[p] = mp_image_pixel_ptr(b, s, b_x, b_y);
  332|  71.5k|    }
  333|       |
  334|  21.4k|    rp->packed_repack_scanline(pa, pb, w);
  335|  21.4k|}
repack.c:update_repack_float:
  841|    180|{
  842|    180|    if (!rp->f32_comp_size)
  ------------------
  |  Branch (842:9): [True: 180, False: 0]
  ------------------
  843|    180|        return;
  844|       |
  845|       |    // Image in input format.
  846|      0|    struct mp_image *ui =  rp->pack ? rp->steps[rp->num_steps - 1].buf[1]
  ------------------
  |  Branch (846:28): [True: 0, False: 0]
  ------------------
  847|      0|                                    : rp->steps[0].buf[0];
  848|      0|    enum pl_color_system csp = ui->params.repr.sys;
  849|      0|    enum pl_color_levels levels = ui->params.repr.levels;
  850|      0|    if (rp->f32_csp_space == csp && rp->f32_csp_levels == levels)
  ------------------
  |  Branch (850:9): [True: 0, False: 0]
  |  Branch (850:37): [True: 0, False: 0]
  ------------------
  851|      0|        return;
  852|       |
  853|       |    // The fixed point format.
  854|      0|    struct mp_regular_imgfmt desc = {0};
  855|      0|    mp_get_regular_imgfmt(&desc, rp->imgfmt_b);
  856|      0|    mp_assert(desc.component_size);
  ------------------
  |  |   41|      0|#define mp_assert assert
  ------------------
  857|       |
  858|      0|    int comp_bits = desc.component_size * 8 + MPMIN(desc.component_pad, 0);
  ------------------
  |  |   44|      0|#define MPMIN(a, b) ((a) > (b) ? (b) : (a))
  |  |  ------------------
  |  |  |  Branch (44:22): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  859|      0|    for (int p = 0; p < desc.num_planes; p++) {
  ------------------
  |  Branch (859:21): [True: 0, False: 0]
  ------------------
  860|      0|        double m, o;
  861|      0|        mp_get_csp_uint_mul(csp, levels, comp_bits, desc.planes[p].components[0],
  862|      0|                            &m, &o);
  863|      0|        rp->f32_m[p] = rp->pack ? 1.0 / m : m;
  ------------------
  |  Branch (863:24): [True: 0, False: 0]
  ------------------
  864|      0|        rp->f32_o[p] = rp->pack ? -o      : o;
  ------------------
  |  Branch (864:24): [True: 0, False: 0]
  ------------------
  865|      0|        rp->f32_pmax[p] = (1u << comp_bits) - 1;
  866|      0|    }
  867|       |
  868|      0|    rp->f32_csp_space = csp;
  869|      0|    rp->f32_csp_levels = levels;
  870|      0|}

mp_sws_alloc:
  191|     99|{
  192|     99|    struct mp_sws_context *ctx = talloc_ptrtype(talloc_ctx, ctx);
  ------------------
  |  |   34|     99|#define talloc_ptrtype                  ta_xnew_ptrtype
  |  |  ------------------
  |  |  |  |  138|     99|#define ta_xnew_ptrtype(...)            ta_oom_g(ta_new_ptrtype(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     99|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  193|     99|    *ctx = (struct mp_sws_context) {
  194|     99|        .log = mp_null_log,
  195|     99|        .flags = SWS_BILINEAR,
  196|     99|        .force_reload = true,
  197|     99|        .params = {SWS_PARAM_DEFAULT, SWS_PARAM_DEFAULT},
  198|     99|        .cached = talloc_zero(ctx, struct mp_sws_context),
  ------------------
  |  |   27|     99|#define talloc_zero                     ta_xznew
  |  |  ------------------
  |  |  |  |  134|     99|#define ta_xznew(...)                   ta_oom_g(ta_znew(__VA_ARGS__))
  |  |  |  |  ------------------
  |  |  |  |  |  |  182|     99|#define ta_oom_g(ptr) (TA_TYPEOF(ptr))ta_oom_p(ptr)
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  199|     99|    };
  200|     99|    talloc_set_destructor(ctx, free_mp_sws);
  ------------------
  |  |   41|     99|#define talloc_set_destructor           ta_set_destructor
  ------------------
  201|       |
  202|       |#if HAVE_ZIMG
  203|       |    ctx->zimg = mp_zimg_alloc();
  204|       |    talloc_steal(ctx, ctx->zimg);
  205|       |#endif
  206|       |
  207|     99|    return ctx;
  208|     99|}
mp_sws_enable_cmdline_opts:
  214|     99|{
  215|       |    // Should only ever be NULL for tests.
  216|     99|    if (!g)
  ------------------
  |  Branch (216:9): [True: 0, False: 99]
  ------------------
  217|      0|        return;
  218|     99|    if (ctx->opts_cache)
  ------------------
  |  Branch (218:9): [True: 0, False: 99]
  ------------------
  219|      0|        return;
  220|       |
  221|     99|    ctx->opts_cache = m_config_cache_alloc(ctx, g, &sws_conf);
  222|     99|    ctx->force_reload = true;
  223|     99|    mp_sws_update_from_cmdline(ctx);
  224|       |
  225|       |#if HAVE_ZIMG
  226|       |    mp_zimg_enable_cmdline_opts(ctx->zimg, g);
  227|       |#endif
  228|     99|}
mp_sws_reinit:
  233|     39|{
  234|     39|    struct mp_image_params src = ctx->src;
  235|     39|    struct mp_image_params dst = ctx->dst;
  236|       |
  237|     39|    if (cache_valid(ctx))
  ------------------
  |  Branch (237:9): [True: 0, False: 39]
  ------------------
  238|      0|        return 0;
  239|       |
  240|     39|    if (ctx->opts_cache)
  ------------------
  |  Branch (240:9): [True: 39, False: 0]
  ------------------
  241|     39|        mp_sws_update_from_cmdline(ctx);
  242|       |
  243|     39|    sws_freeContext(ctx->sws);
  244|     39|    ctx->sws = NULL;
  245|     39|    ctx->zimg_ok = false;
  246|     39|    TA_FREEP(&ctx->aligned_src);
  ------------------
  |  |   81|     39|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|     39|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  247|     39|    TA_FREEP(&ctx->aligned_dst);
  ------------------
  |  |   81|     39|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|     39|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  248|       |
  249|       |#if HAVE_ZIMG
  250|       |    if (allow_zimg(ctx)) {
  251|       |        ctx->zimg->log = ctx->log;
  252|       |        ctx->zimg->src = src;
  253|       |        ctx->zimg->dst = dst;
  254|       |        if (ctx->zimg_opts)
  255|       |            ctx->zimg->opts = *ctx->zimg_opts;
  256|       |        if (mp_zimg_config(ctx->zimg)) {
  257|       |            ctx->zimg_ok = true;
  258|       |            MP_VERBOSE(ctx, "Using zimg.\n");
  259|       |            goto success;
  260|       |        }
  261|       |        MP_WARN(ctx, "Not using zimg, falling back to swscale.\n");
  262|       |    }
  263|       |#endif
  264|       |
  265|     39|    if (!allow_sws(ctx)) {
  ------------------
  |  Branch (265:9): [True: 0, False: 39]
  ------------------
  266|      0|        MP_ERR(ctx, "No scaler.\n");
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  267|      0|        return -1;
  268|      0|    }
  269|       |
  270|     39|    ctx->sws = sws_alloc_context();
  271|     39|    if (!ctx->sws)
  ------------------
  |  Branch (271:9): [True: 0, False: 39]
  ------------------
  272|      0|        return -1;
  273|       |
  274|     39|    mp_image_params_guess_csp(&src); // sanitize colorspace/colorlevels
  275|     39|    mp_image_params_guess_csp(&dst);
  276|       |
  277|     39|    enum AVPixelFormat s_fmt = imgfmt2pixfmt(src.imgfmt);
  278|     39|    if (s_fmt == AV_PIX_FMT_NONE || sws_isSupportedInput(s_fmt) < 1) {
  ------------------
  |  Branch (278:9): [True: 0, False: 39]
  |  Branch (278:37): [True: 0, False: 39]
  ------------------
  279|      0|        MP_ERR(ctx, "Input image format %s not supported by libswscale.\n",
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  280|      0|               mp_imgfmt_to_name(src.imgfmt));
  281|      0|        return -1;
  282|      0|    }
  283|       |
  284|     39|    enum AVPixelFormat d_fmt = imgfmt2pixfmt(dst.imgfmt);
  285|     39|    if (d_fmt == AV_PIX_FMT_NONE || sws_isSupportedOutput(d_fmt) < 1) {
  ------------------
  |  Branch (285:9): [True: 0, False: 39]
  |  Branch (285:37): [True: 0, False: 39]
  ------------------
  286|      0|        MP_ERR(ctx, "Output image format %s not supported by libswscale.\n",
  ------------------
  |  |   85|      0|#define MP_ERR(obj, ...)        MP_MSG(obj, MSGL_ERR, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |   82|      0|#define MP_MSG(obj, lev, ...)   mp_msg((obj)->log, lev, __VA_ARGS__)
  |  |  ------------------
  ------------------
  287|      0|               mp_imgfmt_to_name(dst.imgfmt));
  288|      0|        return -1;
  289|      0|    }
  290|       |
  291|     39|    int s_csp = pl_csp_to_sws_colorspace(src.repr.sys);
  292|     39|    int s_range = src.repr.levels == PL_COLOR_LEVELS_FULL;
  293|       |
  294|     39|    int d_csp = pl_csp_to_sws_colorspace(src.repr.sys);
  295|     39|    int d_range = dst.repr.levels == PL_COLOR_LEVELS_FULL;
  296|       |
  297|     39|    av_opt_set_int(ctx->sws, "sws_flags", ctx->flags, 0);
  298|       |
  299|     39|    av_opt_set_int(ctx->sws, "srcw", src.w, 0);
  300|     39|    av_opt_set_int(ctx->sws, "srch", src.h, 0);
  301|     39|    av_opt_set_int(ctx->sws, "src_format", s_fmt, 0);
  302|       |
  303|     39|    av_opt_set_int(ctx->sws, "dstw", dst.w, 0);
  304|     39|    av_opt_set_int(ctx->sws, "dsth", dst.h, 0);
  305|     39|    av_opt_set_int(ctx->sws, "dst_format", d_fmt, 0);
  306|       |
  307|     39|    av_opt_set_double(ctx->sws, "param0", ctx->params[0], 0);
  308|     39|    av_opt_set_double(ctx->sws, "param1", ctx->params[1], 0);
  309|       |
  310|     39|    int cr_src = pl_chroma_to_av(src.chroma_location);
  311|     39|    int cr_dst = pl_chroma_to_av(dst.chroma_location);
  312|     39|    int cr_xpos, cr_ypos;
  313|     39|    if (av_chroma_location_enum_to_pos(&cr_xpos, &cr_ypos, cr_src) >= 0) {
  ------------------
  |  Branch (313:9): [True: 39, False: 0]
  ------------------
  314|     39|        av_opt_set_int(ctx->sws, "src_h_chr_pos", cr_xpos, 0);
  315|     39|        av_opt_set_int(ctx->sws, "src_v_chr_pos", cr_ypos, 0);
  316|     39|    }
  317|     39|    if (av_chroma_location_enum_to_pos(&cr_xpos, &cr_ypos, cr_dst) >= 0) {
  ------------------
  |  Branch (317:9): [True: 39, False: 0]
  ------------------
  318|     39|        av_opt_set_int(ctx->sws, "dst_h_chr_pos", cr_xpos, 0);
  319|     39|        av_opt_set_int(ctx->sws, "dst_v_chr_pos", cr_ypos, 0);
  320|     39|    }
  321|       |
  322|       |    // This can fail even with normal operation, e.g. if a conversion path
  323|       |    // simply does not support these settings.
  324|     39|    int r =
  325|     39|        sws_setColorspaceDetails(ctx->sws, sws_getCoefficients(s_csp), s_range,
  326|     39|                                 sws_getCoefficients(d_csp), d_range,
  327|     39|                                 0, 1 << 16, 1 << 16);
  328|     39|    ctx->supports_csp = r >= 0;
  329|       |
  330|     39|    if (sws_init_context(ctx->sws, ctx->src_filter, ctx->dst_filter) < 0)
  ------------------
  |  Branch (330:9): [True: 0, False: 39]
  ------------------
  331|      0|        return -1;
  332|       |
  333|       |#if HAVE_ZIMG
  334|       |success:
  335|       |#endif
  336|       |
  337|     39|    ctx->force_reload = false;
  338|     39|    *ctx->cached = *ctx;
  339|     39|    return 1;
  340|     39|}
sws_utils.c:allow_sws:
  138|     39|{
  139|     39|    return ctx->force_scaler == MP_SWS_SWS || ctx->force_scaler == MP_SWS_AUTO;
  ------------------
  |  Branch (139:12): [True: 0, False: 39]
  |  Branch (139:47): [True: 39, False: 0]
  ------------------
  140|     39|}
sws_utils.c:free_mp_sws:
  179|     99|{
  180|     99|    struct mp_sws_context *ctx = p;
  181|     99|    sws_freeContext(ctx->sws);
  182|     99|    sws_freeFilter(ctx->src_filter);
  183|     99|    sws_freeFilter(ctx->dst_filter);
  184|     99|    TA_FREEP(&ctx->aligned_src);
  ------------------
  |  |   81|     99|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|     99|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  185|     99|    TA_FREEP(&ctx->aligned_dst);
  ------------------
  |  |   81|     99|#define TA_FREEP(pctx) do {talloc_free(*(pctx)); *(pctx) = NULL;} while(0)
  |  |  ------------------
  |  |  |  |   47|     99|#define talloc_free                     ta_free
  |  |  ------------------
  |  |  |  Branch (81:73): [Folded - Ignored]
  |  |  ------------------
  ------------------
  186|     99|}
sws_utils.c:mp_sws_update_from_cmdline:
  101|    138|{
  102|    138|    m_config_cache_update(ctx->opts_cache);
  103|    138|    struct sws_opts *opts = ctx->opts_cache->opts;
  104|       |
  105|    138|    sws_freeFilter(ctx->src_filter);
  106|    138|    ctx->src_filter = sws_getDefaultFilter(opts->lum_gblur, opts->chr_gblur,
  107|    138|                                           opts->lum_sharpen, opts->chr_sharpen,
  108|    138|                                           opts->chr_hshift, opts->chr_vshift, 0);
  109|    138|    ctx->force_reload = true;
  110|       |
  111|    138|    ctx->flags = SWS_PRINT_INFO;
  112|    138|    ctx->flags |= opts->scaler;
  113|    138|    if (!opts->fast)
  ------------------
  |  Branch (113:9): [True: 138, False: 0]
  ------------------
  114|    138|        ctx->flags |= mp_sws_hq_flags;
  115|    138|    if (opts->bitexact)
  ------------------
  |  Branch (115:9): [True: 0, False: 138]
  ------------------
  116|      0|        ctx->flags |= SWS_BITEXACT;
  117|       |
  118|    138|    ctx->allow_zimg = opts->zimg;
  119|    138|}
sws_utils.c:cache_valid:
  166|     39|{
  167|     39|    struct mp_sws_context *old = ctx->cached;
  168|     39|    if (ctx->force_reload)
  ------------------
  |  Branch (168:9): [True: 39, False: 0]
  ------------------
  169|     39|        return false;
  170|      0|    return mp_image_params_equal(&ctx->src, &old->src) &&
  ------------------
  |  Branch (170:12): [True: 0, False: 0]
  ------------------
  171|      0|           mp_image_params_equal(&ctx->dst, &old->dst) &&
  ------------------
  |  Branch (171:12): [True: 0, False: 0]
  ------------------
  172|      0|           ctx->flags == old->flags &&
  ------------------
  |  Branch (172:12): [True: 0, False: 0]
  ------------------
  173|      0|           ctx->allow_zimg == old->allow_zimg &&
  ------------------
  |  Branch (173:12): [True: 0, False: 0]
  ------------------
  174|      0|           ctx->force_scaler == old->force_scaler &&
  ------------------
  |  Branch (174:12): [True: 0, False: 0]
  ------------------
  175|      0|           (!ctx->opts_cache || !m_config_cache_update(ctx->opts_cache));
  ------------------
  |  Branch (175:13): [True: 0, False: 0]
  |  Branch (175:33): [True: 0, False: 0]
  ------------------
  176|     39|}
sws_utils.c:pl_csp_to_sws_colorspace:
  159|     78|{
  160|       |    // The SWS_CS_* macros are just convenience redefinitions of the
  161|       |    // AVCOL_SPC_* macros, inside swscale.h.
  162|     78|    return pl_system_to_av(csp);
  163|     78|}

