[FFmpeg-devel] [PATCH] yuv pixel formats support in openjpeg decoder + 10bit support

Alex Zhukov zhukov.alex at gmail.com
Sat Nov 12 12:39:59 CET 2011


re code cleanups: see the new patch
re curly braces: i'd keep them to make further patches less in size

re rgb48, needs a little bit of context
there is no field in j2k (i know of) that tells you what color space
is used. i am guessing even if there was one people would rarely use
it.
so most of the code in check_image_attributes() is guesswork that
basically does the following:
- if component sizes are not the same its more likely to be YUV (ratio 1/2)
- if component sizes ARE the same and precision of component is 8 bit its RGB24

what do we do with higher precisions is, imho, a matter of taste,
16bpp equal component size j2k can either be YUV444P16 or RGB48.

returning PIX_FMT_YUV444P16 i made an assumption that it is more
likely to be YUV444P16, mostly because i encounter such files more
often.
tell me if you have a different experience.


On Sat, Nov 12, 2011 at 1:13 AM, Jean First <jeanfirst at gmail.com> wrote:
> On Fri Nov 11 2011 17:09:01 GMT+0100 (CET), Alex Zhukov wrote:
>>
>> rgb24 works
>>
>> On Fri, Nov 11, 2011 at 7:13 AM, Alex Zhukov<zhukov.alex at gmail.com>
>>  wrote:
>>>
>>> good point
>>> will fix
>
> [...]
>
>> From 29c626cbb5b56d7362ef34ad9751c2ee6718a997 Mon Sep 17 00:00:00 2001
>> From: Alex Zhukov <zhukov.alex at gmail.com>
>> Date: Thu, 10 Nov 2011 14:08:24 -0800
>> Subject: [PATCH] yuv pixel formats support in openjpeg decoder + 10bit
>>  support
>>
>> Signed-off-by: Alex Zhukov <zhukov.alex at gmail.com>
>> ---
>>  libavcodec/libopenjpeg.c |  161
>> ++++++++++++++++++++++++++++++++++++----------
>>  1 files changed, 126 insertions(+), 35 deletions(-)
>>
>> diff --git a/libavcodec/libopenjpeg.c b/libavcodec/libopenjpeg.c
>> index 42c71e3..0d48ad4 100644
>> --- a/libavcodec/libopenjpeg.c
>> +++ b/libavcodec/libopenjpeg.c
>> @@ -25,6 +25,7 @@
>>  */
>>
>>  #include "libavutil/imgutils.h"
>> +#include "libavutil/pixfmt.h"
>>  #include "avcodec.h"
>>  #include "libavutil/intreadwrite.h"
>>  #include "thread.h"
>> @@ -39,14 +40,105 @@ typedef struct {
>>     AVFrame image;
>>  } LibOpenJPEGContext;
>>
>> -static int check_image_attributes(opj_image_t *image)
>> +static enum PixelFormat check_image_attributes(AVCodecContext *avctx,
>> opj_image_t *image)
>>  {
>> -    return image->comps[0].dx == image->comps[1].dx &&
>> -           image->comps[1].dx == image->comps[2].dx &&
>> -           image->comps[0].dy == image->comps[1].dy &&
>> -           image->comps[1].dy == image->comps[2].dy &&
>> -           image->comps[0].prec == image->comps[1].prec &&
>> -           image->comps[1].prec == image->comps[2].prec;
>> +    opj_image_comp_t c0 = image->comps[0];
>> +    opj_image_comp_t c1 = image->comps[1];
>> +    opj_image_comp_t c2 = image->comps[2];
>> +    int compRatio = c0.dx << 15 | c0.dy << 12;
>> +    compRatio |= c1.dx << 9 | c1.dy << 6;
>> +    compRatio |= c2.dx << 3 | c2.dy << 0;
>> +
>> +    switch(compRatio) {
>> +        case 0111111: goto libopenjpeg_yuv444_rgb;
>> +        case 0112121: goto libopenjpeg_yuv422;
>> +        case 0112222: goto libopenjpeg_yuv420;
>> +        default: return PIX_FMT_RGB24;
>> +    }
>
> What about rgb48 ? Can you test it ?
>
>> +
>> +libopenjpeg_yuv420:
>> +    switch (c0.prec) {
>> +        case 8: return PIX_FMT_YUV420P;
>> +        case 9: return PIX_FMT_YUV420P9;
>> +        case 10: return PIX_FMT_YUV420P10;
>> +        case 16: return PIX_FMT_YUV420P16;
>> +    }
>> +
>> +libopenjpeg_yuv422:
>> +    switch (c0.prec) {
>> +        case 8: return PIX_FMT_YUV422P;
>> +        case 9: return PIX_FMT_YUV422P9;
>> +        case 10: return PIX_FMT_YUV422P10;
>> +        case 16: return PIX_FMT_YUV422P16;
>> +    }
>> +
>> +libopenjpeg_yuv444_rgb:
>> +    switch (c0.prec) {
>> +        case 8: return PIX_FMT_RGB24;
>> +        case 9: return PIX_FMT_YUV444P9;
>> +        case 10: return PIX_FMT_YUV444P10;
>> +        case 16: return PIX_FMT_YUV444P16;
>> +    }
>> +    return PIX_FMT_RGB24;
>> +}
>> +
>> +static inline int libopenjpeg_ispacked(enum PixelFormat pix_fmt) {
>> +    int i, component_plane;
>> +    component_plane = av_pix_fmt_descriptors[pix_fmt].comp[0].plane;
>> +    for(i=1; i < av_pix_fmt_descriptors[pix_fmt].nb_components;i++) {
>> +        if (component_plane !=
>> av_pix_fmt_descriptors[pix_fmt].comp[i].plane)
>> +            return 0;
>> +    }
>> +    return 1;
>> +}
>> +
>> +static inline void libopenjpeg_copy_to_packed8(AVFrame *picture,
>> opj_image_t *image) {
>> +    uint8_t *img_ptr;
>> +    int index, x, y, c;
>> +    for(y = 0; y < picture->height; y++) {
>> +        index = y*picture->width;
>> +        img_ptr = picture->data[0] + y*picture->linesize[0];
>> +        for(x = 0; x < picture->width; x++, index++) {
>> +            for(c = 0; c < image->numcomps; c++) {
>> +                *img_ptr++ = image->comps[c].data[index];
>> +            }
>> +        }
>> +    }
>> +}
>> +
>> +static inline void libopenjpeg_copyto8(AVFrame *picture, opj_image_t
>> *image) {
>> +    int *comp_data;
>> +    uint8_t *img_ptr;
>> +    int index, x, y;
>> +
>> +    for(index = 0; index < image->numcomps; index++) {
>> +        comp_data = image->comps[index].data;
>> +        img_ptr = picture->data[index];
>> +        for(y = 0; y < image->comps[index].h; y++) {
>> +            for(x = 0; x < image->comps[index].w; x++) {
>> +                *img_ptr = (uint8_t) *comp_data;
>> +                img_ptr++;
>> +                comp_data++;
>> +            }
>> +        }
>> +    }
>> +}
>> +
>> +static inline void libopenjpeg_copyto16(AVFrame *picture, opj_image_t
>> *image) {
>> +    int *comp_data;
>> +    uint16_t *img_ptr;
>> +    int index, x, y;
>> +    for(index = 0; index < image->numcomps; index++) {
>> +        comp_data = image->comps[index].data;
>> +        img_ptr = (uint16_t*) picture->data[index];
>> +        for(y = 0; y < image->comps[index].h; y++) {
>> +            for(x = 0; x < image->comps[index].w; x++) {
>> +                *img_ptr = *comp_data;
>> +                img_ptr++;
>> +                comp_data++;
>> +            }
>> +        }
>> +    }
>>  }
>>
>>  static av_cold int libopenjpeg_decode_init(AVCodecContext *avctx)
>> @@ -78,10 +170,9 @@ static int libopenjpeg_decode_frame(AVCodecContext
>> *avctx,
>>     opj_dinfo_t *dec;
>>     opj_cio_t *stream;
>>     opj_image_t *image;
>> -    int width, height, has_alpha = 0, ret = -1;
>> -    int x, y, index;
>> -    uint8_t *img_ptr;
>> -    int adjust[4];
>> +    int width, height, ret = -1;
>> +    int pixel_size = 0;
>> +    int ispacked = 0;
>>
>>     *data_size = 0;
>>
>> @@ -115,7 +206,7 @@ static int libopenjpeg_decode_frame(AVCodecContext
>> *avctx,
>>     }
>>
>>     // Decode the header only
>> -    image = opj_decode_with_info(dec, stream, NULL);
>> +    image = opj_decode(dec, stream);
>
> this is not needed. opj_decode calls opj_decode_with_info !
>
>>     opj_cio_close(stream);
>>     if(!image) {
>>         av_log(avctx, AV_LOG_ERROR, "Error decoding codestream.\n");
>> @@ -134,15 +225,9 @@ static int libopenjpeg_decode_frame(AVCodecContext
>> *avctx,
>>     {
>>         case 1:  avctx->pix_fmt = PIX_FMT_GRAY8;
>>                  break;
>> -        case 3:  if(check_image_attributes(image)) {
>> -                     avctx->pix_fmt = PIX_FMT_RGB24;
>> -                 } else {
>> -                     avctx->pix_fmt = PIX_FMT_GRAY8;
>> -                     av_log(avctx, AV_LOG_ERROR, "Only first component
>> will be used.\n");
>> -                 }
>> +        case 3:  avctx->pix_fmt = check_image_attributes(avctx, image);
>>                  break;
>> -        case 4:  has_alpha = 1;
>> -                 avctx->pix_fmt = PIX_FMT_RGBA;
>> +        case 4:  avctx->pix_fmt = PIX_FMT_RGBA;
>>                  break;
>>         default: av_log(avctx, AV_LOG_ERROR, "%d components
>> unsupported.\n", image->numcomps);
>>                  goto done;
>> @@ -170,25 +255,31 @@ static int libopenjpeg_decode_frame(AVCodecContext
>> *avctx,
>>     }
>>
>>     // Decode the codestream
>> -    image = opj_decode_with_info(dec, stream, NULL);
>> +    image = opj_decode(dec, stream);
>
> see above.
>
>>     opj_cio_close(stream);
>>
>> -    for(x = 0; x < image->numcomps; x++) {
>> -        adjust[x] = FFMAX(image->comps[x].prec - 8, 0);
>> -    }
>> +    pixel_size =
>> av_pix_fmt_descriptors[avctx->pix_fmt].comp[0].step_minus1+1;
>> +    ispacked = libopenjpeg_ispacked(avctx->pix_fmt);
>>
>> -    for(y = 0; y < avctx->height; y++) {
>> -        index = y*avctx->width;
>> -        img_ptr = picture->data[0] + y*picture->linesize[0];
>> -        for(x = 0; x < avctx->width; x++, index++) {
>> -            *img_ptr++ = image->comps[0].data[index] >> adjust[0];
>> -            if(image->numcomps > 2 && check_image_attributes(image)) {
>> -                *img_ptr++ = image->comps[1].data[index] >> adjust[1];
>> -                *img_ptr++ = image->comps[2].data[index] >> adjust[2];
>> -                if(has_alpha)
>> -                    *img_ptr++ = image->comps[3].data[index] >>
>> adjust[3];
>> +    switch(pixel_size) {
>> +        case 1:
>> +            if (ispacked) {
>> +                libopenjpeg_copy_to_packed8(picture, image);
>> +            } else {
>> +                libopenjpeg_copyto8(picture, image);
>>             }
>> -        }
>> +            break;
>> +        case 2:
>> +            libopenjpeg_copyto16(picture, image);
>> +            break;
>> +        case 3:
>> +            if (ispacked) {
>> +                libopenjpeg_copy_to_packed8(picture, image);
>> +            }
>> +            break;
>> +        default:
>> +            av_log(avctx, AV_LOG_ERROR, "unsupported pixel size %d\n",
>> pixel_size);
>> +            goto done;
>>     }
>>
>>     *output    = ctx->image;
>> --
>> 1.7.4.4
>>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-yuv-pixel-formats-support-in-openjpeg-decoder-10bit-.patch
Type: application/octet-stream
Size: 7555 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20111112/e907e175/attachment.obj>


More information about the ffmpeg-devel mailing list