xref: /third_party/ffmpeg/libavcodec/ljpegenc.c (revision cabdff1a)
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/opt.h"
36#include "libavutil/pixdesc.h"
37
38#include "avcodec.h"
39#include "codec_internal.h"
40#include "encode.h"
41#include "idctdsp.h"
42#include "jpegtables.h"
43#include "mathops.h"
44#include "mjpegenc_common.h"
45#include "mjpeg.h"
46
47typedef struct LJpegEncContext {
48    AVClass *class;
49    IDCTDSPContext idsp;
50    ScanTable scantable;
51    uint16_t matrix[64];
52
53    int vsample[4];
54    int hsample[4];
55
56    uint16_t huff_code_dc_luminance[12];
57    uint16_t huff_code_dc_chrominance[12];
58    uint8_t  huff_size_dc_luminance[12];
59    uint8_t  huff_size_dc_chrominance[12];
60
61    uint16_t (*scratch)[4];
62    int pred;
63} LJpegEncContext;
64
65static int ljpeg_encode_bgr(AVCodecContext *avctx, PutBitContext *pb,
66                            const AVFrame *frame)
67{
68    LJpegEncContext *s    = avctx->priv_data;
69    const int width       = frame->width;
70    const int height      = frame->height;
71    const int linesize    = frame->linesize[0];
72    uint16_t (*buffer)[4] = s->scratch;
73    int left[4], top[4], topleft[4];
74    int x, y, i;
75
76    for (i = 0; i < 4; i++)
77        buffer[0][i] = 1 << (9 - 1);
78
79    for (y = 0; y < height; y++) {
80        const int modified_predictor = y ? s->pred : 1;
81        uint8_t *ptr = frame->data[0] + (linesize * y);
82
83        if (put_bytes_left(pb, 0) < width * 4 * 4) {
84            av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
85            return -1;
86        }
87
88        for (i = 0; i < 4; i++)
89            top[i]= left[i]= topleft[i]= buffer[0][i];
90
91        for (x = 0; x < width; x++) {
92            if(avctx->pix_fmt == AV_PIX_FMT_BGR24){
93                buffer[x][1] =  ptr[3 * x + 0] -     ptr[3 * x + 1] + 0x100;
94                buffer[x][2] =  ptr[3 * x + 2] -     ptr[3 * x + 1] + 0x100;
95                buffer[x][0] = (ptr[3 * x + 0] + 2 * ptr[3 * x + 1] + ptr[3 * x + 2]) >> 2;
96            }else{
97                buffer[x][1] =  ptr[4 * x + 0] -     ptr[4 * x + 1] + 0x100;
98                buffer[x][2] =  ptr[4 * x + 2] -     ptr[4 * x + 1] + 0x100;
99                buffer[x][0] = (ptr[4 * x + 0] + 2 * ptr[4 * x + 1] + ptr[4 * x + 2]) >> 2;
100                if (avctx->pix_fmt == AV_PIX_FMT_BGRA)
101                    buffer[x][3] =  ptr[4 * x + 3];
102            }
103
104            for (i = 0; i < 3 + (avctx->pix_fmt == AV_PIX_FMT_BGRA); i++) {
105                int pred, diff;
106
107                PREDICT(pred, topleft[i], top[i], left[i], modified_predictor);
108
109                topleft[i] = top[i];
110                top[i]     = buffer[x+1][i];
111
112                left[i]    = buffer[x][i];
113
114                diff       = ((left[i] - pred + 0x100) & 0x1FF) - 0x100;
115
116                if (i == 0 || i == 3)
117                    ff_mjpeg_encode_dc(pb, diff, s->huff_size_dc_luminance, s->huff_code_dc_luminance); //FIXME ugly
118                else
119                    ff_mjpeg_encode_dc(pb, diff, s->huff_size_dc_chrominance, s->huff_code_dc_chrominance);
120            }
121        }
122    }
123
124    return 0;
125}
126
127static inline void ljpeg_encode_yuv_mb(LJpegEncContext *s, PutBitContext *pb,
128                                       const AVFrame *frame, int predictor,
129                                       int mb_x, int mb_y)
130{
131    int i;
132
133    if (mb_x == 0 || mb_y == 0) {
134        for (i = 0; i < 3; i++) {
135            uint8_t *ptr;
136            int x, y, h, v, linesize;
137            h = s->hsample[i];
138            v = s->vsample[i];
139            linesize = frame->linesize[i];
140
141            for (y = 0; y < v; y++) {
142                for (x = 0; x < h; x++) {
143                    int pred;
144
145                    ptr = frame->data[i] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap
146                    if (y == 0 && mb_y == 0) {
147                        if (x == 0 && mb_x == 0)
148                            pred = 128;
149                        else
150                            pred = ptr[-1];
151                    } else {
152                        if (x == 0 && mb_x == 0) {
153                            pred = ptr[-linesize];
154                        } else {
155                            PREDICT(pred, ptr[-linesize - 1], ptr[-linesize],
156                                    ptr[-1], predictor);
157                        }
158                    }
159
160                    if (i == 0)
161                        ff_mjpeg_encode_dc(pb, *ptr - pred, s->huff_size_dc_luminance, s->huff_code_dc_luminance); //FIXME ugly
162                    else
163                        ff_mjpeg_encode_dc(pb, *ptr - pred, s->huff_size_dc_chrominance, s->huff_code_dc_chrominance);
164                }
165            }
166        }
167    } else {
168        for (i = 0; i < 3; i++) {
169            uint8_t *ptr;
170            int x, y, h, v, linesize;
171            h = s->hsample[i];
172            v = s->vsample[i];
173            linesize = frame->linesize[i];
174
175            for (y = 0; y < v; y++) {
176                for (x = 0; x < h; x++) {
177                    int pred;
178
179                    ptr = frame->data[i] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap
180                    PREDICT(pred, ptr[-linesize - 1], ptr[-linesize], ptr[-1], predictor);
181
182                    if (i == 0)
183                        ff_mjpeg_encode_dc(pb, *ptr - pred, s->huff_size_dc_luminance, s->huff_code_dc_luminance); //FIXME ugly
184                    else
185                        ff_mjpeg_encode_dc(pb, *ptr - pred, s->huff_size_dc_chrominance, s->huff_code_dc_chrominance);
186                }
187            }
188        }
189    }
190}
191
192static int ljpeg_encode_yuv(AVCodecContext *avctx, PutBitContext *pb,
193                            const AVFrame *frame)
194{
195    LJpegEncContext *s  = avctx->priv_data;
196    const int mb_width  = (avctx->width  + s->hsample[0] - 1) / s->hsample[0];
197    const int mb_height = (avctx->height + s->vsample[0] - 1) / s->vsample[0];
198    int mb_x, mb_y;
199
200    for (mb_y = 0; mb_y < mb_height; mb_y++) {
201        if (put_bytes_left(pb, 0) <
202            mb_width * 4 * 3 * s->hsample[0] * s->vsample[0]) {
203            av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
204            return -1;
205        }
206
207        for (mb_x = 0; mb_x < mb_width; mb_x++)
208            ljpeg_encode_yuv_mb(s, pb, frame, s->pred, mb_x, mb_y);
209    }
210
211    return 0;
212}
213
214static int ljpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
215                              const AVFrame *pict, int *got_packet)
216{
217    LJpegEncContext *s = avctx->priv_data;
218    PutBitContext pb;
219    const int width  = avctx->width;
220    const int height = avctx->height;
221    const int mb_width  = (width  + s->hsample[0] - 1) / s->hsample[0];
222    const int mb_height = (height + s->vsample[0] - 1) / s->vsample[0];
223    size_t max_pkt_size = AV_INPUT_BUFFER_MIN_SIZE;
224    int ret, header_bits;
225
226    if(    avctx->pix_fmt == AV_PIX_FMT_BGR0
227        || avctx->pix_fmt == AV_PIX_FMT_BGR24)
228        max_pkt_size += width * height * 3 * 4;
229    else if(avctx->pix_fmt == AV_PIX_FMT_BGRA)
230        max_pkt_size += width * height * 4 * 4;
231    else {
232        max_pkt_size += mb_width * mb_height * 3 * 4
233                        * s->hsample[0] * s->vsample[0];
234    }
235
236    if ((ret = ff_mjpeg_add_icc_profile_size(avctx, pict, &max_pkt_size)) < 0)
237        return ret;
238    if ((ret = ff_alloc_packet(avctx, pkt, max_pkt_size)) < 0)
239        return ret;
240
241    init_put_bits(&pb, pkt->data, pkt->size);
242
243    ff_mjpeg_encode_picture_header(avctx, &pb, pict, NULL, &s->scantable,
244                                   s->pred, s->matrix, s->matrix, 0);
245
246    header_bits = put_bits_count(&pb);
247
248    if(    avctx->pix_fmt == AV_PIX_FMT_BGR0
249        || avctx->pix_fmt == AV_PIX_FMT_BGRA
250        || avctx->pix_fmt == AV_PIX_FMT_BGR24)
251        ret = ljpeg_encode_bgr(avctx, &pb, pict);
252    else
253        ret = ljpeg_encode_yuv(avctx, &pb, pict);
254    if (ret < 0)
255        return ret;
256
257    emms_c();
258
259    ff_mjpeg_escape_FF(&pb, header_bits >> 3);
260    ff_mjpeg_encode_picture_trailer(&pb, header_bits);
261
262    flush_put_bits(&pb);
263    pkt->size   = put_bits_ptr(&pb) - pb.buf;
264    *got_packet = 1;
265
266    return 0;
267}
268
269static av_cold int ljpeg_encode_close(AVCodecContext *avctx)
270{
271    LJpegEncContext *s = avctx->priv_data;
272
273    av_freep(&s->scratch);
274
275    return 0;
276}
277
278static av_cold int ljpeg_encode_init(AVCodecContext *avctx)
279{
280    int ret = ff_mjpeg_encode_check_pix_fmt(avctx);
281    LJpegEncContext *s = avctx->priv_data;
282
283    if (ret < 0)
284        return ret;
285
286    s->scratch = av_malloc_array(avctx->width + 1, sizeof(*s->scratch));
287    if (!s->scratch)
288        return AVERROR(ENOMEM);
289
290    ff_idctdsp_init(&s->idsp, avctx);
291    ff_init_scantable(s->idsp.idct_permutation, &s->scantable,
292                      ff_zigzag_direct);
293
294    ff_mjpeg_init_hvsample(avctx, s->hsample, s->vsample);
295
296    ff_mjpeg_build_huffman_codes(s->huff_size_dc_luminance,
297                                 s->huff_code_dc_luminance,
298                                 ff_mjpeg_bits_dc_luminance,
299                                 ff_mjpeg_val_dc);
300    ff_mjpeg_build_huffman_codes(s->huff_size_dc_chrominance,
301                                 s->huff_code_dc_chrominance,
302                                 ff_mjpeg_bits_dc_chrominance,
303                                 ff_mjpeg_val_dc);
304
305    return 0;
306}
307
308#define OFFSET(x) offsetof(LJpegEncContext, x)
309#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
310static const AVOption options[] = {
311{ "pred", "Prediction method", OFFSET(pred), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 3, VE, "pred" },
312    { "left",   NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "pred" },
313    { "plane",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "pred" },
314    { "median", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, INT_MIN, INT_MAX, VE, "pred" },
315
316    { NULL},
317};
318
319static const AVClass ljpeg_class = {
320    .class_name = "ljpeg",
321    .item_name  = av_default_item_name,
322    .option     = options,
323    .version    = LIBAVUTIL_VERSION_INT,
324};
325
326const FFCodec ff_ljpeg_encoder = {
327    .p.name         = "ljpeg",
328    .p.long_name    = NULL_IF_CONFIG_SMALL("Lossless JPEG"),
329    .p.type         = AVMEDIA_TYPE_VIDEO,
330    .p.id           = AV_CODEC_ID_LJPEG,
331    .priv_data_size = sizeof(LJpegEncContext),
332    .p.priv_class   = &ljpeg_class,
333    .init           = ljpeg_encode_init,
334    FF_CODEC_ENCODE_CB(ljpeg_encode_frame),
335    .close          = ljpeg_encode_close,
336    .p.capabilities = AV_CODEC_CAP_FRAME_THREADS,
337    .p.pix_fmts     = (const enum AVPixelFormat[]){
338        AV_PIX_FMT_BGR24   , AV_PIX_FMT_BGRA    , AV_PIX_FMT_BGR0,
339        AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P,
340        AV_PIX_FMT_YUV420P , AV_PIX_FMT_YUV444P , AV_PIX_FMT_YUV422P,
341        AV_PIX_FMT_NONE},
342    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
343};
344