2
* Id RoQ (.roq) File Demuxer
3
* Copyright (c) 2003 The ffmpeg Project
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
* Id RoQ format file demuxer
23
* by Mike Melanson (melanson@pcisys.net)
24
* for more information on the .roq file format, visit:
25
* http://www.csse.monash.edu.au/~timf/
30
#define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
31
#define LE_32(x) ((((uint8_t*)(x))[3] << 24) | \
32
(((uint8_t*)(x))[2] << 16) | \
33
(((uint8_t*)(x))[1] << 8) | \
36
#define RoQ_MAGIC_NUMBER 0x1084
37
#define RoQ_CHUNK_PREAMBLE_SIZE 8
38
#define RoQ_AUDIO_SAMPLE_RATE 22050
39
#define RoQ_CHUNKS_TO_SCAN 30
41
#define RoQ_INFO 0x1001
42
#define RoQ_QUAD_CODEBOOK 0x1002
43
#define RoQ_QUAD_VQ 0x1011
44
#define RoQ_SOUND_MONO 0x1020
45
#define RoQ_SOUND_STEREO 0x1021
47
typedef struct RoqDemuxContext {
55
int video_stream_index;
56
int audio_stream_index;
59
unsigned int audio_frame_count;
63
static int roq_probe(AVProbeData *p)
68
if ((LE_16(&p->buf[0]) != RoQ_MAGIC_NUMBER) ||
69
(LE_32(&p->buf[2]) != 0xFFFFFFFF))
72
return AVPROBE_SCORE_MAX;
75
static int roq_read_header(AVFormatContext *s,
76
AVFormatParameters *ap)
78
RoqDemuxContext *roq = s->priv_data;
79
ByteIOContext *pb = &s->pb;
81
unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
83
unsigned int chunk_size;
84
unsigned int chunk_type;
86
/* get the main header */
87
if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
88
RoQ_CHUNK_PREAMBLE_SIZE)
90
roq->framerate = LE_16(&preamble[6]);
91
roq->frame_pts_inc = 90000 / roq->framerate;
93
/* set the pts reference (1 pts = 1/90000) */
97
/* init private context parameters */
98
roq->width = roq->height = roq->audio_channels = roq->video_pts =
99
roq->audio_frame_count = 0;
101
/* scan the first n chunks searching for A/V parameters */
102
for (i = 0; i < RoQ_CHUNKS_TO_SCAN; i++) {
103
if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
104
RoQ_CHUNK_PREAMBLE_SIZE)
107
chunk_type = LE_16(&preamble[0]);
108
chunk_size = LE_32(&preamble[2]);
110
switch (chunk_type) {
113
/* fetch the width and height; reuse the preamble bytes */
114
if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
115
RoQ_CHUNK_PREAMBLE_SIZE)
117
roq->width = LE_16(&preamble[0]);
118
roq->height = LE_16(&preamble[2]);
121
case RoQ_QUAD_CODEBOOK:
123
/* ignore during this scan */
124
url_fseek(pb, chunk_size, SEEK_CUR);
128
roq->audio_channels = 1;
129
url_fseek(pb, chunk_size, SEEK_CUR);
132
case RoQ_SOUND_STEREO:
133
roq->audio_channels = 2;
134
url_fseek(pb, chunk_size, SEEK_CUR);
138
printf (" unknown RoQ chunk type (%04X)\n", LE_16(&preamble[0]));
139
return AVERROR_INVALIDDATA;
143
/* if all necessary parameters have been gathered, exit early */
144
if ((roq->width && roq->height) && roq->audio_channels)
148
/* seek back to the first chunk */
149
url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_SET);
151
/* initialize the decoders */
152
st = av_new_stream(s, 0);
154
return AVERROR_NOMEM;
155
roq->video_stream_index = st->index;
156
st->codec.codec_type = CODEC_TYPE_VIDEO;
157
st->codec.codec_id = CODEC_ID_ROQ;
158
st->codec.codec_tag = 0; /* no fourcc */
159
st->codec.width = roq->width;
160
st->codec.height = roq->height;
162
if (roq->audio_channels) {
163
st = av_new_stream(s, 0);
165
return AVERROR_NOMEM;
166
roq->audio_stream_index = st->index;
167
st->codec.codec_type = CODEC_TYPE_AUDIO;
168
st->codec.codec_id = CODEC_ID_ROQ_DPCM;
169
st->codec.codec_tag = 0; /* no tag */
170
st->codec.channels = roq->audio_channels;
171
st->codec.sample_rate = RoQ_AUDIO_SAMPLE_RATE;
172
st->codec.bits_per_sample = 16;
173
st->codec.bit_rate = st->codec.channels * st->codec.sample_rate *
174
st->codec.bits_per_sample;
175
st->codec.block_align = st->codec.channels * st->codec.bits_per_sample;
181
static int roq_read_packet(AVFormatContext *s,
184
RoqDemuxContext *roq = s->priv_data;
185
ByteIOContext *pb = &s->pb;
187
unsigned int chunk_size;
188
unsigned int chunk_type;
189
unsigned int codebook_size;
190
unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
192
offset_t codebook_offset;
194
while (!packet_read) {
196
if (url_feof(&s->pb))
199
/* get the next chunk preamble */
200
if ((ret = get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) !=
201
RoQ_CHUNK_PREAMBLE_SIZE)
204
chunk_type = LE_16(&preamble[0]);
205
chunk_size = LE_32(&preamble[2]);
207
switch (chunk_type) {
210
/* don't care about this chunk anymore */
211
url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_CUR);
214
case RoQ_QUAD_CODEBOOK:
215
/* packet needs to contain both this codebook and next VQ chunk */
216
codebook_offset = url_ftell(pb) - RoQ_CHUNK_PREAMBLE_SIZE;
217
codebook_size = chunk_size;
218
url_fseek(pb, codebook_size, SEEK_CUR);
219
if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
220
RoQ_CHUNK_PREAMBLE_SIZE)
222
chunk_size = LE_32(&preamble[2]) + RoQ_CHUNK_PREAMBLE_SIZE * 2 +
226
url_fseek(pb, codebook_offset, SEEK_SET);
228
/* load up the packet */
229
if (av_new_packet(pkt, chunk_size))
231
pkt->stream_index = roq->video_stream_index;
232
pkt->pts = roq->video_pts;
233
ret = get_buffer(pb, pkt->data, chunk_size);
234
if (ret != chunk_size)
237
roq->video_pts += roq->frame_pts_inc;
242
case RoQ_SOUND_STEREO:
244
/* load up the packet */
245
if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE))
247
/* copy over preamble */
248
memcpy(pkt->data, preamble, RoQ_CHUNK_PREAMBLE_SIZE);
250
if (chunk_type == RoQ_QUAD_VQ) {
251
pkt->stream_index = roq->video_stream_index;
252
pkt->pts = roq->video_pts;
253
roq->video_pts += roq->frame_pts_inc;
255
pkt->stream_index = roq->audio_stream_index;
256
pkt->pts = roq->audio_frame_count;
258
pkt->pts /= RoQ_AUDIO_SAMPLE_RATE;
259
roq->audio_frame_count += (chunk_size / roq->audio_channels);
262
ret = get_buffer(pb, pkt->data + RoQ_CHUNK_PREAMBLE_SIZE,
264
if (ret != chunk_size)
271
printf (" unknown RoQ chunk (%04X)\n", chunk_type);
272
return AVERROR_INVALIDDATA;
280
static int roq_read_close(AVFormatContext *s)
282
// RoqDemuxContext *roq = (RoqDemuxContext *)s->priv_data;
287
static AVInputFormat roq_iformat = {
290
sizeof(RoqDemuxContext),
299
av_register_input_format(&roq_iformat);