Mercurial > libavcodec.hg
changeset 1439:a4d00b1f0271 libavcodec
initial commit for Id RoQ and Interplay MVE multimedia subsystems
author | tmmm |
---|---|
date | Tue, 02 Sep 2003 04:32:02 +0000 |
parents | 6339c2b322e6 |
children | 902750d5393b |
files | Makefile allcodecs.c avcodec.h dpcm.c interplayvideo.c roqvideo.c |
diffstat | 6 files changed, 767 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Mon Sep 01 17:42:07 2003 +0000 +++ b/Makefile Tue Sep 02 04:32:02 2003 +0000 @@ -17,7 +17,8 @@ mpeg12.o mpegaudiodec.o pcm.o simple_idct.o \ ratecontrol.o adpcm.o eval.o dv.o error_resilience.o \ fft.o mdct.o mace.o huffyuv.o cyuv.o opts.o raw.o h264.o golomb.o \ - vp3.o asv1.o 4xm.o cabac.o ffv1.o ra144.o ra288.o vcr1.o cljr.o + vp3.o asv1.o 4xm.o cabac.o ffv1.o ra144.o ra288.o vcr1.o cljr.o \ + roqvideo.o dpcm.o interplayvideo.o ifeq ($(AMR_NB),yes) ifeq ($(AMR_NB_FIXED),yes)
--- a/allcodecs.c Mon Sep 01 17:42:07 2003 +0000 +++ b/allcodecs.c Tue Sep 02 04:32:02 2003 +0000 @@ -121,11 +121,15 @@ register_avcodec(&cljr_decoder); register_avcodec(&fourxm_decoder); register_avcodec(&mdec_decoder); + register_avcodec(&roq_decoder); + register_avcodec(&interplay_video_decoder); #ifdef CONFIG_AC3 register_avcodec(&ac3_decoder); #endif register_avcodec(&ra_144_decoder); register_avcodec(&ra_288_decoder); + register_avcodec(&roq_dpcm_decoder); + register_avcodec(&interplay_dpcm_decoder); #endif /* CONFIG_DECODERS */ #ifdef AMR_NB
--- a/avcodec.h Mon Sep 01 17:42:07 2003 +0000 +++ b/avcodec.h Tue Sep 02 04:32:02 2003 +0000 @@ -66,6 +66,8 @@ CODEC_ID_VCR1, CODEC_ID_CLJR, CODEC_ID_MDEC, + CODEC_ID_ROQ, + CODEC_ID_INTERPLAY_VIDEO, /* various pcm "codecs" */ CODEC_ID_PCM_S16LE, @@ -88,6 +90,10 @@ /* RealAudio codecs*/ CODEC_ID_RA_144, CODEC_ID_RA_288, + + /* various DPCM codecs */ + CODEC_ID_ROQ_DPCM, + CODEC_ID_INTERPLAY_DPCM, }; enum CodecType { @@ -1347,8 +1353,12 @@ extern AVCodec ffv1_decoder; extern AVCodec fourxm_decoder; extern AVCodec mdec_decoder; +extern AVCodec roq_decoder; +extern AVCodec interplay_video_decoder; extern AVCodec ra_144_decoder; extern AVCodec ra_288_decoder; +extern AVCodec roq_dpcm_decoder; +extern AVCodec interplay_dpcm_decoder; /* pcm codecs */ #define PCM_CODEC(id, name) \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dpcm.c Tue Sep 02 04:32:02 2003 +0000 @@ -0,0 +1,200 @@ +/* + * Assorted DPCM codecs + * Copyright (c) 2003 The ffmpeg Project. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** + * @file: dpcm.c + * Assorted DPCM (differential pulse code modulation) audio codecs + * by Mike Melanson (melanson@pcisys.net) + * for more information on the specific data formats, visit: + * http://www.pcisys.net/~melanson/codecs/simpleaudio.html + */ + +#include "avcodec.h" + +typedef struct DPCMContext { + int channels; + short roq_square_array[256]; + int last_delta[2]; +} DPCMContext; + +#define SATURATE_S16(x) if (x < -32768) x = -32768; \ + else if (x > 32767) x = 32767; +#define SE_16BIT(x) if (x & 0x8000) x -= 0x10000; +#define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0]) +#define LE_32(x) ((((uint8_t*)(x))[3] << 24) | \ + (((uint8_t*)(x))[2] << 16) | \ + (((uint8_t*)(x))[1] << 8) | \ + ((uint8_t*)(x))[0]) + +static int interplay_delta_table[] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 47, 51, 56, 61, + 66, 72, 79, 86, 94, 102, 112, 122, + 133, 145, 158, 173, 189, 206, 225, 245, + 267, 292, 318, 348, 379, 414, 452, 493, + 538, 587, 640, 699, 763, 832, 908, 991, + 1081, 1180, 1288, 1405, 1534, 1673, 1826, 1993, + 2175, 2373, 2590, 2826, 3084, 3365, 3672, 4008, + 4373, 4772, 5208, 5683, 6202, 6767, 7385, 8059, + 8794, 9597, 10472, 11428, 12471, 13609, 14851, 16206, + 17685, 19298, 21060, 22981, 25078, 27367, 29864, 32589, + -29973, -26728, -23186, -19322, -15105, -10503, -5481, -1, + 1, 1, 5481, 10503, 15105, 19322, 23186, 26728, + 29973, -32589, -29864, -27367, -25078, -22981, -21060, -19298, + -17685, -16206, -14851, -13609, -12471, -11428, -10472, -9597, + -8794, -8059, -7385, -6767, -6202, -5683, -5208, -4772, + -4373, -4008, -3672, -3365, -3084, -2826, -2590, -2373, + -2175, -1993, -1826, -1673, -1534, -1405, -1288, -1180, + -1081, -991, -908, -832, -763, -699, -640, -587, + -538, -493, -452, -414, -379, -348, -318, -292, + -267, -245, -225, -206, -189, -173, -158, -145, + -133, -122, -112, -102, -94, -86, -79, -72, + -66, -61, -56, -51, -47, -43, -42, -41, + -40, -39, -38, -37, -36, -35, -34, -33, + -32, -31, -30, -29, -28, -27, -26, -25, + -24, -23, -22, -21, -20, -19, -18, -17, + -16, -15, -14, -13, -12, -11, -10, -9, + -8, -7, -6, -5, -4, -3, -2, -1 + +}; + +static int dpcm_decode_init(AVCodecContext *avctx) +{ + DPCMContext *s = avctx->priv_data; + int i; + short square; + + s->channels = avctx->channels; + + switch(avctx->codec->id) { + + case CODEC_ID_ROQ_DPCM: + /* initialize square table */ + for (i = 0; i < 128; i++) { + square = i * i; + s->roq_square_array[i] = square; + s->roq_square_array[i + 128] = -square; + } + break; + + default: + break; + } + + return 0; +} + +static int dpcm_decode_frame(AVCodecContext *avctx, + void *data, int *data_size, + uint8_t *buf, int buf_size) +{ + DPCMContext *s = avctx->priv_data; + int in, out = 0; + int i; + int predictor[2]; + int channel_number = 0; + short *output_samples = data; + int sequence_number; + + switch(avctx->codec->id) { + + case CODEC_ID_ROQ_DPCM: + if (s->channels == 1) + predictor[0] = LE_16(&buf[6]); + else { + predictor[0] = buf[7] << 8; + predictor[1] = buf[6] << 8; + } + SE_16BIT(predictor[0]); + SE_16BIT(predictor[1]); + + /* decode the samples */ + for (in = 8, out = 0; in < buf_size; in++, out++) { + predictor[channel_number] += s->roq_square_array[buf[in]]; + SATURATE_S16(predictor[channel_number]); + output_samples[out] = predictor[channel_number]; + + /* toggle channel */ + channel_number ^= s->channels - 1; + } + break; + + case CODEC_ID_INTERPLAY_DPCM: + in = 0; + sequence_number = LE_16(&buf[in]); + in += 6; /* skip over the stream mask and stream length */ + if (sequence_number == 1) { + predictor[0] = LE_16(&buf[in]); + in += 2; + SE_16BIT(predictor[0]) + if (s->channels == 2) { + predictor[1] = LE_16(&buf[in]); + SE_16BIT(predictor[1]) + in += 2; + } + } else { + for (i = 0; i < s->channels; i++) + predictor[i] = s->last_delta[i]; + } + + while (in < buf_size) { + predictor[channel_number] += interplay_delta_table[buf[in++]]; + SATURATE_S16(predictor[channel_number]); + output_samples[out++] = predictor[channel_number]; + + /* toggle channel */ + channel_number ^= s->channels - 1; + } + + /* save predictors for next round */ + for (i = 0; i < s->channels; i++) + s->last_delta[i] = predictor[i]; + + break; + } + + *data_size = out * sizeof(short); + return buf_size; +} + +AVCodec roq_dpcm_decoder = { + "roq_dpcm", + CODEC_TYPE_AUDIO, + CODEC_ID_ROQ_DPCM, + sizeof(DPCMContext), + dpcm_decode_init, + NULL, + NULL, + dpcm_decode_frame, +}; + +AVCodec interplay_dpcm_decoder = { + "interplay_dpcm", + CODEC_TYPE_AUDIO, + CODEC_ID_INTERPLAY_DPCM, + sizeof(DPCMContext), + dpcm_decode_init, + NULL, + NULL, + dpcm_decode_frame, +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/interplayvideo.c Tue Sep 02 04:32:02 2003 +0000 @@ -0,0 +1,145 @@ +/* + * Interplay MVE Video Decoder + * Copyright (C) 2003 the ffmpeg project + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/** + * @file roqvideo.c + * Interplay MVE Video Decoder by Mike Melanson + * For more information about the Interplay MVE format, visit: + * http://www.pcisys.net/~melanson/codecs/ + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "common.h" +#include "avcodec.h" +#include "dsputil.h" + +typedef struct IpvideoContext { + + AVCodecContext *avctx; + DSPContext dsp; + AVFrame last_frame; + AVFrame current_frame; + int first_frame; + int receiving_decoding_map; + unsigned char *decoding_map; + int decoding_map_size; + + unsigned char *buf; + int size; + +} IpvideoContext; + +static int ipvideo_decode_init(AVCodecContext *avctx) +{ + IpvideoContext *s = avctx->priv_data; + + s->avctx = avctx; + avctx->pix_fmt = PIX_FMT_YUV444P; + avctx->has_b_frames = 0; + dsputil_init(&s->dsp, avctx); + + s->first_frame = 1; + s->receiving_decoding_map = 1; /* decoding map will be received first */ + + /* decoding map contains 4 bits of information per 8x8 block */ + s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2); + s->decoding_map = av_malloc(s->decoding_map_size); + + return 0; +} + +static int ipvideo_decode_frame(AVCodecContext *avctx, + void *data, int *data_size, + uint8_t *buf, int buf_size) +{ + IpvideoContext *s = avctx->priv_data; + + if (s->receiving_decoding_map) { + /* receiving the decoding map on this iteration */ + s->receiving_decoding_map = 0; + + if (buf_size != s->decoding_map_size) + printf (" Interplay video: buf_size != decoding_map_size (%d != %d)\n", + buf_size, s->decoding_map_size); + else + memcpy(s->decoding_map, buf, buf_size); + + *data_size = 0; + *(AVFrame*)data = s->last_frame; + } else { + /* receiving the compressed video data on this iteration */ + s->receiving_decoding_map = 1; + s->buf = buf; + s->size = buf_size; + + if (avctx->get_buffer(avctx, &s->current_frame)) { + printf (" Interplay Video: get_buffer() failed\n"); + return -1; + } + +// ipvideo_decode_frame(s); +memset(s->current_frame.data[0], 0x80, s->current_frame.linesize[0] * avctx->height); +memset(s->current_frame.data[1], 0x80, s->current_frame.linesize[1] * avctx->height / 4); +memset(s->current_frame.data[2], 0x80, s->current_frame.linesize[2] * avctx->height / 4); + + /* release the last frame if it is allocated */ + if (s->first_frame) + s->first_frame = 0; + else + avctx->release_buffer(avctx, &s->last_frame); + + /* shuffle frames */ + s->last_frame = s->current_frame; + + *data_size = sizeof(AVFrame); + *(AVFrame*)data = s->current_frame; + } + + /* always report that the buffer was completely consumed */ + return buf_size; +} + +static int ipvideo_decode_end(AVCodecContext *avctx) +{ + IpvideoContext *s = avctx->priv_data; + + /* release the last frame */ + avctx->release_buffer(avctx, &s->last_frame); + + av_free(s->decoding_map); + + return 0; +} + +AVCodec interplay_video_decoder = { + "interplayvideo", + CODEC_TYPE_VIDEO, + CODEC_ID_INTERPLAY_VIDEO, + sizeof(IpvideoContext), + ipvideo_decode_init, + NULL, + ipvideo_decode_end, + ipvideo_decode_frame, + CODEC_CAP_DR1, +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/roqvideo.c Tue Sep 02 04:32:02 2003 +0000 @@ -0,0 +1,406 @@ +/* + * Copyright (C) 2003 the ffmpeg project + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/** + * @file roqvideo.c + * Id RoQ Video Decoder by Dr. Tim Ferguson + * For more information about the Id RoQ format, visit: + * http://www.csse.monash.edu.au/~timf/ + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "common.h" +#include "avcodec.h" +#include "dsputil.h" + +typedef struct { + unsigned char y0, y1, y2, y3, u, v; +} roq_cell; + +typedef struct { + int idx[4]; +} roq_qcell; + + +typedef struct RoqContext { + + AVCodecContext *avctx; + DSPContext dsp; + AVFrame last_frame; + AVFrame current_frame; + int first_frame; + int y_stride; + int c_stride; + + roq_cell cells[256]; + roq_qcell qcells[256]; + + unsigned char *buf; + int size; + +} RoqContext; + +#define RoQ_INFO 0x1001 +#define RoQ_QUAD_CODEBOOK 0x1002 +#define RoQ_QUAD_VQ 0x1011 +#define RoQ_SOUND_MONO 0x1020 +#define RoQ_SOUND_STEREO 0x1021 + +#define RoQ_ID_MOT 0x00 +#define RoQ_ID_FCC 0x01 +#define RoQ_ID_SLD 0x02 +#define RoQ_ID_CCC 0x03 + +#define get_byte(in_buffer) *(in_buffer++) +#define get_word(in_buffer) ((unsigned short)(in_buffer += 2, \ + (in_buffer[-1] << 8 | in_buffer[-2]))) +#define get_long(in_buffer) ((unsigned long)(in_buffer += 4, \ + (in_buffer[-1] << 24 | in_buffer[-2] << 16 | in_buffer[-3] << 8 | in_buffer[-4]))) + + +static void apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell) +{ + unsigned char *yptr; + + yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x; + *yptr++ = cell->y0; + *yptr++ = cell->y1; + yptr += (ri->y_stride - 2); + *yptr++ = cell->y2; + *yptr++ = cell->y3; + ri->current_frame.data[1][(y/2) * (ri->c_stride) + x/2] = cell->u; + ri->current_frame.data[2][(y/2) * (ri->c_stride) + x/2] = cell->v; +} + +static void apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell) +{ + unsigned long row_inc, c_row_inc; + register unsigned char y0, y1, u, v; + unsigned char *yptr, *uptr, *vptr; + + yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x; + uptr = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2; + vptr = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2; + + row_inc = ri->y_stride - 4; + c_row_inc = (ri->c_stride) - 2; + *yptr++ = y0 = cell->y0; *uptr++ = u = cell->u; *vptr++ = v = cell->v; + *yptr++ = y0; + *yptr++ = y1 = cell->y1; *uptr++ = u; *vptr++ = v; + *yptr++ = y1; + + yptr += row_inc; + + *yptr++ = y0; + *yptr++ = y0; + *yptr++ = y1; + *yptr++ = y1; + + yptr += row_inc; uptr += c_row_inc; vptr += c_row_inc; + + *yptr++ = y0 = cell->y2; *uptr++ = u; *vptr++ = v; + *yptr++ = y0; + *yptr++ = y1 = cell->y3; *uptr++ = u; *vptr++ = v; + *yptr++ = y1; + + yptr += row_inc; + + *yptr++ = y0; + *yptr++ = y0; + *yptr++ = y1; + *yptr++ = y1; +} + +static void apply_motion_4x4(RoqContext *ri, int x, int y, unsigned char mv, + char mean_x, char mean_y) +{ + int i, mx, my; + unsigned char *pa, *pb; + + mx = x + 8 - (mv >> 4) - mean_x; + my = y + 8 - (mv & 0xf) - mean_y; + + pa = ri->current_frame.data[0] + (y * ri->y_stride) + x; + pb = ri->last_frame.data[0] + (my * ri->y_stride) + mx; + for(i = 0; i < 4; i++) { + pa[0] = pb[0]; + pa[1] = pb[1]; + pa[2] = pb[2]; + pa[3] = pb[3]; + pa += ri->y_stride; + pb += ri->y_stride; + } + + pa = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2; + pb = ri->last_frame.data[1] + (my/2) * (ri->c_stride) + (mx + 1)/2; + for(i = 0; i < 2; i++) { + pa[0] = pb[0]; + pa[1] = pb[1]; + pa += ri->c_stride; + pb += ri->c_stride; + } + + pa = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2; + pb = ri->last_frame.data[2] + (my/2) * (ri->c_stride) + (mx + 1)/2; + for(i = 0; i < 2; i++) { + pa[0] = pb[0]; + pa[1] = pb[1]; + pa += ri->c_stride; + pb += ri->c_stride; + } +} + +static void apply_motion_8x8(RoqContext *ri, int x, int y, + unsigned char mv, char mean_x, char mean_y) +{ + int mx, my, i; + unsigned char *pa, *pb; + + mx = x + 8 - (mv >> 4) - mean_x; + my = y + 8 - (mv & 0xf) - mean_y; + + pa = ri->current_frame.data[0] + (y * ri->y_stride) + x; + pb = ri->last_frame.data[0] + (my * ri->y_stride) + mx; + for(i = 0; i < 8; i++) { + pa[0] = pb[0]; + pa[1] = pb[1]; + pa[2] = pb[2]; + pa[3] = pb[3]; + pa[4] = pb[4]; + pa[5] = pb[5]; + pa[6] = pb[6]; + pa[7] = pb[7]; + pa += ri->y_stride; + pb += ri->y_stride; + } + + pa = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2; + pb = ri->last_frame.data[1] + (my/2) * (ri->c_stride) + (mx + 1)/2; + for(i = 0; i < 4; i++) { + pa[0] = pb[0]; + pa[1] = pb[1]; + pa[2] = pb[2]; + pa[3] = pb[3]; + pa += ri->c_stride; + pb += ri->c_stride; + } + + pa = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2; + pb = ri->last_frame.data[2] + (my/2) * (ri->c_stride) + (mx + 1)/2; + for(i = 0; i < 4; i++) { + pa[0] = pb[0]; + pa[1] = pb[1]; + pa[2] = pb[2]; + pa[3] = pb[3]; + pa += ri->c_stride; + pb += ri->c_stride; + } +} + +static void roqvideo_decode_frame(RoqContext *ri) +{ + unsigned int chunk_id = 0, chunk_arg = 0; + unsigned long chunk_size = 0; + int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1; + int vqid, bpos, xpos, ypos, xp, yp, x, y; + int frame_stats[2][4] = {{0},{0}}; + roq_qcell *qcell; + unsigned char *buf = ri->buf; + unsigned char *buf_end = ri->buf + ri->size; + + while (buf < buf_end) { + chunk_id = get_word(buf); + chunk_size = get_long(buf); + chunk_arg = get_word(buf); + + if(chunk_id == RoQ_QUAD_VQ) + break; + if(chunk_id == RoQ_QUAD_CODEBOOK) { + if((nv1 = chunk_arg >> 8) == 0) + nv1 = 256; + if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size) + nv2 = 256; + for(i = 0; i < nv1; i++) { + ri->cells[i].y0 = get_byte(buf); + ri->cells[i].y1 = get_byte(buf); + ri->cells[i].y2 = get_byte(buf); + ri->cells[i].y3 = get_byte(buf); + ri->cells[i].u = get_byte(buf); + ri->cells[i].v = get_byte(buf); + } + for(i = 0; i < nv2; i++) + for(j = 0; j < 4; j++) + ri->qcells[i].idx[j] = get_byte(buf); + } + } + + bpos = xpos = ypos = 0; + while(bpos < chunk_size) { + for (yp = ypos; yp < ypos + 16; yp += 8) + for (xp = xpos; xp < xpos + 16; xp += 8) { + if (vqflg_pos < 0) { + vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8); + vqflg_pos = 7; + } + vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; + frame_stats[0][vqid]++; + vqflg_pos--; + + switch(vqid) { + case RoQ_ID_MOT: + apply_motion_8x8(ri, xp, yp, 0, 8, 8); + break; + case RoQ_ID_FCC: + apply_motion_8x8(ri, xp, yp, buf[bpos++], chunk_arg >> 8, + chunk_arg & 0xff); + break; + case RoQ_ID_SLD: + qcell = ri->qcells + buf[bpos++]; + apply_vector_4x4(ri, xp, yp, ri->cells + qcell->idx[0]); + apply_vector_4x4(ri, xp+4, yp, ri->cells + qcell->idx[1]); + apply_vector_4x4(ri, xp, yp+4, ri->cells + qcell->idx[2]); + apply_vector_4x4(ri, xp+4, yp+4, ri->cells + qcell->idx[3]); + break; + case RoQ_ID_CCC: + for (k = 0; k < 4; k++) { + x = xp; y = yp; + if(k & 0x01) x += 4; + if(k & 0x02) y += 4; + + if (vqflg_pos < 0) { + vqflg = buf[bpos++]; + vqflg |= (buf[bpos++] << 8); + vqflg_pos = 7; + } + vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; + frame_stats[1][vqid]++; + vqflg_pos--; + switch(vqid) { + case RoQ_ID_MOT: + apply_motion_4x4(ri, x, y, 0, 8, 8); + break; + case RoQ_ID_FCC: + apply_motion_4x4(ri, x, y, buf[bpos++], + chunk_arg >> 8, chunk_arg & 0xff); + break; + case RoQ_ID_SLD: + qcell = ri->qcells + buf[bpos++]; + apply_vector_2x2(ri, x, y, ri->cells + qcell->idx[0]); + apply_vector_2x2(ri, x+2, y, ri->cells + qcell->idx[1]); + apply_vector_2x2(ri, x, y+2, ri->cells + qcell->idx[2]); + apply_vector_2x2(ri, x+2, y+2, ri->cells + qcell->idx[3]); + break; + case RoQ_ID_CCC: + apply_vector_2x2(ri, x, y, ri->cells + buf[bpos]); + apply_vector_2x2(ri, x+2, y, ri->cells + buf[bpos+1]); + apply_vector_2x2(ri, x, y+2, ri->cells + buf[bpos+2]); + apply_vector_2x2(ri, x+2, y+2, ri->cells + buf[bpos+3]); + bpos += 4; + break; + } + } + break; + default: + printf("Unknown vq code: %d\n", vqid); + } + } + + xpos += 16; + if (xpos >= ri->avctx->width) { + xpos -= ri->avctx->width; + ypos += 16; + } + if(ypos >= ri->avctx->height) + break; + } +} + + +static int roq_decode_init(AVCodecContext *avctx) +{ + RoqContext *s = avctx->priv_data; + + s->avctx = avctx; + s->first_frame = 1; + avctx->pix_fmt = PIX_FMT_YUV420P; + avctx->has_b_frames = 0; + dsputil_init(&s->dsp, avctx); + + return 0; +} + +static int roq_decode_frame(AVCodecContext *avctx, + void *data, int *data_size, + uint8_t *buf, int buf_size) +{ + RoqContext *s = avctx->priv_data; + + *data_size = 0; + + if (avctx->get_buffer(avctx, &s->current_frame)) { + printf (" RoQ: get_buffer() failed\n"); + return -1; + } + s->y_stride = s->current_frame.linesize[0]; + s->c_stride = s->current_frame.linesize[1]; + + s->buf = buf; + s->size = buf_size; + roqvideo_decode_frame(s); + + /* release the last frame if it is allocated */ + if (s->first_frame) + s->first_frame = 0; + else + avctx->release_buffer(avctx, &s->last_frame); + + /* shuffle frames */ + s->last_frame = s->current_frame; + + *data_size = sizeof(AVFrame); + *(AVFrame*)data = s->current_frame; + + return buf_size; +} + +static int roq_decode_end(AVCodecContext *avctx) +{ + RoqContext *s = avctx->priv_data; + + /* release the last frame */ + avctx->release_buffer(avctx, &s->last_frame); + + return 0; +} + +AVCodec roq_decoder = { + "roqvideo", + CODEC_TYPE_VIDEO, + CODEC_ID_ROQ, + sizeof(RoqContext), + roq_decode_init, + NULL, + roq_decode_end, + roq_decode_frame, + CODEC_CAP_DR1, +};