annotate ffmpeg/libavformat/vivo.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 * Vivo stream demuxer
yading@11 3 * Copyright (c) 2009 Daniel Verkamp <daniel at drv.nu>
yading@11 4 *
yading@11 5 * This file is part of FFmpeg.
yading@11 6 *
yading@11 7 * FFmpeg is free software; you can redistribute it and/or
yading@11 8 * modify it under the terms of the GNU Lesser General Public
yading@11 9 * License as published by the Free Software Foundation; either
yading@11 10 * version 2.1 of the License, or (at your option) any later version.
yading@11 11 *
yading@11 12 * FFmpeg is distributed in the hope that it will be useful,
yading@11 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 15 * Lesser General Public License for more details.
yading@11 16 *
yading@11 17 * You should have received a copy of the GNU Lesser General Public
yading@11 18 * License along with FFmpeg; if not, write to the Free Software
yading@11 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 20 */
yading@11 21
yading@11 22 /**
yading@11 23 * @file
yading@11 24 * @brief Vivo stream demuxer
yading@11 25 * @author Daniel Verkamp <daniel at drv.nu>
yading@11 26 * @sa http://wiki.multimedia.cx/index.php?title=Vivo
yading@11 27 */
yading@11 28
yading@11 29 #include "libavutil/parseutils.h"
yading@11 30 #include "avformat.h"
yading@11 31 #include "internal.h"
yading@11 32
yading@11 33 typedef struct VivoContext {
yading@11 34 int version;
yading@11 35
yading@11 36 int type;
yading@11 37 int sequence;
yading@11 38 int length;
yading@11 39
yading@11 40 uint8_t text[1024 + 1];
yading@11 41 } VivoContext;
yading@11 42
yading@11 43 static int vivo_probe(AVProbeData *p)
yading@11 44 {
yading@11 45 const unsigned char *buf = p->buf;
yading@11 46 unsigned c, length = 0;
yading@11 47
yading@11 48 // stream must start with packet of type 0 and sequence number 0
yading@11 49 if (*buf++ != 0)
yading@11 50 return 0;
yading@11 51
yading@11 52 // read at most 2 bytes of coded length
yading@11 53 c = *buf++;
yading@11 54 length = c & 0x7F;
yading@11 55 if (c & 0x80) {
yading@11 56 c = *buf++;
yading@11 57 length = (length << 7) | (c & 0x7F);
yading@11 58 }
yading@11 59 if (c & 0x80 || length > 1024 || length < 21)
yading@11 60 return 0;
yading@11 61
yading@11 62 if (memcmp(buf, "\r\nVersion:Vivo/", 15))
yading@11 63 return 0;
yading@11 64 buf += 15;
yading@11 65
yading@11 66 if (*buf < '0' && *buf > '2')
yading@11 67 return 0;
yading@11 68
yading@11 69 return AVPROBE_SCORE_MAX;
yading@11 70 }
yading@11 71
yading@11 72 static int vivo_get_packet_header(AVFormatContext *s)
yading@11 73 {
yading@11 74 VivoContext *vivo = s->priv_data;
yading@11 75 AVIOContext *pb = s->pb;
yading@11 76 unsigned c, get_length = 0;
yading@11 77
yading@11 78 if (url_feof(pb))
yading@11 79 return AVERROR_EOF;
yading@11 80
yading@11 81 c = avio_r8(pb);
yading@11 82 if (c == 0x82) {
yading@11 83 get_length = 1;
yading@11 84 c = avio_r8(pb);
yading@11 85 }
yading@11 86
yading@11 87 vivo->type = c >> 4;
yading@11 88 vivo->sequence = c & 0xF;
yading@11 89
yading@11 90 switch (vivo->type) {
yading@11 91 case 0: get_length = 1; break;
yading@11 92 case 1: vivo->length = 128; break;
yading@11 93 case 2: get_length = 1; break;
yading@11 94 case 3: vivo->length = 40; break;
yading@11 95 case 4: vivo->length = 24; break;
yading@11 96 default:
yading@11 97 av_log(s, AV_LOG_ERROR, "unknown packet type %d\n", vivo->type);
yading@11 98 return AVERROR_INVALIDDATA;
yading@11 99 }
yading@11 100
yading@11 101 if (get_length) {
yading@11 102 c = avio_r8(pb);
yading@11 103 vivo->length = c & 0x7F;
yading@11 104 if (c & 0x80) {
yading@11 105 c = avio_r8(pb);
yading@11 106 vivo->length = (vivo->length << 7) | (c & 0x7F);
yading@11 107
yading@11 108 if (c & 0x80) {
yading@11 109 av_log(s, AV_LOG_ERROR, "coded length is more than two bytes\n");
yading@11 110 return AVERROR_INVALIDDATA;
yading@11 111 }
yading@11 112 }
yading@11 113 }
yading@11 114
yading@11 115 return 0;
yading@11 116 }
yading@11 117
yading@11 118 static int vivo_read_header(AVFormatContext *s)
yading@11 119 {
yading@11 120 VivoContext *vivo = s->priv_data;
yading@11 121 AVRational fps = { 1, 25};
yading@11 122 AVStream *ast, *vst;
yading@11 123 unsigned char *line, *line_end, *key, *value;
yading@11 124 long value_int;
yading@11 125 int ret, value_used;
yading@11 126 int64_t duration = 0;
yading@11 127 char *end_value;
yading@11 128
yading@11 129 vst = avformat_new_stream(s, NULL);
yading@11 130 ast = avformat_new_stream(s, NULL);
yading@11 131 if (!ast || !vst)
yading@11 132 return AVERROR(ENOMEM);
yading@11 133
yading@11 134 ast->codec->sample_rate = 8000;
yading@11 135
yading@11 136 while (1) {
yading@11 137 if ((ret = vivo_get_packet_header(s)) < 0)
yading@11 138 return ret;
yading@11 139
yading@11 140 // done reading all text header packets?
yading@11 141 if (vivo->sequence || vivo->type)
yading@11 142 break;
yading@11 143
yading@11 144 if (vivo->length <= 1024) {
yading@11 145 avio_read(s->pb, vivo->text, vivo->length);
yading@11 146 vivo->text[vivo->length] = 0;
yading@11 147 } else {
yading@11 148 av_log(s, AV_LOG_WARNING, "too big header, skipping\n");
yading@11 149 avio_skip(s->pb, vivo->length);
yading@11 150 continue;
yading@11 151 }
yading@11 152
yading@11 153 line = vivo->text;
yading@11 154 while (*line) {
yading@11 155 line_end = strstr(line, "\r\n");
yading@11 156 if (!line_end)
yading@11 157 break;
yading@11 158
yading@11 159 *line_end = 0;
yading@11 160 key = line;
yading@11 161 line = line_end + 2; // skip \r\n
yading@11 162
yading@11 163 if (line_end == key) // skip blank lines
yading@11 164 continue;
yading@11 165
yading@11 166 value = strchr(key, ':');
yading@11 167 if (!value) {
yading@11 168 av_log(s, AV_LOG_WARNING, "missing colon in key:value pair '%s'\n",
yading@11 169 value);
yading@11 170 continue;
yading@11 171 }
yading@11 172
yading@11 173 *value++ = 0;
yading@11 174
yading@11 175 av_log(s, AV_LOG_DEBUG, "header: '%s' = '%s'\n", key, value);
yading@11 176
yading@11 177 value_int = strtol(value, &end_value, 10);
yading@11 178 value_used = 0;
yading@11 179 if (*end_value == 0) { // valid integer
yading@11 180 av_log(s, AV_LOG_DEBUG, "got a valid integer (%ld)\n", value_int);
yading@11 181 value_used = 1;
yading@11 182 if (!strcmp(key, "Duration")) {
yading@11 183 duration = value_int;
yading@11 184 } else if (!strcmp(key, "Width")) {
yading@11 185 vst->codec->width = value_int;
yading@11 186 } else if (!strcmp(key, "Height")) {
yading@11 187 vst->codec->height = value_int;
yading@11 188 } else if (!strcmp(key, "TimeUnitNumerator")) {
yading@11 189 fps.num = value_int / 1000;
yading@11 190 } else if (!strcmp(key, "TimeUnitDenominator")) {
yading@11 191 fps.den = value_int;
yading@11 192 } else if (!strcmp(key, "SamplingFrequency")) {
yading@11 193 ast->codec->sample_rate = value_int;
yading@11 194 } else if (!strcmp(key, "NominalBitrate")) {
yading@11 195 } else if (!strcmp(key, "Length")) {
yading@11 196 // size of file
yading@11 197 } else {
yading@11 198 value_used = 0;
yading@11 199 }
yading@11 200 }
yading@11 201
yading@11 202 if (!strcmp(key, "Version")) {
yading@11 203 if (sscanf(value, "Vivo/%d.", &vivo->version) != 1)
yading@11 204 return AVERROR_INVALIDDATA;
yading@11 205 value_used = 1;
yading@11 206 } else if (!strcmp(key, "FPS")) {
yading@11 207 AVRational tmp;
yading@11 208
yading@11 209 value_used = 1;
yading@11 210 if (!av_parse_ratio(&tmp, value, 10000, AV_LOG_WARNING, s))
yading@11 211 fps = av_inv_q(tmp);
yading@11 212 }
yading@11 213
yading@11 214 if (!value_used)
yading@11 215 av_dict_set(&s->metadata, key, value, 0);
yading@11 216 }
yading@11 217 }
yading@11 218
yading@11 219 avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
yading@11 220 avpriv_set_pts_info(vst, 64, fps.num, fps.den);
yading@11 221 if (duration)
yading@11 222 s->duration = av_rescale(duration, 1000, 1);
yading@11 223
yading@11 224 vst->start_time = 0;
yading@11 225 vst->codec->codec_tag = 0;
yading@11 226 vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
yading@11 227
yading@11 228 if (vivo->version == 1) {
yading@11 229 vst->codec->codec_id = AV_CODEC_ID_H263;
yading@11 230 ast->codec->codec_id = AV_CODEC_ID_G723_1;
yading@11 231 ast->codec->bits_per_coded_sample = 8;
yading@11 232 ast->codec->block_align = 24;
yading@11 233 ast->codec->bit_rate = 6400;
yading@11 234 }
yading@11 235
yading@11 236 ast->start_time = 0;
yading@11 237 ast->codec->codec_tag = 0;
yading@11 238 ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
yading@11 239 ast->codec->channels = 1;
yading@11 240
yading@11 241 return 0;
yading@11 242 }
yading@11 243
yading@11 244 static int vivo_read_packet(AVFormatContext *s, AVPacket *pkt)
yading@11 245 {
yading@11 246 VivoContext *vivo = s->priv_data;
yading@11 247 AVIOContext *pb = s->pb;
yading@11 248 unsigned old_sequence = vivo->sequence, old_type = vivo->type;
yading@11 249 int stream_index, ret = 0;
yading@11 250
yading@11 251 restart:
yading@11 252
yading@11 253 if (url_feof(pb))
yading@11 254 return AVERROR_EOF;
yading@11 255
yading@11 256 switch (vivo->type) {
yading@11 257 case 0:
yading@11 258 avio_skip(pb, vivo->length);
yading@11 259 if ((ret = vivo_get_packet_header(s)) < 0)
yading@11 260 return ret;
yading@11 261 goto restart;
yading@11 262 case 1:
yading@11 263 case 2: // video
yading@11 264 stream_index = 0;
yading@11 265 break;
yading@11 266 case 3:
yading@11 267 case 4: // audio
yading@11 268 stream_index = 1;
yading@11 269 break;
yading@11 270 default:
yading@11 271 av_log(s, AV_LOG_ERROR, "unknown packet type %d\n", vivo->type);
yading@11 272 return AVERROR_INVALIDDATA;
yading@11 273 }
yading@11 274
yading@11 275 if ((ret = av_get_packet(pb, pkt, vivo->length)) < 0)
yading@11 276 goto fail;
yading@11 277
yading@11 278 // get next packet header
yading@11 279 if ((ret = vivo_get_packet_header(s)) < 0)
yading@11 280 goto fail;
yading@11 281
yading@11 282 while (vivo->sequence == old_sequence &&
yading@11 283 (((vivo->type - 1) >> 1) == ((old_type - 1) >> 1))) {
yading@11 284 if (url_feof(pb)) {
yading@11 285 ret = AVERROR_EOF;
yading@11 286 break;
yading@11 287 }
yading@11 288
yading@11 289 if ((ret = av_append_packet(pb, pkt, vivo->length)) < 0)
yading@11 290 break;
yading@11 291
yading@11 292 // get next packet header
yading@11 293 if ((ret = vivo_get_packet_header(s)) < 0)
yading@11 294 break;
yading@11 295 }
yading@11 296
yading@11 297 pkt->stream_index = stream_index;
yading@11 298
yading@11 299 fail:
yading@11 300 if (ret < 0)
yading@11 301 av_free_packet(pkt);
yading@11 302 return ret;
yading@11 303 }
yading@11 304
yading@11 305 AVInputFormat ff_vivo_demuxer = {
yading@11 306 .name = "vivo",
yading@11 307 .long_name = NULL_IF_CONFIG_SMALL("Vivo"),
yading@11 308 .priv_data_size = sizeof(VivoContext),
yading@11 309 .read_probe = vivo_probe,
yading@11 310 .read_header = vivo_read_header,
yading@11 311 .read_packet = vivo_read_packet,
yading@11 312 .extensions = "viv",
yading@11 313 };