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

libavformat/idroq.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 
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 
00050     int video_stream_index;
00051     int audio_stream_index;
00052 
00053     int64_t video_pts;
00054     unsigned int audio_frame_count;
00055 
00056 } RoqDemuxContext;
00057 
00058 static int roq_probe(AVProbeData *p)
00059 {
00060     if ((AV_RL16(&p->buf[0]) != RoQ_MAGIC_NUMBER) ||
00061         (AV_RL32(&p->buf[2]) != 0xFFFFFFFF))
00062         return 0;
00063 
00064     return AVPROBE_SCORE_MAX;
00065 }
00066 
00067 static int roq_read_header(AVFormatContext *s,
00068                            AVFormatParameters *ap)
00069 {
00070     RoqDemuxContext *roq = s->priv_data;
00071     ByteIOContext *pb = s->pb;
00072     int framerate;
00073     AVStream *st;
00074     unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
00075 
00076     /* get the main header */
00077     if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
00078         RoQ_CHUNK_PREAMBLE_SIZE)
00079         return AVERROR(EIO);
00080     framerate = 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 
00087     st = av_new_stream(s, 0);
00088     if (!st)
00089         return AVERROR(ENOMEM);
00090     av_set_pts_info(st, 63, 1, framerate);
00091     roq->video_stream_index = st->index;
00092     st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00093     st->codec->codec_id = CODEC_ID_ROQ;
00094     st->codec->codec_tag = 0;  /* no fourcc */
00095 
00096     return 0;
00097 }
00098 
00099 static int roq_read_packet(AVFormatContext *s,
00100                            AVPacket *pkt)
00101 {
00102     RoqDemuxContext *roq = s->priv_data;
00103     ByteIOContext *pb = s->pb;
00104     int ret = 0;
00105     unsigned int chunk_size;
00106     unsigned int chunk_type;
00107     unsigned int codebook_size;
00108     unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
00109     int packet_read = 0;
00110     int64_t codebook_offset;
00111 
00112     while (!packet_read) {
00113 
00114         if (url_feof(s->pb))
00115             return AVERROR(EIO);
00116 
00117         /* get the next chunk preamble */
00118         if ((ret = get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) !=
00119             RoQ_CHUNK_PREAMBLE_SIZE)
00120             return AVERROR(EIO);
00121 
00122         chunk_type = AV_RL16(&preamble[0]);
00123         chunk_size = AV_RL32(&preamble[2]);
00124         if(chunk_size > INT_MAX)
00125             return AVERROR_INVALIDDATA;
00126 
00127         switch (chunk_type) {
00128 
00129         case RoQ_INFO:
00130             if (!roq->width || !roq->height) {
00131                 AVStream *st = s->streams[roq->video_stream_index];
00132                 if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE)
00133                     return AVERROR(EIO);
00134                 st->codec->width  = roq->width  = AV_RL16(preamble);
00135                 st->codec->height = roq->height = AV_RL16(preamble + 2);
00136                 break;
00137             }
00138             /* don't care about this chunk anymore */
00139             url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_CUR);
00140             break;
00141 
00142         case RoQ_QUAD_CODEBOOK:
00143             /* packet needs to contain both this codebook and next VQ chunk */
00144             codebook_offset = url_ftell(pb) - RoQ_CHUNK_PREAMBLE_SIZE;
00145             codebook_size = chunk_size;
00146             url_fseek(pb, codebook_size, SEEK_CUR);
00147             if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
00148                 RoQ_CHUNK_PREAMBLE_SIZE)
00149                 return AVERROR(EIO);
00150             chunk_size = AV_RL32(&preamble[2]) + RoQ_CHUNK_PREAMBLE_SIZE * 2 +
00151                 codebook_size;
00152 
00153             /* rewind */
00154             url_fseek(pb, codebook_offset, SEEK_SET);
00155 
00156             /* load up the packet */
00157             ret= av_get_packet(pb, pkt, chunk_size);
00158             if (ret != chunk_size)
00159                 return AVERROR(EIO);
00160             pkt->stream_index = roq->video_stream_index;
00161             pkt->pts = roq->video_pts++;
00162 
00163             packet_read = 1;
00164             break;
00165 
00166         case RoQ_SOUND_MONO:
00167         case RoQ_SOUND_STEREO:
00168             if (roq->audio_stream_index == -1) {
00169                 AVStream *st = av_new_stream(s, 1);
00170                 if (!st)
00171                     return AVERROR(ENOMEM);
00172                 av_set_pts_info(st, 32, 1, RoQ_AUDIO_SAMPLE_RATE);
00173                 roq->audio_stream_index = st->index;
00174                 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00175                 st->codec->codec_id = CODEC_ID_ROQ_DPCM;
00176                 st->codec->codec_tag = 0;  /* no tag */
00177                 st->codec->channels = roq->audio_channels = chunk_type == RoQ_SOUND_STEREO ? 2 : 1;
00178                 st->codec->sample_rate = RoQ_AUDIO_SAMPLE_RATE;
00179                 st->codec->bits_per_coded_sample = 16;
00180                 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
00181                     st->codec->bits_per_coded_sample;
00182                 st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
00183             }
00184         case RoQ_QUAD_VQ:
00185             /* load up the packet */
00186             if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE))
00187                 return AVERROR(EIO);
00188             /* copy over preamble */
00189             memcpy(pkt->data, preamble, RoQ_CHUNK_PREAMBLE_SIZE);
00190 
00191             if (chunk_type == RoQ_QUAD_VQ) {
00192                 pkt->stream_index = roq->video_stream_index;
00193                 pkt->pts = roq->video_pts++;
00194             } else {
00195                 pkt->stream_index = roq->audio_stream_index;
00196                 pkt->pts = roq->audio_frame_count;
00197                 roq->audio_frame_count += (chunk_size / roq->audio_channels);
00198             }
00199 
00200             pkt->pos= url_ftell(pb);
00201             ret = get_buffer(pb, pkt->data + RoQ_CHUNK_PREAMBLE_SIZE,
00202                 chunk_size);
00203             if (ret != chunk_size)
00204                 ret = AVERROR(EIO);
00205 
00206             packet_read = 1;
00207             break;
00208 
00209         default:
00210             av_log(s, AV_LOG_ERROR, "  unknown RoQ chunk (%04X)\n", chunk_type);
00211             return AVERROR_INVALIDDATA;
00212             break;
00213         }
00214     }
00215 
00216     return ret;
00217 }
00218 
00219 AVInputFormat roq_demuxer = {
00220     "RoQ",
00221     NULL_IF_CONFIG_SMALL("id RoQ format"),
00222     sizeof(RoqDemuxContext),
00223     roq_probe,
00224     roq_read_header,
00225     roq_read_packet,
00226 };

Generated on Fri Sep 16 2011 17:17:48 for FFmpeg by  doxygen 1.7.1