Browse code

Added support for J2K encoding with libopenjpeg

Note: Some of the previous patches have had two bugs that have been fixed
in this patch.

Signed-off-by: Michael Bradshaw <mbradshaw@sorensonmedia.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Michael Bradshaw authored on 2011/11/18 08:57:09
Showing 8 changed files
... ...
@@ -241,6 +241,7 @@ version 0.8:
241 241
 - lut, lutrgb, and lutyuv filters added
242 242
 - buffersink libavfilter sink added
243 243
 - Bump libswscale for recently reported ABI break
244
+- New J2K encoder (via OpenJPEG)
244 245
 
245 246
 
246 247
 version 0.7:
... ...
@@ -157,6 +157,7 @@ Codecs:
157 157
   libgsm.c                              Michel Bardiaux
158 158
   libdirac*                             David Conrad
159 159
   libopenjpeg.c                         Jaikrishnan Menon
160
+  libopenjpegenc.c                      Michael Bradshaw
160 161
   libschroedinger*                      David Conrad
161 162
   libspeexdec.c                         Justin Ruggles
162 163
   libtheoraenc.c                        David Conrad
... ...
@@ -183,7 +183,7 @@ External library support:
183 183
   --enable-libmp3lame      enable MP3 encoding via libmp3lame [no]
184 184
   --enable-libnut          enable NUT (de)muxing via libnut,
185 185
                            native (de)muxer exists [no]
186
-  --enable-libopenjpeg     enable JPEG 2000 decoding via OpenJPEG [no]
186
+  --enable-libopenjpeg     enable JPEG 2000 encoding/decoding via OpenJPEG [no]
187 187
   --enable-librtmp         enable RTMP[E] support via librtmp [no]
188 188
   --enable-libschroedinger enable Dirac support via libschroedinger [no]
189 189
   --enable-libspeex        enable Speex support via libspeex [no]
... ...
@@ -1519,6 +1519,7 @@ libopencore_amrnb_decoder_deps="libopencore_amrnb"
1519 1519
 libopencore_amrnb_encoder_deps="libopencore_amrnb"
1520 1520
 libopencore_amrwb_decoder_deps="libopencore_amrwb"
1521 1521
 libopenjpeg_decoder_deps="libopenjpeg"
1522
+libopenjpeg_encoder_deps="libopenjpeg"
1522 1523
 libschroedinger_decoder_deps="libschroedinger"
1523 1524
 libschroedinger_encoder_deps="libschroedinger"
1524 1525
 libspeex_decoder_deps="libspeex"
... ...
@@ -15,6 +15,14 @@ FFmpeg can be hooked up with a number of external libraries to add support
15 15
 for more formats. None of them are used by default, their use has to be
16 16
 explicitly requested by passing the appropriate flags to @file{./configure}.
17 17
 
18
+@section OpenJPEG
19
+
20
+FFmpeg can use the OpenJPEG libraries for encoding/decoding J2K videos.  Go to
21
+@url{http://www.openjpeg.org/} to get the libraries and follow the installation
22
+instructions.  To enable using OpenJPEG in FFmpeg, pass @code{--enable-libopenjpeg} to
23
+@file{./configure}.
24
+
25
+
18 26
 @section OpenCORE AMR
19 27
 
20 28
 FFmpeg can make use of the OpenCORE libraries for AMR-NB
... ...
@@ -447,6 +455,7 @@ following image formats are supported:
447 447
     @tab Used in the game Cyberia from Interplay.
448 448
 @item Interplay MVE video    @tab     @tab  X
449 449
     @tab Used in Interplay .MVE files.
450
+@item J2K @tab  X  @tab  X
450 451
 @item Karl Morton's video codec  @tab     @tab  X
451 452
     @tab Codec used in Worms games.
452 453
 @item Kega Game Video (KGV1) @tab      @tab  X
... ...
@@ -606,6 +606,7 @@ OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER)  += libopencore-amr.o
606 606
 OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER)  += libopencore-amr.o
