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_GRAY8A:
00073 color_space = CLRSPC_GRAY;
00074 numcomps = 2;
00075 break;
00076 case PIX_FMT_GRAY16:
00077 color_space = CLRSPC_GRAY;
00078 numcomps = 1;
00079 bpp = 16;
00080 break;
00081 case PIX_FMT_RGB24:
00082 color_space = CLRSPC_SRGB;
00083 numcomps = 3;
00084 break;
00085 case PIX_FMT_RGBA:
00086 color_space = CLRSPC_SRGB;
00087 numcomps = 4;
00088 break;
00089 case PIX_FMT_RGB48:
00090 color_space = CLRSPC_SRGB;
00091 numcomps = 3;
00092 bpp = 16;
00093 break;
00094 case PIX_FMT_RGBA64:
00095 color_space = CLRSPC_SRGB;
00096 numcomps = 4;
00097 bpp = 16;
00098 break;
00099 case PIX_FMT_YUV420P:
00100 color_space = CLRSPC_SYCC;
00101 numcomps = 3;
00102 break;
00103 case PIX_FMT_YUV422P:
00104 color_space = CLRSPC_SYCC;
00105 numcomps = 3;
00106 break;
00107 case PIX_FMT_YUV440P:
00108 color_space = CLRSPC_SYCC;
00109 numcomps = 3;
00110 break;
00111 case PIX_FMT_YUV444P:
00112 color_space = CLRSPC_SYCC;
00113 numcomps = 3;
00114 break;
00115 case PIX_FMT_YUVA420P:
00116 color_space = CLRSPC_SYCC;
00117 numcomps = 4;
00118 break;
00119 case PIX_FMT_YUV420P9:
00120 case PIX_FMT_YUV422P9:
00121 case PIX_FMT_YUV444P9:
00122 color_space = CLRSPC_SYCC;
00123 numcomps = 3;
00124 bpp = 9;
00125 break;
00126 case PIX_FMT_YUV420P10:
00127 case PIX_FMT_YUV422P10:
00128 case PIX_FMT_YUV444P10:
00129 color_space = CLRSPC_SYCC;
00130 numcomps = 3;
00131 bpp = 10;
00132 break;
00133 case PIX_FMT_YUV420P16:
00134 case PIX_FMT_YUV422P16:
00135 case PIX_FMT_YUV444P16:
00136 color_space = CLRSPC_SYCC;
00137 numcomps = 3;
00138 bpp = 16;
00139 break;
00140 default:
00141 av_log(avctx, AV_LOG_ERROR, "The requested pixel format '%s' is not supported\n", av_get_pix_fmt_name(avctx->pix_fmt));
00142 return NULL;
00143 }
00144
00145 cmptparm = av_mallocz(numcomps * sizeof(opj_image_cmptparm_t));
00146 if (!cmptparm) {
00147 av_log(avctx, AV_LOG_ERROR, "Not enough memory");
00148 return NULL;
00149 }
00150 for (i = 0; i < numcomps; i++) {
00151 cmptparm[i].prec = bpp;
00152 cmptparm[i].bpp = bpp;
00153 cmptparm[i].sgnd = 0;
00154 cmptparm[i].dx = sub_dx[i];
00155 cmptparm[i].dy = sub_dy[i];
00156 cmptparm[i].w = avctx->width / sub_dx[i];
00157 cmptparm[i].h = avctx->height / sub_dy[i];
00158 }
00159
00160 img = opj_image_create(numcomps, cmptparm, color_space);
00161 av_freep(&cmptparm);
00162 return img;
00163 }
00164
00165 static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx)
00166 {
00167 LibOpenJPEGContext *ctx = avctx->priv_data;
00168
00169 opj_set_default_encoder_parameters(&ctx->enc_params);
00170 ctx->enc_params.tcp_numlayers = 1;
00171 ctx->enc_params.tcp_rates[0] = FFMAX(avctx->compression_level, 0) * 2;
00172 ctx->enc_params.cp_disto_alloc = 1;
00173
00174 ctx->compress = opj_create_compress(CODEC_J2K);
00175 if (!ctx->compress) {
00176 av_log(avctx, AV_LOG_ERROR, "Error creating the compressor\n");
00177 return AVERROR(ENOMEM);
00178 }
00179
00180 avctx->coded_frame = avcodec_alloc_frame();
00181 if (!avctx->coded_frame) {
00182 av_freep(&ctx->compress);
00183 av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n");
00184 return AVERROR(ENOMEM);
00185 }
00186
00187 ctx->image = mj2_create_image(avctx, &ctx->enc_params);
00188 if (!ctx->image) {
00189 av_freep(&ctx->compress);
00190 av_freep(&avctx->coded_frame);
00191 av_log(avctx, AV_LOG_ERROR, "Error creating the mj2 image\n");
00192 return AVERROR(EINVAL);
00193 }
00194
00195 memset(&ctx->event_mgr, 0, sizeof(opj_event_mgr_t));
00196 ctx->event_mgr.error_handler = error_callback;
00197 ctx->event_mgr.warning_handler = warning_callback;
00198 ctx->event_mgr.info_handler = NULL;
00199 opj_set_event_mgr((opj_common_ptr)ctx->compress, &ctx->event_mgr, avctx);
00200
00201 return 0;
00202 }
00203
00204 static int libopenjpeg_copy_packed8(AVCodecContext *avctx, AVFrame *frame, opj_image_t *image)
00205 {
00206 int compno;
00207 int x;
00208 int y;
00209 int image_index;
00210 int frame_index;
00211 const int numcomps = image->numcomps;
00212
00213 for (compno = 0; compno < numcomps; ++compno) {
00214 if (image->comps[compno].w > frame->linesize[0] / numcomps) {
00215 av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n");
00216 return 0;
00217 }
00218 }
00219
00220 for (compno = 0; compno < numcomps; ++compno) {
00221 for (y = 0; y < avctx->height; ++y) {
00222 image_index = y * avctx->width;
00223 frame_index = y * frame->linesize[0] + compno;
00224 for (x = 0; x < avctx->width; ++x) {
00225 image->comps[compno].data[image_index++] = frame->data[0][frame_index];
00226 frame_index += numcomps;
00227 }
00228 }
00229 }
00230
00231 return 1;
00232 }
00233
00234 static int libopenjpeg_copy_packed16(AVCodecContext *avctx, AVFrame *frame, opj_image_t *image)
00235 {
00236 int compno;
00237 int x;
00238 int y;
00239 int image_index;
00240 int frame_index;
00241 const int numcomps = image->numcomps;
00242 uint16_t *frame_ptr = (uint16_t*)frame->data[0];
00243
00244 for (compno = 0; compno < numcomps; ++compno) {
00245 if (image->comps[compno].w > frame->linesize[0] / numcomps) {
00246 av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n");
00247 return 0;
00248 }
00249 }
00250
00251 for (compno = 0; compno < numcomps; ++compno) {
00252 for (y = 0; y < avctx->height; ++y) {
00253 image_index = y * avctx->width;
00254 frame_index = y * (frame->linesize[0] / 2) + compno;
00255 for (x = 0; x < avctx->width; ++x) {
00256 image->comps[compno].data[image_index++] = frame_ptr[frame_index];
00257 frame_index += numcomps;
00258 }
00259 }
00260 }
00261
00262 return 1;
00263 }
00264
00265 static int libopenjpeg_copy_unpacked8(AVCodecContext *avctx, AVFrame *frame, opj_image_t *image)
00266 {
00267 int compno;
00268 int x;
00269 int y;
00270 int width;
00271 int height;
00272 int image_index;
00273 int frame_index;
00274 const int numcomps = image->numcomps;
00275
00276 for (compno = 0; compno < numcomps; ++compno) {
00277 if (image->comps[compno].w > frame->linesize[compno]) {
00278 av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n");
00279 return 0;
00280 }
00281 }
00282
00283 for (compno = 0; compno < numcomps; ++compno) {
00284 width = avctx->width / image->comps[compno].dx;
00285 height = avctx->height / image->comps[compno].dy;
00286 for (y = 0; y < height; ++y) {
00287 image_index = y * width;
00288 frame_index = y * frame->linesize[compno];
00289 for (x = 0; x < width; ++x) {
00290 image->comps[compno].data[image_index++] = frame->data[compno][frame_index++];
00291 }
00292 }
00293 }
00294
00295 return 1;
00296 }
00297
00298 static int libopenjpeg_copy_unpacked16(AVCodecContext *avctx, AVFrame *frame, opj_image_t *image)
00299 {
00300 int compno;
00301 int x;
00302 int y;
00303 int width;
00304 int height;
00305 int image_index;
00306 int frame_index;
00307 const int numcomps = image->numcomps;
00308 uint16_t *frame_ptr;
00309
00310 for (compno = 0; compno < numcomps; ++compno) {
00311 if (image->comps[compno].w > frame->linesize[compno]) {
00312 av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n");
00313 return 0;
00314 }
00315 }
00316
00317 for (compno = 0; compno < numcomps; ++compno) {
00318 width = avctx->width / image->comps[compno].dx;
00319 height = avctx->height / image->comps[compno].dy;
00320 frame_ptr = (uint16_t*)frame->data[compno];
00321 for (y = 0; y < height; ++y) {
00322 image_index = y * width;
00323 frame_index = y * (frame->linesize[compno] / 2);
00324 for (x = 0; x < width; ++x) {
00325 image->comps[compno].data[image_index++] = frame_ptr[frame_index++];
00326 }
00327 }
00328 }
00329
00330 return 1;
00331 }
00332
00333 static int libopenjpeg_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
00334 {
00335 AVFrame *frame = data;
00336 LibOpenJPEGContext *ctx = avctx->priv_data;
00337 opj_cinfo_t *compress = ctx->compress;
00338 opj_image_t *image = ctx->image;
00339 opj_cio_t *stream;
00340 int cpyresult = 0;
00341 int len = 0;
00342
00343
00344
00345 image->x0 = 0;
00346 image->y0 = 0;
00347 image->x1 = (avctx->width - 1) * ctx->enc_params.subsampling_dx + 1;
00348 image->y1 = (avctx->height - 1) * ctx->enc_params.subsampling_dy + 1;
00349
00350 switch (avctx->pix_fmt) {
00351 case PIX_FMT_RGB24:
00352 case PIX_FMT_RGBA:
00353 case PIX_FMT_GRAY8A:
00354 cpyresult = libopenjpeg_copy_packed8(avctx, frame, image);
00355 break;
00356 case PIX_FMT_RGB48:
00357 case PIX_FMT_RGBA64:
00358 cpyresult = libopenjpeg_copy_packed16(avctx, frame, image);
00359 break;
00360 case PIX_FMT_GRAY8:
00361 case PIX_FMT_YUV420P:
00362 case PIX_FMT_YUV422P:
00363 case PIX_FMT_YUV440P:
00364 case PIX_FMT_YUV444P:
00365 case PIX_FMT_YUVA420P:
00366 cpyresult = libopenjpeg_copy_unpacked8(avctx, frame, image);
00367 break;
00368 case PIX_FMT_GRAY16:
00369 case PIX_FMT_YUV420P9:
00370 case PIX_FMT_YUV420P10:
00371 case PIX_FMT_YUV420P16:
00372 case PIX_FMT_YUV422P9:
00373 case PIX_FMT_YUV422P10:
00374 case PIX_FMT_YUV422P16:
00375 case PIX_FMT_YUV444P9:
00376 case PIX_FMT_YUV444P10:
00377 case PIX_FMT_YUV444P16:
00378 cpyresult = libopenjpeg_copy_unpacked16(avctx, frame, image);
00379 break;
00380 default:
00381 av_log(avctx, AV_LOG_ERROR, "The frame's pixel format '%s' is not supported\n", av_get_pix_fmt_name(avctx->pix_fmt));
00382 return AVERROR(EINVAL);
00383 break;
00384 }
00385
00386 if (!cpyresult) {
00387 av_log(avctx, AV_LOG_ERROR, "Could not copy the frame data to the internal image buffer\n");
00388 return -1;
00389 }
00390
00391 opj_setup_encoder(compress, &ctx->enc_params, image);
00392 stream = opj_cio_open((opj_common_ptr)compress, NULL, 0);
00393 if (!stream) {
00394 av_log(avctx, AV_LOG_ERROR, "Error creating the cio stream\n");
00395 return AVERROR(ENOMEM);
00396 }
00397
00398 if (!opj_encode(compress, stream, image, NULL)) {
00399 opj_cio_close(stream);
00400 av_log(avctx, AV_LOG_ERROR, "Error during the opj encode\n");
00401 return -1;
00402 }
00403
00404 len = cio_tell(stream);
00405 if (len > buf_size) {
00406 opj_cio_close(stream);
00407 av_log(avctx, AV_LOG_ERROR, "Error with buf_size, not large enough to hold the frame\n");
00408 return -1;
00409 }
00410
00411 memcpy(buf, stream->buffer, len);
00412 opj_cio_close(stream);
00413 return len;
00414 }
00415
00416 static av_cold int libopenjpeg_encode_close(AVCodecContext *avctx)
00417 {
00418 LibOpenJPEGContext *ctx = avctx->priv_data;
00419
00420 opj_destroy_compress(ctx->compress);
00421 opj_image_destroy(ctx->image);
00422 av_freep(&avctx->coded_frame);
00423 return 0 ;
00424 }
00425
00426
00427 AVCodec ff_libopenjpeg_encoder = {
00428 .name = "libopenjpeg",
00429 .type = AVMEDIA_TYPE_VIDEO,
00430 .id = CODEC_ID_JPEG2000,
00431 .priv_data_size = sizeof(LibOpenJPEGContext),
00432 .init = libopenjpeg_encode_init,
00433 .encode = libopenjpeg_encode_frame,
00434 .close = libopenjpeg_encode_close,
00435 .capabilities = 0,
00436 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24,PIX_FMT_RGBA,PIX_FMT_RGB48,PIX_FMT_RGBA64,
00437 PIX_FMT_GRAY8,PIX_FMT_GRAY8A,PIX_FMT_GRAY16,
00438 PIX_FMT_YUV420P,PIX_FMT_YUV422P,PIX_FMT_YUVA420P,
00439 PIX_FMT_YUV440P,PIX_FMT_YUV444P,
00440 PIX_FMT_YUV420P9,PIX_FMT_YUV422P9,PIX_FMT_YUV444P9,
00441 PIX_FMT_YUV420P10,PIX_FMT_YUV422P10,PIX_FMT_YUV444P10,
00442 PIX_FMT_YUV420P16,PIX_FMT_YUV422P16,PIX_FMT_YUV444P16,
00443 PIX_FMT_NONE},
00444 .long_name = NULL_IF_CONFIG_SMALL("OpenJPEG based JPEG 2000 encoder"),
00445 } ;