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

libavformat/avs.c

Go to the documentation of this file.
00001 /*
00002  * AVS demuxer.
00003  * Copyright (c) 2006  Aurelien Jacobs <aurel@gnuage.org>
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 
00026 typedef struct avs_format {
00027     VocDecContext voc;
00028     AVStream *st_video;
00029     AVStream *st_audio;
00030     int width;
00031     int height;
00032     int bits_per_sample;
00033     int fps;
00034     int nb_frames;
00035     int remaining_frame_size;
00036     int remaining_audio_size;
00037 } AvsFormat;
00038 
00039 typedef enum avs_block_type {
00040     AVS_NONE      = 0x00,
00041     AVS_VIDEO     = 0x01,
00042     AVS_AUDIO     = 0x02,
00043     AVS_PALETTE   = 0x03,
00044     AVS_GAME_DATA = 0x04,
00045 } AvsBlockType;
00046 
00047 static int avs_probe(AVProbeData * p)
00048 {
00049     const uint8_t *d;
00050 
00051     d = p->buf;
00052     if (d[0] == 'w' && d[1] == 'W' && d[2] == 0x10 && d[3] == 0)
00053         return 50;
00054 
00055     return 0;
00056 }
00057 
00058 static int avs_read_header(AVFormatContext * s, AVFormatParameters * ap)
00059 {
00060     AvsFormat *avs = s->priv_data;
00061 
00062     s->ctx_flags |= AVFMTCTX_NOHEADER;
00063 
00064     url_fskip(s->pb, 4);
00065     avs->width = get_le16(s->pb);
00066     avs->height = get_le16(s->pb);
00067     avs->bits_per_sample = get_le16(s->pb);
00068     avs->fps = get_le16(s->pb);
00069     avs->nb_frames = get_le32(s->pb);
00070     avs->remaining_frame_size = 0;
00071     avs->remaining_audio_size = 0;
00072 
00073     avs->st_video = avs->st_audio = NULL;
00074 
00075     if (avs->width != 318 || avs->height != 198)
00076         av_log(s, AV_LOG_ERROR, "This avs pretend to be %dx%d "
00077                "when the avs format is supposed to be 318x198 only.\n",
00078                avs->width, avs->height);
00079 
00080     return 0;
00081 }
00082 
00083 static int
00084 avs_read_video_packet(AVFormatContext * s, AVPacket * pkt,
00085                       AvsBlockType type, int sub_type, int size,
00086                       uint8_t * palette, int palette_size)
00087 {
00088     AvsFormat *avs = s->priv_data;
00089     int ret;
00090 
00091     ret = av_new_packet(pkt, size + palette_size);
00092     if (ret < 0)
00093         return ret;
00094 
00095     if (palette_size) {
00096         pkt->data[0] = 0x00;
00097         pkt->data[1] = 0x03;
00098         pkt->data[2] = palette_size & 0xFF;
00099         pkt->data[3] = (palette_size >> 8) & 0xFF;
00100         memcpy(pkt->data + 4, palette, palette_size - 4);
00101     }
00102 
00103     pkt->data[palette_size + 0] = sub_type;
00104     pkt->data[palette_size + 1] = type;
00105     pkt->data[palette_size + 2] = size & 0xFF;
00106     pkt->data[palette_size + 3] = (size >> 8) & 0xFF;
00107     ret = get_buffer(s->pb, pkt->data + palette_size + 4, size - 4) + 4;
00108     if (ret < size) {
00109         av_free_packet(pkt);
00110         return AVERROR(EIO);
00111     }
00112 
00113     pkt->size = ret + palette_size;
00114     pkt->stream_index = avs->st_video->index;
00115     if (sub_type == 0)
00116         pkt->flags |= AV_PKT_FLAG_KEY;
00117 
00118     return 0;
00119 }
00120 
00121 static int avs_read_audio_packet(AVFormatContext * s, AVPacket * pkt)
00122 {
00123     AvsFormat *avs = s->priv_data;
00124     int ret, size;
00125 
00126     size = url_ftell(s->pb);
00127     ret = voc_get_packet(s, pkt, avs->st_audio, avs->remaining_audio_size);
00128     size = url_ftell(s->pb) - size;
00129     avs->remaining_audio_size -= size;
00130 
00131     if (ret == AVERROR(EIO))
00132         return 0;    /* this indicate EOS */
00133     if (ret < 0)
00134         return ret;
00135 
00136     pkt->stream_index = avs->st_audio->index;
00137     pkt->flags |= AV_PKT_FLAG_KEY;
00138 
00139     return size;
00140 }
00141 
00142 static int avs_read_packet(AVFormatContext * s, AVPacket * pkt)
00143 {
00144     AvsFormat *avs = s->priv_data;
00145     int sub_type = 0, size = 0;
00146     AvsBlockType type = AVS_NONE;
00147     int palette_size = 0;
00148     uint8_t palette[4 + 3 * 256];
00149     int ret;
00150 
00151     if (avs->remaining_audio_size > 0)
00152         if (avs_read_audio_packet(s, pkt) > 0)
00153             return 0;
00154 
00155     while (1) {
00156         if (avs->remaining_frame_size <= 0) {
00157             if (!get_le16(s->pb))    /* found EOF */
00158                 return AVERROR(EIO);
00159             avs->remaining_frame_size = get_le16(s->pb) - 4;
00160         }
00161 
00162         while (avs->remaining_frame_size > 0) {
00163             sub_type = get_byte(s->pb);
00164             type = get_byte(s->pb);
00165             size = get_le16(s->pb);
00166             avs->remaining_frame_size -= size;
00167 
00168             switch (type) {
00169             case AVS_PALETTE:
00170                 ret = get_buffer(s->pb, palette, size - 4);
00171                 if (ret < size - 4)
00172                     return AVERROR(EIO);
00173                 palette_size = size;
00174                 break;
00175 
00176             case AVS_VIDEO:
00177                 if (!avs->st_video) {
00178                     avs->st_video = av_new_stream(s, AVS_VIDEO);
00179                     if (avs->st_video == NULL)
00180                         return AVERROR(ENOMEM);
00181                     avs->st_video->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00182                     avs->st_video->codec->codec_id = CODEC_ID_AVS;
00183                     avs->st_video->codec->width = avs->width;
00184                     avs->st_video->codec->height = avs->height;
00185                     avs->st_video->codec->bits_per_coded_sample=avs->bits_per_sample;
00186                     avs->st_video->nb_frames = avs->nb_frames;
00187                     avs->st_video->codec->time_base = (AVRational) {
00188                     1, avs->fps};
00189                 }
00190                 return avs_read_video_packet(s, pkt, type, sub_type, size,
00191                                              palette, palette_size);
00192 
00193             case AVS_AUDIO:
00194                 if (!avs->st_audio) {
00195                     avs->st_audio = av_new_stream(s, AVS_AUDIO);
00196                     if (avs->st_audio == NULL)
00197                         return AVERROR(ENOMEM);
00198                     avs->st_audio->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00199                 }
00200                 avs->remaining_audio_size = size - 4;
00201                 size = avs_read_audio_packet(s, pkt);
00202                 if (size != 0)
00203                     return size;
00204                 break;
00205 
00206             default:
00207                 url_fskip(s->pb, size - 4);
00208             }
00209         }
00210     }
00211 }
00212 
00213 static int avs_read_close(AVFormatContext * s)
00214 {
00215     return 0;
00216 }
00217 
00218 AVInputFormat avs_demuxer = {
00219     "avs",
00220     NULL_IF_CONFIG_SMALL("AVS format"),
00221     sizeof(AvsFormat),
00222     avs_probe,
00223     avs_read_header,
00224     avs_read_packet,
00225     avs_read_close,
00226 };

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