[FFmpeg-devel] EXR patch to read layers
Gonzalo Garramuno
ggarra13 at gmail.com
Sun Feb 16 00:50:24 CET 2014
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 Normals -i myexr.%04d.exr test.mov
-------------- next part --------------
diff --git a/libavcodec/exr.c b/libavcodec/exr.c
index f231b70..b96f17f 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,16 +1008,28 @@ static int decode_frame(AVCodecContext *avctx,
int channel_index = -1;
int xsub, ysub;
- if (!strcmp(buf, "R"))
- channel_index = 0;
- else if (!strcmp(buf, "G"))
- channel_index = 1;
- else if (!strcmp(buf, "B"))
- channel_index = 2;
- else if (!strcmp(buf, "A"))
- channel_index = 3;
+ 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(b, "G")||!strcmp(b, "Y")||!strcmp(b,"V"))
+ channel_index = 1;
+ else if (!strcmp(b, "B")||!strcmp(b, "Z")||!strcmp(b,"W"))
+ channel_index = 2;
+ else if (!strcmp(b, "A"))
+ channel_index = 3;
else
- av_log(avctx, AV_LOG_WARNING, "Unsupported channel %.256s\n", buf);
+ av_log(avctx, AV_LOG_WARNING, "Unsupported channel %.256s\n", buf);
while (bytestream_get_byte(&buf) && buf < channel_list_end)
continue; /* skip */
@@ -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,
};
More information about the ffmpeg-devel
mailing list