1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Copyright (c) 2016 Umair Khan <omerjerk@gmail.com> 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 "mlz.h" 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ciav_cold int ff_mlz_init_dict(void *context, MLZ *mlz) 24cabdff1aSopenharmony_ci{ 25cabdff1aSopenharmony_ci mlz->dict = av_mallocz(TABLE_SIZE * sizeof(*mlz->dict)); 26cabdff1aSopenharmony_ci if (!mlz->dict) 27cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci mlz->flush_code = FLUSH_CODE; 30cabdff1aSopenharmony_ci mlz->current_dic_index_max = DIC_INDEX_INIT; 31cabdff1aSopenharmony_ci mlz->dic_code_bit = CODE_BIT_INIT; 32cabdff1aSopenharmony_ci mlz->bump_code = (DIC_INDEX_INIT - 1); 33cabdff1aSopenharmony_ci mlz->next_code = FIRST_CODE; 34cabdff1aSopenharmony_ci mlz->freeze_flag = 0; 35cabdff1aSopenharmony_ci mlz->context = context; 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_ci return 0; 38cabdff1aSopenharmony_ci} 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_ciav_cold void ff_mlz_flush_dict(MLZ *mlz) { 41cabdff1aSopenharmony_ci MLZDict *dict = mlz->dict; 42cabdff1aSopenharmony_ci int i; 43cabdff1aSopenharmony_ci for ( i = 0; i < TABLE_SIZE; i++ ) { 44cabdff1aSopenharmony_ci dict[i].string_code = CODE_UNSET; 45cabdff1aSopenharmony_ci dict[i].parent_code = CODE_UNSET; 46cabdff1aSopenharmony_ci dict[i].match_len = 0; 47cabdff1aSopenharmony_ci } 48cabdff1aSopenharmony_ci mlz->current_dic_index_max = DIC_INDEX_INIT; 49cabdff1aSopenharmony_ci mlz->dic_code_bit = CODE_BIT_INIT; // DicCodeBitInit; 50cabdff1aSopenharmony_ci mlz->bump_code = mlz->current_dic_index_max - 1; 51cabdff1aSopenharmony_ci mlz->next_code = FIRST_CODE; 52cabdff1aSopenharmony_ci mlz->freeze_flag = 0; 53cabdff1aSopenharmony_ci} 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_cistatic void set_new_entry_dict(MLZDict* dict, int string_code, int parent_code, int char_code) { 56cabdff1aSopenharmony_ci dict[string_code].parent_code = parent_code; 57cabdff1aSopenharmony_ci dict[string_code].string_code = string_code; 58cabdff1aSopenharmony_ci dict[string_code].char_code = char_code; 59cabdff1aSopenharmony_ci if (parent_code < FIRST_CODE) { 60cabdff1aSopenharmony_ci dict[string_code].match_len = 2; 61cabdff1aSopenharmony_ci } else { 62cabdff1aSopenharmony_ci dict[string_code].match_len = (dict[parent_code].match_len) + 1; 63cabdff1aSopenharmony_ci } 64cabdff1aSopenharmony_ci} 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_cistatic int decode_string(MLZ* mlz, unsigned char *buff, int string_code, int *first_char_code, unsigned long bufsize) { 67cabdff1aSopenharmony_ci MLZDict* dict = mlz->dict; 68cabdff1aSopenharmony_ci unsigned long count, offset; 69cabdff1aSopenharmony_ci int current_code, parent_code, tmp_code; 70cabdff1aSopenharmony_ci 71cabdff1aSopenharmony_ci count = 0; 72cabdff1aSopenharmony_ci current_code = string_code; 73cabdff1aSopenharmony_ci *first_char_code = CODE_UNSET; 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci while (count < bufsize) { 76cabdff1aSopenharmony_ci switch (current_code) { 77cabdff1aSopenharmony_ci case CODE_UNSET: 78cabdff1aSopenharmony_ci return count; 79cabdff1aSopenharmony_ci break; 80cabdff1aSopenharmony_ci default: 81cabdff1aSopenharmony_ci if (current_code < FIRST_CODE) { 82cabdff1aSopenharmony_ci *first_char_code = current_code; 83cabdff1aSopenharmony_ci buff[0] = current_code; 84cabdff1aSopenharmony_ci count++; 85cabdff1aSopenharmony_ci return count; 86cabdff1aSopenharmony_ci } else { 87cabdff1aSopenharmony_ci offset = dict[current_code].match_len - 1; 88cabdff1aSopenharmony_ci tmp_code = dict[current_code].char_code; 89cabdff1aSopenharmony_ci if (offset >= bufsize) { 90cabdff1aSopenharmony_ci av_log(mlz->context, AV_LOG_ERROR, "MLZ offset error.\n"); 91cabdff1aSopenharmony_ci return count; 92cabdff1aSopenharmony_ci } 93cabdff1aSopenharmony_ci buff[offset] = tmp_code; 94cabdff1aSopenharmony_ci count++; 95cabdff1aSopenharmony_ci } 96cabdff1aSopenharmony_ci current_code = dict[current_code].parent_code; 97cabdff1aSopenharmony_ci if ((current_code < 0) || (current_code > (DIC_INDEX_MAX - 1))) { 98cabdff1aSopenharmony_ci av_log(mlz->context, AV_LOG_ERROR, "MLZ dic index error.\n"); 99cabdff1aSopenharmony_ci return count; 100cabdff1aSopenharmony_ci } 101cabdff1aSopenharmony_ci if (current_code > FIRST_CODE) { 102cabdff1aSopenharmony_ci parent_code = dict[current_code].parent_code; 103cabdff1aSopenharmony_ci offset = (dict[current_code].match_len) - 1; 104cabdff1aSopenharmony_ci if (parent_code < 0 || parent_code > DIC_INDEX_MAX-1) { 105cabdff1aSopenharmony_ci av_log(mlz->context, AV_LOG_ERROR, "MLZ dic index error.\n"); 106cabdff1aSopenharmony_ci return count; 107cabdff1aSopenharmony_ci } 108cabdff1aSopenharmony_ci if (( offset > (DIC_INDEX_MAX - 1))) { 109cabdff1aSopenharmony_ci av_log(mlz->context, AV_LOG_ERROR, "MLZ dic offset error.\n"); 110cabdff1aSopenharmony_ci return count; 111cabdff1aSopenharmony_ci } 112cabdff1aSopenharmony_ci } 113cabdff1aSopenharmony_ci break; 114cabdff1aSopenharmony_ci } 115cabdff1aSopenharmony_ci } 116cabdff1aSopenharmony_ci return count; 117cabdff1aSopenharmony_ci} 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_cistatic int input_code(GetBitContext* gb, int len) { 120cabdff1aSopenharmony_ci int tmp_code = 0; 121cabdff1aSopenharmony_ci int i; 122cabdff1aSopenharmony_ci for (i = 0; i < len; ++i) { 123cabdff1aSopenharmony_ci tmp_code |= get_bits1(gb) << i; 124cabdff1aSopenharmony_ci } 125cabdff1aSopenharmony_ci return tmp_code; 126cabdff1aSopenharmony_ci} 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_ciint ff_mlz_decompression(MLZ* mlz, GetBitContext* gb, int size, unsigned char *buff) { 129cabdff1aSopenharmony_ci MLZDict *dict = mlz->dict; 130cabdff1aSopenharmony_ci unsigned long output_chars; 131cabdff1aSopenharmony_ci int string_code, last_string_code, char_code; 132cabdff1aSopenharmony_ci 133cabdff1aSopenharmony_ci string_code = 0; 134cabdff1aSopenharmony_ci char_code = -1; 135cabdff1aSopenharmony_ci last_string_code = -1; 136cabdff1aSopenharmony_ci output_chars = 0; 137cabdff1aSopenharmony_ci 138cabdff1aSopenharmony_ci while (output_chars < size) { 139cabdff1aSopenharmony_ci string_code = input_code(gb, mlz->dic_code_bit); 140cabdff1aSopenharmony_ci switch (string_code) { 141cabdff1aSopenharmony_ci case FLUSH_CODE: 142cabdff1aSopenharmony_ci case MAX_CODE: 143cabdff1aSopenharmony_ci ff_mlz_flush_dict(mlz); 144cabdff1aSopenharmony_ci char_code = -1; 145cabdff1aSopenharmony_ci last_string_code = -1; 146cabdff1aSopenharmony_ci break; 147cabdff1aSopenharmony_ci case FREEZE_CODE: 148cabdff1aSopenharmony_ci mlz->freeze_flag = 1; 149cabdff1aSopenharmony_ci break; 150cabdff1aSopenharmony_ci default: 151cabdff1aSopenharmony_ci if (string_code > mlz->current_dic_index_max) { 152cabdff1aSopenharmony_ci av_log(mlz->context, AV_LOG_ERROR, "String code %d exceeds maximum value of %d.\n", string_code, mlz->current_dic_index_max); 153cabdff1aSopenharmony_ci return output_chars; 154cabdff1aSopenharmony_ci } 155cabdff1aSopenharmony_ci if (string_code == (int) mlz->bump_code) { 156cabdff1aSopenharmony_ci ++mlz->dic_code_bit; 157cabdff1aSopenharmony_ci mlz->current_dic_index_max *= 2; 158cabdff1aSopenharmony_ci mlz->bump_code = mlz->current_dic_index_max - 1; 159cabdff1aSopenharmony_ci } else { 160cabdff1aSopenharmony_ci if (string_code >= mlz->next_code) { 161cabdff1aSopenharmony_ci int ret = decode_string(mlz, &buff[output_chars], last_string_code, &char_code, size - output_chars); 162cabdff1aSopenharmony_ci if (ret < 0 || ret > size - output_chars) { 163cabdff1aSopenharmony_ci av_log(mlz->context, AV_LOG_ERROR, "output chars overflow\n"); 164cabdff1aSopenharmony_ci return output_chars; 165cabdff1aSopenharmony_ci } 166cabdff1aSopenharmony_ci output_chars += ret; 167cabdff1aSopenharmony_ci ret = decode_string(mlz, &buff[output_chars], char_code, &char_code, size - output_chars); 168cabdff1aSopenharmony_ci if (ret < 0 || ret > size - output_chars) { 169cabdff1aSopenharmony_ci av_log(mlz->context, AV_LOG_ERROR, "output chars overflow\n"); 170cabdff1aSopenharmony_ci return output_chars; 171cabdff1aSopenharmony_ci } 172cabdff1aSopenharmony_ci output_chars += ret; 173cabdff1aSopenharmony_ci set_new_entry_dict(dict, mlz->next_code, last_string_code, char_code); 174cabdff1aSopenharmony_ci if (mlz->next_code >= TABLE_SIZE - 1) { 175cabdff1aSopenharmony_ci av_log(mlz->context, AV_LOG_ERROR, "Too many MLZ codes\n"); 176cabdff1aSopenharmony_ci return output_chars; 177cabdff1aSopenharmony_ci } 178cabdff1aSopenharmony_ci mlz->next_code++; 179cabdff1aSopenharmony_ci } else { 180cabdff1aSopenharmony_ci int ret = decode_string(mlz, &buff[output_chars], string_code, &char_code, size - output_chars); 181cabdff1aSopenharmony_ci if (ret < 0 || ret > size - output_chars) { 182cabdff1aSopenharmony_ci av_log(mlz->context, AV_LOG_ERROR, "output chars overflow\n"); 183cabdff1aSopenharmony_ci return output_chars; 184cabdff1aSopenharmony_ci } 185cabdff1aSopenharmony_ci output_chars += ret; 186cabdff1aSopenharmony_ci if (output_chars <= size && !mlz->freeze_flag) { 187cabdff1aSopenharmony_ci if (last_string_code != -1) { 188cabdff1aSopenharmony_ci set_new_entry_dict(dict, mlz->next_code, last_string_code, char_code); 189cabdff1aSopenharmony_ci if (mlz->next_code >= TABLE_SIZE - 1) { 190cabdff1aSopenharmony_ci av_log(mlz->context, AV_LOG_ERROR, "Too many MLZ codes\n"); 191cabdff1aSopenharmony_ci return output_chars; 192cabdff1aSopenharmony_ci } 193cabdff1aSopenharmony_ci mlz->next_code++; 194cabdff1aSopenharmony_ci } 195cabdff1aSopenharmony_ci } else { 196cabdff1aSopenharmony_ci break; 197cabdff1aSopenharmony_ci } 198cabdff1aSopenharmony_ci } 199cabdff1aSopenharmony_ci last_string_code = string_code; 200cabdff1aSopenharmony_ci } 201cabdff1aSopenharmony_ci break; 202cabdff1aSopenharmony_ci } 203cabdff1aSopenharmony_ci } 204cabdff1aSopenharmony_ci return output_chars; 205cabdff1aSopenharmony_ci} 206