607 607
 OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER)  += libopencore-amr.o
608 608
 OBJS-$(CONFIG_LIBOPENJPEG_DECODER)        += libopenjpegdec.o
609
+OBJS-$(CONFIG_LIBOPENJPEG_ENCODER)        += libopenjpegenc.o
609 610
 OBJS-$(CONFIG_LIBSCHROEDINGER_DECODER)    += libschroedingerdec.o \
610 611
                                              libschroedinger.o    \
611 612
                                              libdirac_libschro.o
... ...
@@ -391,7 +391,7 @@ void avcodec_register_all(void)
391 391
     REGISTER_ENCODER (LIBMP3LAME, libmp3lame);
392 392
     REGISTER_ENCDEC  (LIBOPENCORE_AMRNB, libopencore_amrnb);
393 393
     REGISTER_DECODER (LIBOPENCORE_AMRWB, libopencore_amrwb);
394
-    REGISTER_DECODER (LIBOPENJPEG, libopenjpeg);
394
+    REGISTER_ENCDEC (LIBOPENJPEG, libopenjpeg);
395 395
     REGISTER_ENCDEC  (LIBSCHROEDINGER, libschroedinger);
396 396
     REGISTER_ENCDEC  (LIBSPEEX, libspeex);
397 397
     REGISTER_DECODER (LIBSTAGEFRIGHT_H264, libstagefright_h264);
