FFmpeg
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
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 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 "
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
;
///< node's URLContext
33
int64_t
size
;
///< url filesize
34
};
35
36
struct
concat_data
{
37
struct
concat_nodes
*
nodes
;
///< list of nodes to concat
38
size_t
length
;
///< number of cat'ed nodes
39
size_t
current
;
///< index of currently read node
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
};
Generated on Sat May 25 2013 03:58:46 for FFmpeg by
1.8.2