00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00030 #include "avformat.h"
00031
00032 #define RoQ_MAGIC_NUMBER 0x1084
00033 #define RoQ_CHUNK_PREAMBLE_SIZE 8
00034 #define RoQ_AUDIO_SAMPLE_RATE 22050
00035 #define RoQ_CHUNKS_TO_SCAN 30
00036
00037 #define RoQ_INFO 0x1001
00038 #define RoQ_QUAD_CODEBOOK 0x1002
00039 #define RoQ_QUAD_VQ 0x1011
00040 #define RoQ_SOUND_MONO 0x1020
00041 #define RoQ_SOUND_STEREO 0x1021
00042
00043 typedef struct RoqDemuxContext {
00044
00045 int width;
00046 int height;
00047 int audio_channels;
00048 int framerate;
00049 int frame_pts_inc;
00050
00051 int video_stream_index;
00052 int audio_stream_index;
00053
00054 int64_t video_pts;
00055 unsigned int audio_frame_count;
00056
00057 } RoqDemuxContext;
00058
00059 static int roq_probe(AVProbeData *p)
00060 {
00061 if ((AV_RL16(&p->buf[0]) != RoQ_MAGIC_NUMBER) ||
00062 (AV_RL32(&p->buf[2]) != 0xFFFFFFFF))
00063 return 0;
00064
00065 return AVPROBE_SCORE_MAX;
00066 }
00067
00068 static int roq_read_header(AVFormatContext *s,
00069 AVFormatParameters *ap)
00070 {
00071 RoqDemuxContext *roq = s->priv_data;
00072 ByteIOContext *pb = s->pb;
00073 AVStream *st;
00074 unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
00075 int i;
00076 unsigned int chunk_size;
00077 unsigned int chunk_type;
00078
00079
00080 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
00081 RoQ_CHUNK_PREAMBLE_SIZE)
00082 return AVERROR(EIO);
00083 roq->framerate = AV_RL16(&preamble[6]);
00084 roq->frame_pts_inc = 90000 / roq->framerate;
00085
00086
00087 roq->width = roq->height = roq->audio_channels = roq->video_pts =
00088 roq->audio_frame_count = 0;
00089
00090
00091 for (i = 0; i < RoQ_CHUNKS_TO_SCAN; i++) {
00092 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
00093 RoQ_CHUNK_PREAMBLE_SIZE)
00094 return AVERROR(EIO);
00095
00096 chunk_type = AV_RL16(&preamble[0]);
00097 chunk_size = AV_RL32(&preamble[2]);
00098
00099 switch (chunk_type) {
00100
00101 case RoQ_INFO:
00102
00103 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
00104 RoQ_CHUNK_PREAMBLE_SIZE)
00105 return AVERROR(EIO);
00106 roq->width = AV_RL16(&preamble[0]);
00107 roq->height = AV_RL16(&preamble[2]);
00108 break;
00109
00110 case RoQ_QUAD_CODEBOOK:
00111 case RoQ_QUAD_VQ:
00112
00113 url_fseek(pb, chunk_size, SEEK_CUR);
00114 break;
00115
00116 case RoQ_SOUND_MONO:
00117 roq->audio_channels = 1;
00118 url_fseek(pb, chunk_size, SEEK_CUR);
00119 break;
00120
00121 case RoQ_SOUND_STEREO:
00122 roq->audio_channels = 2;
00123 url_fseek(pb, chunk_size, SEEK_CUR);
00124 break;
00125
00126 default:
00127 av_log(s, AV_LOG_ERROR, " unknown RoQ chunk type (%04X)\n", AV_RL16(&preamble[0]));
00128 return AVERROR_INVALIDDATA;
00129 break;
00130 }
00131
00132
00133 if ((roq->width && roq->height) && roq->audio_channels)
00134 break;
00135 }
00136
00137
00138 url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_SET);
00139
00140
00141 st = av_new_stream(s, 0);
00142 if (!st)
00143 return AVERROR(ENOMEM);
00144
00145 av_set_pts_info(st, 33, 1, 90000);
00146 roq->video_stream_index = st->index;
00147 st->codec->codec_type = CODEC_TYPE_VIDEO;
00148 st->codec->codec_id = CODEC_ID_ROQ;
00149 st->codec->codec_tag = 0;
00150 st->codec->width = roq->width;
00151 st->codec->height = roq->height;
00152
00153 if (roq->audio_channels) {
00154 st = av_new_stream(s, 0);
00155 if (!st)
00156 return AVERROR(ENOMEM);
00157 av_set_pts_info(st, 33, 1, 90000);
00158 roq->audio_stream_index = st->index;
00159 st->codec->codec_type = CODEC_TYPE_AUDIO;
00160 st->codec->codec_id = CODEC_ID_ROQ_DPCM;
00161 st->codec->codec_tag = 0;
00162 st->codec->channels = roq->audio_channels;
00163 st->codec->sample_rate = RoQ_AUDIO_SAMPLE_RATE;
00164 st->codec->bits_per_sample = 16;
00165 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
00166 st->codec->bits_per_sample;
00167 st->codec->block_align = st->codec->channels * st->codec->bits_per_sample;
00168 }
00169
00170 return 0;
00171 }
00172
00173 static int roq_read_packet(AVFormatContext *s,
00174 AVPacket *pkt)
00175 {
00176 RoqDemuxContext *roq = s->priv_data;
00177 ByteIOContext *pb = s->pb;
00178 int ret = 0;
00179 unsigned int chunk_size;
00180 unsigned int chunk_type;
00181 unsigned int codebook_size;
00182 unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
00183 int packet_read = 0;
00184 offset_t codebook_offset;
00185
00186 while (!packet_read) {
00187
00188 if (url_feof(s->pb))
00189 return AVERROR(EIO);
00190
00191
00192 if ((ret = get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) !=
00193 RoQ_CHUNK_PREAMBLE_SIZE)
00194 return AVERROR(EIO);
00195
00196 chunk_type = AV_RL16(&preamble[0]);
00197 chunk_size = AV_RL32(&preamble[2]);
00198 if(chunk_size > INT_MAX)
00199 return AVERROR_INVALIDDATA;
00200
00201 switch (chunk_type) {
00202
00203 case RoQ_INFO:
00204
00205 url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_CUR);
00206 break;
00207
00208 case RoQ_QUAD_CODEBOOK:
00209
00210 codebook_offset = url_ftell(pb) - RoQ_CHUNK_PREAMBLE_SIZE;
00211 codebook_size = chunk_size;
00212 url_fseek(pb, codebook_size, SEEK_CUR);
00213 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
00214 RoQ_CHUNK_PREAMBLE_SIZE)
00215 return AVERROR(EIO);
00216 chunk_size = AV_RL32(&preamble[2]) + RoQ_CHUNK_PREAMBLE_SIZE * 2 +
00217 codebook_size;
00218
00219
00220 url_fseek(pb, codebook_offset, SEEK_SET);
00221
00222
00223 ret= av_get_packet(pb, pkt, chunk_size);
00224 if (ret != chunk_size)
00225 return AVERROR(EIO);
00226 pkt->stream_index = roq->video_stream_index;
00227 pkt->pts = roq->video_pts;
00228
00229 roq->video_pts += roq->frame_pts_inc;
00230 packet_read = 1;
00231 break;
00232
00233 case RoQ_SOUND_MONO:
00234 case RoQ_SOUND_STEREO:
00235 case RoQ_QUAD_VQ:
00236
00237 if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE))
00238 return AVERROR(EIO);
00239
00240 memcpy(pkt->data, preamble, RoQ_CHUNK_PREAMBLE_SIZE);
00241
00242 if (chunk_type == RoQ_QUAD_VQ) {
00243 pkt->stream_index = roq->video_stream_index;
00244 pkt->pts = roq->video_pts;
00245 roq->video_pts += roq->frame_pts_inc;
00246 } else {
00247 pkt->stream_index = roq->audio_stream_index;
00248 pkt->pts = roq->audio_frame_count;
00249 pkt->pts *= 90000;
00250 pkt->pts /= RoQ_AUDIO_SAMPLE_RATE;
00251 roq->audio_frame_count += (chunk_size / roq->audio_channels);
00252 }
00253
00254 pkt->pos= url_ftell(pb);
00255 ret = get_buffer(pb, pkt->data + RoQ_CHUNK_PREAMBLE_SIZE,
00256 chunk_size);
00257 if (ret != chunk_size)
00258 ret = AVERROR(EIO);
00259
00260 packet_read = 1;
00261 break;
00262
00263 default:
00264 av_log(s, AV_LOG_ERROR, " unknown RoQ chunk (%04X)\n", chunk_type);
00265 return AVERROR_INVALIDDATA;
00266 break;
00267 }
00268 }
00269
00270 return ret;
00271 }
00272
00273 static int roq_read_close(AVFormatContext *s)
00274 {
00275
00276
00277 return 0;
00278 }
00279
00280 AVInputFormat roq_demuxer = {
00281 "RoQ",
00282 "Id RoQ format",
00283 sizeof(RoqDemuxContext),
00284 roq_probe,
00285 roq_read_header,
00286 roq_read_packet,
00287 roq_read_close,
00288 };