Mercurial > libavcodec.hg
annotate loco.c @ 7983:47f50599b368 libavcodec
x264 has removed the b-rdo and bime options, and instead integrated
them into the subme number to attempt to reduce the number of
unnecessary options. subme now scales up to 9.
Patch by Jason Garett-Glaser %darkshikari A gmail P com%
author | gpoirier |
---|---|
date | Thu, 02 Oct 2008 19:05:35 +0000 |
parents | e943e1409077 |
children | d6bab465b82c |
rev | line source |
---|---|
2530 | 1 /* |
2 * LOCO codec | |
3 * Copyright (c) 2005 Konstantin Shishkov | |
4 * | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
5 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
6 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
2530 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
2530 | 11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
2530 | 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 | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2967
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
2530 | 20 */ |
2967 | 21 |
2530 | 22 /** |
23 * @file loco.c | |
24 * LOCO codec. | |
25 */ | |
2967 | 26 |
2530 | 27 #include "avcodec.h" |
28 #include "bitstream.h" | |
29 #include "golomb.h" | |
30 | |
2587 | 31 enum LOCO_MODE {LOCO_UNKN=0, LOCO_CYUY2=-1, LOCO_CRGB=-2, LOCO_CRGBA=-3, LOCO_CYV12=-4, |
2530 | 32 LOCO_YUY2=1, LOCO_UYVY=2, LOCO_RGB=3, LOCO_RGBA=4, LOCO_YV12=5}; |
33 | |
34 typedef struct LOCOContext{ | |
35 AVCodecContext *avctx; | |
36 AVFrame pic; | |
37 int lossy; | |
38 int mode; | |
39 } LOCOContext; | |
40 | |
41 typedef struct RICEContext{ | |
42 GetBitContext gb; | |
43 int save, run, run2; /* internal rice decoder state */ | |
44 int sum, count; /* sum and count for getting rice parameter */ | |
2558 | 45 int lossy; |
2530 | 46 }RICEContext; |
47 | |
48 static int loco_get_rice_param(RICEContext *r) | |
49 { | |
50 int cnt = 0; | |
51 int val = r->count; | |
2967 | 52 |
2530 | 53 while(r->sum > val && cnt < 9) { |
54 val <<= 1; | |
55 cnt++; | |
56 } | |
2967 | 57 |
2530 | 58 return cnt; |
59 } | |
60 | |
61 static inline void loco_update_rice_param(RICEContext *r, int val) | |
62 { | |
63 r->sum += val; | |
64 r->count++; | |
2967 | 65 |
2530 | 66 if(r->count == 16) { |
67 r->sum >>= 1; | |
68 r->count >>= 1; | |
69 } | |
70 } | |
71 | |
72 static inline int loco_get_rice(RICEContext *r) | |
73 { | |
74 int v; | |
75 if (r->run > 0) { /* we have zero run */ | |
76 r->run--; | |
2558 | 77 loco_update_rice_param(r, 0); |
2530 | 78 return 0; |
79 } | |
2558 | 80 v = get_ur_golomb_jpegls(&r->gb, loco_get_rice_param(r), INT_MAX, 0); |
81 loco_update_rice_param(r, (v+1)>>1); | |
2530 | 82 if (!v) { |
83 if (r->save >= 0) { | |
2558 | 84 r->run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0); |
2530 | 85 if(r->run > 1) |
86 r->save += r->run + 1; | |
87 else | |
88 r->save -= 3; | |
89 } | |
90 else | |
91 r->run2++; | |
2558 | 92 } else { |
93 v = ((v>>1) + r->lossy) ^ -(v&1); | |
94 if (r->run2 > 0) { | |
95 if (r->run2 > 2) | |
96 r->save += r->run2; | |
97 else | |
98 r->save -= 3; | |
99 r->run2 = 0; | |
100 } | |
2530 | 101 } |
2967 | 102 |
2530 | 103 return v; |
104 } | |
105 | |
106 /* LOCO main predictor - LOCO-I/JPEG-LS predictor */ | |
107 static inline int loco_predict(uint8_t* data, int stride, int step) | |
108 { | |
109 int a, b, c; | |
2967 | 110 |
2530 | 111 a = data[-stride]; |
112 b = data[-step]; | |
113 c = data[-stride - step]; | |
2967 | 114 |
2558 | 115 return mid_pred(a, a + b - c, b); |
2530 | 116 } |
117 | |
118 static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height, | |
6218 | 119 int stride, const uint8_t *buf, int buf_size, int step) |
2530 | 120 { |
121 RICEContext rc; | |
122 int val; | |
123 int i, j; | |
2967 | 124 |
2530 | 125 init_get_bits(&rc.gb, buf, buf_size*8); |
126 rc.save = 0; | |
127 rc.run = 0; | |
128 rc.run2 = 0; | |
2967 | 129 rc.lossy = l->lossy; |
130 | |
2530 | 131 rc.sum = 8; |
132 rc.count = 1; | |
2967 | 133 |
2530 | 134 /* restore top left pixel */ |
135 val = loco_get_rice(&rc); | |
136 data[0] = 128 + val; | |
137 /* restore top line */ | |
138 for (i = 1; i < width; i++) { | |
139 val = loco_get_rice(&rc); | |
140 data[i * step] = data[i * step - step] + val; | |
141 } | |
142 data += stride; | |
143 for (j = 1; j < height; j++) { | |
144 /* restore left column */ | |
145 val = loco_get_rice(&rc); | |
146 data[0] = data[-stride] + val; | |
147 /* restore all other pixels */ | |
148 for (i = 1; i < width; i++) { | |
149 val = loco_get_rice(&rc); | |
150 data[i * step] = loco_predict(&data[i * step], stride, step) + val; | |
151 } | |
152 data += stride; | |
153 } | |
2967 | 154 |
6750 | 155 return (get_bits_count(&rc.gb) + 7) >> 3; |
2530 | 156 } |
157 | |
2967 | 158 static int decode_frame(AVCodecContext *avctx, |
2530 | 159 void *data, int *data_size, |
6218 | 160 const uint8_t *buf, int buf_size) |
2530 | 161 { |
162 LOCOContext * const l = avctx->priv_data; | |
163 AVFrame * const p= (AVFrame*)&l->pic; | |
164 int decoded; | |
165 | |
166 if(p->data[0]) | |
167 avctx->release_buffer(avctx, p); | |
168 | |
169 p->reference = 0; | |
170 if(avctx->get_buffer(avctx, p) < 0){ | |
171 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
172 return -1; | |
173 } | |
174 p->key_frame = 1; | |
175 | |
176 switch(l->mode) { | |
177 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY: | |
178 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, | |
179 p->linesize[0], buf, buf_size, 1); | |
180 buf += decoded; buf_size -= decoded; | |
181 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height, | |
182 p->linesize[1], buf, buf_size, 1); | |
183 buf += decoded; buf_size -= decoded; | |
184 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height, | |
185 p->linesize[2], buf, buf_size, 1); | |
186 break; | |
187 case LOCO_CYV12: case LOCO_YV12: | |
188 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, | |
189 p->linesize[0], buf, buf_size, 1); | |
190 buf += decoded; buf_size -= decoded; | |
2598
6eaebf1fbd74
Fix colors for YV12 case (u/v planes are swapped)
rtognimp
parents:
2587
diff
changeset
|
191 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2, |
6eaebf1fbd74
Fix colors for YV12 case (u/v planes are swapped)
rtognimp
parents:
2587
diff
changeset
|
192 p->linesize[2], buf, buf_size, 1); |
6eaebf1fbd74
Fix colors for YV12 case (u/v planes are swapped)
rtognimp
parents:
2587
diff
changeset
|
193 buf += decoded; buf_size -= decoded; |
2530 | 194 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2, |
195 p->linesize[1], buf, buf_size, 1); | |
196 break; | |
197 case LOCO_CRGB: case LOCO_RGB: | |
2599
3e36a706f5b7
Fix upside-down picture for BGR24 images (fixes pig-loco-rgb.avi)
rtognimp
parents:
2598
diff
changeset
|
198 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, |
3e36a706f5b7
Fix upside-down picture for BGR24 images (fixes pig-loco-rgb.avi)
rtognimp
parents:
2598
diff
changeset
|
199 -p->linesize[0], buf, buf_size, 3); |
2530 | 200 buf += decoded; buf_size -= decoded; |
2599
3e36a706f5b7
Fix upside-down picture for BGR24 images (fixes pig-loco-rgb.avi)
rtognimp
parents:
2598
diff
changeset
|
201 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height, |
3e36a706f5b7
Fix upside-down picture for BGR24 images (fixes pig-loco-rgb.avi)
rtognimp
parents:
2598
diff
changeset
|
202 -p->linesize[0], buf, buf_size, 3); |
2530 | 203 buf += decoded; buf_size -= decoded; |
2599
3e36a706f5b7
Fix upside-down picture for BGR24 images (fixes pig-loco-rgb.avi)
rtognimp
parents:
2598
diff
changeset
|
204 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height, |
3e36a706f5b7
Fix upside-down picture for BGR24 images (fixes pig-loco-rgb.avi)
rtognimp
parents:
2598
diff
changeset
|
205 -p->linesize[0], buf, buf_size, 3); |
2530 | 206 break; |
207 case LOCO_RGBA: | |
208 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, | |
209 p->linesize[0], buf, buf_size, 4); | |
210 buf += decoded; buf_size -= decoded; | |
211 decoded = loco_decode_plane(l, p->data[0] + 1, avctx->width, avctx->height, | |
212 p->linesize[0], buf, buf_size, 4); | |
213 buf += decoded; buf_size -= decoded; | |
214 decoded = loco_decode_plane(l, p->data[0] + 2, avctx->width, avctx->height, | |
215 p->linesize[0], buf, buf_size, 4); | |
216 buf += decoded; buf_size -= decoded; | |
217 decoded = loco_decode_plane(l, p->data[0] + 3, avctx->width, avctx->height, | |
218 p->linesize[0], buf, buf_size, 4); | |
219 break; | |
220 } | |
221 | |
222 *data_size = sizeof(AVFrame); | |
223 *(AVFrame*)data = l->pic; | |
2967 | 224 |
2530 | 225 return buf_size; |
226 } | |
227 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6218
diff
changeset
|
228 static av_cold int decode_init(AVCodecContext *avctx){ |
2530 | 229 LOCOContext * const l = avctx->priv_data; |
230 int version; | |
231 | |
232 l->avctx = avctx; | |
233 if (avctx->extradata_size < 12) { | |
234 av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n", | |
235 avctx->extradata_size); | |
236 return -1; | |
237 } | |
4364 | 238 version = AV_RL32(avctx->extradata); |
2530 | 239 switch(version) { |
240 case 1: | |
241 l->lossy = 0; | |
242 break; | |
243 case 2: | |
4364 | 244 l->lossy = AV_RL32(avctx->extradata + 8); |
2530 | 245 break; |
246 default: | |
4364 | 247 l->lossy = AV_RL32(avctx->extradata + 8); |
2530 | 248 av_log(avctx, AV_LOG_INFO, "This is LOCO codec version %i, please upload file for study\n", version); |
249 } | |
2967 | 250 |
4364 | 251 l->mode = AV_RL32(avctx->extradata + 4); |
2530 | 252 switch(l->mode) { |
253 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY: | |
254 avctx->pix_fmt = PIX_FMT_YUV422P; | |
255 break; | |
256 case LOCO_CRGB: case LOCO_RGB: | |
257 avctx->pix_fmt = PIX_FMT_BGR24; | |
258 break; | |
259 case LOCO_CYV12: case LOCO_YV12: | |
260 avctx->pix_fmt = PIX_FMT_YUV420P; | |
261 break; | |
2587 | 262 case LOCO_CRGBA: case LOCO_RGBA: |
4494
ce643a22f049
Replace deprecated PIX_FMT names by the newer variants.
diego
parents:
4364
diff
changeset
|
263 avctx->pix_fmt = PIX_FMT_RGB32; |
2530 | 264 break; |
265 default: | |
266 av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode); | |
267 return -1; | |
268 } | |
2558 | 269 if(avctx->debug & FF_DEBUG_PICT_INFO) |
270 av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode); | |
2530 | 271 |
272 return 0; | |
273 } | |
274 | |
275 AVCodec loco_decoder = { | |
276 "loco", | |
277 CODEC_TYPE_VIDEO, | |
278 CODEC_ID_LOCO, | |
279 sizeof(LOCOContext), | |
280 decode_init, | |
281 NULL, | |
282 NULL, | |
283 decode_frame, | |
284 CODEC_CAP_DR1, | |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6750
diff
changeset
|
285 .long_name = NULL_IF_CONFIG_SMALL("LOCO"), |
2530 | 286 }; |