courtesy of Aurelien Jacobs <aurel at gnuage dot org> Originally committed as revision 5028 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -40,6 +40,7 @@ version <next> | |||
| - Zip Blocks Motion Video decoder | |||
| - Improved Theora/VP3 decoder | |||
| - True Audio (TTA) decoder | |||
| - AVS demuxer and video decoder | |||
| version 0.4.9-pre1: | |||
| @@ -700,6 +700,8 @@ library: | |||
| @item Creative VOC @tab X @tab X @tab Created for the Sound Blaster Pro. | |||
| @item American Laser Games MM @tab @tab X | |||
| @tab Multimedia format used in games like Mad Dog McCree | |||
| @item AVS @tab @tab X | |||
| @tab Multimedia format used by the Creature Shock game. | |||
| @end multitable | |||
| @code{X} means that encoding (resp. decoding) is supported. | |||
| @@ -792,6 +794,7 @@ following image formats are supported: | |||
| @item CamStudio @tab @tab X @tab fourcc: CSCD | |||
| @item American Laser Games Video @tab @tab X @tab Used in games like Mad Dog McCree | |||
| @item ZMBV @tab @tab X @tab | |||
| @item AVS Video @tab @tab X @tab Video encoding used by the Creature Shock game. | |||
| @end multitable | |||
| @code{X} means that encoding (resp. decoding) is supported. | |||
| @@ -29,6 +29,9 @@ endif | |||
| ifneq ($(CONFIG_ASV1_DECODER)$(CONFIG_ASV1_ENCODER)$(CONFIG_ASV2_DECODER)$(CONFIG_ASV2_ENCODER),) | |||
| OBJS+= asv1.o | |||
| endif | |||
| ifeq ($(CONFIG_AVS_DECODER),yes) | |||
| OBJS+= avs.o | |||
| endif | |||
| ifeq ($(CONFIG_CINEPAK_DECODER),yes) | |||
| OBJS+= cinepak.o | |||
| endif | |||
| @@ -511,6 +511,9 @@ void avcodec_register_all(void) | |||
| #ifdef CONFIG_TTA_DECODER | |||
| register_avcodec(&tta_decoder); | |||
| #endif //CONFIG_TTA_DECODER | |||
| #ifdef CONFIG_AVS_DECODER | |||
| register_avcodec(&avs_decoder); | |||
| #endif //CONFIG_AVS_DECODER | |||
| #ifdef CONFIG_RAWVIDEO_DECODER | |||
| register_avcodec(&rawvideo_decoder); | |||
| #endif //CONFIG_RAWVIDEO_DECODER | |||
| @@ -21,8 +21,8 @@ extern "C" { | |||
| #define AV_STRINGIFY(s) AV_TOSTRING(s) | |||
| #define AV_TOSTRING(s) #s | |||
| #define LIBAVCODEC_VERSION_INT ((51<<16)+(6<<8)+0) | |||
| #define LIBAVCODEC_VERSION 51.6.0 | |||
| #define LIBAVCODEC_VERSION_INT ((51<<16)+(7<<8)+0) | |||
| #define LIBAVCODEC_VERSION 51.7.0 | |||
| #define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT | |||
| #define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) | |||
| @@ -117,6 +117,7 @@ enum CodecID { | |||
| CODEC_ID_CSCD, | |||
| CODEC_ID_MMVIDEO, | |||
| CODEC_ID_ZMBV, | |||
| CODEC_ID_AVS, | |||
| /* various pcm "codecs" */ | |||
| CODEC_ID_PCM_S16LE= 0x10000, | |||
| @@ -2233,6 +2234,7 @@ extern AVCodec libgsm_decoder; | |||
| extern AVCodec bmp_decoder; | |||
| extern AVCodec mmvideo_decoder; | |||
| extern AVCodec zmbv_decoder; | |||
| extern AVCodec avs_decoder; | |||
| /* pcm codecs */ | |||
| #define PCM_CODEC(id, name) \ | |||
| @@ -0,0 +1,158 @@ | |||
| /* | |||
| * AVS video decoder. | |||
| * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.org> | |||
| * | |||
| * This library is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation; either | |||
| * version 2 of the License, or (at your option) any later version. | |||
| * | |||
| * This library is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| * Lesser General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU Lesser General Public | |||
| * License along with this library; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #include "avcodec.h" | |||
| #include "bitstream.h" | |||
| typedef struct { | |||
| AVFrame picture; | |||
| } avs_context_t; | |||
| typedef enum { | |||
| AVS_VIDEO = 0x01, | |||
| AVS_AUDIO = 0x02, | |||
| AVS_PALETTE = 0x03, | |||
| AVS_GAME_DATA = 0x04, | |||
| } avs_block_type_t; | |||
| typedef enum { | |||
| AVS_I_FRAME = 0x00, | |||
| AVS_P_FRAME_3X3 = 0x01, | |||
| AVS_P_FRAME_2X2 = 0x02, | |||
| AVS_P_FRAME_2X3 = 0x03, | |||
| } avs_video_sub_type_t; | |||
| static int | |||
| avs_decode_frame(AVCodecContext * avctx, | |||
| void *data, int *data_size, uint8_t * buf, int buf_size) | |||
| { | |||
| avs_context_t *const avs = avctx->priv_data; | |||
| AVFrame *picture = data; | |||
| AVFrame *const p = (AVFrame *) & avs->picture; | |||
| uint8_t *table, *vect, *out; | |||
| int i, j, x, y, stride, vect_w = 3, vect_h = 3; | |||
| int sub_type; | |||
| avs_block_type_t type; | |||
| GetBitContext change_map; | |||
| if (avctx->reget_buffer(avctx, p)) { | |||
| av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); | |||
| return -1; | |||
| } | |||
| p->reference = 1; | |||
| p->pict_type = FF_P_TYPE; | |||
| p->key_frame = 0; | |||
| out = avs->picture.data[0]; | |||
| stride = avs->picture.linesize[0]; | |||
| sub_type = buf[0]; | |||
| type = buf[1]; | |||
| buf += 4; | |||
| if (type == AVS_PALETTE) { | |||
| int first, last; | |||
| uint32_t *pal = (uint32_t *) avs->picture.data[1]; | |||
| first = LE_16(buf); | |||
| last = first + LE_16(buf + 2); | |||
| buf += 4; | |||
| for (i=first; i<last; i++, buf+=3) | |||
| pal[i] = (buf[0] << 18) | (buf[1] << 10) | (buf[2] << 2); | |||
| sub_type = buf[0]; | |||
| type = buf[1]; | |||
| buf += 4; | |||
| } | |||
| if (type != AVS_VIDEO) | |||
| return -1; | |||
| switch (sub_type) { | |||
| case AVS_I_FRAME: | |||
| p->pict_type = FF_I_TYPE; | |||
| p->key_frame = 1; | |||
| case AVS_P_FRAME_3X3: | |||
| vect_w = 3; | |||
| vect_h = 3; | |||
| break; | |||
| case AVS_P_FRAME_2X2: | |||
| vect_w = 2; | |||
| vect_h = 2; | |||
| break; | |||
| case AVS_P_FRAME_2X3: | |||
| vect_w = 2; | |||
| vect_h = 3; | |||
| break; | |||
| default: | |||
| return -1; | |||
| } | |||
| table = buf + (256 * vect_w * vect_h); | |||
| if (sub_type != AVS_I_FRAME) { | |||
| int map_size = ((318 / vect_w + 7) / 8) * (198 / vect_h); | |||
| init_get_bits(&change_map, table, map_size); | |||
| table += map_size; | |||
| } | |||
| for (y=0; y<198; y+=vect_h) { | |||
| for (x=0; x<318; x+=vect_w) { | |||
| if (sub_type == AVS_I_FRAME || get_bits1(&change_map)) { | |||
| vect = &buf[*table++ * (vect_w * vect_h)]; | |||
| for (j=0; j<vect_w; j++) { | |||
| out[(y + 0) * stride + x + j] = vect[(0 * vect_w) + j]; | |||
| out[(y + 1) * stride + x + j] = vect[(1 * vect_w) + j]; | |||
| if (vect_h == 3) | |||
| out[(y + 2) * stride + x + j] = | |||
| vect[(2 * vect_w) + j]; | |||
| } | |||
| } | |||
| } | |||
| if (sub_type != AVS_I_FRAME) | |||
| align_get_bits(&change_map); | |||
| } | |||
| *picture = *(AVFrame *) & avs->picture; | |||
| *data_size = sizeof(AVPicture); | |||
| return buf_size; | |||
| } | |||
| static int avs_decode_init(AVCodecContext * avctx) | |||
| { | |||
| avctx->pix_fmt = PIX_FMT_PAL8; | |||
| return 0; | |||
| } | |||
| AVCodec avs_decoder = { | |||
| "avs", | |||
| CODEC_TYPE_VIDEO, | |||
| CODEC_ID_AVS, | |||
| sizeof(avs_context_t), | |||
| avs_decode_init, | |||
| NULL, | |||
| NULL, | |||
| avs_decode_frame, | |||
| CODEC_CAP_DR1, | |||
| }; | |||
| @@ -18,7 +18,7 @@ OBJS+=mpeg.o mpegts.o mpegtsenc.o ffm.o crc.o img.o img2.o raw.o rm.o \ | |||
| nut.o wc3movie.o mp3.o westwood.o segafilm.o idcin.o flic.o \ | |||
| sierravmd.o matroska.o sol.o electronicarts.o nsvdec.o asf.o \ | |||
| ogg2.o oggparsevorbis.o oggparsetheora.o oggparseflac.o daud.o aiff.o \ | |||
| voc.o tta.o mm.o | |||
| voc.o tta.o mm.o avs.o | |||
| # muxers | |||
| ifeq ($(CONFIG_MUXERS),yes) | |||
| @@ -118,6 +118,7 @@ void av_register_all(void) | |||
| daud_init(); | |||
| voc_init(); | |||
| tta_init(); | |||
| avs_init(); | |||
| #ifdef CONFIG_MUXERS | |||
| /* image formats */ | |||
| @@ -5,8 +5,8 @@ | |||
| extern "C" { | |||
| #endif | |||
| #define LIBAVFORMAT_VERSION_INT ((50<<16)+(2<<8)+1) | |||
| #define LIBAVFORMAT_VERSION 50.2.1 | |||
| #define LIBAVFORMAT_VERSION_INT ((50<<16)+(3<<8)+0) | |||
| #define LIBAVFORMAT_VERSION 50.3.0 | |||
| #define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT | |||
| #define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) | |||
| @@ -564,6 +564,9 @@ int ff_adts_init(void); | |||
| /* mm.c */ | |||
| int mm_init(void); | |||
| /* avs.c */ | |||
| int avs_init(void); | |||
| #include "rtp.h" | |||
| #include "rtsp.h" | |||
| @@ -0,0 +1,238 @@ | |||
| /* | |||
| * AVS demuxer. | |||
| * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.org> | |||
| * | |||
| * This library is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation; either | |||
| * version 2 of the License, or (at your option) any later version. | |||
| * | |||
| * This library is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| * Lesser General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU Lesser General Public | |||
| * License along with this library; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #include "avformat.h" | |||
| #include "voc.h" | |||
| typedef struct avs_format { | |||
| voc_dec_context_t voc; | |||
| AVStream *st_video; | |||
| AVStream *st_audio; | |||
| int width; | |||
| int height; | |||
| int bits_per_sample; | |||
| int fps; | |||
| int nb_frames; | |||
| int remaining_frame_size; | |||
| int remaining_audio_size; | |||
| } avs_format_t; | |||
| typedef enum avs_block_type { | |||
| AVS_VIDEO = 0x01, | |||
| AVS_AUDIO = 0x02, | |||
| AVS_PALETTE = 0x03, | |||
| AVS_GAME_DATA = 0x04, | |||
| } avs_block_type_t; | |||
| #ifdef CONFIG_DEMUXERS | |||
| static int avs_probe(AVProbeData * p) | |||
| { | |||
| const uint8_t *d; | |||
| if (p->buf_size < 2) | |||
| return 0; | |||
| d = p->buf; | |||
| if (d[0] == 'w' && d[1] == 'W' && d[2] == 0x10 && d[3] == 0) | |||
| return 50; | |||
| return 0; | |||
| } | |||
| static int avs_read_header(AVFormatContext * s, AVFormatParameters * ap) | |||
| { | |||
| avs_format_t *avs = s->priv_data; | |||
| s->ctx_flags |= AVFMTCTX_NOHEADER; | |||
| url_fskip(&s->pb, 4); | |||
| avs->width = get_le16(&s->pb); | |||
| avs->height = get_le16(&s->pb); | |||
| avs->bits_per_sample = get_le16(&s->pb); | |||
| avs->fps = get_le16(&s->pb); | |||
| avs->nb_frames = get_le32(&s->pb); | |||
| avs->remaining_frame_size = 0; | |||
| avs->remaining_audio_size = 0; | |||
| avs->st_video = avs->st_audio = NULL; | |||
| if (avs->width != 318 || avs->height != 198) | |||
| av_log(s, AV_LOG_ERROR, "This avs pretend to be %dx%d " | |||
| "when the avs format is supposed to be 318x198 only.\n", | |||
| avs->width, avs->height); | |||
| return 0; | |||
| } | |||
| static int | |||
| avs_read_video_packet(AVFormatContext * s, AVPacket * pkt, | |||
| avs_block_type_t type, int sub_type, int size, | |||
| uint8_t * palette, int palette_size) | |||
| { | |||
| avs_format_t *avs = s->priv_data; | |||
| int ret; | |||
| ret = av_new_packet(pkt, size + palette_size); | |||
| if (ret < 0) | |||
| return ret; | |||
| if (palette_size) { | |||
| pkt->data[0] = 0x00; | |||
| pkt->data[1] = 0x03; | |||
| pkt->data[2] = palette_size & 0xFF; | |||
| pkt->data[3] = (palette_size >> 8) & 0xFF; | |||
| memcpy(pkt->data + 4, palette, palette_size - 4); | |||
| } | |||
| pkt->data[palette_size + 0] = sub_type; | |||
| pkt->data[palette_size + 1] = type; | |||
| pkt->data[palette_size + 2] = size & 0xFF; | |||
| pkt->data[palette_size + 3] = (size >> 8) & 0xFF; | |||
| ret = get_buffer(&s->pb, pkt->data + palette_size + 4, size - 4) + 4; | |||
| if (ret < size) { | |||
| av_free_packet(pkt); | |||
| return AVERROR_IO; | |||
| } | |||
| pkt->size = ret + palette_size; | |||
| pkt->stream_index = avs->st_video->index; | |||
| if (sub_type == 0) | |||
| pkt->flags |= PKT_FLAG_KEY; | |||
| return 0; | |||
| } | |||
| static int avs_read_audio_packet(AVFormatContext * s, AVPacket * pkt) | |||
| { | |||
| avs_format_t *avs = s->priv_data; | |||
| int ret, size; | |||
| size = url_ftell(&s->pb); | |||
| ret = voc_get_packet(s, pkt, avs->st_audio, avs->remaining_audio_size); | |||
| size = url_ftell(&s->pb) - size; | |||
| avs->remaining_audio_size -= size; | |||
| if (ret == AVERROR_IO) | |||
| return 0; /* this indicate EOS */ | |||
| if (ret < 0) | |||
| return ret; | |||
| pkt->stream_index = avs->st_audio->index; | |||
| pkt->flags |= PKT_FLAG_KEY; | |||
| return size; | |||
| } | |||
| static int avs_read_packet(AVFormatContext * s, AVPacket * pkt) | |||
| { | |||
| avs_format_t *avs = s->priv_data; | |||
| int sub_type = 0, size = 0; | |||
| avs_block_type_t type = 0; | |||
| int palette_size = 0; | |||
| uint8_t palette[4 + 3 * 256]; | |||
| int ret; | |||
| if (avs->remaining_audio_size > 0) | |||
| if (avs_read_audio_packet(s, pkt) > 0) | |||
| return 0; | |||
| while (1) { | |||
| if (avs->remaining_frame_size <= 0) { | |||
| if (!get_le16(&s->pb)) /* found EOF */ | |||
| return AVERROR_IO; | |||
| avs->remaining_frame_size = get_le16(&s->pb) - 4; | |||
| } | |||
| while (avs->remaining_frame_size > 0) { | |||
| sub_type = get_byte(&s->pb); | |||
| type = get_byte(&s->pb); | |||
| size = get_le16(&s->pb); | |||
| avs->remaining_frame_size -= size; | |||
| switch (type) { | |||
| case AVS_PALETTE: | |||
| ret = get_buffer(&s->pb, palette, size - 4); | |||
| if (ret < size - 4) | |||
| return AVERROR_IO; | |||
| palette_size = size; | |||
| break; | |||
| case AVS_VIDEO: | |||
| if (!avs->st_video) { | |||
| avs->st_video = av_new_stream(s, AVS_VIDEO); | |||
| if (avs->st_video == NULL) | |||
| return AVERROR_NOMEM; | |||
| avs->st_video->codec->codec_type = CODEC_TYPE_VIDEO; | |||
| avs->st_video->codec->codec_id = CODEC_ID_AVS; | |||
| avs->st_video->codec->width = avs->width; | |||
| avs->st_video->codec->height = avs->height; | |||
| avs->st_video->codec->bits_per_sample=avs->bits_per_sample; | |||
| avs->st_video->nb_frames = avs->nb_frames; | |||
| avs->st_video->codec->time_base = (AVRational) { | |||
| 1, avs->fps}; | |||
| } | |||
| return avs_read_video_packet(s, pkt, type, sub_type, size, | |||
| palette, palette_size); | |||
| case AVS_AUDIO: | |||
| if (!avs->st_audio) { | |||
| avs->st_audio = av_new_stream(s, AVS_AUDIO); | |||
| if (avs->st_audio == NULL) | |||
| return AVERROR_NOMEM; | |||
| avs->st_audio->codec->codec_type = CODEC_TYPE_AUDIO; | |||
| } | |||
| avs->remaining_audio_size = size - 4; | |||
| size = avs_read_audio_packet(s, pkt); | |||
| if (size != 0) | |||
| return size; | |||
| break; | |||
| default: | |||
| url_fskip(&s->pb, size - 4); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| static int avs_read_close(AVFormatContext * s) | |||
| { | |||
| return 0; | |||
| } | |||
| static AVInputFormat avs_iformat = { | |||
| "avs", | |||
| "avs format", | |||
| sizeof(avs_format_t), | |||
| avs_probe, | |||
| avs_read_header, | |||
| avs_read_packet, | |||
| avs_read_close, | |||
| }; | |||
| #endif /* CONFIG_DEMUXERS */ | |||
| int avs_init(void) | |||
| { | |||
| #ifdef CONFIG_DEMUXERS | |||
| av_register_input_format(&avs_iformat); | |||
| #endif /* CONFIG_DEMUXERS */ | |||
| return 0; | |||
| } | |||