Libav 0.7.1
|
00001 /* 00002 * AVS demuxer. 00003 * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.org> 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 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 avio_skip(s->pb, 4); 00065 avs->width = avio_rl16(s->pb); 00066 avs->height = avio_rl16(s->pb); 00067 avs->bits_per_sample = avio_rl16(s->pb); 00068 avs->fps = avio_rl16(s->pb); 00069 avs->nb_frames = avio_rl32(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 = avio_read(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 = avio_tell(s->pb); 00127 ret = voc_get_packet(s, pkt, avs->st_audio, avs->remaining_audio_size); 00128 size = avio_tell(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 (!avio_rl16(s->pb)) /* found EOF */ 00158 return AVERROR(EIO); 00159 avs->remaining_frame_size = avio_rl16(s->pb) - 4; 00160 } 00161 00162 while (avs->remaining_frame_size > 0) { 00163 sub_type = avio_r8(s->pb); 00164 type = avio_r8(s->pb); 00165 size = avio_rl16(s->pb); 00166 if (size < 4) 00167 return AVERROR_INVALIDDATA; 00168 avs->remaining_frame_size -= size; 00169 00170 switch (type) { 00171 case AVS_PALETTE: 00172 if (size - 4 > sizeof(palette)) 00173 return AVERROR_INVALIDDATA; 00174 ret = avio_read(s->pb, palette, size - 4); 00175 if (ret < size - 4) 00176 return AVERROR(EIO); 00177 palette_size = size; 00178 break; 00179 00180 case AVS_VIDEO: 00181 if (!avs->st_video) { 00182 avs->st_video = av_new_stream(s, AVS_VIDEO); 00183 if (avs->st_video == NULL) 00184 return AVERROR(ENOMEM); 00185 avs->st_video->codec->codec_type = AVMEDIA_TYPE_VIDEO; 00186 avs->st_video->codec->codec_id = CODEC_ID_AVS; 00187 avs->st_video->codec->width = avs->width; 00188 avs->st_video->codec->height = avs->height; 00189 avs->st_video->codec->bits_per_coded_sample=avs->bits_per_sample; 00190 avs->st_video->nb_frames = avs->nb_frames; 00191 avs->st_video->codec->time_base = (AVRational) { 00192 1, avs->fps}; 00193 } 00194 return avs_read_video_packet(s, pkt, type, sub_type, size, 00195 palette, palette_size); 00196 00197 case AVS_AUDIO: 00198 if (!avs->st_audio) { 00199 avs->st_audio = av_new_stream(s, AVS_AUDIO); 00200 if (avs->st_audio == NULL) 00201 return AVERROR(ENOMEM); 00202 avs->st_audio->codec->codec_type = AVMEDIA_TYPE_AUDIO; 00203 } 00204 avs->remaining_audio_size = size - 4; 00205 size = avs_read_audio_packet(s, pkt); 00206 if (size != 0) 00207 return size; 00208 break; 00209 00210 default: 00211 avio_skip(s->pb, size - 4); 00212 } 00213 } 00214 } 00215 } 00216 00217 static int avs_read_close(AVFormatContext * s) 00218 { 00219 return 0; 00220 } 00221 00222 AVInputFormat ff_avs_demuxer = { 00223 "avs", 00224 NULL_IF_CONFIG_SMALL("AVS format"), 00225 sizeof(AvsFormat), 00226 avs_probe, 00227 avs_read_header, 00228 avs_read_packet, 00229 avs_read_close, 00230 };