annotate ffmpeg/libavformat/concat.c @ 13:844d341cf643 tip

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