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