annotate concat.c @ 6048:e507a21a9566 libavformat

matroskaenc: Write codec time base as default duration for video tracks. This isn't exactly semantically equivalent, but the field has already been long abused to mean this, and writing it helps in determining a decent cfr time base when transcoding from a mkv where the video codec stores none (VP8).
author conrad
date Mon, 24 May 2010 08:58:19 +0000
parents d3d45b140065
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5634
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
1 /*
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
2 * Concat URL protocol
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
3 * Copyright (c) 2006 Steve Lhomme
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
4 * Copyright (c) 2007 Wolfram Gloger
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
5 * Copyright (c) 2010 Michele OrrĂ¹
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
6 *
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
7 * This file is part of FFmpeg.
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
8 *
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
9 * FFmpeg is free software; you can redistribute it and/or
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
10 * modify it under the terms of the GNU Lesser General Public
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
11 * License as published by the Free Software Foundation; either
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
12 * version 2.1 of the License, or (at your option) any later version.
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
13 *
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
14 * FFmpeg is distributed in the hope that it will be useful,
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
17 * Lesser General Public License for more details.
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
18 *
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
19 * You should have received a copy of the GNU Lesser General Public
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
20 * License along with FFmpeg; if not, write to the Free Software
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
22 */
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
23
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
24 #include "avformat.h"
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
25 #include "libavutil/avstring.h"
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
26 #include "libavutil/mem.h"
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
27
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
28 #define AV_CAT_SEPARATOR "|"
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
29
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
30 struct concat_nodes {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
31 URLContext *uc; ///< node's URLContext
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
32 int64_t size; ///< url filesize
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
33 };
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
34
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
35 struct concat_data {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
36 struct concat_nodes *nodes; ///< list of nodes to concat
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
37 size_t length; ///< number of cat'ed nodes
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
38 size_t current; ///< index of currently read node
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
39 };
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
40
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
41 static av_cold int concat_close(URLContext *h)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
42 {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
43 int err = 0;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
44 size_t i;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
45 struct concat_data *data = h->priv_data;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
46 struct concat_nodes *nodes = data->nodes;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
47
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
48 for (i = 0; i != data->length; i++)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
49 err |= url_close(nodes[i].uc);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
50
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
51 av_freep(&data->nodes);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
52 av_freep(&h->priv_data);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
53
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
54 return err < 0 ? -1 : 0;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
55 }
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
56
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
57 static av_cold int concat_open(URLContext *h, const char *uri, int flags)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
58 {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
59 char *node_uri = NULL, *tmp_uri;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
60 int err = 0;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
61 int64_t size;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
62 size_t len, i;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
63 URLContext *uc;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
64 struct concat_data *data;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
65 struct concat_nodes *nodes;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
66
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
67 av_strstart(uri, "concat:", &uri);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
68
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
69 /* creating data */
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
70 if (!(data = av_mallocz(sizeof(*data))))
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
71 return AVERROR(ENOMEM);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
72 h->priv_data = data;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
73
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
74 for (i = 0, len = 1; uri[i]; i++)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
75 if (uri[i] == *AV_CAT_SEPARATOR)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
76 /* integer overflow */
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
77 if (++len == UINT_MAX / sizeof(*nodes)) {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
78 av_freep(&h->priv_data);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
79 return AVERROR(ENAMETOOLONG);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
80 }
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
81
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
82 if (!(nodes = av_malloc(sizeof(*nodes) * len))) {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
83 av_freep(&h->priv_data);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
84 return AVERROR(ENOMEM);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
85 } else
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
86 data->nodes = nodes;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
87
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
88 /* handle input */
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
89 if (!*uri)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
90 err = AVERROR(ENOENT);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
91 for (i = 0; *uri; i++) {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
92 /* parsing uri */
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
93 len = strcspn(uri, AV_CAT_SEPARATOR);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
94 if (!(tmp_uri = av_realloc(node_uri, len+1))) {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
95 err = AVERROR(ENOMEM);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
96 break;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
97 } else
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
98 node_uri = tmp_uri;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
99 av_strlcpy(node_uri, uri, len+1);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
100 uri += len + strspn(uri+len, AV_CAT_SEPARATOR);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
101
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
102 /* creating URLContext */
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
103 if ((err = url_open(&uc, node_uri, flags)) < 0)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
104 break;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
105
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
106 /* creating size */
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
107 if ((size = url_filesize(uc)) < 0) {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
108 url_close(uc);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
109 err = AVERROR(ENOSYS);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
110 break;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
111 }
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
112
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
113 /* assembling */
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
114 nodes[i].uc = uc;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
115 nodes[i].size = size;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
116 }
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
117 av_free(node_uri);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
118 data->length = i;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
119
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
120 if (err < 0)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
121 concat_close(h);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
122 else if (!(nodes = av_realloc(nodes, data->length * sizeof(*nodes)))) {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
123 concat_close(h);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
124 err = AVERROR(ENOMEM);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
125 } else
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
126 data->nodes = nodes;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
127 return err;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
128 }
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
129
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
130 static int concat_read(URLContext *h, unsigned char *buf, int size)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
131 {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
132 int result, total = 0;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
133 struct concat_data *data = h->priv_data;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
134 struct concat_nodes *nodes = data->nodes;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
135 size_t i = data->current;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
136
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
137 while (size > 0) {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
138 result = url_read(nodes[i].uc, buf, size);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
139 if (result < 0)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
140 return total ? total : result;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
141 if (!result)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
142 if (i + 1 == data->length ||
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
143 url_seek(nodes[++i].uc, 0, SEEK_SET) < 0)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
144 break;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
145 total += result;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
146 buf += result;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
147 size -= result;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
148 }
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
149 data->current = i;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
150 return total;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
151 }
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
152
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
153 static int64_t concat_seek(URLContext *h, int64_t pos, int whence)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
154 {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
155 int64_t result;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
156 struct concat_data *data = h->priv_data;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
157 struct concat_nodes *nodes = data->nodes;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
158 size_t i;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
159
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
160 switch (whence) {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
161 case SEEK_END:
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
162 for (i = data->length - 1;
5772
d3d45b140065 Fix concat seeking SEEK_END case.
stefano
parents: 5771
diff changeset
163 i && pos < -nodes[i].size;
5634
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
164 i--)
5772
d3d45b140065 Fix concat seeking SEEK_END case.
stefano
parents: 5771
diff changeset
165 pos += nodes[i].size;
5634
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
166 break;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
167 case SEEK_CUR:
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
168 /* get the absolute position */
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
169 for (i = 0; i != data->current; i++)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
170 pos += nodes[i].size;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
171 pos += url_seek(nodes[i].uc, 0, SEEK_CUR);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
172 whence = SEEK_SET;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
173 /* fall through with the absolute position */
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
174 case SEEK_SET:
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
175 for (i = 0; i != data->length - 1 && pos >= nodes[i].size; i++)
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
176 pos -= nodes[i].size;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
177 break;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
178 default:
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
179 return AVERROR(EINVAL);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
180 }
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
181
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
182 result = url_seek(nodes[i].uc, pos, whence);
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
183 if (result >= 0) {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
184 data->current = i;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
185 while (i)
5771
e8c8f5a002ff Fix concat seek result.
stefano
parents: 5634
diff changeset
186 result += nodes[--i].size;
5634
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
187 }
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
188 return result;
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
189 }
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
190
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
191 URLProtocol concat_protocol = {
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
192 "concat",
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
193 concat_open,
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
194 concat_read,
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
195 NULL,
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
196 concat_seek,
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
197 concat_close,
b280788e1936 Implement a physical concatenation protocol.
stefano
parents:
diff changeset
198 };