PageRenderTime 45ms CodeModel.GetById 19ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/libavcodec/ljpegenc.c

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