From ae0c133a58e5ebc6c0bf25a2a9a1435c0cf3385a Mon Sep 17 00:00:00 2001 From: David McPaul Date: Mon, 15 Sep 2008 14:02:19 +0000 Subject: [PATCH] Update avcodec to 20080825 git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27544 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../media/plugins/avcodec/libavcodec/c93.c | 254 ++++ .../media/plugins/avcodec/libavcodec/cabac.c | 172 ++- .../media/plugins/avcodec/libavcodec/cabac.h | 595 ++++++-- .../media/plugins/avcodec/libavcodec/cavs.c | 716 ++++++++++ .../media/plugins/avcodec/libavcodec/cavs.h | 314 +++++ .../plugins/avcodec/libavcodec/cavs_parser.c | 107 ++ .../plugins/avcodec/libavcodec/cavsdata.h | 505 +++++++ .../plugins/avcodec/libavcodec/cavsdec.c | 703 ++++++++++ .../plugins/avcodec/libavcodec/cavsdsp.c | 546 ++++++++ .../plugins/avcodec/libavcodec/cinepak.c | 203 +-- .../media/plugins/avcodec/libavcodec/cljr.c | 78 +- .../plugins/avcodec/libavcodec/colorspace.h | 111 ++ .../media/plugins/avcodec/libavcodec/config.h | 359 ++++- .../media/plugins/avcodec/libavcodec/cook.c | 1198 +++++++++++++++++ .../plugins/avcodec/libavcodec/cookdata.h | 563 ++++++++ .../media/plugins/avcodec/libavcodec/cscd.c | 263 ++++ .../media/plugins/avcodec/libavcodec/cyuv.c | 68 +- 17 files changed, 6414 insertions(+), 341 deletions(-) create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/c93.c create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/cavs.c create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/cavs.h create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/cavs_parser.c create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/cavsdata.h create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/cavsdec.c create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/cavsdsp.c create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/colorspace.h create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/cook.c create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/cookdata.h create mode 100644 src/add-ons/media/plugins/avcodec/libavcodec/cscd.c diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/c93.c b/src/add-ons/media/plugins/avcodec/libavcodec/c93.c new file mode 100644 index 0000000000..18ed7afcb4 --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/c93.c @@ -0,0 +1,254 @@ +/* + * Interplay C93 video decoder + * Copyright (c) 2007 Anssi Hannula + * + * This file is part of FFmpeg. + * + * FFmpeg 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.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "bytestream.h" + +typedef struct { + AVFrame pictures[2]; + int currentpic; +} C93DecoderContext; + +typedef enum { + C93_8X8_FROM_PREV = 0x02, + C93_4X4_FROM_PREV = 0x06, + C93_4X4_FROM_CURR = 0x07, + C93_8X8_2COLOR = 0x08, + C93_4X4_2COLOR = 0x0A, + C93_4X4_4COLOR_GRP = 0x0B, + C93_4X4_4COLOR = 0x0D, + C93_NOOP = 0x0E, + C93_8X8_INTRA = 0x0F, +} C93BlockType; + +#define WIDTH 320 +#define HEIGHT 192 + +#define C93_HAS_PALETTE 0x01 +#define C93_FIRST_FRAME 0x02 + +static av_cold int decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = PIX_FMT_PAL8; + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + C93DecoderContext * const c93 = avctx->priv_data; + + if (c93->pictures[0].data[0]) + avctx->release_buffer(avctx, &c93->pictures[0]); + if (c93->pictures[1].data[0]) + avctx->release_buffer(avctx, &c93->pictures[1]); + return 0; +} + +static inline int copy_block(AVCodecContext *avctx, uint8_t *to, + uint8_t *from, int offset, int height, int stride) +{ + int i; + int width = height; + int from_x = offset % WIDTH; + int from_y = offset / WIDTH; + int overflow = from_x + width - WIDTH; + + if (!from) { + /* silently ignoring predictive blocks in first frame */ + return 0; + } + + if (from_y + height > HEIGHT) { + av_log(avctx, AV_LOG_ERROR, "invalid offset %d during C93 decoding\n", + offset); + return -1; + } + + if (overflow > 0) { + width -= overflow; + for (i = 0; i < height; i++) { + memcpy(&to[i*stride+width], &from[(from_y+i)*stride], overflow); + } + } + + for (i = 0; i < height; i++) { + memcpy(&to[i*stride], &from[(from_y+i)*stride+from_x], width); + } + + return 0; +} + +static inline void draw_n_color(uint8_t *out, int stride, int width, + int height, int bpp, uint8_t cols[4], uint8_t grps[4], uint32_t col) +{ + int x, y; + for (y = 0; y < height; y++) { + if (grps) + cols[0] = grps[3 * (y >> 1)]; + for (x = 0; x < width; x++) { + if (grps) + cols[1]= grps[(x >> 1) + 1]; + out[x + y*stride] = cols[col & ((1 << bpp) - 1)]; + col >>= bpp; + } + } +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *data_size, const uint8_t * buf, int buf_size) +{ + C93DecoderContext * const c93 = avctx->priv_data; + AVFrame * const newpic = &c93->pictures[c93->currentpic]; + AVFrame * const oldpic = &c93->pictures[c93->currentpic^1]; + AVFrame *picture = data; + uint8_t *out; + int stride, i, x, y, bt = 0; + + c93->currentpic ^= 1; + + newpic->reference = 1; + newpic->buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | + FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE; + if (avctx->reget_buffer(avctx, newpic)) { + av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); + return -1; + } + + stride = newpic->linesize[0]; + + if (buf[0] & C93_FIRST_FRAME) { + newpic->pict_type = FF_I_TYPE; + newpic->key_frame = 1; + } else { + newpic->pict_type = FF_P_TYPE; + newpic->key_frame = 0; + } + + if (*buf++ & C93_HAS_PALETTE) { + uint32_t *palette = (uint32_t *) newpic->data[1]; + const uint8_t *palbuf = buf + buf_size - 768 - 1; + for (i = 0; i < 256; i++) { + palette[i] = bytestream_get_be24(&palbuf); + } + } else { + if (oldpic->data[1]) + memcpy(newpic->data[1], oldpic->data[1], 256 * 4); + } + + for (y = 0; y < HEIGHT; y += 8) { + out = newpic->data[0] + y * stride; + for (x = 0; x < WIDTH; x += 8) { + uint8_t *copy_from = oldpic->data[0]; + unsigned int offset, j; + uint8_t cols[4], grps[4]; + C93BlockType block_type; + + if (!bt) + bt = *buf++; + + block_type= bt & 0x0F; + switch (block_type) { + case C93_8X8_FROM_PREV: + offset = bytestream_get_le16(&buf); + if (copy_block(avctx, out, copy_from, offset, 8, stride)) + return -1; + break; + + case C93_4X4_FROM_CURR: + copy_from = newpic->data[0]; + case C93_4X4_FROM_PREV: + for (j = 0; j < 8; j += 4) { + for (i = 0; i < 8; i += 4) { + offset = bytestream_get_le16(&buf); + if (copy_block(avctx, &out[j*stride+i], + copy_from, offset, 4, stride)) + return -1; + } + } + break; + + case C93_8X8_2COLOR: + bytestream_get_buffer(&buf, cols, 2); + for (i = 0; i < 8; i++) { + draw_n_color(out + i*stride, stride, 8, 1, 1, cols, + NULL, *buf++); + } + + break; + + case C93_4X4_2COLOR: + case C93_4X4_4COLOR: + case C93_4X4_4COLOR_GRP: + for (j = 0; j < 8; j += 4) { + for (i = 0; i < 8; i += 4) { + if (block_type == C93_4X4_2COLOR) { + bytestream_get_buffer(&buf, cols, 2); + draw_n_color(out + i + j*stride, stride, 4, 4, + 1, cols, NULL, bytestream_get_le16(&buf)); + } else if (block_type == C93_4X4_4COLOR) { + bytestream_get_buffer(&buf, cols, 4); + draw_n_color(out + i + j*stride, stride, 4, 4, + 2, cols, NULL, bytestream_get_le32(&buf)); + } else { + bytestream_get_buffer(&buf, grps, 4); + draw_n_color(out + i + j*stride, stride, 4, 4, + 1, cols, grps, bytestream_get_le16(&buf)); + } + } + } + break; + + case C93_NOOP: + break; + + case C93_8X8_INTRA: + for (j = 0; j < 8; j++) + bytestream_get_buffer(&buf, out + j*stride, 8); + break; + + default: + av_log(avctx, AV_LOG_ERROR, "unexpected type %x at %dx%d\n", + block_type, x, y); + return -1; + } + bt >>= 4; + out += 8; + } + } + + *picture = *newpic; + *data_size = sizeof(AVFrame); + + return buf_size; +} + +AVCodec c93_decoder = { + "c93", + CODEC_TYPE_VIDEO, + CODEC_ID_C93, + sizeof(C93DecoderContext), + decode_init, + NULL, + decode_end, + decode_frame, + CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Interplay C93"), +}; diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/cabac.c b/src/add-ons/media/plugins/avcodec/libavcodec/cabac.c index 27e63045b7..fc17bb6ac4 100644 --- a/src/add-ons/media/plugins/avcodec/libavcodec/cabac.c +++ b/src/add-ons/media/plugins/avcodec/libavcodec/cabac.c @@ -2,20 +2,21 @@ * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder * Copyright (c) 2003 Michael Niedermayer * - * This library is free software; you can redistribute it and/or + * This file is part of FFmpeg. + * + * FFmpeg 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. + * version 2.1 of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * FFmpeg 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 - * + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** @@ -26,9 +27,10 @@ #include #include "common.h" +#include "bitstream.h" #include "cabac.h" -const uint8_t ff_h264_lps_range[64][4]= { +static const uint8_t lps_range[64][4]= { {128,176,208,240}, {128,167,197,227}, {128,158,187,216}, {123,150,178,205}, {116,142,169,195}, {111,135,160,185}, {105,128,152,175}, {100,122,144,166}, { 95,116,137,158}, { 90,110,130,150}, { 85,104,123,142}, { 81, 99,117,135}, @@ -47,7 +49,12 @@ const uint8_t ff_h264_lps_range[64][4]= { { 6, 8, 9, 11}, { 6, 7, 9, 10}, { 6, 7, 8, 9}, { 2, 2, 2, 2}, }; -const uint8_t ff_h264_mps_state[64]= { +uint8_t ff_h264_mlps_state[4*64]; +uint8_t ff_h264_lps_range[4*2*64]; +uint8_t ff_h264_lps_state[2*64]; +uint8_t ff_h264_mps_state[2*64]; + +static const uint8_t mps_state[64]= { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16, 17,18,19,20,21,22,23,24, @@ -58,7 +65,7 @@ const uint8_t ff_h264_mps_state[64]= { 57,58,59,60,61,62,62,63, }; -const uint8_t ff_h264_lps_state[64]= { +static const uint8_t lps_state[64]= { 0, 0, 1, 2, 2, 4, 4, 5, 6, 7, 8, 9, 9,11,11,12, 13,13,15,15,16,16,18,18, @@ -68,6 +75,40 @@ const uint8_t ff_h264_lps_state[64]= { 33,33,34,34,35,35,35,36, 36,36,37,37,37,38,38,63, }; +#if 0 +const uint8_t ff_h264_norm_shift_old[128]= { + 7,6,5,5,4,4,4,4,3,3,3,3,3,3,3,3, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; +#endif +const uint8_t ff_h264_norm_shift[512]= { + 9,8,7,7,6,6,6,6,5,5,5,5,5,5,5,5, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; /** * @@ -82,7 +123,7 @@ void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size){ #ifdef STRICT_LIMITS c->sym_count =0; #endif - + c->pb.bit_left++; //avoids firstBitFlag } @@ -90,61 +131,80 @@ void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size){ * * @param buf_size size of buf in bits */ -void ff_init_cabac_decoder(CABACContext *c, uint8_t *buf, int buf_size){ - c->bytestream_start= +void ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size){ + c->bytestream_start= c->bytestream= buf; + c->bytestream_end= buf + buf_size; - c->low= *c->bytestream++; - c->low= (c->low<<9) + ((*c->bytestream++)<<1); - c->range= 0x1FE00; - c->bits_left= 7; +#if CABAC_BITS == 16 + c->low = (*c->bytestream++)<<18; + c->low+= (*c->bytestream++)<<10; +#else + c->low = (*c->bytestream++)<<10; +#endif + c->low+= ((*c->bytestream++)<<2) + 2; + c->range= 0x1FE; } -void ff_init_cabac_states(CABACContext *c, uint8_t const (*lps_range)[4], - uint8_t const *mps_state, uint8_t const *lps_state, int state_count){ +void ff_init_cabac_states(CABACContext *c){ int i, j; - - for(i=0; ilps_range[2*i+0][j]= - c->lps_range[2*i+1][j]= lps_range[i][j]; + ff_h264_lps_range[j*2*64+2*i+0]= + ff_h264_lps_range[j*2*64+2*i+1]= lps_range[i][j]; } - c->mps_state[2*i+0]= 2*mps_state[i]; - c->mps_state[2*i+1]= 2*mps_state[i]+1; + ff_h264_mlps_state[128+2*i+0]= + ff_h264_mps_state[2*i+0]= 2*mps_state[i]+0; + ff_h264_mlps_state[128+2*i+1]= + ff_h264_mps_state[2*i+1]= 2*mps_state[i]+1; - if(lps_state[i]){ - c->lps_state[2*i+0]= 2*lps_state[i]; - c->lps_state[2*i+1]= 2*lps_state[i]+1; + if( i ){ +#ifdef BRANCHLESS_CABAC_DECODER + ff_h264_mlps_state[128-2*i-1]= 2*lps_state[i]+0; + ff_h264_mlps_state[128-2*i-2]= 2*lps_state[i]+1; }else{ - c->lps_state[2*i+0]= 1; - c->lps_state[2*i+1]= 0; + ff_h264_mlps_state[128-2*i-1]= 1; + ff_h264_mlps_state[128-2*i-2]= 0; +#else + ff_h264_lps_state[2*i+0]= 2*lps_state[i]+0; + ff_h264_lps_state[2*i+1]= 2*lps_state[i]+1; + }else{ + ff_h264_lps_state[2*i+0]= 1; + ff_h264_lps_state[2*i+1]= 0; +#endif } } } -#if 0 //selftest +#ifdef TEST +#undef random #define SIZE 10240 -int main(){ + +#include "avcodec.h" +#include "cabac.h" + +int main(void){ CABACContext c; uint8_t b[9*SIZE]; uint8_t r[9*SIZE]; int i; uint8_t state[10]= {0}; - + ff_init_cabac_encoder(&c, b, SIZE); - ff_init_cabac_states(&c, ff_h264_lps_range, ff_h264_mps_state, ff_h264_lps_state, 64); - + ff_init_cabac_states(&c); + for(i=0; i * - * This library is free software; you can redistribute it and/or + * This file is part of FFmpeg. + * + * FFmpeg 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. + * version 2.1 of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * FFmpeg 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 - * + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - + /** * @file cabac.h * Context Adaptive Binary Arithmetic Coder. */ +#ifndef FFMPEG_CABAC_H +#define FFMPEG_CABAC_H -#undef NDEBUG +#include "bitstream.h" + +//#undef NDEBUG #include +#ifdef ARCH_X86 +#include "x86_cpu.h" +#endif + +#define CABAC_BITS 16 +#define CABAC_MASK ((1<pb, 1, b); - for(;c->outstanding_count; c->outstanding_count--){ + put_bits(&c->pb, 1, b); + for(;c->outstanding_count; c->outstanding_count--){ put_bits(&c->pb, 1, 1-b); } } @@ -72,24 +84,25 @@ static inline void renorm_cabac_encoder(CABACContext *c){ put_cabac_bit(c, 1); c->low -= 0x200; } - + c->range+= c->range; c->low += c->low; } } -static inline void put_cabac(CABACContext *c, uint8_t * const state, int bit){ - int RangeLPS= c->lps_range[*state][((c->range)>>6)&3]; - +#ifdef TEST +static void put_cabac(CABACContext *c, uint8_t * const state, int bit){ + int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + *state]; + if(bit == ((*state)&1)){ c->range -= RangeLPS; - *state= c->mps_state[*state]; + *state= ff_h264_mps_state[*state]; }else{ c->low += c->range - RangeLPS; c->range = RangeLPS; - *state= c->lps_state[*state]; + *state= ff_h264_lps_state[*state]; } - + renorm_cabac_encoder(c); #ifdef STRICT_LIMITS @@ -97,7 +110,7 @@ static inline void put_cabac(CABACContext *c, uint8_t * const state, int bit){ #endif } -static inline void put_cabac_static(CABACContext *c, int RangeLPS, int bit){ +static void put_cabac_static(CABACContext *c, int RangeLPS, int bit){ assert(c->range > RangeLPS); if(!bit){ @@ -117,7 +130,7 @@ static inline void put_cabac_static(CABACContext *c, int RangeLPS, int bit){ /** * @param bit 0 -> write zero bit, !=0 write one bit */ -static inline void put_cabac_bypass(CABACContext *c, int bit){ +static void put_cabac_bypass(CABACContext *c, int bit){ c->low += c->low; if(bit){ @@ -133,7 +146,7 @@ static inline void put_cabac_bypass(CABACContext *c, int bit){ put_cabac_bit(c, 1); c->low -= 0x400; } - + #ifdef STRICT_LIMITS c->symCount++; #endif @@ -143,7 +156,7 @@ static inline void put_cabac_bypass(CABACContext *c, int bit){ * * @return the number of bytes written */ -static inline int put_cabac_terminate(CABACContext *c, int bit){ +static int put_cabac_terminate(CABACContext *c, int bit){ c->range -= 2; if(!bit){ @@ -151,31 +164,31 @@ static inline int put_cabac_terminate(CABACContext *c, int bit){ }else{ c->low += c->range; c->range= 2; - + renorm_cabac_encoder(c); assert(c->low <= 0x1FF); put_cabac_bit(c, c->low>>9); put_bits(&c->pb, 2, ((c->low>>7)&3)|1); - + flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong } - + #ifdef STRICT_LIMITS c->symCount++; #endif - return (get_bit_count(&c->pb)+7)>>3; + return (put_bits_count(&c->pb)+7)>>3; } /** * put (truncated) unary binarization. */ -static inline void put_cabac_u(CABACContext *c, uint8_t * state, int v, int max, int max_index, int truncated){ +static void put_cabac_u(CABACContext *c, uint8_t * state, int v, int max, int max_index, int truncated){ int i; - + assert(v <= max); - + #if 1 for(i=0; ilow+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1); +#else + c->low+= c->bytestream[0]<<1; +#endif + c->low -= CABAC_MASK; + c->bytestream+= CABAC_BITS/8; +} + +#if ! ( defined(ARCH_X86) && defined(HAVE_7REGS) && defined(HAVE_EBX_AVAILABLE) && !defined(BROKEN_RELOCATIONS) ) +static void refill2(CABACContext *c){ + int i, x; + + x= c->low ^ (c->low-1); + i= 7 - ff_h264_norm_shift[x>>(CABAC_BITS-1)]; + + x= -CABAC_MASK; + +#if CABAC_BITS == 16 + x+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1); +#else + x+= c->bytestream[0]<<1; +#endif + + c->low += x<bytestream+= CABAC_BITS/8; +} +#endif static inline void renorm_cabac_decoder(CABACContext *c){ - while(c->range < 0x10000){ + while(c->range < 0x100){ c->range+= c->range; c->low+= c->low; - if(--c->bits_left == 0){ - c->low+= *c->bytestream++; - c->bits_left= 8; + if(!(c->low & CABAC_MASK)) + refill(c); + } +} + +static inline void renorm_cabac_decoder_once(CABACContext *c){ +#ifdef ARCH_X86_DISABLED + int temp; +#if 0 + //P3:683 athlon:475 + asm( + "lea -0x100(%0), %2 \n\t" + "shr $31, %2 \n\t" //FIXME 31->63 for x86-64 + "shl %%cl, %0 \n\t" + "shl %%cl, %1 \n\t" + : "+r"(c->range), "+r"(c->low), "+c"(temp) + ); +#elif 0 + //P3:680 athlon:474 + asm( + "cmp $0x100, %0 \n\t" + "setb %%cl \n\t" //FIXME 31->63 for x86-64 + "shl %%cl, %0 \n\t" + "shl %%cl, %1 \n\t" + : "+r"(c->range), "+r"(c->low), "+c"(temp) + ); +#elif 1 + int temp2; + //P3:665 athlon:517 + asm( + "lea -0x100(%0), %%eax \n\t" + "cltd \n\t" + "mov %0, %%eax \n\t" + "and %%edx, %0 \n\t" + "and %1, %%edx \n\t" + "add %%eax, %0 \n\t" + "add %%edx, %1 \n\t" + : "+r"(c->range), "+r"(c->low), "+a"(temp), "+d"(temp2) + ); +#elif 0 + int temp2; + //P3:673 athlon:509 + asm( + "cmp $0x100, %0 \n\t" + "sbb %%edx, %%edx \n\t" + "mov %0, %%eax \n\t" + "and %%edx, %0 \n\t" + "and %1, %%edx \n\t" + "add %%eax, %0 \n\t" + "add %%edx, %1 \n\t" + : "+r"(c->range), "+r"(c->low), "+a"(temp), "+d"(temp2) + ); +#else + int temp2; + //P3:677 athlon:511 + asm( + "cmp $0x100, %0 \n\t" + "lea (%0, %0), %%eax \n\t" + "lea (%1, %1), %%edx \n\t" + "cmovb %%eax, %0 \n\t" + "cmovb %%edx, %1 \n\t" + : "+r"(c->range), "+r"(c->low), "+a"(temp), "+d"(temp2) + ); +#endif +#else + //P3:675 athlon:476 + int shift= (uint32_t)(c->range - 0x100)>>31; + c->range<<= shift; + c->low <<= shift; +#endif + if(!(c->low & CABAC_MASK)) + refill(c); +} + +static av_always_inline int get_cabac_inline(CABACContext *c, uint8_t * const state){ + //FIXME gcc generates duplicate load/stores for c->low and c->range +#define LOW "0" +#define RANGE "4" +#ifdef ARCH_X86_64 +#define BYTESTART "16" +#define BYTE "24" +#define BYTEEND "32" +#else +#define BYTESTART "12" +#define BYTE "16" +#define BYTEEND "20" +#endif +#if defined(ARCH_X86) && defined(HAVE_7REGS) && defined(HAVE_EBX_AVAILABLE) && !defined(BROKEN_RELOCATIONS) + int bit; + +#ifndef BRANCHLESS_CABAC_DECODER + asm volatile( + "movzbl (%1), %0 \n\t" + "movl "RANGE "(%2), %%ebx \n\t" + "movl "RANGE "(%2), %%edx \n\t" + "andl $0xC0, %%ebx \n\t" + "movzbl "MANGLE(ff_h264_lps_range)"(%0, %%ebx, 2), %%esi\n\t" + "movl "LOW "(%2), %%ebx \n\t" +//eax:state ebx:low, edx:range, esi:RangeLPS + "subl %%esi, %%edx \n\t" + "movl %%edx, %%ecx \n\t" + "shll $17, %%ecx \n\t" + "cmpl %%ecx, %%ebx \n\t" + " ja 1f \n\t" + +#if 1 + //athlon:4067 P3:4110 + "lea -0x100(%%edx), %%ecx \n\t" + "shr $31, %%ecx \n\t" + "shl %%cl, %%edx \n\t" + "shl %%cl, %%ebx \n\t" +#else + //athlon:4057 P3:4130 + "cmp $0x100, %%edx \n\t" //FIXME avoidable + "setb %%cl \n\t" + "shl %%cl, %%edx \n\t" + "shl %%cl, %%ebx \n\t" +#endif + "movzbl "MANGLE(ff_h264_mps_state)"(%0), %%ecx \n\t" + "movb %%cl, (%1) \n\t" +//eax:state ebx:low, edx:range, esi:RangeLPS + "test %%bx, %%bx \n\t" + " jnz 2f \n\t" + "mov "BYTE "(%2), %%"REG_S" \n\t" + "subl $0xFFFF, %%ebx \n\t" + "movzwl (%%"REG_S"), %%ecx \n\t" + "bswap %%ecx \n\t" + "shrl $15, %%ecx \n\t" + "add $2, %%"REG_S" \n\t" + "addl %%ecx, %%ebx \n\t" + "mov %%"REG_S", "BYTE "(%2) \n\t" + "jmp 2f \n\t" + "1: \n\t" +//eax:state ebx:low, edx:range, esi:RangeLPS + "subl %%ecx, %%ebx \n\t" + "movl %%esi, %%edx \n\t" + "movzbl " MANGLE(ff_h264_norm_shift) "(%%esi), %%ecx \n\t" + "shll %%cl, %%ebx \n\t" + "shll %%cl, %%edx \n\t" + "movzbl "MANGLE(ff_h264_lps_state)"(%0), %%ecx \n\t" + "movb %%cl, (%1) \n\t" + "add $1, %0 \n\t" + "test %%bx, %%bx \n\t" + " jnz 2f \n\t" + + "mov "BYTE "(%2), %%"REG_c" \n\t" + "movzwl (%%"REG_c"), %%esi \n\t" + "bswap %%esi \n\t" + "shrl $15, %%esi \n\t" + "subl $0xFFFF, %%esi \n\t" + "add $2, %%"REG_c" \n\t" + "mov %%"REG_c", "BYTE "(%2) \n\t" + + "leal -1(%%ebx), %%ecx \n\t" + "xorl %%ebx, %%ecx \n\t" + "shrl $15, %%ecx \n\t" + "movzbl " MANGLE(ff_h264_norm_shift) "(%%ecx), %%ecx \n\t" + "neg %%ecx \n\t" + "add $7, %%ecx \n\t" + + "shll %%cl , %%esi \n\t" + "addl %%esi, %%ebx \n\t" + "2: \n\t" + "movl %%edx, "RANGE "(%2) \n\t" + "movl %%ebx, "LOW "(%2) \n\t" + :"=&a"(bit) //FIXME this is fragile gcc either runs out of registers or miscompiles it (for example if "+a"(bit) or "+m"(*state) is used + :"r"(state), "r"(c) + : "%"REG_c, "%ebx", "%edx", "%"REG_S, "memory" + ); + bit&=1; +#else /* BRANCHLESS_CABAC_DECODER */ + + +#if defined HAVE_FAST_CMOV +#define BRANCHLESS_GET_CABAC_UPDATE(ret, cabac, statep, low, lowword, range, tmp, tmpbyte)\ + "mov "tmp" , %%ecx \n\t"\ + "shl $17 , "tmp" \n\t"\ + "cmp "low" , "tmp" \n\t"\ + "cmova %%ecx , "range" \n\t"\ + "sbb %%ecx , %%ecx \n\t"\ + "and %%ecx , "tmp" \n\t"\ + "sub "tmp" , "low" \n\t"\ + "xor %%ecx , "ret" \n\t" +#else /* HAVE_FAST_CMOV */ +#define BRANCHLESS_GET_CABAC_UPDATE(ret, cabac, statep, low, lowword, range, tmp, tmpbyte)\ + "mov "tmp" , %%ecx \n\t"\ + "shl $17 , "tmp" \n\t"\ + "sub "low" , "tmp" \n\t"\ + "sar $31 , "tmp" \n\t" /*lps_mask*/\ + "sub %%ecx , "range" \n\t" /*RangeLPS - range*/\ + "and "tmp" , "range" \n\t" /*(RangeLPS - range)&lps_mask*/\ + "add %%ecx , "range" \n\t" /*new range*/\ + "shl $17 , %%ecx \n\t"\ + "and "tmp" , %%ecx \n\t"\ + "sub %%ecx , "low" \n\t"\ + "xor "tmp" , "ret" \n\t" +#endif /* HAVE_FAST_CMOV */ + + +#define BRANCHLESS_GET_CABAC(ret, cabac, statep, low, lowword, range, tmp, tmpbyte)\ + "movzbl "statep" , "ret" \n\t"\ + "mov "range" , "tmp" \n\t"\ + "and $0xC0 , "range" \n\t"\ + "movzbl "MANGLE(ff_h264_lps_range)"("ret", "range", 2), "range" \n\t"\ + "sub "range" , "tmp" \n\t"\ + BRANCHLESS_GET_CABAC_UPDATE(ret, cabac, statep, low, lowword, range, tmp, tmpbyte)\ + "movzbl " MANGLE(ff_h264_norm_shift) "("range"), %%ecx \n\t"\ + "shl %%cl , "range" \n\t"\ + "movzbl "MANGLE(ff_h264_mlps_state)"+128("ret"), "tmp" \n\t"\ + "mov "tmpbyte" , "statep" \n\t"\ + "shl %%cl , "low" \n\t"\ + "test "lowword" , "lowword" \n\t"\ + " jnz 1f \n\t"\ + "mov "BYTE"("cabac"), %%"REG_c" \n\t"\ + "movzwl (%%"REG_c") , "tmp" \n\t"\ + "bswap "tmp" \n\t"\ + "shr $15 , "tmp" \n\t"\ + "sub $0xFFFF , "tmp" \n\t"\ + "add $2 , %%"REG_c" \n\t"\ + "mov %%"REG_c" , "BYTE "("cabac") \n\t"\ + "lea -1("low") , %%ecx \n\t"\ + "xor "low" , %%ecx \n\t"\ + "shr $15 , %%ecx \n\t"\ + "movzbl " MANGLE(ff_h264_norm_shift) "(%%ecx), %%ecx \n\t"\ + "neg %%ecx \n\t"\ + "add $7 , %%ecx \n\t"\ + "shl %%cl , "tmp" \n\t"\ + "add "tmp" , "low" \n\t"\ + "1: \n\t" + + asm volatile( + "movl "RANGE "(%2), %%esi \n\t" + "movl "LOW "(%2), %%ebx \n\t" + BRANCHLESS_GET_CABAC("%0", "%2", "(%1)", "%%ebx", "%%bx", "%%esi", "%%edx", "%%dl") + "movl %%esi, "RANGE "(%2) \n\t" + "movl %%ebx, "LOW "(%2) \n\t" + + :"=&a"(bit) + :"r"(state), "r"(c) + : "%"REG_c, "%ebx", "%edx", "%esi", "memory" + ); + bit&=1; +#endif /* BRANCHLESS_CABAC_DECODER */ +#else /* defined(ARCH_X86) && defined(HAVE_7REGS) && defined(HAVE_EBX_AVAILABLE) && !defined(BROKEN_RELOCATIONS) */ + int s = *state; + int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + s]; + int bit, lps_mask av_unused; + + c->range -= RangeLPS; +#ifndef BRANCHLESS_CABAC_DECODER + if(c->low < (c->range<<(CABAC_BITS+1))){ + bit= s&1; + *state= ff_h264_mps_state[s]; + renorm_cabac_decoder_once(c); + }else{ + bit= ff_h264_norm_shift[RangeLPS]; + c->low -= (c->range<<(CABAC_BITS+1)); + *state= ff_h264_lps_state[s]; + c->range = RangeLPS<low <<= bit; + bit= (s&1)^1; + + if(!(c->low & CABAC_MASK)){ + refill2(c); } } +#else /* BRANCHLESS_CABAC_DECODER */ + lps_mask= ((c->range<<(CABAC_BITS+1)) - c->low)>>31; + + c->low -= (c->range<<(CABAC_BITS+1)) & lps_mask; + c->range += (RangeLPS - c->range) & lps_mask; + + s^=lps_mask; + *state= (ff_h264_mlps_state+128)[s]; + bit= s&1; + + lps_mask= ff_h264_norm_shift[c->range]; + c->range<<= lps_mask; + c->low <<= lps_mask; + if(!(c->low & CABAC_MASK)) + refill2(c); +#endif /* BRANCHLESS_CABAC_DECODER */ +#endif /* defined(ARCH_X86) && defined(HAVE_7REGS) && defined(HAVE_EBX_AVAILABLE) && !defined(BROKEN_RELOCATIONS) */ + return bit; } -static inline int get_cabac(CABACContext *c, uint8_t * const state){ - int RangeLPS= c->lps_range[*state][((c->range)>>14)&3]<<8; +static int av_noinline get_cabac_noinline(CABACContext *c, uint8_t * const state){ + return get_cabac_inline(c,state); +} + +static int get_cabac(CABACContext *c, uint8_t * const state){ + return get_cabac_inline(c,state); +} + +static int get_cabac_bypass(CABACContext *c){ +#if 0 //not faster int bit; - - c->range -= RangeLPS; - if(c->low < c->range){ - bit= (*state)&1; - *state= c->mps_state[*state]; - }else{ - bit= ((*state)&1)^1; - c->low -= c->range; - c->range = RangeLPS; - *state= c->lps_state[*state]; - } - renorm_cabac_decoder(c); - - return bit; -} + asm volatile( + "movl "RANGE "(%1), %%ebx \n\t" + "movl "LOW "(%1), %%eax \n\t" + "shl $17, %%ebx \n\t" + "add %%eax, %%eax \n\t" + "sub %%ebx, %%eax \n\t" + "cltd \n\t" + "and %%edx, %%ebx \n\t" + "add %%ebx, %%eax \n\t" + "test %%ax, %%ax \n\t" + " jnz 1f \n\t" + "movl "BYTE "(%1), %%"REG_b" \n\t" + "subl $0xFFFF, %%eax \n\t" + "movzwl (%%"REG_b"), %%ecx \n\t" + "bswap %%ecx \n\t" + "shrl $15, %%ecx \n\t" + "addl $2, %%"REG_b" \n\t" + "addl %%ecx, %%eax \n\t" + "movl %%"REG_b", "BYTE "(%1) \n\t" + "1: \n\t" + "movl %%eax, "LOW "(%1) \n\t" -static inline int get_cabac_static(CABACContext *c, int RangeLPS){ - int bit; - - c->range -= RangeLPS; - if(c->low < c->range){ - bit= 0; - }else{ - bit= 1; - c->low -= c->range; - c->range = RangeLPS; - } - renorm_cabac_decoder(c); - - return bit; -} - -static inline int get_cabac_bypass(CABACContext *c){ + :"=&d"(bit) + :"r"(c) + : "%eax", "%"REG_b, "%ecx", "memory" + ); + return bit+1; +#else + int range; c->low += c->low; - if(--c->bits_left == 0){ - c->low+= *c->bytestream++; - c->bits_left= 8; - } - - if(c->low < c->range){ + if(!(c->low & CABAC_MASK)) + refill(c); + + range= c->range<<(CABAC_BITS+1); + if(c->low < range){ return 0; }else{ - c->low -= c->range; + c->low -= range; return 1; } +#endif +} + + +static av_always_inline int get_cabac_bypass_sign(CABACContext *c, int val){ +#if defined(ARCH_X86) && !(defined(PIC) && defined(__GNUC__)) + asm volatile( + "movl "RANGE "(%1), %%ebx \n\t" + "movl "LOW "(%1), %%eax \n\t" + "shl $17, %%ebx \n\t" + "add %%eax, %%eax \n\t" + "sub %%ebx, %%eax \n\t" + "cltd \n\t" + "and %%edx, %%ebx \n\t" + "add %%ebx, %%eax \n\t" + "xor %%edx, %%ecx \n\t" + "sub %%edx, %%ecx \n\t" + "test %%ax, %%ax \n\t" + " jnz 1f \n\t" + "mov "BYTE "(%1), %%"REG_b" \n\t" + "subl $0xFFFF, %%eax \n\t" + "movzwl (%%"REG_b"), %%edx \n\t" + "bswap %%edx \n\t" + "shrl $15, %%edx \n\t" + "add $2, %%"REG_b" \n\t" + "addl %%edx, %%eax \n\t" + "mov %%"REG_b", "BYTE "(%1) \n\t" + "1: \n\t" + "movl %%eax, "LOW "(%1) \n\t" + + :"+c"(val) + :"r"(c) + : "%eax", "%"REG_b, "%edx", "memory" + ); + return val; +#else + int range, mask; + c->low += c->low; + + if(!(c->low & CABAC_MASK)) + refill(c); + + range= c->range<<(CABAC_BITS+1); + c->low -= range; + mask= c->low >> 31; + range &= mask; + c->low += range; + return (val^mask)-mask; +#endif } /** * * @return the number of bytes read or 0 if no end */ -static inline int get_cabac_terminate(CABACContext *c){ - c->range -= 2<<8; - if(c->low < c->range){ - renorm_cabac_decoder(c); +static int get_cabac_terminate(CABACContext *c){ + c->range -= 2; + if(c->low < c->range<<(CABAC_BITS+1)){ + renorm_cabac_decoder_once(c); return 0; }else{ return c->bytestream - c->bytestream_start; - } + } } +#if 0 /** - * get (truncated) unnary binarization. + * Get (truncated) unary binarization. */ -static inline int get_cabac_u(CABACContext *c, uint8_t * state, int max, int max_index, int truncated){ +static int get_cabac_u(CABACContext *c, uint8_t * state, int max, int max_index, int truncated){ int i; - - for(i=0; i>=1){ v+= v + get_cabac_bypass(c); @@ -379,3 +755,6 @@ static inline int get_cabac_ueg(CABACContext *c, uint8_t * state, int max, int i }else return i; } +#endif /* 0 */ + +#endif /* FFMPEG_CABAC_H */ diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/cavs.c b/src/add-ons/media/plugins/avcodec/libavcodec/cavs.c new file mode 100644 index 0000000000..60219d4a34 --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/cavs.c @@ -0,0 +1,716 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder. + * Copyright (c) 2006 Stefan Gehrer + * + * This file is part of FFmpeg. + * + * FFmpeg 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.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file cavs.c + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder + * @author Stefan Gehrer + */ + +#include "avcodec.h" +#include "bitstream.h" +#include "golomb.h" +#include "cavs.h" +#include "cavsdata.h" + +/***************************************************************************** + * + * in-loop deblocking filter + * + ****************************************************************************/ + +static inline int get_bs(vector_t *mvP, vector_t *mvQ, int b) { + if((mvP->ref == REF_INTRA) || (mvQ->ref == REF_INTRA)) + return 2; + if( (abs(mvP->x - mvQ->x) >= 4) || (abs(mvP->y - mvQ->y) >= 4) ) + return 1; + if(b){ + mvP += MV_BWD_OFFS; + mvQ += MV_BWD_OFFS; + if( (abs(mvP->x - mvQ->x) >= 4) || (abs(mvP->y - mvQ->y) >= 4) ) + return 1; + }else{ + if(mvP->ref != mvQ->ref) + return 1; + } + return 0; +} + +#define SET_PARAMS \ + alpha = alpha_tab[av_clip(qp_avg + h->alpha_offset,0,63)]; \ + beta = beta_tab[av_clip(qp_avg + h->beta_offset, 0,63)]; \ + tc = tc_tab[av_clip(qp_avg + h->alpha_offset,0,63)]; + +/** + * in-loop deblocking filter for a single macroblock + * + * boundary strength (bs) mapping: + * + * --4---5-- + * 0 2 | + * | 6 | 7 | + * 1 3 | + * --------- + * + */ +void ff_cavs_filter(AVSContext *h, enum mb_t mb_type) { + DECLARE_ALIGNED_8(uint8_t, bs[8]); + int qp_avg, alpha, beta, tc; + int i; + + /* save un-deblocked lines */ + h->topleft_border_y = h->top_border_y[h->mbx*16+15]; + h->topleft_border_u = h->top_border_u[h->mbx*10+8]; + h->topleft_border_v = h->top_border_v[h->mbx*10+8]; + memcpy(&h->top_border_y[h->mbx*16], h->cy + 15* h->l_stride,16); + memcpy(&h->top_border_u[h->mbx*10+1], h->cu + 7* h->c_stride,8); + memcpy(&h->top_border_v[h->mbx*10+1], h->cv + 7* h->c_stride,8); + for(i=0;i<8;i++) { + h->left_border_y[i*2+1] = *(h->cy + 15 + (i*2+0)*h->l_stride); + h->left_border_y[i*2+2] = *(h->cy + 15 + (i*2+1)*h->l_stride); + h->left_border_u[i+1] = *(h->cu + 7 + i*h->c_stride); + h->left_border_v[i+1] = *(h->cv + 7 + i*h->c_stride); + } + if(!h->loop_filter_disable) { + /* determine bs */ + if(mb_type == I_8X8) + *((uint64_t *)bs) = 0x0202020202020202ULL; + else{ + *((uint64_t *)bs) = 0; + if(ff_cavs_partition_flags[mb_type] & SPLITV){ + bs[2] = get_bs(&h->mv[MV_FWD_X0], &h->mv[MV_FWD_X1], mb_type > P_8X8); + bs[3] = get_bs(&h->mv[MV_FWD_X2], &h->mv[MV_FWD_X3], mb_type > P_8X8); + } + if(ff_cavs_partition_flags[mb_type] & SPLITH){ + bs[6] = get_bs(&h->mv[MV_FWD_X0], &h->mv[MV_FWD_X2], mb_type > P_8X8); + bs[7] = get_bs(&h->mv[MV_FWD_X1], &h->mv[MV_FWD_X3], mb_type > P_8X8); + } + bs[0] = get_bs(&h->mv[MV_FWD_A1], &h->mv[MV_FWD_X0], mb_type > P_8X8); + bs[1] = get_bs(&h->mv[MV_FWD_A3], &h->mv[MV_FWD_X2], mb_type > P_8X8); + bs[4] = get_bs(&h->mv[MV_FWD_B2], &h->mv[MV_FWD_X0], mb_type > P_8X8); + bs[5] = get_bs(&h->mv[MV_FWD_B3], &h->mv[MV_FWD_X1], mb_type > P_8X8); + } + if( *((uint64_t *)bs) ) { + if(h->flags & A_AVAIL) { + qp_avg = (h->qp + h->left_qp + 1) >> 1; + SET_PARAMS; + h->s.dsp.cavs_filter_lv(h->cy,h->l_stride,alpha,beta,tc,bs[0],bs[1]); + h->s.dsp.cavs_filter_cv(h->cu,h->c_stride,alpha,beta,tc,bs[0],bs[1]); + h->s.dsp.cavs_filter_cv(h->cv,h->c_stride,alpha,beta,tc,bs[0],bs[1]); + } + qp_avg = h->qp; + SET_PARAMS; + h->s.dsp.cavs_filter_lv(h->cy + 8,h->l_stride,alpha,beta,tc,bs[2],bs[3]); + h->s.dsp.cavs_filter_lh(h->cy + 8*h->l_stride,h->l_stride,alpha,beta,tc, + bs[6],bs[7]); + + if(h->flags & B_AVAIL) { + qp_avg = (h->qp + h->top_qp[h->mbx] + 1) >> 1; + SET_PARAMS; + h->s.dsp.cavs_filter_lh(h->cy,h->l_stride,alpha,beta,tc,bs[4],bs[5]); + h->s.dsp.cavs_filter_ch(h->cu,h->c_stride,alpha,beta,tc,bs[4],bs[5]); + h->s.dsp.cavs_filter_ch(h->cv,h->c_stride,alpha,beta,tc,bs[4],bs[5]); + } + } + } + h->left_qp = h->qp; + h->top_qp[h->mbx] = h->qp; +} + +#undef SET_PARAMS + +/***************************************************************************** + * + * spatial intra prediction + * + ****************************************************************************/ + +void ff_cavs_load_intra_pred_luma(AVSContext *h, uint8_t *top, + uint8_t **left, int block) { + int i; + + switch(block) { + case 0: + *left = h->left_border_y; + h->left_border_y[0] = h->left_border_y[1]; + memset(&h->left_border_y[17],h->left_border_y[16],9); + memcpy(&top[1],&h->top_border_y[h->mbx*16],16); + top[17] = top[16]; + top[0] = top[1]; + if((h->flags & A_AVAIL) && (h->flags & B_AVAIL)) + h->left_border_y[0] = top[0] = h->topleft_border_y; + break; + case 1: + *left = h->intern_border_y; + for(i=0;i<8;i++) + h->intern_border_y[i+1] = *(h->cy + 7 + i*h->l_stride); + memset(&h->intern_border_y[9],h->intern_border_y[8],9); + h->intern_border_y[0] = h->intern_border_y[1]; + memcpy(&top[1],&h->top_border_y[h->mbx*16+8],8); + if(h->flags & C_AVAIL) + memcpy(&top[9],&h->top_border_y[(h->mbx + 1)*16],8); + else + memset(&top[9],top[8],9); + top[17] = top[16]; + top[0] = top[1]; + if(h->flags & B_AVAIL) + h->intern_border_y[0] = top[0] = h->top_border_y[h->mbx*16+7]; + break; + case 2: + *left = &h->left_border_y[8]; + memcpy(&top[1],h->cy + 7*h->l_stride,16); + top[17] = top[16]; + top[0] = top[1]; + if(h->flags & A_AVAIL) + top[0] = h->left_border_y[8]; + break; + case 3: + *left = &h->intern_border_y[8]; + for(i=0;i<8;i++) + h->intern_border_y[i+9] = *(h->cy + 7 + (i+8)*h->l_stride); + memset(&h->intern_border_y[17],h->intern_border_y[16],9); + memcpy(&top[0],h->cy + 7 + 7*h->l_stride,9); + memset(&top[9],top[8],9); + break; + } +} + +void ff_cavs_load_intra_pred_chroma(AVSContext *h) { + /* extend borders by one pixel */ + h->left_border_u[9] = h->left_border_u[8]; + h->left_border_v[9] = h->left_border_v[8]; + h->top_border_u[h->mbx*10+9] = h->top_border_u[h->mbx*10+8]; + h->top_border_v[h->mbx*10+9] = h->top_border_v[h->mbx*10+8]; + if(h->mbx && h->mby) { + h->top_border_u[h->mbx*10] = h->left_border_u[0] = h->topleft_border_u; + h->top_border_v[h->mbx*10] = h->left_border_v[0] = h->topleft_border_v; + } else { + h->left_border_u[0] = h->left_border_u[1]; + h->left_border_v[0] = h->left_border_v[1]; + h->top_border_u[h->mbx*10] = h->top_border_u[h->mbx*10+1]; + h->top_border_v[h->mbx*10] = h->top_border_v[h->mbx*10+1]; + } +} + +static void intra_pred_vert(uint8_t *d,uint8_t *top,uint8_t *left,int stride) { + int y; + uint64_t a = AV_RN64(&top[1]); + for(y=0;y<8;y++) { + *((uint64_t *)(d+y*stride)) = a; + } +} + +static void intra_pred_horiz(uint8_t *d,uint8_t *top,uint8_t *left,int stride) { + int y; + uint64_t a; + for(y=0;y<8;y++) { + a = left[y+1] * 0x0101010101010101ULL; + *((uint64_t *)(d+y*stride)) = a; + } +} + +static void intra_pred_dc_128(uint8_t *d,uint8_t *top,uint8_t *left,int stride) { + int y; + uint64_t a = 0x8080808080808080ULL; + for(y=0;y<8;y++) + *((uint64_t *)(d+y*stride)) = a; +} + +static void intra_pred_plane(uint8_t *d,uint8_t *top,uint8_t *left,int stride) { + int x,y,ia; + int ih = 0; + int iv = 0; + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + + for(x=0; x<4; x++) { + ih += (x+1)*(top[5+x]-top[3-x]); + iv += (x+1)*(left[5+x]-left[3-x]); + } + ia = (top[8]+left[8])<<4; + ih = (17*ih+16)>>5; + iv = (17*iv+16)>>5; + for(y=0; y<8; y++) + for(x=0; x<8; x++) + d[y*stride+x] = cm[(ia+(x-3)*ih+(y-3)*iv+16)>>5]; +} + +#define LOWPASS(ARRAY,INDEX) \ + (( ARRAY[(INDEX)-1] + 2*ARRAY[(INDEX)] + ARRAY[(INDEX)+1] + 2) >> 2) + +static void intra_pred_lp(uint8_t *d,uint8_t *top,uint8_t *left,int stride) { + int x,y; + for(y=0; y<8; y++) + for(x=0; x<8; x++) + d[y*stride+x] = (LOWPASS(top,x+1) + LOWPASS(left,y+1)) >> 1; +} + +static void intra_pred_down_left(uint8_t *d,uint8_t *top,uint8_t *left,int stride) { + int x,y; + for(y=0; y<8; y++) + for(x=0; x<8; x++) + d[y*stride+x] = (LOWPASS(top,x+y+2) + LOWPASS(left,x+y+2)) >> 1; +} + +static void intra_pred_down_right(uint8_t *d,uint8_t *top,uint8_t *left,int stride) { + int x,y; + for(y=0; y<8; y++) + for(x=0; x<8; x++) + if(x==y) + d[y*stride+x] = (left[1]+2*top[0]+top[1]+2)>>2; + else if(x>y) + d[y*stride+x] = LOWPASS(top,x-y); + else + d[y*stride+x] = LOWPASS(left,y-x); +} + +static void intra_pred_lp_left(uint8_t *d,uint8_t *top,uint8_t *left,int stride) { + int x,y; + for(y=0; y<8; y++) + for(x=0; x<8; x++) + d[y*stride+x] = LOWPASS(left,y+1); +} + +static void intra_pred_lp_top(uint8_t *d,uint8_t *top,uint8_t *left,int stride) { + int x,y; + for(y=0; y<8; y++) + for(x=0; x<8; x++) + d[y*stride+x] = LOWPASS(top,x+1); +} + +#undef LOWPASS + +void ff_cavs_modify_mb_i(AVSContext *h, int *pred_mode_uv) { + /* save pred modes before they get modified */ + h->pred_mode_Y[3] = h->pred_mode_Y[5]; + h->pred_mode_Y[6] = h->pred_mode_Y[8]; + h->top_pred_Y[h->mbx*2+0] = h->pred_mode_Y[7]; + h->top_pred_Y[h->mbx*2+1] = h->pred_mode_Y[8]; + + /* modify pred modes according to availability of neighbour samples */ + if(!(h->flags & A_AVAIL)) { + modify_pred(ff_left_modifier_l, &h->pred_mode_Y[4] ); + modify_pred(ff_left_modifier_l, &h->pred_mode_Y[7] ); + modify_pred(ff_left_modifier_c, pred_mode_uv ); + } + if(!(h->flags & B_AVAIL)) { + modify_pred(ff_top_modifier_l, &h->pred_mode_Y[4] ); + modify_pred(ff_top_modifier_l, &h->pred_mode_Y[5] ); + modify_pred(ff_top_modifier_c, pred_mode_uv ); + } +} + +/***************************************************************************** + * + * motion compensation + * + ****************************************************************************/ + +static inline void mc_dir_part(AVSContext *h,Picture *pic,int square, + int chroma_height,int delta,int list,uint8_t *dest_y, + uint8_t *dest_cb,uint8_t *dest_cr,int src_x_offset, + int src_y_offset,qpel_mc_func *qpix_op, + h264_chroma_mc_func chroma_op,vector_t *mv){ + MpegEncContext * const s = &h->s; + const int mx= mv->x + src_x_offset*8; + const int my= mv->y + src_y_offset*8; + const int luma_xy= (mx&3) + ((my&3)<<2); + uint8_t * src_y = pic->data[0] + (mx>>2) + (my>>2)*h->l_stride; + uint8_t * src_cb= pic->data[1] + (mx>>3) + (my>>3)*h->c_stride; + uint8_t * src_cr= pic->data[2] + (mx>>3) + (my>>3)*h->c_stride; + int extra_width= 0; //(s->flags&CODEC_FLAG_EMU_EDGE) ? 0 : 16; + int extra_height= extra_width; + int emu=0; + const int full_mx= mx>>2; + const int full_my= my>>2; + const int pic_width = 16*h->mb_width; + const int pic_height = 16*h->mb_height; + + if(!pic->data[0]) + return; + if(mx&7) extra_width -= 3; + if(my&7) extra_height -= 3; + + if( full_mx < 0-extra_width + || full_my < 0-extra_height + || full_mx + 16/*FIXME*/ > pic_width + extra_width + || full_my + 16/*FIXME*/ > pic_height + extra_height){ + ff_emulated_edge_mc(s->edge_emu_buffer, src_y - 2 - 2*h->l_stride, h->l_stride, + 16+5, 16+5/*FIXME*/, full_mx-2, full_my-2, pic_width, pic_height); + src_y= s->edge_emu_buffer + 2 + 2*h->l_stride; + emu=1; + } + + qpix_op[luma_xy](dest_y, src_y, h->l_stride); //FIXME try variable height perhaps? + if(!square){ + qpix_op[luma_xy](dest_y + delta, src_y + delta, h->l_stride); + } + + if(emu){ + ff_emulated_edge_mc(s->edge_emu_buffer, src_cb, h->c_stride, + 9, 9/*FIXME*/, (mx>>3), (my>>3), pic_width>>1, pic_height>>1); + src_cb= s->edge_emu_buffer; + } + chroma_op(dest_cb, src_cb, h->c_stride, chroma_height, mx&7, my&7); + + if(emu){ + ff_emulated_edge_mc(s->edge_emu_buffer, src_cr, h->c_stride, + 9, 9/*FIXME*/, (mx>>3), (my>>3), pic_width>>1, pic_height>>1); + src_cr= s->edge_emu_buffer; + } + chroma_op(dest_cr, src_cr, h->c_stride, chroma_height, mx&7, my&7); +} + +static inline void mc_part_std(AVSContext *h,int square,int chroma_height,int delta, + uint8_t *dest_y,uint8_t *dest_cb,uint8_t *dest_cr, + int x_offset, int y_offset,qpel_mc_func *qpix_put, + h264_chroma_mc_func chroma_put,qpel_mc_func *qpix_avg, + h264_chroma_mc_func chroma_avg, vector_t *mv){ + qpel_mc_func *qpix_op= qpix_put; + h264_chroma_mc_func chroma_op= chroma_put; + + dest_y += 2*x_offset + 2*y_offset*h->l_stride; + dest_cb += x_offset + y_offset*h->c_stride; + dest_cr += x_offset + y_offset*h->c_stride; + x_offset += 8*h->mbx; + y_offset += 8*h->mby; + + if(mv->ref >= 0){ + Picture *ref= &h->DPB[mv->ref]; + mc_dir_part(h, ref, square, chroma_height, delta, 0, + dest_y, dest_cb, dest_cr, x_offset, y_offset, + qpix_op, chroma_op, mv); + + qpix_op= qpix_avg; + chroma_op= chroma_avg; + } + + if((mv+MV_BWD_OFFS)->ref >= 0){ + Picture *ref= &h->DPB[0]; + mc_dir_part(h, ref, square, chroma_height, delta, 1, + dest_y, dest_cb, dest_cr, x_offset, y_offset, + qpix_op, chroma_op, mv+MV_BWD_OFFS); + } +} + +void ff_cavs_inter(AVSContext *h, enum mb_t mb_type) { + if(ff_cavs_partition_flags[mb_type] == 0){ // 16x16 + mc_part_std(h, 1, 8, 0, h->cy, h->cu, h->cv, 0, 0, + h->s.dsp.put_cavs_qpel_pixels_tab[0], + h->s.dsp.put_h264_chroma_pixels_tab[0], + h->s.dsp.avg_cavs_qpel_pixels_tab[0], + h->s.dsp.avg_h264_chroma_pixels_tab[0],&h->mv[MV_FWD_X0]); + }else{ + mc_part_std(h, 1, 4, 0, h->cy, h->cu, h->cv, 0, 0, + h->s.dsp.put_cavs_qpel_pixels_tab[1], + h->s.dsp.put_h264_chroma_pixels_tab[1], + h->s.dsp.avg_cavs_qpel_pixels_tab[1], + h->s.dsp.avg_h264_chroma_pixels_tab[1],&h->mv[MV_FWD_X0]); + mc_part_std(h, 1, 4, 0, h->cy, h->cu, h->cv, 4, 0, + h->s.dsp.put_cavs_qpel_pixels_tab[1], + h->s.dsp.put_h264_chroma_pixels_tab[1], + h->s.dsp.avg_cavs_qpel_pixels_tab[1], + h->s.dsp.avg_h264_chroma_pixels_tab[1],&h->mv[MV_FWD_X1]); + mc_part_std(h, 1, 4, 0, h->cy, h->cu, h->cv, 0, 4, + h->s.dsp.put_cavs_qpel_pixels_tab[1], + h->s.dsp.put_h264_chroma_pixels_tab[1], + h->s.dsp.avg_cavs_qpel_pixels_tab[1], + h->s.dsp.avg_h264_chroma_pixels_tab[1],&h->mv[MV_FWD_X2]); + mc_part_std(h, 1, 4, 0, h->cy, h->cu, h->cv, 4, 4, + h->s.dsp.put_cavs_qpel_pixels_tab[1], + h->s.dsp.put_h264_chroma_pixels_tab[1], + h->s.dsp.avg_cavs_qpel_pixels_tab[1], + h->s.dsp.avg_h264_chroma_pixels_tab[1],&h->mv[MV_FWD_X3]); + } +} + +/***************************************************************************** + * + * motion vector prediction + * + ****************************************************************************/ + +static inline void scale_mv(AVSContext *h, int *d_x, int *d_y, vector_t *src, int distp) { + int den = h->scale_den[src->ref]; + + *d_x = (src->x*distp*den + 256 + (src->x>>31)) >> 9; + *d_y = (src->y*distp*den + 256 + (src->y>>31)) >> 9; +} + +static inline void mv_pred_median(AVSContext *h, vector_t *mvP, vector_t *mvA, vector_t *mvB, vector_t *mvC) { + int ax, ay, bx, by, cx, cy; + int len_ab, len_bc, len_ca, len_mid; + + /* scale candidates according to their temporal span */ + scale_mv(h, &ax, &ay, mvA, mvP->dist); + scale_mv(h, &bx, &by, mvB, mvP->dist); + scale_mv(h, &cx, &cy, mvC, mvP->dist); + /* find the geometrical median of the three candidates */ + len_ab = abs(ax - bx) + abs(ay - by); + len_bc = abs(bx - cx) + abs(by - cy); + len_ca = abs(cx - ax) + abs(cy - ay); + len_mid = mid_pred(len_ab, len_bc, len_ca); + if(len_mid == len_ab) { + mvP->x = cx; + mvP->y = cy; + } else if(len_mid == len_bc) { + mvP->x = ax; + mvP->y = ay; + } else { + mvP->x = bx; + mvP->y = by; + } +} + +void ff_cavs_mv(AVSContext *h, enum mv_loc_t nP, enum mv_loc_t nC, + enum mv_pred_t mode, enum block_t size, int ref) { + vector_t *mvP = &h->mv[nP]; + vector_t *mvA = &h->mv[nP-1]; + vector_t *mvB = &h->mv[nP-4]; + vector_t *mvC = &h->mv[nC]; + const vector_t *mvP2 = NULL; + + mvP->ref = ref; + mvP->dist = h->dist[mvP->ref]; + if(mvC->ref == NOT_AVAIL) + mvC = &h->mv[nP-5]; // set to top-left (mvD) + if((mode == MV_PRED_PSKIP) && + ((mvA->ref == NOT_AVAIL) || (mvB->ref == NOT_AVAIL) || + ((mvA->x | mvA->y | mvA->ref) == 0) || + ((mvB->x | mvB->y | mvB->ref) == 0) )) { + mvP2 = &ff_cavs_un_mv; + /* if there is only one suitable candidate, take it */ + } else if((mvA->ref >= 0) && (mvB->ref < 0) && (mvC->ref < 0)) { + mvP2= mvA; + } else if((mvA->ref < 0) && (mvB->ref >= 0) && (mvC->ref < 0)) { + mvP2= mvB; + } else if((mvA->ref < 0) && (mvB->ref < 0) && (mvC->ref >= 0)) { + mvP2= mvC; + } else if(mode == MV_PRED_LEFT && mvA->ref == ref){ + mvP2= mvA; + } else if(mode == MV_PRED_TOP && mvB->ref == ref){ + mvP2= mvB; + } else if(mode == MV_PRED_TOPRIGHT && mvC->ref == ref){ + mvP2= mvC; + } + if(mvP2){ + mvP->x = mvP2->x; + mvP->y = mvP2->y; + }else + mv_pred_median(h, mvP, mvA, mvB, mvC); + + if(mode < MV_PRED_PSKIP) { + mvP->x += get_se_golomb(&h->s.gb); + mvP->y += get_se_golomb(&h->s.gb); + } + set_mvs(mvP,size); +} + +/***************************************************************************** + * + * macroblock level + * + ****************************************************************************/ + +/** + * initialise predictors for motion vectors and intra prediction + */ +void ff_cavs_init_mb(AVSContext *h) { + int i; + + /* copy predictors from top line (MB B and C) into cache */ + for(i=0;i<3;i++) { + h->mv[MV_FWD_B2+i] = h->top_mv[0][h->mbx*2+i]; + h->mv[MV_BWD_B2+i] = h->top_mv[1][h->mbx*2+i]; + } + h->pred_mode_Y[1] = h->top_pred_Y[h->mbx*2+0]; + h->pred_mode_Y[2] = h->top_pred_Y[h->mbx*2+1]; + /* clear top predictors if MB B is not available */ + if(!(h->flags & B_AVAIL)) { + h->mv[MV_FWD_B2] = ff_cavs_un_mv; + h->mv[MV_FWD_B3] = ff_cavs_un_mv; + h->mv[MV_BWD_B2] = ff_cavs_un_mv; + h->mv[MV_BWD_B3] = ff_cavs_un_mv; + h->pred_mode_Y[1] = h->pred_mode_Y[2] = NOT_AVAIL; + h->flags &= ~(C_AVAIL|D_AVAIL); + } else if(h->mbx) { + h->flags |= D_AVAIL; + } + if(h->mbx == h->mb_width-1) //MB C not available + h->flags &= ~C_AVAIL; + /* clear top-right predictors if MB C is not available */ + if(!(h->flags & C_AVAIL)) { + h->mv[MV_FWD_C2] = ff_cavs_un_mv; + h->mv[MV_BWD_C2] = ff_cavs_un_mv; + } + /* clear top-left predictors if MB D is not available */ + if(!(h->flags & D_AVAIL)) { + h->mv[MV_FWD_D3] = ff_cavs_un_mv; + h->mv[MV_BWD_D3] = ff_cavs_un_mv; + } + /* set pointer for co-located macroblock type */ + h->col_type = &h->col_type_base[h->mby*h->mb_width + h->mbx]; +} + +/** + * save predictors for later macroblocks and increase + * macroblock address + * @returns 0 if end of frame is reached, 1 otherwise + */ +int ff_cavs_next_mb(AVSContext *h) { + int i; + + h->flags |= A_AVAIL; + h->cy += 16; + h->cu += 8; + h->cv += 8; + /* copy mvs as predictors to the left */ + for(i=0;i<=20;i+=4) + h->mv[i] = h->mv[i+2]; + /* copy bottom mvs from cache to top line */ + h->top_mv[0][h->mbx*2+0] = h->mv[MV_FWD_X2]; + h->top_mv[0][h->mbx*2+1] = h->mv[MV_FWD_X3]; + h->top_mv[1][h->mbx*2+0] = h->mv[MV_BWD_X2]; + h->top_mv[1][h->mbx*2+1] = h->mv[MV_BWD_X3]; + /* next MB address */ + h->mbx++; + if(h->mbx == h->mb_width) { //new mb line + h->flags = B_AVAIL|C_AVAIL; + /* clear left pred_modes */ + h->pred_mode_Y[3] = h->pred_mode_Y[6] = NOT_AVAIL; + /* clear left mv predictors */ + for(i=0;i<=20;i+=4) + h->mv[i] = ff_cavs_un_mv; + h->mbx = 0; + h->mby++; + /* re-calculate sample pointers */ + h->cy = h->picture.data[0] + h->mby*16*h->l_stride; + h->cu = h->picture.data[1] + h->mby*8*h->c_stride; + h->cv = h->picture.data[2] + h->mby*8*h->c_stride; + if(h->mby == h->mb_height) { //frame end + return 0; + } else { + //check_for_slice(h); + } + } + return 1; +} + +/***************************************************************************** + * + * frame level + * + ****************************************************************************/ + +void ff_cavs_init_pic(AVSContext *h) { + int i; + + /* clear some predictors */ + for(i=0;i<=20;i+=4) + h->mv[i] = ff_cavs_un_mv; + h->mv[MV_BWD_X0] = ff_cavs_dir_mv; + set_mvs(&h->mv[MV_BWD_X0], BLK_16X16); + h->mv[MV_FWD_X0] = ff_cavs_dir_mv; + set_mvs(&h->mv[MV_FWD_X0], BLK_16X16); + h->pred_mode_Y[3] = h->pred_mode_Y[6] = NOT_AVAIL; + h->cy = h->picture.data[0]; + h->cu = h->picture.data[1]; + h->cv = h->picture.data[2]; + h->l_stride = h->picture.linesize[0]; + h->c_stride = h->picture.linesize[1]; + h->luma_scan[2] = 8*h->l_stride; + h->luma_scan[3] = 8*h->l_stride+8; + h->mbx = h->mby = 0; + h->flags = 0; +} + +/***************************************************************************** + * + * headers and interface + * + ****************************************************************************/ + +/** + * some predictions require data from the top-neighbouring macroblock. + * this data has to be stored for one complete row of macroblocks + * and this storage space is allocated here + */ +void ff_cavs_init_top_lines(AVSContext *h) { + /* alloc top line of predictors */ + h->top_qp = av_malloc( h->mb_width); + h->top_mv[0] = av_malloc((h->mb_width*2+1)*sizeof(vector_t)); + h->top_mv[1] = av_malloc((h->mb_width*2+1)*sizeof(vector_t)); + h->top_pred_Y = av_malloc( h->mb_width*2*sizeof(*h->top_pred_Y)); + h->top_border_y = av_malloc((h->mb_width+1)*16); + h->top_border_u = av_malloc((h->mb_width)*10); + h->top_border_v = av_malloc((h->mb_width)*10); + + /* alloc space for co-located MVs and types */ + h->col_mv = av_malloc( h->mb_width*h->mb_height*4*sizeof(vector_t)); + h->col_type_base = av_malloc(h->mb_width*h->mb_height); + h->block = av_mallocz(64*sizeof(DCTELEM)); +} + +av_cold int ff_cavs_init(AVCodecContext *avctx) { + AVSContext *h = avctx->priv_data; + MpegEncContext * const s = &h->s; + + MPV_decode_defaults(s); + s->avctx = avctx; + + avctx->pix_fmt= PIX_FMT_YUV420P; + + h->luma_scan[0] = 0; + h->luma_scan[1] = 8; + h->intra_pred_l[ INTRA_L_VERT] = intra_pred_vert; + h->intra_pred_l[ INTRA_L_HORIZ] = intra_pred_horiz; + h->intra_pred_l[ INTRA_L_LP] = intra_pred_lp; + h->intra_pred_l[ INTRA_L_DOWN_LEFT] = intra_pred_down_left; + h->intra_pred_l[INTRA_L_DOWN_RIGHT] = intra_pred_down_right; + h->intra_pred_l[ INTRA_L_LP_LEFT] = intra_pred_lp_left; + h->intra_pred_l[ INTRA_L_LP_TOP] = intra_pred_lp_top; + h->intra_pred_l[ INTRA_L_DC_128] = intra_pred_dc_128; + h->intra_pred_c[ INTRA_C_LP] = intra_pred_lp; + h->intra_pred_c[ INTRA_C_HORIZ] = intra_pred_horiz; + h->intra_pred_c[ INTRA_C_VERT] = intra_pred_vert; + h->intra_pred_c[ INTRA_C_PLANE] = intra_pred_plane; + h->intra_pred_c[ INTRA_C_LP_LEFT] = intra_pred_lp_left; + h->intra_pred_c[ INTRA_C_LP_TOP] = intra_pred_lp_top; + h->intra_pred_c[ INTRA_C_DC_128] = intra_pred_dc_128; + h->mv[ 7] = ff_cavs_un_mv; + h->mv[19] = ff_cavs_un_mv; + return 0; +} + +av_cold int ff_cavs_end(AVCodecContext *avctx) { + AVSContext *h = avctx->priv_data; + + av_free(h->top_qp); + av_free(h->top_mv[0]); + av_free(h->top_mv[1]); + av_free(h->top_pred_Y); + av_free(h->top_border_y); + av_free(h->top_border_u); + av_free(h->top_border_v); + av_free(h->col_mv); + av_free(h->col_type_base); + av_free(h->block); + return 0; +} diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/cavs.h b/src/add-ons/media/plugins/avcodec/libavcodec/cavs.h new file mode 100644 index 0000000000..9afa96e42c --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/cavs.h @@ -0,0 +1,314 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder. + * Copyright (c) 2006 Stefan Gehrer + * + * This file is part of FFmpeg. + * + * FFmpeg 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.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FFMPEG_CAVS_H +#define FFMPEG_CAVS_H + +#include "dsputil.h" +#include "mpegvideo.h" + +#define SLICE_MIN_START_CODE 0x00000101 +#define SLICE_MAX_START_CODE 0x000001af +#define EXT_START_CODE 0x000001b5 +#define USER_START_CODE 0x000001b2 +#define CAVS_START_CODE 0x000001b0 +#define PIC_I_START_CODE 0x000001b3 +#define PIC_PB_START_CODE 0x000001b6 + +#define A_AVAIL 1 +#define B_AVAIL 2 +#define C_AVAIL 4 +#define D_AVAIL 8 +#define NOT_AVAIL -1 +#define REF_INTRA -2 +#define REF_DIR -3 + +#define ESCAPE_CODE 59 + +#define FWD0 0x01 +#define FWD1 0x02 +#define BWD0 0x04 +#define BWD1 0x08 +#define SYM0 0x10 +#define SYM1 0x20 +#define SPLITH 0x40 +#define SPLITV 0x80 + +#define MV_BWD_OFFS 12 +#define MV_STRIDE 4 + +enum mb_t { + I_8X8 = 0, + P_SKIP, + P_16X16, + P_16X8, + P_8X16, + P_8X8, + B_SKIP, + B_DIRECT, + B_FWD_16X16, + B_BWD_16X16, + B_SYM_16X16, + B_8X8 = 29 +}; + +enum sub_mb_t { + B_SUB_DIRECT, + B_SUB_FWD, + B_SUB_BWD, + B_SUB_SYM +}; + +enum intra_luma_t { + INTRA_L_VERT, + INTRA_L_HORIZ, + INTRA_L_LP, + INTRA_L_DOWN_LEFT, + INTRA_L_DOWN_RIGHT, + INTRA_L_LP_LEFT, + INTRA_L_LP_TOP, + INTRA_L_DC_128 +}; + +enum intra_chroma_t { + INTRA_C_LP, + INTRA_C_HORIZ, + INTRA_C_VERT, + INTRA_C_PLANE, + INTRA_C_LP_LEFT, + INTRA_C_LP_TOP, + INTRA_C_DC_128, +}; + +enum mv_pred_t { + MV_PRED_MEDIAN, + MV_PRED_LEFT, + MV_PRED_TOP, + MV_PRED_TOPRIGHT, + MV_PRED_PSKIP, + MV_PRED_BSKIP +}; + +enum block_t { + BLK_16X16, + BLK_16X8, + BLK_8X16, + BLK_8X8 +}; + +enum mv_loc_t { + MV_FWD_D3 = 0, + MV_FWD_B2, + MV_FWD_B3, + MV_FWD_C2, + MV_FWD_A1, + MV_FWD_X0, + MV_FWD_X1, + MV_FWD_A3 = 8, + MV_FWD_X2, + MV_FWD_X3, + MV_BWD_D3 = MV_BWD_OFFS, + MV_BWD_B2, + MV_BWD_B3, + MV_BWD_C2, + MV_BWD_A1, + MV_BWD_X0, + MV_BWD_X1, + MV_BWD_A3 = MV_BWD_OFFS+8, + MV_BWD_X2, + MV_BWD_X3 +}; + +DECLARE_ALIGNED_8(typedef, struct) { + int16_t x; + int16_t y; + int16_t dist; + int16_t ref; +} vector_t; + +typedef struct dec_2dvlc_t { + int8_t rltab[59][3]; + int8_t level_add[27]; + int8_t golomb_order; + int inc_limit; + int8_t max_run; +} dec_2dvlc_t; + +typedef struct { + MpegEncContext s; + Picture picture; ///< currently decoded frame + Picture DPB[2]; ///< reference frames + int dist[2]; ///< temporal distances from current frame to ref frames + int profile, level; + int aspect_ratio; + int mb_width, mb_height; + int pic_type; + int progressive; + int pic_structure; + int skip_mode_flag; ///< select between skip_count or one skip_flag per MB + int loop_filter_disable; + int alpha_offset, beta_offset; + int ref_flag; + int mbx, mby; ///< macroblock coordinates + int flags; ///< availability flags of neighbouring macroblocks + int stc; ///< last start code + uint8_t *cy, *cu, *cv; ///< current MB sample pointers + int left_qp; + uint8_t *top_qp; + + /** mv motion vector cache + 0: D3 B2 B3 C2 + 4: A1 X0 X1 - + 8: A3 X2 X3 - + + X are the vectors in the current macroblock (5,6,9,10) + A is the macroblock to the left (4,8) + B is the macroblock to the top (1,2) + C is the macroblock to the top-right (3) + D is the macroblock to the top-left (0) + + the same is repeated for backward motion vectors */ + vector_t mv[2*4*3]; + vector_t *top_mv[2]; + vector_t *col_mv; + + /** luma pred mode cache + 0: -- B2 B3 + 3: A1 X0 X1 + 6: A3 X2 X3 */ + int pred_mode_Y[3*3]; + int *top_pred_Y; + int l_stride, c_stride; + int luma_scan[4]; + int qp; + int qp_fixed; + int cbp; + ScanTable scantable; + + /** intra prediction is done with un-deblocked samples + they are saved here before deblocking the MB */ + uint8_t *top_border_y, *top_border_u, *top_border_v; + uint8_t left_border_y[26], left_border_u[10], left_border_v[10]; + uint8_t intern_border_y[26]; + uint8_t topleft_border_y, topleft_border_u, topleft_border_v; + + void (*intra_pred_l[8])(uint8_t *d,uint8_t *top,uint8_t *left,int stride); + void (*intra_pred_c[7])(uint8_t *d,uint8_t *top,uint8_t *left,int stride); + uint8_t *col_type_base; + uint8_t *col_type; + + /* scaling factors for MV prediction */ + int sym_factor; ///< for scaling in symmetrical B block + int direct_den[2]; ///< for scaling in direct B block + int scale_den[2]; ///< for scaling neighbouring MVs + + int got_keyframe; + DCTELEM *block; +} AVSContext; + +extern const uint8_t ff_cavs_dequant_shift[64]; +extern const uint16_t ff_cavs_dequant_mul[64]; +extern const dec_2dvlc_t ff_cavs_intra_dec[7]; +extern const dec_2dvlc_t ff_cavs_inter_dec[7]; +extern const dec_2dvlc_t ff_cavs_chroma_dec[5]; +extern const uint8_t ff_cavs_chroma_qp[64]; +extern const uint8_t ff_cavs_scan3x3[4]; +extern const uint8_t ff_cavs_partition_flags[30]; +extern const int_fast8_t ff_left_modifier_l[8]; +extern const int_fast8_t ff_top_modifier_l[8]; +extern const int_fast8_t ff_left_modifier_c[7]; +extern const int_fast8_t ff_top_modifier_c[7]; +extern const vector_t ff_cavs_intra_mv; +extern const vector_t ff_cavs_un_mv; +extern const vector_t ff_cavs_dir_mv; + +static inline void modify_pred(const int_fast8_t *mod_table, int *mode) { + *mode = mod_table[*mode]; + if(*mode < 0) { + av_log(NULL, AV_LOG_ERROR, "Illegal intra prediction mode\n"); + *mode = 0; + } +} + +static inline void set_intra_mode_default(AVSContext *h) { + h->pred_mode_Y[3] = h->pred_mode_Y[6] = INTRA_L_LP; + h->top_pred_Y[h->mbx*2+0] = h->top_pred_Y[h->mbx*2+1] = INTRA_L_LP; +} + +static inline void set_mvs(vector_t *mv, enum block_t size) { + switch(size) { + case BLK_16X16: + mv[MV_STRIDE ] = mv[0]; + mv[MV_STRIDE+1] = mv[0]; + case BLK_16X8: + mv[1] = mv[0]; + break; + case BLK_8X16: + mv[MV_STRIDE] = mv[0]; + break; + } +} + +static inline void set_mv_intra(AVSContext *h) { + h->mv[MV_FWD_X0] = ff_cavs_intra_mv; + set_mvs(&h->mv[MV_FWD_X0], BLK_16X16); + h->mv[MV_BWD_X0] = ff_cavs_intra_mv; + set_mvs(&h->mv[MV_BWD_X0], BLK_16X16); + if(h->pic_type != FF_B_TYPE) + *h->col_type = I_8X8; +} + +static inline int dequant(AVSContext *h, DCTELEM *level_buf, uint8_t *run_buf, + DCTELEM *dst, int mul, int shift, int coeff_num) { + int round = 1 << (shift - 1); + int pos = -1; + const uint8_t *scantab = h->scantable.permutated; + + /* inverse scan and dequantization */ + while(--coeff_num >= 0){ + pos += run_buf[coeff_num]; + if(pos > 63) { + av_log(h->s.avctx, AV_LOG_ERROR, + "position out of block bounds at pic %d MB(%d,%d)\n", + h->picture.poc, h->mbx, h->mby); + return -1; + } + dst[scantab[pos]] = (level_buf[coeff_num]*mul + round) >> shift; + } + return 0; +} + +void ff_cavs_filter(AVSContext *h, enum mb_t mb_type); +void ff_cavs_load_intra_pred_luma(AVSContext *h, uint8_t *top, uint8_t **left, + int block); +void ff_cavs_load_intra_pred_chroma(AVSContext *h); +void ff_cavs_modify_mb_i(AVSContext *h, int *pred_mode_uv); +void ff_cavs_inter(AVSContext *h, enum mb_t mb_type); +void ff_cavs_mv(AVSContext *h, enum mv_loc_t nP, enum mv_loc_t nC, + enum mv_pred_t mode, enum block_t size, int ref); +void ff_cavs_init_mb(AVSContext *h); +int ff_cavs_next_mb(AVSContext *h); +void ff_cavs_init_pic(AVSContext *h); +void ff_cavs_init_top_lines(AVSContext *h); +int ff_cavs_init(AVCodecContext *avctx); +int ff_cavs_end (AVCodecContext *avctx); + +#endif /* FFMPEG_CAVS_H */ diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/cavs_parser.c b/src/add-ons/media/plugins/avcodec/libavcodec/cavs_parser.c new file mode 100644 index 0000000000..33f7fff710 --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/cavs_parser.c @@ -0,0 +1,107 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) parser. + * Copyright (c) 2006 Stefan Gehrer + * + * This file is part of FFmpeg. + * + * FFmpeg 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.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file cavs_parser.c + * Chinese AVS video (AVS1-P2, JiZhun profile) parser + * @author Stefan Gehrer + */ + +#include "parser.h" +#include "cavs.h" + + +/** + * finds the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame, or -1 + */ +static int cavs_find_frame_end(ParseContext *pc, const uint8_t *buf, + int buf_size) { + int pic_found, i; + uint32_t state; + + pic_found= pc->frame_start_found; + state= pc->state; + + i=0; + if(!pic_found){ + for(i=0; i SLICE_MAX_START_CODE){ + pc->frame_start_found=0; + pc->state=-1; + return i-3; + } + } + } + } + pc->frame_start_found= pic_found; + pc->state= state; + return END_NOT_FOUND; +} + +static int cavsvideo_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ + next= buf_size; + }else{ + next= cavs_find_frame_end(pc, buf, buf_size); + + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser cavsvideo_parser = { + { CODEC_ID_CAVS }, + sizeof(ParseContext1), + NULL, + cavsvideo_parse, + ff_parse1_close, + ff_mpeg4video_split, +}; diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/cavsdata.h b/src/add-ons/media/plugins/avcodec/libavcodec/cavsdata.h new file mode 100644 index 0000000000..a24fb5ddb4 --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/cavsdata.h @@ -0,0 +1,505 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder. + * Copyright (c) 2006 Stefan Gehrer + * + * This file is part of FFmpeg. + * + * FFmpeg 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.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FFMPEG_CAVSDATA_H +#define FFMPEG_CAVSDATA_H + +#include "cavs.h" + +const uint8_t ff_cavs_partition_flags[30] = { + 0, //I_8X8 + 0, //P_SKIP + 0, //P_16X16 + SPLITH, //P_16X8 + SPLITV, //P_8X16 + SPLITH|SPLITV, //P_8X8 + SPLITH|SPLITV, //B_SKIP + SPLITH|SPLITV, //B_DIRECT + 0, //B_FWD_16X16 + 0, //B_BWD_16X16 + 0, //B_SYM_16X16 + FWD0|FWD1 |SPLITH, + FWD0|FWD1 |SPLITV, + BWD0|BWD1 |SPLITH, + BWD0|BWD1 |SPLITV, + FWD0|BWD1 |SPLITH, + FWD0|BWD1 |SPLITV, + BWD0|FWD1 |SPLITH, + BWD0|FWD1 |SPLITV, + FWD0|FWD1 |SYM1|SPLITH, + FWD0|FWD1 |SYM1 |SPLITV, + BWD0|FWD1 |SYM1|SPLITH, + BWD0|FWD1 |SYM1 |SPLITV, + FWD0|FWD1|SYM0 |SPLITH, + FWD0|FWD1|SYM0 |SPLITV, + FWD0|BWD1|SYM0 |SPLITH, + FWD0|BWD1|SYM0 |SPLITV, + FWD0|FWD1|SYM0|SYM1|SPLITH, + FWD0|FWD1|SYM0|SYM1 |SPLITV, + SPLITH|SPLITV, //B_8X8 = 29 +}; + +const uint8_t ff_cavs_scan3x3[4] = {4,5,7,8}; + +const uint8_t ff_cavs_chroma_qp[64] = { + 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,42,43,43,44,44, + 45,45,46,46,47,47,48,48,48,49,49,49,50,50,50,51 +}; + +const uint8_t ff_cavs_dequant_shift[64] = { + 14,14,14,14,14,14,14,14, + 13,13,13,13,13,13,13,13, + 13,12,12,12,12,12,12,12, + 11,11,11,11,11,11,11,11, + 11,10,10,10,10,10,10,10, + 10, 9, 9, 9, 9, 9, 9, 9, + 9, 8, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7 +}; + +const uint16_t ff_cavs_dequant_mul[64] = { + 32768,36061,38968,42495,46341,50535,55437,60424, + 32932,35734,38968,42495,46177,50535,55109,59933, + 65535,35734,38968,42577,46341,50617,55027,60097, + 32809,35734,38968,42454,46382,50576,55109,60056, + 65535,35734,38968,42495,46320,50515,55109,60076, + 65535,35744,38968,42495,46341,50535,55099,60087, + 65535,35734,38973,42500,46341,50535,55109,60097, + 32771,35734,38965,42497,46341,50535,55109,60099 +}; + +/** marks block as unavailable, i.e. out of picture + or not yet decoded */ +const vector_t ff_cavs_un_mv = {0,0,1,NOT_AVAIL}; + +/** marks block as "no prediction from this direction" + e.g. forward motion vector in BWD partition */ +const vector_t ff_cavs_dir_mv = {0,0,1,REF_DIR}; + +/** marks block as using intra prediction */ +const vector_t ff_cavs_intra_mv = {0,0,1,REF_INTRA}; + +#define EOB 0,0,0 + +const dec_2dvlc_t ff_cavs_intra_dec[7] = { + { + { //level / run / table_inc + { 1, 1, 1},{ -1, 1, 1},{ 1, 2, 1},{ -1, 2, 1},{ 1, 3, 1},{ -1, 3, 1}, + { 1, 4, 1},{ -1, 4, 1},{ 1, 5, 1},{ -1, 5, 1},{ 1, 6, 1},{ -1, 6, 1}, + { 1, 7, 1},{ -1, 7, 1},{ 1, 8, 1},{ -1, 8, 1},{ 1, 9, 1},{ -1, 9, 1}, + { 1,10, 1},{ -1,10, 1},{ 1,11, 1},{ -1,11, 1},{ 2, 1, 2},{ -2, 1, 2}, + { 1,12, 1},{ -1,12, 1},{ 1,13, 1},{ -1,13, 1},{ 1,14, 1},{ -1,14, 1}, + { 1,15, 1},{ -1,15, 1},{ 2, 2, 2},{ -2, 2, 2},{ 1,16, 1},{ -1,16, 1}, + { 1,17, 1},{ -1,17, 1},{ 3, 1, 3},{ -3, 1, 3},{ 1,18, 1},{ -1,18, 1}, + { 1,19, 1},{ -1,19, 1},{ 2, 3, 2},{ -2, 3, 2},{ 1,20, 1},{ -1,20, 1}, + { 1,21, 1},{ -1,21, 1},{ 2, 4, 2},{ -2, 4, 2},{ 1,22, 1},{ -1,22, 1}, + { 2, 5, 2},{ -2, 5, 2},{ 1,23, 1},{ -1,23, 1},{ EOB } + }, + //level_add + { 0, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2,-1,-1,-1}, + 2, //golomb_order + 0, //inc_limit + 23, //max_run + },{ + { //level / run + { 1, 1, 0},{ -1, 1, 0},{ 1, 2, 0},{ -1, 2, 0},{ 2, 1, 1},{ -2, 1, 1}, + { 1, 3, 0},{ -1, 3, 0},{ EOB },{ 1, 4, 0},{ -1, 4, 0},{ 1, 5, 0}, + { -1, 5, 0},{ 1, 6, 0},{ -1, 6, 0},{ 3, 1, 2},{ -3, 1, 2},{ 2, 2, 1}, + { -2, 2, 1},{ 1, 7, 0},{ -1, 7, 0},{ 1, 8, 0},{ -1, 8, 0},{ 1, 9, 0}, + { -1, 9, 0},{ 2, 3, 1},{ -2, 3, 1},{ 4, 1, 2},{ -4, 1, 2},{ 1,10, 0}, + { -1,10, 0},{ 1,11, 0},{ -1,11, 0},{ 2, 4, 1},{ -2, 4, 1},{ 3, 2, 2}, + { -3, 2, 2},{ 1,12, 0},{ -1,12, 0},{ 2, 5, 1},{ -2, 5, 1},{ 5, 1, 3}, + { -5, 1, 3},{ 1,13, 0},{ -1,13, 0},{ 2, 6, 1},{ -2, 6, 1},{ 1,14, 0}, + { -1,14, 0},{ 2, 7, 1},{ -2, 7, 1},{ 2, 8, 1},{ -2, 8, 1},{ 3, 3, 2}, + { -3, 3, 2},{ 6, 1, 3},{ -6, 1, 3},{ 1,15, 0},{ -1,15, 0} + }, + //level_add + { 0, 7, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + 2, //golomb_order + 1, //inc_limit + 15, //max_run + },{ + { //level / run + { 1, 1, 0},{ -1, 1, 0},{ 2, 1, 0},{ -2, 1, 0},{ 1, 2, 0},{ -1, 2, 0}, + { 3, 1, 1},{ -3, 1, 1},{ EOB },{ 1, 3, 0},{ -1, 3, 0},{ 2, 2, 0}, + { -2, 2, 0},{ 4, 1, 1},{ -4, 1, 1},{ 1, 4, 0},{ -1, 4, 0},{ 5, 1, 2}, + { -5, 1, 2},{ 1, 5, 0},{ -1, 5, 0},{ 3, 2, 1},{ -3, 2, 1},{ 2, 3, 0}, + { -2, 3, 0},{ 1, 6, 0},{ -1, 6, 0},{ 6, 1, 2},{ -6, 1, 2},{ 2, 4, 0}, + { -2, 4, 0},{ 1, 7, 0},{ -1, 7, 0},{ 4, 2, 1},{ -4, 2, 1},{ 7, 1, 2}, + { -7, 1, 2},{ 3, 3, 1},{ -3, 3, 1},{ 2, 5, 0},{ -2, 5, 0},{ 1, 8, 0}, + { -1, 8, 0},{ 2, 6, 0},{ -2, 6, 0},{ 8, 1, 3},{ -8, 1, 3},{ 1, 9, 0}, + { -1, 9, 0},{ 5, 2, 2},{ -5, 2, 2},{ 3, 4, 1},{ -3, 4, 1},{ 2, 7, 0}, + { -2, 7, 0},{ 9, 1, 3},{ -9, 1, 3},{ 1,10, 0},{ -1,10, 0} + }, + //level_add + { 0,10, 6, 4, 4, 3, 3, 3, 2, 2, 2,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + 2, //golomb_order + 2, //inc_limit + 10, //max_run + },{ + { //level / run + { 1, 1, 0},{ -1, 1, 0},{ 2, 1, 0},{ -2, 1, 0},{ 3, 1, 0},{ -3, 1, 0}, + { 1, 2, 0},{ -1, 2, 0},{ EOB },{ 4, 1, 0},{ -4, 1, 0},{ 5, 1, 1}, + { -5, 1, 1},{ 2, 2, 0},{ -2, 2, 0},{ 1, 3, 0},{ -1, 3, 0},{ 6, 1, 1}, + { -6, 1, 1},{ 3, 2, 0},{ -3, 2, 0},{ 7, 1, 1},{ -7, 1, 1},{ 1, 4, 0}, + { -1, 4, 0},{ 8, 1, 2},{ -8, 1, 2},{ 2, 3, 0},{ -2, 3, 0},{ 4, 2, 0}, + { -4, 2, 0},{ 1, 5, 0},{ -1, 5, 0},{ 9, 1, 2},{ -9, 1, 2},{ 5, 2, 1}, + { -5, 2, 1},{ 2, 4, 0},{ -2, 4, 0},{ 10, 1, 2},{-10, 1, 2},{ 3, 3, 0}, + { -3, 3, 0},{ 1, 6, 0},{ -1, 6, 0},{ 11, 1, 3},{-11, 1, 3},{ 6, 2, 1}, + { -6, 2, 1},{ 1, 7, 0},{ -1, 7, 0},{ 2, 5, 0},{ -2, 5, 0},{ 3, 4, 0}, + { -3, 4, 0},{ 12, 1, 3},{-12, 1, 3},{ 4, 3, 0},{ -4, 3, 0} + }, + //level_add + { 0,13, 7, 5, 4, 3, 2, 2,-1,-1,-1 -1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + 2, //golomb_order + 4, //inc_limit + 7, //max_run + },{ + { //level / run + { 1, 1, 0},{ -1, 1, 0},{ 2, 1, 0},{ -2, 1, 0},{ 3, 1, 0},{ -3, 1, 0}, + { EOB },{ 4, 1, 0},{ -4, 1, 0},{ 5, 1, 0},{ -5, 1, 0},{ 6, 1, 0}, + { -6, 1, 0},{ 1, 2, 0},{ -1, 2, 0},{ 7, 1, 0},{ -7, 1, 0},{ 8, 1, 1}, + { -8, 1, 1},{ 2, 2, 0},{ -2, 2, 0},{ 9, 1, 1},{ -9, 1, 1},{ 10, 1, 1}, + {-10, 1, 1},{ 1, 3, 0},{ -1, 3, 0},{ 3, 2, 0},{ -3, 2, 0},{ 11, 1, 2}, + {-11, 1, 2},{ 4, 2, 0},{ -4, 2, 0},{ 12, 1, 2},{-12, 1, 2},{ 13, 1, 2}, + {-13, 1, 2},{ 5, 2, 0},{ -5, 2, 0},{ 1, 4, 0},{ -1, 4, 0},{ 2, 3, 0}, + { -2, 3, 0},{ 14, 1, 2},{-14, 1, 2},{ 6, 2, 0},{ -6, 2, 0},{ 15, 1, 2}, + {-15, 1, 2},{ 16, 1, 2},{-16, 1, 2},{ 3, 3, 0},{ -3, 3, 0},{ 1, 5, 0}, + { -1, 5, 0},{ 7, 2, 0},{ -7, 2, 0},{ 17, 1, 2},{-17, 1, 2} + }, + //level_add + { 0,18, 8, 4, 2, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + 2, //golomb_order + 7, //inc_limit + 5, //max_run + },{ + { //level / run + { EOB },{ 1, 1, 0},{ -1, 1, 0},{ 2, 1, 0},{ -2, 1, 0},{ 3, 1, 0}, + { -3, 1, 0},{ 4, 1, 0},{ -4, 1, 0},{ 5, 1, 0},{ -5, 1, 0},{ 6, 1, 0}, + { -6, 1, 0},{ 7, 1, 0},{ -7, 1, 0},{ 8, 1, 0},{ -8, 1, 0},{ 9, 1, 0}, + { -9, 1, 0},{ 10, 1, 0},{-10, 1, 0},{ 1, 2, 0},{ -1, 2, 0},{ 11, 1, 1}, + {-11, 1, 1},{ 12, 1, 1},{-12, 1, 1},{ 13, 1, 1},{-13, 1, 1},{ 2, 2, 0}, + { -2, 2, 0},{ 14, 1, 1},{-14, 1, 1},{ 15, 1, 1},{-15, 1, 1},{ 3, 2, 0}, + { -3, 2, 0},{ 16, 1, 1},{-16, 1, 1},{ 1, 3, 0},{ -1, 3, 0},{ 17, 1, 1}, + {-17, 1, 1},{ 4, 2, 0},{ -4, 2, 0},{ 18, 1, 1},{-18, 1, 1},{ 5, 2, 0}, + { -5, 2, 0},{ 19, 1, 1},{-19, 1, 1},{ 20, 1, 1},{-20, 1, 1},{ 6, 2, 0}, + { -6, 2, 0},{ 21, 1, 1},{-21, 1, 1},{ 2, 3, 0},{ -2, 3, 0} + }, + //level_add + { 0,22, 7, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + 2, //golomb_order + 10, //inc_limit + 3, //max_run + },{ + { //level / run + { EOB },{ 1, 1, 0},{ -1, 1, 0},{ 2, 1, 0},{ -2, 1, 0},{ 3, 1, 0}, + { -3, 1, 0},{ 4, 1, 0},{ -4, 1, 0},{ 5, 1, 0},{ -5, 1, 0},{ 6, 1, 0}, + { -6, 1, 0},{ 7, 1, 0},{ -7, 1, 0},{ 8, 1, 0},{ -8, 1, 0},{ 9, 1, 0}, + { -9, 1, 0},{ 10, 1, 0},{-10, 1, 0},{ 11, 1, 0},{-11, 1, 0},{ 12, 1, 0}, + {-12, 1, 0},{ 13, 1, 0},{-13, 1, 0},{ 14, 1, 0},{-14, 1, 0},{ 15, 1, 0}, + {-15, 1, 0},{ 16, 1, 0},{-16, 1, 0},{ 1, 2, 0},{ -1, 2, 0},{ 17, 1, 0}, + {-17, 1, 0},{ 18, 1, 0},{-18, 1, 0},{ 19, 1, 0},{-19, 1, 0},{ 20, 1, 0}, + {-20, 1, 0},{ 21, 1, 0},{-21, 1, 0},{ 2, 2, 0},{ -2, 2, 0},{ 22, 1, 0}, + {-22, 1, 0},{ 23, 1, 0},{-23, 1, 0},{ 24, 1, 0},{-24, 1, 0},{ 25, 1, 0}, + {-25, 1, 0},{ 3, 2, 0},{ -3, 2, 0},{ 26, 1, 0},{-26, 1, 0} + }, + //level_add + { 0,27, 4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + 2, //golomb_order + INT_MAX, //inc_limit + 2, //max_run + } +}; + +const dec_2dvlc_t ff_cavs_inter_dec[7] = { + { + { //level / run + { 1, 1, 1},{ -1, 1, 1},{ 1, 2, 1},{ -1, 2, 1},{ 1, 3, 1},{ -1, 3, 1}, + { 1, 4, 1},{ -1, 4, 1},{ 1, 5, 1},{ -1, 5, 1},{ 1, 6, 1},{ -1, 6, 1}, + { 1, 7, 1},{ -1, 7, 1},{ 1, 8, 1},{ -1, 8, 1},{ 1, 9, 1},{ -1, 9, 1}, + { 1,10, 1},{ -1,10, 1},{ 1,11, 1},{ -1,11, 1},{ 1,12, 1},{ -1,12, 1}, + { 1,13, 1},{ -1,13, 1},{ 2, 1, 2},{ -2, 1, 2},{ 1,14, 1},{ -1,14, 1}, + { 1,15, 1},{ -1,15, 1},{ 1,16, 1},{ -1,16, 1},{ 1,17, 1},{ -1,17, 1}, + { 1,18, 1},{ -1,18, 1},{ 1,19, 1},{ -1,19, 1},{ 3, 1, 3},{ -3, 1, 3}, + { 1,20, 1},{ -1,20, 1},{ 1,21, 1},{ -1,21, 1},{ 2, 2, 2},{ -2, 2, 2}, + { 1,22, 1},{ -1,22, 1},{ 1,23, 1},{ -1,23, 1},{ 1,24, 1},{ -1,24, 1}, + { 1,25, 1},{ -1,25, 1},{ 1,26, 1},{ -1,26, 1},{ EOB } + }, + //level_add + { 0, 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, + 3, //golomb_order + 0, //inc_limit + 26 //max_run + },{ + { //level / run + { 1, 1, 0},{ -1, 1, 0},{ EOB },{ 1, 2, 0},{ -1, 2, 0},{ 1, 3, 0}, + { -1, 3, 0},{ 1, 4, 0},{ -1, 4, 0},{ 1, 5, 0},{ -1, 5, 0},{ 1, 6, 0}, + { -1, 6, 0},{ 2, 1, 1},{ -2, 1, 1},{ 1, 7, 0},{ -1, 7, 0},{ 1, 8, 0}, + { -1, 8, 0},{ 1, 9, 0},{ -1, 9, 0},{ 1,10, 0},{ -1,10, 0},{ 2, 2, 1}, + { -2, 2, 1},{ 1,11, 0},{ -1,11, 0},{ 1,12, 0},{ -1,12, 0},{ 3, 1, 2}, + { -3, 1, 2},{ 1,13, 0},{ -1,13, 0},{ 1,14, 0},{ -1,14, 0},{ 2, 3, 1}, + { -2, 3, 1},{ 1,15, 0},{ -1,15, 0},{ 2, 4, 1},{ -2, 4, 1},{ 1,16, 0}, + { -1,16, 0},{ 2, 5, 1},{ -2, 5, 1},{ 1,17, 0},{ -1,17, 0},{ 4, 1, 3}, + { -4, 1, 3},{ 2, 6, 1},{ -2, 6, 1},{ 1,18, 0},{ -1,18, 0},{ 1,19, 0}, + { -1,19, 0},{ 2, 7, 1},{ -2, 7, 1},{ 3, 2, 2},{ -3, 2, 2} + }, + //level_add + { 0, 5, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2,-1,-1,-1,-1,-1,-1,-1}, + 2, //golomb_order + 1, //inc_limit + 19 //max_run + },{ + { //level / run + { 1, 1, 0},{ -1, 1, 0},{ EOB },{ 1, 2, 0},{ -1, 2, 0},{ 2, 1, 0}, + { -2, 1, 0},{ 1, 3, 0},{ -1, 3, 0},{ 1, 4, 0},{ -1, 4, 0},{ 3, 1, 1}, + { -3, 1, 1},{ 2, 2, 0},{ -2, 2, 0},{ 1, 5, 0},{ -1, 5, 0},{ 1, 6, 0}, + { -1, 6, 0},{ 1, 7, 0},{ -1, 7, 0},{ 2, 3, 0},{ -2, 3, 0},{ 4, 1, 2}, + { -4, 1, 2},{ 1, 8, 0},{ -1, 8, 0},{ 3, 2, 1},{ -3, 2, 1},{ 2, 4, 0}, + { -2, 4, 0},{ 1, 9, 0},{ -1, 9, 0},{ 1,10, 0},{ -1,10, 0},{ 5, 1, 2}, + { -5, 1, 2},{ 2, 5, 0},{ -2, 5, 0},{ 1,11, 0},{ -1,11, 0},{ 2, 6, 0}, + { -2, 6, 0},{ 1,12, 0},{ -1,12, 0},{ 3, 3, 1},{ -3, 3, 1},{ 6, 1, 2}, + { -6, 1, 2},{ 4, 2, 2},{ -4, 2, 2},{ 1,13, 0},{ -1,13, 0},{ 2, 7, 0}, + { -2, 7, 0},{ 3, 4, 1},{ -3, 4, 1},{ 1,14, 0},{ -1,14, 0} + }, + //level_add + { 0, 7, 5, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + 2, //golomb_order + 2, //inc_limit + 14 //max_run + },{ + { //level / run + { 1, 1, 0},{ -1, 1, 0},{ EOB },{ 2, 1, 0},{ -2, 1, 0},{ 1, 2, 0}, + { -1, 2, 0},{ 3, 1, 0},{ -3, 1, 0},{ 1, 3, 0},{ -1, 3, 0},{ 2, 2, 0}, + { -2, 2, 0},{ 4, 1, 1},{ -4, 1, 1},{ 1, 4, 0},{ -1, 4, 0},{ 5, 1, 1}, + { -5, 1, 1},{ 1, 5, 0},{ -1, 5, 0},{ 3, 2, 0},{ -3, 2, 0},{ 2, 3, 0}, + { -2, 3, 0},{ 1, 6, 0},{ -1, 6, 0},{ 6, 1, 1},{ -6, 1, 1},{ 2, 4, 0}, + { -2, 4, 0},{ 1, 7, 0},{ -1, 7, 0},{ 4, 2, 1},{ -4, 2, 1},{ 7, 1, 2}, + { -7, 1, 2},{ 3, 3, 0},{ -3, 3, 0},{ 1, 8, 0},{ -1, 8, 0},{ 2, 5, 0}, + { -2, 5, 0},{ 8, 1, 2},{ -8, 1, 2},{ 1, 9, 0},{ -1, 9, 0},{ 3, 4, 0}, + { -3, 4, 0},{ 2, 6, 0},{ -2, 6, 0},{ 5, 2, 1},{ -5, 2, 1},{ 1,10, 0}, + { -1,10, 0},{ 9, 1, 2},{ -9, 1, 2},{ 4, 3, 1},{ -4, 3, 1} + }, + //level_add + { 0,10, 6, 5, 4, 3, 3, 2, 2, 2, 2,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + 2, //golomb_order + 3, //inc_limit + 10 //max_run + },{ + { //level / run + { 1, 1, 0},{ -1, 1, 0},{ EOB },{ 2, 1, 0},{ -2, 1, 0},{ 3, 1, 0}, + { -3, 1, 0},{ 1, 2, 0},{ -1, 2, 0},{ 4, 1, 0},{ -4, 1, 0},{ 5, 1, 0}, + { -5, 1, 0},{ 2, 2, 0},{ -2, 2, 0},{ 1, 3, 0},{ -1, 3, 0},{ 6, 1, 0}, + { -6, 1, 0},{ 3, 2, 0},{ -3, 2, 0},{ 7, 1, 1},{ -7, 1, 1},{ 1, 4, 0}, + { -1, 4, 0},{ 8, 1, 1},{ -8, 1, 1},{ 2, 3, 0},{ -2, 3, 0},{ 4, 2, 0}, + { -4, 2, 0},{ 1, 5, 0},{ -1, 5, 0},{ 9, 1, 1},{ -9, 1, 1},{ 5, 2, 0}, + { -5, 2, 0},{ 2, 4, 0},{ -2, 4, 0},{ 1, 6, 0},{ -1, 6, 0},{ 10, 1, 2}, + {-10, 1, 2},{ 3, 3, 0},{ -3, 3, 0},{ 11, 1, 2},{-11, 1, 2},{ 1, 7, 0}, + { -1, 7, 0},{ 6, 2, 0},{ -6, 2, 0},{ 3, 4, 0},{ -3, 4, 0},{ 2, 5, 0}, + { -2, 5, 0},{ 12, 1, 2},{-12, 1, 2},{ 4, 3, 0},{ -4, 3, 0} + }, + //level_add + { 0,13, 7, 5, 4, 3, 2, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + 2, //golomb_order + 6, //inc_limit + 7 //max_run + },{ + { //level / run + { EOB },{ 1, 1, 0},{ -1, 1, 0},{ 2, 1, 0},{ -2, 1, 0},{ 3, 1, 0}, + { -3, 1, 0},{ 4, 1, 0},{ -4, 1, 0},{ 5, 1, 0},{ -5, 1, 0},{ 1, 2, 0}, + { -1, 2, 0},{ 6, 1, 0},{ -6, 1, 0},{ 7, 1, 0},{ -7, 1, 0},{ 8, 1, 0}, + { -8, 1, 0},{ 2, 2, 0},{ -2, 2, 0},{ 9, 1, 0},{ -9, 1, 0},{ 1, 3, 0}, + { -1, 3, 0},{ 10, 1, 1},{-10, 1, 1},{ 3, 2, 0},{ -3, 2, 0},{ 11, 1, 1}, + {-11, 1, 1},{ 4, 2, 0},{ -4, 2, 0},{ 12, 1, 1},{-12, 1, 1},{ 1, 4, 0}, + { -1, 4, 0},{ 2, 3, 0},{ -2, 3, 0},{ 13, 1, 1},{-13, 1, 1},{ 5, 2, 0}, + { -5, 2, 0},{ 14, 1, 1},{-14, 1, 1},{ 6, 2, 0},{ -6, 2, 0},{ 1, 5, 0}, + { -1, 5, 0},{ 15, 1, 1},{-15, 1, 1},{ 3, 3, 0},{ -3, 3, 0},{ 16, 1, 1}, + {-16, 1, 1},{ 2, 4, 0},{ -2, 4, 0},{ 7, 2, 0},{ -7, 2, 0} + }, + //level_add + { 0,17, 8, 4, 3, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + 2, //golomb_order + 9, //inc_limit + 5 //max_run + },{ + { //level / run + { EOB },{ 1, 1, 0},{ -1, 1, 0},{ 2, 1, 0},{ -2, 1, 0},{ 3, 1, 0}, + { -3, 1, 0},{ 4, 1, 0},{ -4, 1, 0},{ 5, 1, 0},{ -5, 1, 0},{ 6, 1, 0}, + { -6, 1, 0},{ 7, 1, 0},{ -7, 1, 0},{ 1, 2, 0},{ -1, 2, 0},{ 8, 1, 0}, + { -8, 1, 0},{ 9, 1, 0},{ -9, 1, 0},{ 10, 1, 0},{-10, 1, 0},{ 11, 1, 0}, + {-11, 1, 0},{ 12, 1, 0},{-12, 1, 0},{ 2, 2, 0},{ -2, 2, 0},{ 13, 1, 0}, + {-13, 1, 0},{ 1, 3, 0},{ -1, 3, 0},{ 14, 1, 0},{-14, 1, 0},{ 15, 1, 0}, + {-15, 1, 0},{ 3, 2, 0},{ -3, 2, 0},{ 16, 1, 0},{-16, 1, 0},{ 17, 1, 0}, + {-17, 1, 0},{ 18, 1, 0},{-18, 1, 0},{ 4, 2, 0},{ -4, 2, 0},{ 19, 1, 0}, + {-19, 1, 0},{ 20, 1, 0},{-20, 1, 0},{ 2, 3, 0},{ -2, 3, 0},{ 1, 4, 0}, + { -1, 4, 0},{ 5, 2, 0},{ -5, 2, 0},{ 21, 1, 0},{-21, 1, 0} + }, + //level_add + { 0,22, 6, 3, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + 2, //golomb_order + INT_MAX, //inc_limit + 4 //max_run + } +}; + +const dec_2dvlc_t ff_cavs_chroma_dec[5] = { + { + { //level / run + { 1, 1, 1},{ -1, 1, 1},{ 1, 2, 1},{ -1, 2, 1},{ 1, 3, 1},{ -1, 3, 1}, + { 1, 4, 1},{ -1, 4, 1},{ 1, 5, 1},{ -1, 5, 1},{ 1, 6, 1},{ -1, 6, 1}, + { 1, 7, 1},{ -1, 7, 1},{ 2, 1, 2},{ -2, 1, 2},{ 1, 8, 1},{ -1, 8, 1}, + { 1, 9, 1},{ -1, 9, 1},{ 1,10, 1},{ -1,10, 1},{ 1,11, 1},{ -1,11, 1}, + { 1,12, 1},{ -1,12, 1},{ 1,13, 1},{ -1,13, 1},{ 1,14, 1},{ -1,14, 1}, + { 1,15, 1},{ -1,15, 1},{ 3, 1, 3},{ -3, 1, 3},{ 1,16, 1},{ -1,16, 1}, + { 1,17, 1},{ -1,17, 1},{ 1,18, 1},{ -1,18, 1},{ 1,19, 1},{ -1,19, 1}, + { 1,20, 1},{ -1,20, 1},{ 1,21, 1},{ -1,21, 1},{ 1,22, 1},{ -1,22, 1}, + { 2, 2, 2},{ -2, 2, 2},{ 1,23, 1},{ -1,23, 1},{ 1,24, 1},{ -1,24, 1}, + { 1,25, 1},{ -1,25, 1},{ 4, 1, 3},{ -4, 1, 3},{ EOB } + }, + //level_add + { 0, 5, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2,-1}, + 2, //golomb_order + 0, //inc_limit + 25 //max_run + },{ + { //level / run + { EOB },{ 1, 1, 0},{ -1, 1, 0},{ 1, 2, 0},{ -1, 2, 0},{ 2, 1, 1}, + { -2, 1, 1},{ 1, 3, 0},{ -1, 3, 0},{ 1, 4, 0},{ -1, 4, 0},{ 1, 5, 0}, + { -1, 5, 0},{ 1, 6, 0},{ -1, 6, 0},{ 3, 1, 2},{ -3, 1, 2},{ 1, 7, 0}, + { -1, 7, 0},{ 1, 8, 0},{ -1, 8, 0},{ 2, 2, 1},{ -2, 2, 1},{ 1, 9, 0}, + { -1, 9, 0},{ 1,10, 0},{ -1,10, 0},{ 1,11, 0},{ -1,11, 0},{ 4, 1, 2}, + { -4, 1, 2},{ 1,12, 0},{ -1,12, 0},{ 1,13, 0},{ -1,13, 0},{ 1,14, 0}, + { -1,14, 0},{ 2, 3, 1},{ -2, 3, 1},{ 1,15, 0},{ -1,15, 0},{ 2, 4, 1}, + { -2, 4, 1},{ 5, 1, 3},{ -5, 1, 3},{ 3, 2, 2},{ -3, 2, 2},{ 1,16, 0}, + { -1,16, 0},{ 1,17, 0},{ -1,17, 0},{ 1,18, 0},{ -1,18, 0},{ 2, 5, 1}, + { -2, 5, 1},{ 1,19, 0},{ -1,19, 0},{ 1,20, 0},{ -1,20, 0} + }, + //level_add + { 0, 6, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2,-1,-1,-1,-1,-1,-1}, + 0, //golomb_order + 1, //inc_limit + 20 //max_run + },{ + { //level / run + { 1, 1, 0},{ -1, 1, 0},{ EOB },{ 2, 1, 0},{ -2, 1, 0},{ 1, 2, 0}, + { -1, 2, 0},{ 3, 1, 1},{ -3, 1, 1},{ 1, 3, 0},{ -1, 3, 0},{ 4, 1, 1}, + { -4, 1, 1},{ 2, 2, 0},{ -2, 2, 0},{ 1, 4, 0},{ -1, 4, 0},{ 5, 1, 2}, + { -5, 1, 2},{ 1, 5, 0},{ -1, 5, 0},{ 3, 2, 1},{ -3, 2, 1},{ 2, 3, 0}, + { -2, 3, 0},{ 1, 6, 0},{ -1, 6, 0},{ 6, 1, 2},{ -6, 1, 2},{ 1, 7, 0}, + { -1, 7, 0},{ 2, 4, 0},{ -2, 4, 0},{ 7, 1, 2},{ -7, 1, 2},{ 1, 8, 0}, + { -1, 8, 0},{ 4, 2, 1},{ -4, 2, 1},{ 1, 9, 0},{ -1, 9, 0},{ 3, 3, 1}, + { -3, 3, 1},{ 2, 5, 0},{ -2, 5, 0},{ 2, 6, 0},{ -2, 6, 0},{ 8, 1, 2}, + { -8, 1, 2},{ 1,10, 0},{ -1,10, 0},{ 1,11, 0},{ -1,11, 0},{ 9, 1, 2}, + { -9, 1, 2},{ 5, 2, 2},{ -5, 2, 2},{ 3, 4, 1},{ -3, 4, 1}, + }, + //level_add + { 0,10, 6, 4, 4, 3, 3, 2, 2, 2, 2, 2,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + 1, //golomb_order + 2, //inc_limit + 11 //max_run + },{ + { //level / run + { EOB },{ 1, 1, 0},{ -1, 1, 0},{ 2, 1, 0},{ -2, 1, 0},{ 3, 1, 0}, + { -3, 1, 0},{ 4, 1, 0},{ -4, 1, 0},{ 1, 2, 0},{ -1, 2, 0},{ 5, 1, 1}, + { -5, 1, 1},{ 2, 2, 0},{ -2, 2, 0},{ 6, 1, 1},{ -6, 1, 1},{ 1, 3, 0}, + { -1, 3, 0},{ 7, 1, 1},{ -7, 1, 1},{ 3, 2, 0},{ -3, 2, 0},{ 8, 1, 1}, + { -8, 1, 1},{ 1, 4, 0},{ -1, 4, 0},{ 2, 3, 0},{ -2, 3, 0},{ 9, 1, 1}, + { -9, 1, 1},{ 4, 2, 0},{ -4, 2, 0},{ 1, 5, 0},{ -1, 5, 0},{ 10, 1, 1}, + {-10, 1, 1},{ 3, 3, 0},{ -3, 3, 0},{ 5, 2, 1},{ -5, 2, 1},{ 2, 4, 0}, + { -2, 4, 0},{ 11, 1, 1},{-11, 1, 1},{ 1, 6, 0},{ -1, 6, 0},{ 12, 1, 1}, + {-12, 1, 1},{ 1, 7, 0},{ -1, 7, 0},{ 6, 2, 1},{ -6, 2, 1},{ 13, 1, 1}, + {-13, 1, 1},{ 2, 5, 0},{ -2, 5, 0},{ 1, 8, 0},{ -1, 8, 0}, + }, + //level_add + { 0,14, 7, 4, 3, 3, 2, 2, 2,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + 1, //golomb_order + 4, //inc_limit + 8 //max_run + },{ + { //level / run + { EOB },{ 1, 1, 0},{ -1, 1, 0},{ 2, 1, 0},{ -2, 1, 0},{ 3, 1, 0}, + { -3, 1, 0},{ 4, 1, 0},{ -4, 1, 0},{ 5, 1, 0},{ -5, 1, 0},{ 6, 1, 0}, + { -6, 1, 0},{ 7, 1, 0},{ -7, 1, 0},{ 8, 1, 0},{ -8, 1, 0},{ 1, 2, 0}, + { -1, 2, 0},{ 9, 1, 0},{ -9, 1, 0},{ 10, 1, 0},{-10, 1, 0},{ 11, 1, 0}, + {-11, 1, 0},{ 2, 2, 0},{ -2, 2, 0},{ 12, 1, 0},{-12, 1, 0},{ 13, 1, 0}, + {-13, 1, 0},{ 3, 2, 0},{ -3, 2, 0},{ 14, 1, 0},{-14, 1, 0},{ 1, 3, 0}, + { -1, 3, 0},{ 15, 1, 0},{-15, 1, 0},{ 4, 2, 0},{ -4, 2, 0},{ 16, 1, 0}, + {-16, 1, 0},{ 17, 1, 0},{-17, 1, 0},{ 5, 2, 0},{ -5, 2, 0},{ 1, 4, 0}, + { -1, 4, 0},{ 2, 3, 0},{ -2, 3, 0},{ 18, 1, 0},{-18, 1, 0},{ 6, 2, 0}, + { -6, 2, 0},{ 19, 1, 0},{-19, 1, 0},{ 1, 5, 0},{ -1, 5, 0}, + }, + //level_add + { 0,20, 7, 3, 2, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, + 0, //golomb_order + INT_MAX, //inc_limit + 5, //max_run + } +}; + +#undef EOB + +static const uint8_t alpha_tab[64] = { + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, + 4, 4, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 20, + 22, 24, 26, 28, 30, 33, 33, 35, 35, 36, 37, 37, 39, 39, 42, 44, + 46, 48, 50, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 +}; + +static const uint8_t beta_tab[64] = { + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, + 6, 7, 7, 7, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 23, 24, 24, 25, 25, 26, 27 +}; + +static const uint8_t tc_tab[64] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, + 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9 +}; + +const int_fast8_t ff_left_modifier_l[8] = { 0,-1, 6,-1,-1, 7, 6, 7}; +const int_fast8_t ff_top_modifier_l[8] = {-1, 1, 5,-1,-1, 5, 7, 7}; +const int_fast8_t ff_left_modifier_c[7] = { 5,-1, 2,-1, 6, 5, 6}; +const int_fast8_t ff_top_modifier_c[7] = { 4, 1,-1,-1, 4, 6, 6}; + +#endif /* FFMPEG_CAVSDATA_H */ diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/cavsdec.c b/src/add-ons/media/plugins/avcodec/libavcodec/cavsdec.c new file mode 100644 index 0000000000..a978fe1a1a --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/cavsdec.c @@ -0,0 +1,703 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder. + * Copyright (c) 2006 Stefan Gehrer + * + * This file is part of FFmpeg. + * + * FFmpeg 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.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file cavs.c + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder + * @author Stefan Gehrer + */ + +#include "avcodec.h" +#include "bitstream.h" +#include "golomb.h" +#include "cavs.h" + +static const uint8_t mv_scan[4] = { + MV_FWD_X0,MV_FWD_X1, + MV_FWD_X2,MV_FWD_X3 +}; + +static const uint8_t cbp_tab[64][2] = { + {63, 0},{15,15},{31,63},{47,31},{ 0,16},{14,32},{13,47},{11,13}, + { 7,14},{ 5,11},{10,12},{ 8, 5},{12,10},{61, 7},{ 4,48},{55, 3}, + { 1, 2},{ 2, 8},{59, 4},{ 3, 1},{62,61},{ 9,55},{ 6,59},{29,62}, + {45,29},{51,27},{23,23},{39,19},{27,30},{46,28},{53, 9},{30, 6}, + {43,60},{37,21},{60,44},{16,26},{21,51},{28,35},{19,18},{35,20}, + {42,24},{26,53},{44,17},{32,37},{58,39},{24,45},{20,58},{17,43}, + {18,42},{48,46},{22,36},{33,33},{25,34},{49,40},{40,52},{36,49}, + {34,50},{50,56},{52,25},{54,22},{41,54},{56,57},{38,41},{57,38} +}; + +/***************************************************************************** + * + * motion vector prediction + * + ****************************************************************************/ + +static inline void store_mvs(AVSContext *h) { + h->col_mv[(h->mby*h->mb_width + h->mbx)*4 + 0] = h->mv[MV_FWD_X0]; + h->col_mv[(h->mby*h->mb_width + h->mbx)*4 + 1] = h->mv[MV_FWD_X1]; + h->col_mv[(h->mby*h->mb_width + h->mbx)*4 + 2] = h->mv[MV_FWD_X2]; + h->col_mv[(h->mby*h->mb_width + h->mbx)*4 + 3] = h->mv[MV_FWD_X3]; +} + +static inline void mv_pred_direct(AVSContext *h, vector_t *pmv_fw, + vector_t *col_mv) { + vector_t *pmv_bw = pmv_fw + MV_BWD_OFFS; + int den = h->direct_den[col_mv->ref]; + int m = col_mv->x >> 31; + + pmv_fw->dist = h->dist[1]; + pmv_bw->dist = h->dist[0]; + pmv_fw->ref = 1; + pmv_bw->ref = 0; + /* scale the co-located motion vector according to its temporal span */ + pmv_fw->x = (((den+(den*col_mv->x*pmv_fw->dist^m)-m-1)>>14)^m)-m; + pmv_bw->x = m-(((den+(den*col_mv->x*pmv_bw->dist^m)-m-1)>>14)^m); + m = col_mv->y >> 31; + pmv_fw->y = (((den+(den*col_mv->y*pmv_fw->dist^m)-m-1)>>14)^m)-m; + pmv_bw->y = m-(((den+(den*col_mv->y*pmv_bw->dist^m)-m-1)>>14)^m); +} + +static inline void mv_pred_sym(AVSContext *h, vector_t *src, enum block_t size) { + vector_t *dst = src + MV_BWD_OFFS; + + /* backward mv is the scaled and negated forward mv */ + dst->x = -((src->x * h->sym_factor + 256) >> 9); + dst->y = -((src->y * h->sym_factor + 256) >> 9); + dst->ref = 0; + dst->dist = h->dist[0]; + set_mvs(dst, size); +} + +/***************************************************************************** + * + * residual data decoding + * + ****************************************************************************/ + +/** kth-order exponential golomb code */ +static inline int get_ue_code(GetBitContext *gb, int order) { + if(order) { + int ret = get_ue_golomb(gb) << order; + return ret + get_bits(gb,order); + } + return get_ue_golomb(gb); +} + +/** + * decode coefficients from one 8x8 block, dequantize, inverse transform + * and add them to sample block + * @param r pointer to 2D VLC table + * @param esc_golomb_order escape codes are k-golomb with this order k + * @param qp quantizer + * @param dst location of sample block + * @param stride line stride in frame buffer + */ +static int decode_residual_block(AVSContext *h, GetBitContext *gb, + const dec_2dvlc_t *r, int esc_golomb_order, + int qp, uint8_t *dst, int stride) { + int i, level_code, esc_code, level, run, mask; + DCTELEM level_buf[65]; + uint8_t run_buf[65]; + DCTELEM *block = h->block; + + for(i=0;i<65;i++) { + level_code = get_ue_code(gb,r->golomb_order); + if(level_code >= ESCAPE_CODE) { + run = ((level_code - ESCAPE_CODE) >> 1) + 1; + esc_code = get_ue_code(gb,esc_golomb_order); + level = esc_code + (run > r->max_run ? 1 : r->level_add[run]); + while(level > r->inc_limit) + r++; + mask = -(level_code & 1); + level = (level^mask) - mask; + } else { + level = r->rltab[level_code][0]; + if(!level) //end of block signal + break; + run = r->rltab[level_code][1]; + r += r->rltab[level_code][2]; + } + level_buf[i] = level; + run_buf[i] = run; + } + if(dequant(h,level_buf, run_buf, block, ff_cavs_dequant_mul[qp], + ff_cavs_dequant_shift[qp], i)) + return -1; + h->s.dsp.cavs_idct8_add(dst,block,stride); + return 0; +} + + +static inline void decode_residual_chroma(AVSContext *h) { + if(h->cbp & (1<<4)) + decode_residual_block(h,&h->s.gb,ff_cavs_chroma_dec,0, + ff_cavs_chroma_qp[h->qp],h->cu,h->c_stride); + if(h->cbp & (1<<5)) + decode_residual_block(h,&h->s.gb,ff_cavs_chroma_dec,0, + ff_cavs_chroma_qp[h->qp],h->cv,h->c_stride); +} + +static inline int decode_residual_inter(AVSContext *h) { + int block; + + /* get coded block pattern */ + int cbp= get_ue_golomb(&h->s.gb); + if(cbp > 63){ + av_log(h->s.avctx, AV_LOG_ERROR, "illegal inter cbp\n"); + return -1; + } + h->cbp = cbp_tab[cbp][1]; + + /* get quantizer */ + if(h->cbp && !h->qp_fixed) + h->qp = (h->qp + get_se_golomb(&h->s.gb)) & 63; + for(block=0;block<4;block++) + if(h->cbp & (1<s.gb,ff_cavs_inter_dec,0,h->qp, + h->cy + h->luma_scan[block], h->l_stride); + decode_residual_chroma(h); + + return 0; +} + +/***************************************************************************** + * + * macroblock level + * + ****************************************************************************/ + +static int decode_mb_i(AVSContext *h, int cbp_code) { + GetBitContext *gb = &h->s.gb; + int block, pred_mode_uv; + uint8_t top[18]; + uint8_t *left = NULL; + uint8_t *d; + + ff_cavs_init_mb(h); + + /* get intra prediction modes from stream */ + for(block=0;block<4;block++) { + int nA,nB,predpred; + int pos = ff_cavs_scan3x3[block]; + + nA = h->pred_mode_Y[pos-1]; + nB = h->pred_mode_Y[pos-3]; + predpred = FFMIN(nA,nB); + if(predpred == NOT_AVAIL) // if either is not available + predpred = INTRA_L_LP; + if(!get_bits1(gb)){ + int rem_mode= get_bits(gb, 2); + predpred = rem_mode + (rem_mode >= predpred); + } + h->pred_mode_Y[pos] = predpred; + } + pred_mode_uv = get_ue_golomb(gb); + if(pred_mode_uv > 6) { + av_log(h->s.avctx, AV_LOG_ERROR, "illegal intra chroma pred mode\n"); + return -1; + } + ff_cavs_modify_mb_i(h, &pred_mode_uv); + + /* get coded block pattern */ + if(h->pic_type == FF_I_TYPE) + cbp_code = get_ue_golomb(gb); + if(cbp_code > 63){ + av_log(h->s.avctx, AV_LOG_ERROR, "illegal intra cbp\n"); + return -1; + } + h->cbp = cbp_tab[cbp_code][0]; + if(h->cbp && !h->qp_fixed) + h->qp = (h->qp + get_se_golomb(gb)) & 63; //qp_delta + + /* luma intra prediction interleaved with residual decode/transform/add */ + for(block=0;block<4;block++) { + d = h->cy + h->luma_scan[block]; + ff_cavs_load_intra_pred_luma(h, top, &left, block); + h->intra_pred_l[h->pred_mode_Y[ff_cavs_scan3x3[block]]] + (d, top, left, h->l_stride); + if(h->cbp & (1<qp,d,h->l_stride); + } + + /* chroma intra prediction */ + ff_cavs_load_intra_pred_chroma(h); + h->intra_pred_c[pred_mode_uv](h->cu, &h->top_border_u[h->mbx*10], + h->left_border_u, h->c_stride); + h->intra_pred_c[pred_mode_uv](h->cv, &h->top_border_v[h->mbx*10], + h->left_border_v, h->c_stride); + + decode_residual_chroma(h); + ff_cavs_filter(h,I_8X8); + set_mv_intra(h); + return 0; +} + +static void decode_mb_p(AVSContext *h, enum mb_t mb_type) { + GetBitContext *gb = &h->s.gb; + int ref[4]; + + ff_cavs_init_mb(h); + switch(mb_type) { + case P_SKIP: + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_PSKIP, BLK_16X16, 0); + break; + case P_16X16: + ref[0] = h->ref_flag ? 0 : get_bits1(gb); + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16,ref[0]); + break; + case P_16X8: + ref[0] = h->ref_flag ? 0 : get_bits1(gb); + ref[2] = h->ref_flag ? 0 : get_bits1(gb); + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_TOP, BLK_16X8, ref[0]); + ff_cavs_mv(h, MV_FWD_X2, MV_FWD_A1, MV_PRED_LEFT, BLK_16X8, ref[2]); + break; + case P_8X16: + ref[0] = h->ref_flag ? 0 : get_bits1(gb); + ref[1] = h->ref_flag ? 0 : get_bits1(gb); + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_B3, MV_PRED_LEFT, BLK_8X16, ref[0]); + ff_cavs_mv(h, MV_FWD_X1, MV_FWD_C2, MV_PRED_TOPRIGHT,BLK_8X16, ref[1]); + break; + case P_8X8: + ref[0] = h->ref_flag ? 0 : get_bits1(gb); + ref[1] = h->ref_flag ? 0 : get_bits1(gb); + ref[2] = h->ref_flag ? 0 : get_bits1(gb); + ref[3] = h->ref_flag ? 0 : get_bits1(gb); + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_B3, MV_PRED_MEDIAN, BLK_8X8, ref[0]); + ff_cavs_mv(h, MV_FWD_X1, MV_FWD_C2, MV_PRED_MEDIAN, BLK_8X8, ref[1]); + ff_cavs_mv(h, MV_FWD_X2, MV_FWD_X1, MV_PRED_MEDIAN, BLK_8X8, ref[2]); + ff_cavs_mv(h, MV_FWD_X3, MV_FWD_X0, MV_PRED_MEDIAN, BLK_8X8, ref[3]); + } + ff_cavs_inter(h, mb_type); + set_intra_mode_default(h); + store_mvs(h); + if(mb_type != P_SKIP) + decode_residual_inter(h); + ff_cavs_filter(h,mb_type); + *h->col_type = mb_type; +} + +static void decode_mb_b(AVSContext *h, enum mb_t mb_type) { + int block; + enum sub_mb_t sub_type[4]; + int flags; + + ff_cavs_init_mb(h); + + /* reset all MVs */ + h->mv[MV_FWD_X0] = ff_cavs_dir_mv; + set_mvs(&h->mv[MV_FWD_X0], BLK_16X16); + h->mv[MV_BWD_X0] = ff_cavs_dir_mv; + set_mvs(&h->mv[MV_BWD_X0], BLK_16X16); + switch(mb_type) { + case B_SKIP: + case B_DIRECT: + if(!(*h->col_type)) { + /* intra MB at co-location, do in-plane prediction */ + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_BSKIP, BLK_16X16, 1); + ff_cavs_mv(h, MV_BWD_X0, MV_BWD_C2, MV_PRED_BSKIP, BLK_16X16, 0); + } else + /* direct prediction from co-located P MB, block-wise */ + for(block=0;block<4;block++) + mv_pred_direct(h,&h->mv[mv_scan[block]], + &h->col_mv[(h->mby*h->mb_width+h->mbx)*4 + block]); + break; + case B_FWD_16X16: + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, 1); + break; + case B_SYM_16X16: + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, 1); + mv_pred_sym(h, &h->mv[MV_FWD_X0], BLK_16X16); + break; + case B_BWD_16X16: + ff_cavs_mv(h, MV_BWD_X0, MV_BWD_C2, MV_PRED_MEDIAN, BLK_16X16, 0); + break; + case B_8X8: + for(block=0;block<4;block++) + sub_type[block] = get_bits(&h->s.gb,2); + for(block=0;block<4;block++) { + switch(sub_type[block]) { + case B_SUB_DIRECT: + if(!(*h->col_type)) { + /* intra MB at co-location, do in-plane prediction */ + ff_cavs_mv(h, mv_scan[block], mv_scan[block]-3, + MV_PRED_BSKIP, BLK_8X8, 1); + ff_cavs_mv(h, mv_scan[block]+MV_BWD_OFFS, + mv_scan[block]-3+MV_BWD_OFFS, + MV_PRED_BSKIP, BLK_8X8, 0); + } else + mv_pred_direct(h,&h->mv[mv_scan[block]], + &h->col_mv[(h->mby*h->mb_width + h->mbx)*4 + block]); + break; + case B_SUB_FWD: + ff_cavs_mv(h, mv_scan[block], mv_scan[block]-3, + MV_PRED_MEDIAN, BLK_8X8, 1); + break; + case B_SUB_SYM: + ff_cavs_mv(h, mv_scan[block], mv_scan[block]-3, + MV_PRED_MEDIAN, BLK_8X8, 1); + mv_pred_sym(h, &h->mv[mv_scan[block]], BLK_8X8); + break; + } + } + for(block=0;block<4;block++) { + if(sub_type[block] == B_SUB_BWD) + ff_cavs_mv(h, mv_scan[block]+MV_BWD_OFFS, + mv_scan[block]+MV_BWD_OFFS-3, + MV_PRED_MEDIAN, BLK_8X8, 0); + } + break; + default: + assert((mb_type > B_SYM_16X16) && (mb_type < B_8X8)); + flags = ff_cavs_partition_flags[mb_type]; + if(mb_type & 1) { /* 16x8 macroblock types */ + if(flags & FWD0) + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_TOP, BLK_16X8, 1); + if(flags & SYM0) + mv_pred_sym(h, &h->mv[MV_FWD_X0], BLK_16X8); + if(flags & FWD1) + ff_cavs_mv(h, MV_FWD_X2, MV_FWD_A1, MV_PRED_LEFT, BLK_16X8, 1); + if(flags & SYM1) + mv_pred_sym(h, &h->mv[MV_FWD_X2], BLK_16X8); + if(flags & BWD0) + ff_cavs_mv(h, MV_BWD_X0, MV_BWD_C2, MV_PRED_TOP, BLK_16X8, 0); + if(flags & BWD1) + ff_cavs_mv(h, MV_BWD_X2, MV_BWD_A1, MV_PRED_LEFT, BLK_16X8, 0); + } else { /* 8x16 macroblock types */ + if(flags & FWD0) + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_B3, MV_PRED_LEFT, BLK_8X16, 1); + if(flags & SYM0) + mv_pred_sym(h, &h->mv[MV_FWD_X0], BLK_8X16); + if(flags & FWD1) + ff_cavs_mv(h,MV_FWD_X1,MV_FWD_C2,MV_PRED_TOPRIGHT,BLK_8X16,1); + if(flags & SYM1) + mv_pred_sym(h, &h->mv[MV_FWD_X1], BLK_8X16); + if(flags & BWD0) + ff_cavs_mv(h, MV_BWD_X0, MV_BWD_B3, MV_PRED_LEFT, BLK_8X16, 0); + if(flags & BWD1) + ff_cavs_mv(h,MV_BWD_X1,MV_BWD_C2,MV_PRED_TOPRIGHT,BLK_8X16,0); + } + } + ff_cavs_inter(h, mb_type); + set_intra_mode_default(h); + if(mb_type != B_SKIP) + decode_residual_inter(h); + ff_cavs_filter(h,mb_type); +} + +/***************************************************************************** + * + * slice level + * + ****************************************************************************/ + +static inline int decode_slice_header(AVSContext *h, GetBitContext *gb) { + if(h->stc > 0xAF) + av_log(h->s.avctx, AV_LOG_ERROR, "unexpected start code 0x%02x\n", h->stc); + h->mby = h->stc; + if((h->mby == 0) && (!h->qp_fixed)){ + h->qp_fixed = get_bits1(gb); + h->qp = get_bits(gb,6); + } + /* inter frame or second slice can have weighting params */ + if((h->pic_type != FF_I_TYPE) || (!h->pic_structure && h->mby >= h->mb_width/2)) + if(get_bits1(gb)) { //slice_weighting_flag + av_log(h->s.avctx, AV_LOG_ERROR, + "weighted prediction not yet supported\n"); + } + return 0; +} + +static inline void check_for_slice(AVSContext *h) { + GetBitContext *gb = &h->s.gb; + int align; + align = (-get_bits_count(gb)) & 7; + if((show_bits_long(gb,24+align) & 0xFFFFFF) == 0x000001) { + skip_bits_long(gb,24+align); + h->stc = get_bits(gb,8); + decode_slice_header(h,gb); + } +} + +/***************************************************************************** + * + * frame level + * + ****************************************************************************/ + +static int decode_pic(AVSContext *h) { + MpegEncContext *s = &h->s; + int skip_count; + enum mb_t mb_type; + + if (!s->context_initialized) { + s->avctx->idct_algo = FF_IDCT_CAVS; + if (MPV_common_init(s) < 0) + return -1; + ff_init_scantable(s->dsp.idct_permutation,&h->scantable,ff_zigzag_direct); + } + skip_bits(&s->gb,16);//bbv_dwlay + if(h->stc == PIC_PB_START_CODE) { + h->pic_type = get_bits(&s->gb,2) + FF_I_TYPE; + if(h->pic_type > FF_B_TYPE) { + av_log(s->avctx, AV_LOG_ERROR, "illegal picture type\n"); + return -1; + } + /* make sure we have the reference frames we need */ + if(!h->DPB[0].data[0] || + (!h->DPB[1].data[0] && h->pic_type == FF_B_TYPE)) + return -1; + } else { + h->pic_type = FF_I_TYPE; + if(get_bits1(&s->gb)) + skip_bits(&s->gb,16);//time_code + } + /* release last B frame */ + if(h->picture.data[0]) + s->avctx->release_buffer(s->avctx, (AVFrame *)&h->picture); + + s->avctx->get_buffer(s->avctx, (AVFrame *)&h->picture); + ff_cavs_init_pic(h); + h->picture.poc = get_bits(&s->gb,8)*2; + + /* get temporal distances and MV scaling factors */ + if(h->pic_type != FF_B_TYPE) { + h->dist[0] = (h->picture.poc - h->DPB[0].poc + 512) % 512; + } else { + h->dist[0] = (h->DPB[0].poc - h->picture.poc + 512) % 512; + } + h->dist[1] = (h->picture.poc - h->DPB[1].poc + 512) % 512; + h->scale_den[0] = h->dist[0] ? 512/h->dist[0] : 0; + h->scale_den[1] = h->dist[1] ? 512/h->dist[1] : 0; + if(h->pic_type == FF_B_TYPE) { + h->sym_factor = h->dist[0]*h->scale_den[1]; + } else { + h->direct_den[0] = h->dist[0] ? 16384/h->dist[0] : 0; + h->direct_den[1] = h->dist[1] ? 16384/h->dist[1] : 0; + } + + if(s->low_delay) + get_ue_golomb(&s->gb); //bbv_check_times + h->progressive = get_bits1(&s->gb); + if(h->progressive) + h->pic_structure = 1; + else if(!(h->pic_structure = get_bits1(&s->gb) && (h->stc == PIC_PB_START_CODE)) ) + skip_bits1(&s->gb); //advanced_pred_mode_disable + skip_bits1(&s->gb); //top_field_first + skip_bits1(&s->gb); //repeat_first_field + h->qp_fixed = get_bits1(&s->gb); + h->qp = get_bits(&s->gb,6); + if(h->pic_type == FF_I_TYPE) { + if(!h->progressive && !h->pic_structure) + skip_bits1(&s->gb);//what is this? + skip_bits(&s->gb,4); //reserved bits + } else { + if(!(h->pic_type == FF_B_TYPE && h->pic_structure == 1)) + h->ref_flag = get_bits1(&s->gb); + skip_bits(&s->gb,4); //reserved bits + h->skip_mode_flag = get_bits1(&s->gb); + } + h->loop_filter_disable = get_bits1(&s->gb); + if(!h->loop_filter_disable && get_bits1(&s->gb)) { + h->alpha_offset = get_se_golomb(&s->gb); + h->beta_offset = get_se_golomb(&s->gb); + } else { + h->alpha_offset = h->beta_offset = 0; + } + check_for_slice(h); + if(h->pic_type == FF_I_TYPE) { + do { + decode_mb_i(h, 0); + } while(ff_cavs_next_mb(h)); + } else if(h->pic_type == FF_P_TYPE) { + do { + if(h->skip_mode_flag) { + skip_count = get_ue_golomb(&s->gb); + while(skip_count--) { + decode_mb_p(h,P_SKIP); + if(!ff_cavs_next_mb(h)) + goto done; + } + mb_type = get_ue_golomb(&s->gb) + P_16X16; + } else + mb_type = get_ue_golomb(&s->gb) + P_SKIP; + if(mb_type > P_8X8) { + decode_mb_i(h, mb_type - P_8X8 - 1); + } else + decode_mb_p(h,mb_type); + } while(ff_cavs_next_mb(h)); + } else { /* FF_B_TYPE */ + do { + if(h->skip_mode_flag) { + skip_count = get_ue_golomb(&s->gb); + while(skip_count--) { + decode_mb_b(h,B_SKIP); + if(!ff_cavs_next_mb(h)) + goto done; + } + mb_type = get_ue_golomb(&s->gb) + B_DIRECT; + } else + mb_type = get_ue_golomb(&s->gb) + B_SKIP; + if(mb_type > B_8X8) { + decode_mb_i(h, mb_type - B_8X8 - 1); + } else + decode_mb_b(h,mb_type); + } while(ff_cavs_next_mb(h)); + } + done: + if(h->pic_type != FF_B_TYPE) { + if(h->DPB[1].data[0]) + s->avctx->release_buffer(s->avctx, (AVFrame *)&h->DPB[1]); + memcpy(&h->DPB[1], &h->DPB[0], sizeof(Picture)); + memcpy(&h->DPB[0], &h->picture, sizeof(Picture)); + memset(&h->picture,0,sizeof(Picture)); + } + return 0; +} + +/***************************************************************************** + * + * headers and interface + * + ****************************************************************************/ + +static int decode_seq_header(AVSContext *h) { + MpegEncContext *s = &h->s; + int frame_rate_code; + + h->profile = get_bits(&s->gb,8); + h->level = get_bits(&s->gb,8); + skip_bits1(&s->gb); //progressive sequence + s->width = get_bits(&s->gb,14); + s->height = get_bits(&s->gb,14); + skip_bits(&s->gb,2); //chroma format + skip_bits(&s->gb,3); //sample_precision + h->aspect_ratio = get_bits(&s->gb,4); + frame_rate_code = get_bits(&s->gb,4); + skip_bits(&s->gb,18);//bit_rate_lower + skip_bits1(&s->gb); //marker_bit + skip_bits(&s->gb,12);//bit_rate_upper + s->low_delay = get_bits1(&s->gb); + h->mb_width = (s->width + 15) >> 4; + h->mb_height = (s->height + 15) >> 4; + h->s.avctx->time_base.den = ff_frame_rate_tab[frame_rate_code].num; + h->s.avctx->time_base.num = ff_frame_rate_tab[frame_rate_code].den; + h->s.avctx->width = s->width; + h->s.avctx->height = s->height; + if(!h->top_qp) + ff_cavs_init_top_lines(h); + return 0; +} + +static void cavs_flush(AVCodecContext * avctx) { + AVSContext *h = avctx->priv_data; + h->got_keyframe = 0; +} + +static int cavs_decode_frame(AVCodecContext * avctx,void *data, int *data_size, + const uint8_t * buf, int buf_size) { + AVSContext *h = avctx->priv_data; + MpegEncContext *s = &h->s; + int input_size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *picture = data; + uint32_t stc = -1; + + s->avctx = avctx; + + if (buf_size == 0) { + if(!s->low_delay && h->DPB[0].data[0]) { + *data_size = sizeof(AVPicture); + *picture = *(AVFrame *) &h->DPB[0]; + } + return 0; + } + + buf_ptr = buf; + buf_end = buf + buf_size; + for(;;) { + buf_ptr = ff_find_start_code(buf_ptr,buf_end, &stc); + if(stc & 0xFFFFFE00) + return FFMAX(0, buf_ptr - buf - s->parse_context.last_index); + input_size = (buf_end - buf_ptr)*8; + switch(stc) { + case CAVS_START_CODE: + init_get_bits(&s->gb, buf_ptr, input_size); + decode_seq_header(h); + break; + case PIC_I_START_CODE: + if(!h->got_keyframe) { + if(h->DPB[0].data[0]) + avctx->release_buffer(avctx, (AVFrame *)&h->DPB[0]); + if(h->DPB[1].data[0]) + avctx->release_buffer(avctx, (AVFrame *)&h->DPB[1]); + h->got_keyframe = 1; + } + case PIC_PB_START_CODE: + *data_size = 0; + if(!h->got_keyframe) + break; + init_get_bits(&s->gb, buf_ptr, input_size); + h->stc = stc; + if(decode_pic(h)) + break; + *data_size = sizeof(AVPicture); + if(h->pic_type != FF_B_TYPE) { + if(h->DPB[1].data[0]) { + *picture = *(AVFrame *) &h->DPB[1]; + } else { + *data_size = 0; + } + } else + *picture = *(AVFrame *) &h->picture; + break; + case EXT_START_CODE: + //mpeg_decode_extension(avctx,buf_ptr, input_size); + break; + case USER_START_CODE: + //mpeg_decode_user_data(avctx,buf_ptr, input_size); + break; + default: + if (stc >= SLICE_MIN_START_CODE && + stc <= SLICE_MAX_START_CODE) { + init_get_bits(&s->gb, buf_ptr, input_size); + decode_slice_header(h, &s->gb); + } + break; + } + } +} + +AVCodec cavs_decoder = { + "cavs", + CODEC_TYPE_VIDEO, + CODEC_ID_CAVS, + sizeof(AVSContext), + ff_cavs_init, + NULL, + ff_cavs_end, + cavs_decode_frame, + CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .flush= cavs_flush, + .long_name= NULL_IF_CONFIG_SMALL("Chinese AVS video (AVS1-P2, JiZhun profile)"), +}; diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/cavsdsp.c b/src/add-ons/media/plugins/avcodec/libavcodec/cavsdsp.c new file mode 100644 index 0000000000..fd744cc808 --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/cavsdsp.c @@ -0,0 +1,546 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder. + * + * DSP functions + * + * Copyright (c) 2006 Stefan Gehrer + * + * This file is part of FFmpeg. + * + * FFmpeg 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.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "dsputil.h" + +/***************************************************************************** + * + * in-loop deblocking filter + * + ****************************************************************************/ + +#define P2 p0_p[-3*stride] +#define P1 p0_p[-2*stride] +#define P0 p0_p[-1*stride] +#define Q0 p0_p[ 0*stride] +#define Q1 p0_p[ 1*stride] +#define Q2 p0_p[ 2*stride] + +static inline void loop_filter_l2(uint8_t *p0_p,int stride,int alpha, int beta) { + int p0 = P0; + int q0 = Q0; + + if(abs(p0-q0)>2) + 2; + if(abs(P2-p0) < beta && abs(p0-q0) < alpha) { + P0 = (P1 + p0 + s) >> 2; + P1 = (2*P1 + s) >> 2; + } else + P0 = (2*P1 + s) >> 2; + if(abs(Q2-q0) < beta && abs(q0-p0) < alpha) { + Q0 = (Q1 + q0 + s) >> 2; + Q1 = (2*Q1 + s) >> 2; + } else + Q0 = (2*Q1 + s) >> 2; + } +} + +static inline void loop_filter_l1(uint8_t *p0_p, int stride, int alpha, int beta, int tc) { + int p0 = P0; + int q0 = Q0; + + if(abs(p0-q0)>3,-tc, tc); + P0 = av_clip_uint8(p0+delta); + Q0 = av_clip_uint8(q0-delta); + if(abs(P2-p0)>3, -tc, tc); + P1 = av_clip_uint8(P1+delta); + } + if(abs(Q2-q0)>3, -tc, tc); + Q1 = av_clip_uint8(Q1-delta); + } + } +} + +static inline void loop_filter_c2(uint8_t *p0_p,int stride,int alpha, int beta) { + int p0 = P0; + int q0 = Q0; + + if(abs(p0-q0)>2) + 2; + if(abs(P2-p0) < beta && abs(p0-q0) < alpha) { + P0 = (P1 + p0 + s) >> 2; + } else + P0 = (2*P1 + s) >> 2; + if(abs(Q2-q0) < beta && abs(q0-p0) < alpha) { + Q0 = (Q1 + q0 + s) >> 2; + } else + Q0 = (2*Q1 + s) >> 2; + } +} + +static inline void loop_filter_c1(uint8_t *p0_p,int stride,int alpha, int beta, + int tc) { + if(abs(P0-Q0)>3, -tc, tc); + P0 = av_clip_uint8(P0+delta); + Q0 = av_clip_uint8(Q0-delta); + } +} + +#undef P0 +#undef P1 +#undef P2 +#undef Q0 +#undef Q1 +#undef Q2 + +static void cavs_filter_lv_c(uint8_t *d, int stride, int alpha, int beta, int tc, + int bs1, int bs2) { + int i; + if(bs1==2) + for(i=0;i<16;i++) + loop_filter_l2(d + i*stride,1,alpha,beta); + else { + if(bs1) + for(i=0;i<8;i++) + loop_filter_l1(d + i*stride,1,alpha,beta,tc); + if (bs2) + for(i=8;i<16;i++) + loop_filter_l1(d + i*stride,1,alpha,beta,tc); + } +} + +static void cavs_filter_lh_c(uint8_t *d, int stride, int alpha, int beta, int tc, + int bs1, int bs2) { + int i; + if(bs1==2) + for(i=0;i<16;i++) + loop_filter_l2(d + i,stride,alpha,beta); + else { + if(bs1) + for(i=0;i<8;i++) + loop_filter_l1(d + i,stride,alpha,beta,tc); + if (bs2) + for(i=8;i<16;i++) + loop_filter_l1(d + i,stride,alpha,beta,tc); + } +} + +static void cavs_filter_cv_c(uint8_t *d, int stride, int alpha, int beta, int tc, + int bs1, int bs2) { + int i; + if(bs1==2) + for(i=0;i<8;i++) + loop_filter_c2(d + i*stride,1,alpha,beta); + else { + if(bs1) + for(i=0;i<4;i++) + loop_filter_c1(d + i*stride,1,alpha,beta,tc); + if (bs2) + for(i=4;i<8;i++) + loop_filter_c1(d + i*stride,1,alpha,beta,tc); + } +} + +static void cavs_filter_ch_c(uint8_t *d, int stride, int alpha, int beta, int tc, + int bs1, int bs2) { + int i; + if(bs1==2) + for(i=0;i<8;i++) + loop_filter_c2(d + i,stride,alpha,beta); + else { + if(bs1) + for(i=0;i<4;i++) + loop_filter_c1(d + i,stride,alpha,beta,tc); + if (bs2) + for(i=4;i<8;i++) + loop_filter_c1(d + i,stride,alpha,beta,tc); + } +} + +/***************************************************************************** + * + * inverse transform + * + ****************************************************************************/ + +static void cavs_idct8_add_c(uint8_t *dst, DCTELEM *block, int stride) { + int i; + DCTELEM (*src)[8] = (DCTELEM(*)[8])block; + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + + src[0][0] += 8; + + for( i = 0; i < 8; i++ ) { + const int a0 = 3*src[i][1] - (src[i][7]<<1); + const int a1 = 3*src[i][3] + (src[i][5]<<1); + const int a2 = (src[i][3]<<1) - 3*src[i][5]; + const int a3 = (src[i][1]<<1) + 3*src[i][7]; + + const int b4 = ((a0 + a1 + a3)<<1) + a1; + const int b5 = ((a0 - a1 + a2)<<1) + a0; + const int b6 = ((a3 - a2 - a1)<<1) + a3; + const int b7 = ((a0 - a2 - a3)<<1) - a2; + + const int a7 = (src[i][2]<<2) - 10*src[i][6]; + const int a6 = (src[i][6]<<2) + 10*src[i][2]; + const int a5 = ((src[i][0] - src[i][4]) << 3) + 4; + const int a4 = ((src[i][0] + src[i][4]) << 3) + 4; + + const int b0 = a4 + a6; + const int b1 = a5 + a7; + const int b2 = a5 - a7; + const int b3 = a4 - a6; + + src[i][0] = (b0 + b4) >> 3; + src[i][1] = (b1 + b5) >> 3; + src[i][2] = (b2 + b6) >> 3; + src[i][3] = (b3 + b7) >> 3; + src[i][4] = (b3 - b7) >> 3; + src[i][5] = (b2 - b6) >> 3; + src[i][6] = (b1 - b5) >> 3; + src[i][7] = (b0 - b4) >> 3; + } + for( i = 0; i < 8; i++ ) { + const int a0 = 3*src[1][i] - (src[7][i]<<1); + const int a1 = 3*src[3][i] + (src[5][i]<<1); + const int a2 = (src[3][i]<<1) - 3*src[5][i]; + const int a3 = (src[1][i]<<1) + 3*src[7][i]; + + const int b4 = ((a0 + a1 + a3)<<1) + a1; + const int b5 = ((a0 - a1 + a2)<<1) + a0; + const int b6 = ((a3 - a2 - a1)<<1) + a3; + const int b7 = ((a0 - a2 - a3)<<1) - a2; + + const int a7 = (src[2][i]<<2) - 10*src[6][i]; + const int a6 = (src[6][i]<<2) + 10*src[2][i]; + const int a5 = (src[0][i] - src[4][i]) << 3; + const int a4 = (src[0][i] + src[4][i]) << 3; + + const int b0 = a4 + a6; + const int b1 = a5 + a7; + const int b2 = a5 - a7; + const int b3 = a4 - a6; + + dst[i + 0*stride] = cm[ dst[i + 0*stride] + ((b0 + b4) >> 7)]; + dst[i + 1*stride] = cm[ dst[i + 1*stride] + ((b1 + b5) >> 7)]; + dst[i + 2*stride] = cm[ dst[i + 2*stride] + ((b2 + b6) >> 7)]; + dst[i + 3*stride] = cm[ dst[i + 3*stride] + ((b3 + b7) >> 7)]; + dst[i + 4*stride] = cm[ dst[i + 4*stride] + ((b3 - b7) >> 7)]; + dst[i + 5*stride] = cm[ dst[i + 5*stride] + ((b2 - b6) >> 7)]; + dst[i + 6*stride] = cm[ dst[i + 6*stride] + ((b1 - b5) >> 7)]; + dst[i + 7*stride] = cm[ dst[i + 7*stride] + ((b0 - b4) >> 7)]; + } + memset(block,0,64*sizeof(DCTELEM)); +} + +/***************************************************************************** + * + * motion compensation + * + ****************************************************************************/ + +#define CAVS_SUBPIX(OPNAME, OP, NAME, A, B, C, D, E, F) \ +static void OPNAME ## cavs_filt8_h_ ## NAME(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + const int h=8;\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + int i;\ + for(i=0; i>3] +#define op_put2(a, b) a = cm[((b)+64)>>7] +#define op_put3(a, b) a = cm[((b)+32)>>6] +#define op_put4(a, b) a = cm[((b)+512)>>10] +#define op_avg1(a, b) a = ((a)+cm[((b)+4)>>3] +1)>>1 +#define op_avg2(a, b) a = ((a)+cm[((b)+64)>>7] +1)>>1 +#define op_avg3(a, b) a = ((a)+cm[((b)+32)>>6] +1)>>1 +#define op_avg4(a, b) a = ((a)+cm[((b)+512)>>10]+1)>>1 +CAVS_SUBPIX(put_ , op_put1, hpel, 0, -1, 5, 5, -1, 0) +CAVS_SUBPIX(put_ , op_put2, qpel_l, -1, -2, 96, 42, -7, 0) +CAVS_SUBPIX(put_ , op_put2, qpel_r, 0, -7, 42, 96, -2, -1) +CAVS_SUBPIX_HV(put_, op_put3, jj, 0, -1, 5, 5, -1, 0, 0, -1, 5, 5, -1, 0, 0) +CAVS_SUBPIX_HV(put_, op_put4, ff, 0, -1, 5, 5, -1, 0, -1, -2, 96, 42, -7, 0, 0) +CAVS_SUBPIX_HV(put_, op_put4, ii, -1, -2, 96, 42, -7, 0, 0, -1, 5, 5, -1, 0, 0) +CAVS_SUBPIX_HV(put_, op_put4, kk, 0, -7, 42, 96, -2, -1, 0, -1, 5, 5, -1, 0, 0) +CAVS_SUBPIX_HV(put_, op_put4, qq, 0, -1, 5, 5, -1, 0, 0, -7, 42, 96, -2,-1, 0) +CAVS_SUBPIX_HV(put_, op_put2, egpr, 0, -1, 5, 5, -1, 0, 0, -1, 5, 5, -1, 0, 1) +CAVS_SUBPIX(avg_ , op_avg1, hpel, 0, -1, 5, 5, -1, 0) +CAVS_SUBPIX(avg_ , op_avg2, qpel_l, -1, -2, 96, 42, -7, 0) +CAVS_SUBPIX(avg_ , op_avg2, qpel_r, 0, -7, 42, 96, -2, -1) +CAVS_SUBPIX_HV(avg_, op_avg3, jj, 0, -1, 5, 5, -1, 0, 0, -1, 5, 5, -1, 0, 0) +CAVS_SUBPIX_HV(avg_, op_avg4, ff, 0, -1, 5, 5, -1, 0, -1, -2, 96, 42, -7, 0, 0) +CAVS_SUBPIX_HV(avg_, op_avg4, ii, -1, -2, 96, 42, -7, 0, 0, -1, 5, 5, -1, 0, 0) +CAVS_SUBPIX_HV(avg_, op_avg4, kk, 0, -7, 42, 96, -2, -1, 0, -1, 5, 5, -1, 0, 0) +CAVS_SUBPIX_HV(avg_, op_avg4, qq, 0, -1, 5, 5, -1, 0, 0, -7, 42, 96, -2,-1, 0) +CAVS_SUBPIX_HV(avg_, op_avg2, egpr, 0, -1, 5, 5, -1, 0, 0, -1, 5, 5, -1, 0, 1) +CAVS_MC(put_, 8) +CAVS_MC(put_, 16) +CAVS_MC(avg_, 8) +CAVS_MC(avg_, 16) + +void ff_put_cavs_qpel8_mc00_c(uint8_t *dst, uint8_t *src, int stride); +void ff_avg_cavs_qpel8_mc00_c(uint8_t *dst, uint8_t *src, int stride); +void ff_put_cavs_qpel16_mc00_c(uint8_t *dst, uint8_t *src, int stride); +void ff_avg_cavs_qpel16_mc00_c(uint8_t *dst, uint8_t *src, int stride); + +void ff_cavsdsp_init(DSPContext* c, AVCodecContext *avctx) { +#define dspfunc(PFX, IDX, NUM) \ + c->PFX ## _pixels_tab[IDX][ 0] = ff_ ## PFX ## NUM ## _mc00_c; \ + c->PFX ## _pixels_tab[IDX][ 1] = ff_ ## PFX ## NUM ## _mc10_c; \ + c->PFX ## _pixels_tab[IDX][ 2] = ff_ ## PFX ## NUM ## _mc20_c; \ + c->PFX ## _pixels_tab[IDX][ 3] = ff_ ## PFX ## NUM ## _mc30_c; \ + c->PFX ## _pixels_tab[IDX][ 4] = ff_ ## PFX ## NUM ## _mc01_c; \ + c->PFX ## _pixels_tab[IDX][ 5] = ff_ ## PFX ## NUM ## _mc11_c; \ + c->PFX ## _pixels_tab[IDX][ 6] = ff_ ## PFX ## NUM ## _mc21_c; \ + c->PFX ## _pixels_tab[IDX][ 7] = ff_ ## PFX ## NUM ## _mc31_c; \ + c->PFX ## _pixels_tab[IDX][ 8] = ff_ ## PFX ## NUM ## _mc02_c; \ + c->PFX ## _pixels_tab[IDX][ 9] = ff_ ## PFX ## NUM ## _mc12_c; \ + c->PFX ## _pixels_tab[IDX][10] = ff_ ## PFX ## NUM ## _mc22_c; \ + c->PFX ## _pixels_tab[IDX][11] = ff_ ## PFX ## NUM ## _mc32_c; \ + c->PFX ## _pixels_tab[IDX][12] = ff_ ## PFX ## NUM ## _mc03_c; \ + c->PFX ## _pixels_tab[IDX][13] = ff_ ## PFX ## NUM ## _mc13_c; \ + c->PFX ## _pixels_tab[IDX][14] = ff_ ## PFX ## NUM ## _mc23_c; \ + c->PFX ## _pixels_tab[IDX][15] = ff_ ## PFX ## NUM ## _mc33_c + dspfunc(put_cavs_qpel, 0, 16); + dspfunc(put_cavs_qpel, 1, 8); + dspfunc(avg_cavs_qpel, 0, 16); + dspfunc(avg_cavs_qpel, 1, 8); + c->cavs_filter_lv = cavs_filter_lv_c; + c->cavs_filter_lh = cavs_filter_lh_c; + c->cavs_filter_cv = cavs_filter_cv_c; + c->cavs_filter_ch = cavs_filter_ch_c; + c->cavs_idct8_add = cavs_idct8_add_c; +} diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/cinepak.c b/src/add-ons/media/plugins/avcodec/libavcodec/cinepak.c index e8d3efc3c0..b83edd19af 100644 --- a/src/add-ons/media/plugins/avcodec/libavcodec/cinepak.c +++ b/src/add-ons/media/plugins/avcodec/libavcodec/cinepak.c @@ -2,20 +2,21 @@ * Cinepak Video Decoder * Copyright (C) 2003 the ffmpeg project * - * This library is free software; you can redistribute it and/or + * This file is part of FFmpeg. + * + * FFmpeg 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. + * version 2.1 of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * FFmpeg 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 - * + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** @@ -24,6 +25,8 @@ * by Ewald Snel * For more information on the Cinepak algorithm, visit: * http://www.csse.monash.edu.au/~timf/ + * For more information on the quirky data inside Sega FILM/CPK files, visit: + * http://wiki.multimedia.cx/index.php?title=Sega_FILM */ #include @@ -31,17 +34,8 @@ #include #include -#include "common.h" #include "avcodec.h" -#include "dsputil.h" -#define PALETTE_COUNT 256 - -#define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1]) -#define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \ - (((uint8_t*)(x))[1] << 16) | \ - (((uint8_t*)(x))[2] << 8) | \ - ((uint8_t*)(x))[3]) typedef struct { uint8_t y0, y1, y2, y3; @@ -61,25 +55,24 @@ typedef struct { typedef struct CinepakContext { AVCodecContext *avctx; - DSPContext dsp; AVFrame frame; - AVFrame prev_frame; - unsigned char *data; + const unsigned char *data; int size; int width, height; - unsigned char palette[PALETTE_COUNT * 4]; int palette_video; cvid_strip_t strips[MAX_STRIPS]; + int sega_film_skip_bytes; + } CinepakContext; static void cinepak_decode_codebook (cvid_codebook_t *codebook, - int chunk_id, int size, uint8_t *data) + int chunk_id, int size, const uint8_t *data) { - uint8_t *eod = (data + size); + const uint8_t *eod = (data + size); uint32_t flag, mask; int i, n; @@ -93,7 +86,7 @@ static void cinepak_decode_codebook (cvid_codebook_t *codebook, if ((data + 4) > eod) break; - flag = BE_32 (data); + flag = AV_RB32 (data); data += 4; mask = 0x80000000; } @@ -110,7 +103,7 @@ static void cinepak_decode_codebook (cvid_codebook_t *codebook, codebook[i].u = 128 + *data++; codebook[i].v = 128 + *data++; } else { - /* this codebook type indicates either greyscale or + /* this codebook type indicates either greyscale or * palettized video; if palettized, U & V components will * not be used so it is safe to set them to 128 for the * benefit of greyscale rendering in YUV420P */ @@ -126,12 +119,12 @@ static void cinepak_decode_codebook (cvid_codebook_t *codebook, } static int cinepak_decode_vectors (CinepakContext *s, cvid_strip_t *strip, - int chunk_id, int size, uint8_t *data) + int chunk_id, int size, const uint8_t *data) { - uint8_t *eod = (data + size); + const uint8_t *eod = (data + size); uint32_t flag, mask; cvid_codebook_t *codebook; - unsigned int i, j, x, y; + unsigned int x, y; uint32_t iy[4]; uint32_t iu[2]; uint32_t iv[2]; @@ -155,7 +148,7 @@ static int cinepak_decode_vectors (CinepakContext *s, cvid_strip_t *strip, if ((data + 4) > eod) return -1; - flag = BE_32 (data); + flag = AV_RB32 (data); data += 4; mask = 0x80000000; } @@ -165,7 +158,7 @@ static int cinepak_decode_vectors (CinepakContext *s, cvid_strip_t *strip, if ((data + 4) > eod) return -1; - flag = BE_32 (data); + flag = AV_RB32 (data); data += 4; mask = 0x80000000; } @@ -184,28 +177,28 @@ static int cinepak_decode_vectors (CinepakContext *s, cvid_strip_t *strip, s->frame.data[2][iv[0]] = codebook->v; } - s->frame.data[0][iy[0] + 2] = codebook->y0; - s->frame.data[0][iy[0] + 3] = codebook->y0; - s->frame.data[0][iy[1] + 2] = codebook->y0; - s->frame.data[0][iy[1] + 3] = codebook->y0; + s->frame.data[0][iy[0] + 2] = codebook->y1; + s->frame.data[0][iy[0] + 3] = codebook->y1; + s->frame.data[0][iy[1] + 2] = codebook->y1; + s->frame.data[0][iy[1] + 3] = codebook->y1; if (!s->palette_video) { s->frame.data[1][iu[0] + 1] = codebook->u; s->frame.data[2][iv[0] + 1] = codebook->v; } - s->frame.data[0][iy[2] + 0] = codebook->y0; - s->frame.data[0][iy[2] + 1] = codebook->y0; - s->frame.data[0][iy[3] + 0] = codebook->y0; - s->frame.data[0][iy[3] + 1] = codebook->y0; + s->frame.data[0][iy[2] + 0] = codebook->y2; + s->frame.data[0][iy[2] + 1] = codebook->y2; + s->frame.data[0][iy[3] + 0] = codebook->y2; + s->frame.data[0][iy[3] + 1] = codebook->y2; if (!s->palette_video) { s->frame.data[1][iu[1]] = codebook->u; s->frame.data[2][iv[1]] = codebook->v; } - s->frame.data[0][iy[2] + 2] = codebook->y0; - s->frame.data[0][iy[2] + 3] = codebook->y0; - s->frame.data[0][iy[3] + 2] = codebook->y0; - s->frame.data[0][iy[3] + 3] = codebook->y0; + s->frame.data[0][iy[2] + 2] = codebook->y3; + s->frame.data[0][iy[2] + 3] = codebook->y3; + s->frame.data[0][iy[3] + 2] = codebook->y3; + s->frame.data[0][iy[3] + 3] = codebook->y3; if (!s->palette_video) { s->frame.data[1][iu[1] + 1] = codebook->u; s->frame.data[2][iv[1] + 1] = codebook->v; @@ -256,22 +249,6 @@ static int cinepak_decode_vectors (CinepakContext *s, cvid_strip_t *strip, } } - } else { - /* copy from the previous frame */ - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - s->frame.data[0][iy[i] + j] = - s->prev_frame.data[0][iy[i] + j]; - } - } - for (i = 0; i < 2; i++) { - for (j = 0; j < 2; j++) { - s->frame.data[1][iu[i] + j] = - s->prev_frame.data[1][iu[i] + j]; - s->frame.data[2][iv[i] + j] = - s->prev_frame.data[2][iv[i] + j]; - } - } } iy[0] += 4; iy[1] += 4; @@ -285,9 +262,9 @@ static int cinepak_decode_vectors (CinepakContext *s, cvid_strip_t *strip, } static int cinepak_decode_strip (CinepakContext *s, - cvid_strip_t *strip, uint8_t *data, int size) + cvid_strip_t *strip, const uint8_t *data, int size) { - uint8_t *eod = (data + size); + const uint8_t *eod = (data + size); int chunk_id, chunk_size; /* coordinate sanity checks */ @@ -297,8 +274,11 @@ static int cinepak_decode_strip (CinepakContext *s, return -1; while ((data + 4) <= eod) { - chunk_id = BE_16 (&data[0]); - chunk_size = BE_16 (&data[2]) - 4; + chunk_id = AV_RB16 (&data[0]); + chunk_size = AV_RB16 (&data[2]) - 4; + if(chunk_size < 0) + return -1; + data += 4; chunk_size = ((data + chunk_size) > eod) ? (eod - data) : chunk_size; @@ -308,7 +288,7 @@ static int cinepak_decode_strip (CinepakContext *s, case 0x2100: case 0x2400: case 0x2500: - cinepak_decode_codebook (strip->v4_codebook, chunk_id, + cinepak_decode_codebook (strip->v4_codebook, chunk_id, chunk_size, data); break; @@ -316,14 +296,14 @@ static int cinepak_decode_strip (CinepakContext *s, case 0x2300: case 0x2600: case 0x2700: - cinepak_decode_codebook (strip->v1_codebook, chunk_id, + cinepak_decode_codebook (strip->v1_codebook, chunk_id, chunk_size, data); break; case 0x3000: case 0x3100: case 0x3200: - return cinepak_decode_vectors (s, strip, chunk_id, + return cinepak_decode_vectors (s, strip, chunk_id, chunk_size, data); } @@ -335,16 +315,40 @@ static int cinepak_decode_strip (CinepakContext *s, static int cinepak_decode (CinepakContext *s) { - uint8_t *eod = (s->data + s->size); + const uint8_t *eod = (s->data + s->size); int i, result, strip_size, frame_flags, num_strips; int y0 = 0; + int encoded_buf_size; if (s->size < 10) return -1; frame_flags = s->data[0]; - num_strips = BE_16 (&s->data[8]); - s->data += 10; + num_strips = AV_RB16 (&s->data[8]); + encoded_buf_size = ((s->data[1] << 16) | AV_RB16 (&s->data[2])); + + /* if this is the first frame, check for deviant Sega FILM data */ + if (s->sega_film_skip_bytes == -1) { + if (encoded_buf_size != s->size) { + /* If the encoded frame size differs from the frame size as indicated + * by the container file, this data likely comes from a Sega FILM/CPK file. + * If the frame header is followed by the bytes FE 00 00 06 00 00 then + * this is probably one of the two known files that have 6 extra bytes + * after the frame header. Else, assume 2 extra bytes. */ + if ((s->data[10] == 0xFE) && + (s->data[11] == 0x00) && + (s->data[12] == 0x00) && + (s->data[13] == 0x06) && + (s->data[14] == 0x00) && + (s->data[15] == 0x00)) + s->sega_film_skip_bytes = 6; + else + s->sega_film_skip_bytes = 2; + } else + s->sega_film_skip_bytes = 0; + } + + s->data += 10 + s->sega_film_skip_bytes; if (num_strips > MAX_STRIPS) num_strips = MAX_STRIPS; @@ -353,13 +357,13 @@ static int cinepak_decode (CinepakContext *s) if ((s->data + 12) > eod) return -1; - s->strips[i].id = BE_16 (s->data); + s->strips[i].id = AV_RB16 (s->data); s->strips[i].y1 = y0; s->strips[i].x1 = 0; - s->strips[i].y2 = y0 + BE_16 (&s->data[8]); + s->strips[i].y2 = y0 + AV_RB16 (&s->data[8]); s->strips[i].x2 = s->avctx->width; - strip_size = BE_16 (&s->data[2]) - 12; + strip_size = AV_RB16 (&s->data[2]) - 12; s->data += 12; strip_size = ((s->data + strip_size) > eod) ? (eod - s->data) : strip_size; @@ -381,54 +385,56 @@ static int cinepak_decode (CinepakContext *s) return 0; } -static int cinepak_decode_init(AVCodecContext *avctx) +static av_cold int cinepak_decode_init(AVCodecContext *avctx) { - CinepakContext *s = (CinepakContext *)avctx->priv_data; -/* - int i; - unsigned char r, g, b; - unsigned char *raw_palette; - unsigned int *palette32; -*/ + CinepakContext *s = avctx->priv_data; s->avctx = avctx; s->width = (avctx->width + 3) & ~3; s->height = (avctx->height + 3) & ~3; + s->sega_film_skip_bytes = -1; /* uninitialized state */ -// check for paletted data -s->palette_video = 0; + // check for paletted data + if ((avctx->palctrl == NULL) || (avctx->bits_per_sample == 40)) { + s->palette_video = 0; + avctx->pix_fmt = PIX_FMT_YUV420P; + } else { + s->palette_video = 1; + avctx->pix_fmt = PIX_FMT_PAL8; + } - - avctx->pix_fmt = PIX_FMT_YUV420P; - avctx->has_b_frames = 0; - dsputil_init(&s->dsp, avctx); - - s->frame.data[0] = s->prev_frame.data[0] = NULL; + s->frame.data[0] = NULL; return 0; } static int cinepak_decode_frame(AVCodecContext *avctx, void *data, int *data_size, - uint8_t *buf, int buf_size) + const uint8_t *buf, int buf_size) { - CinepakContext *s = (CinepakContext *)avctx->priv_data; + CinepakContext *s = avctx->priv_data; s->data = buf; s->size = buf_size; - if (avctx->get_buffer(avctx, &s->frame)) { - av_log(avctx, AV_LOG_ERROR, " Cinepak: get_buffer() failed\n"); + s->frame.reference = 1; + s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | + FF_BUFFER_HINTS_REUSABLE; + if (avctx->reget_buffer(avctx, &s->frame)) { + av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); return -1; } cinepak_decode(s); - if (s->prev_frame.data[0]) - avctx->release_buffer(avctx, &s->prev_frame); - - /* shuffle frames */ - s->prev_frame = s->frame; + if (s->palette_video) { + memcpy (s->frame.data[1], avctx->palctrl->palette, AVPALETTE_SIZE); + if (avctx->palctrl->palette_changed) { + s->frame.palette_has_changed = 1; + avctx->palctrl->palette_changed = 0; + } else + s->frame.palette_has_changed = 0; + } *data_size = sizeof(AVFrame); *(AVFrame*)data = s->frame; @@ -437,12 +443,12 @@ static int cinepak_decode_frame(AVCodecContext *avctx, return buf_size; } -static int cinepak_decode_end(AVCodecContext *avctx) +static av_cold int cinepak_decode_end(AVCodecContext *avctx) { - CinepakContext *s = (CinepakContext *)avctx->priv_data; + CinepakContext *s = avctx->priv_data; - if (s->prev_frame.data[0]) - avctx->release_buffer(avctx, &s->prev_frame); + if (s->frame.data[0]) + avctx->release_buffer(avctx, &s->frame); return 0; } @@ -457,4 +463,5 @@ AVCodec cinepak_decoder = { cinepak_decode_end, cinepak_decode_frame, CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Cinepak"), }; diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/cljr.c b/src/add-ons/media/plugins/avcodec/libavcodec/cljr.c index 382a77ac7d..ddc00583d1 100644 --- a/src/add-ons/media/plugins/avcodec/libavcodec/cljr.c +++ b/src/add-ons/media/plugins/avcodec/libavcodec/cljr.c @@ -2,29 +2,31 @@ * Cirrus Logic AccuPak (CLJR) codec * Copyright (c) 2003 Alex Beregszaszi * - * This library is free software; you can redistribute it and/or + * This file is part of FFmpeg. + * + * FFmpeg 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. + * version 2.1 of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * FFmpeg 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 - * + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - + /** * @file cljr.c * Cirrus Logic AccuPak codec. */ - + #include "avcodec.h" -#include "mpegvideo.h" +#include "dsputil.h" +#include "bitstream.h" typedef struct CLJRContext{ AVCodecContext *avctx; @@ -34,22 +36,15 @@ typedef struct CLJRContext{ GetBitContext gb; } CLJRContext; -static int decode_frame(AVCodecContext *avctx, +static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, - uint8_t *buf, int buf_size) + const uint8_t *buf, int buf_size) { CLJRContext * const a = avctx->priv_data; AVFrame *picture = data; AVFrame * const p= (AVFrame*)&a->picture; int x, y; - *data_size = 0; - - /* special case for last picture */ - if (buf_size == 0) { - return 0; - } - if(p->data[0]) avctx->release_buffer(avctx, p); @@ -58,7 +53,7 @@ static int decode_frame(AVCodecContext *avctx, av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return -1; } - p->pict_type= I_TYPE; + p->pict_type= FF_I_TYPE; p->key_frame= 1; init_get_bits(&a->gb, buf, buf_size); @@ -68,13 +63,13 @@ static int decode_frame(AVCodecContext *avctx, uint8_t *cb= &a->picture.data[1][ y*a->picture.linesize[1] ]; uint8_t *cr= &a->picture.data[2][ y*a->picture.linesize[2] ]; for(x=0; xwidth; x+=4){ - luma[3] = get_bits(&a->gb, 5) << 3; - luma[2] = get_bits(&a->gb, 5) << 3; - luma[1] = get_bits(&a->gb, 5) << 3; - luma[0] = get_bits(&a->gb, 5) << 3; - luma+= 4; - *(cb++) = get_bits(&a->gb, 6) << 2; - *(cr++) = get_bits(&a->gb, 6) << 2; + luma[3] = get_bits(&a->gb, 5) << 3; + luma[2] = get_bits(&a->gb, 5) << 3; + luma[1] = get_bits(&a->gb, 5) << 3; + luma[0] = get_bits(&a->gb, 5) << 3; + luma+= 4; + *(cb++) = get_bits(&a->gb, 6) << 2; + *(cr++) = get_bits(&a->gb, 6) << 2; } } @@ -82,7 +77,7 @@ static int decode_frame(AVCodecContext *avctx, *data_size = sizeof(AVPicture); emms_c(); - + return buf_size; } @@ -95,50 +90,45 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, int mb_x, mb_y; *p = *pict; - p->pict_type= I_TYPE; + p->pict_type= FF_I_TYPE; p->key_frame= 1; emms_c(); - + align_put_bits(&a->pb); while(get_bit_count(&a->pb)&31) put_bits(&a->pb, 8, 0); - + size= get_bit_count(&a->pb)/32; - + return size*4; } #endif -static void common_init(AVCodecContext *avctx){ +static av_cold void common_init(AVCodecContext *avctx){ CLJRContext * const a = avctx->priv_data; avctx->coded_frame= (AVFrame*)&a->picture; a->avctx= avctx; } -static int decode_init(AVCodecContext *avctx){ +static av_cold int decode_init(AVCodecContext *avctx){ common_init(avctx); - + avctx->pix_fmt= PIX_FMT_YUV411P; return 0; } -static int encode_init(AVCodecContext *avctx){ +#if 0 +static av_cold int encode_init(AVCodecContext *avctx){ common_init(avctx); - - return 0; -} - -static int decode_end(AVCodecContext *avctx){ - - avcodec_default_free_buffers(avctx); return 0; } +#endif AVCodec cljr_decoder = { "cljr", @@ -147,9 +137,10 @@ AVCodec cljr_decoder = { sizeof(CLJRContext), decode_init, NULL, - decode_end, + NULL, decode_frame, CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Cirrus Logic AccuPak"), }; #if 0 #ifdef CONFIG_ENCODERS @@ -162,6 +153,7 @@ AVCodec cljr_encoder = { encode_init, encode_frame, //encode_end, + .long_name = NULL_IF_CONFIG_SMALL("Cirrus Logic AccuPak"), }; #endif //CONFIG_ENCODERS diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/colorspace.h b/src/add-ons/media/plugins/avcodec/libavcodec/colorspace.h new file mode 100644 index 0000000000..9d89d6daa4 --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/colorspace.h @@ -0,0 +1,111 @@ +/* + * Colorspace conversion defines + * Copyright (c) 2001, 2002, 2003 Fabrice Bellard. + * + * This file is part of FFmpeg. + * + * FFmpeg 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.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file colorspace.h + * Various defines for YUV<->RGB conversion + */ + +#ifndef FFMPEG_COLORSPACE_H +#define FFMPEG_COLORSPACE_H + +#define SCALEBITS 10 +#define ONE_HALF (1 << (SCALEBITS - 1)) +#define FIX(x) ((int) ((x) * (1<> SCALEBITS];\ + g = cm[(y + g_add) >> SCALEBITS];\ + b = cm[(y + b_add) >> SCALEBITS];\ +} + +#define YUV_TO_RGB1(cb1, cr1)\ +{\ + cb = (cb1) - 128;\ + cr = (cr1) - 128;\ + r_add = FIX(1.40200) * cr + ONE_HALF;\ + g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\ + b_add = FIX(1.77200) * cb + ONE_HALF;\ +} + +#define YUV_TO_RGB2(r, g, b, y1)\ +{\ + y = (y1) << SCALEBITS;\ + r = cm[(y + r_add) >> SCALEBITS];\ + g = cm[(y + g_add) >> SCALEBITS];\ + b = cm[(y + b_add) >> SCALEBITS];\ +} + +#define Y_CCIR_TO_JPEG(y)\ + cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS] + +#define Y_JPEG_TO_CCIR(y)\ + (((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) + +#define C_CCIR_TO_JPEG(y)\ + cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS] + +/* NOTE: the clamp is really necessary! */ +static inline int C_JPEG_TO_CCIR(int y) { + y = (((y - 128) * FIX(112.0/127.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS); + if (y < 16) + y = 16; + return y; +} + + +#define RGB_TO_Y(r, g, b) \ +((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \ + FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS) + +#define RGB_TO_U(r1, g1, b1, shift)\ +(((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \ + FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_V(r1, g1, b1, shift)\ +(((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \ + FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_Y_CCIR(r, g, b) \ +((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \ + FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) + +#define RGB_TO_U_CCIR(r1, g1, b1, shift)\ +(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \ + FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_V_CCIR(r1, g1, b1, shift)\ +(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \ + FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#endif /* FFMPEG_COLORSPACE_H */ diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/config.h b/src/add-ons/media/plugins/avcodec/libavcodec/config.h index aeb63e0944..a34c05962e 100644 --- a/src/add-ons/media/plugins/avcodec/libavcodec/config.h +++ b/src/add-ons/media/plugins/avcodec/libavcodec/config.h @@ -1,11 +1,11 @@ /* Automatically generated by configure - do not modify */ /* But I modified it now! */ -#define ARCH_X86 1 +#define ARCH_X8 1 #define TUNECPU generic /* #define EMULATE_FAST_INT 1 */ #define HAVE_LOCALTIME_R 1 #define HAVE_VHOOK 1 -#define CONFIG_ENCODERS 1 +#define CONFIG_ENCODERS 0 #define CONFIG_DECODERS 1 #define CONFIG_MPEGAUDIO_HP 1 #define CONFIG_HAVE_DLOPEN 1 @@ -18,4 +18,359 @@ #define SIMPLE_IDCT 1 /* #define CONFIG_FFSERVER 1 */ #define CONFIG_RISKY 1 +#define HAVE_ROUND 1 +#define HAVE_ROUNDF 1 +#define G729_BITEXACT 1 +#define ENABLE_SMALL 0 +#define ENABLE_GRAY 0 +#define ENABLE_THREADS 0 +#define CODEC_ID_G729 0 + +#define ENABLE_MMX 0 +#define ENABLE_ARMV4L 0 +#define ENABLE_MLIB 0 +#define ENABLE_VIS 0 +#define ENABLE_ALPHA 0 +#define ENABLE_POWERPC 0 +#define ENABLE_MMI 0 +#define ENABLE_SH4 0 +#define ENABLE_BFIN 0 + +#define ENABLE_AASC_DECODER 1 +#define ENABLE_AMV_DECODER 0 +#define ENABLE_ASV1_ENCODER 0 +#define ENABLE_ASV1_DECODER 1 +#define ENABLE_ASV2_ENCODER 0 +#define ENABLE_ASV2_DECODER 1 +#define ENABLE_AVS_DECODER 1 +#define ENABLE_BETHSOFTVID_DECODER 0 +#define ENABLE_BFI_DECODER 1 +#define ENABLE_BMP_ENCODER 0 +#define ENABLE_BMP_DECODER 1 +#define ENABLE_C93_DECODER 1 +#define ENABLE_CAVS_DECODER 1 +#define ENABLE_CINEPAK_DECODER 1 +#define ENABLE_CLJR_DECODER 1 +#define ENABLE_CSCD_DECODER 1 +#define ENABLE_CYUV_DECODER 1 +#define ENABLE_DNXHD_ENCODER 0 +#define ENABLE_DNXHD_DECODER 1 +#define ENABLE_DSICINVIDEO_DECODER 1 +#define ENABLE_DVVIDEO_ENCODER 0 +#define ENABLE_DVVIDEO_DECODER 0 +#define ENABLE_DXA_DECODER 0 +#define ENABLE_EACMV_DECODER 1 +#define ENABLE_EATGV_DECODER 0 +#define ENABLE_EIGHTBPS_DECODER 1 +#define ENABLE_EIGHTSVX_EXP_DECODER 1 +#define ENABLE_EIGHTSVX_FIB_DECODER 1 +#define ENABLE_ESCAPE124_DECODER 1 +#define ENABLE_FFV1_ENCODER 0 +#define ENABLE_FFV1_DECODER 1 +#define ENABLE_FFVHUFF_ENCODER 0 +#define ENABLE_FFVHUFF_DECODER 1 +#define ENABLE_FLASHSV_ENCODER 0 +#define ENABLE_FLASHSV_DECODER 0 +#define ENABLE_FLIC_DECODER 1 +#define ENABLE_FLV_ENCODER 0 +#define ENABLE_FLV_DECODER 1 +#define ENABLE_FOURXM_DECODER 1 +#define ENABLE_FRAPS_DECODER 1 +#define ENABLE_GIF_ENCODER 0 +#define ENABLE_GIF_DECODER 1 +#define ENABLE_H261_ENCODER 0 +#define ENABLE_H261_DECODER 1 +#define ENABLE_H263_ENCODER 0 +#define ENABLE_H263_DECODER 1 +#define ENABLE_H263I_DECODER 1 +#define ENABLE_H263P_ENCODER 0 +#define ENABLE_H264_DECODER 1 +#define ENABLE_HUFFYUV_ENCODER 0 +#define ENABLE_HUFFYUV_DECODER 1 +#define ENABLE_IDCIN_DECODER 1 +#define ENABLE_INDEO2_DECODER 1 +#define ENABLE_INDEO3_DECODER 1 +#define ENABLE_INTERPLAY_VIDEO_DECODER 1 +#define ENABLE_JPEGLS_ENCODER 0 +#define ENABLE_JPEGLS_DECODER 1 +#define ENABLE_KMVC_DECODER 1 +#define ENABLE_LJPEG_ENCODER 0 +#define ENABLE_LOCO_DECODER 1 +#define ENABLE_MDEC_DECODER 1 +#define ENABLE_MIMIC_DECODER 1 +#define ENABLE_MJPEG_ENCODER 0 +#define ENABLE_MJPEG_DECODER 1 +#define ENABLE_MJPEGB_DECODER 1 +#define ENABLE_MMVIDEO_DECODER 0 +#define ENABLE_MOTIONPIXELS_DECODER 1 +#define ENABLE_MPEG_XVMC_DECODER 0 +#define ENABLE_MPEG1VIDEO_ENCODER 0 +#define ENABLE_MPEG1VIDEO_DECODER 1 +#define ENABLE_MPEG2VIDEO_ENCODER 0 +#define ENABLE_MPEG2VIDEO_DECODER 1 +#define ENABLE_MPEG4_ENCODER 0 +#define ENABLE_MPEG4_DECODER 1 +#define ENABLE_MPEGVIDEO_DECODER 1 +#define ENABLE_MSMPEG4V1_ENCODER 0 +#define ENABLE_MSMPEG4V1_DECODER 1 +#define ENABLE_MSMPEG4V2_ENCODER 0 +#define ENABLE_MSMPEG4V2_DECODER 1 +#define ENABLE_MSMPEG4V3_ENCODER 0 +#define ENABLE_MSMPEG4V3_DECODER 1 +#define ENABLE_MSRLE_DECODER 1 +#define ENABLE_MSVIDEO1_DECODER 0 +#define ENABLE_MSZH_DECODER 0 +#define ENABLE_NUV_DECODER 1 +#define ENABLE_PAM_ENCODER 0 +#define ENABLE_PBM_ENCODER 0 +#define ENABLE_PCX_DECODER 1 +#define ENABLE_PGM_ENCODER 0 +#define ENABLE_PGMYUV_ENCODER 0 +#define ENABLE_PNG_ENCODER 0 +#define ENABLE_PNG_DECODER 0 +#define ENABLE_PPM_ENCODER 0 +#define ENABLE_PTX_DECODER 1 +#define ENABLE_QDRAW_DECODER 1 +#define ENABLE_QPEG_DECODER 1 +#define ENABLE_QTRLE_ENCODER 0 +#define ENABLE_QTRLE_DECODER 1 +#define ENABLE_RAWVIDEO_ENCODER 0 +#define ENABLE_RAWVIDEO_DECODER 1 +#define ENABLE_RL2_DECODER 1 +#define ENABLE_ROQ_ENCODER 0 +#define ENABLE_ROQ_DECODER 0 +#define ENABLE_RPZA_DECODER 1 +#define ENABLE_RV10_ENCODER 0 +#define ENABLE_RV10_DECODER 0 +#define ENABLE_RV20_ENCODER 0 +#define ENABLE_RV20_DECODER 0 +#define ENABLE_SGI_ENCODER 0 +#define ENABLE_SGI_DECODER 1 +#define ENABLE_SMACKER_DECODER 0 +#define ENABLE_SMC_DECODER 1 +#define ENABLE_SNOW_ENCODER 0 +#define ENABLE_SNOW_DECODER 0 +#define ENABLE_SP5X_DECODER 0 +#define ENABLE_SUNRAST_DECODER 0 +#define ENABLE_SVQ1_ENCODER 0 +#define ENABLE_SVQ1_DECODER 0 +#define ENABLE_SVQ3_DECODER 0 +#define ENABLE_TARGA_ENCODER 0 +#define ENABLE_TARGA_DECODER 0 +#define ENABLE_THEORA_DECODER 0 +#define ENABLE_THP_DECODER 1 +#define ENABLE_TIERTEXSEQVIDEO_DECODER 0 +#define ENABLE_TIFF_ENCODER 0 +#define ENABLE_TIFF_DECODER 0 +#define ENABLE_TRUEMOTION1_DECODER 0 +#define ENABLE_TRUEMOTION2_DECODER 0 +#define ENABLE_TSCC_DECODER 0 +#define ENABLE_TXD_DECODER 0 +#define ENABLE_ULTI_DECODER 1 +#define ENABLE_VB_DECODER 1 +#define ENABLE_VC1_DECODER 0 +#define ENABLE_VCR1_DECODER 0 +#define ENABLE_VMDVIDEO_DECODER 0 +#define ENABLE_VMNC_DECODER 0 +#define ENABLE_VP3_DECODER 0 +#define ENABLE_VP5_DECODER 0 +#define ENABLE_VP6_DECODER 0 +#define ENABLE_VP6A_DECODER 0 +#define ENABLE_VP6F_DECODER 0 +#define ENABLE_VQA_DECODER 0 +#define ENABLE_WMV1_ENCODER 0 +#define ENABLE_WMV1_DECODER 0 +#define ENABLE_WMV2_ENCODER 0 +#define ENABLE_WMV2_DECODER 0 +#define ENABLE_WMV3_DECODER 0 +#define ENABLE_WNV1_DECODER 0 +#define ENABLE_XAN_WC3_DECODER 0 +#define ENABLE_XL_DECODER 0 +#define ENABLE_XSUB_DECODER 0 +#define ENABLE_ZLIB_ENCODER 0 +#define ENABLE_ZLIB_DECODER 0 +#define ENABLE_ZMBV_ENCODER 0 +#define ENABLE_ZMBV_DECODER 0 +#define ENABLE_AAC_DECODER 1 +#define ENABLE_AC3_ENCODER 0 +#define ENABLE_AC3_DECODER 0 +#define ENABLE_ALAC_ENCODER 0 +#define ENABLE_ALAC_DECODER 1 +#define ENABLE_APE_DECODER 0 +#define ENABLE_ATRAC3_DECODER 1 +#define ENABLE_COOK_DECODER 1 +#define ENABLE_DCA_DECODER 1 +#define ENABLE_DSICINAUDIO_DECODER 1 +#define ENABLE_FLAC_ENCODER 0 +#define ENABLE_FLAC_DECODER 1 +#define ENABLE_IMC_DECODER 1 +#define ENABLE_MACE3_DECODER 1 +#define ENABLE_MACE6_DECODER 1 +#define ENABLE_MLP_DECODER 0 +#define ENABLE_MP2_ENCODER 0 +#define ENABLE_MP2_DECODER 0 +#define ENABLE_MP3_DECODER 0 +#define ENABLE_MP3ADU_DECODER 0 +#define ENABLE_MP3ON4_DECODER 0 +#define ENABLE_MPC7_DECODER 1 +#define ENABLE_MPC8_DECODER 1 +#define ENABLE_NELLYMOSER_DECODER 0 +#define ENABLE_QDM2_DECODER 1 +#define ENABLE_RA_144_DECODER 1 +#define ENABLE_RA_288_DECODER 1 +#define ENABLE_SHORTEN_DECODER 1 +#define ENABLE_SMACKAUD_DECODER 0 +#define ENABLE_SONIC_ENCODER 0 +#define ENABLE_SONIC_DECODER 1 +#define ENABLE_SONIC_LS_ENCODER 0 +#define ENABLE_TRUESPEECH_DECODER 0 +#define ENABLE_TTA_DECODER 0 +#define ENABLE_VMDAUDIO_DECODER 0 +#define ENABLE_VORBIS_ENCODER 0 +#define ENABLE_VORBIS_DECODER 1 +#define ENABLE_WAVPACK_DECODER 1 +#define ENABLE_WMAV1_ENCODER 0 +#define ENABLE_WMAV1_DECODER 0 +#define ENABLE_WMAV2_ENCODER 0 +#define ENABLE_WMAV2_DECODER 0 +#define ENABLE_WS_SND1_DECODER 0 +#define ENABLE_PCM_ALAW_ENCODER 0 +#define ENABLE_PCM_ALAW_DECODER 1 +#define ENABLE_PCM_DVD_DECODER 1 +#define ENABLE_PCM_F32BE_ENCODER 0 +#define ENABLE_PCM_F32BE_DECODER 1 +#define ENABLE_PCM_F32LE_ENCODER 0 +#define ENABLE_PCM_F32LE_DECODER 1 +#define ENABLE_PCM_F64BE_ENCODER 0 +#define ENABLE_PCM_F64BE_DECODER 1 +#define ENABLE_PCM_F64LE_ENCODER 0 +#define ENABLE_PCM_F64LE_DECODER 1 +#define ENABLE_PCM_MULAW_ENCODER 0 +#define ENABLE_PCM_MULAW_DECODER 1 +#define ENABLE_PCM_S8_ENCODER 0 +#define ENABLE_PCM_S8_DECODER 1 +#define ENABLE_PCM_S16BE_ENCODER 0 +#define ENABLE_PCM_S16BE_DECODER 1 +#define ENABLE_PCM_S16LE_ENCODER 0 +#define ENABLE_PCM_S16LE_DECODER 1 +#define ENABLE_PCM_S16LE_PLANAR_DECODER 1 +#define ENABLE_PCM_S24BE_ENCODER 0 +#define ENABLE_PCM_S24BE_DECODER 1 +#define ENABLE_PCM_S24DAUD_ENCODER 0 +#define ENABLE_PCM_S24DAUD_DECODER 1 +#define ENABLE_PCM_S24LE_ENCODER 0 +#define ENABLE_PCM_S24LE_DECODER 1 +#define ENABLE_PCM_S32BE_ENCODER 0 +#define ENABLE_PCM_S32BE_DECODER 1 +#define ENABLE_PCM_S32LE_ENCODER 0 +#define ENABLE_PCM_S32LE_DECODER 1 +#define ENABLE_PCM_U8_ENCODER 0 +#define ENABLE_PCM_U8_DECODER 1 +#define ENABLE_PCM_U16BE_ENCODER 0 +#define ENABLE_PCM_U16BE_DECODER 1 +#define ENABLE_PCM_U16LE_ENCODER 0 +#define ENABLE_PCM_U16LE_DECODER 1 +#define ENABLE_PCM_U24BE_ENCODER 0 +#define ENABLE_PCM_U24BE_DECODER 1 +#define ENABLE_PCM_U24LE_ENCODER 0 +#define ENABLE_PCM_U24LE_DECODER 1 +#define ENABLE_PCM_U32BE_ENCODER 0 +#define ENABLE_PCM_U32BE_DECODER 1 +#define ENABLE_PCM_U32LE_ENCODER 0 +#define ENABLE_PCM_U32LE_DECODER 1 +#define ENABLE_PCM_ZORK_ENCODER 0 +#define ENABLE_PCM_ZORK_DECODER 1 +#define ENABLE_INTERPLAY_DPCM_DECODER 1 +#define ENABLE_ROQ_DPCM_ENCODER 0 +#define ENABLE_ROQ_DPCM_DECODER 1 +#define ENABLE_SOL_DPCM_DECODER 1 +#define ENABLE_XAN_DPCM_DECODER 1 +#define ENABLE_ADPCM_4XM_DECODER 1 +#define ENABLE_ADPCM_ADX_ENCODER 0 +#define ENABLE_ADPCM_ADX_DECODER 1 +#define ENABLE_ADPCM_CT_DECODER 1 +#define ENABLE_ADPCM_EA_DECODER 1 +#define ENABLE_ADPCM_EA_MAXIS_XA_DECODER 1 +#define ENABLE_ADPCM_EA_R1_DECODER 1 +#define ENABLE_ADPCM_EA_R2_DECODER 1 +#define ENABLE_ADPCM_EA_R3_DECODER 1 +#define ENABLE_ADPCM_EA_XAS_DECODER 1 +#define ENABLE_ADPCM_G726_ENCODER 0 +#define ENABLE_ADPCM_G726_DECODER 1 +#define ENABLE_ADPCM_IMA_AMV_DECODER 1 +#define ENABLE_ADPCM_IMA_DK3_DECODER 1 +#define ENABLE_ADPCM_IMA_DK4_DECODER 1 +#define ENABLE_ADPCM_IMA_EA_EACS_DECODER 1 +#define ENABLE_ADPCM_IMA_EA_SEAD_DECODER 1 +#define ENABLE_ADPCM_IMA_QT_ENCODER 0 +#define ENABLE_ADPCM_IMA_QT_DECODER 1 +#define ENABLE_ADPCM_IMA_SMJPEG_DECODER 1 +#define ENABLE_ADPCM_IMA_WAV_ENCODER 0 +#define ENABLE_ADPCM_IMA_WAV_DECODER 1 +#define ENABLE_ADPCM_IMA_WS_DECODER 1 +#define ENABLE_ADPCM_MS_ENCODER 0 +#define ENABLE_ADPCM_MS_DECODER 1 +#define ENABLE_ADPCM_SBPRO_2_DECODER 1 +#define ENABLE_ADPCM_SBPRO_3_DECODER 1 +#define ENABLE_ADPCM_SBPRO_4_DECODER 1 +#define ENABLE_ADPCM_SWF_ENCODER 0 +#define ENABLE_ADPCM_SWF_DECODER 1 +#define ENABLE_ADPCM_THP_DECODER 1 +#define ENABLE_ADPCM_XA_DECODER 1 +#define ENABLE_ADPCM_YAMAHA_ENCODER 0 +#define ENABLE_ADPCM_YAMAHA_DECODER 1 +#define ENABLE_DVBSUB_ENCODER 0 +#define ENABLE_DVBSUB_DECODER 1 +#define ENABLE_DVDSUB_ENCODER 0 +#define ENABLE_DVDSUB_DECODER 1 +#define ENABLE_LIBA52_DECODER 0 +#define ENABLE_LIBAMR_NB_ENCODER 0 +#define ENABLE_LIBAMR_NB_DECODER 0 +#define ENABLE_LIBAMR_WB_ENCODER 0 +#define ENABLE_LIBAMR_WB_DECODER 0 +#define ENABLE_LIBDIRAC_ENCODER 0 +#define ENABLE_LIBDIRAC_DECODER 0 +#define ENABLE_LIBFAAC_ENCODER 0 +#define ENABLE_LIBFAAD_DECODER 0 +#define ENABLE_LIBGSM_ENCODER 0 +#define ENABLE_LIBGSM_DECODER 0 +#define ENABLE_LIBGSM_MS_ENCODER 0 +#define ENABLE_LIBGSM_MS_DECODER 0 +#define ENABLE_LIBMP3LAME_ENCODER 0 +#define ENABLE_LIBSCHROEDINGER_ENCODER 0 +#define ENABLE_LIBSCHROEDINGER_DECODER 0 +#define ENABLE_LIBTHEORA_ENCODER 0 +#define ENABLE_LIBVORBIS_ENCODER 0 +#define ENABLE_LIBX264_ENCODER 0 +#define ENABLE_LIBXVID_ENCODER 0 +#define ENABLE_MPEG4AAC_DECODER 0 +#define ENABLE_AAC_PARSER 0 +#define ENABLE_AC3_PARSER 0 +#define ENABLE_CAVSVIDEO_PARSER 0 +#define ENABLE_DCA_PARSER 0 +#define ENABLE_DIRAC_PARSER 0 +#define ENABLE_DVBSUB_PARSER 0 +#define ENABLE_DVDSUB_PARSER 0 +#define ENABLE_H261_PARSER 0 +#define ENABLE_H263_PARSER 0 +#define ENABLE_H264_PARSER 0 +#define ENABLE_MJPEG_PARSER 0 +#define ENABLE_MLP_PARSER 0 +#define ENABLE_MPEG4VIDEO_PARSER 0 +#define ENABLE_MPEGAUDIO_PARSER 0 +#define ENABLE_MPEGVIDEO_PARSER 0 +#define ENABLE_PNM_PARSER 0 +#define ENABLE_VC1_PARSER 0 +#define ENABLE_VP3_PARSER 0 +#define ENABLE_DUMP_EXTRADATA_BSF 0 +#define ENABLE_H264_MP4TOANNEXB_BSF 0 +#define ENABLE_IMX_DUMP_HEADER_BSF 0 +#define ENABLE_MJPEGA_DUMP_HEADER_BSF 0 +#define ENABLE_MP3_HEADER_COMPRESS_BSF 0 +#define ENABLE_MP3_HEADER_DECOMPRESS_BSF 1 +#define ENABLE_MOV2TEXTSUB_BSF 0 +#define ENABLE_NOISE_BSF 0 +#define ENABLE_REMOVE_EXTRADATA_BSF 0 +#define ENABLE_TEXT2MOVSUB_BSF 0 + #define restrict __restrict__ diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/cook.c b/src/add-ons/media/plugins/avcodec/libavcodec/cook.c new file mode 100644 index 0000000000..61131905a0 --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/cook.c @@ -0,0 +1,1198 @@ +/* + * COOK compatible decoder + * Copyright (c) 2003 Sascha Sommer + * Copyright (c) 2005 Benjamin Larsson + * + * This file is part of FFmpeg. + * + * FFmpeg 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.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file cook.c + * Cook compatible decoder. Bastardization of the G.722.1 standard. + * This decoder handles RealNetworks, RealAudio G2 data. + * Cook is identified by the codec name cook in RM files. + * + * To use this decoder, a calling application must supply the extradata + * bytes provided from the RM container; 8+ bytes for mono streams and + * 16+ for stereo streams (maybe more). + * + * Codec technicalities (all this assume a buffer length of 1024): + * Cook works with several different techniques to achieve its compression. + * In the timedomain the buffer is divided into 8 pieces and quantized. If + * two neighboring pieces have different quantization index a smooth + * quantization curve is used to get a smooth overlap between the different + * pieces. + * To get to the transformdomain Cook uses a modulated lapped transform. + * The transform domain has 50 subbands with 20 elements each. This + * means only a maximum of 50*20=1000 coefficients are used out of the 1024 + * available. + */ + +#include +#include +#include + +#include "random.h" +#include "avcodec.h" +#include "bitstream.h" +#include "dsputil.h" +#include "bytestream.h" + +#include "cookdata.h" + +/* the different Cook versions */ +#define MONO 0x1000001 +#define STEREO 0x1000002 +#define JOINT_STEREO 0x1000003 +#define MC_COOK 0x2000000 //multichannel Cook, not supported + +#define SUBBAND_SIZE 20 +//#define COOKDEBUG + +typedef struct { + int *now; + int *previous; +} cook_gains; + +typedef struct cook { + /* + * The following 5 functions provide the lowlevel arithmetic on + * the internal audio buffers. + */ + void (* scalar_dequant)(struct cook *q, int index, int quant_index, + int* subband_coef_index, int* subband_coef_sign, + float* mlt_p); + + void (* decouple) (struct cook *q, + int subband, + float f1, float f2, + float *decode_buffer, + float *mlt_buffer1, float *mlt_buffer2); + + void (* imlt_window) (struct cook *q, float *buffer1, + cook_gains *gains_ptr, float *previous_buffer); + + void (* interpolate) (struct cook *q, float* buffer, + int gain_index, int gain_index_next); + + void (* saturate_output) (struct cook *q, int chan, int16_t *out); + + GetBitContext gb; + /* stream data */ + int nb_channels; + int joint_stereo; + int bit_rate; + int sample_rate; + int samples_per_channel; + int samples_per_frame; + int subbands; + int log2_numvector_size; + int numvector_size; //1 << log2_numvector_size; + int js_subband_start; + int total_subbands; + int num_vectors; + int bits_per_subpacket; + int cookversion; + /* states */ + AVRandomState random_state; + + /* transform data */ + MDCTContext mdct_ctx; + float* mlt_window; + + /* gain buffers */ + cook_gains gains1; + cook_gains gains2; + int gain_1[9]; + int gain_2[9]; + int gain_3[9]; + int gain_4[9]; + + /* VLC data */ + int js_vlc_bits; + VLC envelope_quant_index[13]; + VLC sqvh[7]; //scalar quantization + VLC ccpl; //channel coupling + + /* generatable tables and related variables */ + int gain_size_factor; + float gain_table[23]; + + /* data buffers */ + + uint8_t* decoded_bytes_buffer; + DECLARE_ALIGNED_16(float,mono_mdct_output[2048]); + float mono_previous_buffer1[1024]; + float mono_previous_buffer2[1024]; + float decode_buffer_1[1024]; + float decode_buffer_2[1024]; + float decode_buffer_0[1060]; /* static allocation for joint decode */ + + const float *cplscales[5]; +} COOKContext; + +static float pow2tab[127]; +static float rootpow2tab[127]; + +/* debug functions */ + +#ifdef COOKDEBUG +static void dump_float_table(float* table, int size, int delimiter) { + int i=0; + av_log(NULL,AV_LOG_ERROR,"\n[%d]: ",i); + for (i=0 ; igain_size_factor = q->samples_per_channel/8; + for (i=0 ; i<23 ; i++) { + q->gain_table[i] = pow(pow2tab[i+52] , + (1.0/(double)q->gain_size_factor)); + } +} + + +static int init_cook_vlc_tables(COOKContext *q) { + int i, result; + + result = 0; + for (i=0 ; i<13 ; i++) { + result |= init_vlc (&q->envelope_quant_index[i], 9, 24, + envelope_quant_index_huffbits[i], 1, 1, + envelope_quant_index_huffcodes[i], 2, 2, 0); + } + av_log(NULL,AV_LOG_DEBUG,"sqvh VLC init\n"); + for (i=0 ; i<7 ; i++) { + result |= init_vlc (&q->sqvh[i], vhvlcsize_tab[i], vhsize_tab[i], + cvh_huffbits[i], 1, 1, + cvh_huffcodes[i], 2, 2, 0); + } + + if (q->nb_channels==2 && q->joint_stereo==1){ + result |= init_vlc (&q->ccpl, 6, (1<js_vlc_bits)-1, + ccpl_huffbits[q->js_vlc_bits-2], 1, 1, + ccpl_huffcodes[q->js_vlc_bits-2], 2, 2, 0); + av_log(NULL,AV_LOG_DEBUG,"Joint-stereo VLC used.\n"); + } + + av_log(NULL,AV_LOG_DEBUG,"VLC tables initialized.\n"); + return result; +} + +static int init_cook_mlt(COOKContext *q) { + int j; + int mlt_size = q->samples_per_channel; + + if ((q->mlt_window = av_malloc(sizeof(float)*mlt_size)) == 0) + return -1; + + /* Initialize the MLT window: simple sine window. */ + ff_sine_window_init(q->mlt_window, mlt_size); + for(j=0 ; jmlt_window[j] *= sqrt(2.0 / q->samples_per_channel); + + /* Initialize the MDCT. */ + if (ff_mdct_init(&q->mdct_ctx, av_log2(mlt_size)+1, 1)) { + av_free(q->mlt_window); + return -1; + } + av_log(NULL,AV_LOG_DEBUG,"MDCT initialized, order = %d.\n", + av_log2(mlt_size)+1); + + return 0; +} + +static const float *maybe_reformat_buffer32 (COOKContext *q, const float *ptr, int n) +{ + if (1) + return ptr; +} + +static void init_cplscales_table (COOKContext *q) { + int i; + for (i=0;i<5;i++) + q->cplscales[i] = maybe_reformat_buffer32 (q, cplscales[i], (1<<(i+2))-1); +} + +/*************** init functions end ***********/ + +/** + * Cook indata decoding, every 32 bits are XORed with 0x37c511f2. + * Why? No idea, some checksum/error detection method maybe. + * + * Out buffer size: extra bytes are needed to cope with + * padding/misalignment. + * Subpackets passed to the decoder can contain two, consecutive + * half-subpackets, of identical but arbitrary size. + * 1234 1234 1234 1234 extraA extraB + * Case 1: AAAA BBBB 0 0 + * Case 2: AAAA ABBB BB-- 3 3 + * Case 3: AAAA AABB BBBB 2 2 + * Case 4: AAAA AAAB BBBB BB-- 1 5 + * + * Nice way to waste CPU cycles. + * + * @param inbuffer pointer to byte array of indata + * @param out pointer to byte array of outdata + * @param bytes number of bytes + */ +#define DECODE_BYTES_PAD1(bytes) (3 - ((bytes)+3) % 4) +#define DECODE_BYTES_PAD2(bytes) ((bytes) % 4 + DECODE_BYTES_PAD1(2 * (bytes))) + +static inline int decode_bytes(const uint8_t* inbuffer, uint8_t* out, int bytes){ + int i, off; + uint32_t c; + const uint32_t* buf; + uint32_t* obuf = (uint32_t*) out; + /* FIXME: 64 bit platforms would be able to do 64 bits at a time. + * I'm too lazy though, should be something like + * for(i=0 ; i> (off*8)) | (0x37c511f2 << (32-(off*8)))); + bytes += 3 + off; + for (i = 0; i < bytes/4; i++) + obuf[i] = c ^ buf[i]; + + return off; +} + +/** + * Cook uninit + */ + +static int cook_decode_close(AVCodecContext *avctx) +{ + int i; + COOKContext *q = avctx->priv_data; + av_log(avctx,AV_LOG_DEBUG, "Deallocating memory.\n"); + + /* Free allocated memory buffers. */ + av_free(q->mlt_window); + av_free(q->decoded_bytes_buffer); + + /* Free the transform. */ + ff_mdct_end(&q->mdct_ctx); + + /* Free the VLC tables. */ + for (i=0 ; i<13 ; i++) { + free_vlc(&q->envelope_quant_index[i]); + } + for (i=0 ; i<7 ; i++) { + free_vlc(&q->sqvh[i]); + } + if(q->nb_channels==2 && q->joint_stereo==1 ){ + free_vlc(&q->ccpl); + } + + av_log(NULL,AV_LOG_DEBUG,"Memory deallocated.\n"); + + return 0; +} + +/** + * Fill the gain array for the timedomain quantization. + * + * @param q pointer to the COOKContext + * @param gaininfo[9] array of gain indexes + */ + +static void decode_gain_info(GetBitContext *gb, int *gaininfo) +{ + int i, n; + + while (get_bits1(gb)) {} + n = get_bits_count(gb) - 1; //amount of elements*2 to update + + i = 0; + while (n--) { + int index = get_bits(gb, 3); + int gain = get_bits1(gb) ? get_bits(gb, 4) - 7 : -1; + + while (i <= index) gaininfo[i++] = gain; + } + while (i <= 8) gaininfo[i++] = 0; +} + +/** + * Create the quant index table needed for the envelope. + * + * @param q pointer to the COOKContext + * @param quant_index_table pointer to the array + */ + +static void decode_envelope(COOKContext *q, int* quant_index_table) { + int i,j, vlc_index; + + quant_index_table[0]= get_bits(&q->gb,6) - 6; //This is used later in categorize + + for (i=1 ; i < q->total_subbands ; i++){ + vlc_index=i; + if (i >= q->js_subband_start * 2) { + vlc_index-=q->js_subband_start; + } else { + vlc_index/=2; + if(vlc_index < 1) vlc_index = 1; + } + if (vlc_index>13) vlc_index = 13; //the VLC tables >13 are identical to No. 13 + + j = get_vlc2(&q->gb, q->envelope_quant_index[vlc_index-1].table, + q->envelope_quant_index[vlc_index-1].bits,2); + quant_index_table[i] = quant_index_table[i-1] + j - 12; //differential encoding + } +} + +/** + * Calculate the category and category_index vector. + * + * @param q pointer to the COOKContext + * @param quant_index_table pointer to the array + * @param category pointer to the category array + * @param category_index pointer to the category_index array + */ + +static void categorize(COOKContext *q, int* quant_index_table, + int* category, int* category_index){ + int exp_idx, bias, tmpbias1, tmpbias2, bits_left, num_bits, index, v, i, j; + int exp_index2[102]; + int exp_index1[102]; + + int tmp_categorize_array[128*2]; + int tmp_categorize_array1_idx=q->numvector_size; + int tmp_categorize_array2_idx=q->numvector_size; + + bits_left = q->bits_per_subpacket - get_bits_count(&q->gb); + + if(bits_left > q->samples_per_channel) { + bits_left = q->samples_per_channel + + ((bits_left - q->samples_per_channel)*5)/8; + //av_log(NULL, AV_LOG_ERROR, "bits_left = %d\n",bits_left); + } + + memset(&exp_index1,0,102*sizeof(int)); + memset(&exp_index2,0,102*sizeof(int)); + memset(&tmp_categorize_array,0,128*2*sizeof(int)); + + bias=-32; + + /* Estimate bias. */ + for (i=32 ; i>0 ; i=i/2){ + num_bits = 0; + index = 0; + for (j=q->total_subbands ; j>0 ; j--){ + exp_idx = av_clip((i - quant_index_table[index] + bias) / 2, 0, 7); + index++; + num_bits+=expbits_tab[exp_idx]; + } + if(num_bits >= bits_left - 32){ + bias+=i; + } + } + + /* Calculate total number of bits. */ + num_bits=0; + for (i=0 ; itotal_subbands ; i++) { + exp_idx = av_clip((bias - quant_index_table[i]) / 2, 0, 7); + num_bits += expbits_tab[exp_idx]; + exp_index1[i] = exp_idx; + exp_index2[i] = exp_idx; + } + tmpbias1 = tmpbias2 = num_bits; + + for (j = 1 ; j < q->numvector_size ; j++) { + if (tmpbias1 + tmpbias2 > 2*bits_left) { /* ---> */ + int max = -999999; + index=-1; + for (i=0 ; itotal_subbands ; i++){ + if (exp_index1[i] < 7) { + v = (-2*exp_index1[i]) - quant_index_table[i] + bias; + if ( v >= max) { + max = v; + index = i; + } + } + } + if(index==-1)break; + tmp_categorize_array[tmp_categorize_array1_idx++] = index; + tmpbias1 -= expbits_tab[exp_index1[index]] - + expbits_tab[exp_index1[index]+1]; + ++exp_index1[index]; + } else { /* <--- */ + int min = 999999; + index=-1; + for (i=0 ; itotal_subbands ; i++){ + if(exp_index2[i] > 0){ + v = (-2*exp_index2[i])-quant_index_table[i]+bias; + if ( v < min) { + min = v; + index = i; + } + } + } + if(index == -1)break; + tmp_categorize_array[--tmp_categorize_array2_idx] = index; + tmpbias2 -= expbits_tab[exp_index2[index]] - + expbits_tab[exp_index2[index]-1]; + --exp_index2[index]; + } + } + + for(i=0 ; itotal_subbands ; i++) + category[i] = exp_index2[i]; + + for(i=0 ; inumvector_size-1 ; i++) + category_index[i] = tmp_categorize_array[tmp_categorize_array2_idx++]; + +} + + +/** + * Expand the category vector. + * + * @param q pointer to the COOKContext + * @param category pointer to the category array + * @param category_index pointer to the category_index array + */ + +static inline void expand_category(COOKContext *q, int* category, + int* category_index){ + int i; + for(i=0 ; inum_vectors ; i++){ + ++category[category_index[i]]; + } +} + +/** + * The real requantization of the mltcoefs + * + * @param q pointer to the COOKContext + * @param index index + * @param quant_index quantisation index + * @param subband_coef_index array of indexes to quant_centroid_tab + * @param subband_coef_sign signs of coefficients + * @param mlt_p pointer into the mlt buffer + */ + +static void scalar_dequant_float(COOKContext *q, int index, int quant_index, + int* subband_coef_index, int* subband_coef_sign, + float* mlt_p){ + int i; + float f1; + + for(i=0 ; irandom_state) < 0x80000000) f1 = -f1; + } + mlt_p[i] = f1 * rootpow2tab[quant_index+63]; + } +} +/** + * Unpack the subband_coef_index and subband_coef_sign vectors. + * + * @param q pointer to the COOKContext + * @param category pointer to the category array + * @param subband_coef_index array of indexes to quant_centroid_tab + * @param subband_coef_sign signs of coefficients + */ + +static int unpack_SQVH(COOKContext *q, int category, int* subband_coef_index, + int* subband_coef_sign) { + int i,j; + int vlc, vd ,tmp, result; + + vd = vd_tab[category]; + result = 0; + for(i=0 ; igb, q->sqvh[category].table, q->sqvh[category].bits, 3); + if (q->bits_per_subpacket < get_bits_count(&q->gb)){ + vlc = 0; + result = 1; + } + for(j=vd-1 ; j>=0 ; j--){ + tmp = (vlc * invradix_tab[category])/0x100000; + subband_coef_index[vd*i+j] = vlc - tmp * (kmax_tab[category]+1); + vlc = tmp; + } + for(j=0 ; jgb) < q->bits_per_subpacket){ + subband_coef_sign[i*vd+j] = get_bits1(&q->gb); + } else { + result=1; + subband_coef_sign[i*vd+j]=0; + } + } else { + subband_coef_sign[i*vd+j]=0; + } + } + } + return result; +} + + +/** + * Fill the mlt_buffer with mlt coefficients. + * + * @param q pointer to the COOKContext + * @param category pointer to the category array + * @param quant_index_table pointer to the array + * @param mlt_buffer pointer to mlt coefficients + */ + + +static void decode_vectors(COOKContext* q, int* category, + int *quant_index_table, float* mlt_buffer){ + /* A zero in this table means that the subband coefficient is + random noise coded. */ + int subband_coef_index[SUBBAND_SIZE]; + /* A zero in this table means that the subband coefficient is a + positive multiplicator. */ + int subband_coef_sign[SUBBAND_SIZE]; + int band, j; + int index=0; + + for(band=0 ; bandtotal_subbands ; band++){ + index = category[band]; + if(category[band] < 7){ + if(unpack_SQVH(q, category[band], subband_coef_index, subband_coef_sign)){ + index=7; + for(j=0 ; jtotal_subbands ; j++) category[band+j]=7; + } + } + if(index==7) { + memset(subband_coef_index, 0, sizeof(subband_coef_index)); + memset(subband_coef_sign, 0, sizeof(subband_coef_sign)); + } + q->scalar_dequant(q, index, quant_index_table[band], + subband_coef_index, subband_coef_sign, + &mlt_buffer[band * SUBBAND_SIZE]); + } + + if(q->total_subbands*SUBBAND_SIZE >= q->samples_per_channel){ + return; + } /* FIXME: should this be removed, or moved into loop above? */ +} + + +/** + * function for decoding mono data + * + * @param q pointer to the COOKContext + * @param mlt_buffer pointer to mlt coefficients + */ + +static void mono_decode(COOKContext *q, float* mlt_buffer) { + + int category_index[128]; + int quant_index_table[102]; + int category[128]; + + memset(&category, 0, 128*sizeof(int)); + memset(&category_index, 0, 128*sizeof(int)); + + decode_envelope(q, quant_index_table); + q->num_vectors = get_bits(&q->gb,q->log2_numvector_size); + categorize(q, quant_index_table, category, category_index); + expand_category(q, category, category_index); + decode_vectors(q, category, quant_index_table, mlt_buffer); +} + + +/** + * the actual requantization of the timedomain samples + * + * @param q pointer to the COOKContext + * @param buffer pointer to the timedomain buffer + * @param gain_index index for the block multiplier + * @param gain_index_next index for the next block multiplier + */ + +static void interpolate_float(COOKContext *q, float* buffer, + int gain_index, int gain_index_next){ + int i; + float fc1, fc2; + fc1 = pow2tab[gain_index+63]; + + if(gain_index == gain_index_next){ //static gain + for(i=0 ; igain_size_factor ; i++){ + buffer[i]*=fc1; + } + return; + } else { //smooth gain + fc2 = q->gain_table[11 + (gain_index_next-gain_index)]; + for(i=0 ; igain_size_factor ; i++){ + buffer[i]*=fc1; + fc1*=fc2; + } + return; + } +} + +/** + * Apply transform window, overlap buffers. + * + * @param q pointer to the COOKContext + * @param inbuffer pointer to the mltcoefficients + * @param gains_ptr current and previous gains + * @param previous_buffer pointer to the previous buffer to be used for overlapping + */ + +static void imlt_window_float (COOKContext *q, float *buffer1, + cook_gains *gains_ptr, float *previous_buffer) +{ + const float fc = pow2tab[gains_ptr->previous[0] + 63]; + int i; + /* The weird thing here, is that the two halves of the time domain + * buffer are swapped. Also, the newest data, that we save away for + * next frame, has the wrong sign. Hence the subtraction below. + * Almost sounds like a complex conjugate/reverse data/FFT effect. + */ + + /* Apply window and overlap */ + for(i = 0; i < q->samples_per_channel; i++){ + buffer1[i] = buffer1[i] * fc * q->mlt_window[i] - + previous_buffer[i] * q->mlt_window[q->samples_per_channel - 1 - i]; + } +} + +/** + * The modulated lapped transform, this takes transform coefficients + * and transforms them into timedomain samples. + * Apply transform window, overlap buffers, apply gain profile + * and buffer management. + * + * @param q pointer to the COOKContext + * @param inbuffer pointer to the mltcoefficients + * @param gains_ptr current and previous gains + * @param previous_buffer pointer to the previous buffer to be used for overlapping + */ + +static void imlt_gain(COOKContext *q, float *inbuffer, + cook_gains *gains_ptr, float* previous_buffer) +{ + float *buffer0 = q->mono_mdct_output; + float *buffer1 = q->mono_mdct_output + q->samples_per_channel; + int i; + + /* Inverse modified discrete cosine transform */ + ff_imdct_calc(&q->mdct_ctx, q->mono_mdct_output, inbuffer); + + q->imlt_window (q, buffer1, gains_ptr, previous_buffer); + + /* Apply gain profile */ + for (i = 0; i < 8; i++) { + if (gains_ptr->now[i] || gains_ptr->now[i + 1]) + q->interpolate(q, &buffer1[q->gain_size_factor * i], + gains_ptr->now[i], gains_ptr->now[i + 1]); + } + + /* Save away the current to be previous block. */ + memcpy(previous_buffer, buffer0, sizeof(float)*q->samples_per_channel); +} + + +/** + * function for getting the jointstereo coupling information + * + * @param q pointer to the COOKContext + * @param decouple_tab decoupling array + * + */ + +static void decouple_info(COOKContext *q, int* decouple_tab){ + int length, i; + + if(get_bits1(&q->gb)) { + if(cplband[q->js_subband_start] > cplband[q->subbands-1]) return; + + length = cplband[q->subbands-1] - cplband[q->js_subband_start] + 1; + for (i=0 ; ijs_subband_start] + i] = get_vlc2(&q->gb, q->ccpl.table, q->ccpl.bits, 2); + } + return; + } + + if(cplband[q->js_subband_start] > cplband[q->subbands-1]) return; + + length = cplband[q->subbands-1] - cplband[q->js_subband_start] + 1; + for (i=0 ; ijs_subband_start] + i] = get_bits(&q->gb, q->js_vlc_bits); + } + return; +} + +/* + * function decouples a pair of signals from a single signal via multiplication. + * + * @param q pointer to the COOKContext + * @param subband index of the current subband + * @param f1 multiplier for channel 1 extraction + * @param f2 multiplier for channel 2 extraction + * @param decode_buffer input buffer + * @param mlt_buffer1 pointer to left channel mlt coefficients + * @param mlt_buffer2 pointer to right channel mlt coefficients + */ +static void decouple_float (COOKContext *q, + int subband, + float f1, float f2, + float *decode_buffer, + float *mlt_buffer1, float *mlt_buffer2) +{ + int j, tmp_idx; + for (j=0 ; jjs_subband_start + subband)*SUBBAND_SIZE)+j; + mlt_buffer1[SUBBAND_SIZE*subband + j] = f1 * decode_buffer[tmp_idx]; + mlt_buffer2[SUBBAND_SIZE*subband + j] = f2 * decode_buffer[tmp_idx]; + } +} + +/** + * function for decoding joint stereo data + * + * @param q pointer to the COOKContext + * @param mlt_buffer1 pointer to left channel mlt coefficients + * @param mlt_buffer2 pointer to right channel mlt coefficients + */ + +static void joint_decode(COOKContext *q, float* mlt_buffer1, + float* mlt_buffer2) { + int i,j; + int decouple_tab[SUBBAND_SIZE]; + float *decode_buffer = q->decode_buffer_0; + int idx, cpl_tmp; + float f1,f2; + const float* cplscale; + + memset(decouple_tab, 0, sizeof(decouple_tab)); + memset(decode_buffer, 0, sizeof(decode_buffer)); + + /* Make sure the buffers are zeroed out. */ + memset(mlt_buffer1,0, 1024*sizeof(float)); + memset(mlt_buffer2,0, 1024*sizeof(float)); + decouple_info(q, decouple_tab); + mono_decode(q, decode_buffer); + + /* The two channels are stored interleaved in decode_buffer. */ + for (i=0 ; ijs_subband_start ; i++) { + for (j=0 ; jjs_vlc_bits) - 1; + for (i=q->js_subband_start ; isubbands ; i++) { + cpl_tmp = cplband[i]; + idx -=decouple_tab[cpl_tmp]; + cplscale = q->cplscales[q->js_vlc_bits-2]; //choose decoupler table + f1 = cplscale[decouple_tab[cpl_tmp]]; + f2 = cplscale[idx-1]; + q->decouple (q, i, f1, f2, decode_buffer, mlt_buffer1, mlt_buffer2); + idx = (1 << q->js_vlc_bits) - 1; + } +} + +/** + * First part of subpacket decoding: + * decode raw stream bytes and read gain info. + * + * @param q pointer to the COOKContext + * @param inbuffer pointer to raw stream data + * @param gain_ptr array of current/prev gain pointers + */ + +static inline void +decode_bytes_and_gain(COOKContext *q, const uint8_t *inbuffer, + cook_gains *gains_ptr) +{ + int offset; + + offset = decode_bytes(inbuffer, q->decoded_bytes_buffer, + q->bits_per_subpacket/8); + init_get_bits(&q->gb, q->decoded_bytes_buffer + offset, + q->bits_per_subpacket); + decode_gain_info(&q->gb, gains_ptr->now); + + /* Swap current and previous gains */ + FFSWAP(int *, gains_ptr->now, gains_ptr->previous); +} + + /** + * Saturate the output signal to signed 16bit integers. + * + * @param q pointer to the COOKContext + * @param chan channel to saturate + * @param out pointer to the output vector + */ +static void +saturate_output_float (COOKContext *q, int chan, int16_t *out) +{ + int j; + float *output = q->mono_mdct_output + q->samples_per_channel; + /* Clip and convert floats to 16 bits. + */ + for (j = 0; j < q->samples_per_channel; j++) { + out[chan + q->nb_channels * j] = + av_clip_int16(lrintf(output[j])); + } +} + +/** + * Final part of subpacket decoding: + * Apply modulated lapped transform, gain compensation, + * clip and convert to integer. + * + * @param q pointer to the COOKContext + * @param decode_buffer pointer to the mlt coefficients + * @param gain_ptr array of current/prev gain pointers + * @param previous_buffer pointer to the previous buffer to be used for overlapping + * @param out pointer to the output buffer + * @param chan 0: left or single channel, 1: right channel + */ + +static inline void +mlt_compensate_output(COOKContext *q, float *decode_buffer, + cook_gains *gains, float *previous_buffer, + int16_t *out, int chan) +{ + imlt_gain(q, decode_buffer, gains, previous_buffer); + q->saturate_output (q, chan, out); +} + + +/** + * Cook subpacket decoding. This function returns one decoded subpacket, + * usually 1024 samples per channel. + * + * @param q pointer to the COOKContext + * @param inbuffer pointer to the inbuffer + * @param sub_packet_size subpacket size + * @param outbuffer pointer to the outbuffer + */ + + +static int decode_subpacket(COOKContext *q, const uint8_t *inbuffer, + int sub_packet_size, int16_t *outbuffer) { + /* packet dump */ +// for (i=0 ; igains1); + + if (q->joint_stereo) { + joint_decode(q, q->decode_buffer_1, q->decode_buffer_2); + } else { + mono_decode(q, q->decode_buffer_1); + + if (q->nb_channels == 2) { + decode_bytes_and_gain(q, inbuffer + sub_packet_size/2, &q->gains2); + mono_decode(q, q->decode_buffer_2); + } + } + + mlt_compensate_output(q, q->decode_buffer_1, &q->gains1, + q->mono_previous_buffer1, outbuffer, 0); + + if (q->nb_channels == 2) { + if (q->joint_stereo) { + mlt_compensate_output(q, q->decode_buffer_2, &q->gains1, + q->mono_previous_buffer2, outbuffer, 1); + } else { + mlt_compensate_output(q, q->decode_buffer_2, &q->gains2, + q->mono_previous_buffer2, outbuffer, 1); + } + } + return q->samples_per_frame * sizeof(int16_t); +} + + +/** + * Cook frame decoding + * + * @param avctx pointer to the AVCodecContext + */ + +static int cook_decode_frame(AVCodecContext *avctx, + void *data, int *data_size, + const uint8_t *buf, int buf_size) { + COOKContext *q = avctx->priv_data; + + if (buf_size < avctx->block_align) + return buf_size; + + *data_size = decode_subpacket(q, buf, avctx->block_align, data); + + /* Discard the first two frames: no valid audio. */ + if (avctx->frame_number < 2) *data_size = 0; + + return avctx->block_align; +} + +#ifdef COOKDEBUG +static void dump_cook_context(COOKContext *q) +{ + //int i=0; +#define PRINT(a,b) av_log(NULL,AV_LOG_ERROR," %s = %d\n", a, b); + av_log(NULL,AV_LOG_ERROR,"COOKextradata\n"); + av_log(NULL,AV_LOG_ERROR,"cookversion=%x\n",q->cookversion); + if (q->cookversion > STEREO) { + PRINT("js_subband_start",q->js_subband_start); + PRINT("js_vlc_bits",q->js_vlc_bits); + } + av_log(NULL,AV_LOG_ERROR,"COOKContext\n"); + PRINT("nb_channels",q->nb_channels); + PRINT("bit_rate",q->bit_rate); + PRINT("sample_rate",q->sample_rate); + PRINT("samples_per_channel",q->samples_per_channel); + PRINT("samples_per_frame",q->samples_per_frame); + PRINT("subbands",q->subbands); + PRINT("random_state",q->random_state); + PRINT("js_subband_start",q->js_subband_start); + PRINT("log2_numvector_size",q->log2_numvector_size); + PRINT("numvector_size",q->numvector_size); + PRINT("total_subbands",q->total_subbands); +} +#endif + +/** + * Cook initialization + * + * @param avctx pointer to the AVCodecContext + */ + +static int cook_decode_init(AVCodecContext *avctx) +{ + COOKContext *q = avctx->priv_data; + const uint8_t *edata_ptr = avctx->extradata; + + /* Take care of the codec specific extradata. */ + if (avctx->extradata_size <= 0) { + av_log(avctx,AV_LOG_ERROR,"Necessary extradata missing!\n"); + return -1; + } else { + /* 8 for mono, 16 for stereo, ? for multichannel + Swap to right endianness so we don't need to care later on. */ + av_log(avctx,AV_LOG_DEBUG,"codecdata_length=%d\n",avctx->extradata_size); + if (avctx->extradata_size >= 8){ + q->cookversion = bytestream_get_be32(&edata_ptr); + q->samples_per_frame = bytestream_get_be16(&edata_ptr); + q->subbands = bytestream_get_be16(&edata_ptr); + } + if (avctx->extradata_size >= 16){ + bytestream_get_be32(&edata_ptr); //Unknown unused + q->js_subband_start = bytestream_get_be16(&edata_ptr); + q->js_vlc_bits = bytestream_get_be16(&edata_ptr); + } + } + + /* Take data from the AVCodecContext (RM container). */ + q->sample_rate = avctx->sample_rate; + q->nb_channels = avctx->channels; + q->bit_rate = avctx->bit_rate; + + /* Initialize RNG. */ + av_init_random(1, &q->random_state); + + /* Initialize extradata related variables. */ + q->samples_per_channel = q->samples_per_frame / q->nb_channels; + q->bits_per_subpacket = avctx->block_align * 8; + + /* Initialize default data states. */ + q->log2_numvector_size = 5; + q->total_subbands = q->subbands; + + /* Initialize version-dependent variables */ + av_log(NULL,AV_LOG_DEBUG,"q->cookversion=%x\n",q->cookversion); + q->joint_stereo = 0; + switch (q->cookversion) { + case MONO: + if (q->nb_channels != 1) { + av_log(avctx,AV_LOG_ERROR,"Container channels != 1, report sample!\n"); + return -1; + } + av_log(avctx,AV_LOG_DEBUG,"MONO\n"); + break; + case STEREO: + if (q->nb_channels != 1) { + q->bits_per_subpacket = q->bits_per_subpacket/2; + } + av_log(avctx,AV_LOG_DEBUG,"STEREO\n"); + break; + case JOINT_STEREO: + if (q->nb_channels != 2) { + av_log(avctx,AV_LOG_ERROR,"Container channels != 2, report sample!\n"); + return -1; + } + av_log(avctx,AV_LOG_DEBUG,"JOINT_STEREO\n"); + if (avctx->extradata_size >= 16){ + q->total_subbands = q->subbands + q->js_subband_start; + q->joint_stereo = 1; + } + if (q->samples_per_channel > 256) { + q->log2_numvector_size = 6; + } + if (q->samples_per_channel > 512) { + q->log2_numvector_size = 7; + } + break; + case MC_COOK: + av_log(avctx,AV_LOG_ERROR,"MC_COOK not supported!\n"); + return -1; + break; + default: + av_log(avctx,AV_LOG_ERROR,"Unknown Cook version, report sample!\n"); + return -1; + break; + } + + /* Initialize variable relations */ + q->numvector_size = (1 << q->log2_numvector_size); + + /* Generate tables */ + init_pow2table(); + init_gain_table(q); + init_cplscales_table(q); + + if (init_cook_vlc_tables(q) != 0) + return -1; + + + if(avctx->block_align >= UINT_MAX/2) + return -1; + + /* Pad the databuffer with: + DECODE_BYTES_PAD1 or DECODE_BYTES_PAD2 for decode_bytes(), + FF_INPUT_BUFFER_PADDING_SIZE, for the bitstreamreader. */ + if (q->nb_channels==2 && q->joint_stereo==0) { + q->decoded_bytes_buffer = + av_mallocz(avctx->block_align/2 + + DECODE_BYTES_PAD2(avctx->block_align/2) + + FF_INPUT_BUFFER_PADDING_SIZE); + } else { + q->decoded_bytes_buffer = + av_mallocz(avctx->block_align + + DECODE_BYTES_PAD1(avctx->block_align) + + FF_INPUT_BUFFER_PADDING_SIZE); + } + if (q->decoded_bytes_buffer == NULL) + return -1; + + q->gains1.now = q->gain_1; + q->gains1.previous = q->gain_2; + q->gains2.now = q->gain_3; + q->gains2.previous = q->gain_4; + + /* Initialize transform. */ + if ( init_cook_mlt(q) != 0 ) + return -1; + + /* Initialize COOK signal arithmetic handling */ + if (1) { + q->scalar_dequant = scalar_dequant_float; + q->decouple = decouple_float; + q->imlt_window = imlt_window_float; + q->interpolate = interpolate_float; + q->saturate_output = saturate_output_float; + } + + /* Try to catch some obviously faulty streams, othervise it might be exploitable */ + if (q->total_subbands > 53) { + av_log(avctx,AV_LOG_ERROR,"total_subbands > 53, report sample!\n"); + return -1; + } + if (q->subbands > 50) { + av_log(avctx,AV_LOG_ERROR,"subbands > 50, report sample!\n"); + return -1; + } + if ((q->samples_per_channel == 256) || (q->samples_per_channel == 512) || (q->samples_per_channel == 1024)) { + } else { + av_log(avctx,AV_LOG_ERROR,"unknown amount of samples_per_channel = %d, report sample!\n",q->samples_per_channel); + return -1; + } + if ((q->js_vlc_bits > 6) || (q->js_vlc_bits < 0)) { + av_log(avctx,AV_LOG_ERROR,"q->js_vlc_bits = %d, only >= 0 and <= 6 allowed!\n",q->js_vlc_bits); + return -1; + } + + avctx->sample_fmt = SAMPLE_FMT_S16; + +#ifdef COOKDEBUG + dump_cook_context(q); +#endif + return 0; +} + + +AVCodec cook_decoder = +{ + .name = "cook", + .type = CODEC_TYPE_AUDIO, + .id = CODEC_ID_COOK, + .priv_data_size = sizeof(COOKContext), + .init = cook_decode_init, + .close = cook_decode_close, + .decode = cook_decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("COOK"), +}; diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/cookdata.h b/src/add-ons/media/plugins/avcodec/libavcodec/cookdata.h new file mode 100644 index 0000000000..c86577c6b7 --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/cookdata.h @@ -0,0 +1,563 @@ +/* + * COOK compatible decoder data + * Copyright (c) 2003 Sascha Sommer + * Copyright (c) 2005 Benjamin Larsson + * + * This file is part of FFmpeg. + * + * FFmpeg 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.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file cookdata.h + * Cook AKA RealAudio G2 compatible decoderdata + */ + +#ifndef FFMPEG_COOKDATA_H +#define FFMPEG_COOKDATA_H + +#include + +/* various data tables */ + +static const int expbits_tab[8] = { + 52,47,43,37,29,22,16,0, +}; + +static const float dither_tab[8] = { + 0.0, 0.0, 0.0, 0.0, 0.0, 0.176777, 0.25, 0.707107, +}; + +static const float quant_centroid_tab[7][14] = { + { 0.000, 0.392, 0.761, 1.120, 1.477, 1.832, 2.183, 2.541, 2.893, 3.245, 3.598, 3.942, 4.288, 4.724 }, + { 0.000, 0.544, 1.060, 1.563, 2.068, 2.571, 3.072, 3.562, 4.070, 4.620, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 0.746, 1.464, 2.180, 2.882, 3.584, 4.316, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 1.006, 2.000, 2.993, 3.985, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 1.321, 2.703, 3.983, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 1.657, 3.491, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 1.964, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 } +}; + +static const int invradix_tab[7] = { + 74899, 104858, 149797, 209716, 262144, 349526, 524288, +}; + +static const int kmax_tab[7] = { + 13, 9, 6, 4, 3, 2, 1, +}; + +static const int vd_tab[7] = { + 2, 2, 2, 4, 4, 5, 5, +}; + +static const int vpr_tab[7] = { + 10, 10, 10, 5, 5, 4, 4, +}; + + + +/* VLC data */ + +static const int vhsize_tab[7] = { + 191, 97, 48, 607, 246, 230, 32, +}; + +static const int vhvlcsize_tab[7] = { + 8, 7, 7, 10, 9, 9, 6, +}; + +static const uint8_t envelope_quant_index_huffbits[13][24] = { + { 4, 6, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 5, 7, 8, 9, 11, 11, 12, 12, 12, 12 }, + { 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 7, 9, 11, 12, 13, 15, 15, 15, 16, 16 }, + { 12, 10, 8, 6, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 5, 5, 7, 9, 11, 13, 14, 14 }, + { 13, 10, 9, 9, 7, 7, 5, 5, 4, 3, 3, 3, 3, 3, 4, 4, 4, 5, 7, 9, 11, 13, 13, 13 }, + { 12, 13, 10, 8, 6, 6, 5, 5, 4, 4, 3, 3, 3, 3, 3, 4, 5, 5, 6, 7, 9, 11, 14, 14 }, + { 12, 11, 9, 8, 8, 7, 5, 4, 4, 3, 3, 3, 3, 3, 4, 4, 5, 5, 7, 8, 10, 13, 14, 14 }, + { 15, 16, 15, 12, 10, 8, 6, 5, 4, 3, 3, 3, 2, 3, 4, 5, 5, 7, 9, 11, 13, 16, 16, 16 }, + { 14, 14, 11, 10, 9, 7, 7, 5, 5, 4, 3, 3, 2, 3, 3, 4, 5, 7, 9, 9, 12, 14, 15, 15 }, + { 9, 9, 9, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 13 }, + { 14, 12, 10, 8, 6, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 8, 8, 9, 11, 14, 14, 14 }, + { 13, 10, 9, 8, 6, 6, 5, 4, 4, 4, 3, 3, 2, 3, 4, 5, 6, 8, 9, 9, 11, 12, 14, 14 }, + { 16, 13, 12, 11, 9, 6, 5, 5, 4, 4, 4, 3, 2, 3, 3, 4, 5, 7, 8, 10, 14, 16, 16, 16 }, + { 13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14 }, +}; + +static const uint16_t envelope_quant_index_huffcodes[13][24] = { + {0x0006, 0x003e, 0x001c, 0x001d, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x0000, 0x0001, + 0x0002, 0x000d, 0x001e, 0x007e, 0x00fe, 0x01fe, 0x07fc, 0x07fd, 0x0ffc, 0x0ffd, 0x0ffe, 0x0fff}, + {0x03fe, 0x00fe, 0x003e, 0x001c, 0x001d, 0x000c, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x000d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x0ffe, 0x1ffe, 0x7ffc, 0x7ffd, 0x7ffe, 0xfffe, 0xffff}, + {0x0ffe, 0x03fe, 0x00fe, 0x003e, 0x001c, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x0000, + 0x0001, 0x0002, 0x000c, 0x000d, 0x001d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x1ffe, 0x3ffe, 0x3fff}, + {0x1ffc, 0x03fe, 0x01fc, 0x01fd, 0x007c, 0x007d, 0x001c, 0x001d, 0x000a, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x000b, 0x000c, 0x000d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x1ffd, 0x1ffe, 0x1fff}, + {0x0ffe, 0x1ffe, 0x03fe, 0x00fe, 0x003c, 0x003d, 0x001a, 0x001b, 0x000a, 0x000b, 0x0000, 0x0001, + 0x0002, 0x0003, 0x0004, 0x000c, 0x001c, 0x001d, 0x003e, 0x007e, 0x01fe, 0x07fe, 0x3ffe, 0x3fff}, + {0x0ffe, 0x07fe, 0x01fe, 0x00fc, 0x00fd, 0x007c, 0x001c, 0x000a, 0x000b, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x000c, 0x000d, 0x001d, 0x001e, 0x007d, 0x00fe, 0x03fe, 0x1ffe, 0x3ffe, 0x3fff}, + {0x7ffc, 0xfffc, 0x7ffd, 0x0ffe, 0x03fe, 0x00fe, 0x003e, 0x001c, 0x000c, 0x0002, 0x0003, 0x0004, + 0x0000, 0x0005, 0x000d, 0x001d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x1ffe, 0xfffd, 0xfffe, 0xffff}, + {0x3ffc, 0x3ffd, 0x07fe, 0x03fe, 0x01fc, 0x007c, 0x007d, 0x001c, 0x001d, 0x000c, 0x0002, 0x0003, + 0x0000, 0x0004, 0x0005, 0x000d, 0x001e, 0x007e, 0x01fd, 0x01fe, 0x0ffe, 0x3ffe, 0x7ffe, 0x7fff}, + {0x01fc, 0x01fd, 0x01fe, 0x00fc, 0x007c, 0x003c, 0x001c, 0x000c, 0x0000, 0x0001, 0x0002, 0x0003, + 0x0004, 0x0005, 0x000d, 0x001d, 0x003d, 0x007d, 0x00fd, 0x03fe, 0x07fe, 0x0ffe, 0x1ffe, 0x1fff}, + {0x3ffc, 0x0ffe, 0x03fe, 0x00fc, 0x003c, 0x003d, 0x001c, 0x000c, 0x0000, 0x0001, 0x0002, 0x0003, + 0x0004, 0x0005, 0x000d, 0x001d, 0x003e, 0x00fd, 0x00fe, 0x01fe, 0x07fe, 0x3ffd, 0x3ffe, 0x3fff}, + {0x1ffe, 0x03fe, 0x01fc, 0x00fc, 0x003c, 0x003d, 0x001c, 0x000a, 0x000b, 0x000c, 0x0002, 0x0003, + 0x0000, 0x0004, 0x000d, 0x001d, 0x003e, 0x00fd, 0x01fd, 0x01fe, 0x07fe, 0x0ffe, 0x3ffe, 0x3fff}, + {0xfffc, 0x1ffe, 0x0ffe, 0x07fe, 0x01fe, 0x003e, 0x001c, 0x001d, 0x000a, 0x000b, 0x000c, 0x0002, + 0x0000, 0x0003, 0x0004, 0x000d, 0x001e, 0x007e, 0x00fe, 0x03fe, 0x3ffe, 0xfffd, 0xfffe, 0xffff}, + {0x1ffc, 0x3ffa, 0x3ffb, 0x3ffc, 0x03fe, 0x00fe, 0x007c, 0x007d, 0x001c, 0x000c, 0x0002, 0x0003, + 0x0000, 0x0004, 0x0005, 0x000d, 0x001d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x3ffd, 0x3ffe, 0x3fff}, +}; + + +static const uint8_t cvh_huffbits0[191] = { + 1, 4, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, + 11, 11, 4, 5, 6, 7, 7, 8, 8, 9, 9, 9, + 9, 10, 11, 11, 5, 6, 7, 8, 8, 9, 9, 9, + 9, 10, 10, 10, 11, 12, 6, 7, 8, 9, 9, 9, + 9, 10, 10, 10, 10, 11, 12, 13, 7, 7, 8, 9, + 9, 9, 10, 10, 10, 10, 11, 11, 12, 13, 8, 8, + 9, 9, 9, 10, 10, 10, 10, 11, 11, 12, 13, 14, + 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, + 13, 15, 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, + 12, 13, 14, 15, 9, 9, 9, 10, 10, 10, 11, 11, + 12, 13, 12, 14, 15, 16, 9, 9, 10, 10, 10, 10, + 11, 12, 12, 14, 14, 16, 16, 0, 9, 9, 10, 10, + 11, 11, 12, 13, 13, 14, 14, 15, 0, 0, 10, 10, + 10, 11, 11, 12, 12, 13, 15, 15, 16, 0, 0, 0, + 11, 11, 11, 12, 13, 13, 13, 15, 16, 16, 0, 0, + 0, 0, 11, 11, 12, 13, 13, 14, 15, 16, 16, +}; + +static const uint16_t cvh_huffcodes0[191] = { + 0x0000,0x0008,0x002c,0x002d,0x0062,0x0063,0x00d4,0x00d5,0x00d6,0x01c6,0x01c7,0x03ca, + 0x07d6,0x07d7,0x0009,0x0014,0x002e,0x0064,0x0065,0x00d7,0x00d8,0x01c8,0x01c9,0x01ca, + 0x01cb,0x03cb,0x07d8,0x07d9,0x0015,0x002f,0x0066,0x00d9,0x00da,0x01cc,0x01cd,0x01ce, + 0x01cf,0x03cc,0x03cd,0x03ce,0x07da,0x0fe4,0x0030,0x0067,0x00db,0x01d0,0x01d1,0x01d2, + 0x01d3,0x03cf,0x03d0,0x03d1,0x03d2,0x07db,0x0fe5,0x1fea,0x0068,0x0069,0x00dc,0x01d4, + 0x01d5,0x01d6,0x03d3,0x03d4,0x03d5,0x03d6,0x07dc,0x07dd,0x0fe6,0x1feb,0x00dd,0x00de, + 0x01d7,0x01d8,0x01d9,0x03d7,0x03d8,0x03d9,0x03da,0x07de,0x07df,0x0fe7,0x1fec,0x3ff2, + 0x00df,0x00e0,0x01da,0x01db,0x03db,0x03dc,0x07e0,0x07e1,0x07e2,0x0fe8,0x0fe9,0x1fed, + 0x1fee,0x7ff4,0x00e1,0x00e2,0x01dc,0x01dd,0x03dd,0x03de,0x07e3,0x07e4,0x07e5,0x0fea, + 0x0feb,0x1fef,0x3ff3,0x7ff5,0x01de,0x01df,0x01e0,0x03df,0x03e0,0x03e1,0x07e6,0x07e7, + 0x0fec,0x1ff0,0x0fed,0x3ff4,0x7ff6,0xfff8,0x01e1,0x01e2,0x03e2,0x03e3,0x03e4,0x03e5, + 0x07e8,0x0fee,0x0fef,0x3ff5,0x3ff6,0xfff9,0xfffa,0xfffa,0x01e3,0x01e4,0x03e6,0x03e7, + 0x07e9,0x07ea,0x0ff0,0x1ff1,0x1ff2,0x3ff7,0x3ff8,0x7ff7,0x7ff7,0xfffa,0x03e8,0x03e9, + 0x03ea,0x07eb,0x07ec,0x0ff1,0x0ff2,0x1ff3,0x7ff8,0x7ff9,0xfffb,0x3ff8,0x7ff7,0x7ff7, + 0x07ed,0x07ee,0x07ef,0x0ff3,0x1ff4,0x1ff5,0x1ff6,0x7ffa,0xfffc,0xfffd,0xfffb,0xfffb, + 0x3ff8,0x7ff7,0x07f0,0x07f1,0x0ff4,0x1ff7,0x1ff8,0x3ff9,0x7ffb,0xfffe,0xffff, +}; + + +static const uint8_t cvh_huffbits1[97] = { + 1, 4, 5, 6, 7, 8, 8, 9, 10, 10, 4, 5, + 6, 7, 7, 8, 8, 9, 9, 11, 5, 5, 6, 7, + 8, 8, 9, 9, 10, 11, 6, 6, 7, 8, 8, 9, + 9, 10, 11, 12, 7, 7, 8, 8, 9, 9, 10, 11, + 11, 13, 8, 8, 8, 9, 9, 10, 10, 11, 12, 14, + 8, 8, 8, 9, 10, 11, 11, 12, 13, 15, 9, 9, + 9, 10, 11, 12, 12, 14, 14, 0, 9, 9, 9, 10, + 11, 12, 14, 16, 0, 0, 10, 10, 11, 12, 13, 14, + 16, +}; + + +static const uint16_t cvh_huffcodes1[97] = { + 0x0000,0x0008,0x0014,0x0030,0x006a,0x00e2,0x00e3,0x01e4,0x03ec,0x03ed,0x0009,0x0015, + 0x0031,0x006b,0x006c,0x00e4,0x00e5,0x01e5,0x01e6,0x07f0,0x0016,0x0017,0x0032,0x006d, + 0x00e6,0x00e7,0x01e7,0x01e8,0x03ee,0x07f1,0x0033,0x0034,0x006e,0x00e8,0x00e9,0x01e9, + 0x01ea,0x03ef,0x07f2,0x0ff6,0x006f,0x0070,0x00ea,0x00eb,0x01eb,0x01ec,0x03f0,0x07f3, + 0x07f4,0x1ffa,0x00ec,0x00ed,0x00ee,0x01ed,0x01ee,0x03f1,0x03f2,0x07f5,0x0ff7,0x3ffa, + 0x00ef,0x00f0,0x00f1,0x01ef,0x03f3,0x07f6,0x07f7,0x0ff8,0x1ffb,0x7ffe,0x01f0,0x01f1, + 0x01f2,0x03f4,0x07f8,0x0ff9,0x0ffa,0x3ffb,0x3ffc,0x0000,0x01f3,0x01f4,0x01f5,0x03f5, + 0x07f9,0x0ffb,0x3ffd,0xfffe,0x0000,0x0000,0x03f6,0x03f7,0x07fa,0x0ffc,0x1ffc,0x3ffe, + 0xffff, +}; + +static const uint8_t cvh_huffbits2[48] = { + 1, 4, 5, 7, 8, 9, 10, 3, 4, 5, 7, 8, + 9, 10, 5, 5, 6, 7, 8, 10, 10, 7, 6, 7, + 8, 9, 10, 12, 8, 8, 8, 9, 10, 12, 14, 8, + 9, 9, 10, 11, 15, 16, 9, 10, 11, 12, 13, 16, +}; + +static const uint16_t cvh_huffcodes2[48] = { + 0x0000,0x000a,0x0018,0x0074,0x00f2,0x01f4,0x03f6,0x0004,0x000b,0x0019,0x0075,0x00f3, + 0x01f5,0x03f7,0x001a,0x001b,0x0038,0x0076,0x00f4,0x03f8,0x03f9,0x0077,0x0039,0x0078, + 0x00f5,0x01f6,0x03fa,0x0ffc,0x00f6,0x00f7,0x00f8,0x01f7,0x03fb,0x0ffd,0x3ffe,0x00f9, + 0x01f8,0x01f9,0x03fc,0x07fc,0x7ffe,0xfffe,0x01fa,0x03fd,0x07fd,0x0ffe,0x1ffe,0xffff, +}; + +static const uint8_t cvh_huffbits3[607] = { + 2, 4, 6, 8, 10, 5, 5, 6, 8, 10, 7, 8, + 8, 10, 12, 9, 9, 10, 12, 15, 10, 11, 13, 16, + 16, 5, 6, 8, 10, 11, 5, 6, 8, 10, 12, 7, + 7, 8, 10, 13, 9, 9, 10, 12, 15, 12, 11, 13, + 16, 16, 7, 9, 10, 12, 15, 7, 8, 10, 12, 13, + 9, 9, 11, 13, 16, 11, 11, 12, 14, 16, 12, 12, + 14, 16, 0, 9, 11, 12, 16, 16, 9, 10, 13, 15, + 16, 10, 11, 12, 16, 16, 13, 13, 16, 16, 16, 16, + 16, 15, 16, 0, 11, 13, 16, 16, 15, 11, 13, 15, + 16, 16, 13, 13, 16, 16, 0, 14, 16, 16, 16, 0, + 16, 16, 0, 0, 0, 4, 6, 8, 10, 13, 6, 6, + 8, 10, 13, 9, 8, 10, 12, 16, 10, 10, 11, 15, + 16, 13, 12, 14, 16, 16, 5, 6, 8, 11, 13, 6, + 6, 8, 10, 13, 8, 8, 9, 11, 14, 10, 10, 12, + 12, 16, 13, 12, 13, 15, 16, 7, 8, 9, 12, 16, + 7, 8, 10, 12, 14, 9, 9, 10, 13, 16, 11, 10, + 12, 15, 16, 13, 13, 16, 16, 0, 9, 11, 13, 16, + 16, 9, 10, 12, 15, 16, 10, 11, 13, 16, 16, 13, + 12, 16, 16, 16, 16, 16, 16, 16, 0, 11, 13, 16, + 16, 16, 11, 13, 16, 16, 16, 12, 13, 15, 16, 0, + 16, 16, 16, 16, 0, 16, 16, 0, 0, 0, 6, 8, + 11, 13, 16, 8, 8, 10, 12, 16, 11, 10, 11, 13, + 16, 12, 13, 13, 15, 16, 16, 16, 14, 16, 0, 6, + 8, 10, 13, 16, 8, 8, 10, 12, 16, 10, 10, 11, + 13, 16, 13, 12, 13, 16, 16, 14, 14, 14, 16, 0, + 8, 9, 11, 13, 16, 8, 9, 11, 16, 14, 10, 10, + 12, 15, 16, 12, 12, 13, 16, 16, 15, 16, 16, 16, + 0, 10, 12, 15, 16, 16, 10, 12, 12, 14, 16, 12, + 12, 13, 16, 16, 14, 15, 16, 16, 0, 16, 16, 16, + 0, 0, 12, 15, 15, 16, 0, 13, 13, 16, 16, 0, + 14, 16, 16, 16, 0, 16, 16, 16, 0, 0, 0, 0, + 0, 0, 0, 8, 10, 13, 15, 16, 10, 11, 13, 16, + 16, 13, 13, 14, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 0, 8, 10, 11, 15, 16, 9, 10, 12, + 16, 16, 12, 12, 15, 16, 16, 16, 14, 16, 16, 16, + 16, 16, 16, 16, 0, 9, 11, 14, 16, 16, 10, 11, + 13, 16, 16, 14, 13, 14, 16, 16, 16, 15, 15, 16, + 0, 16, 16, 16, 0, 0, 11, 13, 16, 16, 16, 11, + 13, 15, 16, 16, 13, 16, 16, 16, 0, 16, 16, 16, + 16, 0, 16, 16, 0, 0, 0, 15, 16, 16, 16, 0, + 14, 16, 16, 16, 0, 16, 16, 16, 0, 0, 16, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 13, 16, 16, + 16, 11, 13, 16, 16, 16, 14, 15, 16, 16, 0, 15, + 16, 16, 16, 0, 16, 16, 0, 0, 0, 9, 13, 15, + 15, 16, 12, 13, 14, 16, 16, 16, 15, 16, 16, 0, + 16, 16, 16, 16, 0, 16, 16, 0, 0, 0, 11, 13, + 15, 16, 0, 12, 14, 16, 16, 0, 16, 16, 16, 16, + 0, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 16, + 16, 16, 16, 0, 16, 16, 16, 16, 0, 16, 16, 16, + 0, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 0, 0, 0, 16, 16, +}; + + +static const uint16_t cvh_huffcodes3[607] = { + 0x0000,0x0004,0x0022,0x00c6,0x03b0,0x000c,0x000d,0x0023,0x00c7,0x03b1,0x005c,0x00c8, + 0x00c9,0x03b2,0x0fa4,0x01c2,0x01c3,0x03b3,0x0fa5,0x7f72,0x03b4,0x07b2,0x1f9a,0xff24, + 0xff25,0x000e,0x0024,0x00ca,0x03b5,0x07b3,0x000f,0x0025,0x00cb,0x03b6,0x0fa6,0x005d, + 0x005e,0x00cc,0x03b7,0x1f9b,0x01c4,0x01c5,0x03b8,0x0fa7,0x7f73,0x0fa8,0x07b4,0x1f9c, + 0xff26,0xff27,0x005f,0x01c6,0x03b9,0x0fa9,0x7f74,0x0060,0x00cd,0x03ba,0x0faa,0x1f9d, + 0x01c7,0x01c8,0x07b5,0x1f9e,0xff28,0x07b6,0x07b7,0x0fab,0x3fa2,0xff29,0x0fac,0x0fad, + 0x3fa3,0xff2a,0x3fa2,0x01c9,0x07b8,0x0fae,0xff2b,0xff2c,0x01ca,0x03bb,0x1f9f,0x7f75, + 0xff2d,0x03bc,0x07b9,0x0faf,0xff2e,0xff2f,0x1fa0,0x1fa1,0xff30,0xff31,0xff32,0xff33, + 0xff34,0x7f76,0xff35,0xff31,0x07ba,0x1fa2,0xff36,0xff37,0x7f77,0x07bb,0x1fa3,0x7f78, + 0xff38,0xff39,0x1fa4,0x1fa5,0xff3a,0xff3b,0xff2e,0x3fa4,0xff3c,0xff3d,0xff3e,0xff31, + 0xff3f,0xff40,0xff30,0xff31,0xff31,0x0005,0x0026,0x00ce,0x03bd,0x1fa6,0x0027,0x0028, + 0x00cf,0x03be,0x1fa7,0x01cb,0x00d0,0x03bf,0x0fb0,0xff41,0x03c0,0x03c1,0x07bc,0x7f79, + 0xff42,0x1fa8,0x0fb1,0x3fa5,0xff43,0xff44,0x0010,0x0029,0x00d1,0x07bd,0x1fa9,0x002a, + 0x002b,0x00d2,0x03c2,0x1faa,0x00d3,0x00d4,0x01cc,0x07be,0x3fa6,0x03c3,0x03c4,0x0fb2, + 0x0fb3,0xff45,0x1fab,0x0fb4,0x1fac,0x7f7a,0xff46,0x0061,0x00d5,0x01cd,0x0fb5,0xff47, + 0x0062,0x00d6,0x03c5,0x0fb6,0x3fa7,0x01ce,0x01cf,0x03c6,0x1fad,0xff48,0x07bf,0x03c7, + 0x0fb7,0x7f7b,0xff49,0x1fae,0x1faf,0xff4a,0xff4b,0x7f7b,0x01d0,0x07c0,0x1fb0,0xff4c, + 0xff4d,0x01d1,0x03c8,0x0fb8,0x7f7c,0xff4e,0x03c9,0x07c1,0x1fb1,0xff4f,0xff50,0x1fb2, + 0x0fb9,0xff51,0xff52,0xff53,0xff54,0xff55,0xff56,0xff57,0xff52,0x07c2,0x1fb3,0xff58, + 0xff59,0xff5a,0x07c3,0x1fb4,0xff5b,0xff5c,0xff5d,0x0fba,0x1fb5,0x7f7d,0xff5e,0xff4f, + 0xff5f,0xff60,0xff61,0xff62,0xff52,0xff63,0xff64,0xff51,0xff52,0xff52,0x002c,0x00d7, + 0x07c4,0x1fb6,0xff65,0x00d8,0x00d9,0x03ca,0x0fbb,0xff66,0x07c5,0x03cb,0x07c6,0x1fb7, + 0xff67,0x0fbc,0x1fb8,0x1fb9,0x7f7e,0xff68,0xff69,0xff6a,0x3fa8,0xff6b,0x7f7e,0x002d, + 0x00da,0x03cc,0x1fba,0xff6c,0x00db,0x00dc,0x03cd,0x0fbd,0xff6d,0x03ce,0x03cf,0x07c7, + 0x1fbb,0xff6e,0x1fbc,0x0fbe,0x1fbd,0xff6f,0xff70,0x3fa9,0x3faa,0x3fab,0xff71,0xff6f, + 0x00dd,0x01d2,0x07c8,0x1fbe,0xff72,0x00de,0x01d3,0x07c9,0xff73,0x3fac,0x03d0,0x03d1, + 0x0fbf,0x7f7f,0xff74,0x0fc0,0x0fc1,0x1fbf,0xff75,0xff76,0x7f80,0xff77,0xff78,0xff79, + 0xff75,0x03d2,0x0fc2,0x7f81,0xff7a,0xff7b,0x03d3,0x0fc3,0x0fc4,0x3fad,0xff7c,0x0fc5, + 0x0fc6,0x1fc0,0xff7d,0xff7e,0x3fae,0x7f82,0xff7f,0xff80,0xff80,0xff81,0xff82,0xff83, + 0xff80,0xff80,0x0fc7,0x7f83,0x7f84,0xff84,0xff7a,0x1fc1,0x1fc2,0xff85,0xff86,0x3fad, + 0x3faf,0xff87,0xff88,0xff89,0xff7d,0xff8a,0xff8b,0xff8c,0xff80,0xff80,0x3fae,0x7f82, + 0xff7f,0xff80,0xff80,0x00df,0x03d4,0x1fc3,0x7f85,0xff8d,0x03d5,0x07ca,0x1fc4,0xff8e, + 0xff8f,0x1fc5,0x1fc6,0x3fb0,0xff90,0xff91,0xff92,0xff93,0xff94,0xff95,0xff96,0xff97, + 0xff98,0xff99,0xff9a,0xff95,0x00e0,0x03d6,0x07cb,0x7f86,0xff9b,0x01d4,0x03d7,0x0fc8, + 0xff9c,0xff9d,0x0fc9,0x0fca,0x7f87,0xff9e,0xff9f,0xffa0,0x3fb1,0xffa1,0xffa2,0xffa3, + 0xffa4,0xffa5,0xffa6,0xffa7,0xffa2,0x01d5,0x07cc,0x3fb2,0xffa8,0xffa9,0x03d8,0x07cd, + 0x1fc7,0xffaa,0xffab,0x3fb3,0x1fc8,0x3fb4,0xffac,0xffad,0xffae,0x7f88,0x7f89,0xffaf, + 0xffaf,0xffb0,0xffb1,0xffb2,0xffaf,0xffaf,0x07ce,0x1fc9,0xffb3,0xffb4,0xffb5,0x07cf, + 0x1fca,0x7f8a,0xffb6,0xffb7,0x1fcb,0xffb8,0xffb9,0xffba,0xffba,0xffbb,0xffbc,0xffbd, + 0xffbe,0xffbe,0xffbf,0xffc0,0xffbd,0xffbe,0xffbe,0x7f8b,0xffc1,0xffc2,0xffc3,0xffb4, + 0x3fb5,0xffc4,0xffc5,0xffc6,0xffb6,0xffc7,0xffc8,0xffc9,0xffba,0xffba,0xffca,0xffcb, + 0xffbd,0xffbe,0xffbe,0xffbb,0xffbc,0xffbd,0xffbe,0xffbe,0x01d6,0x1fcc,0xffcc,0xffcd, + 0xffce,0x07d0,0x1fcd,0xffcf,0xffd0,0xffd1,0x3fb6,0x7f8c,0xffd2,0xffd3,0xff90,0x7f8d, + 0xffd4,0xffd5,0xffd6,0xff95,0xffd7,0xffd8,0xff94,0xff95,0xff95,0x01d7,0x1fce,0x7f8e, + 0x7f8f,0xffd9,0x0fcb,0x1fcf,0x3fb7,0xffda,0xffdb,0xffdc,0x7f90,0xffdd,0xffde,0xff9e, + 0xffdf,0xffe0,0xffe1,0xffe2,0xffa2,0xffe3,0xffe4,0xffa1,0xffa2,0xffa2,0x07d1,0x1fd0, + 0x7f91,0xffe5,0xffa8,0x0fcc,0x3fb8,0xffe6,0xffe7,0xffaa,0xffe8,0xffe9,0xffea,0xffeb, + 0xffac,0xffec,0xffed,0xffee,0xffaf,0xffaf,0xffae,0x7f88,0x7f89,0xffaf,0xffaf,0xffef, + 0xfff0,0xfff1,0xfff2,0xffb4,0xfff3,0xfff4,0xfff5,0xfff6,0xffb6,0xfff7,0xfff8,0xfff9, + 0xffba,0xffba,0xfffa,0xfffb,0xffbd,0xffbe,0xffbe,0xffbb,0xffbc,0xffbd,0xffbe,0xffbe, + 0xfffc,0xfffd,0xffb3,0xffb4,0xffb4,0xfffe,0xffff, +}; + +static const uint8_t cvh_huffbits4[246] = { + 2, 4, 7, 10, 4, 5, 7, 10, 7, 8, 10, 14, + 11, 11, 15, 15, 4, 5, 9, 12, 5, 5, 8, 12, + 8, 7, 10, 15, 11, 11, 15, 15, 7, 9, 12, 15, + 8, 8, 12, 15, 10, 10, 13, 15, 14, 14, 15, 0, + 11, 13, 15, 15, 11, 13, 15, 15, 14, 15, 15, 0, + 15, 15, 0, 0, 4, 5, 9, 13, 5, 6, 9, 13, + 9, 9, 11, 15, 14, 13, 15, 15, 4, 6, 9, 12, + 5, 6, 9, 13, 9, 8, 11, 15, 13, 12, 15, 15, + 7, 9, 12, 15, 7, 8, 11, 15, 10, 10, 14, 15, + 14, 15, 15, 0, 10, 12, 15, 15, 11, 13, 15, 15, + 15, 15, 15, 0, 15, 15, 0, 0, 6, 9, 13, 14, + 8, 9, 12, 15, 12, 12, 15, 15, 15, 15, 15, 0, + 7, 9, 13, 15, 8, 9, 12, 15, 11, 12, 15, 15, + 15, 15, 15, 0, 9, 11, 15, 15, 9, 11, 15, 15, + 14, 14, 15, 0, 15, 15, 0, 0, 14, 15, 15, 0, + 14, 15, 15, 0, 15, 15, 0, 0, 0, 0, 0, 0, + 9, 12, 15, 15, 12, 13, 15, 15, 15, 15, 15, 0, + 15, 15, 0, 0, 10, 12, 15, 15, 12, 14, 15, 15, + 15, 15, 15, 0, 15, 15, 0, 0, 14, 15, 15, 0, + 15, 15, 15, 0, 15, 15, 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 15, 15, +}; + + +static const uint16_t cvh_huffcodes4[246] = { + 0x0000,0x0004,0x006c,0x03e6,0x0005,0x0012,0x006d,0x03e7,0x006e,0x00e8,0x03e8,0x3fc4, + 0x07e0,0x07e1,0x7fa4,0x7fa5,0x0006,0x0013,0x01e2,0x0fda,0x0014,0x0015,0x00e9,0x0fdb, + 0x00ea,0x006f,0x03e9,0x7fa6,0x07e2,0x07e3,0x7fa7,0x7fa8,0x0070,0x01e3,0x0fdc,0x7fa9, + 0x00eb,0x00ec,0x0fdd,0x7faa,0x03ea,0x03eb,0x1fd6,0x7fab,0x3fc5,0x3fc6,0x7fac,0x1fd6, + 0x07e4,0x1fd7,0x7fad,0x7fae,0x07e5,0x1fd8,0x7faf,0x7fb0,0x3fc7,0x7fb1,0x7fb2,0x1fd6, + 0x7fb3,0x7fb4,0x1fd6,0x1fd6,0x0007,0x0016,0x01e4,0x1fd9,0x0017,0x0032,0x01e5,0x1fda, + 0x01e6,0x01e7,0x07e6,0x7fb5,0x3fc8,0x1fdb,0x7fb6,0x7fb7,0x0008,0x0033,0x01e8,0x0fde, + 0x0018,0x0034,0x01e9,0x1fdc,0x01ea,0x00ed,0x07e7,0x7fb8,0x1fdd,0x0fdf,0x7fb9,0x7fba, + 0x0071,0x01eb,0x0fe0,0x7fbb,0x0072,0x00ee,0x07e8,0x7fbc,0x03ec,0x03ed,0x3fc9,0x7fbd, + 0x3fca,0x7fbe,0x7fbf,0x3fc9,0x03ee,0x0fe1,0x7fc0,0x7fc1,0x07e9,0x1fde,0x7fc2,0x7fc3, + 0x7fc4,0x7fc5,0x7fc6,0x3fc9,0x7fc7,0x7fc8,0x3fc9,0x3fc9,0x0035,0x01ec,0x1fdf,0x3fcb, + 0x00ef,0x01ed,0x0fe2,0x7fc9,0x0fe3,0x0fe4,0x7fca,0x7fcb,0x7fcc,0x7fcd,0x7fce,0x7fca, + 0x0073,0x01ee,0x1fe0,0x7fcf,0x00f0,0x01ef,0x0fe5,0x7fd0,0x07ea,0x0fe6,0x7fd1,0x7fd2, + 0x7fd3,0x7fd4,0x7fd5,0x7fd1,0x01f0,0x07eb,0x7fd6,0x7fd7,0x01f1,0x07ec,0x7fd8,0x7fd9, + 0x3fcc,0x3fcd,0x7fda,0x7fda,0x7fdb,0x7fdc,0x7fda,0x7fda,0x3fce,0x7fdd,0x7fde,0x7fd6, + 0x3fcf,0x7fdf,0x7fe0,0x7fd8,0x7fe1,0x7fe2,0x7fda,0x7fda,0x3fcc,0x3fcd,0x7fda,0x7fda, + 0x01f2,0x0fe7,0x7fe3,0x7fe4,0x0fe8,0x1fe1,0x7fe5,0x7fe6,0x7fe7,0x7fe8,0x7fe9,0x7fca, + 0x7fea,0x7feb,0x7fca,0x7fca,0x03ef,0x0fe9,0x7fec,0x7fed,0x0fea,0x3fd0,0x7fee,0x7fef, + 0x7ff0,0x7ff1,0x7ff2,0x7fd1,0x7ff3,0x7ff4,0x7fd1,0x7fd1,0x3fd1,0x7ff5,0x7ff6,0x7fd6, + 0x7ff7,0x7ff8,0x7ff9,0x7fd8,0x7ffa,0x7ffb,0x7fda,0x7fda,0x3fcc,0x3fcd,0x7fda,0x7fda, + 0x7ffc,0x7ffd,0x7fd6,0x7fd6,0x7ffe,0x7fff, +}; + + +static const uint8_t cvh_huffbits5[230] = { + 2, 4, 8, 4, 5, 9, 9, 10, 14, 4, 6, 11, + 5, 6, 12, 10, 11, 15, 9, 11, 15, 10, 13, 15, + 14, 15, 0, 4, 6, 12, 6, 7, 12, 12, 12, 15, + 5, 7, 13, 6, 7, 13, 12, 13, 15, 10, 12, 15, + 11, 13, 15, 15, 15, 0, 8, 13, 15, 11, 12, 15, + 15, 15, 0, 10, 13, 15, 12, 15, 15, 15, 15, 0, + 15, 15, 0, 15, 15, 0, 0, 0, 0, 4, 5, 11, + 5, 7, 12, 11, 12, 15, 6, 7, 13, 7, 8, 14, + 12, 14, 15, 11, 13, 15, 12, 13, 15, 15, 15, 0, + 5, 6, 13, 7, 8, 15, 12, 14, 15, 6, 8, 14, + 7, 8, 15, 14, 15, 15, 12, 12, 15, 12, 13, 15, + 15, 15, 0, 9, 13, 15, 12, 13, 15, 15, 15, 0, + 11, 13, 15, 13, 13, 15, 15, 15, 0, 14, 15, 0, + 15, 15, 0, 0, 0, 0, 8, 10, 15, 11, 12, 15, + 15, 15, 0, 10, 12, 15, 12, 13, 15, 15, 15, 0, + 14, 15, 0, 15, 15, 0, 0, 0, 0, 8, 12, 15, + 12, 13, 15, 15, 15, 0, 11, 13, 15, 13, 15, 15, + 15, 15, 0, 15, 15, 0, 15, 15, 0, 0, 0, 0, + 14, 15, 0, 15, 15, 0, 0, 0, 0, 15, 15, 0, + 15, 15, +}; + + + +static const uint16_t cvh_huffcodes5[230] = { + 0x0000,0x0004,0x00f0,0x0005,0x0012,0x01f0,0x01f1,0x03e8,0x3fce,0x0006,0x0030,0x07de, + 0x0013,0x0031,0x0fd2,0x03e9,0x07df,0x7fb0,0x01f2,0x07e0,0x7fb1,0x03ea,0x1fd2,0x7fb2, + 0x3fcf,0x7fb3,0x0031,0x0007,0x0032,0x0fd3,0x0033,0x0070,0x0fd4,0x0fd5,0x0fd6,0x7fb4, + 0x0014,0x0071,0x1fd3,0x0034,0x0072,0x1fd4,0x0fd7,0x1fd5,0x7fb5,0x03eb,0x0fd8,0x7fb6, + 0x07e1,0x1fd6,0x7fb7,0x7fb8,0x7fb9,0x0072,0x00f1,0x1fd7,0x7fba,0x07e2,0x0fd9,0x7fbb, + 0x7fbc,0x7fbd,0x0070,0x03ec,0x1fd8,0x7fbe,0x0fda,0x7fbf,0x7fc0,0x7fc1,0x7fc2,0x0072, + 0x7fc3,0x7fc4,0x0071,0x7fc5,0x7fc6,0x0072,0x0034,0x0072,0x0072,0x0008,0x0015,0x07e3, + 0x0016,0x0073,0x0fdb,0x07e4,0x0fdc,0x7fc7,0x0035,0x0074,0x1fd9,0x0075,0x00f2,0x3fd0, + 0x0fdd,0x3fd1,0x7fc8,0x07e5,0x1fda,0x7fc9,0x0fde,0x1fdb,0x7fca,0x7fcb,0x7fcc,0x00f2, + 0x0017,0x0036,0x1fdc,0x0076,0x00f3,0x7fcd,0x0fdf,0x3fd2,0x7fce,0x0037,0x00f4,0x3fd3, + 0x0077,0x00f5,0x7fcf,0x3fd4,0x7fd0,0x7fd1,0x0fe0,0x0fe1,0x7fd2,0x0fe2,0x1fdd,0x7fd3, + 0x7fd4,0x7fd5,0x00f5,0x01f3,0x1fde,0x7fd6,0x0fe3,0x1fdf,0x7fd7,0x7fd8,0x7fd9,0x00f3, + 0x07e6,0x1fe0,0x7fda,0x1fe1,0x1fe2,0x7fdb,0x7fdc,0x7fdd,0x00f5,0x3fd5,0x7fde,0x00f4, + 0x7fdf,0x7fe0,0x00f5,0x0077,0x00f5,0x00f5,0x00f6,0x03ed,0x7fe1,0x07e7,0x0fe4,0x7fe2, + 0x7fe3,0x7fe4,0x0073,0x03ee,0x0fe5,0x7fe5,0x0fe6,0x1fe3,0x7fe6,0x7fe7,0x7fe8,0x00f2, + 0x3fd6,0x7fe9,0x0074,0x7fea,0x7feb,0x00f2,0x0075,0x00f2,0x00f2,0x00f7,0x0fe7,0x7fec, + 0x0fe8,0x1fe4,0x7fed,0x7fee,0x7fef,0x00f3,0x07e8,0x1fe5,0x7ff0,0x1fe6,0x7ff1,0x7ff2, + 0x7ff3,0x7ff4,0x00f5,0x7ff5,0x7ff6,0x00f4,0x7ff7,0x7ff8,0x00f5,0x0077,0x00f5,0x00f5, + 0x3fd7,0x7ff9,0x0036,0x7ffa,0x7ffb,0x00f3,0x0076,0x00f3,0x00f3,0x7ffc,0x7ffd,0x0000, + 0x7ffe,0x7fff, +}; + + +static const uint8_t cvh_huffbits6[32] = { + 1, 4, 4, 6, 4, 6, 6, 8, 4, 6, 6, 8, + 6, 9, 8, 10, 4, 6, 7, 8, 6, 9, 8, 11, + 6, 9, 8, 10, 8, 10, 9, 11, +}; + +static const uint16_t cvh_huffcodes6[32] = { + 0x0000,0x0008,0x0009,0x0034,0x000a,0x0035,0x0036,0x00f6,0x000b,0x0037,0x0038,0x00f7, + 0x0039,0x01fa,0x00f8,0x03fc,0x000c,0x003a,0x007a,0x00f9,0x003b,0x01fb,0x00fa,0x07fe, + 0x003c,0x01fc,0x00fb,0x03fd,0x00fc,0x03fe,0x01fd,0x07ff, +}; + +static const uint16_t* const cvh_huffcodes[7] = { + cvh_huffcodes0, cvh_huffcodes1, cvh_huffcodes2, cvh_huffcodes3, + cvh_huffcodes4, cvh_huffcodes5, cvh_huffcodes6, +}; + +static const uint8_t* const cvh_huffbits[7] = { + cvh_huffbits0, cvh_huffbits1, cvh_huffbits2, cvh_huffbits3, + cvh_huffbits4, cvh_huffbits5, cvh_huffbits6, +}; + + +static const uint16_t ccpl_huffcodes2[3] = { + 0x02,0x00,0x03, +}; + +static const uint16_t ccpl_huffcodes3[7] = { + 0x3e,0x1e,0x02,0x00,0x06,0x0e,0x3f, +}; + +static const uint16_t ccpl_huffcodes4[15] = { + 0xfc,0xfd,0x7c,0x3c,0x1c,0x0c,0x04,0x00,0x05,0x0d,0x1d,0x3d, + 0x7d,0xfe,0xff, +}; + +static const uint16_t ccpl_huffcodes5[31] = { + 0x03f8,0x03f9,0x03fa,0x03fb,0x01f8,0x01f9,0x00f8,0x00f9,0x0078,0x0079,0x0038,0x0039, + 0x0018,0x0019,0x0004,0x0000,0x0005,0x001a,0x001b,0x003a,0x003b,0x007a,0x007b,0x00fa, + 0x00fb,0x01fa,0x01fb,0x03fc,0x03fd,0x03fe,0x03ff, +}; + +static const uint16_t ccpl_huffcodes6[63] = { + 0x0004,0x0005,0x0005,0x0006,0x0006,0x0007,0x0007,0x0007,0x0007,0x0008,0x0008,0x0008, + 0x0008,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b, + 0x000b,0x000b,0x000c,0x000d,0x000e,0x000e,0x0010,0x0000,0x000a,0x0018,0x0019,0x0036, + 0x0037,0x0074,0x0075,0x0076,0x0077,0x00f4,0x00f5,0x00f6,0x00f7,0x01f5,0x01f6,0x01f7, + 0x01f8,0x03f6,0x03f7,0x03f8,0x03f9,0x03fa,0x07fa,0x07fb,0x07fc,0x07fd,0x0ffd,0x1ffd, + 0x3ffd,0x3ffe,0xffff, +}; + +static const uint8_t ccpl_huffbits2[3] = { + 2,1,2, +}; + +static const uint8_t ccpl_huffbits3[7] = { + 6,5,2,1,3,4,6, +}; + +static const uint8_t ccpl_huffbits4[15] = { + 8,8,7,6,5,4,3,1,3,4,5,6,7,8,8, +}; + +static const uint8_t ccpl_huffbits5[31] = { + 10,10,10,10,9,9,8,8,7,7,6,6, + 5,5,3,1,3,5,5,6,6,7,7,8, + 8,9,9,10,10,10,10, +}; + +static const uint8_t ccpl_huffbits6[63] = { + 16,15,14,13,12,11,11,11,11,10,10,10, + 10,9,9,9,9,9,8,8,8,8,7,7, + 7,7,6,6,5,5,3,1,4,5,5,6, + 6,7,7,7,7,8,8,8,8,9,9,9, + 9,10,10,10,10,10,11,11,11,11,12,13, + 14,14,16, +}; + +static const uint16_t* const ccpl_huffcodes[5] = { + ccpl_huffcodes2,ccpl_huffcodes3, + ccpl_huffcodes4,ccpl_huffcodes5,ccpl_huffcodes6 +}; + +static const uint8_t* const ccpl_huffbits[5] = { + ccpl_huffbits2,ccpl_huffbits3, + ccpl_huffbits4,ccpl_huffbits5,ccpl_huffbits6 +}; + + +//Coupling tables + +static const int cplband[51] = { + 0,1,2,3,4,5,6,7,8,9, + 10,11,11,12,12,13,13,14,14,14, + 15,15,15,15,16,16,16,16,16,17, + 17,17,17,17,17,18,18,18,18,18, + 18,18,19,19,19,19,19,19,19,19, + 19, +}; + +static const float cplscale2[3] = { +0.953020632266998,0.70710676908493,0.302905440330505, +}; + +static const float cplscale3[7] = { +0.981279790401459,0.936997592449188,0.875934481620789,0.70710676908493, +0.482430040836334,0.349335819482803,0.192587479948997, +}; + +static const float cplscale4[15] = { +0.991486728191376,0.973249018192291,0.953020632266998,0.930133521556854, +0.903453230857849,0.870746195316315,0.826180458068848,0.70710676908493, +0.563405573368073,0.491732746362686,0.428686618804932,0.367221474647522, +0.302905440330505,0.229752898216248,0.130207896232605, +}; + +static const float cplscale5[31] = { +0.995926380157471,0.987517595291138,0.978726446628571,0.969505727291107, +0.95979779958725,0.949531257152557,0.938616216182709,0.926936149597168, +0.914336204528809,0.900602877140045,0.885426938533783,0.868331849575043, +0.84851086139679,0.824381768703461,0.791833400726318,0.70710676908493, +0.610737144947052,0.566034197807312,0.529177963733673,0.495983630418777, +0.464778542518616,0.434642940759659,0.404955863952637,0.375219136476517, +0.344963222742081,0.313672333955765,0.280692428350449,0.245068684220314, +0.205169528722763,0.157508864998817,0.0901700109243393, +}; + +static const float cplscale6[63] = { +0.998005926609039,0.993956744670868,0.989822506904602,0.985598564147949, +0.981279790401459,0.976860702037811,0.972335040569305,0.967696130275726, +0.962936460971832,0.958047747612000,0.953020632266998,0.947844684123993, +0.942508161067963,0.936997592449188,0.931297719478607,0.925390899181366, +0.919256627559662,0.912870943546295,0.906205296516418,0.899225592613220, +0.891890347003937,0.884148240089417,0.875934481620789,0.867165684700012, +0.857730865478516,0.847477376461029,0.836184680461884,0.823513329029083, +0.808890223503113,0.791194140911102,0.767520070075989,0.707106769084930, +0.641024887561798,0.611565053462982,0.587959706783295,0.567296981811523, +0.548448026180267,0.530831515789032,0.514098942279816,0.498019754886627, +0.482430040836334,0.467206478118896,0.452251672744751,0.437485188245773, +0.422837972640991,0.408248275518417,0.393658757209778,0.379014074802399, +0.364258885383606,0.349335819482803,0.334183186292648,0.318732559680939, +0.302905440330505,0.286608695983887,0.269728302955627,0.252119421958923, +0.233590632677078,0.213876649737358,0.192587479948997,0.169101938605309, +0.142307326197624,0.109772264957428,0.0631198287010193, +}; + +static const float* const cplscales[5] = { + cplscale2, cplscale3, cplscale4, cplscale5, cplscale6, +}; + +#endif /* FFMPEG_COOKDATA_H */ diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/cscd.c b/src/add-ons/media/plugins/avcodec/libavcodec/cscd.c new file mode 100644 index 0000000000..1a753ba885 --- /dev/null +++ b/src/add-ons/media/plugins/avcodec/libavcodec/cscd.c @@ -0,0 +1,263 @@ +/* + * CamStudio decoder + * Copyright (c) 2006 Reimar Doeffinger + * + * This file is part of FFmpeg. + * + * FFmpeg 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.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include + +#include "avcodec.h" + +#ifdef CONFIG_ZLIB +#include +#endif +#include "lzo.h" + +typedef struct { + AVFrame pic; + int linelen, height, bpp; + unsigned int decomp_size; + unsigned char* decomp_buf; +} CamStudioContext; + +static void copy_frame_default(AVFrame *f, const uint8_t *src, + int linelen, int height) { + int i; + uint8_t *dst = f->data[0]; + dst += (height - 1) * f->linesize[0]; + for (i = height; i; i--) { + memcpy(dst, src, linelen); + src += linelen; + dst -= f->linesize[0]; + } +} + +static void add_frame_default(AVFrame *f, const uint8_t *src, + int linelen, int height) { + int i, j; + uint8_t *dst = f->data[0]; + dst += (height - 1) * f->linesize[0]; + for (i = height; i; i--) { + for (j = linelen; j; j--) + *dst++ += *src++; + dst -= f->linesize[0] + linelen; + } +} + +#ifndef WORDS_BIGENDIAN +#define copy_frame_16 copy_frame_default +#define copy_frame_32 copy_frame_default +#define add_frame_16 add_frame_default +#define add_frame_32 add_frame_default +#else +static void copy_frame_16(AVFrame *f, const uint8_t *src, + int linelen, int height) { + int i, j; + uint8_t *dst = f->data[0]; + dst += (height - 1) * f->linesize[0]; + for (i = height; i; i--) { + for (j = linelen / 2; j; j--) { + dst[0] = src[1]; + dst[1] = src[0]; + src += 2; + dst += 2; + } + dst -= f->linesize[0] + linelen; + } +} + +static void copy_frame_32(AVFrame *f, const uint8_t *src, + int linelen, int height) { + int i, j; + uint8_t *dst = f->data[0]; + dst += (height - 1) * f->linesize[0]; + for (i = height; i; i--) { + for (j = linelen / 4; j; j--) { + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; + src += 4; + dst += 4; + } + dst -= f->linesize[0] + linelen; + } +} + +static void add_frame_16(AVFrame *f, const uint8_t *src, + int linelen, int height) { + int i, j; + uint8_t *dst = f->data[0]; + dst += (height - 1) * f->linesize[0]; + for (i = height; i; i--) { + for (j = linelen / 2; j; j--) { + dst[0] += src[1]; + dst[1] += src[0]; + src += 2; + dst += 2; + } + dst -= f->linesize[0] + linelen; + } +} + +static void add_frame_32(AVFrame *f, const uint8_t *src, + int linelen, int height) { + int i, j; + uint8_t *dst = f->data[0]; + dst += (height - 1) * f->linesize[0]; + for (i = height; i; i--) { + for (j = linelen / 4; j; j--) { + dst[0] += src[3]; + dst[1] += src[2]; + dst[2] += src[1]; + dst[3] += src[0]; + src += 4; + dst += 4; + } + dst -= f->linesize[0] + linelen; + } +} +#endif + +static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, + const uint8_t *buf, int buf_size) { + CamStudioContext *c = avctx->priv_data; + AVFrame *picture = data; + + if (buf_size < 2) { + av_log(avctx, AV_LOG_ERROR, "coded frame too small\n"); + return -1; + } + + if (c->pic.data[0]) + avctx->release_buffer(avctx, &c->pic); + c->pic.reference = 1; + c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_READABLE | + FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; + if (avctx->get_buffer(avctx, &c->pic) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return -1; + } + + // decompress data + switch ((buf[0] >> 1) & 7) { + case 0: { // lzo compression + int outlen = c->decomp_size, inlen = buf_size - 2; + if (lzo1x_decode(c->decomp_buf, &outlen, &buf[2], &inlen)) + av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n"); + break; + } + case 1: { // zlib compression +#ifdef CONFIG_ZLIB + unsigned long dlen = c->decomp_size; + if (uncompress(c->decomp_buf, &dlen, &buf[2], buf_size - 2) != Z_OK) + av_log(avctx, AV_LOG_ERROR, "error during zlib decompression\n"); + break; +#else + av_log(avctx, AV_LOG_ERROR, "compiled without zlib support\n"); + return -1; +#endif + } + default: + av_log(avctx, AV_LOG_ERROR, "unknown compression\n"); + return -1; + } + + // flip upside down, add difference frame + if (buf[0] & 1) { // keyframe + c->pic.pict_type = FF_I_TYPE; + c->pic.key_frame = 1; + switch (c->bpp) { + case 16: + copy_frame_16(&c->pic, c->decomp_buf, c->linelen, c->height); + break; + case 32: + copy_frame_32(&c->pic, c->decomp_buf, c->linelen, c->height); + break; + default: + copy_frame_default(&c->pic, c->decomp_buf, c->linelen, c->height); + } + } else { + c->pic.pict_type = FF_P_TYPE; + c->pic.key_frame = 0; + switch (c->bpp) { + case 16: + add_frame_16(&c->pic, c->decomp_buf, c->linelen, c->height); + break; + case 32: + add_frame_32(&c->pic, c->decomp_buf, c->linelen, c->height); + break; + default: + add_frame_default(&c->pic, c->decomp_buf, c->linelen, c->height); + } + } + + *picture = c->pic; + *data_size = sizeof(AVFrame); + return buf_size; +} + +static av_cold int decode_init(AVCodecContext *avctx) { + CamStudioContext *c = avctx->priv_data; + if (avcodec_check_dimensions(avctx, avctx->height, avctx->width) < 0) { + return 1; + } + switch (avctx->bits_per_sample) { + case 16: avctx->pix_fmt = PIX_FMT_RGB555; break; + case 24: avctx->pix_fmt = PIX_FMT_BGR24; break; + case 32: avctx->pix_fmt = PIX_FMT_RGB32; break; + default: + av_log(avctx, AV_LOG_ERROR, + "CamStudio codec error: invalid depth %i bpp\n", + avctx->bits_per_sample); + return 1; + } + c->bpp = avctx->bits_per_sample; + c->pic.data[0] = NULL; + c->linelen = avctx->width * avctx->bits_per_sample / 8; + c->height = avctx->height; + c->decomp_size = c->height * c->linelen; + c->decomp_buf = av_malloc(c->decomp_size + LZO_OUTPUT_PADDING); + if (!c->decomp_buf) { + av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); + return 1; + } + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) { + CamStudioContext *c = avctx->priv_data; + av_freep(&c->decomp_buf); + if (c->pic.data[0]) + avctx->release_buffer(avctx, &c->pic); + return 0; +} + +AVCodec cscd_decoder = { + "camstudio", + CODEC_TYPE_VIDEO, + CODEC_ID_CSCD, + sizeof(CamStudioContext), + decode_init, + NULL, + decode_end, + decode_frame, + CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("CamStudio"), +}; + diff --git a/src/add-ons/media/plugins/avcodec/libavcodec/cyuv.c b/src/add-ons/media/plugins/avcodec/libavcodec/cyuv.c index 70b55066ad..d64f6df275 100644 --- a/src/add-ons/media/plugins/avcodec/libavcodec/cyuv.c +++ b/src/add-ons/media/plugins/avcodec/libavcodec/cyuv.c @@ -1,42 +1,40 @@ /* - * - * 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 - * * Creative YUV (CYUV) Video Decoder * by Mike Melanson (melanson@pcisys.net) * based on "Creative YUV (CYUV) stream format for AVI": * http://www.csse.monash.edu.au/~timf/videocodec/cyuv.txt * + * Copyright (C) 2003 the ffmpeg project + * + * This file is part of FFmpeg. + * + * FFmpeg 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.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** - * @file cyuv.c + * @file cyuv.c * Creative YUV (CYUV) Video Decoder. */ - + #include #include #include #include -#include "common.h" #include "avcodec.h" #include "dsputil.h" -#include "mpegvideo.h" typedef struct CyuvDecodeContext { @@ -45,22 +43,24 @@ typedef struct CyuvDecodeContext { AVFrame frame; } CyuvDecodeContext; -static int cyuv_decode_init(AVCodecContext *avctx) +static av_cold int cyuv_decode_init(AVCodecContext *avctx) { CyuvDecodeContext *s = avctx->priv_data; s->avctx = avctx; s->width = avctx->width; + /* width needs to be divisible by 4 for this codec to work */ + if (s->width & 0x3) + return -1; s->height = avctx->height; avctx->pix_fmt = PIX_FMT_YUV411P; - avctx->has_b_frames = 0; return 0; } -static int cyuv_decode_frame(AVCodecContext *avctx, +static int cyuv_decode_frame(AVCodecContext *avctx, void *data, int *data_size, - uint8_t *buf, int buf_size) + const uint8_t *buf, int buf_size) { CyuvDecodeContext *s=avctx->priv_data; @@ -72,17 +72,15 @@ static int cyuv_decode_frame(AVCodecContext *avctx, int v_ptr; /* prediction error tables (make it clear that they are signed values) */ - signed char *y_table = buf + 0; - signed char *u_table = buf + 16; - signed char *v_table = buf + 32; + const signed char *y_table = (const signed char*)buf + 0; + const signed char *u_table = (const signed char*)buf + 16; + const signed char *v_table = (const signed char*)buf + 32; unsigned char y_pred, u_pred, v_pred; int stream_ptr; unsigned char cur_byte; int pixel_groups; - *data_size = 0; - /* sanity check the buffer size: A buffer has 3x16-bytes tables * followed by (height) lines each with 3 bytes to represent groups * of 4 pixels. Thus, the total size of the buffer ought to be: @@ -100,6 +98,7 @@ static int cyuv_decode_frame(AVCodecContext *avctx, if(s->frame.data[0]) avctx->release_buffer(avctx, &s->frame); + s->frame.buffer_hints = FF_BUFFER_HINTS_VALID; s->frame.reference = 0; if(avctx->get_buffer(avctx, &s->frame) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); @@ -112,7 +111,7 @@ static int cyuv_decode_frame(AVCodecContext *avctx, /* iterate through each line in the height */ for (y_ptr = 0, u_ptr = 0, v_ptr = 0; - y_ptr < (s->height * s->frame.linesize[0]); + y_ptr < (s->height * s->frame.linesize[0]); y_ptr += s->frame.linesize[0] - s->width, u_ptr += s->frame.linesize[1] - s->width / 4, v_ptr += s->frame.linesize[2] - s->width / 4) { @@ -164,7 +163,7 @@ static int cyuv_decode_frame(AVCodecContext *avctx, return buf_size; } -static int cyuv_decode_end(AVCodecContext *avctx) +static av_cold int cyuv_decode_end(AVCodecContext *avctx) { /* CyuvDecodeContext *s = avctx->priv_data;*/ @@ -180,7 +179,8 @@ AVCodec cyuv_decoder = { NULL, cyuv_decode_end, cyuv_decode_frame, - 0, - NULL + CODEC_CAP_DR1, + NULL, + .long_name = NULL_IF_CONFIG_SMALL("Creative YUV (CYUV)"), };