1/* 2 * lzf decompression algorithm 3 * Copyright (c) 2015 Luca Barbato 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 * lzf decompression 25 * 26 * LZF is a fast compression/decompression algorithm that takes very little 27 * code space and working memory, ideal for real-time and block compression. 28 * 29 * https://en.wikibooks.org/wiki/Data_Compression/Dictionary_compression#LZF 30 */ 31 32#include "libavutil/mem.h" 33 34#include "bytestream.h" 35#include "lzf.h" 36 37#define LZF_LITERAL_MAX (1 << 5) 38#define LZF_LONG_BACKREF 7 + 2 39 40int ff_lzf_uncompress(GetByteContext *gb, uint8_t **buf, int64_t *size) 41{ 42 int ret = 0; 43 uint8_t *p = *buf; 44 int64_t len = 0; 45 46 while (bytestream2_get_bytes_left(gb) > 2) { 47 uint8_t s = bytestream2_get_byte(gb); 48 49 if (s < LZF_LITERAL_MAX) { 50 s++; 51 if (s > *size - len) { 52 *size += s + *size /2; 53 ret = av_reallocp(buf, *size); 54 if (ret < 0) 55 return ret; 56 p = *buf + len; 57 } 58 59 bytestream2_get_buffer(gb, p, s); 60 p += s; 61 len += s; 62 } else { 63 int l = 2 + (s >> 5); 64 int off = ((s & 0x1f) << 8) + 1; 65 66 if (l == LZF_LONG_BACKREF) 67 l += bytestream2_get_byte(gb); 68 69 off += bytestream2_get_byte(gb); 70 71 if (off > len) 72 return AVERROR_INVALIDDATA; 73 74 if (l > *size - len) { 75 *size += l + *size / 2; 76 ret = av_reallocp(buf, *size); 77 if (ret < 0) 78 return ret; 79 p = *buf + len; 80 } 81 82 av_memcpy_backptr(p, off, l); 83 84 p += l; 85 len += l; 86 } 87 } 88 89 *size = len; 90 91 return 0; 92} 93