Thanks to visit codestin.com
Credit goes to www.ffmpeg.org

FFmpeg
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 
28 #include "libavutil/attributes.h"
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 
39 struct concat_nodes {
40  URLContext *uc; ///< node's URLContext
41  int64_t size; ///< url filesize
42 };
43 
44 struct concat_data {
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
67 static 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;
73  URLContext *uc;
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) {
112  ffurl_close(uc);
113  err = AVERROR(ENOSYS);
114  break;
115  }
116 
117  if (total_size > INT64_MAX - size) {
118  ffurl_close(uc);
119  err = AVERROR_INVALIDDATA;
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)
132  concat_close(h);
133  else if (!(nodes = av_realloc(nodes, data->length * sizeof(*nodes)))) {
134  concat_close(h);
135  err = AVERROR(ENOMEM);
136  } else
137  data->nodes = nodes;
138  data->total_size = total_size;
139  return err;
140 }
141 #endif
142 
143 static 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 
168 static int64_t concat_seek(URLContext *h, int64_t pos, int whence)
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
220 static 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;
226  int64_t total_size = 0;
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) {
249  av_bprint_finalize(&bp, NULL);
250  return err;
251  }
252 
253  cursor = bp.str;
254  while (*cursor) {
255  struct concat_nodes *nodes;
256  URLContext *uc;
257  char *node_uri;
258  int64_t size;
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) {
288  ffurl_close(uc);
289  err = AVERROR(ENOSYS);
290  break;
291  }
292 
293  if (total_size > INT64_MAX - size) {
294  ffurl_close(uc);
295  err = AVERROR_INVALIDDATA;
296  break;
297  }
298 
299  nodes = av_fast_realloc(data->nodes, &nodes_size, sizeof(*nodes) * len);
300  if (!nodes) {
301  ffurl_close(uc);
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  }
312  av_bprint_finalize(&bp, NULL);
313  data->length = i;
314 
315  if (!data->length)
316  err = AVERROR_INVALIDDATA;
317  if (err < 0)
318  concat_close(h);
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
flags
const SwsFlags flags[]
Definition: swscale.c:72
ffurl_seek
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:222
ffio_open_whitelist
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:477
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
concat_data::length
size_t length
number of cat'ed nodes
Definition: concat.c:46
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
int64_t
long long int64_t
Definition: coverity.c:34
AVSEEK_SIZE
#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
data
const char data[16]
Definition: mxf.c:149
ffurl_close
int ffurl_close(URLContext *h)
Definition: avio.c:617
URLProtocol
Definition: url.h:51
AV_CAT_SEPARATOR
#define AV_CAT_SEPARATOR
Definition: concat.c:37
concat_nodes::size
int64_t size
url filesize
Definition: concat.c:41
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
av_cold
#define av_cold
Definition: attributes.h:119
ffurl_open_whitelist
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:368
av_fast_realloc
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:497
avio_read_to_bprint
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
av_realloc_array
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:217
ff_concat_protocol
const URLProtocol ff_concat_protocol
av_fallthrough
#define av_fallthrough
Definition: attributes.h:67
result
and forward the result(frame or status change) to the corresponding input. If nothing is possible
NULL
#define NULL
Definition: coverity.c:32
error.h
AVIOContext
Bytestream IO Context.
Definition: avio.h:160
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
size
int size
Definition: twinvq_data.h:10344
concat_data::nodes
struct concat_nodes * nodes
list of nodes to concat
Definition: concat.c:45
av_reallocp
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
URLProtocol::name
const char * name
Definition: url.h:52
concat_read
static int concat_read(URLContext *h, unsigned char *buf, int size)
Definition: concat.c:143
attributes.h
av_strstart
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
ff_concatf_protocol
const URLProtocol ff_concatf_protocol
bprint.h
URLContext
Definition: url.h:35
avio_internal.h
url.h
len
int len
Definition: vorbis_enc_data.h:426
concat_data::current
size_t current
index of currently read node
Definition: concat.c:47
ffurl_closep
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:594
concat_data::total_size
int64_t total_size
Definition: concat.c:48
concat_seek
static int64_t concat_seek(URLContext *h, int64_t pos, int whence)
Definition: concat.c:168
pos
unsigned int pos
Definition: spdifenc.c:414
concat_nodes::uc
URLContext * uc
node's URLContext
Definition: concat.c:40
av_get_token
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
av_realloc
#define av_realloc(p, s)
Definition: ops_asmgen.c:46
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:617
mem.h
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
avio_closep
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:655
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
concat_data
Definition: concat.c:44
av_strlcpy
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
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
ffurl_size
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:805
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
h
h
Definition: vp9dsp_template.c:2070
concat_close
static av_cold int concat_close(URLContext *h)
Definition: concat.c:51
avstring.h
concat_nodes
Definition: concat.c:39
ffurl_read
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:181