• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/idroqdec.c

Go to the documentation of this file.
00001 /*
00002  * id RoQ (.roq) File Demuxer
00003  * Copyright (c) 2003 The ffmpeg Project
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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     /* get the main header */
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     /* init private context parameters */
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         /* get the next chunk preamble */
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;  /* no fourcc */
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             /* don't care about this chunk anymore */
00144             avio_skip(pb, RoQ_CHUNK_PREAMBLE_SIZE);
00145             break;
00146 
00147         case RoQ_QUAD_CODEBOOK:
00148             /* packet needs to contain both this codebook and next VQ chunk */
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             /* rewind */
00159             avio_seek(pb, codebook_offset, SEEK_SET);
00160 
00161             /* load up the packet */
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;  /* no tag */
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             /* load up the packet */
00191             if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE))
00192                 return AVERROR(EIO);
00193             /* copy over preamble */
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 };
Generated on Fri Feb 1 2013 14:34:52 for FFmpeg by doxygen 1.7.1