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