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
vqf.c
Go to the documentation of this file.
1
/*
2
* VQF demuxer
3
* Copyright (c) 2009 Vitor Sessak
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
#include "
avformat.h
"
23
#include "
internal.h
"
24
#include "
libavutil/intreadwrite.h
"
25
#include "
libavutil/dict.h
"
26
#include "
libavutil/mathematics.h
"
27
#include "
riff.h
"
28
29
typedef
struct
VqfContext
{
30
int
frame_bit_len
;
31
uint8_t
last_frame_bits
;
32
int
remaining_bits
;
33
}
VqfContext
;
34
35
static
int
vqf_probe
(
AVProbeData
*probe_packet)
36
{
37
if
(
AV_RL32
(probe_packet->
buf
) !=
MKTAG
(
'T'
,
'W'
,
'I'
,
'N'
))
38
return
0;
39
40
if
(!memcmp(probe_packet->
buf
+ 4,
"97012000"
, 8))
41
return
AVPROBE_SCORE_MAX
;
42
43
if
(!memcmp(probe_packet->
buf
+ 4,
"00052200"
, 8))
44
return
AVPROBE_SCORE_MAX
;
45
46
return
AVPROBE_SCORE_EXTENSION
;
47
}
48
49
static
void
add_metadata
(
AVFormatContext
*
s
, uint32_t
tag
,
50
unsigned
int
tag_len,
unsigned
int
remaining)
51
{
52
int
len
=
FFMIN
(tag_len, remaining);
53
char
*
buf
, key[5] = {0};
54
55
if
(len == UINT_MAX)
56
return
;
57
58
buf =
av_malloc
(len+1);
59
if
(!buf)
60
return
;
61
avio_read
(s->
pb
, buf, len);
62
buf[
len
] = 0;
63
AV_WL32
(key, tag);
64
av_dict_set
(&s->
metadata
, key, buf,
AV_DICT_DONT_STRDUP_VAL
);
65
}
66
67
static
const
AVMetadataConv
vqf_metadata_conv
[] = {
68
{
"(c) "
,
"copyright"
},
69
{
"ARNG"
,
"arranger"
},
70
{
"AUTH"
,
"author"
},
71
{
"BAND"
,
"band"
},
72
{
"CDCT"
,
"conductor"
},
73
{
"COMT"
,
"comment"
},
74
{
"FILE"
,
"filename"
},
75
{
"GENR"
,
"genre"
},
76
{
"LABL"
,
"publisher"
},
77
{
"MUSC"
,
"composer"
},
78
{
"NAME"
,
"title"
},
79
{
"NOTE"
,
"note"
},
80
{
"PROD"
,
"producer"
},
81
{
"PRSN"
,
"personnel"
},
82
{
"REMX"
,
"remixer"
},
83
{
"SING"
,
"singer"
},
84
{
"TRCK"
,
"track"
},
85
{
"WORD"
,
"words"
},
86
{ 0 },
87
};
88
89
static
int
vqf_read_header
(
AVFormatContext
*
s
)
90
{
91
VqfContext
*
c
= s->
priv_data
;
92
AVStream
*st =
avformat_new_stream
(s,
NULL
);
93
int
chunk_tag;
94
int
rate_flag = -1;
95
int
header_size;
96
int
read_bitrate = 0;
97
int
size
;
98
uint8_t
comm_chunk[12];
99
100
if
(!st)
101
return
AVERROR
(ENOMEM);
102
103
avio_skip
(s->
pb
, 12);
104
105
header_size =
avio_rb32
(s->
pb
);
106
107
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
108
st->
codec
->
codec_id
=
AV_CODEC_ID_TWINVQ
;
109
st->
start_time
= 0;
110
111
do
{
112
int
len
;
113
chunk_tag =
avio_rl32
(s->
pb
);
114
115
if
(chunk_tag ==
MKTAG
(
'D'
,
'A'
,
'T'
,
'A'
))
116
break
;
117
118
len =
avio_rb32
(s->
pb
);
119
120
if
((
unsigned
) len > INT_MAX/2) {
121
av_log
(s,
AV_LOG_ERROR
,
"Malformed header\n"
);
122
return
-1;
123
}
124
125
header_size -= 8;
126
127
switch
(chunk_tag){
128
case
MKTAG
(
'C'
,
'O'
,
'M'
,
'M'
):
129
avio_read
(s->
pb
, comm_chunk, 12);
130
st->
codec
->
channels
=
AV_RB32
(comm_chunk ) + 1;
131
read_bitrate =
AV_RB32
(comm_chunk + 4);
132
rate_flag =
AV_RB32
(comm_chunk + 8);
133
avio_skip
(s->
pb
, len-12);
134
135
if
(st->
codec
->
channels
<= 0) {
136
av_log
(s,
AV_LOG_ERROR
,
"Invalid number of channels\n"
);
137
return
AVERROR_INVALIDDATA
;
138
}
139
140
st->
codec
->
bit_rate
= read_bitrate*1000;
141
break
;
142
case
MKTAG
(
'D'
,
'S'
,
'I'
,
'Z'
):
// size of compressed data
143
{
144
char
buf
[8] = {0};
145
int
size =
avio_rb32
(s->
pb
);
146
147
snprintf
(buf,
sizeof
(buf),
"%d"
, size);
148
av_dict_set
(&s->
metadata
,
"size"
, buf, 0);
149
}
150
break
;
151
case
MKTAG
(
'Y'
,
'E'
,
'A'
,
'R'
):
// recording date
152
case
MKTAG
(
'E'
,
'N'
,
'C'
,
'D'
):
// compression date
153
case
MKTAG
(
'E'
,
'X'
,
'T'
,
'R'
):
// reserved
154
case
MKTAG
(
'_'
,
'Y'
,
'M'
,
'H'
):
// reserved
155
case
MKTAG
(
'_'
,
'N'
,
'T'
,
'T'
):
// reserved
156
case
MKTAG
(
'_'
,
'I'
,
'D'
,
'3'
):
// reserved for ID3 tags
157
avio_skip
(s->
pb
,
FFMIN
(len, header_size));
158
break
;
159
default
:
160
add_metadata
(s, chunk_tag, len, header_size);
161
break
;
162
}
163
164
header_size -=
len
;
165
166
}
while
(header_size >= 0);
167
168
switch
(rate_flag) {
169
case
-1:
170
av_log
(s,
AV_LOG_ERROR
,
"COMM tag not found!\n"
);
171
return
-1;
172
case
44:
173
st->
codec
->
sample_rate
= 44100;
174
break
;
175
case
22:
176
st->
codec
->
sample_rate
= 22050;
177
break
;
178
case
11:
179
st->
codec
->
sample_rate
= 11025;
180
break
;
181
default
:
182
st->
codec
->
sample_rate
= rate_flag*1000;
183
if
(st->
codec
->
sample_rate
<= 0) {
184
av_log
(s,
AV_LOG_ERROR
,
"sample rate %d is invalid\n"
, st->
codec
->
sample_rate
);
185
return
-1;
186
}
187
break
;
188
}
189
190
switch
(((st->
codec
->
sample_rate
/1000) << 8) +
191
read_bitrate/st->
codec
->
channels
) {
192
case
(11<<8) + 8 :
193
case
(8 <<8) + 8 :
194
case
(11<<8) + 10:
195
case
(22<<8) + 32:
196
size = 512;
197
break
;
198
case
(16<<8) + 16:
199
case
(22<<8) + 20:
200
case
(22<<8) + 24:
201
size = 1024;
202
break
;
203
case
(44<<8) + 40:
204
case
(44<<8) + 48:
205
size = 2048;
206
break
;
207
default
:
208
av_log
(s,
AV_LOG_ERROR
,
"Mode not suported: %d Hz, %d kb/s.\n"
,
209
st->
codec
->
sample_rate
, st->
codec
->
bit_rate
);
210
return
-1;
211
}
212
c->
frame_bit_len
= st->
codec
->
bit_rate
*size/st->
codec
->
sample_rate
;
213
avpriv_set_pts_info
(st, 64, size, st->
codec
->
sample_rate
);
214
215
/* put first 12 bytes of COMM chunk in extradata */
216
if
(!(st->
codec
->
extradata
=
av_malloc
(12 +
FF_INPUT_BUFFER_PADDING_SIZE
)))
217
return
AVERROR
(ENOMEM);
218
st->
codec
->
extradata_size
= 12;
219
memcpy(st->
codec
->
extradata
, comm_chunk, 12);
220
221
ff_metadata_conv_ctx
(s,
NULL
, vqf_metadata_conv);
222
223
return
0;
224
}
225
226
static
int
vqf_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
227
{
228
VqfContext
*
c
= s->
priv_data
;
229
int
ret
;
230
int
size
= (c->
frame_bit_len
- c->
remaining_bits
+ 7)>>3;
231
232
if
(
av_new_packet
(pkt, size+2) < 0)
233
return
AVERROR
(EIO);
234
235
pkt->
pos
=
avio_tell
(s->
pb
);
236
pkt->
stream_index
= 0;
237
pkt->
duration
= 1;
238
239
pkt->
data
[0] = 8 - c->
remaining_bits
;
// Number of bits to skip
240
pkt->
data
[1] = c->
last_frame_bits
;
241
ret =
avio_read
(s->
pb
, pkt->
data
+2, size);
242
243
if
(ret<=0) {
244
av_free_packet
(pkt);
245
return
AVERROR
(EIO);
246
}
247
248
c->
last_frame_bits
= pkt->
data
[size+1];
249
c->
remaining_bits
= (size << 3) - c->
frame_bit_len
+ c->
remaining_bits
;
250
251
return
size+2;
252
}
253
254
static
int
vqf_read_seek
(
AVFormatContext
*
s
,
255
int
stream_index, int64_t timestamp,
int
flags
)
256
{
257
VqfContext
*
c
= s->
priv_data
;
258
AVStream
*st;
259
int
ret
;
260
int64_t pos;
261
262
st = s->
streams
[stream_index];
263
pos =
av_rescale_rnd
(timestamp * st->
codec
->
bit_rate
,
264
st->
time_base
.
num
,
265
st->
time_base
.
den
* (int64_t)c->
frame_bit_len
,
266
(flags &
AVSEEK_FLAG_BACKWARD
) ?
267
AV_ROUND_DOWN
:
AV_ROUND_UP
);
268
pos *= c->
frame_bit_len
;
269
270
st->
cur_dts
=
av_rescale
(pos, st->
time_base
.
den
,
271
st->
codec
->
bit_rate
* (int64_t)st->
time_base
.
num
);
272
273
if
((ret =
avio_seek
(s->
pb
, ((pos-7) >> 3) + s->
data_offset
, SEEK_SET)) < 0)
274
return
ret
;
275
276
c->
remaining_bits
= -7 - ((pos-7)&7);
277
return
0;
278
}
279
280
AVInputFormat
ff_vqf_demuxer
= {
281
.
name
=
"vqf"
,
282
.long_name =
NULL_IF_CONFIG_SMALL
(
"Nippon Telegraph and Telephone Corporation (NTT) TwinVQ"
),
283
.priv_data_size =
sizeof
(
VqfContext
),
284
.
read_probe
=
vqf_probe
,
285
.
read_header
=
vqf_read_header
,
286
.
read_packet
=
vqf_read_packet
,
287
.
read_seek
=
vqf_read_seek
,
288
.extensions =
"vqf,vql,vqe"
,
289
};
Generated on Tue May 21 2013 19:21:08 for FFmpeg by
1.8.2