Coverage Report

Created: 2025-06-12 07:21

/src/mpv/stream/stream_cb.c
Line
Count
Source (jump to first uncovered line)
1
#include <stdio.h>
2
#include <sys/types.h>
3
#include <sys/stat.h>
4
#include <fcntl.h>
5
#include <errno.h>
6
7
#include "osdep/io.h"
8
9
#include "common/common.h"
10
#include "common/msg.h"
11
#include "stream.h"
12
#include "options/m_option.h"
13
#include "options/path.h"
14
#include "player/client.h"
15
#include "mpv/stream_cb.h"
16
#include "misc/thread_tools.h"
17
18
struct priv {
19
    mpv_stream_cb_info info;
20
    struct mp_cancel *cancel;
21
};
22
23
static int fill_buffer(stream_t *s, void *buffer, int max_len)
24
0
{
25
0
    struct priv *p = s->priv;
26
0
    return (int)p->info.read_fn(p->info.cookie, buffer, (size_t)max_len);
27
0
}
28
29
static int seek(stream_t *s, int64_t newpos)
30
0
{
31
0
    struct priv *p = s->priv;
32
0
    return p->info.seek_fn(p->info.cookie, newpos) >= 0;
33
0
}
34
35
static int64_t get_size(stream_t *s)
36
0
{
37
0
    struct priv *p = s->priv;
38
39
0
    if (p->info.size_fn) {
40
0
        int64_t size = p->info.size_fn(p->info.cookie);
41
0
        if (size >= 0)
42
0
            return size;
43
0
    }
44
45
0
    return -1;
46
0
}
47
48
static void s_close(stream_t *s)
49
0
{
50
0
    struct priv *p = s->priv;
51
0
    p->info.close_fn(p->info.cookie);
52
0
}
53
54
static int open_cb(stream_t *stream)
55
30.3k
{
56
30.3k
    struct priv *p = talloc_ptrtype(stream, p);
57
30.3k
    stream->priv = p;
58
59
30.3k
    bstr bproto = mp_split_proto(bstr0(stream->url), NULL);
60
30.3k
    char *proto = bstrto0(stream, bproto);
61
62
30.3k
    void *user_data;
63
30.3k
    mpv_stream_cb_open_ro_fn open_fn;
64
65
30.3k
    if (!mp_streamcb_lookup(stream->global, proto, &user_data, &open_fn))
66
30.3k
        return STREAM_UNSUPPORTED;
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) {
72
0
        if (r != MPV_ERROR_LOADING_FAILED)
73
0
            MP_WARN(stream, "unknown error from user callback\n");
74
0
        return STREAM_ERROR;
75
0
    }
76
77
0
    if (!info.read_fn || !info.close_fn) {
78
0
        MP_FATAL(stream, "required read_fn or close_fn callbacks not set.\n");
79
0
        return STREAM_ERROR;
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) {
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) {
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;
100
0
}
101
102
const stream_info_t stream_info_cb = {
103
    .name = "stream_callback",
104
    .open = open_cb,
105
    .stream_origin = STREAM_ORIGIN_UNSAFE,
106
};