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 | - Zip Blocks Motion Video decoder | ||||
| - Improved Theora/VP3 decoder | - Improved Theora/VP3 decoder | ||||
| - True Audio (TTA) decoder | - True Audio (TTA) decoder | ||||
| - AVS demuxer and video decoder | |||||
| version 0.4.9-pre1: | 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 Creative VOC @tab X @tab X @tab Created for the Sound Blaster Pro. | ||||
| @item American Laser Games MM @tab @tab X | @item American Laser Games MM @tab @tab X | ||||
| @tab Multimedia format used in games like Mad Dog McCree | @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 | @end multitable | ||||
| @code{X} means that encoding (resp. decoding) is supported. | @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 CamStudio @tab @tab X @tab fourcc: CSCD | ||||
| @item American Laser Games Video @tab @tab X @tab Used in games like Mad Dog McCree | @item American Laser Games Video @tab @tab X @tab Used in games like Mad Dog McCree | ||||
| @item ZMBV @tab @tab X @tab | @item ZMBV @tab @tab X @tab | ||||
| @item AVS Video @tab @tab X @tab Video encoding used by the Creature Shock game. | |||||
| @end multitable | @end multitable | ||||
| @code{X} means that encoding (resp. decoding) is supported. | @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),) | ifneq ($(CONFIG_ASV1_DECODER)$(CONFIG_ASV1_ENCODER)$(CONFIG_ASV2_DECODER)$(CONFIG_ASV2_ENCODER),) | ||||
| OBJS+= asv1.o | OBJS+= asv1.o | ||||
| endif | endif | ||||
| ifeq ($(CONFIG_AVS_DECODER),yes) | |||||
| OBJS+= avs.o | |||||
| endif | |||||
| ifeq ($(CONFIG_CINEPAK_DECODER),yes) | ifeq ($(CONFIG_CINEPAK_DECODER),yes) | ||||
| OBJS+= cinepak.o | OBJS+= cinepak.o | ||||
| endif | endif | ||||
| @@ -511,6 +511,9 @@ void avcodec_register_all(void) | |||||
| #ifdef CONFIG_TTA_DECODER | #ifdef CONFIG_TTA_DECODER | ||||
| register_avcodec(&tta_decoder); | register_avcodec(&tta_decoder); | ||||
| #endif //CONFIG_TTA_DECODER | #endif //CONFIG_TTA_DECODER | ||||
| #ifdef CONFIG_AVS_DECODER | |||||
| register_avcodec(&avs_decoder); | |||||
| #endif //CONFIG_AVS_DECODER | |||||
| #ifdef CONFIG_RAWVIDEO_DECODER | #ifdef CONFIG_RAWVIDEO_DECODER | ||||
| register_avcodec(&rawvideo_decoder); | register_avcodec(&rawvideo_decoder); | ||||
| #endif //CONFIG_RAWVIDEO_DECODER | #endif //CONFIG_RAWVIDEO_DECODER | ||||
| @@ -21,8 +21,8 @@ extern "C" { | |||||
| #define AV_STRINGIFY(s) AV_TOSTRING(s) | #define AV_STRINGIFY(s) AV_TOSTRING(s) | ||||
| #define AV_TOSTRING(s) #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_BUILD LIBAVCODEC_VERSION_INT | ||||
| #define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) | #define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) | ||||
| @@ -117,6 +117,7 @@ enum CodecID { | |||||
| CODEC_ID_CSCD, | CODEC_ID_CSCD, | ||||
| CODEC_ID_MMVIDEO, | CODEC_ID_MMVIDEO, | ||||
| CODEC_ID_ZMBV, | CODEC_ID_ZMBV, | ||||
| CODEC_ID_AVS, | |||||
| /* various pcm "codecs" */ | /* various pcm "codecs" */ | ||||
| CODEC_ID_PCM_S16LE= 0x10000, | CODEC_ID_PCM_S16LE= 0x10000, | ||||
| @@ -2233,6 +2234,7 @@ extern AVCodec libgsm_decoder; | |||||
| extern AVCodec bmp_decoder; | extern AVCodec bmp_decoder; | ||||
| extern AVCodec mmvideo_decoder; | extern AVCodec mmvideo_decoder; | ||||
| extern AVCodec zmbv_decoder; | extern AVCodec zmbv_decoder; | ||||
| extern AVCodec avs_decoder; | |||||
| /* pcm codecs */ | /* pcm codecs */ | ||||
| #define PCM_CODEC(id, name) \ | #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 \ | 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 \ | sierravmd.o matroska.o sol.o electronicarts.o nsvdec.o asf.o \ | ||||
| ogg2.o oggparsevorbis.o oggparsetheora.o oggparseflac.o daud.o aiff.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 | # muxers | ||||
| ifeq ($(CONFIG_MUXERS),yes) | ifeq ($(CONFIG_MUXERS),yes) | ||||
| @@ -118,6 +118,7 @@ void av_register_all(void) | |||||
| daud_init(); | daud_init(); | ||||
| voc_init(); | voc_init(); | ||||
| tta_init(); | tta_init(); | ||||
| avs_init(); | |||||
| #ifdef CONFIG_MUXERS | #ifdef CONFIG_MUXERS | ||||
| /* image formats */ | /* image formats */ | ||||
| @@ -5,8 +5,8 @@ | |||||
| extern "C" { | extern "C" { | ||||
| #endif | #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_BUILD LIBAVFORMAT_VERSION_INT | ||||
| #define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) | #define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) | ||||
| @@ -564,6 +564,9 @@ int ff_adts_init(void); | |||||
| /* mm.c */ | /* mm.c */ | ||||
| int mm_init(void); | int mm_init(void); | ||||
| /* avs.c */ | |||||
| int avs_init(void); | |||||
| #include "rtp.h" | #include "rtp.h" | ||||
| #include "rtsp.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; | |||||
| } | |||||