[vlc-devel] [PATCH 2/3] Add CineForm decoding/encoding plugin

Emeric Grange emeric.grange at gmail.com
Tue Aug 28 16:23:47 CEST 2018


From: Emeric <emeric.grange at gmail.com>

---
 modules/codec/Makefile.am                  |  11 +
 modules/codec/cineform/cineform_plugin.c   | 796 +++++++++++++++++++++
 modules/codec/cineform/cineform_plugin.h   | 136 ++++
 modules/codec/cineform/cineform_settings.c | 402 +++++++++++
 modules/codec/cineform/cineform_settings.h |  91 +++
 5 files changed, 1436 insertions(+)
 create mode 100755 modules/codec/cineform/cineform_plugin.c
 create mode 100755 modules/codec/cineform/cineform_plugin.h
 create mode 100755 modules/codec/cineform/cineform_settings.c
 create mode 100755 modules/codec/cineform/cineform_settings.h

diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am
index 9f0b9bf4bb..fbffbf2047 100644
--- a/modules/codec/Makefile.am
+++ b/modules/codec/Makefile.am
@@ -130,6 +130,17 @@ EXTRA_LTLIBRARIES += libschroedinger_plugin.la
 codec_LTLIBRARIES += $(LTLIBschroedinger)
 
 
+libcineform_plugin_la_SOURCES = dummy.cpp \
+    codec/cineform/cineform_plugin.c codec/cineform/cineform_plugin.h \
+    codec/cineform/cineform_settings.c codec/cineform/cineform_settings.h
+libcineform_plugin_la_CFLAGS = $(AM_CFLAGS) $(CFLAGS_cineform)
+libcineform_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_cineform)
+libcineform_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(codecdir)'
+libcineform_plugin_la_LIBADD = $(LIBS_cineform)
+EXTRA_LTLIBRARIES += libcineform_plugin.la
+codec_LTLIBRARIES += $(LTLIBcineform)
+
+
 ### Image codecs ###
 
 libpng_plugin_la_SOURCES = codec/png.c
