FFmpeg
Loading...
Searching...
No Matches
concat.c
Go to the documentation of this file.
1/*
2 * Concat URL protocol
3 * Copyright (c) 2006 Steve Lhomme
4 * Copyright (c) 2007 Wolfram Gloger
5 * Copyright (c) 2010 Michele OrrĂ¹
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <string.h>
25
26#include "config_components.h"
27
29#include "libavutil/avstring.h"
30#include "libavutil/bprint.h"
31#include "libavutil/error.h"
32#include "libavutil/mem.h"
33
34#include "avio_internal.h"
35#include "url.h"
36
37#define AV_CAT_SEPARATOR "|"
38
40 URLContext *uc; ///< node's URLContext
41 int64_t size; ///< url filesize
42};
43
45 struct concat_nodes *nodes; ///< list of nodes to concat
46 size_t length; ///< number of cat'ed nodes
47 size_t current; ///< index of currently read node
49};
50
52{
53 int err = 0;
54 size_t i;
55 struct concat_data *data = h->priv_data;
56 struct concat_nodes *nodes = data->nodes;
57
58 for (i = 0; i != data->length; i++)
59 err |= ffurl_closep(&nodes[i].uc);
60
61 av_freep(&data->nodes);
62
63 return err < 0 ? -1 : 0;
64}
65
66#if CONFIG_CONCAT_PROTOCOL
67static av_cold int concat_open(URLContext *h, const char *uri, int flags)
68{
69 char *node_uri = NULL;
70 int err = 0;
71 int64_t size, total_size = 0;
72 size_t len, i;
74 struct concat_data *data = h->priv_data;
75 struct concat_nodes *nodes;
76
77 if (!av_strstart(uri, "concat:", &uri)) {
78 av_log(h, AV_LOG_ERROR, "URL %s lacks prefix\n", uri);
79 return AVERROR(EINVAL);
80 }
81
82 for (i = 0, len = 1; uri[i]; i++) {
83 if (uri[i] == *AV_CAT_SEPARATOR) {
84 len++;
85 }
86 }
87
88 if (!(nodes = av_realloc_array(NULL, len, sizeof(*nodes))))
89 return AVERROR(ENOMEM);
90 else
91 data->nodes = nodes;
92
93 /* handle input */
94 if (!*uri)
95 err = AVERROR(ENOENT);
96 for (i = 0; *uri; i++) {
97 /* parsing uri */
98 len = strcspn(uri, AV_CAT_SEPARATOR);
99 if ((err = av_reallocp(&node_uri, len + 1)) < 0)
100 break;
101 av_strlcpy(node_uri, uri, len + 1);
102 uri += len + strspn(uri + len, AV_CAT_SEPARATOR);
103
104 /* creating URLContext */
105 err = ffurl_open_whitelist(&uc, node_uri, flags,
106 &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h);
107 if (err < 0)
108 break;
109
110 /* creating size */
111 if ((size = ffurl_size(uc)) < 0) {
113 err = AVERROR(ENOSYS);
114 break;
115 }
116
117 if (total_size > INT64_MAX - size) {
120 break;
121 }
122
123 /* assembling */
124 nodes[i].uc = uc;
125 nodes[i].size = size;
126 total_size += size;
127 }
128 av_free(node_uri);
129 data->length = i;
130
131 if (err < 0)
133 else if (!(nodes = av_realloc(nodes, data->length * sizeof(*nodes)))) {
135 err = AVERROR(ENOMEM);
136 } else
137 data->nodes = nodes;
138 data->total_size = total_size;
139 return err;
140}
141#endif
142
143static int concat_read(URLContext *h, unsigned char *buf, int size)
144{
145 int result, total = 0;
146 struct concat_data *data = h->priv_data;
147 struct concat_nodes *nodes = data->nodes;
148 size_t i = data->current;
149
150 while (size > 0) {
151 result = ffurl_read(nodes[i].uc, buf, size);
152 if (result == AVERROR_EOF) {
153 if (i + 1 == data->length ||
154 ffurl_seek(nodes[++i].uc, 0, SEEK_SET) < 0)
155 break;
156 result = 0;
157 }
158 if (result < 0)
159 return total ? total : result;
160 total += result;
161 buf += result;
162 size -= result;
163 }
164 data->current = i;
165 return total ? total : result;
166}
167
169{
170 int64_t result;
171 struct concat_data *data = h->priv_data;
172 struct concat_nodes *nodes = data->nodes;
173 size_t i;
174
175 if ((whence & AVSEEK_SIZE))
176 return data->total_size;
177 switch (whence) {
178 case SEEK_END:
179 for (i = data->length - 1; i && pos < -nodes[i].size; i--)
180 pos += nodes[i].size;
181 break;
182 case SEEK_CUR:
183 /* get the absolute position */
184 for (i = 0; i != data->current; i++)
185 pos += nodes[i].size;
186 pos += ffurl_seek(nodes[i].uc, 0, SEEK_CUR);
187 whence = SEEK_SET;
188 /* fall through with the absolute position */
190 case SEEK_SET:
191 for (i = 0; i != data->length - 1 && pos >= nodes[i].size; i++)
192 pos -= nodes[i].size;
193 break;
194 default:
195 return AVERROR(EINVAL);
196 }
197
198 result = ffurl_seek(nodes[i].uc, pos, whence);
199 if (result >= 0) {
200 data->current = i;
201 while (i)
202 result += nodes[--i].size;
203 }
204 return result;
205}
206
207#if CONFIG_CONCAT_PROTOCOL
209 .name = "concat",
210 .url_open = concat_open,
211 .url_read = concat_read,
212 .url_seek = concat_seek,
213 .url_close = concat_close,
214 .priv_data_size = sizeof(struct concat_data),
215 .default_whitelist = "concat,file,subfile",
216};
217#endif
218
219#if CONFIG_CONCATF_PROTOCOL
220static av_cold int concatf_open(URLContext *h, const char *uri, int flags)
221{
222 AVBPrint bp;
223 struct concat_data *data = h->priv_data;
224 AVIOContext *in = NULL;
225 const char *cursor;
227 unsigned int nodes_size = 0;
228 size_t i = 0;
229 int err;
230
231 if (!av_strstart(uri, "concatf:", &uri)) {
232 av_log(h, AV_LOG_ERROR, "URL %s lacks prefix\n", uri);
233 return AVERROR(EINVAL);
234 }
235
236 /* handle input */
237 if (!*uri)
238 return AVERROR(ENOENT);
239
240 err = ffio_open_whitelist(&in, uri, AVIO_FLAG_READ, &h->interrupt_callback,
241 NULL, h->protocol_whitelist, h->protocol_blacklist);
242 if (err < 0)
243 return err;
244
246 err = avio_read_to_bprint(in, &bp, SIZE_MAX);
247 avio_closep(&in);
248 if (err < 0) {
250 return err;
251 }
252
253 cursor = bp.str;
254 while (*cursor) {
255 struct concat_nodes *nodes;
256 URLContext *uc;
257 char *node_uri;
259 size_t len = i;
260 int leading_spaces = strspn(cursor, " \n\t\r");
261
262 if (!cursor[leading_spaces])
263 break;
264
265 node_uri = av_get_token(&cursor, "\r\n");
266 if (!node_uri) {
267 err = AVERROR(ENOMEM);
268 break;
269 }
270 if (*cursor)
271 cursor++;
272
273 if (++len == SIZE_MAX / sizeof(*nodes)) {
274 av_free(node_uri);
275 err = AVERROR(ENAMETOOLONG);
276 break;
277 }
278
279 /* creating URLContext */
280 err = ffurl_open_whitelist(&uc, node_uri, flags,
281 &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h);
282 av_free(node_uri);
283 if (err < 0)
284 break;
285
286 /* creating size */
287 if ((size = ffurl_size(uc)) < 0) {
289 err = AVERROR(ENOSYS);
290 break;
291 }
292
293 if (total_size > INT64_MAX - size) {
296 break;
297 }
298
299 nodes = av_fast_realloc(data->nodes, &nodes_size, sizeof(*nodes) * len);
300 if (!nodes) {
302 err = AVERROR(ENOMEM);
303 break;
304 }
305 data->nodes = nodes;
306
307 /* assembling */
308 data->nodes[i].uc = uc;
309 data->nodes[i++].size = size;
310 total_size += size;
311 }
313 data->length = i;
314
315 if (!data->length)
317 if (err < 0)
319
320 data->total_size = total_size;
321 return err;
322}
323
325 .name = "concatf",
326 .url_open = concatf_open,
327 .url_read = concat_read,
328 .url_seek = concat_seek,
329 .url_close = concat_close,
330 .priv_data_size = sizeof(struct concat_data),
331 .default_whitelist = "concatf,concat,file,subfile",
332};
333#endif
int ffio_open_whitelist(AVIOContext **s, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist)
Definition avio.c:551
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist, URLContext *parent)
Create an URLContext for accessing to the resource indicated by url, and open it.
Definition avio.c:461
int64_t ffurl_size(URLContext *h)
Return the filesize of the resource accessed by h, AVERROR(ENOSYS) if the operation is not supported ...
Definition avio.c:867
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition avio.c:656
int ffurl_close(URLContext *h)
Definition avio.c:679
int avio_closep(AVIOContext **s)
Close the resource accessed by the AVIOContext *s, free it and set the pointer pointing to it to NULL...
Definition avio.c:717
#define AVIO_FLAG_READ
read-only
Definition avio.h:617
#define AVSEEK_SIZE
Passing this as the "whence" parameter to a seek function causes it to return the filesize without se...
Definition avio.h:468
int avio_read_to_bprint(AVIOContext *h, struct AVBPrint *pb, size_t max_size)
Read contents of h into print buffer, up to max_size bytes, or up to EOF.
Definition aviobuf.c:1254
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition bprint.c:69
AVBPrint public header.
#define AV_BPRINT_SIZE_UNLIMITED
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
static int concat_read(URLContext *h, unsigned char *buf, int size)
Definition concat.c:143
static av_cold int concat_close(URLContext *h)
Definition concat.c:51
#define AV_CAT_SEPARATOR
Definition concat.c:37
static int64_t concat_seek(URLContext *h, int64_t pos, int whence)
Definition concat.c:168
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
error code definitions
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition bprint.c:235
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition mem.c:495
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition mem.c:217
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition mem.c:188
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition avstring.c:36
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition avstring.c:85
char * av_get_token(const char **buf, const char *term)
Unescape the given string until a non escaped terminating char, and return the token corresponding to...
Definition avstring.c:143
Macro definitions for various function/variable attributes.
#define av_fallthrough
Definition attributes.h:67
#define av_cold
Definition attributes.h:117
Memory handling functions.
const char data[16]
Definition mxf.c:149
#define av_realloc(p, s)
Definition ops_static.c:54
const URLProtocol ff_concatf_protocol
const URLProtocol ff_concat_protocol
unsigned int pos
Definition spdifenc.c:431
Bytestream IO Context.
Definition avio.h:160
size_t length
number of cat'ed nodes
Definition concat.c:46
size_t current
index of currently read node
Definition concat.c:47
struct concat_nodes * nodes
list of nodes to concat
Definition concat.c:45
int64_t total_size
Definition concat.c:48
URLContext * uc
node's URLContext
Definition concat.c:40
int64_t size
url filesize
Definition concat.c:41
#define av_free(p)
#define av_freep(p)
#define av_log(a,...)
int size
unbuffered private I/O API
static int64_t ffurl_seek(URLContext *h, int64_t pos, int whence)
Change the position that will be used by the next read/write operation on the resource accessed by h.
Definition url.h:224
static int ffurl_read(URLContext *h, uint8_t *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf.
Definition url.h:183
int len