18bd2087c0663103854a53133163d104377ca1b5
[platform/upstream/libaec.git] / src / decode.c
1 /**
2  * @file decode.c
3  *
4  * @author Mathis Rosenhauer, Deutsches Klimarechenzentrum
5  * @author Moritz Hanke, Deutsches Klimarechenzentrum
6  * @author Joerg Behrens, Deutsches Klimarechenzentrum
7  * @author Luis Kornblueh, Max-Planck-Institut fuer Meteorologie
8  *
9  * @section LICENSE
10  * Copyright 2012
11  *
12  * Mathis Rosenhauer,                 Luis Kornblueh
13  * Moritz Hanke,
14  * Joerg Behrens
15  *
16  * Deutsches Klimarechenzentrum GmbH  Max-Planck-Institut fuer Meteorologie
17  * Bundesstr. 45a                     Bundesstr. 53
18  * 20146 Hamburg                      20146 Hamburg
19  * Germany                            Germany
20  *
21  * All rights reserved.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  *
27  * 1. Redistributions of source code must retain the above copyright
28  *    notice, this list of conditions and the following disclaimer.
29  * 2. Redistributions in binary form must reproduce the above
30  *    copyright notice, this list of conditions and the following
31  *    disclaimer in the documentation and/or other materials provided
32  *    with the distribution.
33  *
34  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
35  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
37  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
38  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
39  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
41  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
43  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
45  * OF THE POSSIBILITY OF SUCH DAMAGE.
46  *
47  * @section DESCRIPTION
48  *
49  * Adaptive Entropy Decoder
50  * Based on CCSDS documents 121.0-B-2 and 120.0-G-2
51  *
52  */
53
54 #include <config.h>
55
56 #if HAVE_STDINT_H
57 # include <stdint.h>
58 #endif
59
60 #include <stdio.h>
61 #include <unistd.h>
62 #include <stdlib.h>
63 #include <string.h>
64
65 #include "libaec.h"
66 #include "decode.h"
67
68 #define ROS 5
69
70 #define BUFFERSPACE(strm) (strm->avail_in >= strm->state->in_blklen     \
71                            && strm->avail_out >= strm->state->out_blklen)
72
73 #define FLUSH(KIND)                                                     \
74     static void flush_##KIND(struct aec_stream *strm)                   \
75     {                                                                   \
76         uint32_t *bp, *flush_end;                                       \
77         int64_t d, m;                                                   \
78         int64_t data, med, half_d, xmin, xmax;                          \
79         struct internal_state *state = strm->state;                     \
80                                                                         \
81         flush_end = state->rsip;                                        \
82         if (state->pp) {                                                \
83             if (state->flush_start == state->rsi_buffer                 \
84                 && state->rsip > state->rsi_buffer) {                   \
85                 state->last_out = *state->rsi_buffer;                   \
86                                                                         \
87                 if (strm->flags & AEC_DATA_SIGNED) {                    \
88                     m = 1ULL << (strm->bits_per_sample - 1);            \
89                     /* Reference samples have to be sign extended */    \
90                     state->last_out = (state->last_out ^ m) - m;        \
91                 }                                                       \
92                 put_##KIND(strm, state->last_out);                      \
93                 state->flush_start++;                                   \
94             }                                                           \
95                                                                         \
96             data = state->last_out;                                     \
97             if (strm->flags & AEC_DATA_SIGNED)                          \
98                 med = 0;                                                \
99             else                                                        \
100                 med = (state->xmax - state->xmin) / 2 + 1;              \
101                                                                         \
102             xmin = state->xmin;                                         \
103             xmax = state->xmax;                                         \
104                                                                         \
105             for (bp = state->flush_start; bp < flush_end; bp++) {       \
106                 d = *bp;                                                \
107                 half_d = (d + 1) >> 1;                                  \
108                                                                         \
109                 if (data < med) {                                       \
110                     if (half_d <= data - xmin) {                        \
111                         if (d & 1)                                      \
112                             data -= half_d;                             \
113                         else                                            \
114                             data += half_d;                             \
115                     } else {                                            \
116                         data = xmin + d;                                \
117                     }                                                   \
118                 } else {                                                \
119                     if (half_d <= xmax - data) {                        \
120                         if (d & 1)                                      \
121                             data -= half_d;                             \
122                         else                                            \
123                             data += half_d;                             \
124                     } else {                                            \
125                         data = xmax - d;                                \
126                     }                                                   \
127                 }                                                       \
128                 put_##KIND(strm, data);                                 \
129             }                                                           \
130             state->last_out = data;                                     \
131         } else {                                                        \
132             for (bp = state->flush_start; bp < flush_end; bp++)         \
133                 put_##KIND(strm, *bp);                                  \
134         }                                                               \
135         state->flush_start = state->rsip;                               \
136     }
137
138
139 static inline void put_msb_32(struct aec_stream *strm, uint32_t data)
140 {
141     *strm->next_out++ = data >> 24;
142     *strm->next_out++ = data >> 16;
143     *strm->next_out++ = data >> 8;
144     *strm->next_out++ = data;
145 }
146
147 static inline void put_msb_24(struct aec_stream *strm, uint32_t data)
148 {
149     *strm->next_out++ = data >> 16;
150     *strm->next_out++ = data >> 8;
151     *strm->next_out++ = data;
152 }
153
154 static inline void put_msb_16(struct aec_stream *strm, uint32_t data)
155 {
156     *strm->next_out++ = data >> 8;
157     *strm->next_out++ = data;
158 }
159
160 static inline void put_lsb_32(struct aec_stream *strm, uint32_t data)
161 {
162     *strm->next_out++ = data;
163     *strm->next_out++ = data >> 8;
164     *strm->next_out++ = data >> 16;
165     *strm->next_out++ = data >> 24;
166 }
167
168 static inline void put_lsb_24(struct aec_stream *strm, uint32_t data)
169 {
170     *strm->next_out++ = data;
171     *strm->next_out++ = data >> 8;
172     *strm->next_out++ = data >> 16;
173 }
174
175 static inline void put_lsb_16(struct aec_stream *strm, uint32_t data)
176 {
177     *strm->next_out++ = data;
178     *strm->next_out++ = data >> 8;
179 }
180
181 static inline void put_8(struct aec_stream *strm, uint32_t data)
182 {
183     *strm->next_out++ = data;
184 }
185
186 FLUSH(msb_32);
187 FLUSH(msb_24);
188 FLUSH(msb_16);
189 FLUSH(lsb_32);
190 FLUSH(lsb_24);
191 FLUSH(lsb_16);
192 FLUSH(8);
193
194 static inline void check_rsi_end(struct aec_stream *strm)
195 {
196     /**
197        Flush output if end of RSI reached
198      */
199     struct internal_state *state = strm->state;
200
201     if (state->rsip - state->rsi_buffer == state->rsi_size) {
202         state->flush_output(strm);
203         state->flush_start = state->rsi_buffer;
204         state->rsip = state->rsi_buffer;
205     }
206 }
207
208 static inline void put_sample(struct aec_stream *strm, uint32_t s)
209 {
210     struct internal_state *state = strm->state;
211
212     *state->rsip++ = s;
213     strm->avail_out -= state->bytes_per_sample;
214     check_rsi_end(strm);
215 }
216
217 static inline void fill_acc(struct aec_stream *strm)
218 {
219     int b = (63 - strm->state->bitp) >> 3;
220
221     strm->avail_in -= b;
222     strm->state->bitp += b << 3;
223
224     switch (b) {
225       case (7):
226         strm->state->acc = (strm->state->acc << 8) | *strm->next_in++;
227       case (6):
228         strm->state->acc = (strm->state->acc << 8) | *strm->next_in++;
229       case (5):
230         strm->state->acc = (strm->state->acc << 8) | *strm->next_in++;
231       case (4):
232         strm->state->acc = (strm->state->acc << 8) | *strm->next_in++;
233       case (3):
234         strm->state->acc = (strm->state->acc << 8) | *strm->next_in++;
235       case (2):
236         strm->state->acc = (strm->state->acc << 8) | *strm->next_in++;
237       case (1):
238         strm->state->acc = (strm->state->acc << 8) | *strm->next_in++;
239     };
240
241 }
242
243 static inline uint32_t direct_get(struct aec_stream *strm, unsigned int n)
244 {
245     /**
246        Get n bit from input stream
247
248        No checking whatsoever. Read bits are dumped.
249      */
250
251     struct internal_state *state = strm->state;
252
253     if (state->bitp < n)
254         fill_acc(strm);
255
256     state->bitp -= n;
257     return (state->acc >> state->bitp) & ((1ULL << n) - 1);
258 }
259
260 static inline uint32_t direct_get_fs(struct aec_stream *strm)
261 {
262     /**
263        Interpret a Fundamental Sequence from the input buffer.
264
265        Essentially counts the number of 0 bits until a 1 is
266        encountered. The longest FS we can safely detect is 56 bits. If
267        no FS is found in accumulator then we top it up to at least 56
268        bits.
269      */
270
271     uint32_t fs = 0;
272     struct internal_state *state = strm->state;
273
274     state->acc &= ((1ULL << state->bitp) - 1);
275
276     if (state->acc == 0)
277         fill_acc(strm);
278
279 #ifdef HAVE_DECL___BUILTIN_CLZLL
280     fs = __builtin_clzll(state->acc) - (64 - state->bitp);
281     state->bitp -= fs + 1;
282 #else
283     state->bitp--;
284     while ((state->acc & (1ULL << state->bitp)) == 0) {
285         state->bitp--;
286         fs++;
287     }
288 #endif
289     return fs;
290 }
291
292 static inline uint32_t bits_ask(struct aec_stream *strm, int n)
293 {
294     while (strm->state->bitp < n) {
295         if (strm->avail_in == 0)
296             return 0;
297         strm->avail_in--;
298         strm->state->acc <<= 8;
299         strm->state->acc |= *strm->next_in++;
300         strm->state->bitp += 8;
301     }
302     return 1;
303 }
304
305 static inline uint32_t bits_get(struct aec_stream *strm, int n)
306 {
307     return (strm->state->acc >> (strm->state->bitp - n))
308         & ((1ULL << n) - 1);
309 }
310
311 static inline void bits_drop(struct aec_stream *strm, int n)
312 {
313     strm->state->bitp -= n;
314 }
315
316 static inline uint32_t fs_ask(struct aec_stream *strm)
317 {
318     if (bits_ask(strm, 1) == 0)
319         return 0;
320     while ((strm->state->acc & (1ULL << (strm->state->bitp - 1))) == 0) {
321         if (strm->state->bitp == 1) {
322             if (strm->avail_in == 0)
323                 return 0;
324             strm->avail_in--;
325             strm->state->acc <<= 8;
326             strm->state->acc |= *strm->next_in++;
327             strm->state->bitp += 8;
328         }
329         strm->state->fs++;
330         strm->state->bitp--;
331     }
332     return 1;
333 }
334
335 static inline void fs_drop(struct aec_stream *strm)
336 {
337     strm->state->fs = 0;
338     strm->state->bitp--;
339 }
340
341 static inline uint32_t copysample(struct aec_stream *strm)
342 {
343     if (bits_ask(strm, strm->bits_per_sample) == 0
344         || strm->avail_out == 0)
345         return 0;
346
347     put_sample(strm, bits_get(strm, strm->bits_per_sample));
348     bits_drop(strm, strm->bits_per_sample);
349     return 1;
350 }
351
352 static int m_id(struct aec_stream *strm)
353 {
354     struct internal_state *state = strm->state;
355
356     if (state->pp && state->rsip == state->rsi_buffer)
357         state->ref = 1;
358     else
359         state->ref = 0;
360
361     if (bits_ask(strm, state->id_len) == 0)
362         return M_EXIT;
363     state->id = bits_get(strm, state->id_len);
364     bits_drop(strm, state->id_len);
365     state->mode = state->id_table[state->id];
366
367     return M_CONTINUE;
368 }
369
370 static int m_split_output(struct aec_stream *strm)
371 {
372     struct internal_state *state = strm->state;
373     int k = state->id - 1;
374
375     do {
376         if (bits_ask(strm, k) == 0 || strm->avail_out == 0)
377             return M_EXIT;
378         *state->rsip++ += bits_get(strm, k);
379         strm->avail_out -= state->bytes_per_sample;
380         bits_drop(strm, k);
381     } while(++state->i < state->n);
382
383     check_rsi_end(strm);
384     state->mode = m_id;
385     return M_CONTINUE;
386 }
387
388 static int m_split_fs(struct aec_stream *strm)
389 {
390     struct internal_state *state = strm->state;
391     int k = state->id - 1;
392
393     do {
394         if (fs_ask(strm) == 0)
395             return M_EXIT;
396         state->rsip[state->i] = state->fs << k;
397         fs_drop(strm);
398     } while(++state->i < state->n);
399
400     state->i = 0;
401     state->mode = m_split_output;
402     return M_CONTINUE;
403 }
404
405 static int m_split(struct aec_stream *strm)
406 {
407     int i, k;
408     struct internal_state *state = strm->state;
409
410     if (BUFFERSPACE(strm)) {
411         k = state->id - 1;
412
413         if (state->ref)
414             *state->rsip++ = direct_get(strm, strm->bits_per_sample);
415
416         for (i = 0; i < strm->block_size - state->ref; i++)
417             state->rsip[i] = direct_get_fs(strm) << k;
418
419         for (i = state->ref; i < strm->block_size; i++)
420             *state->rsip++ += direct_get(strm, k);
421
422         strm->avail_out -= state->out_blklen;
423         check_rsi_end(strm);
424
425         state->mode = m_id;
426         return M_CONTINUE;
427     }
428
429     if (state->ref) {
430         if (copysample(strm) == 0)
431             return M_EXIT;
432         state->n = strm->block_size - 1;
433     } else {
434         state->n = strm->block_size;
435     }
436
437     state->i = 0;
438     state->mode = m_split_fs;
439     return M_CONTINUE;
440 }
441
442 static int m_zero_output(struct aec_stream *strm)
443 {
444     struct internal_state *state = strm->state;
445
446     do {
447         if (strm->avail_out == 0)
448             return M_EXIT;
449         put_sample(strm, 0);
450     } while(--state->i);
451
452     state->mode = m_id;
453     return M_CONTINUE;
454 }
455
456 static int m_zero_block(struct aec_stream *strm)
457 {
458     int i, zero_blocks, b, zero_bytes;
459     struct internal_state *state = strm->state;
460
461     if (fs_ask(strm) == 0)
462         return M_EXIT;
463     zero_blocks = state->fs + 1;
464     fs_drop(strm);
465
466     if (zero_blocks == ROS) {
467         b = (state->rsip - state->rsi_buffer) / strm->block_size;
468         zero_blocks = MIN(strm->rsi - b, 64 - (b % 64));
469     } else if (zero_blocks > ROS) {
470         zero_blocks--;
471     }
472
473     if (state->ref)
474         i = zero_blocks * strm->block_size - 1;
475     else
476         i = zero_blocks * strm->block_size;
477
478     zero_bytes = i * state->bytes_per_sample;
479     if (strm->avail_out >= zero_bytes) {
480         memset(state->rsip, 0, i * sizeof(uint32_t));
481         state->rsip += i;
482         strm->avail_out -= zero_bytes;
483         check_rsi_end(strm);
484
485         state->mode = m_id;
486         return M_CONTINUE;
487     }
488
489     state->i = i;
490     state->mode = m_zero_output;
491     return M_CONTINUE;
492 }
493
494 static int m_se_decode(struct aec_stream *strm)
495 {
496     int32_t m, d1;
497     struct internal_state *state = strm->state;
498
499     while(state->i < strm->block_size) {
500         if (fs_ask(strm) == 0)
501             return M_EXIT;
502         m = state->fs;
503         d1 = m - state->se_table[2 * m + 1];
504
505         if ((state->i & 1) == 0) {
506             if (strm->avail_out == 0)
507                 return M_EXIT;
508             put_sample(strm, state->se_table[2 * m] - d1);
509             state->i++;
510         }
511
512         if (strm->avail_out == 0)
513             return M_EXIT;
514         put_sample(strm, d1);
515         state->i++;
516         fs_drop(strm);
517     }
518
519     state->mode = m_id;
520     return M_CONTINUE;
521 }
522
523 static int m_se(struct aec_stream *strm)
524 {
525     int i;
526     int32_t m, d1;
527     struct internal_state *state = strm->state;
528
529     if (BUFFERSPACE(strm)) {
530         i = state->ref;
531
532         while (i < strm->block_size) {
533             m = direct_get_fs(strm);
534             d1 = m - state->se_table[2 * m + 1];
535
536             if ((i & 1) == 0) {
537                 put_sample(strm, state->se_table[2 * m] - d1);
538                 i++;
539             }
540             put_sample(strm, d1);
541             i++;
542         }
543         state->mode = m_id;
544         return M_CONTINUE;
545     }
546
547     state->mode = m_se_decode;
548     state->i = state->ref;
549     return M_CONTINUE;
550 }
551
552 static int m_low_entropy_ref(struct aec_stream *strm)
553 {
554     struct internal_state *state = strm->state;
555
556     if (state->ref && copysample(strm) == 0)
557         return M_EXIT;
558
559     if(state->id == 1) {
560         state->mode = m_se;
561         return M_CONTINUE;
562     }
563
564     state->mode = m_zero_block;
565     return M_CONTINUE;
566 }
567
568 static int m_low_entropy(struct aec_stream *strm)
569 {
570     struct internal_state *state = strm->state;
571
572     if (bits_ask(strm, 1) == 0)
573         return M_EXIT;
574     state->id = bits_get(strm, 1);
575     bits_drop(strm, 1);
576     state->mode = m_low_entropy_ref;
577     return M_CONTINUE;
578 }
579
580 static int m_uncomp_copy(struct aec_stream *strm)
581 {
582     struct internal_state *state = strm->state;
583
584     do {
585         if (copysample(strm) == 0)
586             return M_EXIT;
587     } while(--state->i);
588
589     state->mode = m_id;
590     return M_CONTINUE;
591 }
592
593 static int m_uncomp(struct aec_stream *strm)
594 {
595     int i;
596     struct internal_state *state = strm->state;
597
598     if (BUFFERSPACE(strm)) {
599         for (i = 0; i < strm->block_size; i++)
600             *state->rsip++ = direct_get(strm, strm->bits_per_sample);
601         strm->avail_out -= state->out_blklen;
602         check_rsi_end(strm);
603
604         state->mode = m_id;
605         return M_CONTINUE;
606     }
607
608     state->i = strm->block_size;
609     state->mode = m_uncomp_copy;
610     return M_CONTINUE;
611 }
612
613 static void create_se_table(int *table)
614 {
615     int i, j, k, ms;
616
617     k = 0;
618     for (i = 0; i < 13; i++) {
619         ms = k;
620         for (j = 0; j <= i; j++) {
621             table[2 * k] = i;
622             table[2 * k + 1] = ms;
623             k++;
624         }
625     }
626 }
627
628 int aec_decode_init(struct aec_stream *strm)
629 {
630     int i, modi;
631     struct internal_state *state;
632
633     if (strm->bits_per_sample > 32 || strm->bits_per_sample == 0)
634         return AEC_CONF_ERROR;
635
636     state = malloc(sizeof(struct internal_state));
637     if (state == NULL)
638         return AEC_MEM_ERROR;
639
640     create_se_table(state->se_table);
641
642     strm->state = state;
643
644     if (strm->bits_per_sample > 16) {
645         state->id_len = 5;
646
647         if (strm->bits_per_sample <= 24 && strm->flags & AEC_DATA_3BYTE) {
648             state->bytes_per_sample = 3;
649             if (strm->flags & AEC_DATA_MSB)
650                 state->flush_output = flush_msb_24;
651             else
652                 state->flush_output = flush_lsb_24;
653         } else {
654             state->bytes_per_sample = 4;
655             if (strm->flags & AEC_DATA_MSB)
656                 state->flush_output = flush_msb_32;
657             else
658                 state->flush_output = flush_lsb_32;
659         }
660         state->out_blklen = strm->block_size
661             * state->bytes_per_sample;
662     }
663     else if (strm->bits_per_sample > 8) {
664         state->bytes_per_sample = 2;
665         state->id_len = 4;
666         state->out_blklen = strm->block_size * 2;
667         if (strm->flags & AEC_DATA_MSB)
668             state->flush_output = flush_msb_16;
669         else
670             state->flush_output = flush_lsb_16;
671     } else {
672         if (strm->flags & AEC_DATA_RESTRICT) {
673             if (strm->bits_per_sample <= 4) {
674                 if (strm->bits_per_sample <= 2)
675                     state->id_len = 1;
676                 else
677                     state->id_len = 2;
678             } else {
679                 return AEC_CONF_ERROR;
680             }
681         } else {
682             state->id_len = 3;
683         }
684
685         state->bytes_per_sample = 1;
686         state->out_blklen = strm->block_size;
687         state->flush_output = flush_8;
688     }
689
690     if (strm->flags & AEC_DATA_SIGNED) {
691         state->xmin = -(1ULL << (strm->bits_per_sample - 1));
692         state->xmax = (1ULL << (strm->bits_per_sample - 1)) - 1;
693     } else {
694         state->xmin = 0;
695         state->xmax = (1ULL << strm->bits_per_sample) - 1;
696     }
697
698     state->in_blklen = (strm->block_size * strm->bits_per_sample
699                         + state->id_len) / 8 + 9;
700
701     modi = 1UL << state->id_len;
702     state->id_table = malloc(modi * sizeof(int (*)(struct aec_stream *)));
703     if (state->id_table == NULL)
704         return AEC_MEM_ERROR;
705
706     state->id_table[0] = m_low_entropy;
707     for (i = 1; i < modi - 1; i++) {
708         state->id_table[i] = m_split;
709     }
710     state->id_table[modi - 1] = m_uncomp;
711
712     state->rsi_size = strm->rsi * strm->block_size;
713     state->rsi_buffer = malloc(state->rsi_size * sizeof(uint32_t));
714     if (state->rsi_buffer == NULL)
715         return AEC_MEM_ERROR;
716
717     strm->total_in = 0;
718     strm->total_out = 0;
719
720     state->rsip = state->rsi_buffer;
721     state->flush_start = state->rsi_buffer;
722     state->bitp = 0;
723     state->fs = 0;
724     state->pp = strm->flags & AEC_DATA_PREPROCESS;
725     state->mode = m_id;
726     return AEC_OK;
727 }
728
729 int aec_decode(struct aec_stream *strm, int flush)
730 {
731     /**
732        Finite-state machine implementation of the adaptive entropy
733        decoder.
734
735        Can work with one byte input und one sample output buffers. If
736        enough buffer space is available, then faster implementations
737        of the states are called. Inspired by zlib.
738     */
739
740     struct internal_state *state = strm->state;
741
742     strm->total_in += strm->avail_in;
743     strm->total_out += strm->avail_out;
744
745     while (state->mode(strm) == M_CONTINUE);
746     state->flush_output(strm);
747
748     strm->total_in -= strm->avail_in;
749     strm->total_out -= strm->avail_out;
750
751     return AEC_OK;
752 }
753
754 int aec_decode_end(struct aec_stream *strm)
755 {
756     struct internal_state *state = strm->state;
757
758     free(state->id_table);
759     free(state->rsi_buffer);
760     free(state);
761     return AEC_OK;
762 }
763
764 int aec_buffer_decode(struct aec_stream *strm)
765 {
766     int status;
767
768     status = aec_decode_init(strm);
769     if (status != AEC_OK)
770         return status;
771
772     status = aec_decode(strm, AEC_FLUSH);
773     aec_decode_end(strm);
774     return status;
775 }