FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
•
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
vivo.c
Go to the documentation of this file.
1
/*
2
* Vivo stream demuxer
3
* Copyright (c) 2009 Daniel Verkamp <daniel at drv.nu>
4
*
5
* This file is part of FFmpeg.
6
*
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.
11
*
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.
16
*
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
20
*/
21
22
/**
23
* @file
24
* @brief Vivo stream demuxer
25
* @author Daniel Verkamp <daniel at drv.nu>
26
* @sa http://wiki.multimedia.cx/index.php?title=Vivo
27
*/
28
29
#include "
libavutil/parseutils.h
"
30
#include "
avformat.h
"
31
#include "
internal.h
"
32
33
typedef
struct
VivoContext
{
34
int
version
;
35
36
int
type
;
37
int
sequence
;
38
int
length
;
39
40
uint8_t
text
[1024 + 1];
41
}
VivoContext
;
42
43
static
int
vivo_probe
(
AVProbeData
*p)
44
{
45
const
unsigned
char
*
buf
= p->
buf
;
46
unsigned
c
,
length
= 0;
47
48
// stream must start with packet of type 0 and sequence number 0
49
if
(*buf++ != 0)
50
return
0;
51
52
// read at most 2 bytes of coded length
53
c = *buf++;
54
length = c & 0x7F;
55
if
(c & 0x80) {
56
c = *buf++;
57
length = (length << 7) | (c & 0x7F);
58
}
59
if
(c & 0x80 || length > 1024 || length < 21)
60
return
0;
61
62
if
(memcmp(buf,
"\r\nVersion:Vivo/"
, 15))
63
return
0;
64
buf += 15;
65
66
if
(*buf < '0' && *buf >
'2'
)
67
return
0;
68
69
return
AVPROBE_SCORE_MAX
;
70
}
71
72
static
int
vivo_get_packet_header
(
AVFormatContext
*
s
)
73
{
74
VivoContext
*vivo = s->
priv_data
;
75
AVIOContext
*pb = s->
pb
;
76
unsigned
c
, get_length = 0;
77
78
if
(
url_feof
(pb))
79
return
AVERROR_EOF
;
80
81
c =
avio_r8
(pb);
82
if
(c == 0x82) {
83
get_length = 1;
84
c =
avio_r8
(pb);
85
}
86
87
vivo->
type
= c >> 4;
88
vivo->
sequence
= c & 0xF;
89
90
switch
(vivo->
type
) {
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
;
96
default
:
97
av_log
(s,
AV_LOG_ERROR
,
"unknown packet type %d\n"
, vivo->
type
);
98
return
AVERROR_INVALIDDATA
;
99
}
100
101
if
(get_length) {
102
c =
avio_r8
(pb);
103
vivo->
length
= c & 0x7F;
104
if
(c & 0x80) {
105
c =
avio_r8
(pb);
106
vivo->
length
= (vivo->
length
<< 7) | (c & 0x7F);
107
108
if
(c & 0x80) {
109
av_log
(s,
AV_LOG_ERROR
,
"coded length is more than two bytes\n"
);
110
return
AVERROR_INVALIDDATA
;
111
}
112
}
113
}
114
115
return
0;
116
}
117
118
static
int
vivo_read_header
(
AVFormatContext
*
s
)
119
{
120
VivoContext
*vivo = s->
priv_data
;
121
AVRational
fps = { 1, 25};
122
AVStream
*ast, *vst;
123
unsigned
char
*
line
, *line_end, *key, *
value
;
124
long
value_int;
125
int
ret
, value_used;
126
int64_t
duration
= 0;
127
char
*end_value;
128
129
vst =
avformat_new_stream
(s, NULL);
130
ast =
avformat_new_stream
(s, NULL);
131
if
(!ast || !vst)
132
return
AVERROR
(ENOMEM);
133
134
ast->
codec
->
sample_rate
= 8000;
135
136
while
(1) {
137
if
((ret =
vivo_get_packet_header
(s)) < 0)
138
return
ret
;
139
140
// done reading all text header packets?
141
if
(vivo->
sequence
|| vivo->
type
)
142
break
;
143
144
if
(vivo->
length
<= 1024) {
145
avio_read
(s->
pb
, vivo->
text
, vivo->
length
);
146
vivo->
text
[vivo->
length
] = 0;
147
}
else
{
148
av_log
(s,
AV_LOG_WARNING
,
"too big header, skipping\n"
);
149
avio_skip
(s->
pb
, vivo->
length
);
150
continue
;
151
}
152
153
line = vivo->
text
;
154
while
(*line) {
155
line_end = strstr(line,
"\r\n"
);
156
if
(!line_end)
157
break
;
158
159
*line_end = 0;
160
key = line;
161
line = line_end + 2;
// skip \r\n
162
163
if
(line_end == key)
// skip blank lines
164
continue
;
165
166
value = strchr(key,
':'
);
167
if
(!value) {
168
av_log
(s,
AV_LOG_WARNING
,
"missing colon in key:value pair '%s'\n"
,
169
value);
170
continue
;
171
}
172
173
*value++ = 0;
174
175
av_log
(s,
AV_LOG_DEBUG
,
"header: '%s' = '%s'\n"
, key, value);
176
177
value_int = strtol(value, &end_value, 10);
178
value_used = 0;
179
if
(*end_value == 0) {
// valid integer
180
av_log
(s,
AV_LOG_DEBUG
,
"got a valid integer (%ld)\n"
, value_int);
181
value_used = 1;
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"
)) {
191
fps.
den
= value_int;
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"
)) {
196
// size of file
197
}
else
{
198
value_used = 0;
199
}
200
}
201
202
if
(!strcmp(key,
"Version"
)) {
203
if
(sscanf(value,
"Vivo/%d."
, &vivo->
version
) != 1)
204
return
AVERROR_INVALIDDATA
;
205
value_used = 1;
206
}
else
if
(!strcmp(key,
"FPS"
)) {
207
AVRational
tmp;
208
209
value_used = 1;
210
if
(!
av_parse_ratio
(&tmp, value, 10000,
AV_LOG_WARNING
, s))
211
fps =
av_inv_q
(tmp);
212
}
213
214
if
(!value_used)
215
av_dict_set
(&s->
metadata
, key, value, 0);
216
}
217
}
218
219
avpriv_set_pts_info
(ast, 64, 1, ast->
codec
->
sample_rate
);
220
avpriv_set_pts_info
(vst, 64, fps.
num
, fps.
den
);
221
if
(duration)
222
s->
duration
=
av_rescale
(duration, 1000, 1);
223
224
vst->
start_time
= 0;
225
vst->
codec
->
codec_tag
= 0;
226
vst->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
227
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;
234
}
235
236
ast->
start_time
= 0;
237
ast->
codec
->
codec_tag
= 0;
238
ast->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
239
ast->
codec
->
channels
= 1;
240
241
return
0;
242
}
243
244
static
int
vivo_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
245
{
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;
250
251
restart:
252
253
if
(
url_feof
(pb))
254
return
AVERROR_EOF
;
255
256
switch
(vivo->
type
) {
257
case
0:
258
avio_skip
(pb, vivo->
length
);
259
if
((ret =
vivo_get_packet_header
(s)) < 0)
260
return
ret
;
261
goto
restart;
262
case
1:
263
case
2:
// video
264
stream_index = 0;
265
break
;
266
case
3:
267
case
4:
// audio
268
stream_index = 1;
269
break
;
270
default
:
271
av_log
(s,
AV_LOG_ERROR
,
"unknown packet type %d\n"
, vivo->
type
);
272
return
AVERROR_INVALIDDATA
;
273
}
274
275
if
((ret =
av_get_packet
(pb, pkt, vivo->
length
)) < 0)
276
goto
fail;
277
278
// get next packet header
279
if
((ret =
vivo_get_packet_header
(s)) < 0)
280
goto
fail;
281
282
while
(vivo->
sequence
== old_sequence &&
283
(((vivo->
type
- 1) >> 1) == ((old_type - 1) >> 1))) {
284
if
(
url_feof
(pb)) {
285
ret =
AVERROR_EOF
;
286
break
;
287
}
288
289
if
((ret =
av_append_packet
(pb, pkt, vivo->
length
)) < 0)
290
break
;
291
292
// get next packet header
293
if
((ret =
vivo_get_packet_header
(s)) < 0)
294
break
;
295
}
296
297
pkt->
stream_index
= stream_index;
298
299
fail:
300
if
(ret < 0)
301
av_free_packet
(pkt);
302
return
ret
;
303
}
304
305
AVInputFormat
ff_vivo_demuxer
= {
306
.
name
=
"vivo"
,
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
,
312
.extensions =
"viv"
,
313
};
Generated on Sun Mar 23 2014 23:50:14 for FFmpeg by
1.8.2