00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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;
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))
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 = avformat_new_stream(s, NULL);
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 = avformat_new_stream(s, NULL);
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 .name = "avs",
00224 .long_name = NULL_IF_CONFIG_SMALL("AVS format"),
00225 .priv_data_size = sizeof(AvsFormat),
00226 .read_probe = avs_probe,
00227 .read_header = avs_read_header,
00228 .read_packet = avs_read_packet,
00229 .read_close = avs_read_close,
00230 };