/src/ffmpeg/libavcodec/mqcenc.c
Line | Count | Source |
1 | | /* |
2 | | * MQ-coder encoder |
3 | | * Copyright (c) 2007 Kamil Nowosad |
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 | | * MQ-coder encoder |
24 | | * @file |
25 | | * @author Kamil Nowosad |
26 | | */ |
27 | | |
28 | | #include <string.h> |
29 | | |
30 | | #include "libavutil/avassert.h" |
31 | | #include "mqc.h" |
32 | | |
33 | | static void byteout(MqcState *mqc) |
34 | 88.0M | { |
35 | 89.7M | retry: |
36 | 89.7M | if (*mqc->bp == 0xff){ |
37 | 1.40M | mqc->bp++; |
38 | 1.40M | *mqc->bp = mqc->c >> 20; |
39 | 1.40M | mqc->c &= 0xfffff; |
40 | 1.40M | mqc->ct = 7; |
41 | 88.3M | } else if ((mqc->c & 0x8000000)){ |
42 | 1.66M | (*mqc->bp)++; |
43 | 1.66M | mqc->c &= 0x7ffffff; |
44 | 1.66M | goto retry; |
45 | 86.6M | } else{ |
46 | 86.6M | mqc->bp++; |
47 | 86.6M | *mqc->bp = mqc->c >> 19; |
48 | 86.6M | mqc->c &= 0x7ffff; |
49 | 86.6M | mqc->ct = 8; |
50 | 86.6M | } |
51 | 89.7M | } |
52 | | |
53 | | static void renorme(MqcState *mqc) |
54 | 169M | { |
55 | 215M | do{ |
56 | 215M | mqc->a += mqc->a; |
57 | 215M | mqc->c += mqc->c; |
58 | 215M | if (!--mqc->ct) |
59 | 25.6M | byteout(mqc); |
60 | 215M | } while (!(mqc->a & 0x8000)); |
61 | 169M | } |
62 | | |
63 | | static void setbits(MqcState *mqc) |
64 | 31.2M | { |
65 | 31.2M | int tmp = mqc->c + mqc->a; |
66 | 31.2M | mqc->c |= 0xffff; |
67 | 31.2M | if (mqc->c >= tmp) |
68 | 8.97M | mqc->c -= 0x8000; |
69 | 31.2M | } |
70 | | |
71 | | void ff_mqc_initenc(MqcState *mqc, uint8_t *bp) |
72 | 2.91M | { |
73 | 2.91M | ff_mqc_init_contexts(mqc); |
74 | 2.91M | mqc->a = 0x8000; |
75 | 2.91M | mqc->c = 0; |
76 | 2.91M | mqc->bp = bp-1; |
77 | 2.91M | mqc->bpstart = bp; |
78 | 2.91M | mqc->ct = 12 + (*mqc->bp == 0xff); |
79 | 2.91M | } |
80 | | |
81 | | void ff_mqc_encode(MqcState *mqc, uint8_t *cxstate, int d) |
82 | 264M | { |
83 | 264M | int qe; |
84 | | |
85 | 264M | qe = ff_mqc_qe[*cxstate]; |
86 | 264M | mqc->a -= qe; |
87 | 264M | if ((*cxstate & 1) == d){ |
88 | 176M | if (!(mqc->a & 0x8000)){ |
89 | 81.3M | if (mqc->a < qe) |
90 | 25.6M | mqc->a = qe; |
91 | 55.7M | else |
92 | 55.7M | mqc->c += qe; |
93 | 81.3M | *cxstate = ff_mqc_nmps[*cxstate]; |
94 | 81.3M | renorme(mqc); |
95 | 81.3M | } else |
96 | 94.9M | mqc->c += qe; |
97 | 176M | } else{ |
98 | 87.9M | if (mqc->a < qe) |
99 | 23.9M | mqc->c += qe; |
100 | 63.9M | else |
101 | 63.9M | mqc->a = qe; |
102 | 87.9M | *cxstate = ff_mqc_nlps[*cxstate]; |
103 | 87.9M | renorme(mqc); |
104 | 87.9M | } |
105 | 264M | } |
106 | | |
107 | | static int mqc_flush(MqcState *mqc) |
108 | 31.2M | { |
109 | 31.2M | setbits(mqc); |
110 | 31.2M | mqc->c = mqc->c << mqc->ct; |
111 | 31.2M | byteout(mqc); |
112 | 31.2M | mqc->c = mqc->c << mqc->ct; |
113 | 31.2M | byteout(mqc); |
114 | 31.2M | if (*mqc->bp != 0xff) |
115 | 7.89M | mqc->bp++; |
116 | 31.2M | return mqc->bp - mqc->bpstart; |
117 | 31.2M | } |
118 | | |
119 | | int ff_mqc_flush_to(MqcState *mqc, uint8_t *dst, int *dst_len) |
120 | 31.2M | { |
121 | 31.2M | MqcState mqc2 = *mqc; |
122 | 31.2M | mqc2.bpstart= |
123 | 31.2M | mqc2.bp = dst; |
124 | 31.2M | *mqc2.bp = *mqc->bp; |
125 | 31.2M | mqc_flush(&mqc2); |
126 | 31.2M | *dst_len = mqc2.bp - dst; |
127 | 31.2M | if (mqc->bp < mqc->bpstart) { |
128 | 1.39M | av_assert1(mqc->bpstart - mqc->bp == 1); |
129 | 1.39M | av_assert1(*dst_len > 0); |
130 | 1.39M | av_assert1(mqc->bp[0] == 0 && dst[0] == 0); |
131 | 1.39M | (*dst_len) --; |
132 | 1.39M | memmove(dst, dst+1, *dst_len); |
133 | 1.39M | return mqc->bp - mqc->bpstart + 1 + *dst_len; |
134 | 1.39M | } |
135 | 29.8M | return mqc->bp - mqc->bpstart + *dst_len; |
136 | 31.2M | } |