Rename "tx_ctx" and "cur_tx" variables to "transport_priv" and
[ffmpeg-lucabe.git] / libavformat / idroq.c
blob7cf3808e22b0d1c86ffc40291679abe8bdec0b4b
1 /*
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
22 /**
23 * @file libavformat/idroq.c
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/
30 #include "libavutil/intreadwrite.h"
31 #include "avformat.h"
33 #define RoQ_MAGIC_NUMBER 0x1084
34 #define RoQ_CHUNK_PREAMBLE_SIZE 8
35 #define RoQ_AUDIO_SAMPLE_RATE 22050
36 #define RoQ_CHUNKS_TO_SCAN 30
38 #define RoQ_INFO 0x1001
39 #define RoQ_QUAD_CODEBOOK 0x1002
40 #define RoQ_QUAD_VQ 0x1011
41 #define RoQ_SOUND_MONO 0x1020
42 #define RoQ_SOUND_STEREO 0x1021
44 typedef struct RoqDemuxContext {
46 int width;
47 int height;
48 int audio_channels;
49 int framerate;
50 int frame_pts_inc;
52 int video_stream_index;
53 int audio_stream_index;
55 int64_t video_pts;
56 unsigned int audio_frame_count;
58 } RoqDemuxContext;
60 static int roq_probe(AVProbeData *p)
62 if ((AV_RL16(&p->buf[0]) != RoQ_MAGIC_NUMBER) ||
63 (AV_RL32(&p->buf[2]) != 0xFFFFFFFF))
64 return 0;
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;
74 AVStream *st;
75 unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
76 int i;
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)
83 return AVERROR(EIO);
84 roq->framerate = AV_RL16(&preamble[6]);
85 roq->frame_pts_inc = 90000 / roq->framerate;
87 /* init private context parameters */
88 roq->width = roq->height = roq->audio_channels = roq->video_pts =
89 roq->audio_frame_count = 0;
91 /* scan the first n chunks searching for A/V parameters */
92 for (i = 0; i < RoQ_CHUNKS_TO_SCAN; i++) {
93 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
94 RoQ_CHUNK_PREAMBLE_SIZE)
95 return AVERROR(EIO);
97 chunk_type = AV_RL16(&preamble[0]);
98 chunk_size = AV_RL32(&preamble[2]);
100 switch (chunk_type) {
102 case RoQ_INFO:
103 /* fetch the width and height; reuse the preamble bytes */
104 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
105 RoQ_CHUNK_PREAMBLE_SIZE)
106 return AVERROR(EIO);
107 roq->width = AV_RL16(&preamble[0]);
108 roq->height = AV_RL16(&preamble[2]);
109 break;
111 case RoQ_QUAD_CODEBOOK:
112 case RoQ_QUAD_VQ:
113 /* ignore during this scan */
114 url_fseek(pb, chunk_size, SEEK_CUR);
115 break;
117 case RoQ_SOUND_MONO:
118 roq->audio_channels = 1;
119 url_fseek(pb, chunk_size, SEEK_CUR);
120 break;
122 case RoQ_SOUND_STEREO:
123 roq->audio_channels = 2;
124 url_fseek(pb, chunk_size, SEEK_CUR);
125 break;
127 default:
128 av_log(s, AV_LOG_ERROR, " unknown RoQ chunk type (%04X)\n", AV_RL16(&preamble[0]));
129 return AVERROR_INVALIDDATA;
130 break;
133 /* if all necessary parameters have been gathered, exit early */
134 if ((roq->width && roq->height) && roq->audio_channels)
135 break;
138 /* seek back to the first chunk */
139 url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_SET);
141 /* initialize the decoders */
142 st = av_new_stream(s, 0);
143 if (!st)
144 return AVERROR(ENOMEM);
145 /* set the pts reference (1 pts = 1/90000) */
146 av_set_pts_info(st, 33, 1, 90000);
147 roq->video_stream_index = st->index;
148 st->codec->codec_type = CODEC_TYPE_VIDEO;
149 st->codec->codec_id = CODEC_ID_ROQ;
150 st->codec->codec_tag = 0; /* no fourcc */
151 st->codec->width = roq->width;
152 st->codec->height = roq->height;
154 if (roq->audio_channels) {
155 st = av_new_stream(s, 0);
156 if (!st)
157 return AVERROR(ENOMEM);
158 av_set_pts_info(st, 33, 1, 90000);
159 roq->audio_stream_index = st->index;
160 st->codec->codec_type = CODEC_TYPE_AUDIO;
161 st->codec->codec_id = CODEC_ID_ROQ_DPCM;
162 st->codec->codec_tag = 0; /* no tag */
163 st->codec->channels = roq->audio_channels;
164 st->codec->sample_rate = RoQ_AUDIO_SAMPLE_RATE;
165 st->codec->bits_per_coded_sample = 16;
166 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
167 st->codec->bits_per_coded_sample;
168 st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
171 return 0;
174 static int roq_read_packet(AVFormatContext *s,
175 AVPacket *pkt)
177 RoqDemuxContext *roq = s->priv_data;
178 ByteIOContext *pb = s->pb;
179 int ret = 0;
180 unsigned int chunk_size;
181 unsigned int chunk_type;
182 unsigned int codebook_size;
183 unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
184 int packet_read = 0;
185 int64_t codebook_offset;
187 while (!packet_read) {
189 if (url_feof(s->pb))
190 return AVERROR(EIO);
192 /* get the next chunk preamble */
193 if ((ret = get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) !=
194 RoQ_CHUNK_PREAMBLE_SIZE)
195 return AVERROR(EIO);
197 chunk_type = AV_RL16(&preamble[0]);
198 chunk_size = AV_RL32(&preamble[2]);
199 if(chunk_size > INT_MAX)
200 return AVERROR_INVALIDDATA;
202 switch (chunk_type) {
204 case RoQ_INFO:
205 /* don't care about this chunk anymore */
206 url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_CUR);
207 break;
209 case RoQ_QUAD_CODEBOOK:
210 /* packet needs to contain both this codebook and next VQ chunk */
211 codebook_offset = url_ftell(pb) - RoQ_CHUNK_PREAMBLE_SIZE;
212 codebook_size = chunk_size;
213 url_fseek(pb, codebook_size, SEEK_CUR);
214 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
215 RoQ_CHUNK_PREAMBLE_SIZE)
216 return AVERROR(EIO);
217 chunk_size = AV_RL32(&preamble[2]) + RoQ_CHUNK_PREAMBLE_SIZE * 2 +
218 codebook_size;
220 /* rewind */
221 url_fseek(pb, codebook_offset, SEEK_SET);
223 /* load up the packet */
224 ret= av_get_packet(pb, pkt, chunk_size);
225 if (ret != chunk_size)
226 return AVERROR(EIO);
227 pkt->stream_index = roq->video_stream_index;
228 pkt->pts = roq->video_pts;
230 roq->video_pts += roq->frame_pts_inc;
231 packet_read = 1;
232 break;
234 case RoQ_SOUND_MONO:
235 case RoQ_SOUND_STEREO:
236 case RoQ_QUAD_VQ:
237 /* load up the packet */
238 if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE))
239 return AVERROR(EIO);
240 /* copy over preamble */
241 memcpy(pkt->data, preamble, RoQ_CHUNK_PREAMBLE_SIZE);
243 if (chunk_type == RoQ_QUAD_VQ) {
244 pkt->stream_index = roq->video_stream_index;
245 pkt->pts = roq->video_pts;
246 roq->video_pts += roq->frame_pts_inc;
247 } else {
248 pkt->stream_index = roq->audio_stream_index;
249 pkt->pts = roq->audio_frame_count;
250 pkt->pts *= 90000;
251 pkt->pts /= RoQ_AUDIO_SAMPLE_RATE;
252 roq->audio_frame_count += (chunk_size / roq->audio_channels);
255 pkt->pos= url_ftell(pb);
256 ret = get_buffer(pb, pkt->data + RoQ_CHUNK_PREAMBLE_SIZE,
257 chunk_size);
258 if (ret != chunk_size)
259 ret = AVERROR(EIO);
261 packet_read = 1;
262 break;
264 default:
265 av_log(s, AV_LOG_ERROR, " unknown RoQ chunk (%04X)\n", chunk_type);
266 return AVERROR_INVALIDDATA;
267 break;
271 return ret;
274 AVInputFormat roq_demuxer = {
275 "RoQ",
276 NULL_IF_CONFIG_SMALL("id RoQ format"),
277 sizeof(RoqDemuxContext),
278 roq_probe,
279 roq_read_header,
280 roq_read_packet,