Line | Count | Source |
1 | | /* |
2 | | * This file is part of mpv. |
3 | | * |
4 | | * mpv is free software; you can redistribute it and/or |
5 | | * modify it under the terms of the GNU Lesser General Public |
6 | | * License as published by the Free Software Foundation; either |
7 | | * version 2.1 of the License, or (at your option) any later version. |
8 | | * |
9 | | * mpv is distributed in the hope that it will be useful, |
10 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | * GNU Lesser General Public License for more details. |
13 | | * |
14 | | * You should have received a copy of the GNU Lesser General Public |
15 | | * License along with mpv. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | |
18 | | #ifndef MPLAYER_STREAM_H |
19 | | #define MPLAYER_STREAM_H |
20 | | |
21 | | #include "common/msg.h" |
22 | | #include <stdbool.h> |
23 | | #include <stdio.h> |
24 | | #include <string.h> |
25 | | #include <inttypes.h> |
26 | | #include <sys/types.h> |
27 | | #include <fcntl.h> |
28 | | |
29 | | #include "misc/bstr.h" |
30 | | |
31 | | // Minimum guaranteed buffer and seek-back size. For any reads <= of this size, |
32 | | // it's guaranteed that you can seek back by <= of this size again. |
33 | 192k | #define STREAM_BUFFER_SIZE 2048 |
34 | | |
35 | | // Maximum size of a complete read. |
36 | 35.4k | #define STREAM_MAX_READ_SIZE (INT_MAX - 1) |
37 | | |
38 | | // flags for stream_open_ext (this includes STREAM_READ and STREAM_WRITE) |
39 | | |
40 | | // stream->mode |
41 | 684k | #define STREAM_READ 0 |
42 | 1.64M | #define STREAM_WRITE (1 << 0) |
43 | | |
44 | 536k | #define STREAM_SILENT (1 << 1) |
45 | | |
46 | | // Origin value for "security". This is an integer within the flags bit-field. |
47 | 755k | #define STREAM_ORIGIN_DIRECT (1 << 2) // passed from cmdline or loadfile |
48 | 61.1k | #define STREAM_ORIGIN_FS (2 << 2) // referenced from playlist on unix FS |
49 | 73.9k | #define STREAM_ORIGIN_NET (3 << 2) // referenced from playlist on network |
50 | 108k | #define STREAM_ORIGIN_UNSAFE (4 << 2) // from a grotesque source |
51 | | |
52 | 354k | #define STREAM_ORIGIN_MASK (7 << 2) // for extracting origin value from flags |
53 | | |
54 | 1.56M | #define STREAM_LOCAL_FS_ONLY (1 << 5) // stream_file only, no URLs |
55 | 354k | #define STREAM_LESS_NOISE (1 << 6) // try to log errors only |
56 | 354k | #define STREAM_ALLOW_PARTIAL_READ (1 << 7) // allows partial read with stream_read_file() |
57 | | |
58 | | // Default flags used by stream_read_file(). |
59 | | #define STREAM_READ_FILE_FLAGS_DEFAULT \ |
60 | 0 | (STREAM_ORIGIN_DIRECT | STREAM_READ | STREAM_LOCAL_FS_ONLY | STREAM_LESS_NOISE) |
61 | | |
62 | | // end flags for stream_open_ext (the naming convention sucks) |
63 | | |
64 | 81.3k | #define STREAM_UNSAFE -3 |
65 | 3.93M | #define STREAM_NO_MATCH -2 |
66 | 6.75M | #define STREAM_UNSUPPORTED -1 |
67 | 29.4k | #define STREAM_ERROR 0 |
68 | 2.30M | #define STREAM_OK 1 |
69 | | |
70 | | // EOF value returned by stream_read_char() |
71 | 3.39M | #define STREAM_EOF (-256) |
72 | | |
73 | | enum stream_ctrl { |
74 | | // Certain network protocols |
75 | | STREAM_CTRL_AVSEEK, |
76 | | STREAM_CTRL_HAS_AVSEEK, |
77 | | STREAM_CTRL_GET_METADATA, |
78 | | |
79 | | // Optical discs (internal interface between streams and demux_disc) |
80 | | STREAM_CTRL_GET_TIME_LENGTH, |
81 | | STREAM_CTRL_GET_DVD_INFO, |
82 | | STREAM_CTRL_GET_DISC_NAME, |
83 | | STREAM_CTRL_GET_NUM_CHAPTERS, |
84 | | STREAM_CTRL_GET_CURRENT_TIME, |
85 | | STREAM_CTRL_GET_CHAPTER_TIME, |
86 | | STREAM_CTRL_SEEK_TO_TIME, |
87 | | STREAM_CTRL_GET_ASPECT_RATIO, |
88 | | STREAM_CTRL_GET_NUM_ANGLES, |
89 | | STREAM_CTRL_GET_ANGLE, |
90 | | STREAM_CTRL_SET_ANGLE, |
91 | | STREAM_CTRL_GET_NUM_TITLES, |
92 | | STREAM_CTRL_GET_TITLE_LENGTH, // double* (in: title number, out: len) |
93 | | STREAM_CTRL_GET_TITLE_PLAYLIST, // double* (in: title number, out: playlist) |
94 | | STREAM_CTRL_GET_LANG, |
95 | | STREAM_CTRL_GET_CURRENT_TITLE, |
96 | | STREAM_CTRL_SET_CURRENT_TITLE, |
97 | | }; |
98 | | |
99 | | struct stream_lang_req { |
100 | | int type; // STREAM_AUDIO, STREAM_SUB |
101 | | int id; |
102 | | char name[50]; |
103 | | }; |
104 | | |
105 | | struct stream_dvd_info_req { |
106 | | unsigned int palette[16]; |
107 | | int num_subs; |
108 | | }; |
109 | | |
110 | | // for STREAM_CTRL_AVSEEK |
111 | | struct stream_avseek { |
112 | | int stream_index; |
113 | | int64_t timestamp; |
114 | | int flags; |
115 | | }; |
116 | | |
117 | | struct stream; |
118 | | struct stream_open_args; |
119 | | typedef struct stream_info_st { |
120 | | const char *name; |
121 | | // opts is set from ->opts |
122 | | int (*open)(struct stream *st); |
123 | | // Alternative to open(). Only either open() or open2() can be set. |
124 | | int (*open2)(struct stream *st, const struct stream_open_args *args); |
125 | | const char *const *protocols; |
126 | | // Alternative to protocols. For stream_lavf. |
127 | | char **(*get_protocols)(void); |
128 | | bool can_write; // correctly checks for READ/WRITE modes |
129 | | bool local_fs; // supports STREAM_LOCAL_FS_ONLY |
130 | | int stream_origin; // 0 or set of STREAM_ORIGIN_*; if 0, the same origin |
131 | | // is set, or the stream's open() function handles it |
132 | | } stream_info_t; |
133 | | |
134 | | typedef struct stream { |
135 | | const struct stream_info_st *info; |
136 | | |
137 | | // Read |
138 | | int (*fill_buffer)(struct stream *s, void *buffer, int max_len); |
139 | | // Write |
140 | | int (*write_buffer)(struct stream *s, void *buffer, int len); |
141 | | // Seek |
142 | | int (*seek)(struct stream *s, int64_t pos); |
143 | | // Total stream size in bytes (negative if unavailable) |
144 | | int64_t (*get_size)(struct stream *s); |
145 | | // Control |
146 | | int (*control)(struct stream *s, int cmd, void *arg); |
147 | | // Close |
148 | | void (*close)(struct stream *s); |
149 | | |
150 | | int64_t pos; |
151 | | int eof; // valid only after read calls that returned a short result |
152 | | int mode; //STREAM_READ or STREAM_WRITE |
153 | | int stream_origin; // any STREAM_ORIGIN_* |
154 | | void *priv; // used for DVD, TV, RTSP etc |
155 | | char *url; // filename/url (possibly including protocol prefix) |
156 | | char *path; // filename (url without protocol prefix) |
157 | | char *mime_type; // when HTTP streaming is used |
158 | | char *demuxer; // request demuxer to be used |
159 | | char *lavf_type; // name of expected demuxer type for lavf |
160 | | bool streaming : 1; // known to be a network stream if true |
161 | | bool seekable : 1; // presence of general byte seeking support |
162 | | bool fast_skip : 1; // consider stream fast enough to fw-seek by skipping |
163 | | bool is_network : 1; // I really don't know what this is for |
164 | | bool is_local_fs : 1; // from the filesystem |
165 | | bool is_directory : 1; // directory on the filesystem |
166 | | bool is_regular : 1; // regular file |
167 | | bool access_references : 1; // open other streams |
168 | | bool allow_partial_read : 1; // allows partial read with stream_read_file() |
169 | | struct mp_log *log; |
170 | | struct mpv_global *global; |
171 | | |
172 | | struct mp_cancel *cancel; // cancellation notification |
173 | | |
174 | | // Read statistic for fill_buffer calls. All bytes read by fill_buffer() are |
175 | | // added to this. The user can reset this as needed. |
176 | | uint64_t total_unbuffered_read_bytes; |
177 | | // Seek statistics. The user can reset this as needed. |
178 | | uint64_t total_stream_seeks; |
179 | | |
180 | | // Buffer size requested by user; s->buffer may have a different size |
181 | | int requested_buffer_size; |
182 | | |
183 | | // This is a ring buffer. It is reset only on seeks (or when buffers are |
184 | | // dropped). Otherwise old contents always stay valid. |
185 | | // The valid buffer is from buf_start to buf_end; buf_end can be larger |
186 | | // than the buffer size (requires wrap around). buf_cur is a value in the |
187 | | // range [buf_start, buf_end]. |
188 | | // When reading more data from the stream, buf_start is advanced as old |
189 | | // data is overwritten with new data. |
190 | | // Example: |
191 | | // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
192 | | // +===========================+---------------------------+ |
193 | | // + 05 06 07 08 | 01 02 03 04 + 05 06 07 08 | 01 02 03 04 + |
194 | | // +===========================+---------------------------+ |
195 | | // ^ buf_start (4) | | |
196 | | // | ^ buf_end (12 % 8 => 4) |
197 | | // ^ buf_cur (9 % 8 => 1) |
198 | | // Here, the entire 8 byte buffer is filled, i.e. buf_end - buf_start = 8. |
199 | | // buffer_mask == 7, so (x & buffer_mask) == (x % buffer_size) |
200 | | unsigned int buf_start; // index of oldest byte in buffer (is <= buffer_mask) |
201 | | unsigned int buf_cur; // current read pos (can be > buffer_mask) |
202 | | unsigned int buf_end; // end position (can be > buffer_mask) |
203 | | |
204 | | unsigned int buffer_mask; // buffer_size-1, where buffer_size == 2**n |
205 | | uint8_t *buffer; |
206 | | } stream_t; |
207 | | |
208 | | // Non-inline version of stream_read_char(). |
209 | | int stream_read_char_fallback(stream_t *s); |
210 | | |
211 | | int stream_write_buffer(stream_t *s, void *buf, int len); |
212 | | |
213 | | inline static int stream_read_char(stream_t *s) |
214 | 88.5M | { |
215 | 88.5M | return s->buf_cur < s->buf_end |
216 | 88.5M | ? s->buffer[(s->buf_cur++) & s->buffer_mask] |
217 | 88.5M | : stream_read_char_fallback(s); |
218 | 88.5M | } Unexecuted instantiation: client.c:stream_read_char Unexecuted instantiation: command.c:stream_read_char Unexecuted instantiation: configfiles.c:stream_read_char Unexecuted instantiation: loadfile.c:stream_read_char Unexecuted instantiation: misc.c:stream_read_char Unexecuted instantiation: osd.c:stream_read_char Unexecuted instantiation: playloop.c:stream_read_char Unexecuted instantiation: screenshot.c:stream_read_char Unexecuted instantiation: sub.c:stream_read_char Unexecuted instantiation: video.c:stream_read_char Unexecuted instantiation: stream.c:stream_read_char Unexecuted instantiation: stream_avdevice.c:stream_read_char Unexecuted instantiation: stream_cb.c:stream_read_char Unexecuted instantiation: stream_edl.c:stream_read_char Unexecuted instantiation: stream_file.c:stream_read_char Unexecuted instantiation: stream_lavf.c:stream_read_char Unexecuted instantiation: stream_memory.c:stream_read_char Unexecuted instantiation: stream_mf.c:stream_read_char Unexecuted instantiation: stream_mpv.c:stream_read_char Unexecuted instantiation: stream_null.c:stream_read_char Unexecuted instantiation: stream_slice.c:stream_read_char Unexecuted instantiation: vo_gpu_next.c:stream_read_char Unexecuted instantiation: stream_dvb.c:stream_read_char Unexecuted instantiation: utils.c:stream_read_char Unexecuted instantiation: encode_lavc.c:stream_read_char Unexecuted instantiation: playlist.c:stream_read_char Unexecuted instantiation: demux.c:stream_read_char Unexecuted instantiation: demux_cue.c:stream_read_char Unexecuted instantiation: demux_disc.c:stream_read_char Unexecuted instantiation: demux_edl.c:stream_read_char Unexecuted instantiation: demux_lavf.c:stream_read_char Unexecuted instantiation: demux_mf.c:stream_read_char demux_mkv.c:stream_read_char Line | Count | Source | 214 | 868k | { | 215 | 868k | return s->buf_cur < s->buf_end | 216 | 868k | ? s->buffer[(s->buf_cur++) & s->buffer_mask] | 217 | 868k | : stream_read_char_fallback(s); | 218 | 868k | } |
Unexecuted instantiation: demux_mkv_timeline.c:stream_read_char Unexecuted instantiation: demux_mpv.c:stream_read_char Unexecuted instantiation: demux_null.c:stream_read_char demux_playlist.c:stream_read_char Line | Count | Source | 214 | 2.54M | { | 215 | 2.54M | return s->buf_cur < s->buf_end | 216 | 2.54M | ? s->buffer[(s->buf_cur++) & s->buffer_mask] | 217 | 2.54M | : stream_read_char_fallback(s); | 218 | 2.54M | } |
Unexecuted instantiation: demux_raw.c:stream_read_char Unexecuted instantiation: demux_timeline.c:stream_read_char Line | Count | Source | 214 | 85.0M | { | 215 | 85.0M | return s->buf_cur < s->buf_end | 216 | 85.0M | ? s->buffer[(s->buf_cur++) & s->buffer_mask] | 217 | 85.0M | : stream_read_char_fallback(s); | 218 | 85.0M | } |
Unexecuted instantiation: packet.c:stream_read_char Unexecuted instantiation: timeline.c:stream_read_char Unexecuted instantiation: input.c:stream_read_char Unexecuted instantiation: options.c:stream_read_char Unexecuted instantiation: parse_configfile.c:stream_read_char Unexecuted instantiation: cookies.c:stream_read_char Unexecuted instantiation: stream_concat.c:stream_read_char Unexecuted instantiation: ass_mp.c:stream_read_char Unexecuted instantiation: dvb_tune.c:stream_read_char Unexecuted instantiation: lcms.c:stream_read_char Unexecuted instantiation: shader_cache.c:stream_read_char |
219 | | |
220 | | int stream_skip_bom(struct stream *s); |
221 | | |
222 | | inline static int64_t stream_tell(stream_t *s) |
223 | 19.8M | { |
224 | 19.8M | return s->pos + s->buf_cur - s->buf_end; |
225 | 19.8M | } Unexecuted instantiation: client.c:stream_tell Unexecuted instantiation: command.c:stream_tell Unexecuted instantiation: configfiles.c:stream_tell Unexecuted instantiation: loadfile.c:stream_tell Unexecuted instantiation: misc.c:stream_tell Unexecuted instantiation: osd.c:stream_tell Unexecuted instantiation: playloop.c:stream_tell Unexecuted instantiation: screenshot.c:stream_tell Unexecuted instantiation: sub.c:stream_tell Unexecuted instantiation: video.c:stream_tell Line | Count | Source | 223 | 7.06M | { | 224 | 7.06M | return s->pos + s->buf_cur - s->buf_end; | 225 | 7.06M | } |
Unexecuted instantiation: stream_avdevice.c:stream_tell Unexecuted instantiation: stream_cb.c:stream_tell Unexecuted instantiation: stream_edl.c:stream_tell Unexecuted instantiation: stream_file.c:stream_tell Unexecuted instantiation: stream_lavf.c:stream_tell Unexecuted instantiation: stream_memory.c:stream_tell Unexecuted instantiation: stream_mf.c:stream_tell Unexecuted instantiation: stream_mpv.c:stream_tell Unexecuted instantiation: stream_null.c:stream_tell Unexecuted instantiation: stream_slice.c:stream_tell Unexecuted instantiation: vo_gpu_next.c:stream_tell Unexecuted instantiation: stream_dvb.c:stream_tell Unexecuted instantiation: utils.c:stream_tell Unexecuted instantiation: encode_lavc.c:stream_tell Unexecuted instantiation: playlist.c:stream_tell Unexecuted instantiation: demux.c:stream_tell Unexecuted instantiation: demux_cue.c:stream_tell Unexecuted instantiation: demux_disc.c:stream_tell Unexecuted instantiation: demux_edl.c:stream_tell Line | Count | Source | 223 | 1.55M | { | 224 | 1.55M | return s->pos + s->buf_cur - s->buf_end; | 225 | 1.55M | } |
Line | Count | Source | 223 | 31.5k | { | 224 | 31.5k | return s->pos + s->buf_cur - s->buf_end; | 225 | 31.5k | } |
Line | Count | Source | 223 | 8.86M | { | 224 | 8.86M | return s->pos + s->buf_cur - s->buf_end; | 225 | 8.86M | } |
Unexecuted instantiation: demux_mkv_timeline.c:stream_tell Unexecuted instantiation: demux_mpv.c:stream_tell Unexecuted instantiation: demux_null.c:stream_tell demux_playlist.c:stream_tell Line | Count | Source | 223 | 1.59M | { | 224 | 1.59M | return s->pos + s->buf_cur - s->buf_end; | 225 | 1.59M | } |
Unexecuted instantiation: demux_raw.c:stream_tell Unexecuted instantiation: demux_timeline.c:stream_tell Line | Count | Source | 223 | 719k | { | 224 | 719k | return s->pos + s->buf_cur - s->buf_end; | 225 | 719k | } |
Unexecuted instantiation: packet.c:stream_tell Unexecuted instantiation: timeline.c:stream_tell Unexecuted instantiation: input.c:stream_tell Unexecuted instantiation: options.c:stream_tell Unexecuted instantiation: parse_configfile.c:stream_tell Unexecuted instantiation: cookies.c:stream_tell Unexecuted instantiation: stream_concat.c:stream_tell Unexecuted instantiation: ass_mp.c:stream_tell Unexecuted instantiation: dvb_tune.c:stream_tell Unexecuted instantiation: lcms.c:stream_tell Unexecuted instantiation: shader_cache.c:stream_tell |
226 | | |
227 | | bool stream_seek_skip(stream_t *s, int64_t pos); |
228 | | bool stream_seek(stream_t *s, int64_t pos); |
229 | | int stream_read(stream_t *s, void *mem, int total); |
230 | | int stream_read_partial(stream_t *s, void *buf, int buf_size); |
231 | | int stream_peek(stream_t *s, int forward_size); |
232 | | int stream_read_peek(stream_t *s, void *buf, int buf_size); |
233 | | void stream_drop_buffers(stream_t *s); |
234 | | int64_t stream_get_size(stream_t *s); |
235 | | |
236 | | struct mpv_global; |
237 | | |
238 | | struct bstr stream_read_complete(struct stream *s, void *talloc_ctx, |
239 | | int max_size); |
240 | | struct bstr stream_read_file(const char *filename, void *talloc_ctx, |
241 | | struct mpv_global *global, int max_size); |
242 | | // Like stream_read_file(), but allows specifying flags like with stream_create(). |
243 | | struct bstr stream_read_file2(const char *filename, void *talloc_ctx, |
244 | | int flags, struct mpv_global *global, int max_size); |
245 | | |
246 | | int stream_control(stream_t *s, int cmd, void *arg); |
247 | | void free_stream(stream_t *s); |
248 | | |
249 | | struct stream_open_args { |
250 | | struct mpv_global *global; |
251 | | struct mp_cancel *cancel; // aborting stream access (used directly) |
252 | | const char *url; |
253 | | int flags; // STREAM_READ etc. |
254 | | const stream_info_t *sinfo; // NULL = autoprobe, otherwise force stream impl. |
255 | | void *special_arg; // specific to impl., use only with sinfo |
256 | | }; |
257 | | |
258 | | int stream_create_with_args(struct stream_open_args *args, struct stream **ret); |
259 | | struct stream *stream_create(const char *url, int flags, |
260 | | struct mp_cancel *c, struct mpv_global *global); |
261 | | stream_t *open_output_stream(const char *filename, struct mpv_global *global); |
262 | | |
263 | | void mp_url_unescape_inplace(char *buf); |
264 | | char *mp_url_unescape(void *talloc_ctx, const char *url); |
265 | | char *mp_url_escape(void *talloc_ctx, const char *s, const char *ok); |
266 | | |
267 | | // stream_memory.c |
268 | | struct stream *stream_memory_open(struct mpv_global *global, void *data, int len); |
269 | | |
270 | | // stream_concat.c |
271 | | struct stream *stream_concat_open(struct mpv_global *global, struct mp_cancel *c, |
272 | | struct stream **streams, int num_streams); |
273 | | |
274 | | // stream_file.c |
275 | | char *mp_file_url_to_filename(void *talloc_ctx, bstr url); |
276 | | char *mp_file_get_path(void *talloc_ctx, bstr url); |
277 | | |
278 | | // stream_lavf.c |
279 | | struct AVDictionary; |
280 | | void mp_setup_av_network_options(struct AVDictionary **dict, |
281 | | const char *target_fmt, |
282 | | struct mpv_global *global, |
283 | | struct mp_log *log); |
284 | | |
285 | | void stream_print_proto_list(struct mp_log *log); |
286 | | char **stream_get_proto_list(bool safe_only); |
287 | | bool stream_has_proto(const char *proto); |
288 | | |
289 | | #endif /* MPLAYER_STREAM_H */ |