1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Duck TrueMotion 2.0 Real Time decoder 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * This file is part of FFmpeg. 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14cabdff1aSopenharmony_ci * Lesser General Public License for more details. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19cabdff1aSopenharmony_ci */ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include <stdio.h> 22cabdff1aSopenharmony_ci#include <stdlib.h> 23cabdff1aSopenharmony_ci#include <string.h> 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 26cabdff1aSopenharmony_ci#include "libavutil/internal.h" 27cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#define BITSTREAM_READER_LE 30cabdff1aSopenharmony_ci#include "avcodec.h" 31cabdff1aSopenharmony_ci#include "codec_internal.h" 32cabdff1aSopenharmony_ci#include "get_bits.h" 33cabdff1aSopenharmony_ci#include "internal.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_citypedef struct TrueMotion2RTContext { 36cabdff1aSopenharmony_ci GetBitContext gb; 37cabdff1aSopenharmony_ci int delta_size; 38cabdff1aSopenharmony_ci int hscale; 39cabdff1aSopenharmony_ci} TrueMotion2RTContext; 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_cistatic const int16_t delta_tab2[] = { 42cabdff1aSopenharmony_ci 5, -7, 36, -36, 43cabdff1aSopenharmony_ci}; 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_cistatic const int16_t delta_tab3[] = { 46cabdff1aSopenharmony_ci 2, -3, 8, -8, 18, -18, 36, -36, 47cabdff1aSopenharmony_ci}; 48cabdff1aSopenharmony_ci 49cabdff1aSopenharmony_cistatic const int16_t delta_tab4[] = { 50cabdff1aSopenharmony_ci 1, -1, 2, -3, 8, -8, 18, -18, 36, -36, 54, -54, 96, -96, 144, -144, 51cabdff1aSopenharmony_ci}; 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_cistatic const int16_t *const delta_tabs[] = { 54cabdff1aSopenharmony_ci delta_tab2, delta_tab3, delta_tab4, 55cabdff1aSopenharmony_ci}; 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_ci/* Returns the number of bytes consumed from the bytestream, or 58cabdff1aSopenharmony_ci * AVERROR_INVALIDDATA if there was an error while decoding the header. */ 59cabdff1aSopenharmony_cistatic int truemotion2rt_decode_header(AVCodecContext *avctx, const AVPacket *avpkt) 60cabdff1aSopenharmony_ci{ 61cabdff1aSopenharmony_ci TrueMotion2RTContext *s = avctx->priv_data; 62cabdff1aSopenharmony_ci int header_size; 63cabdff1aSopenharmony_ci uint8_t header_buffer[128] = { 0 }; /* logical maximum header size */ 64cabdff1aSopenharmony_ci const uint8_t *buf = avpkt->data; 65cabdff1aSopenharmony_ci int size = avpkt->size; 66cabdff1aSopenharmony_ci int width, height; 67cabdff1aSopenharmony_ci int ret, i; 68cabdff1aSopenharmony_ci 69cabdff1aSopenharmony_ci if (size < 1) { 70cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "input packet too small (%d)\n", size); 71cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 72cabdff1aSopenharmony_ci } 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci header_size = ((buf[0] >> 5) | (buf[0] << 3)) & 0x7f; 75cabdff1aSopenharmony_ci if (header_size < 10) { 76cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "invalid header size (%d)\n", header_size); 77cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 78cabdff1aSopenharmony_ci } 79cabdff1aSopenharmony_ci 80cabdff1aSopenharmony_ci if (header_size + 1 > size) { 81cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "input packet too small (%d)\n", size); 82cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 83cabdff1aSopenharmony_ci } 84cabdff1aSopenharmony_ci 85cabdff1aSopenharmony_ci /* unscramble the header bytes with a XOR operation */ 86cabdff1aSopenharmony_ci for (i = 1; i < header_size; i++) 87cabdff1aSopenharmony_ci header_buffer[i - 1] = buf[i] ^ buf[i + 1]; 88cabdff1aSopenharmony_ci 89cabdff1aSopenharmony_ci s->delta_size = header_buffer[1]; 90cabdff1aSopenharmony_ci s->hscale = 1 + !!header_buffer[3]; 91cabdff1aSopenharmony_ci if (s->delta_size < 2 || s->delta_size > 4) 92cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_ci height = AV_RL16(header_buffer + 5); 95cabdff1aSopenharmony_ci width = AV_RL16(header_buffer + 7); 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_ci ret = ff_set_dimensions(avctx, width, height); 98cabdff1aSopenharmony_ci if (ret < 0) 99cabdff1aSopenharmony_ci return ret; 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, "Header size: %d\n", header_size); 102cabdff1aSopenharmony_ci return header_size; 103cabdff1aSopenharmony_ci} 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_cistatic int truemotion2rt_decode_frame(AVCodecContext *avctx, AVFrame *p, 106cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 107cabdff1aSopenharmony_ci{ 108cabdff1aSopenharmony_ci TrueMotion2RTContext *s = avctx->priv_data; 109cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 110cabdff1aSopenharmony_ci uint8_t *dst; 111cabdff1aSopenharmony_ci int x, y, delta_mode; 112cabdff1aSopenharmony_ci int ret; 113cabdff1aSopenharmony_ci 114cabdff1aSopenharmony_ci ret = truemotion2rt_decode_header(avctx, avpkt); 115cabdff1aSopenharmony_ci if (ret < 0) 116cabdff1aSopenharmony_ci return ret; 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci if ((avctx->width + s->hscale - 1)/ s->hscale * avctx->height * s->delta_size > avpkt->size * 8LL * 4) 119cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_ci ret = init_get_bits8(gb, avpkt->data + ret, avpkt->size - ret); 122cabdff1aSopenharmony_ci if (ret < 0) 123cabdff1aSopenharmony_ci return ret; 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci ret = ff_get_buffer(avctx, p, 0); 126cabdff1aSopenharmony_ci if (ret < 0) 127cabdff1aSopenharmony_ci return ret; 128cabdff1aSopenharmony_ci 129cabdff1aSopenharmony_ci skip_bits(gb, 32); 130cabdff1aSopenharmony_ci delta_mode = s->delta_size - 2; 131cabdff1aSopenharmony_ci dst = p->data[0]; 132cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 133cabdff1aSopenharmony_ci int diff = 0; 134cabdff1aSopenharmony_ci for (x = 0; x < avctx->width; x += s->hscale) { 135cabdff1aSopenharmony_ci diff += delta_tabs[delta_mode][get_bits(gb, s->delta_size)]; 136cabdff1aSopenharmony_ci dst[x] = av_clip_uint8((y ? dst[x - p->linesize[0]] : 0) + diff); 137cabdff1aSopenharmony_ci } 138cabdff1aSopenharmony_ci dst += p->linesize[0]; 139cabdff1aSopenharmony_ci } 140cabdff1aSopenharmony_ci 141cabdff1aSopenharmony_ci if (s->hscale > 1) { 142cabdff1aSopenharmony_ci dst = p->data[0]; 143cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 144cabdff1aSopenharmony_ci for (x = 1; x < avctx->width; x += s->hscale) 145cabdff1aSopenharmony_ci dst[x] = dst[x - 1]; 146cabdff1aSopenharmony_ci dst += p->linesize[0]; 147cabdff1aSopenharmony_ci } 148cabdff1aSopenharmony_ci } 149cabdff1aSopenharmony_ci 150cabdff1aSopenharmony_ci dst = p->data[0]; 151cabdff1aSopenharmony_ci for (y = 0; y < avctx->height; y++) { 152cabdff1aSopenharmony_ci for (x = 0; x < avctx->width; x++) 153cabdff1aSopenharmony_ci dst[x] = av_clip_uint8(dst[x] + (dst[x] - 128) / 3); 154cabdff1aSopenharmony_ci dst += p->linesize[0]; 155cabdff1aSopenharmony_ci } 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci dst = p->data[1]; 158cabdff1aSopenharmony_ci for (y = 0; y < avctx->height >> 2; y++) { 159cabdff1aSopenharmony_ci int diff = 0; 160cabdff1aSopenharmony_ci for (x = 0; x < avctx->width >> 2; x += s->hscale) { 161cabdff1aSopenharmony_ci diff += delta_tabs[delta_mode][get_bits(gb, s->delta_size)]; 162cabdff1aSopenharmony_ci dst[x] = av_clip_uint8((y ? dst[x - p->linesize[1]] : 128) + diff); 163cabdff1aSopenharmony_ci } 164cabdff1aSopenharmony_ci dst += p->linesize[1]; 165cabdff1aSopenharmony_ci } 166cabdff1aSopenharmony_ci 167cabdff1aSopenharmony_ci if (s->hscale > 1) { 168cabdff1aSopenharmony_ci dst = p->data[1]; 169cabdff1aSopenharmony_ci for (y = 0; y < avctx->height >> 2; y++) { 170cabdff1aSopenharmony_ci for (x = 1; x < avctx->width >> 2; x += s->hscale) 171cabdff1aSopenharmony_ci dst[x] = dst[x - 1]; 172cabdff1aSopenharmony_ci dst += p->linesize[1]; 173cabdff1aSopenharmony_ci } 174cabdff1aSopenharmony_ci } 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ci dst = p->data[1]; 177cabdff1aSopenharmony_ci for (y = 0; y < avctx->height >> 2; y++) { 178cabdff1aSopenharmony_ci for (x = 0; x < avctx->width >> 2; x++) 179cabdff1aSopenharmony_ci dst[x] += (dst[x] - 128) / 8; 180cabdff1aSopenharmony_ci dst += p->linesize[1]; 181cabdff1aSopenharmony_ci } 182cabdff1aSopenharmony_ci 183cabdff1aSopenharmony_ci dst = p->data[2]; 184cabdff1aSopenharmony_ci for (y = 0; y < avctx->height >> 2; y++) { 185cabdff1aSopenharmony_ci int diff = 0; 186cabdff1aSopenharmony_ci for (x = 0; x < avctx->width >> 2; x += s->hscale) { 187cabdff1aSopenharmony_ci diff += delta_tabs[delta_mode][get_bits(gb, s->delta_size)]; 188cabdff1aSopenharmony_ci dst[x] = av_clip_uint8((y ? dst[x - p->linesize[2]] : 128) + diff); 189cabdff1aSopenharmony_ci } 190cabdff1aSopenharmony_ci dst += p->linesize[2]; 191cabdff1aSopenharmony_ci } 192cabdff1aSopenharmony_ci 193cabdff1aSopenharmony_ci if (s->hscale > 1) { 194cabdff1aSopenharmony_ci dst = p->data[2]; 195cabdff1aSopenharmony_ci for (y = 0; y < avctx->height >> 2; y++) { 196cabdff1aSopenharmony_ci for (x = 1; x < avctx->width >> 2; x += s->hscale) 197cabdff1aSopenharmony_ci dst[x] = dst[x - 1]; 198cabdff1aSopenharmony_ci dst += p->linesize[2]; 199cabdff1aSopenharmony_ci } 200cabdff1aSopenharmony_ci } 201cabdff1aSopenharmony_ci 202cabdff1aSopenharmony_ci dst = p->data[2]; 203cabdff1aSopenharmony_ci for (y = 0; y < avctx->height >> 2; y++) { 204cabdff1aSopenharmony_ci for (x = 0; x < avctx->width >> 2; x++) 205cabdff1aSopenharmony_ci dst[x] += (dst[x] - 128) / 8; 206cabdff1aSopenharmony_ci dst += p->linesize[2]; 207cabdff1aSopenharmony_ci } 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci p->pict_type = AV_PICTURE_TYPE_I; 210cabdff1aSopenharmony_ci p->key_frame = 1; 211cabdff1aSopenharmony_ci *got_frame = 1; 212cabdff1aSopenharmony_ci 213cabdff1aSopenharmony_ci return avpkt->size; 214cabdff1aSopenharmony_ci} 215cabdff1aSopenharmony_ci 216cabdff1aSopenharmony_cistatic av_cold int truemotion2rt_decode_init(AVCodecContext *avctx) 217cabdff1aSopenharmony_ci{ 218cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_YUV410P; 219cabdff1aSopenharmony_ci return 0; 220cabdff1aSopenharmony_ci} 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ciconst FFCodec ff_truemotion2rt_decoder = { 223cabdff1aSopenharmony_ci .p.name = "truemotion2rt", 224cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0 Real Time"), 225cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 226cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_TRUEMOTION2RT, 227cabdff1aSopenharmony_ci .priv_data_size = sizeof(TrueMotion2RTContext), 228cabdff1aSopenharmony_ci .init = truemotion2rt_decode_init, 229cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(truemotion2rt_decode_frame), 230cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 231cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 232cabdff1aSopenharmony_ci}; 233