From f7813a5324be39d13ab536c245d15dfc602a7849 Mon Sep 17 00:00:00 2001 From: Tim Redfern Date: Sun, 29 Dec 2013 12:19:38 +0000 Subject: basic type mechanism working --- ffmpeg/libavcodec/libopenjpegenc.c | 206 ++++++++++++++++++++++++++----------- 1 file changed, 147 insertions(+), 59 deletions(-) (limited to 'ffmpeg/libavcodec/libopenjpegenc.c') diff --git a/ffmpeg/libavcodec/libopenjpegenc.c b/ffmpeg/libavcodec/libopenjpegenc.c index c355083..0205c7d 100644 --- a/ffmpeg/libavcodec/libopenjpegenc.c +++ b/ffmpeg/libavcodec/libopenjpegenc.c @@ -43,6 +43,7 @@ typedef struct { AVClass *avclass; opj_image_t *image; + opj_cio_t *stream; opj_cparameters_t enc_params; opj_cinfo_t *compress; opj_event_mgr_t event_mgr; @@ -75,7 +76,7 @@ static void info_callback(const char *msg, void *data) static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *parameters) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); - opj_image_cmptparm_t *cmptparm; + opj_image_cmptparm_t cmptparm[4] = {{0}}; opj_image_t *img; int i; int sub_dx[4]; @@ -106,6 +107,7 @@ static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *p case AV_PIX_FMT_GBRP12: case AV_PIX_FMT_GBRP14: case AV_PIX_FMT_GBRP16: + case AV_PIX_FMT_XYZ12: color_space = CLRSPC_SRGB; break; case AV_PIX_FMT_YUV410P: @@ -150,23 +152,25 @@ static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *p return NULL; } - cmptparm = av_mallocz(numcomps * sizeof(*cmptparm)); - if (!cmptparm) { - av_log(avctx, AV_LOG_ERROR, "Not enough memory\n"); - return NULL; - } for (i = 0; i < numcomps; i++) { cmptparm[i].prec = desc->comp[i].depth_minus1 + 1; cmptparm[i].bpp = desc->comp[i].depth_minus1 + 1; cmptparm[i].sgnd = 0; cmptparm[i].dx = sub_dx[i]; cmptparm[i].dy = sub_dy[i]; - cmptparm[i].w = avctx->width / sub_dx[i]; - cmptparm[i].h = avctx->height / sub_dy[i]; + cmptparm[i].w = (avctx->width + sub_dx[i] - 1) / sub_dx[i]; + cmptparm[i].h = (avctx->height + sub_dy[i] - 1) / sub_dy[i]; } img = opj_image_create(numcomps, cmptparm, color_space); - av_freep(&cmptparm); + + // 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; + return img; } @@ -223,18 +227,26 @@ static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); } - avctx->coded_frame = avcodec_alloc_frame(); - if (!avctx->coded_frame) { - av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n"); - goto fail; - } - ctx->image = mj2_create_image(avctx, &ctx->enc_params); if (!ctx->image) { av_log(avctx, AV_LOG_ERROR, "Error creating the mj2 image\n"); err = AVERROR(EINVAL); goto fail; } + 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; + } + + avctx->coded_frame = av_frame_alloc(); + if (!avctx->coded_frame) { + av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n"); + goto fail; + } memset(&ctx->event_mgr, 0, sizeof(opj_event_mgr_t)); ctx->event_mgr.info_handler = info_callback; @@ -245,7 +257,12 @@ static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx) return 0; fail: - av_freep(&ctx->compress); + opj_cio_close(ctx->stream); + ctx->stream = NULL; + opj_destroy_compress(ctx->compress); + ctx->compress = NULL; + opj_image_destroy(ctx->image); + ctx->image = NULL; av_freep(&avctx->coded_frame); return err; } @@ -255,7 +272,7 @@ static int libopenjpeg_copy_packed8(AVCodecContext *avctx, const AVFrame *frame, int compno; int x; int y; - int image_index; + int *image_line; int frame_index; const int numcomps = image->numcomps; @@ -268,12 +285,62 @@ static int libopenjpeg_copy_packed8(AVCodecContext *avctx, const AVFrame *frame, for (compno = 0; compno < numcomps; ++compno) { for (y = 0; y < avctx->height; ++y) { - image_index = y * avctx->width; + image_line = image->comps[compno].data + y * image->comps[compno].w; frame_index = y * frame->linesize[0] + compno; for (x = 0; x < avctx->width; ++x) { - image->comps[compno].data[image_index++] = frame->data[0][frame_index]; + image_line[x] = frame->data[0][frame_index]; + frame_index += numcomps; + } + 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]; + } + } + } + + return 1; +} + +// for XYZ 12 bit +static int libopenjpeg_copy_packed12(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) +{ + int compno; + int x; + int y; + int *image_line; + 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) { + image_line = image->comps[compno].data + y * image->comps[compno].w; + frame_index = y * (frame->linesize[0] / 2) + compno; + for (x = 0; x < avctx->width; ++x) { + image_line[x] = frame_ptr[frame_index] >> 4; frame_index += numcomps; } + 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]; + } } } @@ -285,7 +352,7 @@ static int libopenjpeg_copy_packed16(AVCodecContext *avctx, const AVFrame *frame int compno; int x; int y; - int image_index; + int *image_line; int frame_index; const int numcomps = image->numcomps; uint16_t *frame_ptr = (uint16_t*)frame->data[0]; @@ -299,12 +366,21 @@ static int libopenjpeg_copy_packed16(AVCodecContext *avctx, const AVFrame *frame for (compno = 0; compno < numcomps; ++compno) { for (y = 0; y < avctx->height; ++y) { - image_index = y * avctx->width; + image_line = image->comps[compno].data + y * image->comps[compno].w; frame_index = y * (frame->linesize[0] / 2) + compno; for (x = 0; x < avctx->width; ++x) { - image->comps[compno].data[image_index++] = frame_ptr[frame_index]; + image_line[x] = frame_ptr[frame_index]; frame_index += numcomps; } + 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]; + } } } @@ -318,7 +394,7 @@ static int libopenjpeg_copy_unpacked8(AVCodecContext *avctx, const AVFrame *fram int y; int width; int height; - int image_index; + int *image_line; int frame_index; const int numcomps = image->numcomps; @@ -333,10 +409,19 @@ static int libopenjpeg_copy_unpacked8(AVCodecContext *avctx, const AVFrame *fram width = avctx->width / image->comps[compno].dx; height = avctx->height / image->comps[compno].dy; for (y = 0; y < height; ++y) { - image_index = y * width; + image_line = image->comps[compno].data + y * image->comps[compno].w; frame_index = y * frame->linesize[compno]; for (x = 0; x < width; ++x) - image->comps[compno].data[image_index++] = frame->data[compno][frame_index++]; + 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]; + } } } @@ -350,7 +435,7 @@ static int libopenjpeg_copy_unpacked16(AVCodecContext *avctx, const AVFrame *fra int y; int width; int height; - int image_index; + int *image_line; int frame_index; const int numcomps = image->numcomps; uint16_t *frame_ptr; @@ -367,10 +452,19 @@ static int libopenjpeg_copy_unpacked16(AVCodecContext *avctx, const AVFrame *fra height = avctx->height / image->comps[compno].dy; frame_ptr = (uint16_t*)frame->data[compno]; for (y = 0; y < height; ++y) { - image_index = y * width; + image_line = image->comps[compno].data + y * image->comps[compno].w; frame_index = y * (frame->linesize[compno] / 2); for (x = 0; x < width; ++x) - image->comps[compno].data[image_index++] = frame_ptr[frame_index++]; + 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]; + } } } @@ -383,17 +477,10 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, LibOpenJPEGContext *ctx = avctx->priv_data; opj_cinfo_t *compress = ctx->compress; opj_image_t *image = ctx->image; - opj_cio_t *stream; + opj_cio_t *stream = ctx->stream; int cpyresult = 0; int ret, len; - AVFrame gbrframe; - - // x0, y0 is the top left corner of the image - // x1, y1 is the width, height of the reference grid - image->x0 = 0; - image->y0 = 0; - image->x1 = (avctx->width - 1) * ctx->enc_params.subsampling_dx + 1; - image->y1 = (avctx->height - 1) * ctx->enc_params.subsampling_dy + 1; + AVFrame *gbrframe; switch (avctx->pix_fmt) { case AV_PIX_FMT_RGB24: @@ -401,6 +488,9 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, case AV_PIX_FMT_GRAY8A: cpyresult = libopenjpeg_copy_packed8(avctx, frame, image); break; + case AV_PIX_FMT_XYZ12: + cpyresult = libopenjpeg_copy_packed12(avctx, frame, image); + break; case AV_PIX_FMT_RGB48: case AV_PIX_FMT_RGBA64: cpyresult = libopenjpeg_copy_packed16(avctx, frame, image); @@ -411,18 +501,20 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, case AV_PIX_FMT_GBRP12: case AV_PIX_FMT_GBRP14: case AV_PIX_FMT_GBRP16: - gbrframe = *frame; - 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]; + gbrframe = av_frame_alloc(); + av_frame_ref(gbrframe, frame); + 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]; if (avctx->pix_fmt == AV_PIX_FMT_GBR24P) { - cpyresult = libopenjpeg_copy_unpacked8(avctx, &gbrframe, image); + cpyresult = libopenjpeg_copy_unpacked8(avctx, gbrframe, image); } else { - cpyresult = libopenjpeg_copy_unpacked16(avctx, &gbrframe, image); + cpyresult = libopenjpeg_copy_unpacked16(avctx, gbrframe, image); } + av_frame_free(&gbrframe); break; case AV_PIX_FMT_GRAY8: case AV_PIX_FMT_YUV410P: @@ -477,29 +569,20 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return -1; } - opj_setup_encoder(compress, &ctx->enc_params, image); - stream = opj_cio_open((opj_common_ptr)compress, NULL, 0); - if (!stream) { - av_log(avctx, AV_LOG_ERROR, "Error creating the cio stream\n"); - return AVERROR(ENOMEM); - } - + cio_seek(stream, 0); if (!opj_encode(compress, stream, image, NULL)) { - opj_cio_close(stream); av_log(avctx, AV_LOG_ERROR, "Error during the opj encode\n"); return -1; } len = cio_tell(stream); if ((ret = ff_alloc_packet2(avctx, pkt, len)) < 0) { - opj_cio_close(stream); return ret; } memcpy(pkt->data, stream->buffer, len); pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; - opj_cio_close(stream); return 0; } @@ -507,8 +590,12 @@ static av_cold int libopenjpeg_encode_close(AVCodecContext *avctx) { LibOpenJPEGContext *ctx = avctx->priv_data; + opj_cio_close(ctx->stream); + ctx->stream = NULL; opj_destroy_compress(ctx->compress); + ctx->compress = NULL; opj_image_destroy(ctx->image); + ctx->image = NULL; av_freep(&avctx->coded_frame); return 0; } @@ -542,7 +629,7 @@ static const AVOption options[] = { { NULL }, }; -static const AVClass class = { +static const AVClass openjpeg_class = { .class_name = "libopenjpeg", .item_name = av_default_item_name, .option = options, @@ -551,6 +638,7 @@ static const AVClass class = { AVCodec ff_libopenjpeg_encoder = { .name = "libopenjpeg", + .long_name = NULL_IF_CONFIG_SMALL("OpenJPEG JPEG 2000"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_JPEG2000, .priv_data_size = sizeof(LibOpenJPEGContext), @@ -574,8 +662,8 @@ AVCodec ff_libopenjpeg_encoder = { AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_XYZ12, AV_PIX_FMT_NONE }, - .long_name = NULL_IF_CONFIG_SMALL("OpenJPEG JPEG 2000"), - .priv_class = &class, + .priv_class = &openjpeg_class, }; -- cgit v1.2.3