1/* 2 * VBLE Decoder 3 * Copyright (c) 2011 Derek Buitenhuis 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * VBLE Decoder 25 */ 26 27#define BITSTREAM_READER_LE 28 29#include "avcodec.h" 30#include "get_bits.h" 31#include "huffyuvdsp.h" 32#include "internal.h" 33#include "mathops.h" 34 35typedef struct { 36 AVCodecContext *avctx; 37 HuffYUVDSPContext hdsp; 38 39 int size; 40 uint8_t *val; ///< This array first holds the lengths of vlc symbols and then their value. 41} VBLEContext; 42 43static int vble_unpack(VBLEContext *ctx, GetBitContext *gb) 44{ 45 int i; 46 int allbits = 0; 47 static const uint8_t LUT[256] = { 48 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, 49 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, 50 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, 51 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, 52 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, 53 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, 54 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, 55 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, 56 }; 57 58 /* Read all the lengths in first */ 59 for (i = 0; i < ctx->size; i++) { 60 /* At most we need to read 9 bits total to get indices up to 8 */ 61 int val = show_bits(gb, 8); 62 63 // read reverse unary 64 if (val) { 65 val = LUT[val]; 66 skip_bits(gb, val + 1); 67 ctx->val[i] = val; 68 } else { 69 skip_bits(gb, 8); 70 if (!get_bits1(gb)) 71 return -1; 72 ctx->val[i] = 8; 73 } 74 allbits += ctx->val[i]; 75 } 76 77 /* Check we have enough bits left */ 78 if (get_bits_left(gb) < allbits) 79 return -1; 80 return 0; 81} 82 83static void vble_restore_plane(VBLEContext *ctx, AVFrame *pic, 84 GetBitContext *gb, int plane, 85 int offset, int width, int height) 86{ 87 uint8_t *dst = pic->data[plane]; 88 uint8_t *val = ctx->val + offset; 89 int stride = pic->linesize[plane]; 90 int i, j, left, left_top; 91 92 for (i = 0; i < height; i++) { 93 for (j = 0; j < width; j++) { 94 /* get_bits can't take a length of 0 */ 95 if (val[j]) { 96 int v = (1 << val[j]) + get_bits(gb, val[j]) - 1; 97 val[j] = (v >> 1) ^ -(v & 1); 98 } 99 } 100 if (i) { 101 left = 0; 102 left_top = dst[-stride]; 103 ctx->hdsp.add_hfyu_median_pred(dst, dst - stride, val, 104 width, &left, &left_top); 105 } else { 106 dst[0] = val[0]; 107 for (j = 1; j < width; j++) 108 dst[j] = val[j] + dst[j - 1]; 109 } 110 dst += stride; 111 val += width; 112 } 113} 114 115static int vble_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, 116 AVPacket *avpkt) 117{ 118 VBLEContext *ctx = avctx->priv_data; 119 AVFrame *pic = data; 120 GetBitContext gb; 121 const uint8_t *src = avpkt->data; 122 int version; 123 int offset = 0; 124 int width_uv = avctx->width / 2, height_uv = avctx->height / 2; 125 int ret; 126 127 if (avpkt->size < 4 || avpkt->size - 4 > INT_MAX/8) { 128 av_log(avctx, AV_LOG_ERROR, "Invalid packet size\n"); 129 return AVERROR_INVALIDDATA; 130 } 131 132 /* Allocate buffer */ 133 if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) 134 return ret; 135 136 /* Set flags */ 137 pic->key_frame = 1; 138 pic->pict_type = AV_PICTURE_TYPE_I; 139 140 /* Version should always be 1 */ 141 version = AV_RL32(src); 142 143 if (version != 1) 144 av_log(avctx, AV_LOG_WARNING, "Unsupported VBLE Version: %d\n", version); 145 146 init_get_bits(&gb, src + 4, (avpkt->size - 4) * 8); 147 148 /* Unpack */ 149 if (vble_unpack(ctx, &gb) < 0) { 150 av_log(avctx, AV_LOG_ERROR, "Invalid Code\n"); 151 return AVERROR_INVALIDDATA; 152 } 153 154 /* Restore planes. Should be almost identical to Huffyuv's. */ 155 vble_restore_plane(ctx, pic, &gb, 0, offset, avctx->width, avctx->height); 156 157 /* Chroma */ 158 if (!(ctx->avctx->flags & CODEC_FLAG_GRAY)) { 159 offset += avctx->width * avctx->height; 160 vble_restore_plane(ctx, pic, &gb, 1, offset, width_uv, height_uv); 161 162 offset += width_uv * height_uv; 163 vble_restore_plane(ctx, pic, &gb, 2, offset, width_uv, height_uv); 164 } 165 166 *got_frame = 1; 167 168 return avpkt->size; 169} 170 171static av_cold int vble_decode_close(AVCodecContext *avctx) 172{ 173 VBLEContext *ctx = avctx->priv_data; 174 av_freep(&ctx->val); 175 176 return 0; 177} 178 179static av_cold int vble_decode_init(AVCodecContext *avctx) 180{ 181 VBLEContext *ctx = avctx->priv_data; 182 183 /* Stash for later use */ 184 ctx->avctx = avctx; 185 ff_huffyuvdsp_init(&ctx->hdsp); 186 187 avctx->pix_fmt = AV_PIX_FMT_YUV420P; 188 avctx->bits_per_raw_sample = 8; 189 190 ctx->size = avpicture_get_size(avctx->pix_fmt, 191 avctx->width, avctx->height); 192 193 ctx->val = av_malloc_array(ctx->size, sizeof(*ctx->val)); 194 195 if (!ctx->val) { 196 av_log(avctx, AV_LOG_ERROR, "Could not allocate values buffer.\n"); 197 vble_decode_close(avctx); 198 return AVERROR(ENOMEM); 199 } 200 201 return 0; 202} 203 204AVCodec ff_vble_decoder = { 205 .name = "vble", 206 .long_name = NULL_IF_CONFIG_SMALL("VBLE Lossless Codec"), 207 .type = AVMEDIA_TYPE_VIDEO, 208 .id = AV_CODEC_ID_VBLE, 209 .priv_data_size = sizeof(VBLEContext), 210 .init = vble_decode_init, 211 .close = vble_decode_close, 212 .decode = vble_decode_frame, 213 .capabilities = CODEC_CAP_DR1, 214}; 215