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

libavformat/c93.c

Go to the documentation of this file.
00001 /*
00002  * Interplay C93 demuxer
00003  * Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com>
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 
00022 #include "avformat.h"
00023 #include "voc.h"
00024 
00025 typedef struct {
00026     uint16_t index;
00027     uint8_t length;
00028     uint8_t frames;
00029 } C93BlockRecord;
00030 
00031 typedef struct {
00032     VocDecContext voc;
00033 
00034     C93BlockRecord block_records[512];
00035     int current_block;
00036 
00037     uint32_t frame_offsets[32];
00038     int current_frame;
00039     int next_pkt_is_audio;
00040 
00041     AVStream *audio;
00042 } C93DemuxContext;
00043 
00044 static int probe(AVProbeData *p)
00045 {
00046     if (p->buf[0] == 0x01 && p->buf[1] == 0x00 &&
00047         p->buf[4] == 0x01 + p->buf[2] &&
00048         p->buf[8] == p->buf[4] + p->buf[6] &&
00049         p->buf[12] == p->buf[8] + p->buf[10])
00050         return AVPROBE_SCORE_MAX;
00051 
00052     return 0;
00053 }
00054 
00055 static int read_header(AVFormatContext *s,
00056                            AVFormatParameters *ap)
00057 {
00058     AVStream *video;
00059     ByteIOContext *pb = s->pb;
00060     C93DemuxContext *c93 = s->priv_data;
00061     int i;
00062     int framecount = 0;
00063 
00064     for (i = 0; i < 512; i++) {
00065         c93->block_records[i].index = get_le16(pb);
00066         c93->block_records[i].length = get_byte(pb);
00067         c93->block_records[i].frames = get_byte(pb);
00068         if (c93->block_records[i].frames > 32) {
00069             av_log(s, AV_LOG_ERROR, "too many frames in block\n");
00070             return AVERROR_INVALIDDATA;
00071         }
00072         framecount += c93->block_records[i].frames;
00073     }
00074 
00075     /* Audio streams are added if audio packets are found */
00076     s->ctx_flags |= AVFMTCTX_NOHEADER;
00077 
00078     video = av_new_stream(s, 0);
00079     if (!video)
00080         return AVERROR(ENOMEM);
00081 
00082     video->codec->codec_type = CODEC_TYPE_VIDEO;
00083     video->codec->codec_id = CODEC_ID_C93;
00084     video->codec->width = 320;
00085     video->codec->height = 192;
00086     /* 4:3 320x200 with 8 empty lines */
00087     video->sample_aspect_ratio = (AVRational) { 5, 6 };
00088     video->time_base = (AVRational) { 2, 25 };
00089     video->nb_frames = framecount;
00090     video->duration = framecount;
00091     video->start_time = 0;
00092 
00093     c93->current_block = 0;
00094     c93->current_frame = 0;
00095     c93->next_pkt_is_audio = 0;
00096     return 0;
00097 }
00098 
00099 #define C93_HAS_PALETTE 0x01
00100 #define C93_FIRST_FRAME 0x02
00101 
00102 static int read_packet(AVFormatContext *s, AVPacket *pkt)
00103 {
00104     ByteIOContext *pb = s->pb;
00105     C93DemuxContext *c93 = s->priv_data;
00106     C93BlockRecord *br = &c93->block_records[c93->current_block];
00107     int datasize;
00108     int ret, i;
00109 
00110     if (c93->next_pkt_is_audio) {
00111         c93->current_frame++;
00112         c93->next_pkt_is_audio = 0;
00113         datasize = get_le16(pb);
00114         if (datasize > 42) {
00115             if (!c93->audio) {
00116                 c93->audio = av_new_stream(s, 1);
00117                 if (!c93->audio)
00118                     return AVERROR(ENOMEM);
00119                 c93->audio->codec->codec_type = CODEC_TYPE_AUDIO;
00120             }
00121             url_fskip(pb, 26); /* VOC header */
00122             ret = voc_get_packet(s, pkt, c93->audio, datasize - 26);
00123             if (ret > 0) {
00124                 pkt->stream_index = 1;
00125                 pkt->flags |= PKT_FLAG_KEY;
00126                 return ret;
00127             }
00128         }
00129     }
00130     if (c93->current_frame >= br->frames) {
00131         if (c93->current_block >= 511 || !br[1].length)
00132             return AVERROR(EIO);
00133         br++;
00134         c93->current_block++;
00135         c93->current_frame = 0;
00136     }
00137 
00138     if (c93->current_frame == 0) {
00139         url_fseek(pb, br->index * 2048, SEEK_SET);
00140         for (i = 0; i < 32; i++) {
00141             c93->frame_offsets[i] = get_le32(pb);
00142         }
00143     }
00144 
00145     url_fseek(pb,br->index * 2048 +
00146             c93->frame_offsets[c93->current_frame], SEEK_SET);
00147     datasize = get_le16(pb); /* video frame size */
00148 
00149     ret = av_new_packet(pkt, datasize + 768 + 1);
00150     if (ret < 0)
00151         return ret;
00152     pkt->data[0] = 0;
00153     pkt->size = datasize + 1;
00154 
00155     ret = get_buffer(pb, pkt->data + 1, datasize);
00156     if (ret < datasize) {
00157         ret = AVERROR(EIO);
00158         goto fail;
00159     }
00160 
00161     datasize = get_le16(pb); /* palette size */
00162     if (datasize) {
00163         if (datasize != 768) {
00164             av_log(s, AV_LOG_ERROR, "invalid palette size %u\n", datasize);
00165             ret = AVERROR_INVALIDDATA;
00166             goto fail;
00167         }
00168         pkt->data[0] |= C93_HAS_PALETTE;
00169         ret = get_buffer(pb, pkt->data + pkt->size, datasize);
00170         if (ret < datasize) {
00171             ret = AVERROR(EIO);
00172             goto fail;
00173         }
00174         pkt->size += 768;
00175     }
00176     pkt->stream_index = 0;
00177     c93->next_pkt_is_audio = 1;
00178 
00179     /* only the first frame is guaranteed to not reference previous frames */
00180     if (c93->current_block == 0 && c93->current_frame == 0) {
00181         pkt->flags |= PKT_FLAG_KEY;
00182         pkt->data[0] |= C93_FIRST_FRAME;
00183     }
00184     return 0;
00185 
00186     fail:
00187     av_free_packet(pkt);
00188     return ret;
00189 }
00190 
00191 AVInputFormat c93_demuxer = {
00192     "c93",
00193     NULL_IF_CONFIG_SMALL("Interplay C93"),
00194     sizeof(C93DemuxContext),
00195     probe,
00196     read_header,
00197     read_packet,
00198 };

Generated on Tue Nov 4 2014 12:59:21 for ffmpeg by  doxygen 1.7.1