annotate loco.c @ 2530:eace30b70601 libavcodec

go LOCO, courtesy of Kostya Shishkov
author melanson
date Tue, 01 Mar 2005 02:24:58 +0000
parents
children 2b01396ab483
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2530
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
1 /*
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
2 * LOCO codec
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
3 * Copyright (c) 2005 Konstantin Shishkov
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
4 *
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
5 * This library is free software; you can redistribute it and/or
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
6 * modify it under the terms of the GNU Lesser General Public
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
7 * License as published by the Free Software Foundation; either
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
8 * version 2 of the License, or (at your option) any later version.
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
9 *
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
10 * This library is distributed in the hope that it will be useful,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
13 * Lesser General Public License for more details.
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
14 *
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
15 * You should have received a copy of the GNU Lesser General Public
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
16 * License along with this library; if not, write to the Free Software
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
18 *
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
19 */
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
20
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
21 /**
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
22 * @file loco.c
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
23 * LOCO codec.
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
24 */
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
25
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
26 #include "avcodec.h"
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
27 #include "common.h"
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
28 #include "bitstream.h"
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
29 #include "golomb.h"
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
30
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
31 enum LOCO_MODE {LOCO_UNKN=0, LOCO_CYUY2=-1, LOCO_CRGB=-2, LOCO_CYV12=-3,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
32 LOCO_YUY2=1, LOCO_UYVY=2, LOCO_RGB=3, LOCO_RGBA=4, LOCO_YV12=5};
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
33
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
34 typedef struct LOCOContext{
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
35 AVCodecContext *avctx;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
36 AVFrame pic;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
37 int lossy;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
38 int mode;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
39 } LOCOContext;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
40
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
41 typedef struct RICEContext{
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
42 GetBitContext gb;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
43 int save, run, run2; /* internal rice decoder state */
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
44 int sum, count; /* sum and count for getting rice parameter */
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
45 }RICEContext;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
46
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
47 /* could use get_sr_golomb() but is behaves differently on numbers like Rice(2, -64) */
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
48 static inline int get_rice(GetBitContext *gb, int K)
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
49 {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
50 int i;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
51 int V = 0;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
52 for(i = 0; !get_bits1(gb); i++);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
53 V = i;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
54 for(i = 0; i < K; i++) V = (V << 1) | get_bits1(gb);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
55 if(V & 1) return (V + 1) >> 1;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
56 return -(V >> 1);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
57 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
58
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
59 static inline int get_u_rice(GetBitContext *gb, int K)
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
60 {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
61 int i;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
62 int V = 0;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
63 for(i = 0; !get_bits1(gb); i++);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
64 V = i;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
65 for(i = 0; i < K; i++) V = (V << 1) | get_bits1(gb);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
66 return V;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
67 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
68
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
69 static int loco_get_rice_param(RICEContext *r)
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
70 {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
71 int cnt = 0;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
72 int val = r->count;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
73
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
74 while(r->sum > val && cnt < 9) {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
75 val <<= 1;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
76 cnt++;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
77 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
78
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
79 return cnt;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
80 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
81
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
82 static inline void loco_update_rice_param(RICEContext *r, int val)
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
83 {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
84 if (val < 0)
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
85 val = -val;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
86 r->sum += val;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
87 r->count++;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
88
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
89 if(r->count == 16) {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
90 r->sum >>= 1;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
91 r->count >>= 1;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
92 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
93 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
94
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
95 static inline int loco_get_rice(RICEContext *r)
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
96 {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
97 int v;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
98
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
99 if (r->run > 0) { /* we have zero run */
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
100 r->run--;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
101 return 0;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
102 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
103 v = -get_rice(&r->gb, loco_get_rice_param(r));
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
104 if (!v) {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
105 if (r->save >= 0) {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
106 r->run = get_u_rice(&r->gb, 2);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
107 if(r->run > 1)
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
108 r->save += r->run + 1;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
109 else
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
110 r->save -= 3;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
111 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
112 else
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
113 r->run2++;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
114 } else if (r->run2 > 0) {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
115 if (r->run2 > 2)
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
116 r->save += r->run2;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
117 else
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
118 r->save -= 3;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
119 r->run2 = 0;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
120 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
121
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
122 return v;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
123 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
124
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
125 /* LOCO main predictor - LOCO-I/JPEG-LS predictor */
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
126 static inline int loco_predict(uint8_t* data, int stride, int step)
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
127 {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
128 int max_ab, min_ab;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
129 int a, b, c;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
130
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
131 a = data[-stride];
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
132 b = data[-step];
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
133 c = data[-stride - step];
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
134
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
135 max_ab = (a > b) ? a : b;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
136 min_ab = (a < b) ? a : b;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
137
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
138 if (c >= max_ab) return min_ab;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
139 if (c <= min_ab) return max_ab;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
140 return (a + b - c);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
141 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
142
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
143 static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
144 int stride, uint8_t *buf, int buf_size, int step)
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
145 {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
146 RICEContext rc;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
147 int val;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
148 int i, j;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
149
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
150 init_get_bits(&rc.gb, buf, buf_size*8);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
151 rc.save = 0;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
152 rc.run = 0;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
153 rc.run2 = 0;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
154
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
155 rc.sum = 8;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
156 rc.count = 1;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
157
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
158 /* restore top left pixel */
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
159 val = loco_get_rice(&rc);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
160 loco_update_rice_param(&rc, val);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
161 if (val < 0) val -= l->lossy;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
162 if (val > 0) val += l->lossy;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
163 data[0] = 128 + val;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
164 /* restore top line */
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
165 for (i = 1; i < width; i++) {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
166 val = loco_get_rice(&rc);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
167 loco_update_rice_param(&rc, val);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
168 if (val < 0) val -= l->lossy;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
169 if (val > 0) val += l->lossy;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
170 data[i * step] = data[i * step - step] + val;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
171 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
172 data += stride;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
173 for (j = 1; j < height; j++) {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
174 /* restore left column */
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
175 val = loco_get_rice(&rc);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
176 loco_update_rice_param(&rc, val);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
177 if (val < 0) val -= l->lossy;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
178 if (val > 0) val += l->lossy;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
179 data[0] = data[-stride] + val;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
180 /* restore all other pixels */
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
181 for (i = 1; i < width; i++) {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
182 val = loco_get_rice(&rc);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
183 loco_update_rice_param(&rc, val);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
184 if (val < 0) val -= l->lossy;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
185 if (val > 0) val += l->lossy;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
186 data[i * step] = loco_predict(&data[i * step], stride, step) + val;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
187 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
188 data += stride;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
189 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
190
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
191 return ((get_bits_count(&rc.gb) + 7) >> 3);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
192 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
193
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
194 static int decode_frame(AVCodecContext *avctx,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
195 void *data, int *data_size,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
196 uint8_t *buf, int buf_size)
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
197 {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
198 LOCOContext * const l = avctx->priv_data;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
199 AVFrame * const p= (AVFrame*)&l->pic;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
200 int decoded;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
201
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
202 if(p->data[0])
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
203 avctx->release_buffer(avctx, p);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
204
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
205 p->reference = 0;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
206 if(avctx->get_buffer(avctx, p) < 0){
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
207 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
208 return -1;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
209 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
210 p->key_frame = 1;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
211
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
212 switch(l->mode) {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
213 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY:
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
214 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
215 p->linesize[0], buf, buf_size, 1);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
216 buf += decoded; buf_size -= decoded;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
217 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
218 p->linesize[1], buf, buf_size, 1);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
219 buf += decoded; buf_size -= decoded;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
220 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
221 p->linesize[2], buf, buf_size, 1);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
222 break;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
223 case LOCO_CYV12: case LOCO_YV12:
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
224 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
225 p->linesize[0], buf, buf_size, 1);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
226 buf += decoded; buf_size -= decoded;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
227 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
228 p->linesize[1], buf, buf_size, 1);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
229 buf += decoded; buf_size -= decoded;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
230 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
231 p->linesize[2], buf, buf_size, 1);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
232 break;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
233 case LOCO_CRGB: case LOCO_RGB:
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
234 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
235 p->linesize[0], buf, buf_size, 3);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
236 buf += decoded; buf_size -= decoded;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
237 decoded = loco_decode_plane(l, p->data[0] + 1, avctx->width, avctx->height,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
238 p->linesize[0], buf, buf_size, 3);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
239 buf += decoded; buf_size -= decoded;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
240 decoded = loco_decode_plane(l, p->data[0] + 2, avctx->width, avctx->height,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
241 p->linesize[0], buf, buf_size, 3);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
242 break;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
243 case LOCO_RGBA:
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
244 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
245 p->linesize[0], buf, buf_size, 4);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
246 buf += decoded; buf_size -= decoded;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
247 decoded = loco_decode_plane(l, p->data[0] + 1, avctx->width, avctx->height,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
248 p->linesize[0], buf, buf_size, 4);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
249 buf += decoded; buf_size -= decoded;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
250 decoded = loco_decode_plane(l, p->data[0] + 2, avctx->width, avctx->height,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
251 p->linesize[0], buf, buf_size, 4);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
252 buf += decoded; buf_size -= decoded;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
253 decoded = loco_decode_plane(l, p->data[0] + 3, avctx->width, avctx->height,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
254 p->linesize[0], buf, buf_size, 4);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
255 break;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
256 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
257
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
258 *data_size = sizeof(AVFrame);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
259 *(AVFrame*)data = l->pic;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
260
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
261 return buf_size;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
262 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
263
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
264 static int decode_init(AVCodecContext *avctx){
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
265 LOCOContext * const l = avctx->priv_data;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
266 int version;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
267
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
268 l->avctx = avctx;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
269 if (avctx->extradata_size < 12) {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
270 av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n",
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
271 avctx->extradata_size);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
272 return -1;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
273 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
274 version = LE_32(avctx->extradata);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
275 switch(version) {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
276 case 1:
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
277 l->lossy = 0;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
278 break;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
279 case 2:
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
280 l->lossy = LE_32(avctx->extradata + 8);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
281 break;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
282 default:
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
283 l->lossy = LE_32(avctx->extradata + 8);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
284 av_log(avctx, AV_LOG_INFO, "This is LOCO codec version %i, please upload file for study\n", version);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
285 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
286
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
287 l->mode = LE_32(avctx->extradata + 4);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
288 switch(l->mode) {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
289 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY:
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
290 avctx->pix_fmt = PIX_FMT_YUV422P;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
291 break;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
292 case LOCO_CRGB: case LOCO_RGB:
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
293 avctx->pix_fmt = PIX_FMT_BGR24;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
294 break;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
295 case LOCO_CYV12: case LOCO_YV12:
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
296 avctx->pix_fmt = PIX_FMT_YUV420P;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
297 break;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
298 case LOCO_RGBA:
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
299 avctx->pix_fmt = PIX_FMT_RGBA32;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
300 break;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
301 default:
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
302 av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode);
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
303 return -1;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
304 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
305
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
306 return 0;
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
307 }
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
308
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
309 AVCodec loco_decoder = {
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
310 "loco",
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
311 CODEC_TYPE_VIDEO,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
312 CODEC_ID_LOCO,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
313 sizeof(LOCOContext),
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
314 decode_init,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
315 NULL,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
316 NULL,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
317 decode_frame,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
318 CODEC_CAP_DR1,
eace30b70601 go LOCO, courtesy of Kostya Shishkov
melanson
parents:
diff changeset
319 };