1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Intel Indeo 2 codec 3cabdff1aSopenharmony_ci * Copyright (c) 2005 Konstantin Shishkov 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * Intel Indeo 2 decoder. 25cabdff1aSopenharmony_ci */ 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include "libavutil/attributes.h" 28cabdff1aSopenharmony_ci#include "libavutil/thread.h" 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#define BITSTREAM_READER_LE 31cabdff1aSopenharmony_ci#include "avcodec.h" 32cabdff1aSopenharmony_ci#include "codec_internal.h" 33cabdff1aSopenharmony_ci#include "get_bits.h" 34cabdff1aSopenharmony_ci#include "indeo2data.h" 35cabdff1aSopenharmony_ci#include "internal.h" 36cabdff1aSopenharmony_ci#include "mathops.h" 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_citypedef struct Ir2Context{ 39cabdff1aSopenharmony_ci AVCodecContext *avctx; 40cabdff1aSopenharmony_ci AVFrame *picture; 41cabdff1aSopenharmony_ci GetBitContext gb; 42cabdff1aSopenharmony_ci int decode_delta; 43cabdff1aSopenharmony_ci} Ir2Context; 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_ci#define CODE_VLC_BITS 14 46cabdff1aSopenharmony_cistatic VLC ir2_vlc; 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci/* Indeo 2 codes are in range 0x01..0x7F and 0x81..0x90 */ 49cabdff1aSopenharmony_cistatic inline int ir2_get_code(GetBitContext *gb) 50cabdff1aSopenharmony_ci{ 51cabdff1aSopenharmony_ci return get_vlc2(gb, ir2_vlc.table, CODE_VLC_BITS, 1); 52cabdff1aSopenharmony_ci} 53cabdff1aSopenharmony_ci 54cabdff1aSopenharmony_cistatic int ir2_decode_plane(Ir2Context *ctx, int width, int height, uint8_t *dst, 55cabdff1aSopenharmony_ci int pitch, const uint8_t *table) 56cabdff1aSopenharmony_ci{ 57cabdff1aSopenharmony_ci int i; 58cabdff1aSopenharmony_ci int j; 59cabdff1aSopenharmony_ci int out = 0; 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_ci if ((width & 1) || width * height / (2*(IR2_CODES - 0x7F)) > get_bits_left(&ctx->gb)) 62cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 63cabdff1aSopenharmony_ci 64cabdff1aSopenharmony_ci /* first line contain absolute values, other lines contain deltas */ 65cabdff1aSopenharmony_ci while (out < width) { 66cabdff1aSopenharmony_ci int c = ir2_get_code(&ctx->gb); 67cabdff1aSopenharmony_ci if (c >= 0x80) { /* we have a run */ 68cabdff1aSopenharmony_ci c -= 0x7F; 69cabdff1aSopenharmony_ci if (out + c*2 > width) 70cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 71cabdff1aSopenharmony_ci for (i = 0; i < c * 2; i++) 72cabdff1aSopenharmony_ci dst[out++] = 0x80; 73cabdff1aSopenharmony_ci } else { /* copy two values from table */ 74cabdff1aSopenharmony_ci if (c <= 0) 75cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 76cabdff1aSopenharmony_ci dst[out++] = table[c * 2]; 77cabdff1aSopenharmony_ci dst[out++] = table[(c * 2) + 1]; 78cabdff1aSopenharmony_ci } 79cabdff1aSopenharmony_ci } 80cabdff1aSopenharmony_ci dst += pitch; 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_ci for (j = 1; j < height; j++) { 83cabdff1aSopenharmony_ci out = 0; 84cabdff1aSopenharmony_ci while (out < width) { 85cabdff1aSopenharmony_ci int c; 86cabdff1aSopenharmony_ci if (get_bits_left(&ctx->gb) <= 0) 87cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 88cabdff1aSopenharmony_ci c = ir2_get_code(&ctx->gb); 89cabdff1aSopenharmony_ci if (c >= 0x80) { /* we have a skip */ 90cabdff1aSopenharmony_ci c -= 0x7F; 91cabdff1aSopenharmony_ci if (out + c*2 > width) 92cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 93cabdff1aSopenharmony_ci for (i = 0; i < c * 2; i++) { 94cabdff1aSopenharmony_ci dst[out] = dst[out - pitch]; 95cabdff1aSopenharmony_ci out++; 96cabdff1aSopenharmony_ci } 97cabdff1aSopenharmony_ci } else { /* add two deltas from table */ 98cabdff1aSopenharmony_ci int t; 99cabdff1aSopenharmony_ci if (c <= 0) 100cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 101cabdff1aSopenharmony_ci t = dst[out - pitch] + (table[c * 2] - 128); 102cabdff1aSopenharmony_ci t = av_clip_uint8(t); 103cabdff1aSopenharmony_ci dst[out] = t; 104cabdff1aSopenharmony_ci out++; 105cabdff1aSopenharmony_ci t = dst[out - pitch] + (table[(c * 2) + 1] - 128); 106cabdff1aSopenharmony_ci t = av_clip_uint8(t); 107cabdff1aSopenharmony_ci dst[out] = t; 108cabdff1aSopenharmony_ci out++; 109cabdff1aSopenharmony_ci } 110cabdff1aSopenharmony_ci } 111cabdff1aSopenharmony_ci dst += pitch; 112cabdff1aSopenharmony_ci } 113cabdff1aSopenharmony_ci return 0; 114cabdff1aSopenharmony_ci} 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_cistatic int ir2_decode_plane_inter(Ir2Context *ctx, int width, int height, uint8_t *dst, 117cabdff1aSopenharmony_ci int pitch, const uint8_t *table) 118cabdff1aSopenharmony_ci{ 119cabdff1aSopenharmony_ci int j; 120cabdff1aSopenharmony_ci int out = 0; 121cabdff1aSopenharmony_ci int c; 122cabdff1aSopenharmony_ci int t; 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_ci if (width & 1) 125cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 126cabdff1aSopenharmony_ci 127cabdff1aSopenharmony_ci for (j = 0; j < height; j++) { 128cabdff1aSopenharmony_ci out = 0; 129cabdff1aSopenharmony_ci while (out < width) { 130cabdff1aSopenharmony_ci if (get_bits_left(&ctx->gb) <= 0) 131cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 132cabdff1aSopenharmony_ci c = ir2_get_code(&ctx->gb); 133cabdff1aSopenharmony_ci if (c >= 0x80) { /* we have a skip */ 134cabdff1aSopenharmony_ci c -= 0x7F; 135cabdff1aSopenharmony_ci out += c * 2; 136cabdff1aSopenharmony_ci } else { /* add two deltas from table */ 137cabdff1aSopenharmony_ci if (c <= 0) 138cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 139cabdff1aSopenharmony_ci t = dst[out] + (((table[c * 2] - 128)*3) >> 2); 140cabdff1aSopenharmony_ci t = av_clip_uint8(t); 141cabdff1aSopenharmony_ci dst[out] = t; 142cabdff1aSopenharmony_ci out++; 143cabdff1aSopenharmony_ci t = dst[out] + (((table[(c * 2) + 1] - 128)*3) >> 2); 144cabdff1aSopenharmony_ci t = av_clip_uint8(t); 145cabdff1aSopenharmony_ci dst[out] = t; 146cabdff1aSopenharmony_ci out++; 147cabdff1aSopenharmony_ci } 148cabdff1aSopenharmony_ci } 149cabdff1aSopenharmony_ci dst += pitch; 150cabdff1aSopenharmony_ci } 151cabdff1aSopenharmony_ci return 0; 152cabdff1aSopenharmony_ci} 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_cistatic int ir2_decode_frame(AVCodecContext *avctx, AVFrame *picture, 155cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 156cabdff1aSopenharmony_ci{ 157cabdff1aSopenharmony_ci Ir2Context * const s = avctx->priv_data; 158cabdff1aSopenharmony_ci const uint8_t *buf = avpkt->data; 159cabdff1aSopenharmony_ci int buf_size = avpkt->size; 160cabdff1aSopenharmony_ci AVFrame * const p = s->picture; 161cabdff1aSopenharmony_ci int start, ret; 162cabdff1aSopenharmony_ci int ltab, ctab; 163cabdff1aSopenharmony_ci 164cabdff1aSopenharmony_ci if ((ret = ff_reget_buffer(avctx, p, 0)) < 0) 165cabdff1aSopenharmony_ci return ret; 166cabdff1aSopenharmony_ci 167cabdff1aSopenharmony_ci start = 48; /* hardcoded for now */ 168cabdff1aSopenharmony_ci 169cabdff1aSopenharmony_ci if (start >= buf_size) { 170cabdff1aSopenharmony_ci av_log(s->avctx, AV_LOG_ERROR, "input buffer size too small (%d)\n", buf_size); 171cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 172cabdff1aSopenharmony_ci } 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci s->decode_delta = buf[18]; 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ci /* decide whether frame uses deltas or not */ 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci if ((ret = init_get_bits8(&s->gb, buf + start, buf_size - start)) < 0) 179cabdff1aSopenharmony_ci return ret; 180cabdff1aSopenharmony_ci 181cabdff1aSopenharmony_ci ltab = buf[0x22] & 3; 182cabdff1aSopenharmony_ci ctab = buf[0x22] >> 2; 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_ci if (ctab > 3) { 185cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "ctab %d is invalid\n", ctab); 186cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 187cabdff1aSopenharmony_ci } 188cabdff1aSopenharmony_ci 189cabdff1aSopenharmony_ci if (s->decode_delta) { /* intraframe */ 190cabdff1aSopenharmony_ci if ((ret = ir2_decode_plane(s, avctx->width, avctx->height, 191cabdff1aSopenharmony_ci p->data[0], p->linesize[0], 192cabdff1aSopenharmony_ci ir2_delta_table[ltab])) < 0) 193cabdff1aSopenharmony_ci return ret; 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_ci /* swapped U and V */ 196cabdff1aSopenharmony_ci if ((ret = ir2_decode_plane(s, avctx->width >> 2, avctx->height >> 2, 197cabdff1aSopenharmony_ci p->data[2], p->linesize[2], 198cabdff1aSopenharmony_ci ir2_delta_table[ctab])) < 0) 199cabdff1aSopenharmony_ci return ret; 200cabdff1aSopenharmony_ci if ((ret = ir2_decode_plane(s, avctx->width >> 2, avctx->height >> 2, 201cabdff1aSopenharmony_ci p->data[1], p->linesize[1], 202cabdff1aSopenharmony_ci ir2_delta_table[ctab])) < 0) 203cabdff1aSopenharmony_ci return ret; 204cabdff1aSopenharmony_ci } else { /* interframe */ 205cabdff1aSopenharmony_ci if ((ret = ir2_decode_plane_inter(s, avctx->width, avctx->height, 206cabdff1aSopenharmony_ci p->data[0], p->linesize[0], 207cabdff1aSopenharmony_ci ir2_delta_table[ltab])) < 0) 208cabdff1aSopenharmony_ci return ret; 209cabdff1aSopenharmony_ci /* swapped U and V */ 210cabdff1aSopenharmony_ci if ((ret = ir2_decode_plane_inter(s, avctx->width >> 2, avctx->height >> 2, 211cabdff1aSopenharmony_ci p->data[2], p->linesize[2], 212cabdff1aSopenharmony_ci ir2_delta_table[ctab])) < 0) 213cabdff1aSopenharmony_ci return ret; 214cabdff1aSopenharmony_ci if ((ret = ir2_decode_plane_inter(s, avctx->width >> 2, avctx->height >> 2, 215cabdff1aSopenharmony_ci p->data[1], p->linesize[1], 216cabdff1aSopenharmony_ci ir2_delta_table[ctab])) < 0) 217cabdff1aSopenharmony_ci return ret; 218cabdff1aSopenharmony_ci } 219cabdff1aSopenharmony_ci 220cabdff1aSopenharmony_ci if ((ret = av_frame_ref(picture, p)) < 0) 221cabdff1aSopenharmony_ci return ret; 222cabdff1aSopenharmony_ci 223cabdff1aSopenharmony_ci *got_frame = 1; 224cabdff1aSopenharmony_ci 225cabdff1aSopenharmony_ci return buf_size; 226cabdff1aSopenharmony_ci} 227cabdff1aSopenharmony_ci 228cabdff1aSopenharmony_cistatic av_cold void ir2_init_static(void) 229cabdff1aSopenharmony_ci{ 230cabdff1aSopenharmony_ci INIT_VLC_STATIC_FROM_LENGTHS(&ir2_vlc, CODE_VLC_BITS, IR2_CODES, 231cabdff1aSopenharmony_ci &ir2_tab[0][1], 2, &ir2_tab[0][0], 2, 1, 232cabdff1aSopenharmony_ci 0, INIT_VLC_OUTPUT_LE, 1 << CODE_VLC_BITS); 233cabdff1aSopenharmony_ci} 234cabdff1aSopenharmony_ci 235cabdff1aSopenharmony_cistatic av_cold int ir2_decode_init(AVCodecContext *avctx) 236cabdff1aSopenharmony_ci{ 237cabdff1aSopenharmony_ci static AVOnce init_static_once = AV_ONCE_INIT; 238cabdff1aSopenharmony_ci Ir2Context * const ic = avctx->priv_data; 239cabdff1aSopenharmony_ci 240cabdff1aSopenharmony_ci ic->avctx = avctx; 241cabdff1aSopenharmony_ci 242cabdff1aSopenharmony_ci avctx->pix_fmt= AV_PIX_FMT_YUV410P; 243cabdff1aSopenharmony_ci 244cabdff1aSopenharmony_ci ic->picture = av_frame_alloc(); 245cabdff1aSopenharmony_ci if (!ic->picture) 246cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 247cabdff1aSopenharmony_ci 248cabdff1aSopenharmony_ci ff_thread_once(&init_static_once, ir2_init_static); 249cabdff1aSopenharmony_ci 250cabdff1aSopenharmony_ci return 0; 251cabdff1aSopenharmony_ci} 252cabdff1aSopenharmony_ci 253cabdff1aSopenharmony_cistatic av_cold int ir2_decode_end(AVCodecContext *avctx) 254cabdff1aSopenharmony_ci{ 255cabdff1aSopenharmony_ci Ir2Context * const ic = avctx->priv_data; 256cabdff1aSopenharmony_ci 257cabdff1aSopenharmony_ci av_frame_free(&ic->picture); 258cabdff1aSopenharmony_ci 259cabdff1aSopenharmony_ci return 0; 260cabdff1aSopenharmony_ci} 261cabdff1aSopenharmony_ci 262cabdff1aSopenharmony_ciconst FFCodec ff_indeo2_decoder = { 263cabdff1aSopenharmony_ci .p.name = "indeo2", 264cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 2"), 265cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 266cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_INDEO2, 267cabdff1aSopenharmony_ci .priv_data_size = sizeof(Ir2Context), 268cabdff1aSopenharmony_ci .init = ir2_decode_init, 269cabdff1aSopenharmony_ci .close = ir2_decode_end, 270cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(ir2_decode_frame), 271cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 272cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 273cabdff1aSopenharmony_ci}; 274