Mercurial > libavcodec.hg
annotate loco.c @ 4166:eced83504436 libavcodec
mp3 header (de)compression bitstream filter
this will make mp3 frames 4 bytes smaller, it will not give you binary identical mp3 files, but it will give you mp3 files which decode to binary identical output
this will only work in containers providing at least packet size, sample_rate and number of channels
bugreports about mp3 files for which this fails are welcome
and this is experimental (dont expect compatibility and dont even expect to be able to decompress what you compressed, hell dont even expect this to work without editing the source a little)
author | michael |
---|---|
date | Fri, 10 Nov 2006 01:41:53 +0000 |
parents | c8c591fe26f8 |
children | 05e932ddaaa9 |
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 * |
21 */ | |
2967 | 22 |
2530 | 23 /** |
24 * @file loco.c | |
25 * LOCO codec. | |
26 */ | |
2967 | 27 |
2530 | 28 #include "avcodec.h" |
29 #include "common.h" | |
30 #include "bitstream.h" | |
31 #include "golomb.h" | |
32 | |
2587 | 33 enum LOCO_MODE {LOCO_UNKN=0, LOCO_CYUY2=-1, LOCO_CRGB=-2, LOCO_CRGBA=-3, LOCO_CYV12=-4, |
2530 | 34 LOCO_YUY2=1, LOCO_UYVY=2, LOCO_RGB=3, LOCO_RGBA=4, LOCO_YV12=5}; |
35 | |
36 typedef struct LOCOContext{ | |
37 AVCodecContext *avctx; | |
38 AVFrame pic; | |
39 int lossy; | |
40 int mode; | |
41 } LOCOContext; | |
42 | |
43 typedef struct RICEContext{ | |
44 GetBitContext gb; | |
45 int save, run, run2; /* internal rice decoder state */ | |
46 int sum, count; /* sum and count for getting rice parameter */ | |
2558 | 47 int lossy; |
2530 | 48 }RICEContext; |
49 | |
50 static int loco_get_rice_param(RICEContext *r) | |
51 { | |
52 int cnt = 0; | |
53 int val = r->count; | |
2967 | 54 |
2530 | 55 while(r->sum > val && cnt < 9) { |
56 val <<= 1; | |
57 cnt++; | |
58 } | |
2967 | 59 |
2530 | 60 return cnt; |
61 } | |
62 | |
63 static inline void loco_update_rice_param(RICEContext *r, int val) | |
64 { | |
65 r->sum += val; | |
66 r->count++; | |
2967 | 67 |
2530 | 68 if(r->count == 16) { |
69 r->sum >>= 1; | |
70 r->count >>= 1; | |
71 } | |
72 } | |
73 | |
74 static inline int loco_get_rice(RICEContext *r) | |
75 { | |
76 int v; | |
77 if (r->run > 0) { /* we have zero run */ | |
78 r->run--; | |
2558 | 79 loco_update_rice_param(r, 0); |
2530 | 80 return 0; |
81 } | |
2558 | 82 v = get_ur_golomb_jpegls(&r->gb, loco_get_rice_param(r), INT_MAX, 0); |
83 loco_update_rice_param(r, (v+1)>>1); | |
2530 | 84 if (!v) { |
85 if (r->save >= 0) { | |
2558 | 86 r->run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0); |
2530 | 87 if(r->run > 1) |
88 r->save += r->run + 1; | |
89 else | |
90 r->save -= 3; | |
91 } | |
92 else | |
93 r->run2++; | |
2558 | 94 } else { |
95 v = ((v>>1) + r->lossy) ^ -(v&1); | |
96 if (r->run2 > 0) { | |
97 if (r->run2 > 2) | |
98 r->save += r->run2; | |
99 else | |
100 r->save -= 3; | |
101 r->run2 = 0; | |
102 } | |
2530 | 103 } |
2967 | 104 |
2530 | 105 return v; |
106 } | |
107 | |
108 /* LOCO main predictor - LOCO-I/JPEG-LS predictor */ | |
109 static inline int loco_predict(uint8_t* data, int stride, int step) | |
110 { | |
111 int a, b, c; | |
2967 | 112 |
2530 | 113 a = data[-stride]; |
114 b = data[-step]; | |
115 c = data[-stride - step]; | |
2967 | 116 |
2558 | 117 return mid_pred(a, a + b - c, b); |
2530 | 118 } |
119 | |
120 static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height, | |
121 int stride, uint8_t *buf, int buf_size, int step) | |
122 { | |
123 RICEContext rc; | |
124 int val; | |
125 int i, j; | |
2967 | 126 |
2530 | 127 init_get_bits(&rc.gb, buf, buf_size*8); |
128 rc.save = 0; | |
129 rc.run = 0; | |
130 rc.run2 = 0; | |
2967 | 131 rc.lossy = l->lossy; |
132 | |
2530 | 133 rc.sum = 8; |
134 rc.count = 1; | |
2967 | 135 |
2530 | 136 /* restore top left pixel */ |
137 val = loco_get_rice(&rc); | |
138 data[0] = 128 + val; | |
139 /* restore top line */ | |
140 for (i = 1; i < width; i++) { | |
141 val = loco_get_rice(&rc); | |
142 data[i * step] = data[i * step - step] + val; | |
143 } | |
144 data += stride; | |
145 for (j = 1; j < height; j++) { | |
146 /* restore left column */ | |
147 val = loco_get_rice(&rc); | |
148 data[0] = data[-stride] + val; | |
149 /* restore all other pixels */ | |
150 for (i = 1; i < width; i++) { | |
151 val = loco_get_rice(&rc); | |
152 data[i * step] = loco_predict(&data[i * step], stride, step) + val; | |
153 } | |
154 data += stride; | |
155 } | |
2967 | 156 |
2530 | 157 return ((get_bits_count(&rc.gb) + 7) >> 3); |
158 } | |
159 | |
2967 | 160 static int decode_frame(AVCodecContext *avctx, |
2530 | 161 void *data, int *data_size, |
162 uint8_t *buf, int buf_size) | |
163 { | |
164 LOCOContext * const l = avctx->priv_data; | |
165 AVFrame * const p= (AVFrame*)&l->pic; | |
166 int decoded; | |
167 | |
168 if(p->data[0]) | |
169 avctx->release_buffer(avctx, p); | |
170 | |
171 p->reference = 0; | |
172 if(avctx->get_buffer(avctx, p) < 0){ | |
173 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
174 return -1; | |
175 } | |
176 p->key_frame = 1; | |
177 | |
178 switch(l->mode) { | |
179 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY: | |
180 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, | |
181 p->linesize[0], buf, buf_size, 1); | |
182 buf += decoded; buf_size -= decoded; | |
183 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height, | |
184 p->linesize[1], buf, buf_size, 1); | |
185 buf += decoded; buf_size -= decoded; | |
186 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height, | |
187 p->linesize[2], buf, buf_size, 1); | |
188 break; | |
189 case LOCO_CYV12: case LOCO_YV12: | |
190 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, | |
191 p->linesize[0], buf, buf_size, 1); | |
192 buf += decoded; buf_size -= decoded; | |
2598
6eaebf1fbd74
Fix colors for YV12 case (u/v planes are swapped)
rtognimp
parents:
2587
diff
changeset
|
193 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
|
194 p->linesize[2], buf, buf_size, 1); |
6eaebf1fbd74
Fix colors for YV12 case (u/v planes are swapped)
rtognimp
parents:
2587
diff
changeset
|
195 buf += decoded; buf_size -= decoded; |
2530 | 196 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2, |
197 p->linesize[1], buf, buf_size, 1); | |
198 break; | |
199 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
|
200 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
|
201 -p->linesize[0], buf, buf_size, 3); |
2530 | 202 buf += decoded; buf_size -= decoded; |
2599
3e36a706f5b7
Fix upside-down picture for BGR24 images (fixes pig-loco-rgb.avi)
rtognimp
parents:
2598
diff
changeset
|
203 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
|
204 -p->linesize[0], buf, buf_size, 3); |
2530 | 205 buf += decoded; buf_size -= decoded; |
2599
3e36a706f5b7
Fix upside-down picture for BGR24 images (fixes pig-loco-rgb.avi)
rtognimp
parents:
2598
diff
changeset
|
206 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
|
207 -p->linesize[0], buf, buf_size, 3); |
2530 | 208 break; |
209 case LOCO_RGBA: | |
210 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, | |
211 p->linesize[0], buf, buf_size, 4); | |
212 buf += decoded; buf_size -= decoded; | |
213 decoded = loco_decode_plane(l, p->data[0] + 1, avctx->width, avctx->height, | |
214 p->linesize[0], buf, buf_size, 4); | |
215 buf += decoded; buf_size -= decoded; | |
216 decoded = loco_decode_plane(l, p->data[0] + 2, avctx->width, avctx->height, | |
217 p->linesize[0], buf, buf_size, 4); | |
218 buf += decoded; buf_size -= decoded; | |
219 decoded = loco_decode_plane(l, p->data[0] + 3, avctx->width, avctx->height, | |
220 p->linesize[0], buf, buf_size, 4); | |
221 break; | |
222 } | |
223 | |
224 *data_size = sizeof(AVFrame); | |
225 *(AVFrame*)data = l->pic; | |
2967 | 226 |
2530 | 227 return buf_size; |
228 } | |
229 | |
230 static int decode_init(AVCodecContext *avctx){ | |
231 LOCOContext * const l = avctx->priv_data; | |
232 int version; | |
233 | |
234 l->avctx = avctx; | |
235 if (avctx->extradata_size < 12) { | |
236 av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n", | |
237 avctx->extradata_size); | |
238 return -1; | |
239 } | |
240 version = LE_32(avctx->extradata); | |
241 switch(version) { | |
242 case 1: | |
243 l->lossy = 0; | |
244 break; | |
245 case 2: | |
246 l->lossy = LE_32(avctx->extradata + 8); | |
247 break; | |
248 default: | |
249 l->lossy = LE_32(avctx->extradata + 8); | |
250 av_log(avctx, AV_LOG_INFO, "This is LOCO codec version %i, please upload file for study\n", version); | |
251 } | |
2967 | 252 |
2530 | 253 l->mode = LE_32(avctx->extradata + 4); |
254 switch(l->mode) { | |
255 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY: | |
256 avctx->pix_fmt = PIX_FMT_YUV422P; | |
257 break; | |
258 case LOCO_CRGB: case LOCO_RGB: | |
259 avctx->pix_fmt = PIX_FMT_BGR24; | |
260 break; | |
261 case LOCO_CYV12: case LOCO_YV12: | |
262 avctx->pix_fmt = PIX_FMT_YUV420P; | |
263 break; | |
2587 | 264 case LOCO_CRGBA: case LOCO_RGBA: |
2530 | 265 avctx->pix_fmt = PIX_FMT_RGBA32; |
266 break; | |
267 default: | |
268 av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode); | |
269 return -1; | |
270 } | |
2558 | 271 if(avctx->debug & FF_DEBUG_PICT_INFO) |
272 av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode); | |
2530 | 273 |
274 return 0; | |
275 } | |
276 | |
277 AVCodec loco_decoder = { | |
278 "loco", | |
279 CODEC_TYPE_VIDEO, | |
280 CODEC_ID_LOCO, | |
281 sizeof(LOCOContext), | |
282 decode_init, | |
283 NULL, | |
284 NULL, | |
285 decode_frame, | |
286 CODEC_CAP_DR1, | |
287 }; |