blob: afaab05568af56d9fe8558648094d9f3c7b29f67
1 | /* |
2 | * lossless JPEG encoder |
3 | * Copyright (c) 2000, 2001 Fabrice Bellard |
4 | * Copyright (c) 2003 Alex Beregszaszi |
5 | * Copyright (c) 2003-2004 Michael Niedermayer |
6 | * |
7 | * Support for external huffman table, various fixes (AVID workaround), |
8 | * aspecting, new decode_frame mechanism and apple mjpeg-b support |
9 | * by Alex Beregszaszi |
10 | * |
11 | * This file is part of FFmpeg. |
12 | * |
13 | * FFmpeg is free software; you can redistribute it and/or |
14 | * modify it under the terms of the GNU Lesser General Public |
15 | * License as published by the Free Software Foundation; either |
16 | * version 2.1 of the License, or (at your option) any later version. |
17 | * |
18 | * FFmpeg is distributed in the hope that it will be useful, |
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
21 | * Lesser General Public License for more details. |
22 | * |
23 | * You should have received a copy of the GNU Lesser General Public |
24 | * License along with FFmpeg; if not, write to the Free Software |
25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
26 | */ |
27 | |
28 | /** |
29 | * @file |
30 | * lossless JPEG encoder. |
31 | */ |
32 | |
33 | #include "libavutil/frame.h" |
34 | #include "libavutil/mem.h" |
35 | #include "libavutil/pixdesc.h" |
36 | |
37 | #include "avcodec.h" |
38 | #include "idctdsp.h" |
39 | #include "internal.h" |
40 | #include "jpegtables.h" |
41 | #include "mjpegenc_common.h" |
42 | #include "mjpeg.h" |
43 | #include "mjpegenc.h" |
44 | |
45 | typedef struct LJpegEncContext { |
46 | AVClass *class; |
47 | IDCTDSPContext idsp; |
48 | ScanTable scantable; |
49 | uint16_t matrix[64]; |
50 | |
51 | int vsample[4]; |
52 | int hsample[4]; |
53 | |
54 | uint16_t huff_code_dc_luminance[12]; |
55 | uint16_t huff_code_dc_chrominance[12]; |
56 | uint8_t huff_size_dc_luminance[12]; |
57 | uint8_t huff_size_dc_chrominance[12]; |
58 | |
59 | uint16_t (*scratch)[4]; |
60 | int pred; |
61 | } LJpegEncContext; |
62 | |
63 | static int ljpeg_encode_bgr(AVCodecContext *avctx, PutBitContext *pb, |
64 | const AVFrame *frame) |
65 | { |
66 | LJpegEncContext *s = avctx->priv_data; |
67 | const int width = frame->width; |
68 | const int height = frame->height; |
69 | const int linesize = frame->linesize[0]; |
70 | uint16_t (*buffer)[4] = s->scratch; |
71 | int left[4], top[4], topleft[4]; |
72 | int x, y, i; |
73 | |
74 | #if FF_API_PRIVATE_OPT |
75 | FF_DISABLE_DEPRECATION_WARNINGS |
76 | if (avctx->prediction_method) |
77 | s->pred = avctx->prediction_method + 1; |
78 | FF_ENABLE_DEPRECATION_WARNINGS |
79 | #endif |
80 | |
81 | for (i = 0; i < 4; i++) |
82 | buffer[0][i] = 1 << (9 - 1); |
83 | |
84 | for (y = 0; y < height; y++) { |
85 | const int modified_predictor = y ? s->pred : 1; |
86 | uint8_t *ptr = frame->data[0] + (linesize * y); |
87 | |
88 | if (pb->buf_end - pb->buf - (put_bits_count(pb) >> 3) < width * 4 * 4) { |
89 | av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n"); |
90 | return -1; |
91 | } |
92 | |
93 | for (i = 0; i < 4; i++) |
94 | top[i]= left[i]= topleft[i]= buffer[0][i]; |
95 | |
96 | for (x = 0; x < width; x++) { |
97 | if(avctx->pix_fmt == AV_PIX_FMT_BGR24){ |
98 | buffer[x][1] = ptr[3 * x + 0] - ptr[3 * x + 1] + 0x100; |
99 | buffer[x][2] = ptr[3 * x + 2] - ptr[3 * x + 1] + 0x100; |
100 | buffer[x][0] = (ptr[3 * x + 0] + 2 * ptr[3 * x + 1] + ptr[3 * x + 2]) >> 2; |
101 | }else{ |
102 | buffer[x][1] = ptr[4 * x + 0] - ptr[4 * x + 1] + 0x100; |
103 | buffer[x][2] = ptr[4 * x + 2] - ptr[4 * x + 1] + 0x100; |
104 | buffer[x][0] = (ptr[4 * x + 0] + 2 * ptr[4 * x + 1] + ptr[4 * x + 2]) >> 2; |
105 | if (avctx->pix_fmt == AV_PIX_FMT_BGRA) |
106 | buffer[x][3] = ptr[4 * x + 3]; |
107 | } |
108 | |
109 | for (i = 0; i < 3 + (avctx->pix_fmt == AV_PIX_FMT_BGRA); i++) { |
110 | int pred, diff; |
111 | |
112 | PREDICT(pred, topleft[i], top[i], left[i], modified_predictor); |
113 | |
114 | topleft[i] = top[i]; |
115 | top[i] = buffer[x+1][i]; |
116 | |
117 | left[i] = buffer[x][i]; |
118 | |
119 | diff = ((left[i] - pred + 0x100) & 0x1FF) - 0x100; |
120 | |
121 | if (i == 0 || i == 3) |
122 | ff_mjpeg_encode_dc(pb, diff, s->huff_size_dc_luminance, s->huff_code_dc_luminance); //FIXME ugly |
123 | else |
124 | ff_mjpeg_encode_dc(pb, diff, s->huff_size_dc_chrominance, s->huff_code_dc_chrominance); |
125 | } |
126 | } |
127 | } |
128 | |
129 | return 0; |
130 | } |
131 | |
132 | static inline void ljpeg_encode_yuv_mb(LJpegEncContext *s, PutBitContext *pb, |
133 | const AVFrame *frame, int predictor, |
134 | int mb_x, int mb_y) |
135 | { |
136 | int i; |
137 | |
138 | if (mb_x == 0 || mb_y == 0) { |
139 | for (i = 0; i < 3; i++) { |
140 | uint8_t *ptr; |
141 | int x, y, h, v, linesize; |
142 | h = s->hsample[i]; |
143 | v = s->vsample[i]; |
144 | linesize = frame->linesize[i]; |
145 | |
146 | for (y = 0; y < v; y++) { |
147 | for (x = 0; x < h; x++) { |
148 | int pred; |
149 | |
150 | ptr = frame->data[i] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap |
151 | if (y == 0 && mb_y == 0) { |
152 | if (x == 0 && mb_x == 0) |
153 | pred = 128; |
154 | else |
155 | pred = ptr[-1]; |
156 | } else { |
157 | if (x == 0 && mb_x == 0) { |
158 | pred = ptr[-linesize]; |
159 | } else { |
160 | PREDICT(pred, ptr[-linesize - 1], ptr[-linesize], |
161 | ptr[-1], predictor); |
162 | } |
163 | } |
164 | |
165 | if (i == 0) |
166 | ff_mjpeg_encode_dc(pb, *ptr - pred, s->huff_size_dc_luminance, s->huff_code_dc_luminance); //FIXME ugly |
167 | else |
168 | ff_mjpeg_encode_dc(pb, *ptr - pred, s->huff_size_dc_chrominance, s->huff_code_dc_chrominance); |
169 | } |
170 | } |
171 | } |
172 | } else { |
173 | for (i = 0; i < 3; i++) { |
174 | uint8_t *ptr; |
175 | int x, y, h, v, linesize; |
176 | h = s->hsample[i]; |
177 | v = s->vsample[i]; |
178 | linesize = frame->linesize[i]; |
179 | |
180 | for (y = 0; y < v; y++) { |
181 | for (x = 0; x < h; x++) { |
182 | int pred; |
183 | |
184 | ptr = frame->data[i] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap |
185 | PREDICT(pred, ptr[-linesize - 1], ptr[-linesize], ptr[-1], predictor); |
186 | |
187 | if (i == 0) |
188 | ff_mjpeg_encode_dc(pb, *ptr - pred, s->huff_size_dc_luminance, s->huff_code_dc_luminance); //FIXME ugly |
189 | else |
190 | ff_mjpeg_encode_dc(pb, *ptr - pred, s->huff_size_dc_chrominance, s->huff_code_dc_chrominance); |
191 | } |
192 | } |
193 | } |
194 | } |
195 | } |
196 | |
197 | static int ljpeg_encode_yuv(AVCodecContext *avctx, PutBitContext *pb, |
198 | const AVFrame *frame) |
199 | { |
200 | LJpegEncContext *s = avctx->priv_data; |
201 | const int mb_width = (avctx->width + s->hsample[0] - 1) / s->hsample[0]; |
202 | const int mb_height = (avctx->height + s->vsample[0] - 1) / s->vsample[0]; |
203 | int mb_x, mb_y; |
204 | |
205 | #if FF_API_PRIVATE_OPT |
206 | FF_DISABLE_DEPRECATION_WARNINGS |
207 | if (avctx->prediction_method) |
208 | s->pred = avctx->prediction_method + 1; |
209 | FF_ENABLE_DEPRECATION_WARNINGS |
210 | #endif |
211 | |
212 | for (mb_y = 0; mb_y < mb_height; mb_y++) { |
213 | if (pb->buf_end - pb->buf - (put_bits_count(pb) >> 3) < |
214 | mb_width * 4 * 3 * s->hsample[0] * s->vsample[0]) { |
215 | av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n"); |
216 | return -1; |
217 | } |
218 | |
219 | for (mb_x = 0; mb_x < mb_width; mb_x++) |
220 | ljpeg_encode_yuv_mb(s, pb, frame, s->pred, mb_x, mb_y); |
221 | } |
222 | |
223 | return 0; |
224 | } |
225 | |
226 | static int ljpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
227 | const AVFrame *pict, int *got_packet) |
228 | { |
229 | LJpegEncContext *s = avctx->priv_data; |
230 | PutBitContext pb; |
231 | const int width = avctx->width; |
232 | const int height = avctx->height; |
233 | const int mb_width = (width + s->hsample[0] - 1) / s->hsample[0]; |
234 | const int mb_height = (height + s->vsample[0] - 1) / s->vsample[0]; |
235 | int max_pkt_size = AV_INPUT_BUFFER_MIN_SIZE; |
236 | int ret, header_bits; |
237 | |
238 | if( avctx->pix_fmt == AV_PIX_FMT_BGR0 |
239 | || avctx->pix_fmt == AV_PIX_FMT_BGR24) |
240 | max_pkt_size += width * height * 3 * 4; |
241 | else if(avctx->pix_fmt == AV_PIX_FMT_BGRA) |
242 | max_pkt_size += width * height * 4 * 4; |
243 | else { |
244 | max_pkt_size += mb_width * mb_height * 3 * 4 |
245 | * s->hsample[0] * s->vsample[0]; |
246 | } |
247 | |
248 | if ((ret = ff_alloc_packet2(avctx, pkt, max_pkt_size, 0)) < 0) |
249 | return ret; |
250 | |
251 | init_put_bits(&pb, pkt->data, pkt->size); |
252 | |
253 | ff_mjpeg_encode_picture_header(avctx, &pb, &s->scantable, |
254 | s->pred, s->matrix, s->matrix); |
255 | |
256 | header_bits = put_bits_count(&pb); |
257 | |
258 | if( avctx->pix_fmt == AV_PIX_FMT_BGR0 |
259 | || avctx->pix_fmt == AV_PIX_FMT_BGRA |
260 | || avctx->pix_fmt == AV_PIX_FMT_BGR24) |
261 | ret = ljpeg_encode_bgr(avctx, &pb, pict); |
262 | else |
263 | ret = ljpeg_encode_yuv(avctx, &pb, pict); |
264 | if (ret < 0) |
265 | return ret; |
266 | |
267 | emms_c(); |
268 | |
269 | ff_mjpeg_escape_FF(&pb, header_bits >> 3); |
270 | ff_mjpeg_encode_picture_trailer(&pb, header_bits); |
271 | |
272 | flush_put_bits(&pb); |
273 | pkt->size = put_bits_ptr(&pb) - pb.buf; |
274 | pkt->flags |= AV_PKT_FLAG_KEY; |
275 | *got_packet = 1; |
276 | |
277 | return 0; |
278 | } |
279 | |
280 | static av_cold int ljpeg_encode_close(AVCodecContext *avctx) |
281 | { |
282 | LJpegEncContext *s = avctx->priv_data; |
283 | |
284 | av_freep(&s->scratch); |
285 | |
286 | return 0; |
287 | } |
288 | |
289 | static av_cold int ljpeg_encode_init(AVCodecContext *avctx) |
290 | { |
291 | LJpegEncContext *s = avctx->priv_data; |
292 | |
293 | if ((avctx->pix_fmt == AV_PIX_FMT_YUV420P || |
294 | avctx->pix_fmt == AV_PIX_FMT_YUV422P || |
295 | avctx->pix_fmt == AV_PIX_FMT_YUV444P || |
296 | avctx->color_range == AVCOL_RANGE_MPEG) && |
297 | avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { |
298 | av_log(avctx, AV_LOG_ERROR, |
299 | "Limited range YUV is non-standard, set strict_std_compliance to " |
300 | "at least unofficial to use it.\n"); |
301 | return AVERROR(EINVAL); |
302 | } |
303 | |
304 | #if FF_API_CODED_FRAME |
305 | FF_DISABLE_DEPRECATION_WARNINGS |
306 | avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; |
307 | avctx->coded_frame->key_frame = 1; |
308 | FF_ENABLE_DEPRECATION_WARNINGS |
309 | #endif |
310 | |
311 | s->scratch = av_malloc_array(avctx->width + 1, sizeof(*s->scratch)); |
312 | if (!s->scratch) |
313 | goto fail; |
314 | |
315 | ff_idctdsp_init(&s->idsp, avctx); |
316 | ff_init_scantable(s->idsp.idct_permutation, &s->scantable, |
317 | ff_zigzag_direct); |
318 | |
319 | ff_mjpeg_init_hvsample(avctx, s->hsample, s->vsample); |
320 | |
321 | ff_mjpeg_build_huffman_codes(s->huff_size_dc_luminance, |
322 | s->huff_code_dc_luminance, |
323 | avpriv_mjpeg_bits_dc_luminance, |
324 | avpriv_mjpeg_val_dc); |
325 | ff_mjpeg_build_huffman_codes(s->huff_size_dc_chrominance, |
326 | s->huff_code_dc_chrominance, |
327 | avpriv_mjpeg_bits_dc_chrominance, |
328 | avpriv_mjpeg_val_dc); |
329 | |
330 | return 0; |
331 | fail: |
332 | ljpeg_encode_close(avctx); |
333 | return AVERROR(ENOMEM); |
334 | } |
335 | |
336 | #define OFFSET(x) offsetof(LJpegEncContext, x) |
337 | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM |
338 | static const AVOption options[] = { |
339 | { "pred", "Prediction method", OFFSET(pred), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 3, VE, "pred" }, |
340 | { "left", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "pred" }, |
341 | { "plane", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "pred" }, |
342 | { "median", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, INT_MIN, INT_MAX, VE, "pred" }, |
343 | |
344 | { NULL}, |
345 | }; |
346 | |
347 | static const AVClass ljpeg_class = { |
348 | .class_name = "ljpeg", |
349 | .item_name = av_default_item_name, |
350 | .option = options, |
351 | .version = LIBAVUTIL_VERSION_INT, |
352 | }; |
353 | |
354 | AVCodec ff_ljpeg_encoder = { |
355 | .name = "ljpeg", |
356 | .long_name = NULL_IF_CONFIG_SMALL("Lossless JPEG"), |
357 | .type = AVMEDIA_TYPE_VIDEO, |
358 | .id = AV_CODEC_ID_LJPEG, |
359 | .priv_data_size = sizeof(LJpegEncContext), |
360 | .priv_class = &ljpeg_class, |
361 | .init = ljpeg_encode_init, |
362 | .encode2 = ljpeg_encode_frame, |
363 | .close = ljpeg_encode_close, |
364 | .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, |
365 | .pix_fmts = (const enum AVPixelFormat[]){ |
366 | AV_PIX_FMT_BGR24 , AV_PIX_FMT_BGRA , AV_PIX_FMT_BGR0, |
367 | AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, |
368 | AV_PIX_FMT_YUV420P , AV_PIX_FMT_YUV444P , AV_PIX_FMT_YUV422P, |
369 | AV_PIX_FMT_NONE}, |
370 | }; |
371 |