00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "libavutil/imgutils.h"
00028 #include "libavutil/avassert.h"
00029 #include "avcodec.h"
00030 #include "libavutil/intreadwrite.h"
00031 #define OPJ_STATIC
00032 #include <openjpeg.h>
00033
00034 typedef struct {
00035 opj_image_t *image;
00036 opj_cparameters_t enc_params;
00037 opj_cinfo_t *compress;
00038 opj_event_mgr_t event_mgr;
00039 } LibOpenJPEGContext;
00040
00041 static void error_callback(const char *msg, void *data)
00042 {
00043 av_log((AVCodecContext*)data, AV_LOG_ERROR, "libopenjpeg: %s\n", msg);
00044 }
00045
00046 static void warning_callback(const char *msg, void *data)
00047 {
00048 av_log((AVCodecContext*)data, AV_LOG_WARNING, "libopenjpeg: %s\n", msg);
00049 }
00050
00051 static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *parameters)
00052 {
00053 opj_image_cmptparm_t *cmptparm;
00054 opj_image_t *img;
00055 int i;
00056 int bpp = 8;
00057 int sub_dx[4];
00058 int sub_dy[4];
00059 int numcomps = 0;
00060 OPJ_COLOR_SPACE color_space = CLRSPC_UNKNOWN;
00061
00062 sub_dx[0] = sub_dx[3] = 1;
00063 sub_dy[0] = sub_dy[3] = 1;
00064 sub_dx[1] = sub_dx[2] = 1<<av_pix_fmt_descriptors[avctx->pix_fmt].log2_chroma_w;
00065 sub_dy[1] = sub_dy[2] = 1<<av_pix_fmt_descriptors[avctx->pix_fmt].log2_chroma_h;
00066
00067 switch (avctx->pix_fmt) {
00068 case PIX_FMT_GRAY8:
00069 color_space = CLRSPC_GRAY;
00070 numcomps = 1;
00071 break;
00072 case PIX_FMT_RGB24:
00073 color_space = CLRSPC_SRGB;
00074 numcomps = 3;
00075 break;
00076 case PIX_FMT_RGBA:
00077 color_space = CLRSPC_SRGB;
00078 numcomps = 4;
00079 break;
00080 case PIX_FMT_YUV420P:
00081 color_space = CLRSPC_SYCC;
00082 numcomps = 3;
00083 break;
00084 case PIX_FMT_YUV422P:
00085 color_space = CLRSPC_SYCC;
00086 numcomps = 3;
00087 break;
00088 case PIX_FMT_YUV440P:
00089 color_space = CLRSPC_SYCC;
00090 numcomps = 3;
00091 break;
00092 case PIX_FMT_YUV444P:
00093 color_space = CLRSPC_SYCC;
00094 numcomps = 3;
00095 break;
00096 case PIX_FMT_YUVA420P:
00097 color_space = CLRSPC_SYCC;
00098 numcomps = 4;
00099 break;
00100 case PIX_FMT_YUV420P9:
00101 case PIX_FMT_YUV422P9:
00102 case PIX_FMT_YUV444P9:
00103 color_space = CLRSPC_SYCC;
00104 numcomps = 3;
00105 bpp = 9;
00106 break;
00107 case PIX_FMT_YUV420P10:
00108 case PIX_FMT_YUV422P10:
00109 case PIX_FMT_YUV444P10:
00110 color_space = CLRSPC_SYCC;
00111 numcomps = 3;
00112 bpp = 10;
00113 break;
00114 case PIX_FMT_YUV420P16:
00115 case PIX_FMT_YUV422P16:
00116 case PIX_FMT_YUV444P16:
00117 color_space = CLRSPC_SYCC;
00118 numcomps = 3;
00119 bpp = 16;
00120 break;
00121 default:
00122 av_log(avctx, AV_LOG_ERROR, "The requested pixel format '%s' is not supported\n", av_get_pix_fmt_name(avctx->pix_fmt));
00123 return NULL;
00124 }
00125
00126 cmptparm = av_mallocz(numcomps * sizeof(opj_image_cmptparm_t));
00127 if (!cmptparm) {
00128 av_log(avctx, AV_LOG_ERROR, "Not enough memory");
00129 return NULL;
00130 }
00131 for (i = 0; i < numcomps; i++) {
00132 cmptparm[i].prec = bpp;
00133 cmptparm[i].bpp = bpp;
00134 cmptparm[i].sgnd = 0;
00135 cmptparm[i].dx = sub_dx[i];
00136 cmptparm[i].dy = sub_dy[i];
00137 cmptparm[i].w = avctx->width / sub_dx[i];
00138 cmptparm[i].h = avctx->height / sub_dy[i];
00139 }
00140
00141 img = opj_image_create(numcomps, cmptparm, color_space);
00142 av_freep(&cmptparm);
00143 return img;
00144 }
00145
00146 static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx)
00147 {
00148 LibOpenJPEGContext *ctx = avctx->priv_data;
00149
00150 opj_set_default_encoder_parameters(&ctx->enc_params);
00151 ctx->enc_params.tcp_numlayers = 1;
00152 ctx->enc_params.tcp_rates[0] = FFMAX(avctx->compression_level, 0) * 2;
00153 ctx->enc_params.cp_disto_alloc = 1;
00154
00155 ctx->compress = opj_create_compress(CODEC_J2K);
00156 if (!ctx->compress) {
00157 av_log(avctx, AV_LOG_ERROR, "Error creating the compressor\n");
00158 return AVERROR(ENOMEM);
00159 }
00160
00161 avctx->coded_frame = avcodec_alloc_frame();
00162 if (!avctx->coded_frame) {
00163 av_freep(&ctx->compress);
00164 av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n");
00165 return AVERROR(ENOMEM);
00166 }
00167
00168 ctx->image = mj2_create_image(avctx, &ctx->enc_params);
00169 if (!ctx->image) {
00170 av_freep(&ctx->compress);
00171 av_freep(&avctx->coded_frame);
00172 av_log(avctx, AV_LOG_ERROR, "Error creating the mj2 image\n");
00173 return AVERROR(EINVAL);
00174 }
00175
00176 memset(&ctx->event_mgr, 0, sizeof(opj_event_mgr_t));
00177 ctx->event_mgr.error_handler = error_callback;
00178 ctx->event_mgr.warning_handler = warning_callback;
00179 ctx->event_mgr.info_handler = NULL;
00180 opj_set_event_mgr((opj_common_ptr)ctx->compress, &ctx->event_mgr, avctx);
00181
00182 return 0;
00183 }
00184
00185 static int libopenjpeg_copy_rgba(AVCodecContext *avctx, AVFrame *frame, opj_image_t *image, int numcomps)
00186 {
00187 int compno;
00188 int x;
00189 int y;
00190
00191 av_assert0(numcomps == 1 || numcomps == 3 || numcomps == 4);
00192
00193 for (compno = 0; compno < numcomps; ++compno) {
00194 if (image->comps[compno].w > frame->linesize[0] / numcomps) {
00195 return 0;
00196 }
00197 }
00198
00199 for (compno = 0; compno < numcomps; ++compno) {
00200 for (y = 0; y < avctx->height; ++y) {
00201 for (x = 0; x < avctx->width; ++x) {
00202 image->comps[compno].data[y * avctx->width + x] = frame->data[0][y * frame->linesize[0] + x * numcomps + compno];
00203 }
00204 }
00205 }
00206
00207 return 1;
00208 }
00209
00210 static int libopenjpeg_copy_yuv8(AVCodecContext *avctx, AVFrame *frame, opj_image_t *image)
00211 {
00212 int compno;
00213 int x;
00214 int y;
00215 int width;
00216 int height;
00217 const int numcomps = avctx->pix_fmt == PIX_FMT_YUVA420P ? 4 : 3;
00218
00219 for (compno = 0; compno < numcomps; ++compno) {
00220 if (image->comps[compno].w > frame->linesize[compno]) {
00221 return 0;
00222 }
00223 }
00224
00225 for (compno = 0; compno < numcomps; ++compno) {
00226 width = avctx->width / image->comps[compno].dx;
00227 height = avctx->height / image->comps[compno].dy;
00228 for (y = 0; y < height; ++y) {
00229 for (x = 0; x < width; ++x) {
00230 image->comps[compno].data[y * width + x] = frame->data[compno][y * frame->linesize[compno] + x];
00231 }
00232 }
00233 }
00234
00235 return 1;
00236 }
00237
00238 static int libopenjpeg_copy_yuv16(AVCodecContext *avctx, AVFrame *frame, opj_image_t *image)
00239 {
00240 int compno;
00241 int x;
00242 int y;
00243 int width;
00244 int height;
00245 const int numcomps = 3;
00246 uint16_t *frame_ptr;
00247
00248 for (compno = 0; compno < numcomps; ++compno) {
00249 if (image->comps[compno].w > frame->linesize[compno]) {
00250 return 0;
00251 }
00252 }
00253
00254 for (compno = 0; compno < numcomps; ++compno) {
00255 width = avctx->width / image->comps[compno].dx;
00256 height = avctx->height / image->comps[compno].dy;
00257 frame_ptr = (uint16_t*)frame->data[compno];
00258 for (y = 0; y < height; ++y) {
00259 for (x = 0; x < width; ++x) {
00260 image->comps[compno].data[y * width + x] = frame_ptr[y * (frame->linesize[compno] / 2) + x];
00261 }
00262 }
00263 }
00264
00265 return 1;
00266 }
00267
00268 static int libopenjpeg_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
00269 {
00270 AVFrame *frame = data;
00271 LibOpenJPEGContext *ctx = avctx->priv_data;
00272 opj_cinfo_t *compress = ctx->compress;
00273 opj_image_t *image = ctx->image;
00274 opj_cio_t *stream;
00275 int cpyresult = 0;
00276 int len = 0;
00277
00278
00279
00280 image->x0 = 0;
00281 image->y0 = 0;
00282 image->x1 = (avctx->width - 1) * ctx->enc_params.subsampling_dx + 1;
00283 image->y1 = (avctx->height - 1) * ctx->enc_params.subsampling_dy + 1;
00284
00285 switch (avctx->pix_fmt) {
00286 case PIX_FMT_GRAY8:
00287 cpyresult = libopenjpeg_copy_rgba(avctx, frame, image, 1);
00288 break;
00289 case PIX_FMT_RGB24:
00290 cpyresult = libopenjpeg_copy_rgba(avctx, frame, image, 3);
00291 break;
00292 case PIX_FMT_RGBA:
00293 cpyresult = libopenjpeg_copy_rgba(avctx, frame, image, 4);
00294 break;
00295 case PIX_FMT_YUV420P:
00296 case PIX_FMT_YUV422P:
00297 case PIX_FMT_YUV440P:
00298 case PIX_FMT_YUV444P:
00299 case PIX_FMT_YUVA420P:
00300 cpyresult = libopenjpeg_copy_yuv8(avctx, frame, image);
00301 break;
00302 case PIX_FMT_YUV420P9:
00303 case PIX_FMT_YUV420P10:
00304 case PIX_FMT_YUV420P16:
00305 case PIX_FMT_YUV422P9:
00306 case PIX_FMT_YUV422P10:
00307 case PIX_FMT_YUV422P16:
00308 case PIX_FMT_YUV444P9:
00309 case PIX_FMT_YUV444P10:
00310 case PIX_FMT_YUV444P16:
00311 cpyresult = libopenjpeg_copy_yuv16(avctx, frame, image);
00312 break;
00313 default:
00314 av_log(avctx, AV_LOG_ERROR, "The frame's pixel format '%s' is not supported\n", av_get_pix_fmt_name(avctx->pix_fmt));
00315 return AVERROR(EINVAL);
00316 break;
00317 }
00318
00319 if (!cpyresult) {
00320 av_log(avctx, AV_LOG_ERROR, "Could not copy the frame data to the internal image buffer\n");
00321 return -1;
00322 }
00323
00324 opj_setup_encoder(compress, &ctx->enc_params, image);
00325 stream = opj_cio_open((opj_common_ptr)compress, NULL, 0);
00326 if (!stream) {
00327 av_log(avctx, AV_LOG_ERROR, "Error creating the cio stream\n");
00328 return AVERROR(ENOMEM);
00329 }
00330
00331 if (!opj_encode(compress, stream, image, NULL)) {
00332 opj_cio_close(stream);
00333 av_log(avctx, AV_LOG_ERROR, "Error during the opj encode\n");
00334 return -1;
00335 }
00336
00337 len = cio_tell(stream);
00338 if (len > buf_size) {
00339 opj_cio_close(stream);
00340 av_log(avctx, AV_LOG_ERROR, "Error with buf_size, not large enough to hold the frame\n");
00341 return -1;
00342 }
00343
00344 memcpy(buf, stream->buffer, len);
00345 opj_cio_close(stream);
00346 return len;
00347 }
00348
00349 static av_cold int libopenjpeg_encode_close(AVCodecContext *avctx)
00350 {
00351 LibOpenJPEGContext *ctx = avctx->priv_data;
00352
00353 opj_destroy_compress(ctx->compress);
00354 opj_image_destroy(ctx->image);
00355 av_freep(&avctx->coded_frame);
00356 return 0 ;
00357 }
00358
00359
00360 AVCodec ff_libopenjpeg_encoder = {
00361 .name = "libopenjpeg",
00362 .type = AVMEDIA_TYPE_VIDEO,
00363 .id = CODEC_ID_JPEG2000,
00364 .priv_data_size = sizeof(LibOpenJPEGContext),
00365 .init = libopenjpeg_encode_init,
00366 .encode = libopenjpeg_encode_frame,
00367 .close = libopenjpeg_encode_close,
00368 .decode = NULL,
00369 .capabilities = 0,
00370 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24,PIX_FMT_RGBA,PIX_FMT_GRAY8,
00371 PIX_FMT_YUV420P,PIX_FMT_YUV422P,PIX_FMT_YUVA420P,
00372 PIX_FMT_YUV440P,PIX_FMT_YUV444P,
00373 PIX_FMT_YUV420P9,PIX_FMT_YUV422P9,PIX_FMT_YUV444P9,
00374 PIX_FMT_YUV420P10,PIX_FMT_YUV422P10,PIX_FMT_YUV444P10,
00375 PIX_FMT_YUV420P16,PIX_FMT_YUV422P16,PIX_FMT_YUV444P16,
00376 PIX_FMT_NONE},
00377 .long_name = NULL_IF_CONFIG_SMALL("OpenJPEG based JPEG 2000 encoder"),
00378 } ;