• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • 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 Libav.
00006  *
00007  * Libav 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  * Libav 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 Libav; 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 
00034 #define RoQ_MAGIC_NUMBER 0x1084
00035 #define RoQ_CHUNK_PREAMBLE_SIZE 8
00036 #define RoQ_AUDIO_SAMPLE_RATE 22050
00037 #define RoQ_CHUNKS_TO_SCAN 30
00038 
00039 #define RoQ_INFO           0x1001
00040 #define RoQ_QUAD_CODEBOOK  0x1002
00041 #define RoQ_QUAD_VQ        0x1011
00042 #define RoQ_SOUND_MONO     0x1020
00043 #define RoQ_SOUND_STEREO   0x1021
00044 
00045 typedef struct RoqDemuxContext {
00046 
00047     int frame_rate;
00048     int width;
00049     int height;
00050     int audio_channels;
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     AVIOContext *pb = s->pb;
00074     unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
00075 
00076     /* get the main header */
00077     if (avio_read(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
00078         RoQ_CHUNK_PREAMBLE_SIZE)
00079         return AVERROR(EIO);
00080     roq->frame_rate = AV_RL16(&preamble[6]);
00081 
00082     /* init private context parameters */
00083     roq->width = roq->height = roq->audio_channels = roq->video_pts =
00084     roq->audio_frame_count = 0;
00085     roq->audio_stream_index = -1;
00086     roq->video_stream_index = -1;
00087 
00088     s->ctx_flags |= AVFMTCTX_NOHEADER;
00089 
00090     return 0;
00091 }
00092 
00093 static int roq_read_packet(AVFormatContext *s,
00094                            AVPacket *pkt)
00095 {
00096     RoqDemuxContext *roq = s->priv_data;
00097     AVIOContext *pb = s->pb;
00098     int ret = 0;
00099     unsigned int chunk_size;
00100     unsigned int chunk_type;
00101     unsigned int codebook_size;
00102     unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
00103     int packet_read = 0;
00104     int64_t codebook_offset;
00105 
00106     while (!packet_read) {
00107 
00108         if (s->pb->eof_reached)
00109             return AVERROR(EIO);
00110 
00111         /* get the next chunk preamble */
00112         if ((ret = avio_read(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) !=
00113             RoQ_CHUNK_PREAMBLE_SIZE)
00114             return AVERROR(EIO);
00115 
00116         chunk_type = AV_RL16(&preamble[0]);
00117         chunk_size = AV_RL32(&preamble[2]);
00118         if(chunk_size > INT_MAX)
00119             return AVERROR_INVALIDDATA;
00120 
00121         switch (chunk_type) {
00122 
00123         case RoQ_INFO:
00124             if (roq->video_stream_index == -1) {
00125                 AVStream *st = avformat_new_stream(s, NULL);
00126                 if (!st)
00127                     return AVERROR(ENOMEM);
00128                 avpriv_set_pts_info(st, 63, 1, roq->frame_rate);
00129                 roq->video_stream_index = st->index;
00130                 st->codec->codec_type   = AVMEDIA_TYPE_VIDEO;
00131                 st->codec->codec_id     = CODEC_ID_ROQ;
00132                 st->codec->codec_tag    = 0;  /* no fourcc */
00133 
00134                 if (avio_read(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE)
00135                     return AVERROR(EIO);
00136                 st->codec->width  = roq->width  = AV_RL16(preamble);
00137                 st->codec->height = roq->height = AV_RL16(preamble + 2);
00138                 break;
00139             }
00140             /* don't care about this chunk anymore */
00141             avio_skip(pb, RoQ_CHUNK_PREAMBLE_SIZE);
00142             break;
00143 
00144         case RoQ_QUAD_CODEBOOK:
00145             /* packet needs to contain both this codebook and next VQ chunk */
00146             codebook_offset = avio_tell(pb) - RoQ_CHUNK_PREAMBLE_SIZE;
00147             codebook_size = chunk_size;
00148             avio_skip(pb, codebook_size);
00149             if (avio_read(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
00150                 RoQ_CHUNK_PREAMBLE_SIZE)
00151                 return AVERROR(EIO);
00152             chunk_size = AV_RL32(&preamble[2]) + RoQ_CHUNK_PREAMBLE_SIZE * 2 +
00153                 codebook_size;
00154 
00155             /* rewind */
00156             avio_seek(pb, codebook_offset, SEEK_SET);
00157 
00158             /* load up the packet */
00159             ret= av_get_packet(pb, pkt, chunk_size);
00160             if (ret != chunk_size)
00161                 return AVERROR(EIO);
00162             pkt->stream_index = roq->video_stream_index;
00163             pkt->pts = roq->video_pts++;
00164 
00165             packet_read = 1;
00166             break;
00167 
00168         case RoQ_SOUND_MONO:
00169         case RoQ_SOUND_STEREO:
00170             if (roq->audio_stream_index == -1) {
00171                 AVStream *st = avformat_new_stream(s, NULL);
00172                 if (!st)
00173                     return AVERROR(ENOMEM);
00174                 avpriv_set_pts_info(st, 32, 1, RoQ_AUDIO_SAMPLE_RATE);
00175                 roq->audio_stream_index = st->index;
00176                 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00177                 st->codec->codec_id = CODEC_ID_ROQ_DPCM;
00178                 st->codec->codec_tag = 0;  /* no tag */
00179                 st->codec->channels = roq->audio_channels = chunk_type == RoQ_SOUND_STEREO ? 2 : 1;
00180                 st->codec->sample_rate = RoQ_AUDIO_SAMPLE_RATE;
00181                 st->codec->bits_per_coded_sample = 16;
00182                 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
00183                     st->codec->bits_per_coded_sample;
00184                 st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
00185             }
00186         case RoQ_QUAD_VQ:
00187             /* load up the packet */
00188             if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE))
00189                 return AVERROR(EIO);
00190             /* copy over preamble */
00191             memcpy(pkt->data, preamble, RoQ_CHUNK_PREAMBLE_SIZE);
00192 
00193             if (chunk_type == RoQ_QUAD_VQ) {
00194                 pkt->stream_index = roq->video_stream_index;
00195                 pkt->pts = roq->video_pts++;
00196             } else {
00197                 pkt->stream_index = roq->audio_stream_index;
00198                 pkt->pts = roq->audio_frame_count;
00199                 roq->audio_frame_count += (chunk_size / roq->audio_channels);
00200             }
00201 
00202             pkt->pos= avio_tell(pb);
00203             ret = avio_read(pb, pkt->data + RoQ_CHUNK_PREAMBLE_SIZE,
00204                 chunk_size);
00205             if (ret != chunk_size)
00206                 ret = AVERROR(EIO);
00207 
00208             packet_read = 1;
00209             break;
00210 
00211         default:
00212             av_log(s, AV_LOG_ERROR, "  unknown RoQ chunk (%04X)\n", chunk_type);
00213             return AVERROR_INVALIDDATA;
00214         }
00215     }
00216 
00217     return ret;
00218 }
00219 
00220 AVInputFormat ff_roq_demuxer = {
00221     .name           = "RoQ",
00222     .long_name      = NULL_IF_CONFIG_SMALL("id RoQ format"),
00223     .priv_data_size = sizeof(RoqDemuxContext),
00224     .read_probe     = roq_probe,
00225     .read_header    = roq_read_header,
00226     .read_packet    = roq_read_packet,
00227 };
Generated on Sat Mar 17 2012 12:57:53 for Libav by doxygen 1.7.1