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 #include "internal.h"
00033 #include "avio_internal.h"
00034
00035 #define RoQ_MAGIC_NUMBER 0x1084
00036 #define RoQ_CHUNK_PREAMBLE_SIZE 8
00037 #define RoQ_AUDIO_SAMPLE_RATE 22050
00038 #define RoQ_CHUNKS_TO_SCAN 30
00039
00040 #define RoQ_INFO 0x1001
00041 #define RoQ_QUAD_CODEBOOK 0x1002
00042 #define RoQ_QUAD_VQ 0x1011
00043 #define RoQ_SOUND_MONO 0x1020
00044 #define RoQ_SOUND_STEREO 0x1021
00045
00046 typedef struct RoqDemuxContext {
00047
00048 int frame_rate;
00049 int width;
00050 int height;
00051 int audio_channels;
00052
00053 int video_stream_index;
00054 int audio_stream_index;
00055
00056 int64_t video_pts;
00057 unsigned int audio_frame_count;
00058
00059 } RoqDemuxContext;
00060
00061 static int roq_probe(AVProbeData *p)
00062 {
00063 if ((AV_RL16(&p->buf[0]) != RoQ_MAGIC_NUMBER) ||
00064 (AV_RL32(&p->buf[2]) != 0xFFFFFFFF))
00065 return 0;
00066
00067 return AVPROBE_SCORE_MAX;
00068 }
00069
00070 static int roq_read_header(AVFormatContext *s,
00071 AVFormatParameters *ap)
00072 {
00073 RoqDemuxContext *roq = s->priv_data;
00074 AVIOContext *pb = s->pb;
00075 unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
00076
00077
00078 if (avio_read(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
00079 RoQ_CHUNK_PREAMBLE_SIZE)
00080 return AVERROR(EIO);
00081 roq->frame_rate = AV_RL16(&preamble[6]);
00082
00083
00084 roq->width = roq->height = roq->audio_channels = roq->video_pts =
00085 roq->audio_frame_count = 0;
00086 roq->audio_stream_index = -1;
00087 roq->video_stream_index = -1;
00088
00089 s->ctx_flags |= AVFMTCTX_NOHEADER;
00090
00091 return 0;
00092 }
00093
00094 static int roq_read_packet(AVFormatContext *s,
00095 AVPacket *pkt)
00096 {
00097 RoqDemuxContext *roq = s->priv_data;
00098 AVIOContext *pb = s->pb;
00099 int ret = 0;
00100 unsigned int chunk_size;
00101 unsigned int chunk_type;
00102 unsigned int codebook_size;
00103 unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
00104 int packet_read = 0;
00105 int64_t codebook_offset;
00106
00107 while (!packet_read) {
00108
00109 if (url_feof(s->pb))
00110 return AVERROR(EIO);
00111
00112
00113 if ((ret = avio_read(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) !=
00114 RoQ_CHUNK_PREAMBLE_SIZE)
00115 return AVERROR(EIO);
00116
00117 chunk_type = AV_RL16(&preamble[0]);
00118 chunk_size = AV_RL32(&preamble[2]);
00119 if(chunk_size > INT_MAX)
00120 return AVERROR_INVALIDDATA;
00121
00122 chunk_size = ffio_limit(pb, chunk_size);
00123
00124 switch (chunk_type) {
00125
00126 case RoQ_INFO:
00127 if (roq->video_stream_index == -1) {
00128 AVStream *st = avformat_new_stream(s, NULL);
00129 if (!st)
00130 return AVERROR(ENOMEM);
00131 avpriv_set_pts_info(st, 63, 1, roq->frame_rate);
00132 roq->video_stream_index = st->index;
00133 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00134 st->codec->codec_id = CODEC_ID_ROQ;
00135 st->codec->codec_tag = 0;
00136
00137 if (avio_read(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE)
00138 return AVERROR(EIO);
00139 st->codec->width = roq->width = AV_RL16(preamble);
00140 st->codec->height = roq->height = AV_RL16(preamble + 2);
00141 break;
00142 }
00143
00144 avio_skip(pb, RoQ_CHUNK_PREAMBLE_SIZE);
00145 break;
00146
00147 case RoQ_QUAD_CODEBOOK:
00148
00149 codebook_offset = avio_tell(pb) - RoQ_CHUNK_PREAMBLE_SIZE;
00150 codebook_size = chunk_size;
00151 avio_skip(pb, codebook_size);
00152 if (avio_read(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
00153 RoQ_CHUNK_PREAMBLE_SIZE)
00154 return AVERROR(EIO);
00155 chunk_size = AV_RL32(&preamble[2]) + RoQ_CHUNK_PREAMBLE_SIZE * 2 +
00156 codebook_size;
00157
00158
00159 avio_seek(pb, codebook_offset, SEEK_SET);
00160
00161
00162 ret= av_get_packet(pb, pkt, chunk_size);
00163 if (ret != chunk_size)
00164 return AVERROR(EIO);
00165 pkt->stream_index = roq->video_stream_index;
00166 pkt->pts = roq->video_pts++;
00167
00168 packet_read = 1;
00169 break;
00170
00171 case RoQ_SOUND_MONO:
00172 case RoQ_SOUND_STEREO:
00173 if (roq->audio_stream_index == -1) {
00174 AVStream *st = avformat_new_stream(s, NULL);
00175 if (!st)
00176 return AVERROR(ENOMEM);
00177 avpriv_set_pts_info(st, 32, 1, RoQ_AUDIO_SAMPLE_RATE);
00178 roq->audio_stream_index = st->index;
00179 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00180 st->codec->codec_id = CODEC_ID_ROQ_DPCM;
00181 st->codec->codec_tag = 0;
00182 st->codec->channels = roq->audio_channels = chunk_type == RoQ_SOUND_STEREO ? 2 : 1;
00183 st->codec->sample_rate = RoQ_AUDIO_SAMPLE_RATE;
00184 st->codec->bits_per_coded_sample = 16;
00185 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
00186 st->codec->bits_per_coded_sample;
00187 st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
00188 }
00189 case RoQ_QUAD_VQ:
00190
00191 if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE))
00192 return AVERROR(EIO);
00193
00194 memcpy(pkt->data, preamble, RoQ_CHUNK_PREAMBLE_SIZE);
00195
00196 if (chunk_type == RoQ_QUAD_VQ) {
00197 pkt->stream_index = roq->video_stream_index;
00198 pkt->pts = roq->video_pts++;
00199 } else {
00200 pkt->stream_index = roq->audio_stream_index;
00201 pkt->pts = roq->audio_frame_count;
00202 roq->audio_frame_count += (chunk_size / roq->audio_channels);
00203 }
00204
00205 pkt->pos= avio_tell(pb);
00206 ret = avio_read(pb, pkt->data + RoQ_CHUNK_PREAMBLE_SIZE,
00207 chunk_size);
00208 if (ret != chunk_size)
00209 ret = AVERROR(EIO);
00210
00211 packet_read = 1;
00212 break;
00213
00214 default:
00215 av_log(s, AV_LOG_ERROR, " unknown RoQ chunk (%04X)\n", chunk_type);
00216 return AVERROR_INVALIDDATA;
00217 }
00218 }
00219
00220 return ret;
00221 }
00222
00223 AVInputFormat ff_roq_demuxer = {
00224 .name = "RoQ",
00225 .long_name = NULL_IF_CONFIG_SMALL("id RoQ format"),
00226 .priv_data_size = sizeof(RoqDemuxContext),
00227 .read_probe = roq_probe,
00228 .read_header = roq_read_header,
00229 .read_packet = roq_read_packet,
00230 };