2 * Copyright (c) 2016 Umair Khan <omerjerk@gmail.com>
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 av_cold
int ff_mlz_init_dict(void *context
, MLZ
*mlz
)
25 mlz
->dict
= av_mallocz(TABLE_SIZE
* sizeof(*mlz
->dict
));
27 return AVERROR(ENOMEM
);
29 mlz
->flush_code
= FLUSH_CODE
;
30 mlz
->current_dic_index_max
= DIC_INDEX_INIT
;
31 mlz
->dic_code_bit
= CODE_BIT_INIT
;
32 mlz
->bump_code
= (DIC_INDEX_INIT
- 1);
33 mlz
->next_code
= FIRST_CODE
;
35 mlz
->context
= context
;
40 av_cold
void ff_mlz_flush_dict(MLZ
*mlz
) {
41 MLZDict
*dict
= mlz
->dict
;
43 for ( i
= 0; i
< TABLE_SIZE
; i
++ ) {
44 dict
[i
].string_code
= CODE_UNSET
;
45 dict
[i
].parent_code
= CODE_UNSET
;
46 dict
[i
].match_len
= 0;
48 mlz
->current_dic_index_max
= DIC_INDEX_INIT
;
49 mlz
->dic_code_bit
= CODE_BIT_INIT
; // DicCodeBitInit;
50 mlz
->bump_code
= mlz
->current_dic_index_max
- 1;
51 mlz
->next_code
= FIRST_CODE
;
55 static void set_new_entry_dict(MLZDict
* dict
, int string_code
, int parent_code
, int char_code
) {
56 dict
[string_code
].parent_code
= parent_code
;
57 dict
[string_code
].string_code
= string_code
;
58 dict
[string_code
].char_code
= char_code
;
59 if (parent_code
< FIRST_CODE
) {
60 dict
[string_code
].match_len
= 2;
62 dict
[string_code
].match_len
= (dict
[parent_code
].match_len
) + 1;
66 static int decode_string(MLZ
* mlz
, unsigned char *buff
, int string_code
, int *first_char_code
, unsigned long bufsize
) {
67 MLZDict
* dict
= mlz
->dict
;
68 unsigned long count
, offset
;
69 int current_code
, parent_code
, tmp_code
;
72 current_code
= string_code
;
73 *first_char_code
= CODE_UNSET
;
75 while (count
< bufsize
) {
76 switch (current_code
) {
81 if (current_code
< FIRST_CODE
) {
82 *first_char_code
= current_code
;
83 buff
[0] = current_code
;
87 offset
= dict
[current_code
].match_len
- 1;
88 tmp_code
= dict
[current_code
].char_code
;
89 if (offset
>= bufsize
) {
90 av_log(mlz
->context
, AV_LOG_ERROR
, "MLZ offset error.\n");
93 buff
[offset
] = tmp_code
;
96 current_code
= dict
[current_code
].parent_code
;
97 if ((current_code
< 0) || (current_code
> (DIC_INDEX_MAX
- 1))) {
98 av_log(mlz
->context
, AV_LOG_ERROR
, "MLZ dic index error.\n");
101 if (current_code
> FIRST_CODE
) {
102 parent_code
= dict
[current_code
].parent_code
;
103 offset
= (dict
[current_code
].match_len
) - 1;
104 if (parent_code
< 0 || parent_code
> DIC_INDEX_MAX
-1) {
105 av_log(mlz
->context
, AV_LOG_ERROR
, "MLZ dic index error.\n");
108 if (( offset
> (DIC_INDEX_MAX
- 1))) {
109 av_log(mlz
->context
, AV_LOG_ERROR
, "MLZ dic offset error.\n");
119 static int input_code(GetBitContext
* gb
, int len
) {
122 for (i
= 0; i
< len
; ++i
) {
123 tmp_code
|= get_bits1(gb
) << i
;
128 int ff_mlz_decompression(MLZ
* mlz
, GetBitContext
* gb
, int size
, unsigned char *buff
) {
129 MLZDict
*dict
= mlz
->dict
;
130 unsigned long output_chars
;
131 int string_code
, last_string_code
, char_code
;
135 last_string_code
= -1;
138 while (output_chars
< size
) {
139 string_code
= input_code(gb
, mlz
->dic_code_bit
);
140 switch (string_code
) {
143 ff_mlz_flush_dict(mlz
);
145 last_string_code
= -1;
148 mlz
->freeze_flag
= 1;
151 if (string_code
> mlz
->current_dic_index_max
) {
152 av_log(mlz
->context
, AV_LOG_ERROR
, "String code %d exceeds maximum value of %d.\n", string_code
, mlz
->current_dic_index_max
);
155 if (string_code
== (int) mlz
->bump_code
) {
157 mlz
->current_dic_index_max
*= 2;
158 mlz
->bump_code
= mlz
->current_dic_index_max
- 1;
160 if (string_code
>= mlz
->next_code
) {
161 int ret
= decode_string(mlz
, &buff
[output_chars
], last_string_code
, &char_code
, size
- output_chars
);
162 if (ret
< 0 || ret
> size
- output_chars
) {
163 av_log(mlz
->context
, AV_LOG_ERROR
, "output chars overflow\n");
167 ret
= decode_string(mlz
, &buff
[output_chars
], char_code
, &char_code
, size
- output_chars
);
168 if (ret
< 0 || ret
> size
- output_chars
) {
169 av_log(mlz
->context
, AV_LOG_ERROR
, "output chars overflow\n");
173 set_new_entry_dict(dict
, mlz
->next_code
, last_string_code
, char_code
);
174 if (mlz
->next_code
>= TABLE_SIZE
- 1) {
175 av_log(mlz
->context
, AV_LOG_ERROR
, "Too many MLZ codes\n");
180 int ret
= decode_string(mlz
, &buff
[output_chars
], string_code
, &char_code
, size
- output_chars
);
181 if (ret
< 0 || ret
> size
- output_chars
) {
182 av_log(mlz
->context
, AV_LOG_ERROR
, "output chars overflow\n");
186 if (output_chars
<= size
&& !mlz
->freeze_flag
) {
187 if (last_string_code
!= -1) {
188 set_new_entry_dict(dict
, mlz
->next_code
, last_string_code
, char_code
);
189 if (mlz
->next_code
>= TABLE_SIZE
- 1) {
190 av_log(mlz
->context
, AV_LOG_ERROR
, "Too many MLZ codes\n");
199 last_string_code
= string_code
;