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 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;
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))
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 };