2 * Id RoQ (.roq) File Demuxer
3 * Copyright (c) 2003 The ffmpeg Project
5 * This file is part of FFmpeg.
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.
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.
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
24 * Id RoQ format file demuxer
25 * by Mike Melanson (melanson@pcisys.net)
26 * for more information on the .roq file format, visit:
27 * http://www.csse.monash.edu.au/~timf/
32 #define RoQ_MAGIC_NUMBER 0x1084
33 #define RoQ_CHUNK_PREAMBLE_SIZE 8
34 #define RoQ_AUDIO_SAMPLE_RATE 22050
35 #define RoQ_CHUNKS_TO_SCAN 30
37 #define RoQ_INFO 0x1001
38 #define RoQ_QUAD_CODEBOOK 0x1002
39 #define RoQ_QUAD_VQ 0x1011
40 #define RoQ_SOUND_MONO 0x1020
41 #define RoQ_SOUND_STEREO 0x1021
43 typedef struct RoqDemuxContext {
51 int video_stream_index;
52 int audio_stream_index;
55 unsigned int audio_frame_count;
59 static int roq_probe(AVProbeData *p)
64 if ((LE_16(&p->buf[0]) != RoQ_MAGIC_NUMBER) ||
65 (LE_32(&p->buf[2]) != 0xFFFFFFFF))
68 return AVPROBE_SCORE_MAX;
71 static int roq_read_header(AVFormatContext *s,
72 AVFormatParameters *ap)
74 RoqDemuxContext *roq = s->priv_data;
75 ByteIOContext *pb = &s->pb;
77 unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
79 unsigned int chunk_size;
80 unsigned int chunk_type;
82 /* get the main header */
83 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
84 RoQ_CHUNK_PREAMBLE_SIZE)
86 roq->framerate = LE_16(&preamble[6]);
87 roq->frame_pts_inc = 90000 / roq->framerate;
89 /* init private context parameters */
90 roq->width = roq->height = roq->audio_channels = roq->video_pts =
91 roq->audio_frame_count = 0;
93 /* scan the first n chunks searching for A/V parameters */
94 for (i = 0; i < RoQ_CHUNKS_TO_SCAN; i++) {
95 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
96 RoQ_CHUNK_PREAMBLE_SIZE)
99 chunk_type = LE_16(&preamble[0]);
100 chunk_size = LE_32(&preamble[2]);
102 switch (chunk_type) {
105 /* fetch the width and height; reuse the preamble bytes */
106 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
107 RoQ_CHUNK_PREAMBLE_SIZE)
109 roq->width = LE_16(&preamble[0]);
110 roq->height = LE_16(&preamble[2]);
113 case RoQ_QUAD_CODEBOOK:
115 /* ignore during this scan */
116 url_fseek(pb, chunk_size, SEEK_CUR);
120 roq->audio_channels = 1;
121 url_fseek(pb, chunk_size, SEEK_CUR);
124 case RoQ_SOUND_STEREO:
125 roq->audio_channels = 2;
126 url_fseek(pb, chunk_size, SEEK_CUR);
130 av_log(s, AV_LOG_ERROR, " unknown RoQ chunk type (%04X)\n", LE_16(&preamble[0]));
131 return AVERROR_INVALIDDATA;
135 /* if all necessary parameters have been gathered, exit early */
136 if ((roq->width && roq->height) && roq->audio_channels)
140 /* seek back to the first chunk */
141 url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_SET);
143 /* initialize the decoders */
144 st = av_new_stream(s, 0);
146 return AVERROR_NOMEM;
147 /* set the pts reference (1 pts = 1/90000) */
148 av_set_pts_info(st, 33, 1, 90000);
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 av_set_pts_info(st, 33, 1, 90000);
161 roq->audio_stream_index = st->index;
162 st->codec->codec_type = CODEC_TYPE_AUDIO;
163 st->codec->codec_id = CODEC_ID_ROQ_DPCM;
164 st->codec->codec_tag = 0; /* no tag */
165 st->codec->channels = roq->audio_channels;
166 st->codec->sample_rate = RoQ_AUDIO_SAMPLE_RATE;
167 st->codec->bits_per_sample = 16;
168 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
169 st->codec->bits_per_sample;
170 st->codec->block_align = st->codec->channels * st->codec->bits_per_sample;
176 static int roq_read_packet(AVFormatContext *s,
179 RoqDemuxContext *roq = s->priv_data;
180 ByteIOContext *pb = &s->pb;
182 unsigned int chunk_size;
183 unsigned int chunk_type;
184 unsigned int codebook_size;
185 unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
187 offset_t codebook_offset;
189 while (!packet_read) {
191 if (url_feof(&s->pb))
194 /* get the next chunk preamble */
195 if ((ret = get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) !=
196 RoQ_CHUNK_PREAMBLE_SIZE)
199 chunk_type = LE_16(&preamble[0]);
200 chunk_size = LE_32(&preamble[2]);
201 if(chunk_size > INT_MAX)
202 return AVERROR_INVALIDDATA;
204 switch (chunk_type) {
207 /* don't care about this chunk anymore */
208 url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_CUR);
211 case RoQ_QUAD_CODEBOOK:
212 /* packet needs to contain both this codebook and next VQ chunk */
213 codebook_offset = url_ftell(pb) - RoQ_CHUNK_PREAMBLE_SIZE;
214 codebook_size = chunk_size;
215 url_fseek(pb, codebook_size, SEEK_CUR);
216 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
217 RoQ_CHUNK_PREAMBLE_SIZE)
219 chunk_size = LE_32(&preamble[2]) + RoQ_CHUNK_PREAMBLE_SIZE * 2 +
223 url_fseek(pb, codebook_offset, SEEK_SET);
225 /* load up the packet */
226 ret= av_get_packet(pb, pkt, chunk_size);
227 if (ret != chunk_size)
229 pkt->stream_index = roq->video_stream_index;
230 pkt->pts = roq->video_pts;
232 roq->video_pts += roq->frame_pts_inc;
237 case RoQ_SOUND_STEREO:
239 /* load up the packet */
240 if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE))
242 /* copy over preamble */
243 memcpy(pkt->data, preamble, RoQ_CHUNK_PREAMBLE_SIZE);
245 if (chunk_type == RoQ_QUAD_VQ) {
246 pkt->stream_index = roq->video_stream_index;
247 pkt->pts = roq->video_pts;
248 roq->video_pts += roq->frame_pts_inc;
250 pkt->stream_index = roq->audio_stream_index;
251 pkt->pts = roq->audio_frame_count;
253 pkt->pts /= RoQ_AUDIO_SAMPLE_RATE;
254 roq->audio_frame_count += (chunk_size / roq->audio_channels);
257 pkt->pos= url_ftell(pb);
258 ret = get_buffer(pb, pkt->data + RoQ_CHUNK_PREAMBLE_SIZE,
260 if (ret != chunk_size)
267 av_log(s, AV_LOG_ERROR, " unknown RoQ chunk (%04X)\n", chunk_type);
268 return AVERROR_INVALIDDATA;
276 static int roq_read_close(AVFormatContext *s)
278 // RoqDemuxContext *roq = (RoqDemuxContext *)s->priv_data;
283 AVInputFormat roq_demuxer = {
286 sizeof(RoqDemuxContext),