398 398
new file mode 100644
... ...
@@ -0,0 +1,330 @@
0
+/*
1
+ * JPEG 2000 encoding support via OpenJPEG
2
+ * Copyright (c) 2011 Michael Bradshaw <mbradshaw@sorensonmedia.com>
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+/**
22
+* @file
23
+* JPEG 2000 encoder using libopenjpeg
24
+*/
25
+
26
+#include "libavutil/imgutils.h"
27
+#include "avcodec.h"
28
+#include "libavutil/intreadwrite.h"
29
+#define  OPJ_STATIC
30
+#include <openjpeg.h>
31
+
32
+typedef struct {
33
+    opj_image_t *image;
34
+    opj_cparameters_t enc_params;
35
+    opj_cinfo_t *compress;
36
+    opj_event_mgr_t event_mgr;
37
+} LibOpenJPEGContext;
38
+
39
+static void error_callback(const char *msg, void *data)
40
+{
41
+    av_log((AVCodecContext*)data, AV_LOG_ERROR, "libopenjpeg: %s\n", msg);
42
+}
43
+
44
+static void warning_callback(const char *msg, void *data)
45
+{
46
+    av_log((AVCodecContext*)data, AV_LOG_WARNING, "libopenjpeg: %s\n", msg);
47
+}
48
+
49
+static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *parameters)
50
+{
51
+    opj_image_cmptparm_t *cmptparm;
52
+    opj_image_t *img;
53
+    int i;
54
+    int bpp;
55
+    int sub_dx[4];
56
+    int sub_dy[4];
57
+    int numcomps = 0;
58
+    OPJ_COLOR_SPACE color_space = CLRSPC_UNKNOWN;
59
+
60
+    switch (avctx->pix_fmt) {
61
+    case PIX_FMT_GRAY8:
62
+        color_space = CLRSPC_GRAY;
63
+        numcomps = 1;
64
+        bpp = 8;
65
+        sub_dx[0] = 1;
66
+        sub_dy[0] = 1;
67
+        break;
68
+    case PIX_FMT_RGB24:
69
+        color_space = CLRSPC_SRGB;
70
+        numcomps = 3;
71
+        bpp = 24;
72
+        sub_dx[0] = sub_dx[1] = sub_dx[2] = 1;
73
+        sub_dy[0] = sub_dy[1] = sub_dy[2] = 1;
74
+        break;
75
+    case PIX_FMT_RGBA:
76
+        color_space = CLRSPC_SRGB;
77
+        numcomps = 4;
78
+        bpp = 32;
79
+        sub_dx[0] = sub_dx[1] = sub_dx[2] = sub_dx[3] = 1;
80
+        sub_dy[0] = sub_dy[1] = sub_dy[2] = sub_dy[3] = 1;
81
+        break;
82
+    case PIX_FMT_YUV420P:
83
+        color_space = CLRSPC_SYCC;
84
+        numcomps = 3;
85
+        bpp = 12;
86
+        sub_dx[0] = 1;
87
+        sub_dx[1] = sub_dx[2] = 2;
88
+        sub_dy[0] = 1;
89
+        sub_dy[1] = sub_dy[2] = 2;
90
+        break;
91
+    case PIX_FMT_YUV422P:
92
+        color_space = CLRSPC_SYCC;
93
+        numcomps = 3;
94
+        bpp = 16;
95
+        sub_dx[0] = 1;
96
+        sub_dx[1] = sub_dx[2] = 2;
97
+        sub_dy[0] = sub_dy[1] = sub_dy[2] = 1;
98
+        break;
99
+    case PIX_FMT_YUV440P:
100
+        color_space = CLRSPC_SYCC;
101
+        numcomps = 3;
102
+        bpp = 16;
103
+        sub_dx[0] = sub_dx[1] = sub_dx[2] = 1;
104
+        sub_dy[0] = 1;
105
+        sub_dy[1] = sub_dy[2] = 2;
106
+            break;
107
+    case PIX_FMT_YUV444P:
108
+        color_space = CLRSPC_SYCC;
109
+        numcomps = 3;
110
+        bpp = 24;
111
+        sub_dx[0] = sub_dx[1] = sub_dx[2] = 1;
112
+        sub_dy[0] = sub_dy[1] = sub_dy[2] = 1;
113
+        break;
114
+    default:
115
+        av_log(avctx, AV_LOG_ERROR, "The requested pixel format '%s' is not supported\n", av_get_pix_fmt_name(avctx->pix_fmt));
116
+        return NULL;
117
+    }
118
+
119
+    cmptparm = av_malloc(numcomps * sizeof(opj_image_cmptparm_t));
120
+    if (!cmptparm) {
121
+        av_log(avctx, AV_LOG_ERROR, "Not enough memory");
122
+        return NULL;
123
+    }
124
+    memset(cmptparm, 0, numcomps * sizeof(opj_image_cmptparm_t));
125
+    for (i = 0; i < numcomps; i++) {
126
+        cmptparm[i].prec = 8;
127
+        cmptparm[i].bpp = bpp;
128
+        cmptparm[i].sgnd = 0;
129
+        cmptparm[i].dx = sub_dx[i];
130
+        cmptparm[i].dy = sub_dy[i];
131
+        cmptparm[i].w = avctx->width / sub_dx[i];
132
+        cmptparm[i].h = avctx->height / sub_dy[i];
133
+    }
134
+
135
+    img = opj_image_create(numcomps, cmptparm, color_space);
136
+    av_freep(&cmptparm);
137
+    return img;
138
+}
139
+
140
+static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx)
141
+{
142
+    LibOpenJPEGContext *ctx = avctx->priv_data;
143
+
144
+    opj_set_default_encoder_parameters(&ctx->enc_params);
145
+    ctx->enc_params.tcp_numlayers = 1;
146
+    ctx->enc_params.tcp_rates[0] = avctx->compression_level > 0 ? avctx->compression_level : 0;
147
+    ctx->enc_params.cp_disto_alloc = 1;
148
+
149
+    ctx->compress = opj_create_compress(CODEC_J2K);
150
+    if (!ctx->compress) {
151
+        av_log(avctx, AV_LOG_ERROR, "Error creating the compressor\n");
152
+        return AVERROR(ENOMEM);
153
+    }
154
+
155
+    avctx->coded_frame = avcodec_alloc_frame();
156
+    if (!avctx->coded_frame) {
157
+        av_freep(&ctx->compress);
158
+        ctx->compress = NULL;
159
+        av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n");
160
+        return AVERROR(ENOMEM);
161
+    }
162
+
163
+    ctx->image = mj2_create_image(avctx, &ctx->enc_params);
164
+    if (!ctx->image) {
165
+        av_freep(&ctx->compress);
166
+        ctx->compress = NULL;
167
+        av_freep(&avctx->coded_frame);
168
+        avctx->coded_frame = NULL;
169
+        av_log(avctx, AV_LOG_ERROR, "Error creating the mj2 image\n");
170
+        return AVERROR(EINVAL);
171
+    }
172
+
173
+    memset(&ctx->event_mgr, 0, sizeof(opj_event_mgr_t));
174
+    ctx->event_mgr.error_handler = error_callback;
175
+    ctx->event_mgr.warning_handler = warning_callback;
176
+    ctx->event_mgr.info_handler = NULL;
177
+    opj_set_event_mgr((opj_common_ptr)ctx->compress, &ctx->event_mgr, avctx);
178
+
179
+    return 0;
180
+}
181
+
182
+static int libopenjpeg_copy_rgba(AVCodecContext *avctx, AVFrame *frame, opj_image_t *image, int numcomps)
183
+{
184
+    int compno;
185
+    int x;
186
+    int y;
187
+
188
+    if (numcomps != 1 && numcomps != 3 && numcomps != 4) {
189
+        return 0;
190
+    }
191
+
192
+    for (compno = 0; compno < numcomps; ++compno) {
193
+        if (image->comps[compno].w > frame->linesize[0] / numcomps) {
194
+            return 0;
195
+        }
196
+    }
197
+
198
+    for (compno = 0; compno < numcomps; ++compno) {
199
+        for (y = 0; y < avctx->height; ++y) {
200
+            for (x = 0; x < avctx->width; ++x) {
201
+                image->comps[compno].data[y * avctx->width + x] = frame->data[0][y * frame->linesize[0] + x * numcomps + compno];
202
+            }
203
+        }
204
+    }
205
+
206
+    return 1;
207
+}
208
+
209
+static int libopenjpeg_copy_yuv(AVCodecContext *avctx, AVFrame *frame, opj_image_t *image)
210
+{
211
+    int compno;
212
+    int x;
213
+    int y;
214
+    int width;
215
+    int height;
216
+    const int numcomps = 3;
217
+
218
+    for (compno = 0; compno < numcomps; ++compno) {
219
+        if (image->comps[compno].w > frame->linesize[compno]) {
220
+            return 0;
221
+        }
222
+    }
223
+
224
+    for (compno = 0; compno < numcomps; ++compno) {
225
+        width = avctx->width / image->comps[compno].dx;
226
+        height = avctx->height / image->comps[compno].dy;
227
+        for (y = 0; y < height; ++y) {
228
+            for (x = 0; x < width; ++x) {
229
+                image->comps[compno].data[y * width + x] = frame->data[compno][y * frame->linesize[compno] + x];
230
+            }
231
+        }
232
+    }
233
+
234
+    return 1;
235
+}
236
+
237
+static int libopenjpeg_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
238
+{
239
+    AVFrame *frame = data;
240
+    LibOpenJPEGContext *ctx = avctx->priv_data;
241
+    opj_cinfo_t *compress = ctx->compress;
242
+    opj_image_t *image = ctx->image;
243
+    opj_cio_t *stream;
244
+    int cpyresult = 0;
245
+    int len = 0;
246
+
247
+    // x0, y0 is the top left corner of the image
248
+    // x1, y1 is the width, height of the reference grid
249
+    image->x0 = 0;
250
+    image->y0 = 0;
251
+    image->x1 = (avctx->width - 1) * ctx->enc_params.subsampling_dx + 1;
252
+    image->y1 = (avctx->height - 1) * ctx->enc_params.subsampling_dy + 1;
253
+
254
+    switch (avctx->pix_fmt) {
255
+    case PIX_FMT_GRAY8:
256
+        cpyresult = libopenjpeg_copy_rgba(avctx, frame, image, 1);
257
+        break;
258
+    case PIX_FMT_RGB24:
259
+        cpyresult = libopenjpeg_copy_rgba(avctx, frame, image, 3);
260
+        break;
261
+    case PIX_FMT_RGBA:
262
+        cpyresult = libopenjpeg_copy_rgba(avctx, frame, image, 4);
263
+        break;
264
+    case PIX_FMT_YUV420P:
265
+    case PIX_FMT_YUV422P:
266
+    case PIX_FMT_YUV440P:
267
+    case PIX_FMT_YUV444P:
268
+        cpyresult = libopenjpeg_copy_yuv(avctx, frame, image);
269
+        break;
270
+    default:
271
+        av_log(avctx, AV_LOG_ERROR, "The frame's pixel format '%s' is not supported\n", av_get_pix_fmt_name(avctx->pix_fmt));
272
+        return AVERROR(EINVAL);
273
+        break;
274
+    }
275
+
276
+    if (!cpyresult) {
277
+        av_log(avctx, AV_LOG_ERROR, "Could not copy the frame data to the internal image buffer\n");
278
+        return -1;
279
+    }
280
+
281
+    opj_setup_encoder(compress, &ctx->enc_params, image);
282
+    stream = opj_cio_open((opj_common_ptr)compress, NULL, 0);
283
+    if (!stream) {
284
+        av_log(avctx, AV_LOG_ERROR, "Error creating the cio stream\n");
285
+        return AVERROR(ENOMEM);
286
+    }
287
+
288
+    if (!opj_encode(compress, stream, image, NULL)) {
289
+        opj_cio_close(stream);
290
+        av_log(avctx, AV_LOG_ERROR, "Error during the opj encode\n");
291
+        return -1;
292
+    }
293
+
294
+    len = cio_tell(stream);
295
+    if (len > buf_size) {
296
+        opj_cio_close(stream);
297
+        av_log(avctx, AV_LOG_ERROR, "Error with buf_size, not large enough to hold the frame\n");
298
+        return -1;
299
+    }
300
+
301
+    memcpy(buf, stream->buffer, len);
302
+    opj_cio_close(stream);
303
+    return len;
304
+}
305
+
306
+static av_cold int libopenjpeg_encode_close(AVCodecContext *avctx)
307
+{
308
+    LibOpenJPEGContext *ctx = avctx->priv_data;
309
+
310
+    opj_destroy_compress(ctx->compress);
311
+    opj_image_destroy(ctx->image);
312
+    av_freep(&avctx->coded_frame);
313
+    return 0 ;
314
+}
315
+
316
+
317
+AVCodec ff_libopenjpeg_encoder = {
318
+    .name = "libopenjpeg",
319
+    .type = AVMEDIA_TYPE_VIDEO,
320
+    .id = CODEC_ID_JPEG2000,
321
+    .priv_data_size = sizeof(LibOpenJPEGContext),
322
+    .init = libopenjpeg_encode_init,
323
+    .encode = libopenjpeg_encode_frame,
324
+    .close = libopenjpeg_encode_close,
325
+    .decode = NULL,
326
+    .capabilities = 0,
327
+    .pix_fmts = (const enum PixelFormat[]){PIX_FMT_GRAY8,PIX_FMT_RGB24,PIX_FMT_RGBA,PIX_FMT_YUV420P,PIX_FMT_YUV422P,PIX_FMT_YUV440P,PIX_FMT_YUV444P},
328
+    .long_name = NULL_IF_CONFIG_SMALL("OpenJPEG based JPEG 2000 encoder/decoder"),
329
+} ;
... ...
@@ -21,7 +21,7 @@
21 21
 #define AVCODEC_VERSION_H
22 22
 
23 23
 #define LIBAVCODEC_VERSION_MAJOR 53
24
-#define LIBAVCODEC_VERSION_MINOR 34
24
+#define LIBAVCODEC_VERSION_MINOR 35
25 25
 #define LIBAVCODEC_VERSION_MICRO  0
26 26
 
27 27
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \