7c92c03b |
/*
* JPEG 2000 encoding support via OpenJPEG |
c430cb49 |
* Copyright (c) 2011 Michael Bradshaw <mjbshaw gmail com> |
7c92c03b |
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** |
51a5ddfa |
* @file
* JPEG 2000 encoder using libopenjpeg
*/ |
7c92c03b |
|
453c02f9 |
#define OPJ_STATIC
|
1b987c4b |
#include "libavutil/avassert.h" |
7ebe3962 |
#include "libavutil/common.h" |
453c02f9 |
#include "libavutil/imgutils.h" |
7c92c03b |
#include "libavutil/intreadwrite.h" |
51a5ddfa |
#include "libavutil/opt.h" |
453c02f9 |
#include "avcodec.h" |
b222c28e |
#include "internal.h" |
7c92c03b |
|
e749b5dd |
#if HAVE_OPENJPEG_1_5_OPENJPEG_H
# include <openjpeg-1.5/openjpeg.h>
#else
# include <openjpeg.h>
#endif
|
7c92c03b |
typedef struct { |
67d5fcc9 |
AVClass *avclass; |
7c92c03b |
opj_image_t *image; |
3cfd4df8 |
opj_cio_t *stream; |
7c92c03b |
opj_cparameters_t enc_params;
opj_cinfo_t *compress;
opj_event_mgr_t event_mgr; |
67d5fcc9 |
int format;
int profile;
int prog_order; |
453c02f9 |
int cinema_mode; |
67d5fcc9 |
int numresolution;
int numlayers;
int disto_alloc;
int fixed_alloc;
int fixed_quality; |
7c92c03b |
} LibOpenJPEGContext;
static void error_callback(const char *msg, void *data)
{ |
453c02f9 |
av_log(data, AV_LOG_ERROR, "%s\n", msg); |
7c92c03b |
}
static void warning_callback(const char *msg, void *data)
{ |
453c02f9 |
av_log(data, AV_LOG_WARNING, "%s\n", msg);
}
static void info_callback(const char *msg, void *data)
{
av_log(data, AV_LOG_DEBUG, "%s\n", msg); |
7c92c03b |
}
static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *parameters)
{ |
50ba57e0 |
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); |
3cfd4df8 |
opj_image_cmptparm_t cmptparm[4] = {{0}}; |
7c92c03b |
opj_image_t *img;
int i;
int sub_dx[4];
int sub_dy[4]; |
06b0c6a6 |
int numcomps; |
7c92c03b |
OPJ_COLOR_SPACE color_space = CLRSPC_UNKNOWN;
|
1b987c4b |
sub_dx[0] = sub_dx[3] = 1;
sub_dy[0] = sub_dy[3] = 1; |
af7dd79a |
sub_dx[1] = sub_dx[2] = 1 << desc->log2_chroma_w;
sub_dy[1] = sub_dy[2] = 1 << desc->log2_chroma_h; |
1b987c4b |
|
af7dd79a |
numcomps = desc->nb_components; |
06b0c6a6 |
|
7c92c03b |
switch (avctx->pix_fmt) { |
716d413c |
case AV_PIX_FMT_GRAY8: |
ac627b3d |
case AV_PIX_FMT_GRAY8A: |
716d413c |
case AV_PIX_FMT_GRAY16: |
ffd1017f |
color_space = CLRSPC_GRAY;
break; |
716d413c |
case AV_PIX_FMT_RGB24:
case AV_PIX_FMT_RGBA:
case AV_PIX_FMT_RGB48: |
ac627b3d |
case AV_PIX_FMT_RGBA64: |
c58c6739 |
case AV_PIX_FMT_GBR24P:
case AV_PIX_FMT_GBRP9:
case AV_PIX_FMT_GBRP10:
case AV_PIX_FMT_GBRP12:
case AV_PIX_FMT_GBRP14:
case AV_PIX_FMT_GBRP16: |
4443213d |
case AV_PIX_FMT_XYZ12: |
36397ea1 |
color_space = CLRSPC_SRGB;
break; |
716d413c |
case AV_PIX_FMT_YUV410P:
case AV_PIX_FMT_YUV411P:
case AV_PIX_FMT_YUV420P:
case AV_PIX_FMT_YUV422P:
case AV_PIX_FMT_YUV440P:
case AV_PIX_FMT_YUV444P:
case AV_PIX_FMT_YUVA420P: |
ac627b3d |
case AV_PIX_FMT_YUVA422P:
case AV_PIX_FMT_YUVA444P: |
716d413c |
case AV_PIX_FMT_YUV420P9:
case AV_PIX_FMT_YUV422P9:
case AV_PIX_FMT_YUV444P9: |
b5d496f3 |
case AV_PIX_FMT_YUVA420P9:
case AV_PIX_FMT_YUVA422P9:
case AV_PIX_FMT_YUVA444P9: |
716d413c |
case AV_PIX_FMT_YUV420P10:
case AV_PIX_FMT_YUV422P10:
case AV_PIX_FMT_YUV444P10: |
b5d496f3 |
case AV_PIX_FMT_YUVA420P10:
case AV_PIX_FMT_YUVA422P10:
case AV_PIX_FMT_YUVA444P10: |
ac627b3d |
case AV_PIX_FMT_YUV420P12:
case AV_PIX_FMT_YUV422P12:
case AV_PIX_FMT_YUV444P12:
case AV_PIX_FMT_YUV420P14:
case AV_PIX_FMT_YUV422P14:
case AV_PIX_FMT_YUV444P14: |
716d413c |
case AV_PIX_FMT_YUV420P16:
case AV_PIX_FMT_YUV422P16:
case AV_PIX_FMT_YUV444P16: |
b5d496f3 |
case AV_PIX_FMT_YUVA420P16:
case AV_PIX_FMT_YUVA422P16:
case AV_PIX_FMT_YUVA444P16: |
0275b75a |
color_space = CLRSPC_SYCC; |
7c92c03b |
break;
default: |
453c02f9 |
av_log(avctx, AV_LOG_ERROR,
"The requested pixel format '%s' is not supported\n",
av_get_pix_fmt_name(avctx->pix_fmt)); |
7c92c03b |
return NULL;
}
for (i = 0; i < numcomps; i++) { |
50ba57e0 |
cmptparm[i].prec = desc->comp[i].depth_minus1 + 1;
cmptparm[i].bpp = desc->comp[i].depth_minus1 + 1; |
7c92c03b |
cmptparm[i].sgnd = 0;
cmptparm[i].dx = sub_dx[i];
cmptparm[i].dy = sub_dy[i]; |
f46a3e3d |
cmptparm[i].w = (avctx->width + sub_dx[i] - 1) / sub_dx[i];
cmptparm[i].h = (avctx->height + sub_dy[i] - 1) / sub_dy[i]; |
7c92c03b |
}
img = opj_image_create(numcomps, cmptparm, color_space); |
3cfd4df8 |
// x0, y0 is the top left corner of the image
// x1, y1 is the width, height of the reference grid
img->x0 = 0;
img->y0 = 0;
img->x1 = (avctx->width - 1) * parameters->subsampling_dx + 1;
img->y1 = (avctx->height - 1) * parameters->subsampling_dy + 1;
|
7c92c03b |
return img;
}
static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx)
{
LibOpenJPEGContext *ctx = avctx->priv_data; |
453c02f9 |
int err = AVERROR(ENOMEM); |
7c92c03b |
opj_set_default_encoder_parameters(&ctx->enc_params); |
453c02f9 |
|
67d5fcc9 |
ctx->enc_params.cp_rsiz = ctx->profile;
ctx->enc_params.mode = !!avctx->global_quality;
ctx->enc_params.cp_cinema = ctx->cinema_mode;
ctx->enc_params.prog_order = ctx->prog_order;
ctx->enc_params.numresolution = ctx->numresolution;
ctx->enc_params.cp_disto_alloc = ctx->disto_alloc;
ctx->enc_params.cp_fixed_alloc = ctx->fixed_alloc;
ctx->enc_params.cp_fixed_quality = ctx->fixed_quality;
ctx->enc_params.tcp_numlayers = ctx->numlayers; |
0275b75a |
ctx->enc_params.tcp_rates[0] = FFMAX(avctx->compression_level, 0) * 2; |
7c92c03b |
|
60f06f98 |
if (ctx->cinema_mode > 0) {
ctx->enc_params.irreversible = 1;
ctx->enc_params.tcp_mct = 1;
ctx->enc_params.tile_size_on = 0;
/* no subsampling */
ctx->enc_params.cp_tdx=1;
ctx->enc_params.cp_tdy=1;
ctx->enc_params.subsampling_dx = 1;
ctx->enc_params.subsampling_dy = 1;
/* Tile and Image shall be at (0,0) */
ctx->enc_params.cp_tx0 = 0;
ctx->enc_params.cp_ty0 = 0;
ctx->enc_params.image_offset_x0 = 0;
ctx->enc_params.image_offset_y0 = 0;
/* Codeblock size= 32*32 */
ctx->enc_params.cblockw_init = 32;
ctx->enc_params.cblockh_init = 32;
ctx->enc_params.csty |= 0x01;
/* No ROI */
ctx->enc_params.roi_compno = -1;
if (ctx->enc_params.prog_order != CPRL) {
av_log(avctx, AV_LOG_ERROR, "prog_order forced to CPRL\n");
ctx->enc_params.prog_order = CPRL;
}
ctx->enc_params.tp_flag = 'C';
ctx->enc_params.tp_on = 1;
}
|
67d5fcc9 |
ctx->compress = opj_create_compress(ctx->format); |
7c92c03b |
if (!ctx->compress) {
av_log(avctx, AV_LOG_ERROR, "Error creating the compressor\n");
return AVERROR(ENOMEM);
}
ctx->image = mj2_create_image(avctx, &ctx->enc_params);
if (!ctx->image) {
av_log(avctx, AV_LOG_ERROR, "Error creating the mj2 image\n"); |
453c02f9 |
err = AVERROR(EINVAL);
goto fail; |
7c92c03b |
} |
3cfd4df8 |
opj_setup_encoder(ctx->compress, &ctx->enc_params, ctx->image);
ctx->stream = opj_cio_open((opj_common_ptr)ctx->compress, NULL, 0);
if (!ctx->stream) {
av_log(avctx, AV_LOG_ERROR, "Error creating the cio stream\n");
err = AVERROR(ENOMEM);
goto fail;
}
|
0ee905e2 |
avctx->coded_frame = av_frame_alloc(); |
3cfd4df8 |
if (!avctx->coded_frame) {
av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n");
goto fail;
} |
7c92c03b |
memset(&ctx->event_mgr, 0, sizeof(opj_event_mgr_t)); |
453c02f9 |
ctx->event_mgr.info_handler = info_callback; |
7c92c03b |
ctx->event_mgr.error_handler = error_callback;
ctx->event_mgr.warning_handler = warning_callback;
opj_set_event_mgr((opj_common_ptr)ctx->compress, &ctx->event_mgr, avctx);
return 0; |
453c02f9 |
fail: |
3cfd4df8 |
opj_cio_close(ctx->stream);
ctx->stream = NULL;
opj_destroy_compress(ctx->compress);
ctx->compress = NULL;
opj_image_destroy(ctx->image);
ctx->image = NULL; |
453c02f9 |
av_freep(&avctx->coded_frame);
return err; |
7c92c03b |
}
|
b222c28e |
static int libopenjpeg_copy_packed8(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) |
7c92c03b |
{
int compno;
int x;
int y; |
f46a3e3d |
int *image_line; |
de073550 |
int frame_index; |
56af084c |
const int numcomps = image->numcomps; |
7c92c03b |
for (compno = 0; compno < numcomps; ++compno) {
if (image->comps[compno].w > frame->linesize[0] / numcomps) { |
0abe25aa |
av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n"); |
7c92c03b |
return 0;
}
}
for (compno = 0; compno < numcomps; ++compno) {
for (y = 0; y < avctx->height; ++y) { |
f46a3e3d |
image_line = image->comps[compno].data + y * image->comps[compno].w; |
de073550 |
frame_index = y * frame->linesize[0] + compno; |
7c92c03b |
for (x = 0; x < avctx->width; ++x) { |
f46a3e3d |
image_line[x] = frame->data[0][frame_index]; |
de073550 |
frame_index += numcomps; |
7c92c03b |
} |
f46a3e3d |
for (; x < image->comps[compno].w; ++x) {
image_line[x] = image_line[x - 1];
}
}
for (; y < image->comps[compno].h; ++y) {
image_line = image->comps[compno].data + y * image->comps[compno].w;
for (x = 0; x < image->comps[compno].w; ++x) {
image_line[x] = image_line[x - image->comps[compno].w];
} |
7c92c03b |
}
}
return 1;
}
|
4443213d |
// for XYZ 12 bit
static int libopenjpeg_copy_packed12(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image)
{
int compno;
int x;
int y; |
f46a3e3d |
int *image_line; |
4443213d |
int frame_index;
const int numcomps = image->numcomps;
uint16_t *frame_ptr = (uint16_t*)frame->data[0];
for (compno = 0; compno < numcomps; ++compno) {
if (image->comps[compno].w > frame->linesize[0] / numcomps) {
av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n");
return 0;
}
}
for (compno = 0; compno < numcomps; ++compno) {
for (y = 0; y < avctx->height; ++y) { |
f46a3e3d |
image_line = image->comps[compno].data + y * image->comps[compno].w; |
4443213d |
frame_index = y * (frame->linesize[0] / 2) + compno;
for (x = 0; x < avctx->width; ++x) { |
f46a3e3d |
image_line[x] = frame_ptr[frame_index] >> 4; |
4443213d |
frame_index += numcomps;
} |
f46a3e3d |
for (; x < image->comps[compno].w; ++x) {
image_line[x] = image_line[x - 1];
}
}
for (; y < image->comps[compno].h; ++y) {
image_line = image->comps[compno].data + y * image->comps[compno].w;
for (x = 0; x < image->comps[compno].w; ++x) {
image_line[x] = image_line[x - image->comps[compno].w];
} |
4443213d |
}
}
return 1;
}
|
b222c28e |
static int libopenjpeg_copy_packed16(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) |
4093d130 |
{
int compno;
int x;
int y; |
f46a3e3d |
int *image_line; |
de073550 |
int frame_index; |
56af084c |
const int numcomps = image->numcomps; |
4093d130 |
uint16_t *frame_ptr = (uint16_t*)frame->data[0];
for (compno = 0; compno < numcomps; ++compno) {
if (image->comps[compno].w > frame->linesize[0] / numcomps) { |
0abe25aa |
av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n"); |
4093d130 |
return 0;
}
}
for (compno = 0; compno < numcomps; ++compno) {
for (y = 0; y < avctx->height; ++y) { |
f46a3e3d |
image_line = image->comps[compno].data + y * image->comps[compno].w; |
de073550 |
frame_index = y * (frame->linesize[0] / 2) + compno; |
4093d130 |
for (x = 0; x < avctx->width; ++x) { |
f46a3e3d |
image_line[x] = frame_ptr[frame_index]; |
de073550 |
frame_index += numcomps; |
4093d130 |
} |
f46a3e3d |
for (; x < image->comps[compno].w; ++x) {
image_line[x] = image_line[x - 1];
}
}
for (; y < image->comps[compno].h; ++y) {
image_line = image->comps[compno].data + y * image->comps[compno].w;
for (x = 0; x < image->comps[compno].w; ++x) {
image_line[x] = image_line[x - image->comps[compno].w];
} |
4093d130 |
}
}
return 1;
}
|
b222c28e |
static int libopenjpeg_copy_unpacked8(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) |
7c92c03b |
{
int compno;
int x;
int y;
int width;
int height; |
f46a3e3d |
int *image_line; |
de073550 |
int frame_index; |
a02694c9 |
const int numcomps = image->numcomps; |
7c92c03b |
for (compno = 0; compno < numcomps; ++compno) {
if (image->comps[compno].w > frame->linesize[compno]) { |
0abe25aa |
av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n"); |
7c92c03b |
return 0;
}
}
for (compno = 0; compno < numcomps; ++compno) {
width = avctx->width / image->comps[compno].dx;
height = avctx->height / image->comps[compno].dy;
for (y = 0; y < height; ++y) { |
f46a3e3d |
image_line = image->comps[compno].data + y * image->comps[compno].w; |
de073550 |
frame_index = y * frame->linesize[compno]; |
51a5ddfa |
for (x = 0; x < width; ++x) |
f46a3e3d |
image_line[x] = frame->data[compno][frame_index++];
for (; x < image->comps[compno].w; ++x) {
image_line[x] = image_line[x - 1];
}
}
for (; y < image->comps[compno].h; ++y) {
image_line = image->comps[compno].data + y * image->comps[compno].w;
for (x = 0; x < image->comps[compno].w; ++x) {
image_line[x] = image_line[x - image->comps[compno].w];
} |
7c92c03b |
}
}
return 1;
}
|
b222c28e |
static int libopenjpeg_copy_unpacked16(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) |
0275b75a |
{
int compno;
int x;
int y;
int width;
int height; |
f46a3e3d |
int *image_line; |
de073550 |
int frame_index; |
a02694c9 |
const int numcomps = image->numcomps; |
0275b75a |
uint16_t *frame_ptr;
for (compno = 0; compno < numcomps; ++compno) {
if (image->comps[compno].w > frame->linesize[compno]) { |
0abe25aa |
av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n"); |
0275b75a |
return 0;
}
}
for (compno = 0; compno < numcomps; ++compno) {
width = avctx->width / image->comps[compno].dx;
height = avctx->height / image->comps[compno].dy;
frame_ptr = (uint16_t*)frame->data[compno];
for (y = 0; y < height; ++y) { |
f46a3e3d |
image_line = image->comps[compno].data + y * image->comps[compno].w; |
de073550 |
frame_index = y * (frame->linesize[compno] / 2); |
51a5ddfa |
for (x = 0; x < width; ++x) |
f46a3e3d |
image_line[x] = frame_ptr[frame_index++];
for (; x < image->comps[compno].w; ++x) {
image_line[x] = image_line[x - 1];
}
}
for (; y < image->comps[compno].h; ++y) {
image_line = image->comps[compno].data + y * image->comps[compno].w;
for (x = 0; x < image->comps[compno].w; ++x) {
image_line[x] = image_line[x - image->comps[compno].w];
} |
0275b75a |
}
}
return 1;
}
|
b222c28e |
static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
const AVFrame *frame, int *got_packet) |
7c92c03b |
{
LibOpenJPEGContext *ctx = avctx->priv_data;
opj_cinfo_t *compress = ctx->compress; |
51a5ddfa |
opj_image_t *image = ctx->image; |
3cfd4df8 |
opj_cio_t *stream = ctx->stream; |
7c92c03b |
int cpyresult = 0; |
b222c28e |
int ret, len; |
1458f064 |
AVFrame *gbrframe; |
7c92c03b |
switch (avctx->pix_fmt) { |
716d413c |
case AV_PIX_FMT_RGB24:
case AV_PIX_FMT_RGBA: |
ac627b3d |
case AV_PIX_FMT_GRAY8A: |
56af084c |
cpyresult = libopenjpeg_copy_packed8(avctx, frame, image); |
7c92c03b |
break; |
4443213d |
case AV_PIX_FMT_XYZ12:
cpyresult = libopenjpeg_copy_packed12(avctx, frame, image);
break; |
716d413c |
case AV_PIX_FMT_RGB48: |
ac627b3d |
case AV_PIX_FMT_RGBA64: |
56af084c |
cpyresult = libopenjpeg_copy_packed16(avctx, frame, image); |
36397ea1 |
break; |
c58c6739 |
case AV_PIX_FMT_GBR24P:
case AV_PIX_FMT_GBRP9:
case AV_PIX_FMT_GBRP10:
case AV_PIX_FMT_GBRP12:
case AV_PIX_FMT_GBRP14:
case AV_PIX_FMT_GBRP16: |
9b68538f |
gbrframe = av_frame_clone(frame); |
97af2faa |
if (!gbrframe)
return AVERROR(ENOMEM); |
1458f064 |
gbrframe->data[0] = frame->data[2]; // swap to be rgb
gbrframe->data[1] = frame->data[0];
gbrframe->data[2] = frame->data[1];
gbrframe->linesize[0] = frame->linesize[2];
gbrframe->linesize[1] = frame->linesize[0];
gbrframe->linesize[2] = frame->linesize[1]; |
28f36dce |
if (avctx->pix_fmt == AV_PIX_FMT_GBR24P) { |
1458f064 |
cpyresult = libopenjpeg_copy_unpacked8(avctx, gbrframe, image); |
28f36dce |
} else { |
1458f064 |
cpyresult = libopenjpeg_copy_unpacked16(avctx, gbrframe, image); |
28f36dce |
} |
1458f064 |
av_frame_free(&gbrframe); |
c58c6739 |
break; |
716d413c |
case AV_PIX_FMT_GRAY8:
case AV_PIX_FMT_YUV410P:
case AV_PIX_FMT_YUV411P:
case AV_PIX_FMT_YUV420P:
case AV_PIX_FMT_YUV422P:
case AV_PIX_FMT_YUV440P:
case AV_PIX_FMT_YUV444P:
case AV_PIX_FMT_YUVA420P: |
ac627b3d |
case AV_PIX_FMT_YUVA422P:
case AV_PIX_FMT_YUVA444P: |
ee33eb40 |
cpyresult = libopenjpeg_copy_unpacked8(avctx, frame, image); |
0275b75a |
break; |
716d413c |
case AV_PIX_FMT_GRAY16:
case AV_PIX_FMT_YUV420P9:
case AV_PIX_FMT_YUV422P9:
case AV_PIX_FMT_YUV444P9: |
b5d496f3 |
case AV_PIX_FMT_YUVA420P9:
case AV_PIX_FMT_YUVA422P9:
case AV_PIX_FMT_YUVA444P9: |
716d413c |
case AV_PIX_FMT_YUV444P10:
case AV_PIX_FMT_YUV422P10:
case AV_PIX_FMT_YUV420P10: |
b5d496f3 |
case AV_PIX_FMT_YUVA444P10:
case AV_PIX_FMT_YUVA422P10:
case AV_PIX_FMT_YUVA420P10: |
ac627b3d |
case AV_PIX_FMT_YUV420P12:
case AV_PIX_FMT_YUV422P12:
case AV_PIX_FMT_YUV444P12:
case AV_PIX_FMT_YUV420P14:
case AV_PIX_FMT_YUV422P14:
case AV_PIX_FMT_YUV444P14: |
716d413c |
case AV_PIX_FMT_YUV444P16:
case AV_PIX_FMT_YUV422P16:
case AV_PIX_FMT_YUV420P16: |
b5d496f3 |
case AV_PIX_FMT_YUVA444P16:
case AV_PIX_FMT_YUVA422P16:
case AV_PIX_FMT_YUVA420P16: |
ee33eb40 |
cpyresult = libopenjpeg_copy_unpacked16(avctx, frame, image); |
7c92c03b |
break;
default: |
453c02f9 |
av_log(avctx, AV_LOG_ERROR,
"The frame's pixel format '%s' is not supported\n",
av_get_pix_fmt_name(avctx->pix_fmt)); |
7c92c03b |
return AVERROR(EINVAL);
break;
}
if (!cpyresult) { |
56ae5926 |
av_log(avctx, AV_LOG_ERROR,
"Could not copy the frame data to the internal image buffer\n"); |
7c92c03b |
return -1;
}
|
3cfd4df8 |
cio_seek(stream, 0); |
7c92c03b |
if (!opj_encode(compress, stream, image, NULL)) {
av_log(avctx, AV_LOG_ERROR, "Error during the opj encode\n");
return -1;
}
len = cio_tell(stream); |
b222c28e |
if ((ret = ff_alloc_packet2(avctx, pkt, len)) < 0) {
return ret; |
7c92c03b |
}
|
b222c28e |
memcpy(pkt->data, stream->buffer, len);
pkt->flags |= AV_PKT_FLAG_KEY;
*got_packet = 1;
return 0; |
7c92c03b |
}
static av_cold int libopenjpeg_encode_close(AVCodecContext *avctx)
{
LibOpenJPEGContext *ctx = avctx->priv_data;
|
3cfd4df8 |
opj_cio_close(ctx->stream);
ctx->stream = NULL; |
7c92c03b |
opj_destroy_compress(ctx->compress); |
3cfd4df8 |
ctx->compress = NULL; |
7c92c03b |
opj_image_destroy(ctx->image); |
3cfd4df8 |
ctx->image = NULL; |
7c92c03b |
av_freep(&avctx->coded_frame); |
51a5ddfa |
return 0; |
7c92c03b |
}
|
67d5fcc9 |
#define OFFSET(x) offsetof(LibOpenJPEGContext, x)
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = { |
e6153f17 |
{ "format", "Codec Format", OFFSET(format), AV_OPT_TYPE_INT, { .i64 = CODEC_JP2 }, CODEC_J2K, CODEC_JP2, VE, "format" }, |
124134e4 |
{ "j2k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CODEC_J2K }, 0, 0, VE, "format" },
{ "jp2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CODEC_JP2 }, 0, 0, VE, "format" }, |
e6153f17 |
{ "profile", NULL, OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = STD_RSIZ }, STD_RSIZ, CINEMA4K, VE, "profile" }, |
124134e4 |
{ "jpeg2000", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = STD_RSIZ }, 0, 0, VE, "profile" },
{ "cinema2k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CINEMA2K }, 0, 0, VE, "profile" },
{ "cinema4k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CINEMA4K }, 0, 0, VE, "profile" }, |
e6153f17 |
{ "cinema_mode", "Digital Cinema", OFFSET(cinema_mode), AV_OPT_TYPE_INT, { .i64 = OFF }, OFF, CINEMA4K_24, VE, "cinema_mode" }, |
124134e4 |
{ "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OFF }, 0, 0, VE, "cinema_mode" },
{ "2k_24", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CINEMA2K_24 }, 0, 0, VE, "cinema_mode" },
{ "2k_48", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CINEMA2K_48 }, 0, 0, VE, "cinema_mode" },
{ "4k_24", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CINEMA4K_24 }, 0, 0, VE, "cinema_mode" }, |
e6153f17 |
{ "prog_order", "Progression Order", OFFSET(prog_order), AV_OPT_TYPE_INT, { .i64 = LRCP }, LRCP, CPRL, VE, "prog_order" }, |
124134e4 |
{ "lrcp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LRCP }, 0, 0, VE, "prog_order" },
{ "rlcp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = RLCP }, 0, 0, VE, "prog_order" },
{ "rpcl", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = RPCL }, 0, 0, VE, "prog_order" },
{ "pcrl", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PCRL }, 0, 0, VE, "prog_order" },
{ "cprl", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPRL }, 0, 0, VE, "prog_order" }, |
d46c1c72 |
{ "numresolution", NULL, OFFSET(numresolution), AV_OPT_TYPE_INT, { .i64 = 6 }, 1, INT_MAX, VE },
{ "numlayers", NULL, OFFSET(numlayers), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 10, VE },
{ "disto_alloc", NULL, OFFSET(disto_alloc), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE },
{ "fixed_alloc", NULL, OFFSET(fixed_alloc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
{ "fixed_quality", NULL, OFFSET(fixed_quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, |
67d5fcc9 |
{ NULL },
};
|
bf18abb2 |
static const AVClass openjpeg_class = { |
67d5fcc9 |
.class_name = "libopenjpeg",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
}; |
7c92c03b |
AVCodec ff_libopenjpeg_encoder = { |
0275b75a |
.name = "libopenjpeg", |
b2bed932 |
.long_name = NULL_IF_CONFIG_SMALL("OpenJPEG JPEG 2000"), |
0275b75a |
.type = AVMEDIA_TYPE_VIDEO, |
36ef5369 |
.id = AV_CODEC_ID_JPEG2000, |
7c92c03b |
.priv_data_size = sizeof(LibOpenJPEGContext), |
0275b75a |
.init = libopenjpeg_encode_init, |
b222c28e |
.encode2 = libopenjpeg_encode_frame, |
0275b75a |
.close = libopenjpeg_encode_close,
.capabilities = 0, |
716d413c |
.pix_fmts = (const enum AVPixelFormat[]) { |
ac627b3d |
AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48, AV_PIX_FMT_RGBA64, |
c58c6739 |
AV_PIX_FMT_GBR24P,
AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, |
ac627b3d |
AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A, AV_PIX_FMT_GRAY16, |
716d413c |
AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, |
ac627b3d |
AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA422P,
AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUVA444P, |
716d413c |
AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, |
b5d496f3 |
AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, |
716d413c |
AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, |
b5d496f3 |
AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, |
ac627b3d |
AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12,
AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, |
716d413c |
AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, |
b5d496f3 |
AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, |
4443213d |
AV_PIX_FMT_XYZ12, |
716d413c |
AV_PIX_FMT_NONE |
f06269dd |
}, |
bf18abb2 |
.priv_class = &openjpeg_class, |
67d5fcc9 |
}; |