Linux Audio

Check our new training course

Loading...
v5.14.15
  1// SPDX-License-Identifier: Zlib
  2
  3#include "../zlib_deflate/defutil.h"
  4#include "dfltcc_util.h"
  5#include "dfltcc.h"
  6#include <asm/setup.h>
  7#include <linux/export.h>
  8#include <linux/zutil.h>
  9
 
 
 10/*
 11 * Compress.
 12 */
 13int dfltcc_can_deflate(
 14    z_streamp strm
 15)
 16{
 17    deflate_state *state = (deflate_state *)strm->state;
 18    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
 19
 20    /* Check for kernel dfltcc command line parameter */
 21    if (zlib_dfltcc_support == ZLIB_DFLTCC_DISABLED ||
 22            zlib_dfltcc_support == ZLIB_DFLTCC_INFLATE_ONLY)
 23        return 0;
 24
 25    /* Unsupported compression settings */
 26    if (!dfltcc_are_params_ok(state->level, state->w_bits, state->strategy,
 27                              dfltcc_state->level_mask))
 28        return 0;
 29
 30    /* Unsupported hardware */
 31    if (!is_bit_set(dfltcc_state->af.fns, DFLTCC_GDHT) ||
 32            !is_bit_set(dfltcc_state->af.fns, DFLTCC_CMPR) ||
 33            !is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0))
 34        return 0;
 35
 36    return 1;
 37}
 38EXPORT_SYMBOL(dfltcc_can_deflate);
 39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 40static void dfltcc_gdht(
 41    z_streamp strm
 42)
 43{
 44    deflate_state *state = (deflate_state *)strm->state;
 45    struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
 46    size_t avail_in = avail_in = strm->avail_in;
 47
 48    dfltcc(DFLTCC_GDHT,
 49           param, NULL, NULL,
 50           &strm->next_in, &avail_in, NULL);
 51}
 52
 53static dfltcc_cc dfltcc_cmpr(
 54    z_streamp strm
 55)
 56{
 57    deflate_state *state = (deflate_state *)strm->state;
 58    struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
 59    size_t avail_in = strm->avail_in;
 60    size_t avail_out = strm->avail_out;
 61    dfltcc_cc cc;
 62
 63    cc = dfltcc(DFLTCC_CMPR | HBT_CIRCULAR,
 64                param, &strm->next_out, &avail_out,
 65                &strm->next_in, &avail_in, state->window);
 66    strm->total_in += (strm->avail_in - avail_in);
 67    strm->total_out += (strm->avail_out - avail_out);
 68    strm->avail_in = avail_in;
 69    strm->avail_out = avail_out;
 70    return cc;
 71}
 72
 73static void send_eobs(
 74    z_streamp strm,
 75    const struct dfltcc_param_v0 *param
 76)
 77{
 78    deflate_state *state = (deflate_state *)strm->state;
 79
 80    zlib_tr_send_bits(
 81          state,
 82          bi_reverse(param->eobs >> (15 - param->eobl), param->eobl),
 83          param->eobl);
 84    flush_pending(strm);
 85    if (state->pending != 0) {
 86        /* The remaining data is located in pending_out[0:pending]. If someone
 87         * calls put_byte() - this might happen in deflate() - the byte will be
 88         * placed into pending_buf[pending], which is incorrect. Move the
 89         * remaining data to the beginning of pending_buf so that put_byte() is
 90         * usable again.
 91         */
 92        memmove(state->pending_buf, state->pending_out, state->pending);
 93        state->pending_out = state->pending_buf;
 94    }
 95#ifdef ZLIB_DEBUG
 96    state->compressed_len += param->eobl;
 97#endif
 98}
 99
