3 * Copyright (c) 2009 Daniel Verkamp <daniel at drv.nu>
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * @brief Vivo stream demuxer
25 * @author Daniel Verkamp <daniel at drv.nu>
26 * @sa http://wiki.multimedia.cx/index.php?title=Vivo
29 #include "libavutil/parseutils.h"
33 typedef struct VivoContext
{
40 uint8_t text
[1024 + 1];
43 static int vivo_probe(AVProbeData
*p
)
45 const unsigned char *buf
= p
->buf
;
46 unsigned c
, length
= 0;
48 // stream must start with packet of type 0 and sequence number 0
52 // read at most 2 bytes of coded length
57 length
= (length
<< 7) | (c
& 0x7F);
59 if (c
& 0x80 || length
> 1024 || length
< 21)
62 if (memcmp(buf
, "\r\nVersion:Vivo/", 15))
66 if (*buf
< '0' && *buf
> '2')
69 return AVPROBE_SCORE_MAX
;
72 static int vivo_get_packet_header(AVFormatContext
*s
)
74 VivoContext
*vivo
= s
->priv_data
;
75 AVIOContext
*pb
= s
->pb
;
76 unsigned c
, get_length
= 0;
88 vivo
->sequence
= c
& 0xF;
91 case 0: get_length
= 1; break;
92 case 1: vivo
->length
= 128; break;
93 case 2: get_length
= 1; break;
94 case 3: vivo
->length
= 40; break;
95 case 4: vivo
->length
= 24; break;
97 av_log(s
, AV_LOG_ERROR
, "unknown packet type %d\n", vivo
->type
);
98 return AVERROR_INVALIDDATA
;
103 vivo
->length
= c
& 0x7F;
106 vivo
->length
= (vivo
->length
<< 7) | (c
& 0x7F);
109 av_log(s
, AV_LOG_ERROR
, "coded length is more than two bytes\n");
110 return AVERROR_INVALIDDATA
;
118 static int vivo_read_header(AVFormatContext
*s
)
120 VivoContext
*vivo
= s
->priv_data
;
121 AVRational fps
= { 1, 25};
123 unsigned char *line
, *line_end
, *key
, *value
;
126 int64_t duration
= 0;
129 vst
= avformat_new_stream(s
, NULL
);
130 ast
= avformat_new_stream(s
, NULL
);
132 return AVERROR(ENOMEM
);
134 ast
->codec
->sample_rate
= 8000;
137 if ((ret
= vivo_get_packet_header(s
)) < 0)
140 // done reading all text header packets?
141 if (vivo
->sequence
|| vivo
->type
)
144 if (vivo
->length
<= 1024) {
145 avio_read(s
->pb
, vivo
->text
, vivo
->length
);
146 vivo
->text
[vivo
->length
] = 0;
148 av_log(s
, AV_LOG_WARNING
, "too big header, skipping\n");
149 avio_skip(s
->pb
, vivo
->length
);
155 line_end
= strstr(line
, "\r\n");
161 line
= line_end
+ 2; // skip \r\n
163 if (line_end
== key
) // skip blank lines
166 value
= strchr(key
, ':');
168 av_log(s
, AV_LOG_WARNING
, "missing colon in key:value pair '%s'\n",
175 av_log(s
, AV_LOG_DEBUG
, "header: '%s' = '%s'\n", key
, value
);
177 value_int
= strtol(value
, &end_value
, 10);
179 if (*end_value
== 0) { // valid integer
180 av_log(s
, AV_LOG_DEBUG
, "got a valid integer (%ld)\n", value_int
);
182 if (!strcmp(key
, "Duration")) {
183 duration
= value_int
;
184 } else if (!strcmp(key
, "Width")) {
185 vst
->codec
->width
= value_int
;
186 } else if (!strcmp(key
, "Height")) {
187 vst
->codec
->height
= value_int
;
188 } else if (!strcmp(key
, "TimeUnitNumerator")) {
189 fps
.num
= value_int
/ 1000;
190 } else if (!strcmp(key
, "TimeUnitDenominator")) {
192 } else if (!strcmp(key
, "SamplingFrequency")) {
193 ast
->codec
->sample_rate
= value_int
;
194 } else if (!strcmp(key
, "NominalBitrate")) {
195 } else if (!strcmp(key
, "Length")) {
202 if (!strcmp(key
, "Version")) {
203 if (sscanf(value
, "Vivo/%d.", &vivo
->version
) != 1)
204 return AVERROR_INVALIDDATA
;
206 } else if (!strcmp(key
, "FPS")) {
210 if (!av_parse_ratio(&tmp
, value
, 10000, AV_LOG_WARNING
, s
))
215 av_dict_set(&s
->metadata
, key
, value
, 0);
219 avpriv_set_pts_info(ast
, 64, 1, ast
->codec
->sample_rate
);
220 avpriv_set_pts_info(vst
, 64, fps
.num
, fps
.den
);
222 s
->duration
= av_rescale(duration
, 1000, 1);
225 vst
->codec
->codec_tag
= 0;
226 vst
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
228 if (vivo
->version
== 1) {
229 vst
->codec
->codec_id
= AV_CODEC_ID_H263
;
230 ast
->codec
->codec_id
= AV_CODEC_ID_G723_1
;
231 ast
->codec
->bits_per_coded_sample
= 8;
232 ast
->codec
->block_align
= 24;
233 ast
->codec
->bit_rate
= 6400;
237 ast
->codec
->codec_tag
= 0;
238 ast
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
239 ast
->codec
->channels
= 1;
244 static int vivo_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
246 VivoContext
*vivo
= s
->priv_data
;
247 AVIOContext
*pb
= s
->pb
;
248 unsigned old_sequence
= vivo
->sequence
, old_type
= vivo
->type
;
249 int stream_index
, ret
= 0;
256 switch (vivo
->type
) {
258 avio_skip(pb
, vivo
->length
);
259 if ((ret
= vivo_get_packet_header(s
)) < 0)
271 av_log(s
, AV_LOG_ERROR
, "unknown packet type %d\n", vivo
->type
);
272 return AVERROR_INVALIDDATA
;
275 if ((ret
= av_get_packet(pb
, pkt
, vivo
->length
)) < 0)
278 // get next packet header
279 if ((ret
= vivo_get_packet_header(s
)) < 0)
282 while (vivo
->sequence
== old_sequence
&&
283 (((vivo
->type
- 1) >> 1) == ((old_type
- 1) >> 1))) {
289 if ((ret
= av_append_packet(pb
, pkt
, vivo
->length
)) < 0)
292 // get next packet header
293 if ((ret
= vivo_get_packet_header(s
)) < 0)
297 pkt
->stream_index
= stream_index
;
305 AVInputFormat ff_vivo_demuxer
= {
307 .long_name
= NULL_IF_CONFIG_SMALL("Vivo"),
308 .priv_data_size
= sizeof(VivoContext
),
309 .read_probe
= vivo_probe
,
310 .read_header
= vivo_read_header
,
311 .read_packet
= vivo_read_packet
,