Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
idroqdec.c
Go to the documentation of this file.
1
/*
2
* id RoQ (.roq) File Demuxer
3
* Copyright (c) 2003 The ffmpeg Project
4
*
5
* This file is part of Libav.
6
*
7
* Libav 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
* Libav 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 Libav; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
30
#include "
libavutil/intreadwrite.h
"
31
#include "
avformat.h
"
32
#include "
internal.h
"
33
34
#define RoQ_MAGIC_NUMBER 0x1084
35
#define RoQ_CHUNK_PREAMBLE_SIZE 8
36
#define RoQ_AUDIO_SAMPLE_RATE 22050
37
#define RoQ_CHUNKS_TO_SCAN 30
38
39
#define RoQ_INFO 0x1001
40
#define RoQ_QUAD_CODEBOOK 0x1002
41
#define RoQ_QUAD_VQ 0x1011
42
#define RoQ_SOUND_MONO 0x1020
43
#define RoQ_SOUND_STEREO 0x1021
44
45
typedef
struct
RoqDemuxContext
{
46
47
int
frame_rate
;
48
int
width
;
49
int
height
;
50
int
audio_channels
;
51
52
int
video_stream_index
;
53
int
audio_stream_index
;
54
55
int64_t
video_pts
;
56
unsigned
int
audio_frame_count
;
57
58
}
RoqDemuxContext
;
59
60
static
int
roq_probe
(
AVProbeData
*p)
61
{
62
if
((
AV_RL16
(&p->
buf
[0]) !=
RoQ_MAGIC_NUMBER
) ||
63
(
AV_RL32
(&p->
buf
[2]) != 0xFFFFFFFF))
64
return
0;
65
66
return
AVPROBE_SCORE_MAX
;
67
}
68
69
static
int
roq_read_header
(
AVFormatContext
*s,
70
AVFormatParameters
*ap)
71
{
72
RoqDemuxContext
*roq = s->
priv_data
;
73
AVIOContext
*pb = s->
pb
;
74
unsigned
char
preamble[
RoQ_CHUNK_PREAMBLE_SIZE
];
75
76
/* get the main header */
77
if
(
avio_read
(pb, preamble,
RoQ_CHUNK_PREAMBLE_SIZE
) !=
78
RoQ_CHUNK_PREAMBLE_SIZE
)
79
return
AVERROR
(EIO);
80
roq->
frame_rate
=
AV_RL16
(&preamble[6]);
81
82
/* init private context parameters */
83
roq->
width
= roq->
height
= roq->
audio_channels
= roq->
video_pts
=
84
roq->
audio_frame_count
= 0;
85
roq->
audio_stream_index
= -1;
86
roq->
video_stream_index
= -1;
87
88
s->
ctx_flags
|=
AVFMTCTX_NOHEADER
;
89
90
return
0;
91
}
92
93
static
int
roq_read_packet
(
AVFormatContext
*s,
94
AVPacket
*pkt)
95
{
96
RoqDemuxContext
*roq = s->
priv_data
;
97
AVIOContext
*pb = s->
pb
;
98
int
ret = 0;
99
unsigned
int
chunk_size;
100
unsigned
int
chunk_type;
101
unsigned
int
codebook_size;
102
unsigned
char
preamble[
RoQ_CHUNK_PREAMBLE_SIZE
];
103
int
packet_read = 0;
104
int64_t codebook_offset;
105
106
while
(!packet_read) {
107
108
if
(s->
pb
->
eof_reached
)
109
return
AVERROR
(EIO);
110
111
/* get the next chunk preamble */
112
if
((ret =
avio_read
(pb, preamble,
RoQ_CHUNK_PREAMBLE_SIZE
)) !=
113
RoQ_CHUNK_PREAMBLE_SIZE
)
114
return
AVERROR
(EIO);
115
116
chunk_type =
AV_RL16
(&preamble[0]);
117
chunk_size =
AV_RL32
(&preamble[2]);
118
if
(chunk_size > INT_MAX)
119
return
AVERROR_INVALIDDATA
;
120
121
switch
(chunk_type) {
122
123
case
RoQ_INFO
:
124
if
(roq->
video_stream_index
== -1) {
125
AVStream
*st =
avformat_new_stream
(s,
NULL
);
126
if
(!st)
127
return
AVERROR
(ENOMEM);
128
avpriv_set_pts_info
(st, 63, 1, roq->
frame_rate
);
129
roq->
video_stream_index
= st->
index
;
130
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
131
st->
codec
->
codec_id
=
CODEC_ID_ROQ
;
132
st->
codec
->
codec_tag
= 0;
/* no fourcc */
133
134
if
(
avio_read
(pb, preamble,
RoQ_CHUNK_PREAMBLE_SIZE
) !=
RoQ_CHUNK_PREAMBLE_SIZE
)
135
return
AVERROR
(EIO);
136
st->
codec
->
width
= roq->
width
=
AV_RL16
(preamble);
137
st->
codec
->
height
= roq->
height
=
AV_RL16
(preamble + 2);
138
break
;
139
}
140
/* don't care about this chunk anymore */
141
avio_skip
(pb,
RoQ_CHUNK_PREAMBLE_SIZE
);
142
break
;
143
144
case
RoQ_QUAD_CODEBOOK
:
145
if
(roq->
video_stream_index
< 0)
146
return
AVERROR_INVALIDDATA
;
147
/* packet needs to contain both this codebook and next VQ chunk */
148
codebook_offset =
avio_tell
(pb) -
RoQ_CHUNK_PREAMBLE_SIZE
;
149
codebook_size = chunk_size;
150
avio_skip
(pb, codebook_size);
151
if
(
avio_read
(pb, preamble,
RoQ_CHUNK_PREAMBLE_SIZE
) !=
152
RoQ_CHUNK_PREAMBLE_SIZE
)
153
return
AVERROR
(EIO);
154
chunk_size =
AV_RL32
(&preamble[2]) +
RoQ_CHUNK_PREAMBLE_SIZE
* 2 +
155
codebook_size;
156
157
/* rewind */
158
avio_seek
(pb, codebook_offset, SEEK_SET);
159
160
/* load up the packet */
161
ret=
av_get_packet
(pb, pkt, chunk_size);
162
if
(ret != chunk_size)
163
return
AVERROR
(EIO);
164
pkt->
stream_index
= roq->
video_stream_index
;
165
pkt->
pts
= roq->
video_pts
++;
166
167
packet_read = 1;
168
break
;
169
170
case
RoQ_SOUND_MONO
:
171
case
RoQ_SOUND_STEREO
:
172
if
(roq->
audio_stream_index
== -1) {
173
AVStream
*st =
avformat_new_stream
(s,
NULL
);
174
if
(!st)
175
return
AVERROR
(ENOMEM);
176
avpriv_set_pts_info
(st, 32, 1,
RoQ_AUDIO_SAMPLE_RATE
);
177
roq->
audio_stream_index
= st->
index
;
178
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
179
st->
codec
->
codec_id
=
CODEC_ID_ROQ_DPCM
;
180
st->
codec
->
codec_tag
= 0;
/* no tag */
181
st->
codec
->
channels
= roq->
audio_channels
= chunk_type ==
RoQ_SOUND_STEREO
? 2 : 1;
182
st->
codec
->
sample_rate
=
RoQ_AUDIO_SAMPLE_RATE
;
183
st->
codec
->
bits_per_coded_sample
= 16;
184
st->
codec
->
bit_rate
= st->
codec
->
channels
* st->
codec
->
sample_rate
*
185
st->
codec
->
bits_per_coded_sample
;
186
st->
codec
->
block_align
= st->
codec
->
channels
* st->
codec
->
bits_per_coded_sample
;
187
}
188
case
RoQ_QUAD_VQ
:
189
if
(chunk_type ==
RoQ_QUAD_VQ
) {
190
if
(roq->
video_stream_index
< 0)
191
return
AVERROR_INVALIDDATA
;
192
}
193
194
/* load up the packet */
195
if
(
av_new_packet
(pkt, chunk_size +
RoQ_CHUNK_PREAMBLE_SIZE
))
196
return
AVERROR
(EIO);
197
/* copy over preamble */
198
memcpy(pkt->
data
, preamble,
RoQ_CHUNK_PREAMBLE_SIZE
);
199
200
if
(chunk_type ==
RoQ_QUAD_VQ
) {
201
pkt->
stream_index
= roq->
video_stream_index
;
202
pkt->
pts
= roq->
video_pts
++;
203
}
else
{
204
pkt->
stream_index
= roq->
audio_stream_index
;
205
pkt->
pts
= roq->
audio_frame_count
;
206
roq->
audio_frame_count
+= (chunk_size / roq->
audio_channels
);
207
}
208
209
pkt->
pos
=
avio_tell
(pb);
210
ret =
avio_read
(pb, pkt->
data
+
RoQ_CHUNK_PREAMBLE_SIZE
,
211
chunk_size);
212
if
(ret != chunk_size)
213
ret =
AVERROR
(EIO);
214
215
packet_read = 1;
216
break
;
217
218
default
:
219
av_log
(s,
AV_LOG_ERROR
,
" unknown RoQ chunk (%04X)\n"
, chunk_type);
220
return
AVERROR_INVALIDDATA
;
221
}
222
}
223
224
return
ret;
225
}
226
227
AVInputFormat
ff_roq_demuxer
= {
228
.
name
=
"RoQ"
,
229
.long_name =
NULL_IF_CONFIG_SMALL
(
"id RoQ format"
),
230
.priv_data_size =
sizeof
(
RoqDemuxContext
),
231
.
read_probe
=
roq_probe
,
232
.
read_header
=
roq_read_header
,
233
.
read_packet
=
roq_read_packet
,
234
};