100int dfltcc_deflate(
101    z_streamp strm,
102    int flush,
103    block_state *result
104)
105{
106    deflate_state *state = (deflate_state *)strm->state;
107    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
108    struct dfltcc_param_v0 *param = &dfltcc_state->param;
109    uInt masked_avail_in;
110    dfltcc_cc cc;
111    int need_empty_block;
112    int soft_bcc;
113    int no_flush;
114
115    if (!dfltcc_can_deflate(strm))
 
 
 
116        return 0;
 
117
118again:
119    masked_avail_in = 0;
120    soft_bcc = 0;
121    no_flush = flush == Z_NO_FLUSH;
122
123    /* Trailing empty block. Switch to software, except when Continuation Flag
124     * is set, which means that DFLTCC has buffered some output in the
125     * parameter block and needs to be called again in order to flush it.
126     */
127    if (flush == Z_FINISH && strm->avail_in == 0 && !param->cf) {
128        if (param->bcf) {
129            /* A block is still open, and the hardware does not support closing
130             * blocks without adding data. Thus, close it manually.
131             */
132            send_eobs(strm, param);
133            param->bcf = 0;
134        }
135        return 0;
136    }
137
138    if (strm->avail_in == 0 && !param->cf) {
139        *result = need_more;
 
 
 
140        return 1;
141    }
142
143    /* There is an open non-BFINAL block, we are not going to close it just
144     * yet, we have compressed more than DFLTCC_BLOCK_SIZE bytes and we see
145     * more than DFLTCC_DHT_MIN_SAMPLE_SIZE bytes. Open a new block with a new
146     * DHT in order to adapt to a possibly changed input data distribution.
147     */
148    if (param->bcf && no_flush &&
149            strm->total_in > dfltcc_state->block_threshold &&
150            strm->avail_in >= dfltcc_state->dht_threshold) {
151        if (param->cf) {
152            /* We need to flush the DFLTCC buffer before writing the
153             * End-of-block Symbol. Mask the input data and proceed as usual.
154             */
155            masked_avail_in += strm->avail_in;
156            strm->avail_in = 0;
157            no_flush = 0;
158        } else {
159            /* DFLTCC buffer is empty, so we can manually write the
160             * End-of-block Symbol right away.
161             */
162            send_eobs(strm, param);
163            param->bcf = 0;
164            dfltcc_state->block_threshold =
165                strm->total_in + dfltcc_state->block_size;
166            if (strm->avail_out == 0) {
167                *result = need_more;
168                return 1;
169            }
170        }
171    }
172
 
 
 
 
 
 
 
 
 
173    /* The caller gave us too much data. Pass only one block worth of
174     * uncompressed data to DFLTCC and mask the rest, so that on the next
175     * iteration we start a new block.
176     */
177    if (no_flush && strm->avail_in > dfltcc_state->block_size) {
178        masked_avail_in += (strm->avail_in - dfltcc_state->block_size);
179        strm->avail_in = dfltcc_state->block_size;
180    }
181
182    /* When we have an open non-BFINAL deflate block and caller indicates that
183     * the stream is ending, we need to close an open deflate block and open a
184     * BFINAL one.
185     */
186    need_empty_block = flush == Z_FINISH && param->bcf && !param->bhf;
187
188    /* Translate stream to parameter block */
189    param->cvt = CVT_ADLER32;
190    if (!no_flush)
191        /* We need to close a block. Always do this in software - when there is
192         * no input data, the hardware will not nohor BCC. */
193        soft_bcc = 1;
194    if (flush == Z_FINISH && !param->bcf)
195        /* We are about to open a BFINAL block, set Block Header Final bit
196         * until the stream ends.
197         */
198        param->bhf = 1;
199    /* DFLTCC-CMPR will write to next_out, so make sure that buffers with
200     * higher precedence are empty.
201     */
202    Assert(state->pending == 0, "There must be no pending bytes");
203    Assert(state->bi_valid < 8, "There must be less than 8 pending bits");
204    param->sbb = (unsigned int)state->bi_valid;
205    if (param->sbb > 0)
206        *strm->next_out = (Byte)state->bi_buf;
207    if (param->hl)
208        param->nt = 0; /* Honor history */
209    param->cv = strm->adler;
210
211    /* When opening a block, choose a Huffman-Table Type */
212    if (!param->bcf) {
213        if (strm->total_in == 0 && dfltcc_state->block_threshold > 0) {
214            param->htt = HTT_FIXED;
215        }
216        else {
217            param->htt = HTT_DYNAMIC;
218            dfltcc_gdht(strm);
219        }
220    }
221
222    /* Deflate */
223    do {
224        cc = dfltcc_cmpr(strm);
225        if (strm->avail_in < 4096 && masked_avail_in > 0)
226            /* We are about to call DFLTCC with a small input buffer, which is
227             * inefficient. Since there is masked data, there will be at least
228             * one more DFLTCC call, so skip the current one and make the next
229             * one handle more data.
230             */
231            break;
232    } while (cc == DFLTCC_CC_AGAIN);
233
234    /* Translate parameter block to stream */
235    strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
236    state->bi_valid = param->sbb;
237    if (state->bi_valid == 0)
238        state->bi_buf = 0; /* Avoid accessing next_out */
239    else
240        state->bi_buf = *strm->next_out & ((1 << state->bi_valid) - 1);
241    strm->adler = param->cv;
242
243    /* Unmask the input data */
244    strm->avail_in += masked_avail_in;
245    masked_avail_in = 0;
246
247    /* If we encounter an error, it means there is a bug in DFLTCC call */
248    Assert(cc != DFLTCC_CC_OP2_CORRUPT || param->oesc == 0, "BUG");
249
250    /* Update Block-Continuation Flag. It will be used to check whether to call
251     * GDHT the next time.
252     */
253    if (cc == DFLTCC_CC_OK) {
254        if (soft_bcc) {
255            send_eobs(strm, param);
256            param->bcf = 0;
257            dfltcc_state->block_threshold =
258                strm->total_in + dfltcc_state->block_size;
259        } else
260            param->bcf = 1;
261        if (flush == Z_FINISH) {
262            if (need_empty_block)
263                /* Make the current deflate() call also close the stream */
264                return 0;
265            else {
266                bi_windup(state);
267                *result = finish_done;
268            }
269        } else {
270            if (flush == Z_FULL_FLUSH)
271                param->hl = 0; /* Clear history */
272            *result = flush == Z_NO_FLUSH ? need_more : block_done;
273        }
274    } else {
275        param->bcf = 1;
276        *result = need_more;
277    }
278    if (strm->avail_in != 0 && strm->avail_out != 0)
279        goto again; /* deflate() must use all input or all output */
280    return 1;
281}
282EXPORT_SYMBOL(dfltcc_deflate);
v6.9.4
  1// SPDX-License-Identifier: Zlib
  2
  3#include "../zlib_deflate/defutil.h"
  4#include "dfltcc_util.h"
  5#include "dfltcc_deflate.h"
  6#include <asm/setup.h>
  7#include <linux/export.h>
  8#include <linux/zutil.h>
  9
 10#define GET_DFLTCC_DEFLATE_STATE(state) ((struct dfltcc_deflate_state *)GET_DFLTCC_STATE(state))
 11
 12/*
 13 * Compress.
 14 */
 15int dfltcc_can_deflate(
 16    z_streamp strm
 17)
 18{
 19    deflate_state *state = (deflate_state *)strm->state;
 20    struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state);
 21
 22    /* Check for kernel dfltcc command line parameter */
 23    if (zlib_dfltcc_support == ZLIB_DFLTCC_DISABLED ||
 24            zlib_dfltcc_support == ZLIB_DFLTCC_INFLATE_ONLY)
 25        return 0;
 26
 27    /* Unsupported compression settings */
 28    if (!dfltcc_are_params_ok(state->level, state->w_bits, state->strategy,
 29                              dfltcc_state->level_mask))
 30        return 0;
 31
 32    /* Unsupported hardware */
 33    if (!is_bit_set(dfltcc_state->common.af.fns, DFLTCC_GDHT) ||
 34            !is_bit_set(dfltcc_state->common.af.fns, DFLTCC_CMPR) ||
 35            !is_bit_set(dfltcc_state->common.af.fmts, DFLTCC_FMT0))
 36        return 0;
 37
 38    return 1;
 39}
 40EXPORT_SYMBOL(dfltcc_can_deflate);
 41
 42void dfltcc_reset_deflate_state(z_streamp strm) {
 43    deflate_state *state = (deflate_state *)strm->state;
 44    struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state);
 45
 46    dfltcc_reset_state(&dfltcc_state->common);
 47
 48    /* Initialize tuning parameters */
 49    if (zlib_dfltcc_support == ZLIB_DFLTCC_FULL_DEBUG)
 50        dfltcc_state->level_mask = DFLTCC_LEVEL_MASK_DEBUG;
 51    else
 52        dfltcc_state->level_mask = DFLTCC_LEVEL_MASK;
 53    dfltcc_state->block_size = DFLTCC_BLOCK_SIZE;
 54    dfltcc_state->block_threshold = DFLTCC_FIRST_FHT_BLOCK_SIZE;
 55    dfltcc_state->dht_threshold = DFLTCC_DHT_MIN_SAMPLE_SIZE;
 56}
 57EXPORT_SYMBOL(dfltcc_reset_deflate_state);
 58
 59static void dfltcc_gdht(
 60    z_streamp strm
 61)
 62{
 63    deflate_state *state = (deflate_state *)strm->state;
 64    struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
 65    size_t avail_in = strm->avail_in;
 66
 67    dfltcc(DFLTCC_GDHT,
 68           param, NULL, NULL,
 69           &strm->next_in, &avail_in, NULL);
 70}
 71
 72static dfltcc_cc dfltcc_cmpr(
 73    z_streamp strm
 74)
 75{
 76    deflate_state *state = (deflate_state *)strm->state;
 77    struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
 78    size_t avail_in = strm->avail_in;
 79    size_t avail_out = strm->avail_out;
 80    dfltcc_cc cc;
 81
 82    cc = dfltcc(DFLTCC_CMPR | HBT_CIRCULAR,
 83                param, &strm->next_out, &avail_out,
 84                &strm->next_in, &avail_in, state->window);
 85    strm->total_in += (strm->avail_in - avail_in);
 86    strm->total_out += (strm->avail_out - avail_out);
 87    strm->avail_in = avail_in;
 88    strm->avail_out = avail_out;
 89    return cc;
 90}
 91
 92static void send_eobs(
 93    z_streamp strm,
 94    const struct dfltcc_param_v0 *param
 95)
 96{
 97    deflate_state *state = (deflate_state *)strm->state;
 98
 99    zlib_tr_send_bits(
100          state,
101          bi_reverse(param->eobs >> (15 - param->eobl), param->eobl),
102          param->eobl);
103    flush_pending(strm);
104    if (state->pending != 0) {
105        /* The remaining data is located in pending_out[0:pending]. If someone
106         * calls put_byte() - this might happen in deflate() - the byte will be
107         * placed into pending_buf[pending], which is incorrect. Move the
108         * remaining data to the beginning of pending_buf so that put_byte() is
109         * usable again.
110         */
111        memmove(state->pending_buf, state->pending_out, state->pending);
112        state->pending_out = state->pending_buf;
113    }
114#ifdef ZLIB_DEBUG
115    state->compressed_len += param->eobl;
116#endif
117}
118
119int dfltcc_deflate(
120    z_streamp strm,
121    int flush,
122    block_state *result
123)
124{
125    deflate_state *state = (deflate_state *)strm->state;
126    struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state);
127    struct dfltcc_param_v0 *param = &dfltcc_state->common.param;
128    uInt masked_avail_in;
129    dfltcc_cc cc;
130    int need_empty_block;
131    int soft_bcc;
132    int no_flush;
133
134    if (!dfltcc_can_deflate(strm)) {
135        /* Clear history. */
136        if (flush == Z_FULL_FLUSH)
137            param->hl = 0;
138        return 0;
139    }
140
141again:
142    masked_avail_in = 0;
143    soft_bcc = 0;
144    no_flush = flush == Z_NO_FLUSH;
145
146    /* No input data. Return, except when Continuation Flag is set, which means
147     * that DFLTCC has buffered some output in the parameter block and needs to
148     * be called again in order to flush it.
149     */
150    if (strm->avail_in == 0 && !param->cf) {
151        /* A block is still open, and the hardware does not support closing
152         * blocks without adding data. Thus, close it manually.
153         */
154        if (!no_flush && param->bcf) {
155            send_eobs(strm, param);
156            param->bcf = 0;
157        }
158        /* Let one of deflate_* functions write a trailing empty block. */
159        if (flush == Z_FINISH)
160            return 0;
161        /* Clear history. */
162        if (flush == Z_FULL_FLUSH)
163            param->hl = 0;
164        /* Trigger block post-processing if necessary. */
165        *result = no_flush ? need_more : block_done;
166        return 1;
167    }
168
169    /* There is an open non-BFINAL block, we are not going to close it just
170     * yet, we have compressed more than DFLTCC_BLOCK_SIZE bytes and we see
171     * more than DFLTCC_DHT_MIN_SAMPLE_SIZE bytes. Open a new block with a new
172     * DHT in order to adapt to a possibly changed input data distribution.
173     */
174    if (param->bcf && no_flush &&
175            strm->total_in > dfltcc_state->block_threshold &&
176            strm->avail_in >= dfltcc_state->dht_threshold) {
177        if (param->cf) {
178            /* We need to flush the DFLTCC buffer before writing the
179             * End-of-block Symbol. Mask the input data and proceed as usual.
180             */
181            masked_avail_in += strm->avail_in;
182            strm->avail_in = 0;
183            no_flush = 0;
184        } else {
185            /* DFLTCC buffer is empty, so we can manually write the
186             * End-of-block Symbol right away.
187             */
188            send_eobs(strm, param);
189            param->bcf = 0;
190            dfltcc_state->block_threshold =
191                strm->total_in + dfltcc_state->block_size;
 
 
 
 
192        }
193    }
194
195    /* No space for compressed data. If we proceed, dfltcc_cmpr() will return
196     * DFLTCC_CC_OP1_TOO_SHORT without buffering header bits, but we will still
197     * set BCF=1, which is wrong. Avoid complications and return early.
198     */
199    if (strm->avail_out == 0) {
200        *result = need_more;
201        return 1;
202    }
203
204    /* The caller gave us too much data. Pass only one block worth of
205     * uncompressed data to DFLTCC and mask the rest, so that on the next
206     * iteration we start a new block.
207     */
208    if (no_flush && strm->avail_in > dfltcc_state->block_size) {
209        masked_avail_in += (strm->avail_in - dfltcc_state->block_size);
210        strm->avail_in = dfltcc_state->block_size;
211    }
212
213    /* When we have an open non-BFINAL deflate block and caller indicates that
214     * the stream is ending, we need to close an open deflate block and open a
215     * BFINAL one.
216     */
217    need_empty_block = flush == Z_FINISH && param->bcf && !param->bhf;
218
219    /* Translate stream to parameter block */
220    param->cvt = CVT_ADLER32;
221    if (!no_flush)
222        /* We need to close a block. Always do this in software - when there is
223         * no input data, the hardware will not hohor BCC. */
224        soft_bcc = 1;
225    if (flush == Z_FINISH && !param->bcf)
226        /* We are about to open a BFINAL block, set Block Header Final bit
227         * until the stream ends.
228         */
229        param->bhf = 1;
230    /* DFLTCC-CMPR will write to next_out, so make sure that buffers with
231     * higher precedence are empty.
232     */
233    Assert(state->pending == 0, "There must be no pending bytes");
234    Assert(state->bi_valid < 8, "There must be less than 8 pending bits");
235    param->sbb = (unsigned int)state->bi_valid;
236    if (param->sbb > 0)
237        *strm->next_out = (Byte)state->bi_buf;
238    /* Honor history and check value */
239    param->nt = 0;
240    param->cv = strm->adler;
241
242    /* When opening a block, choose a Huffman-Table Type */
243    if (!param->bcf) {
244        if (strm->total_in == 0 && dfltcc_state->block_threshold > 0) {
245            param->htt = HTT_FIXED;
246        }
247        else {
248            param->htt = HTT_DYNAMIC;
249            dfltcc_gdht(strm);
250        }
251    }
252
253    /* Deflate */
254    do {
255        cc = dfltcc_cmpr(strm);
256        if (strm->avail_in < 4096 && masked_avail_in > 0)
257            /* We are about to call DFLTCC with a small input buffer, which is
258             * inefficient. Since there is masked data, there will be at least
259             * one more DFLTCC call, so skip the current one and make the next
260             * one handle more data.
261             */
262            break;
263    } while (cc == DFLTCC_CC_AGAIN);
264
265    /* Translate parameter block to stream */
266    strm->msg = oesc_msg(dfltcc_state->common.msg, param->oesc);
267    state->bi_valid = param->sbb;
268    if (state->bi_valid == 0)
269        state->bi_buf = 0; /* Avoid accessing next_out */
270    else
271        state->bi_buf = *strm->next_out & ((1 << state->bi_valid) - 1);
272    strm->adler = param->cv;
273
274    /* Unmask the input data */
275    strm->avail_in += masked_avail_in;
276    masked_avail_in = 0;
277
278    /* If we encounter an error, it means there is a bug in DFLTCC call */
279    Assert(cc != DFLTCC_CC_OP2_CORRUPT || param->oesc == 0, "BUG");
280
281    /* Update Block-Continuation Flag. It will be used to check whether to call
282     * GDHT the next time.
283     */
284    if (cc == DFLTCC_CC_OK) {
285        if (soft_bcc) {
286            send_eobs(strm, param);
287            param->bcf = 0;
288            dfltcc_state->block_threshold =
289                strm->total_in + dfltcc_state->block_size;
290        } else
291            param->bcf = 1;
292        if (flush == Z_FINISH) {
293            if (need_empty_block)
294                /* Make the current deflate() call also close the stream */
295                return 0;
296            else {
297                bi_windup(state);
298                *result = finish_done;
299            }
300        } else {
301            if (flush == Z_FULL_FLUSH)
302                param->hl = 0; /* Clear history */
303            *result = flush == Z_NO_FLUSH ? need_more : block_done;
304        }
305    } else {
306        param->bcf = 1;
307        *result = need_more;
308    }
309    if (strm->avail_in != 0 && strm->avail_out != 0)
310        goto again; /* deflate() must use all input or all output */
311    return 1;
312}
313EXPORT_SYMBOL(dfltcc_deflate);