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