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 RoQ_MAGIC_NUMBER 0x1084
31 #define RoQ_CHUNK_PREAMBLE_SIZE 8
32 #define RoQ_AUDIO_SAMPLE_RATE 22050
33 #define RoQ_CHUNKS_TO_SCAN 30
35 #define RoQ_INFO 0x1001
36 #define RoQ_QUAD_CODEBOOK 0x1002
37 #define RoQ_QUAD_VQ 0x1011
38 #define RoQ_SOUND_MONO 0x1020
39 #define RoQ_SOUND_STEREO 0x1021
41 typedef struct RoqDemuxContext {
49 int video_stream_index;
50 int audio_stream_index;
53 unsigned int audio_frame_count;
57 static int roq_probe(AVProbeData *p)
62 if ((LE_16(&p->buf[0]) != RoQ_MAGIC_NUMBER) ||
63 (LE_32(&p->buf[2]) != 0xFFFFFFFF))
66 return AVPROBE_SCORE_MAX;
69 static int roq_read_header(AVFormatContext *s,
70 AVFormatParameters *ap)
72 RoqDemuxContext *roq = s->priv_data;
73 ByteIOContext *pb = &s->pb;
75 unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
77 unsigned int chunk_size;
78 unsigned int chunk_type;
80 /* get the main header */
81 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
82 RoQ_CHUNK_PREAMBLE_SIZE)
84 roq->framerate = LE_16(&preamble[6]);
85 roq->frame_pts_inc = 90000 / roq->framerate;
87 /* set the pts reference (1 pts = 1/90000) */
91 /* init private context parameters */
92 roq->width = roq->height = roq->audio_channels = roq->video_pts =
93 roq->audio_frame_count = 0;
95 /* scan the first n chunks searching for A/V parameters */
96 for (i = 0; i < RoQ_CHUNKS_TO_SCAN; i++) {
97 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
98 RoQ_CHUNK_PREAMBLE_SIZE)
101 chunk_type = LE_16(&preamble[0]);
102 chunk_size = LE_32(&preamble[2]);
104 switch (chunk_type) {
107 /* fetch the width and height; reuse the preamble bytes */
108 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
109 RoQ_CHUNK_PREAMBLE_SIZE)
111 roq->width = LE_16(&preamble[0]);
112 roq->height = LE_16(&preamble[2]);
115 case RoQ_QUAD_CODEBOOK:
117 /* ignore during this scan */
118 url_fseek(pb, chunk_size, SEEK_CUR);
122 roq->audio_channels = 1;
123 url_fseek(pb, chunk_size, SEEK_CUR);
126 case RoQ_SOUND_STEREO:
127 roq->audio_channels = 2;
128 url_fseek(pb, chunk_size, SEEK_CUR);
132 av_log(s, AV_LOG_ERROR, " unknown RoQ chunk type (%04X)\n", LE_16(&preamble[0]));
133 return AVERROR_INVALIDDATA;
137 /* if all necessary parameters have been gathered, exit early */
138 if ((roq->width && roq->height) && roq->audio_channels)
142 /* seek back to the first chunk */
143 url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_SET);
145 /* initialize the decoders */
146 st = av_new_stream(s, 0);
148 return AVERROR_NOMEM;
149 roq->video_stream_index = st->index;
150 st->codec.codec_type = CODEC_TYPE_VIDEO;
151 st->codec.codec_id = CODEC_ID_ROQ;
152 st->codec.codec_tag = 0; /* no fourcc */
153 st->codec.width = roq->width;
154 st->codec.height = roq->height;
156 if (roq->audio_channels) {
157 st = av_new_stream(s, 0);
159 return AVERROR_NOMEM;
160 roq->audio_stream_index = st->index;
161 st->codec.codec_type = CODEC_TYPE_AUDIO;
162 st->codec.codec_id = CODEC_ID_ROQ_DPCM;
163 st->codec.codec_tag = 0; /* no tag */
164 st->codec.channels = roq->audio_channels;
165 st->codec.sample_rate = RoQ_AUDIO_SAMPLE_RATE;
166 st->codec.bits_per_sample = 16;
167 st->codec.bit_rate = st->codec.channels * st->codec.sample_rate *
168 st->codec.bits_per_sample;
169 st->codec.block_align = st->codec.channels * st->codec.bits_per_sample;
175 static int roq_read_packet(AVFormatContext *s,
178 RoqDemuxContext *roq = s->priv_data;
179 ByteIOContext *pb = &s->pb;
181 unsigned int chunk_size;
182 unsigned int chunk_type;
183 unsigned int codebook_size;
184 unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
186 offset_t codebook_offset;
188 while (!packet_read) {
190 if (url_feof(&s->pb))
193 /* get the next chunk preamble */
194 if ((ret = get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) !=
195 RoQ_CHUNK_PREAMBLE_SIZE)
198 chunk_type = LE_16(&preamble[0]);
199 chunk_size = LE_32(&preamble[2]);
201 switch (chunk_type) {
204 /* don't care about this chunk anymore */
205 url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_CUR);
208 case RoQ_QUAD_CODEBOOK:
209 /* packet needs to contain both this codebook and next VQ chunk */
210 codebook_offset = url_ftell(pb) - RoQ_CHUNK_PREAMBLE_SIZE;
211 codebook_size = chunk_size;
212 url_fseek(pb, codebook_size, SEEK_CUR);
213 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
214 RoQ_CHUNK_PREAMBLE_SIZE)
216 chunk_size = LE_32(&preamble[2]) + RoQ_CHUNK_PREAMBLE_SIZE * 2 +
220 url_fseek(pb, codebook_offset, SEEK_SET);
222 /* load up the packet */
223 if (av_new_packet(pkt, chunk_size))
225 pkt->stream_index = roq->video_stream_index;
226 pkt->pts = roq->video_pts;
227 ret = get_buffer(pb, pkt->data, chunk_size);
228 if (ret != chunk_size)
231 roq->video_pts += roq->frame_pts_inc;
236 case RoQ_SOUND_STEREO:
238 /* load up the packet */
239 if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE))
241 /* copy over preamble */
242 memcpy(pkt->data, preamble, RoQ_CHUNK_PREAMBLE_SIZE);
244 if (chunk_type == RoQ_QUAD_VQ) {
245 pkt->stream_index = roq->video_stream_index;
246 pkt->pts = roq->video_pts;
247 roq->video_pts += roq->frame_pts_inc;
249 pkt->stream_index = roq->audio_stream_index;
250 pkt->pts = roq->audio_frame_count;
252 pkt->pts /= RoQ_AUDIO_SAMPLE_RATE;
253 roq->audio_frame_count += (chunk_size / roq->audio_channels);
256 ret = get_buffer(pb, pkt->data + RoQ_CHUNK_PREAMBLE_SIZE,
258 if (ret != chunk_size)
265 av_log(s, AV_LOG_ERROR, " unknown RoQ chunk (%04X)\n", chunk_type);
266 return AVERROR_INVALIDDATA;
274 static int roq_read_close(AVFormatContext *s)
276 // RoqDemuxContext *roq = (RoqDemuxContext *)s->priv_data;
281 static AVInputFormat roq_iformat = {
284 sizeof(RoqDemuxContext),
293 av_register_input_format(&roq_iformat);