diff --git a/modules/codec/cineform/cineform_plugin.c b/modules/codec/cineform/cineform_plugin.c
new file mode 100755
index 0000000000..0a05528c35
--- /dev/null
+++ b/modules/codec/cineform/cineform_plugin.c
@@ -0,0 +1,796 @@
+/*****************************************************************************
+ * cineform_plugin.c : CineForm decoder and encoder
+ *****************************************************************************
+ * Copyright (C) 2018 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Emeric Grange <emeric.grange at gmail.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include "cineform_plugin.h"
+#include "cineform_settings.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <time.h>
+#include <math.h>
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+
+vlc_module_begin ()
+
+    set_category(CAT_INPUT)
+    set_subcategory(SUBCAT_INPUT_VCODEC)
+
+    // Description
+    set_shortname("CineForm")
+    set_help(N_("GoPro CineForm SDK decoding/encoding plugin"))
+
+    set_capability("video decoder", 100)
+    set_description(N_("CineForm decoding plugin"))
+    set_callbacks(OpenDecoder, CloseDecoder)
+    add_shortcut("cineform")
+
+    // User defined settings
+    set_section("Decoding", NULL)
+    add_string("cineform-output-formats", "AUTO",
+               OUTPUT_FORMATS_TEXT, OUTPUT_FORMATS_LONGTEXT, false)
+        vlc_config_set(VLC_CONFIG_LIST, (sizeof(output_formats) / sizeof(char*)) - 1,
+                       output_formats, output_formats);
+    add_string("cineform-decoding-resolutions", "FULL RESOLUTION",
+               DECODING_RESOLUTIONS_TEXT, DECODING_RESOLUTIONS_LONGTEXT, false)
+        vlc_config_set(VLC_CONFIG_LIST, (sizeof(decoding_resolutions) / sizeof(char*)) - 1,
+                       decoding_resolutions, decoding_resolutions);
+    add_string("cineform-decoding-flags", "NONE",
+               DECODING_FLAGS_TEXT, DECODING_FLAGS_LONGTEXT, false)
+        vlc_config_set(VLC_CONFIG_LIST, (sizeof(decoding_flags) / sizeof(char*)) - 1,
+                       decoding_flags, decoding_flags);
+    add_string("cineform-stereo-select", "DEFAULT",
+               STEREO_SELECT_TEXT, STEREO_SELECT_LONGTEXT, false)
+        vlc_config_set(VLC_CONFIG_LIST, (sizeof(stereo_select) / sizeof(char*)) - 1,
+                       stereo_select, stereo_select);
+    add_string("cineform-stereo-type", "DEFAULT",
+               STEREO_TYPE_TEXT, STEREO_TYPE_LONGTEXT, false)
+        vlc_config_set(VLC_CONFIG_LIST, (sizeof(stereo_type) / sizeof(char*)) - 1,
+                       stereo_type, stereo_type);
+    add_string("cineform-stereo-flags", "DEFAULT",
+               STEREO_FLAGS_TEXT, STEREO_FLAGS_LONGTEXT, false)
+        vlc_config_set(VLC_CONFIG_LIST, (sizeof(stereo_flags) / sizeof(char*)) - 1,
+                       stereo_flags, stereo_flags);
+
+#ifdef ENABLE_SOUT
+    add_submodule()
+
+    set_capability("encoder", 150)
+    set_description(N_("CineForm encoding plugin"))
+    set_callbacks(OpenEncoder, CloseEncoder)
+    add_shortcut("cineform")
+
+    // User defined settings
+    set_section(N_("Encoding"), NULL)
+    add_string("cineform-encoding-format", "YUV 4:2:2",
+               ENCODING_FORMAT_TEXT, ENCODING_FORMAT_LONGTEXT, false)
+        vlc_config_set(VLC_CONFIG_LIST, (sizeof(encoding_format) / sizeof(char*)) - 1,
+                       encoding_format, encoding_format);
+    add_string("cineform-encoding-quality", "MEDIUM",
+               ENCODING_QUALITY_TEXT, ENCODING_QUALITY_LONGTEXT, false)
+        vlc_config_set(VLC_CONFIG_LIST, (sizeof(encoding_quality) / sizeof(char*)) - 1,
+                       encoding_quality, encoding_quality);
+    add_string("cineform-encoding-flags", "NONE",
+               ENCODING_FLAGS_TEXT, ENCODING_FLAGS_LONGTEXT, false)
+        vlc_config_set(VLC_CONFIG_LIST, (sizeof(encoding_flags) / sizeof(char*)) - 1,
+                       encoding_flags, encoding_flags);
+#endif
+
+vlc_module_end ()
+
+/*****************************************************************************
+ * Common
+ *****************************************************************************/
+
+static const char *getErrorString(const CFHD_Error error)
+{
+    switch (error)
+    {
+    case CFHD_ERROR_OKAY:
+        return "OKAY";
+
+    case CFHD_ERROR_INVALID_ARGUMENT:
+        return "INVALID ARGUMENT";
+    case CFHD_ERROR_OUTOFMEMORY:
+        return "OUT OF MEMORY";
+    case CFHD_ERROR_BADFORMAT:
+        return "BAD FORMAT";
+    case CFHD_ERROR_BADSCALING:
+        return "BAD SCALING";
+    case CFHD_ERROR_BADSAMPLE:
+        return "BAD SAMPLE";
+    case CFHD_ERROR_INTERNAL:
+        return "INTERNAL ERROR";
+    case CFHD_ERROR_METADATA_CLASS:
+        return "METADATA CLASS";
+    case CFHD_ERROR_METADATA_UNDEFINED:
+        return "METADATA UNDEFINED";
+    case CFHD_ERROR_METADATA_END:
+        return "METADATA END";
+    case CFHD_ERROR_UNEXPECTED:
+        return "UNEXPECTED ERROR";
+    case CFHD_ERROR_BAD_RESOLUTION:
+        return "BAD RESOLUTION";
+    case CFHD_ERROR_BAD_PIXEL_SIZE:
+        return "BAD PIXEL SIZE";
+    case CFHD_ERROR_NOT_FINISHED:
+        return "NOT FINISHED";
+    case CFHD_ERROR_ENCODING_NOT_STARTED:
+        return "NOT STARTED";
+    case CFHD_ERROR_METADATA_ATTACHED:
+        return "METADATA ATTACHED";
+    case CFHD_ERROR_BAD_METADATA:
+        return "BAD METADATA";
+    case CFHD_ERROR_THREAD_CREATE_FAILED:
+        return "THREAD CREATE FAILED";
+    case CFHD_ERROR_THREAD_WAIT_FAILED:
+        return "THREAD WAIT FAILED";
+    case CFHD_ERROR_UNKNOWN_TAG:
+        return "UNKNOWN TAG";
+    case CFHD_ERROR_LICENSING:
+        return "LICENSING ERROR";
+
+    // Error codes returned by the codec library
+    case CFHD_ERROR_CODEC_ERROR:
+        return "CODEC ERROR";
+    case CFHD_ERROR_DECODE_BUFFER_SIZE:
+        return "DECODE BUFFER SIZE ERROR";
+
+    // Error codes used by the sample code distributed with the codec SDK
+    case CFHD_ERROR_SAMPLE_CODE:
+        return "SAMPLE CODE ERROR";
+    case CFHD_ERROR_FILE_CREATE:
+        return "FILE CREATE ERROR";
+    case CFHD_ERROR_FILE_OPEN:
+        return "FILE OPEN ERROR";
+    case CFHD_ERROR_BADFILE:
+        return "BAD FILE";
+    case CFHD_ERROR_READ_FAILURE:
+        return "READ FAILURE";
+    case CFHD_ERROR_WRITE_FAILURE:
+        return "WRITE FAILURE";
+    case CFHD_ERROR_FILE_SIZE:
+        return "FILE SIZE ERROR";
+    case CFHD_ERROR_END_OF_FILE:
+        return "END OF FILE";
+    case CFHD_ERROR_END_OF_DATABASE:
+        return "END OF DATABASE";
+    case CFHD_ERROR_THREAD:
+        return "THREAD ERROR";
+
+    default:
+        return "UNKNOW ERROR";
+    }
+}
+
+/*****************************************************************************
+ * Decoder
+ *****************************************************************************/
+
+int OpenDecoder(vlc_object_t *obj)
+{
+    decoder_t *p_dec = (decoder_t*)obj;
+    decoder_sys_t *p_sys = NULL;
+
+    if (p_dec->fmt_in.i_codec != VLC_CODEC_CINEFORM)
+    {
+        return VLC_EGENERIC;
+    }
+
+    // Init decoder_sys_t // Allocate the memory needed to store the decoder's private context
+    if ((p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(*p_sys))) == NULL)
+    {
+        msg_Err(p_dec, "CineForm decoding plugin (unable to allocate internal decoding structure)");
+        return VLC_ENOMEM;
+    }
+
+    // Set VLC output properties
+    p_dec->fmt_out.i_cat = VIDEO_ES;
+
+    // Register VLC decoding callback
+    p_dec->pf_decode = DecodeVideo;
+
+    // Init decoder_sys_t content
+    p_sys->SDKversion = 0;
+    p_sys->SAMPLEversion = 0;
+
+    p_sys->sampleCount = 0;
+    p_sys->sampleDecoded = 0;
+    p_sys->sampleFailed = 0;
+
+    p_sys->sourceWidth = 0;
+    p_sys->sourceHeight = 0;
+    p_sys->sourceChannels = 0;
+    p_sys->sourcePixelSize = 0;
+    p_sys->sourcePixelFormat = CFHD_ENCODED_FORMAT_YUV_422;
+
+    p_sys->decFormatAuto = false;
+    p_sys->decSize = getDecodingResolutions(p_dec);
+    p_sys->decFlags = getDecodingFlags(p_dec);
+    p_sys->decFormat = getOutputFormats(p_dec, p_sys);
+
+    p_sys->stereo3Dtype = getStereoType(p_dec);
+    p_sys->stereoFlags = getStereoFlags(p_dec);
+    p_sys->stereoChannelSelection = getStereoSelect(p_dec);
+
+    // Init CineForm decoder
+    CFHD_Error errorCode = CFHD_OpenDecoder(&(p_sys->decoderRef), NULL);
+    if (errorCode)
+    {
+        msg_Err(p_dec, "CFHD_OpenDecoder(error %i / %s)", errorCode, getErrorString(errorCode));
+        return VLC_EGENERIC;
+    }
+
+    // Open an interface to the CineForm metadata
+    errorCode = CFHD_OpenMetadata(&(p_sys->metadataRef));
+    if (errorCode)
+    {
+        msg_Err(p_dec, "CFHD_OpenMetadata(error %i / %s)", errorCode, getErrorString(errorCode));
+        return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+
+void CloseDecoder(vlc_object_t *obj)
+{
+    decoder_t *p_dec = (decoder_t*)obj;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    if (p_sys)
+    {
+        CFHD_CloseDecoder(p_sys->decoderRef);
+        CFHD_CloseMetadata(p_sys->metadataRef);
+
+        free(p_sys);
+    }
+}
+
+int DecodeVideo(decoder_t *p_dec, block_t *p_block)
+{
+    if (p_block == NULL) /* No Drain */
+        return VLCDEC_SUCCESS;
+
+    picture_t *p_pic = DecodeBlock(p_dec, &p_block);
+    if (p_pic != NULL)
+        decoder_QueueVideo(p_dec, p_pic);
+
+    return VLCDEC_SUCCESS;
+}
+
+picture_t *DecodeBlock(decoder_t *p_dec, block_t **pp_block)
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    block_t *p_block;
+    CFHD_Error errorCode = CFHD_ERROR_OKAY;
+
+    if (!pp_block || !*pp_block)
+        return NULL;
+
+    p_block = *pp_block;
+    if (p_block->i_flags & (BLOCK_FLAG_CORRUPTED))
+    {
+        block_Release(p_block);
+        return VLCDEC_SUCCESS;
+    }
+
+    // We have a block
+    p_sys->sampleCount++;
+
+    // Packet handling
+    cf_packet_t packet;
+    packet.sampleData = p_block->p_buffer;
+    packet.sampleSize = p_block->i_buffer;
+    packet.samplePTS  = p_block->i_dts;
+
+    // Prepare decoding process
+    if (p_sys->sampleDecoded == 0)
+    {
+        if (p_sys->sampleDecoded == 0)
+        {
+            int SDKversion = 0;
+            errorCode = CFHD_GetSampleInfo(p_sys->decoderRef, packet.sampleData, packet.sampleSize,
+                                           CFHD_SAMPLE_SDK_VERSION, &SDKversion, sizeof(SDKversion));
+            if (errorCode != CFHD_ERROR_OKAY)
+            {
+                // not critical...
+                msg_Warn(p_dec, "CFHD_GetSampleInfo(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+            }
+            if (SDKversion)
+            {
+                msg_Dbg(p_dec, "CineForm SDK version used = %d.%d.%d", (SDKversion >> 16) & 0xFF, (SDKversion >> 8) & 0xFF, (SDKversion) & 0xFF);
+                p_sys->SDKversion = SDKversion;
+            }
+
+            int SAMPLEversion = 0;
+            errorCode = CFHD_GetSampleInfo(p_sys->decoderRef, packet.sampleData, packet.sampleSize,
+                                           CFHD_SAMPLE_ENCODE_VERSION, &SAMPLEversion, sizeof(SAMPLEversion));
+            if (errorCode != CFHD_ERROR_OKAY)
+            {
+                // not critical...
+                msg_Warn(p_dec, "CFHD_GetSampleInfo(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+            }
+            if (SAMPLEversion)
+            {
+                msg_Dbg(p_dec, "CineForm SDK version used = %d.%d.%d", (SAMPLEversion >> 16) & 0xFF, (SAMPLEversion >> 8) & 0xFF, (SAMPLEversion) & 0xFF);
+                p_sys->SAMPLEversion = SAMPLEversion;
+            }
+        }
+
+        // Get various infos from the current sample, choose buffer formats, and then initialize the decoder
+        errorCode = prepareDecoding(p_dec, p_sys, &packet);
+        if (errorCode)
+        {
+            msg_Err(p_dec, "getSampleInfos(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+            return NULL;
+        }
+    }
+
+    // Ask VLC for a picture buffer
+    if (decoder_UpdateVideoFormat(p_dec))
+        return NULL;
+
+    picture_t *p_pic = decoder_NewPicture(p_dec);
+    if (p_pic == NULL)
+        return NULL;
+
+    if (!p_pic)
+    {
+        msg_Err(p_dec, "CineForm DECODER plugin (unable to get an %i * %i picture_t output buffer)",
+                p_dec->fmt_out.video.i_width, p_dec->fmt_out.video.i_height);
+        goto error;
+    }
+    else
+    {
+        p_pic->date = packet.samplePTS;
+    }
+
+    // Use the CineForm SDK to do the decoding into the VLC picture_t
+    errorCode = CFHD_DecodeSample(p_sys->decoderRef,
+                                  packet.sampleData, packet.sampleSize,
+                                  p_pic->p[0].p_pixels, p_pic->p[0].i_pitch);
+    if (errorCode != CFHD_ERROR_OKAY)
+    {
+        msg_Err(p_dec, "CFHD_DecodeSample(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+        goto error;
+    }
+
+    block_Release(p_block);
+    *pp_block = NULL;
+
+    p_sys->sampleDecoded++;
+    return p_pic;
+
+error:
+    p_sys->sampleFailed++;
+    if (p_block)
+    {
+        block_Release(p_block);
+        *pp_block = NULL;
+    }
+    return NULL;
+}
+
+CFHD_Error prepareDecoding(decoder_t *p_dec, decoder_sys_t *p_sys, cf_packet_t *packet)
+{
+    CFHD_Error errorCode = CFHD_ERROR_OKAY;
+
+    // Get channel(s) count
+    errorCode = CFHD_GetSampleInfo(p_sys->decoderRef, packet->sampleData, packet->sampleSize,
+                                   CFHD_SAMPLE_INFO_CHANNELS, &(p_sys->sourceChannels), sizeof(p_sys->sourceChannels));
+    if (errorCode)
+    {
+        msg_Err(p_dec, "CFHD_GetSampleInfo(CFHD_SAMPLE_INFO_CHANNELS)(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+        return errorCode;
+    }
+    else
+    {
+        if (p_sys->sourceChannels < 1)
+        {
+            p_sys->sourceChannels = 1;
+        }
+        else if (p_sys->sourceChannels > 1)
+        {
+            msg_Warn(p_dec, "This video has more than one video channel (3d video?) and it's not supported.");
+        }
+    }
+
+    // Get display width and height
+    errorCode = CFHD_GetSampleInfo(p_sys->decoderRef, packet->sampleData, packet->sampleSize,
+                                   CFHD_SAMPLE_DISPLAY_WIDTH, &(p_sys->sourceVisibleWidth), sizeof(p_sys->sourceVisibleWidth));
+    if (errorCode)
+    {
+        msg_Err(p_dec, "CFHD_GetSampleInfo(CFHD_SAMPLE_DISPLAY_WIDTH)(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+        return errorCode;
+    }
+
+    errorCode = CFHD_GetSampleInfo(p_sys->decoderRef, packet->sampleData, packet->sampleSize,
+                                   CFHD_SAMPLE_DISPLAY_HEIGHT, &(p_sys->sourceVisibleHeight), sizeof(p_sys->sourceVisibleHeight));
+    if (errorCode)
+    {
+        msg_Err(p_dec, "CFHD_GetSampleInfo(CFHD_SAMPLE_DISPLAY_HEIGHT)(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+        return errorCode;
+    }
+
+    // Get internal encoding format
+    errorCode = CFHD_GetSampleInfo(p_sys->decoderRef, packet->sampleData, packet->sampleSize,
+                                   CFHD_SAMPLE_ENCODED_FORMAT, &(p_sys->sourcePixelFormat), sizeof(p_sys->sourcePixelFormat));
+    if (errorCode)
+    {
+        msg_Err(p_dec, "CFHD_GetSampleInfo(CFHD_SAMPLE_ENCODED_FORMAT)(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+        return errorCode;
+    }
+    else
+    {
+        // Old CineForm SDKs return CFHD_EncodedFormat differently, let's fix that
+        if (p_sys->SDKversion == 0 && p_sys->sourcePixelFormat)
+        {
+            switch ((int)p_sys->sourcePixelFormat)
+            {
+                case 1: p_sys->sourcePixelFormat = CFHD_ENCODED_FORMAT_YUV_422; break;
+                case 2: p_sys->sourcePixelFormat = CFHD_ENCODED_FORMAT_BAYER; break;
+                case 3: p_sys->sourcePixelFormat = CFHD_ENCODED_FORMAT_RGB_444; break;
+                case 4: p_sys->sourcePixelFormat = CFHD_ENCODED_FORMAT_RGBA_4444; break;
+            }
+        }
+    }
+
+    // Autodetect best buffer format combination (now that we got the internal encoding format)
+    if (p_sys->decFormatAuto == true ||
+        p_sys->decFormat == CFHD_PIXEL_FORMAT_UNKNOWN)
+    {
+        // Adjust VLC output format depending on video characteristics AND CineForm plugin settings
+        if (p_sys->sourcePixelFormat == CFHD_ENCODED_FORMAT_YUV_422)
+        {
+            p_sys->decFormat = CFHD_PIXEL_FORMAT_YUYV;
+            p_dec->fmt_out.i_codec = VLC_CODEC_YUYV;
+        }
+        else if (p_sys->sourcePixelFormat == CFHD_ENCODED_FORMAT_RGB_444 ||
+                 p_sys->sourcePixelFormat == CFHD_ENCODED_FORMAT_RGBA_4444)
+        {
+            p_sys->decFormat = CFHD_PIXEL_FORMAT_BGRa;
+            p_dec->fmt_out.i_codec = VLC_CODEC_BGRA;
+        }
+        else if (p_sys->sourcePixelFormat == CFHD_ENCODED_FORMAT_BAYER ||
+                 p_sys->sourcePixelFormat == CFHD_ENCODED_FORMAT_YUVA_4444)
+        {
+            p_sys->decFormat = CFHD_PIXEL_FORMAT_BGRa;
+            p_dec->fmt_out.i_codec = VLC_CODEC_BGRA;
+        }
+    }
+
+    // Get sample size/format infos
+    errorCode = CFHD_PrepareToDecode(p_sys->decoderRef,
+                                     0, 0, // do not use CineForm SDK internal scaler
+                                     p_sys->decFormat,
+                                     p_sys->decSize,
+                                     p_sys->decFlags,
+                                     packet->sampleData,
+                                     packet->sampleSize,
+                                     &(p_sys->sourceWidth),
+                                     &(p_sys->sourceHeight),
+                                     &(p_sys->internalBufferPixelFormat));
+    if (errorCode)
+    {
+        if (errorCode == CFHD_ERROR_BADFORMAT)
+        {
+            // Fallback
+            p_dec->fmt_out.i_codec = VLC_CODEC_BGRA;
+            p_sys->decFormat = CFHD_PIXEL_FORMAT_BGRa;
+        }
+
+        msg_Err(p_dec, "CFHD_PrepareToDecode(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+        return errorCode;
+    }
+
+    // Get the size of ONE pixel
+    errorCode = CFHD_GetPixelSize(p_sys->internalBufferPixelFormat, &(p_sys->sourcePixelSize));
+    if (errorCode)
+    {
+        msg_Err(p_dec, "CFHD_GetPixelSize(error: %i)", errorCode);
+        return errorCode;
+    }
+
+    // To decode CineForm footage, the frame width must be evenly divisible by 16 and the frame height by 8.
+    // Dimensions that do not meet these requirements are automatically rounded to a valid value.
+
+    if (p_sys->sourceWidth % 16 != 0 || p_sys->sourceHeight % 8 != 0)
+    {
+        msg_Warn(p_dec, "CineForm video width is not a multiple of 16");
+        p_sys->internalBufferWidth = ceil((double)(p_sys->sourceWidth) / 16.0) * 16;
+        p_sys->internalBufferPitch = (p_sys->internalBufferWidth) * p_sys->sourcePixelSize;
+    }
+    else
+    {
+        // Get buffer pitch and round the pitch to a multiple of 16 bytes
+        p_sys->internalBufferWidth = p_sys->sourceWidth;
+        p_sys->internalBufferPitch = p_sys->sourceWidth * p_sys->sourcePixelSize;
+        p_sys->internalBufferPitch = ((p_sys->internalBufferPitch + 0x0F) & ~0x0F);
+    }
+
+    if (p_sys->sourceHeight % 8 != 0)
+    {
+        msg_Warn(p_dec, "CineForm video height is not a multiple of 8");
+        p_sys->internalBufferHeight = ceil((double)(p_sys->sourceHeight) / 8.0) * 8;
+    }
+    else
+    {
+        p_sys->internalBufferHeight = p_sys->sourceHeight;
+    }
+
+    // Get buffer size
+    p_sys->internalBufferSizeComputed = p_sys->internalBufferPitch * p_sys->internalBufferHeight;
+
+    // Set VLC output properties
+    p_dec->fmt_out.i_cat = VIDEO_ES;
+    p_dec->fmt_out.video.i_width = p_sys->internalBufferWidth;
+    p_dec->fmt_out.video.i_height = p_sys->internalBufferHeight;
+    p_dec->fmt_out.video.i_visible_width = p_sys->sourceWidth;
+    p_dec->fmt_out.video.i_visible_height = p_sys->sourceHeight;
+
+    return errorCode;
+}
+
+/*****************************************************************************
+ * Encoder
+ *****************************************************************************/
+#ifdef ENABLE_SOUT
+int OpenEncoder(vlc_object_t *obj)
+{
+    encoder_t *p_enc = (encoder_t *)obj;
+    encoder_sys_t *p_sys = NULL;
+
+    if (p_enc->fmt_out.i_codec != VLC_CODEC_CINEFORM &&
+        !p_enc->obj.force)
+    {
+        return VLC_EGENERIC;
+    }
+
+    p_enc->fmt_out.i_cat = VIDEO_ES;
+    p_enc->fmt_out.i_codec = VLC_CODEC_CINEFORM;
+    p_enc->fmt_in.i_codec = VLC_CODEC_YUYV;
+
+    // Init encoder_sys_t // Allocate the memory needed to store the encoder's private context
+    if ((p_enc->p_sys = p_sys = malloc(sizeof(*p_sys))) == NULL)
+    {
+        msg_Err(p_enc, "CineForm encoding plugin (unable to allocate internal encoding context)");
+        return VLC_ENOMEM;
+    }
+
+    // Register settings
+    config_ChainParse(p_enc, ENC_CFG_PREFIX, enc_cfg_options, p_enc->p_cfg);
+
+    // Register encoding callback
+    p_enc->pf_encode_video = EncodeBlock;
+
+    // Init encoder_sys_t content
+    p_sys->SDKversion = 0;
+    p_sys->SAMPLEversion = 0;
+    p_sys->sampleCount = 0;
+
+    p_sys->encFormat = getEncodingFormat(p_enc);
+    p_sys->encQuality = getEncodingQuality(p_enc);
+    p_sys->encFlags = getEncodingFlags(p_enc);
+
+    p_sys->videoWidth = p_enc->fmt_in.video.i_visible_width;
+    p_sys->videoHeight = p_enc->fmt_in.video.i_visible_height;
+    p_sys->videoChannels = 1; // 3d not yet supported
+
+    p_sys->internalBuffer = NULL;
+    p_sys->internalBufferPixelSize = 0;
+    p_sys->internalBufferWidth = 0;
+    p_sys->internalBufferHeight = 0;
+    p_sys->internalBufferPitch = 0;
+    p_sys->internalBufferSizeComputed = 0;
+    p_sys->internalBufferSize = 0;
+    p_sys->internalBufferPixelFormat = CFHD_PIXEL_FORMAT_YUY2;
+
+    // Ask a different vlc picture type than default input (YUYV) depending on choosen encoding format
+    if (p_sys->encFormat != CFHD_ENCODED_FORMAT_YUV_422)
+    {
+        msg_Info(p_enc, "Switching internal format to BGRa");
+        p_enc->fmt_in.i_codec = VLC_CODEC_BGRA;
+        p_sys->internalBufferPixelFormat = CFHD_PIXEL_FORMAT_BGRa;
+    }
+
+    // Init CineForm encoder
+    CFHD_Error errorCode = CFHD_OpenEncoder(&(p_sys->encoderRef), NULL);
+    if (errorCode)
+    {
+        msg_Err(p_enc, "CFHD_OpenEncoder(error %i / %s)", errorCode, getErrorString(errorCode));
+        return VLC_EGENERIC;
+    }
+
+    // Open an interface to the CineForm metadata
+    errorCode = CFHD_OpenMetadata(&(p_sys->metadataRef));
+    if (errorCode)
+    {
+        msg_Err(p_enc, "CFHD_OpenMetadata(error %i / %s)", errorCode, getErrorString(errorCode));
+        return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+
+void CloseEncoder(vlc_object_t *obj)
+{
+    encoder_t *p_enc = (encoder_t*)obj;
+    encoder_sys_t *p_sys = p_enc->p_sys;
+
+    if (p_sys)
+    {
+        CFHD_CloseEncoder(p_sys->encoderRef);
+        CFHD_CloseMetadata(p_sys->metadataRef);
+
+        if (p_sys->internalBuffer && !p_sys->directMapping)
+            free(p_sys->internalBuffer);
+
+        free(p_sys);
+    }
+}
+
+block_t *EncodeBlock(encoder_t *p_enc, picture_t *p_pic)
+{
+    CFHD_Error errorCode = CFHD_ERROR_OKAY;
+    encoder_sys_t *p_sys = p_enc->p_sys;
+    block_t *p_block = NULL;
+
+    // Check picture datas
+    if (!p_pic)
+        return NULL;
+
+    // Prepare encoding process
+    if (p_sys->sampleCount == 0)
+    {
+        // Initialize the encoder with the height of each channel (note: disabled, assume no multi video track)
+        //int videochannel_gap = 0;
+        //int encodedHeight = (p_sys->videoHeight - videochannel_gap) / p_sys->videoChannels;
+
+        // Get pixel size in byte
+        errorCode = CFHD_GetPixelSize(p_sys->internalBufferPixelFormat, &(p_sys->internalBufferPixelSize));
+        if (errorCode)
+        {
+            msg_Warn(p_enc, "CFHD_GetPixelSize(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+            return NULL;
+        }
+
+        // To encode CineForm footage, the frame width must be evenly divisible by 16 and the frame height by 8.
+        // Dimensions that do not meet these requirements are automatically rounded to a valid value.
+
+        if (p_sys->videoWidth % 16 != 0)
+        {
+            msg_Warn(p_enc, "CineForm video width is not a multiple of 16");
+            p_sys->internalBufferWidth = ceil((double)(p_sys->videoWidth) / 16.0) * 16;
+        }
+        else
+            p_sys->internalBufferWidth = p_sys->videoWidth;
+
+        if (p_sys->videoHeight % 8 != 0)
+        {
+            msg_Warn(p_enc, "CineForm video height is not a multiple of 8");
+            p_sys->internalBufferHeight = ceil((double)(p_sys->videoHeight) / 8.0) * 8;
+        }
+        else
+            p_sys->internalBufferHeight = p_sys->videoHeight;
+
+        // Compute
+        p_sys->internalBufferPitch = p_sys->internalBufferWidth * p_sys->internalBufferPixelSize;
+        p_sys->internalBufferSizeComputed = p_sys->internalBufferHeight * p_sys->internalBufferPitch;
+
+        // Prepare for encoding frames
+        errorCode = CFHD_PrepareToEncode(p_sys->encoderRef,
+                                         p_sys->internalBufferWidth,
+                                         p_sys->internalBufferHeight,
+                                         p_sys->internalBufferPixelFormat,
+                                         p_sys->encFormat,
+                                         p_sys->encFlags,
+                                         p_sys->encQuality);
+        if (errorCode != CFHD_ERROR_OKAY)
+        {
+            msg_Err(p_enc, "CFHD_PrepareToEncode(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+            return NULL;
+        }
+
+        // Allocate a buffer for the decoded frame
+        if (p_sys->internalBufferSizeComputed > p_sys->internalBufferSize)
+        {
+            if (p_sys->internalBuffer && !p_sys->directMapping)
+            {
+                free(p_sys->internalBuffer);
+                p_sys->internalBuffer = NULL;
+            }
+
+            // Allocate a new one
+            p_sys->internalBuffer = (char *)malloc(p_sys->internalBufferSizeComputed);
+            if (p_sys->internalBuffer == NULL)
+            {
+                msg_Err(p_enc, "Allocate internal output buffer FAILED");
+                return NULL;
+            }
+            else
+            {
+                p_sys->internalBufferSize = p_sys->internalBufferSizeComputed;
+            }
+        }
+
+        // Output params
+        p_enc->fmt_out.video.i_width = p_sys->internalBufferWidth;
+        p_enc->fmt_out.video.i_height = p_sys->internalBufferHeight;
+        p_enc->fmt_out.video.i_visible_width = p_sys->videoWidth;
+        p_enc->fmt_out.video.i_visible_height = p_sys->videoHeight;
+    }
+
+    if (p_enc->fmt_in.i_codec == VLC_CODEC_YUYV &&
+        p_sys->internalBufferPixelFormat == CFHD_PIXEL_FORMAT_YUY2)
+    {
+        p_sys->internalBuffer = (char *)(p_pic->p[0].p_pixels);
+        p_sys->directMapping = true;
+    }
+    else if (p_enc->fmt_in.i_codec == VLC_CODEC_BGRA &&
+             p_sys->internalBufferPixelFormat == CFHD_PIXEL_FORMAT_BGRa)
+    {
+        p_sys->internalBuffer = (char *)(p_pic->p[0].p_pixels);
+        p_sys->directMapping = true;
+    }
+    else
+    {
+        msg_Err(p_enc, "pictureConvertion(no known conversion)");
+        return NULL;
+    }
+
+    // Encode the video frame
+    errorCode = CFHD_EncodeSample(p_sys->encoderRef, p_sys->internalBuffer, p_sys->internalBufferPitch);
+    if (errorCode)
+    {
+        msg_Err(p_enc, "CFHD_EncodeSample(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+        return NULL;
+    }
+
+    // Get the encoded frame from the encoder
+    unsigned char *sampleBuffer;
+    size_t sampleSize;
+
+    errorCode = CFHD_GetSampleData(p_sys->encoderRef, (void **)&sampleBuffer, &sampleSize);
+    if (errorCode)
+    {
+        msg_Err(p_enc, "CFHD_GetSampleData(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+        return NULL;
+    }
+
+    p_block = block_Alloc(sampleSize);
+    if (!p_block)
+    {
+        return NULL;
+    }
+
+    memcpy(p_block->p_buffer, sampleBuffer, sampleSize);
+    p_block->i_pts = p_block->i_dts = p_pic->date;
+
+    p_sys->sampleCount++;
+    return p_block;
+}
+#endif // ENABLE_SOUT
diff --git a/modules/codec/cineform/cineform_plugin.h b/modules/codec/cineform/cineform_plugin.h
new file mode 100755
index 0000000000..a91cc91a6c
--- /dev/null
+++ b/modules/codec/cineform/cineform_plugin.h
@@ -0,0 +1,136 @@
+/*****************************************************************************
+ * cineform_plugin.h : CineForm decoder and encoder
+ *****************************************************************************
+ * Copyright (C) 2018 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Emeric Grange <emeric.grange at gmail.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef CINEFORM_PLUGIN_H
+#define CINEFORM_PLUGIN_H
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_input.h>
+#include <vlc_codec.h>
+
+#include <libcineform/CFHDDecoder.h>
+#include <libcineform/CFHDEncoder.h>
+#include <libcineform/CFHDTypes.h>
+#include <libcineform/CFHDError.h>
+
+typedef struct cf_packet_t {
+    unsigned char *sampleData;
+    size_t sampleSize;
+    int samplePTS;
+} cf_packet_t;
+
+typedef struct
+{
+    CFHD_DecoderRef decoderRef;
+    CFHD_MetadataRef metadataRef;
+
+    int SDKversion;
+    int SAMPLEversion;
+
+    // Flow control, mostly used for stats
+    uint64_t sampleCount;
+    uint64_t sampleDecoded;
+    uint64_t sampleFailed;
+
+    // Source video parameters, decoded and returned by the SDK (do not trust datas from VLC)
+    int32_t sourceWidth;
+    int32_t sourceHeight;
+    int32_t sourceVisibleWidth;
+    int32_t sourceVisibleHeight;
+    int32_t sourceChannels;
+    uint32_t sourcePixelSize;
+    CFHD_EncodedFormat sourcePixelFormat; ///< Pixel format of the compressed video, informative only
+
+    // Internal decoding buffer
+    int32_t internalBufferWidth;
+    int32_t internalBufferHeight;
+    int32_t internalBufferPitch;
+    uint32_t internalBufferSizeComputed;
+    uint32_t internalBufferSize;
+    CFHD_PixelFormat internalBufferPixelFormat; ///< The output buffer format set by the CineForm SDK, using 'decFormat'
+
+    // User defined parameters
+    bool decFormatAuto;
+    CFHD_DecodedResolution decSize;
+    CFHD_DecodingFlags decFlags;
+    CFHD_PixelFormat decFormat; ///< The output buffer format we'd like (may be superseeded if 'decSizeAuto' is set, or by the SDK)
+
+    CFHD_Stereo3DType stereo3Dtype;
+    CFHD_StereoFlags stereoFlags;
+    CFHD_VideoSelect stereoChannelSelection;
+} decoder_sys_t;
+
+int OpenDecoder(vlc_object_t *);
+void CloseDecoder(vlc_object_t *);
+int DecodeVideo(decoder_t *, block_t *);
+picture_t *DecodeBlock(decoder_t *, block_t **);
+    bool pictureConvertion(decoder_t *, decoder_sys_t *, picture_t *);
+    CFHD_Error prepareDecoding(decoder_t *, decoder_sys_t *, cf_packet_t *);
+
+#ifdef ENABLE_SOUT
+typedef struct
+{
+    CFHD_EncoderRef encoderRef;
+    CFHD_MetadataRef metadataRef;
+    CFHD_ALLOCATOR allocator;
+
+    int SDKversion;
+    int SAMPLEversion;
+
+    // Flow control
+    int sampleCount;
+
+    // User defined parameters
+    CFHD_EncodingQuality encQuality;
+    CFHD_EncodingFlags encFlags;
+    CFHD_EncodedFormat encFormat;
+
+    // Source video
+    int32_t videoWidth;
+    int32_t videoHeight;
+    int32_t videoChannels;
+
+    bool directMapping; ///< Indicate if we can encode directly the VLC picture, or if we need an intermediate internalBuffer
+
+    // Internal encoding buffer
+    char *internalBuffer;
+    CFHD_PixelFormat internalBufferPixelFormat;
+    uint32_t internalBufferPixelSize;
+    int32_t internalBufferWidth;
+    int32_t internalBufferHeight;
+    int32_t internalBufferPitch;
+    uint32_t internalBufferSizeComputed;
+    uint32_t internalBufferSize;
+} encoder_sys_t;
+
+int OpenEncoder(vlc_object_t *);
+void CloseEncoder(vlc_object_t *);
+block_t *EncodeBlock(encoder_t *, picture_t *);
+#endif // ENABLE_SOUT
+
+#endif // CINEFORM_PLUGIN_H
diff --git a/modules/codec/cineform/cineform_settings.c b/modules/codec/cineform/cineform_settings.c
new file mode 100755
index 0000000000..b23e518ee3
--- /dev/null
+++ b/modules/codec/cineform/cineform_settings.c
@@ -0,0 +1,402 @@
+/*****************************************************************************
+ * cineform_settings.c : CineForm decoder and encoder
+ *****************************************************************************
+ * Copyright (C) 2018 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Emeric Grange <emeric.grange at gmail.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include "cineform_settings.h"
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/*****************************************************************************
+ * Config helpers (decoder)
+ *****************************************************************************/
+
+CFHD_DecodedResolution getDecodingResolutions(decoder_t *p_dec)
+{
+    CFHD_DecodedResolution setting = CFHD_DECODED_RESOLUTION_FULL;
+
+    char *string = var_InheritString(p_dec, "cineform-decoding-resolutions");
+    if (string)
+    {
+        msg_Dbg(p_dec, "> cineform-decoding-resolutions: '%s'", string);
+
+        if (strcmp("RESOLUTION HALF", string) == 0)
+        {
+            setting = CFHD_DECODED_RESOLUTION_HALF;
+        }
+        else if (strcmp("RESOLUTION QUARTER", string) == 0)
+        {
+            setting = CFHD_DECODED_RESOLUTION_QUARTER;
+        }
+        else if (strcmp("THUMBNAIL", string) == 0)
+        {
+            setting = CFHD_DECODED_RESOLUTION_THUMBNAIL;
+        }
+
+        free(string);
+    }
+
+    return setting;
+}
+
+CFHD_DecodingFlags getDecodingFlags(decoder_t *p_dec)
+{
+    uint32_t flags = CFHD_DECODING_FLAGS_NONE;
+
+    char *string = var_InheritString(p_dec, "cineform-decoding-flags");
+    if (string)
+    {
+        msg_Dbg(p_dec, "> cineform-decoding-flags: '%s'", string);
+
+        if (strcmp("IGNORE OUTPUT", string) == 0)
+        {
+            flags += CFHD_DECODING_FLAGS_IGNORE_OUTPUT;
+        }
+        if (strcmp("MUST SCALE", string) == 0)
+        {
+            flags += CFHD_DECODING_FLAGS_MUST_SCALE;
+        }
+        if (strcmp("USE RESOLUTION", string) == 0)
+        {
+            flags += CFHD_DECODING_FLAGS_USE_RESOLUTION;
+        }
+
+        free(string);
+    }
+
+    return (CFHD_DecodingFlags)flags;
+}
+
+CFHD_PixelFormat getOutputFormats(decoder_t *p_dec, decoder_sys_t *p_sys)
+{
+    CFHD_PixelFormat setting = CFHD_PIXEL_FORMAT_UNKNOWN;
+    p_sys->decFormatAuto = true;
+
+    char *string = var_InheritString(p_dec, "cineform-output-formats");
+    if (string)
+    {
+        msg_Dbg(p_dec, "> cineform-output-formats: '%s'", string);
+
+        if (strcmp("YUYV", string) == 0)
+        {
+            setting = CFHD_PIXEL_FORMAT_YUYV;
+            p_dec->fmt_out.i_codec = VLC_CODEC_YUYV;
+            p_sys->decFormatAuto = false;
+        }
+        else if (strcmp("BGRa", string) == 0)
+        {
+            setting = CFHD_PIXEL_FORMAT_BGRa;
+            p_dec->fmt_out.i_codec = VLC_CODEC_BGRA;
+            p_sys->decFormatAuto = false;
+        }
+        else if (strcmp("RG24", string) == 0)
+        {
+            setting = CFHD_PIXEL_FORMAT_RG24;
+            p_dec->fmt_out.i_codec = VLC_CODEC_RGB24;
+            p_sys->decFormatAuto = false;
+        }
+        else if (strcmp("AUTO", string) == 0)
+        {
+            setting = CFHD_PIXEL_FORMAT_UNKNOWN;
+            p_sys->decFormatAuto = true;
+        }
+
+        free(string);
+    }
+
+    return setting;
+}
+
+CFHD_VideoSelect getStereoSelect(decoder_t *p_dec)
+{
+    CFHD_VideoSelect setting = VIDEO_SELECT_DEFAULT;
+
+    char *string = var_InheritString(p_dec, "cineform-stereo-select");
+    if (string)
+    {
+        msg_Dbg(p_dec, "> cineform-stereo-select: '%s'", string);
+
+        if (strcmp("LEFT EYE", string) == 0)
+        {
+            setting = VIDEO_SELECT_LEFT_EYE;
+        }
+        else if (strcmp("RIGHT EYE", string) == 0)
+        {
+            setting = VIDEO_SELECT_RIGHT_EYE;
+        }
+        else if (strcmp("BOTH EYES", string) == 0)
+        {
+            setting = VIDEO_SELECT_BOTH_EYES;
+        }
+
+        free(string);
+    }
+
+    return setting;
+}
+
+CFHD_Stereo3DType getStereoType(decoder_t *p_dec)
+{
+    CFHD_Stereo3DType setting = STEREO3D_TYPE_DEFAULT;
+
+    char *string = var_InheritString(p_dec, "cineform-stereo-type");
+    if (string)
+    {
+        msg_Dbg(p_dec, "> cineform-stereo-type: '%s'", string);
+
+        if (strcmp("STACKED", string) == 0)
+        {
+            setting = STEREO3D_TYPE_STACKED;
+        }
+        else if (strcmp("SIDE BY SIDE", string) == 0)
+        {
+            setting = STEREO3D_TYPE_SIDEBYSIDE;
+        }
+/*
+        // TODO
+        STEREO3D_TYPE_FIELDS = 3,
+        STEREO3D_TYPE_ONION = 4,
+        STEREO3D_TYPE_DIFFERENCE = 5,
+        STEREO3D_TYPE_FREEVIEW = 7,
+        STEREO3D_TYPE_ANAGLYPH_RED_CYAN = 16,
+        STEREO3D_TYPE_ANAGLYPH_RED_CYAN_BW = 17,
+        STEREO3D_TYPE_ANAGLYPH_BLU_YLLW = 18,
+        STEREO3D_TYPE_ANAGLYPH_BLU_YLLW_BW = 19,
+        STEREO3D_TYPE_ANAGLYPH_GRN_MGTA = 20,
+        STEREO3D_TYPE_ANAGLYPH_GRN_MGTA_BW = 21,
+        STEREO3D_TYPE_ANAGLYPH_OPTIMIZED = 22,
+*/
+        free(string);
+    }
+
+    return setting;
+}
+
+CFHD_StereoFlags getStereoFlags(decoder_t *p_dec)
+{
+    uint32_t flags = STEREO_FLAGS_DEFAULT;
+
+    char *string = var_InheritString(p_dec, "cineform-stereo-flags");
+    if (string)
+    {
+        msg_Dbg(p_dec, "> cineform-stereo-flags: '%s'", string);
+
+        if (strcmp("SWAP EYES", string) == 0)
+        {
+            flags += STEREO_FLAGS_SWAP_EYES;
+        }
+        if (strcmp("SPEED 3D", string) == 0)
+        {
+            flags += STEREO_FLAGS_SPEED_3D;
+        }
+
+        free(string);
+    }
+
+    return (CFHD_StereoFlags)flags;
+}
+
+/*****************************************************************************
+ * Config helpers (encoder)
+ *****************************************************************************/
+
+CFHD_EncodedFormat getEncodingFormat(encoder_t *p_enc)
+{
+    CFHD_EncodedFormat setting = CFHD_ENCODED_FORMAT_YUV_422;
+
+    char *string = var_InheritString(p_enc, "cineform-encoding-format");
+    if (string)
+    {
+        msg_Dbg(p_enc, "> cineform-encoding-format: '%s'", string);
+
+        if (strcmp("RGB 4:4:4", string) == 0)
+        {
+            setting = CFHD_ENCODED_FORMAT_RGB_444;
+        }
+        else if (strcmp("RGBA 4:4:4:4", string) == 0)
+        {
+            setting = CFHD_ENCODED_FORMAT_RGBA_4444;
+        }
+        else if (strcmp("Bayer", string) == 0)
+        {
+            setting = CFHD_ENCODED_FORMAT_BAYER;
+/*
+            // TODO bayer does not make sense, sources from VLC aren't bayer anyway
+            // TODO add these bayer format variations directly here?
+            CFHD_BAYER_FORMAT_UNKNOWN = -1,
+            CFHD_BAYER_FORMAT_RED_GRN = 0,
+            CFHD_BAYER_FORMAT_GRN_RED = 1,
+            CFHD_BAYER_FORMAT_GRN_BLU = 2,
+            CFHD_BAYER_FORMAT_BLU_GRN = 3,
+*/
+        }
+
+        free(string);
+    }
+
+    return setting;
+}
+
+CFHD_EncodingQuality getEncodingQuality(encoder_t *p_enc)
+{
+    CFHD_EncodingQuality setting = CFHD_ENCODING_QUALITY_MEDIUM;
+
+    char *string = var_InheritString(p_enc, "cineform-encoding-quality");
+    if (string)
+    {
+        msg_Dbg(p_enc, "> cineform-encoding-quality: '%s'", string);
+
+        if (strcmp("FIXED", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_FIXED;
+        }
+        else if (strcmp("LOW", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_LOW;
+        }
+        else if (strcmp("MEDIUM", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_MEDIUM;
+        }
+        else if (strcmp("HIGH", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_HIGH;
+        }
+        else if (strcmp("FILM SCAN 1", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_FILMSCAN1;
+        }
+        else if (strcmp("FILM SCAN 2", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_FILMSCAN2;
+        }
+        else if (strcmp("FILM SCAN 3", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_FILMSCAN3;
+        }
+        else if (strcmp("KEYING", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_KEYING;
+        }
+        else if (strcmp("ONE EIGHTH UNCOMPRESSED", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_ONE_EIGHTH_UNCOMPRESSED;
+        }
+        else if (strcmp("QUARTER UNCOMPRESSED", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_QUARTER_UNCOMPRESSED;
+        }
+        else if (strcmp("THREE EIGHTH UNCOMPRESSED", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_THREE_EIGHTH_UNCOMPRESSED;
+        }
+        else if (strcmp("HALF UNCOMPRESSED", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_HALF_UNCOMPRESSED;
+        }
+        else if (strcmp("FIVE EIGHTH UNCOMPRESSED", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_FIVE_EIGHTH_UNCOMPRESSED;
+        }
+        else if (strcmp("THREE QUARTER UNCOMPRESSED", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_THREE_QUARTER_UNCOMPRESSED;
+        }
+        else if (strcmp("SEVEN EIGHTH UNCOMPRESSED", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_SEVEN_EIGHTH_UNCOMPRESSED;
+        }
+        else if (strcmp("UNCOMPRESSED", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_UNCOMPRESSED;
+        }
+        else if (strcmp("UNC NO STORE", string) == 0)
+        {
+            setting = CFHD_ENCODING_QUALITY_UNC_NO_STORE;
+        }
+
+        free(string);
+    }
+
+    return setting;
+}
+
+CFHD_EncodingFlags getEncodingFlags(encoder_t *p_enc)
+{
+    uint32_t flags = CFHD_ENCODING_FLAGS_NONE;
+
+    char *string = var_InheritString(p_enc, "cineform-encoding-flags");
+    if (string)
+    {
+        msg_Dbg(p_enc, "> cineform-encoding-flags: '%s'", string);
+
+        if (strcmp("YUV INTERLACED", string) == 0)
+        {
+            flags += CFHD_ENCODING_FLAGS_YUV_INTERLACED;
+        }
+        if (strcmp("YUV 2 FRAMES GOP", string) == 0)
+        {
+            flags += CFHD_ENCODING_FLAGS_YUV_2FRAME_GOP;
+        }
+        if (strcmp("YUV 601", string) == 0)
+        {
+            flags += CFHD_ENCODING_FLAGS_YUV_601;
+        }
+        if (strcmp("CURVE APPLIED", string) == 0)
+        {
+            flags += CFHD_ENCODING_FLAGS_CURVE_APPLIED;
+        }
+        if (strcmp("CURVE GAMMA 22", string) == 0)
+        {
+            flags += CFHD_ENCODING_FLAGS_CURVE_GAMMA22;
+        }
+        if (strcmp("CURVE LOG 90", string) == 0)
+        {
+            flags += CFHD_ENCODING_FLAGS_CURVE_LOG90;
+        }
+        if (strcmp("CURVE LINEAR", string) == 0)
+        {
+            flags += CFHD_ENCODING_FLAGS_CURVE_LINEAR;
+        }
+        if (strcmp("CURVE CUSTOM", string) == 0)
+        {
+            flags += CFHD_ENCODING_FLAGS_CURVE_CUSTOM;
+        }
+        if (strcmp("RGB STUDIO", string) == 0)
+        {
+            flags += CFHD_ENCODING_FLAGS_RGB_STUDIO;
+        }
+/*
+        // TODO
+        CFHD_ENCODING_FLAGS_APPEND_THUMBNAIL
+        CFHD_ENCODING_FLAGS_WATERMARK_THUMBNAIL
+        CFHD_ENCODING_FLAGS_LARGER_OUTPUT
+*/
+        free(string);
+    }
+
+    return (CFHD_EncodingFlags)flags;
+}
diff --git a/modules/codec/cineform/cineform_settings.h b/modules/codec/cineform/cineform_settings.h
new file mode 100755
index 0000000000..418b79fbf0
--- /dev/null
+++ b/modules/codec/cineform/cineform_settings.h
@@ -0,0 +1,91 @@
+/*****************************************************************************
+ * cineform_settings.h : CineForm decoder and encoder
+ *****************************************************************************
+ * Copyright (C) 2018 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Emeric Grange <emeric.grange at gmail.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef CINEFORM_SETTINGS_H
+#define CINEFORM_SETTINGS_H
+
+#include "cineform_plugin.h"
+
+#include <libcineform/CFHDTypes.h>
+
+// Decoder
+
+#define DEC_CFG_PREFIX "cineform-"
+
+#define OUTPUT_FORMATS_TEXT "Prefered output format"
+#define OUTPUT_FORMATS_LONGTEXT "Choose the prefered output format (can be overwritten at run time if prefered format 'color resolution' is not high enough to store decoded format)."
+static const char *const output_formats[] = {"AUTO", "YUYV", "I422", "I444", "BGRa", "RG24", NULL};
+
+#define DECODING_RESOLUTIONS_TEXT "Decoding resolutions"
+#define DECODING_RESOLUTIONS_LONGTEXT "You can tweak the decoding resolution, very useful depending on how much CPU time available you've got."
+static const char *const decoding_resolutions[] = {"FULL RESOLUTION", "HALF RESOLUTION", "QUARTER RESOLUTION", "THUMBNAIL", NULL};
+
+#define DECODING_FLAGS_TEXT "Decoding flags"
+#define DECODING_FLAGS_LONGTEXT "Apply various decoding flags."
+static const char *const decoding_flags[] = {"NONE", "IGNORE OUTPUT", "MUST SCALE", "USE RESOLUTION", NULL};
+
+#define STEREO_SELECT_TEXT "Eye selection"
+#define STEREO_SELECT_LONGTEXT "Eye selection (only in case of 3d video)."
+static const char *const stereo_select[] = {"DEFAULT", "LEFT EYE", "RIGHT EYE", "BOTH EYES", NULL};
+
+#define STEREO_TYPE_TEXT "Stereo 3D type"
+#define STEREO_TYPE_LONGTEXT "Stereo 3D type (only in case of 3d video)."
+static const char *const stereo_type[] = {"DEFAULT", "STACKED", "SIDE BY SIDE", NULL};
+
+#define STEREO_FLAGS_TEXT "Stereo flags"
+#define STEREO_FLAGS_LONGTEXT "Apply stereo flags (only in case of 3d video)."
+static const char *const stereo_flags[] = {"DEFAULT", "SWAP EYES", "SPEED 3D", NULL};
+
+CFHD_DecodedResolution getDecodingResolutions(decoder_t *p_dec);
+CFHD_DecodingFlags getDecodingFlags(decoder_t *p_dec);
+CFHD_PixelFormat getOutputFormats(decoder_t *p_dec, decoder_sys_t *p_sys);
+CFHD_VideoSelect getStereoSelect(decoder_t *p_dec);
+CFHD_Stereo3DType getStereoType(decoder_t *p_dec);
+CFHD_StereoFlags getStereoFlags(decoder_t *p_dec);
+
+// Encoder
+
+#define ENC_CFG_PREFIX "cineform-"
+
+static const char *const enc_cfg_options[] = {
+    "encoding-format", "encoding-quality", "encoding-flags", NULL
+};
+
+#define ENCODING_FORMAT_TEXT "Encoding format"
+#define ENCODING_FORMAT_LONGTEXT "Choose the internal encoding format, depending on how much visual quality you need."
+static const char *const encoding_format[] = {"YUV 4:2:2", "RGB 4:4:4", "RGBA 4:4:4:4", "Bayer", NULL};
+
+#define ENCODING_QUALITY_TEXT "Encoding quality"
+#define ENCODING_QUALITY_LONGTEXT "Choose an encoding quality preset."
+static const char *const encoding_quality[] = {"LOW", "MEDIUM", "HIGH", "UNCOMPRESSED", NULL};
+
+#define ENCODING_FLAGS_TEXT "Encoding flags"
+#define ENCODING_FLAGS_LONGTEXT "Apply encoding flags."
+static const char *const encoding_flags[] = {"NONE", "YUV INTERLACED", "YUV 2 FRAMES GOP", "CURVE APPLIED",
+                                             "CURVE GAMMA 22", "CURVE LOG 90", "CURVE LINEAR", "CURVE CUSTOM", "RGB STUDIO", NULL};
+
+CFHD_EncodedFormat getEncodingFormat(encoder_t *p_enc);
+CFHD_EncodingQuality getEncodingQuality(encoder_t *p_enc);
+CFHD_EncodingFlags getEncodingFlags(encoder_t *p_enc);
+
+#endif // CINEFORM_SETTINGS_H
-- 
2.18.0



More information about the vlc-devel mailing list