From 3d20260157cb65582cb547befe744b9cbfaeac1d Mon Sep 17 00:00:00 2001 From: Gonzalo Garramuno Date: Mon, 17 Feb 2014 14:53:30 -0300 Subject: [PATCH] avcodec/exr: read layers EXR files have, like tiffs, multiple channels and layers. I have a patch for exr.c that allows you to select the layer you want to process thru a -layer flag. It is not bulletproof but works for all layers that have 3 channels in them (normals, motion vectors, etc). The calling convention for ffmpeg is: ffmpeg -layer Diffuse -i myexr.%d.exr test.mov Here's an exr image with multiple layers: http://www.datafilehost.com/d/e45d9a1c Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer --- libavcodec/exr.c | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index f231b70375..77247fcb81 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -40,6 +40,7 @@ #include "thread.h" #include "libavutil/imgutils.h" #include "libavutil/avassert.h" +#include "libavutil/opt.h" enum ExrCompr { EXR_RAW = 0, @@ -75,6 +76,7 @@ typedef struct EXRThreadData { } EXRThreadData; typedef struct EXRContext { + AVClass *class; AVFrame *picture; int compr; enum ExrPixelType pixel_type; @@ -98,8 +100,24 @@ typedef struct EXRContext { EXRThreadData *thread_data; int thread_data_size; + + const char* layer; } EXRContext; +#define OFFSET(x) offsetof(EXRContext, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "layer", "Set the decoding layer", OFFSET(layer), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VD}, + { NULL }, +}; + +static const AVClass exr_class = { + .class_name = "EXR", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + /** * Converts from 32-bit float as uint32_t to uint16_t * @@ -990,13 +1008,25 @@ static int decode_frame(AVCodecContext *avctx, int channel_index = -1; int xsub, ysub; - if (!strcmp(buf, "R")) + const char* b = buf; + + if ( strcmp( s->layer, "" ) != 0 ) { + if ( strncmp( b, s->layer, strlen(s->layer) ) == 0 ) { + b += strlen(s->layer); + if ( *b == '.' ) ++b; /* skip dot if not given */ + av_log( avctx, AV_LOG_INFO, "Layer %s.%s matched\n", + s->layer, b ); + } + } + + + if (!strcmp(b, "R")||!strcmp(b, "X")||!strcmp(b,"U")) channel_index = 0; - else if (!strcmp(buf, "G")) + else if (!strcmp(b, "G")||!strcmp(b, "Y")||!strcmp(b,"V")) channel_index = 1; - else if (!strcmp(buf, "B")) + else if (!strcmp(b, "B")||!strcmp(b, "Z")||!strcmp(b,"W")) channel_index = 2; - else if (!strcmp(buf, "A")) + else if (!strcmp(b, "A")) channel_index = 3; else av_log(avctx, AV_LOG_WARNING, "Unsupported channel %.256s\n", buf); @@ -1275,4 +1305,5 @@ AVCodec ff_exr_decoder = { .close = decode_end, .decode = decode_frame, .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS | CODEC_CAP_SLICE_THREADS, + .priv_class = &exr_class, };