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