Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
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 Libav.
8
*
9
* Libav 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
* Libav 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 Libav; if not, write to the Free Software
21
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
*/
23
24
#include "
avformat.h
"
25
#include "
libavutil/avstring.h
"
26
#include "
libavutil/mem.h
"
27
#include "
url.h
"
28
29
#define AV_CAT_SEPARATOR "|"
30
31
struct
concat_nodes
{
32
URLContext
*
uc
;
33
int64_t
size
;
34
};
35
36
struct
concat_data
{
37
struct
concat_nodes
*
nodes
;
38
size_t
length
;
39
size_t
current
;
40
};
41
42
static
av_cold
int
concat_close
(
URLContext
*h)
43
{
44
int
err = 0;
45
size_t
i;
46
struct
concat_data
*
data
= h->
priv_data
;
47
struct
concat_nodes
*nodes = data->
nodes
;
48
49
for
(i = 0; i != data->
length
; i++)
50
err |=
ffurl_close
(nodes[i].
uc
);
51
52
av_freep
(&data->
nodes
);
53
54
return
err < 0 ? -1 : 0;
55
}
56
57
static
av_cold
int
concat_open
(
URLContext
*h,
const
char
*uri,
int
flags
)
58
{
59
char
*node_uri =
NULL
, *tmp_uri;
60
int
err = 0;
61
int64_t
size
;
62
size_t
len
, i;
63
URLContext
*
uc
;
64
struct
concat_data
*
data
= h->
priv_data
;
65
struct
concat_nodes
*nodes;
66
67
av_strstart
(uri,
"concat:"
, &uri);
68
69
for
(i = 0, len = 1; uri[i]; i++)
70
if
(uri[i] == *
AV_CAT_SEPARATOR
)
71
/* integer overflow */
72
if
(++len == UINT_MAX /
sizeof
(*nodes)) {
73
av_freep
(&h->
priv_data
);
74
return
AVERROR
(ENAMETOOLONG);
75
}
76
77
if
(!(nodes =
av_malloc
(
sizeof
(*nodes) * len))) {
78
return
AVERROR
(ENOMEM);
79
}
else
80
data->
nodes
= nodes;
81
82
/* handle input */
83
if
(!*uri)
84
err =
AVERROR
(ENOENT);
85
for
(i = 0; *uri; i++) {
86
/* parsing uri */
87
len = strcspn(uri,
AV_CAT_SEPARATOR
);
88
if
(!(tmp_uri =
av_realloc
(node_uri, len+1))) {
89
err =
AVERROR
(ENOMEM);
90
break
;
91
}
else
92
node_uri = tmp_uri;
93
av_strlcpy
(node_uri, uri, len+1);
94
uri += len + strspn(uri+len,
AV_CAT_SEPARATOR
);
95
96
/* creating URLContext */
97
if
((err =
ffurl_open
(&uc, node_uri, flags,
98
&h->
interrupt_callback
,
NULL
)) < 0)
99
break
;
100
101
/* creating size */
102
if
((size =
ffurl_size
(uc)) < 0) {
103
ffurl_close
(uc);
104
err =
AVERROR
(ENOSYS);
105
break
;
106
}
107
108
/* assembling */
109
nodes[i].
uc
=
uc
;
110
nodes[i].
size
=
size
;
111
}
112
av_free
(node_uri);
113
data->
length
= i;
114
115
if
(err < 0)
116
concat_close
(h);
117
else
if
(!(nodes =
av_realloc
(nodes, data->
length
*
sizeof
(*nodes)))) {
118
concat_close
(h);
119
err =
AVERROR
(ENOMEM);
120
}
else
121
data->
nodes
= nodes;
122
return
err;
123
}
124
125
static
int
concat_read
(
URLContext
*h,
unsigned
char
*buf,
int
size
)
126
{
127
int
result, total = 0;
128
struct
concat_data
*
data
= h->
priv_data
;
129
struct
concat_nodes
*nodes = data->
nodes
;
130
size_t
i = data->
current
;
131
132
while
(size > 0) {
133
result =
ffurl_read
(nodes[i].
uc
, buf, size);
134
if
(result < 0)
135
return
total ? total : result;
136
if
(!result)
137
if
(i + 1 == data->
length
||
138
ffurl_seek
(nodes[++i].uc, 0, SEEK_SET) < 0)
139
break
;
140
total += result;
141
buf += result;
142
size -= result;
143
}
144
data->
current
= i;
145
return
total;
146
}
147
148
static
int64_t
concat_seek
(
URLContext
*h, int64_t pos,
int
whence)
149
{
150
int64_t result;
151
struct
concat_data
*
data
= h->
priv_data
;
152
struct
concat_nodes
*nodes = data->
nodes
;
153
size_t
i;
154
155
switch
(whence) {
156
case
SEEK_END:
157
for
(i = data->
length
- 1;
158
i && pos < -nodes[i].
size
;
159
i--)
160
pos += nodes[i].
size
;
161
break
;
162
case
SEEK_CUR:
163
/* get the absolute position */
164
for
(i = 0; i != data->
current
; i++)
165
pos += nodes[i].
size
;
166
pos +=
ffurl_seek
(nodes[i].
uc
, 0, SEEK_CUR);
167
whence = SEEK_SET;
168
/* fall through with the absolute position */
169
case
SEEK_SET:
170
for
(i = 0; i != data->
length
- 1 && pos >= nodes[i].
size
; i++)
171
pos -= nodes[i].
size
;
172
break
;
173
default
:
174
return
AVERROR
(EINVAL);
175
}
176
177
result =
ffurl_seek
(nodes[i].
uc
, pos, whence);
178
if
(result >= 0) {
179
data->
current
= i;
180
while
(i)
181
result += nodes[--i].
size
;
182
}
183
return
result;
184
}
185
186
URLProtocol
ff_concat_protocol
= {
187
.
name
=
"concat"
,
188
.url_open =
concat_open
,
189
.url_read =
concat_read
,
190
.url_seek =
concat_seek
,
191
.url_close =
concat_close
,
192
.priv_data_size =
sizeof
(
struct
concat_data
),
193
};