[vlc-devel] [PATCH v2 2/3] Add CineForm plugin v1
Emeric Grange
egrange at gopro.com
Tue Nov 21 11:41:06 CET 2017
---
modules/codec/cineformsdk/cineform_allocator.c | 76 ++
modules/codec/cineformsdk/cineform_allocator.h | 38 +
modules/codec/cineformsdk/cineform_debug.c | 246 +++++
modules/codec/cineformsdk/cineform_debug.h | 41 +
modules/codec/cineformsdk/cineform_plugin.c | 1364 ++++++++++++++++++++++++
modules/codec/cineformsdk/cineform_plugin.h | 173 +++
modules/codec/cineformsdk/cineform_settings.c | 427 ++++++++
modules/codec/cineformsdk/cineform_settings.h | 94 ++
8 files changed, 2459 insertions(+)
create mode 100755 modules/codec/cineformsdk/cineform_allocator.c
create mode 100755 modules/codec/cineformsdk/cineform_allocator.h
create mode 100755 modules/codec/cineformsdk/cineform_debug.c
create mode 100755 modules/codec/cineformsdk/cineform_debug.h
create mode 100755 modules/codec/cineformsdk/cineform_plugin.c
create mode 100755 modules/codec/cineformsdk/cineform_plugin.h
create mode 100755 modules/codec/cineformsdk/cineform_settings.c
create mode 100755 modules/codec/cineformsdk/cineform_settings.h
diff --git a/modules/codec/cineformsdk/cineform_allocator.c b/modules/codec/cineformsdk/cineform_allocator.c
new file mode 100755
index 0000000000..99a897dd14
--- /dev/null
+++ b/modules/codec/cineformsdk/cineform_allocator.c
@@ -0,0 +1,76 @@
+/*****************************************************************************
+ * cineform_allocator.c : CineForm decoder and encoder
+ *****************************************************************************
+ * Copyright (C) 2017 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Emeric Grange <egrange at gopro.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_allocator.h"
+
+#include <stdlib.h> // regular memory handling
+#include <emmintrin.h> // aligned memory handling and SSE intrisics?
+
+#ifdef _MSC_VER
+#include "malloc.h" // _mm_malloc for MSVC
+#endif
+
+void *AlignedAlloc(void *allocator, size_t size, size_t alignment)
+{
+ (void)allocator; // custom UNUSED macro
+ return _mm_malloc(size, alignment);
+}
+
+void AlignedFree(void *allocator, void *block)
+{
+ (void)allocator; // custom UNUSED macro
+ _mm_free(block);
+}
+
+void UnalignedFree(void *allocator, void *block)
+{
+ (void)allocator; // custom UNUSED macro
+ free(block);
+}
+
+void *UnalignedAlloc(void *allocator, size_t size)
+{
+ (void)allocator; // custom UNUSED macro
+ return malloc(size);
+}
+
+void *AllocateBuffer(size_t size)
+{
+ // Align buffers to a 16 byte boundary for SSE2 instructions
+ const size_t alignment = 16;
+
+#ifdef _MSC_VER
+ return _aligned_malloc(size, alignment);
+#else
+ return _mm_malloc(size, alignment);
+#endif
+}
+
+void DeallocateBuffer(void *buffer)
+{
+#ifdef _MSC_VER
+ _aligned_free(buffer);
+#else
+ _mm_free(buffer);
+#endif
+}
diff --git a/modules/codec/cineformsdk/cineform_allocator.h b/modules/codec/cineformsdk/cineform_allocator.h
new file mode 100755
index 0000000000..e8fd9febed
--- /dev/null
+++ b/modules/codec/cineformsdk/cineform_allocator.h
@@ -0,0 +1,38 @@
+/*****************************************************************************
+ * cineform_allocator.h : CineForm decoder and encoder
+ *****************************************************************************
+ * Copyright (C) 2017 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Emeric Grange <egrange at gopro.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_ALLOCATOR_H
+#define CINEFORM_ALLOCATOR_H
+
+#include <stddef.h>
+
+void *AlignedAlloc(void *allocator, size_t size, size_t alignment);
+void AlignedFree(void *allocator, void *block);
+
+void UnalignedFree(void *allocator, void *block);
+void *UnalignedAlloc(void *allocator, size_t size);
+
+void *AllocateBuffer(size_t size);
+void DeallocateBuffer(void *buffer);
+
+#endif // CINEFORM_ALLOCATOR_H
diff --git a/modules/codec/cineformsdk/cineform_debug.c b/modules/codec/cineformsdk/cineform_debug.c
new file mode 100755
index 0000000000..ae7ed4f02f
--- /dev/null
+++ b/modules/codec/cineformsdk/cineform_debug.c
@@ -0,0 +1,246 @@
+/*****************************************************************************
+ * cineform_debug.c : CineForm decoder and encoder
+ *****************************************************************************
+ * Copyright (C) 2017 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Emeric Grange <egrange at gopro.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_debug.h"
+
+#include <stdio.h>
+
+char *getFourccStr_le(unsigned fcc, char *fcc_str)
+{
+ // "fcc_str" must be at least 5 characters long
+ if (fcc_str)
+ {
+ fcc_str[0] = (char)((fcc >> 0) & 0xFF);
+ fcc_str[1] = (char)((fcc >> 8) & 0xFF);
+ fcc_str[2] = (char)((fcc >> 16) & 0xFF);
+ fcc_str[3] = (char)((fcc >> 24) & 0xFF);
+ fcc_str[4] = '\0';
+ }
+
+ return fcc_str;
+}
+
+char *getFourccStr_be(unsigned fcc, char *fcc_str)
+{
+ // "fcc_str" must be at least 5 characters long
+ if (fcc_str)
+ {
+ fcc_str[0] = (char)((fcc >> 24) & 0xFF);
+ fcc_str[1] = (char)((fcc >> 16) & 0xFF);
+ fcc_str[2] = (char)((fcc >> 8) & 0xFF);
+ fcc_str[3] = (char)((fcc >> 0) & 0xFF);
+ fcc_str[4] = '\0';
+ }
+
+ return fcc_str;
+}
+
+void printBuffer(const unsigned char *bufferData, const unsigned bufferSize)
+{
+ if (bufferData)
+ {
+ printf("BUFFER (raw) datas @ '%p'\n", &bufferData);
+ printf("BUFFER (raw) datas (size : %i)\n", bufferSize);
+
+ // how many bytes per line
+ unsigned linesize = 48;
+ unsigned datavolumetoprint = 1000000000;
+
+ // how many bytes to print
+ if (datavolumetoprint <= 0 || datavolumetoprint > bufferSize)
+ {
+ datavolumetoprint = bufferSize;
+ }
+
+ for (unsigned i = 0; i < datavolumetoprint; i+=linesize)
+ {
+ for (unsigned j = 0; j < linesize; j++)
+ {
+ printf("%02X ", (bufferData[i+j]));
+ }
+ printf("\n");
+ }
+ printf("\n");
+
+ // Force flush to the terminal?
+ //fflush(stdout);
+ //fflush(stderr);
+ }
+ else
+ {
+ printf("printBuffer() ERROR > empty sampleDatas\n");
+ }
+}
+
+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";
+ }
+}
+
+void printEncodedFormats(const CFHD_EncodedFormat format)
+{
+ switch (format)
+ {
+ case CFHD_ENCODED_FORMAT_YUV_422:
+ printf("- encodedFormat: CFHD_ENCODED_FORMAT_YUV_422\n");
+ break;
+ case CFHD_ENCODED_FORMAT_RGB_444:
+ printf("- encodedFormat: CFHD_ENCODED_FORMAT_RGB_444\n");
+ break;
+ case CFHD_ENCODED_FORMAT_RGBA_4444:
+ printf("- encodedFormat: CFHD_ENCODED_FORMAT_RGBA_4444\n");
+ break;
+ case CFHD_ENCODED_FORMAT_BAYER:
+ printf("- encodedFormat: CFHD_ENCODED_FORMAT_BAYER\n");
+ break;
+ case CFHD_ENCODED_FORMAT_YUVA_4444:
+ printf("- encodedFormat: CFHD_ENCODED_FORMAT_YUVA_4444\n");
+ break;
+ }
+}
+
+void printEncodingFormats(const unsigned level, const CFHD_EncodedFormat format)
+{
+ printf("SUPPORTED ENCODING FORMATS\n");
+ if (level & 1)
+ {
+ if (format == CFHD_ENCODED_FORMAT_YUV_422)
+ printf("[X] ");
+ else
+ printf("- ");
+
+ printf("YUV 4:2:2\n");
+ }
+ if (level & 2)
+ {
+ if (format == CFHD_ENCODED_FORMAT_RGB_444)
+ printf("[X] ");
+ else
+ printf("- ");
+
+ printf("RGB 4:4:4\n");
+ }
+ if (level & 4)
+ {
+ if (format == CFHD_ENCODED_FORMAT_RGBA_4444)
+ printf("[X] ");
+ else
+ printf("- ");
+
+ printf("RGBA 4:4:4:4\n");
+ }
+ if (level & 8)
+ {
+ if (format == CFHD_ENCODED_FORMAT_BAYER)
+ printf("[X] ");
+ else
+ printf("- ");
+
+ printf("RAW bayer\n");
+ }
+ if (level & 16)
+ {
+ if (format == CFHD_ENCODED_FORMAT_YUVA_4444)
+ printf("[X] ");
+ else
+ printf("- ");
+
+ printf("YUVA 4:4:4:4\n");
+ }
+}
diff --git a/modules/codec/cineformsdk/cineform_debug.h b/modules/codec/cineformsdk/cineform_debug.h
new file mode 100755
index 0000000000..2a19dacf60
--- /dev/null
+++ b/modules/codec/cineformsdk/cineform_debug.h
@@ -0,0 +1,41 @@
+/*****************************************************************************
+ * cineform_debug.h : CineForm decoder and encoder
+ *****************************************************************************
+ * Copyright (C) 2017 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Emeric Grange <egrange at gopro.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_DEBUG_H
+#define CINEFORM_DEBUG_H
+
+#include <stdint.h>
+#include <string.h>
+
+char *getFourccStr_le(unsigned fcc, char *fcc_str);
+char *getFourccStr_be(unsigned fcc, char *fcc_str);
+void printBuffer(const unsigned char *bufferData, const unsigned bufferSize);
+
+#include <cineformsdk/CFHDError.h>
+#include <cineformsdk/CFHDTypes.h>
+
+const char *getErrorString(const CFHD_Error error);
+void printEncodedFormats(const CFHD_EncodedFormat format);
+void printEncodingFormats(const unsigned level, const CFHD_EncodedFormat format);
+
+#endif // CINEFORM_DEBUG_H
diff --git a/modules/codec/cineformsdk/cineform_plugin.c b/modules/codec/cineformsdk/cineform_plugin.c
new file mode 100755
index 0000000000..1ef78cbbfa
--- /dev/null
+++ b/modules/codec/cineformsdk/cineform_plugin.c
@@ -0,0 +1,1364 @@
+/*****************************************************************************
+ * cineform_plugin.c : CineForm decoder and encoder
+ *****************************************************************************
+ * Copyright (C) 2017 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Emeric Grange <egrange at gopro.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_allocator.h"
+#include "cineform_settings.h"
+#include "cineform_debug.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_description("CineForm DECODER plugin")
+ set_help("CineForm encoding/decoding plugin for VLC3, using GoPro CineForm SDK")
+
+ set_capability("video decoder", 100)
+ set_callbacks(OpenDecoder, CloseDecoder)
+
+ // User defined settings
+ set_section("Decoding", NULL)
+ add_bool("cineform-skip-frames", true,
+ SKIP_FRAMES_TEXT, SKIP_FRAMES_LONGTEXT, false)
+ 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);
+
+#if ENABLE_ENCODER == 1
+ add_submodule()
+
+ set_capability("encoder", 150)
+ set_description("CineForm ENCODER plugin")
+ set_callbacks(OpenEncoder, CloseEncoder)
+
+ // User defined settings
+ set_section("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 // ENABLE_ENCODER
+
+vlc_module_end ()
+
+/*****************************************************************************
+ * Decoder
+ *****************************************************************************/
+
+/**
+ * @brief Starts and init the CineForm decoder plugin.
+ * @param obj A pointer to a decoder_t structure allocated by VLC.
+ * @return VLC_SUCCESS or an error code.
+ */
+int OpenDecoder(vlc_object_t *obj)
+{
+ decoder_t *p_dec = (decoder_t*)obj;
+ decoder_sys_t *p_sys = NULL;
+
+ // First, check if we have a CineForm video track as input
+ if (p_dec->fmt_in.i_cat == VIDEO_ES && p_dec->fmt_in.i_codec == VLC_CODEC_CINEFORM)
+ {
+ char fcc[5];
+ msg_Info(p_dec, "CineForm DECODER plugin (OpenDecoder with fourCC '%s')",
+ getFourccStr_le(p_dec->fmt_in.i_codec, fcc));
+ }
+ else
+ {
+ 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 DECODER 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->sampleSkipped = 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->directMapping = false;
+
+ p_sys->internalBuffer = NULL;
+ p_sys->internalBufferWidth = 0;
+ p_sys->internalBufferHeight = 0;
+ p_sys->internalBufferPitch = 0;
+ p_sys->internalBufferSize = 0;
+ p_sys->internalBufferSizeComputed = 0;
+ p_sys->internalBufferPixelFormat = CFHD_PIXEL_FORMAT_UNKNOWN;
+
+ p_sys->decSizeAuto = false;
+ p_sys->decFormatAuto = false;
+
+ p_sys->skipFrames = var_InheritBool(p_dec, "cineform-skip-frames");
+ p_sys->decSize = getDecodingResolutions(p_dec);
+ p_sys->decFlags = getDecodingFlags(p_dec);
+ p_sys->decFormat = getOutputFormats(p_dec);
+
+ p_sys->stereo3Dtype = getStereoType(p_dec);
+ p_sys->stereoFlags = getStereoFlags(p_dec);
+ p_sys->stereoChannelSelection = getStereoSelect(p_dec);
+
+#if ENABLE_STATS == 1
+ p_sys->total_fn = 0;
+ p_sys->total_dec = 0;
+ p_sys->total_pic = 0;
+ p_sys->total_conv = 0;
+#endif
+
+ // Init allocator
+ if ((p_sys->allocator.vtable = (struct cfhd_allocator_vtable *)malloc(sizeof(struct cfhd_allocator_vtable))) == NULL)
+ {
+ return VLC_ENOMEM;
+ }
+ p_sys->allocator.vtable->aligned_malloc = AlignedAlloc;
+ p_sys->allocator.vtable->aligned_free = AlignedFree;
+ p_sys->allocator.vtable->unaligned_malloc = UnalignedAlloc;
+ p_sys->allocator.vtable->unaligned_free = UnalignedFree;
+
+ // Init CineForm HD decoder
+ CFHD_Error errorCode = CFHD_OpenDecoder(&(p_sys->decoderRef), &(p_sys->allocator));
+ if (errorCode)
+ {
+ msg_Err(p_dec, "CFHD_OpenDecoder(error %i / %s)\n", errorCode, getErrorString(errorCode));
+ return VLC_EGENERIC;
+ }
+
+ // Open an interface to the CineForm HD metadata
+ errorCode = CFHD_OpenMetadata(&(p_sys->metadataRef));
+ if (errorCode)
+ {
+ msg_Err(p_dec, "CFHD_OpenMetadata(error %i / %s)\n", 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;
+
+ msg_Info(p_dec, "CineForm DECODER plugin (CloseDecoder)");
+
+#if ENABLE_STATS == 1
+ printf("CineForm DECODER plugin (stats: %llu samples / %llu decoded / %llu skipped / %llu failed)\n",
+ p_sys->sampleCount, p_sys->sampleDecoded, p_sys->sampleSkipped, p_sys->sampleFailed);
+
+ if (p_sys->sampleCount > 0)
+ {
+ printf("- mean function time: %.2f ms\n", (double)(p_sys->total_fn) / (double)(p_sys->sampleCount));
+ printf("- mean decoding time: %.2f ms\n", (double)(p_sys->total_dec) / (double)(p_sys->sampleCount));
+ printf("- mean pic allo time: %.2f ms\n", (double)(p_sys->total_pic) / (double)(p_sys->sampleCount));
+ printf("- mean pic conv time: %.2f ms\n", (double)(p_sys->total_conv) / (double)(p_sys->sampleCount));
+ }
+#endif
+
+ // Cleanup
+ if (p_sys)
+ {
+ CFHD_CloseDecoder(p_sys->decoderRef);
+ CFHD_CloseMetadata(p_sys->metadataRef);
+
+ if (p_sys->internalBuffer)
+ {
+ DeallocateBuffer(p_sys->internalBuffer);
+ p_sys->internalBuffer = NULL;
+ }
+
+ free(p_sys);
+ p_sys = NULL;
+ }
+}
+
+/**
+ * @brief DecodeVideo
+ * @param p_dec
+ * @param p_block
+ * @return picture_t
+ */
+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;
+}
+
+/**
+ * @brief DecodeBlock
+ * @param p_dec
+ * @param pp_block
+ * @return picture_t
+ */
+picture_t *DecodeBlock(decoder_t *p_dec, block_t **pp_block)
+{
+#if ENABLE_STATS == 1
+ clock_t timer_fn_start = clock();
+ clock_t timer_fn_end = 0;
+ clock_t timer_pic_start = 0;
+ clock_t timer_pic_end = 0;
+ clock_t timer_dec_start = 0;
+ clock_t timer_dec_end = 0;
+ clock_t timer_conv_start = 0;
+ clock_t timer_conv_end = 0;
+ int64_t diff_fn = 0;
+ int64_t diff_pic = 0;
+ int64_t diff_dec = 0;
+ int64_t diff_conv = 0;
+#endif
+
+ if (!pp_block || !*pp_block)
+ return NULL;
+
+ CFHD_Error errorCode = CFHD_ERROR_OKAY;
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ block_t *p_block = *pp_block;
+ picture_t *p_pic = NULL;
+
+ // We have a block
+ p_sys->sampleCount++;
+
+ // Check block flags
+ if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED))
+ {
+ msg_Warn(p_dec, "DecodeBlock error (block corrupted?)");
+ goto error;
+ }
+
+ // Drop late frames instead of slowing down the video output? Activated by default.
+ if (p_sys->skipFrames == true)
+ {
+ mtime_t i_display_date = 0;
+
+ if (!(p_block->i_flags & BLOCK_FLAG_PREROLL))
+ i_display_date = decoder_GetDisplayDate(p_dec, p_block->i_dts);
+
+ if (i_display_date > 0 && i_display_date < mdate())
+ {
+#if ENABLE_STATS
+ msg_Warn(p_dec, "SKIPPING frame %llu (%lli μs too late)",
+ p_sys->sampleCount, mdate() - i_display_date);
+#endif
+ goto skip;
+ }
+ }
+
+ // Packet handling
+ cf_packet_t packet;
+ packet.sampleData = p_block->p_buffer;
+ packet.sampleSize = p_block->i_buffer;
+ packet.samplePTS = p_block->i_dts;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ if (p_sys->sampleDecoded == 0 /*|| video_size_changed*/)
+ {
+ 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_Info(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_Info(p_dec, "CineForm encoder 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 ENABLE_STATS == 1
+ printf("ENCODED VIDEO PARAMETERS\n");
+ printf("- surface: %d x %d\n", p_sys->sourceWidth, p_sys->sourceHeight);
+ printf("- visible: %d x %d\n", p_sys->sourceVisibleWidth, p_sys->sourceVisibleHeight);
+ printf("- macropixel size: %d byte(s)\n", p_sys->sourcePixelSize);
+ printf("- %d video channel(s)\n", p_sys->sourceChannels);
+
+ if (p_dec->fmt_in.video.i_frame_rate_base != 0)
+ printf("- %.3f fps\n", (float)p_dec->fmt_in.video.i_frame_rate / (float)p_dec->fmt_in.video.i_frame_rate_base);
+
+ printEncodedFormats(p_sys->sourcePixelFormat);
+ printPreferedOutputFormats(p_sys, &packet);
+#endif // ENABLE_STATS
+
+ if (errorCode != CFHD_ERROR_OKAY)
+ {
+ msg_Err(p_dec, "getSampleInfos(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+ return NULL;
+ }
+
+ // Allocate a buffer for the decoded frame, if needed
+ if (p_sys->directMapping == false)
+ {
+ if (p_sys->internalBufferSizeComputed > p_sys->internalBufferSize)
+ {
+ // Make sure we do not aleady have an output buffer
+ DeallocateBuffer(p_sys->internalBuffer);
+
+ // Allocate a new one
+ p_sys->internalBuffer = (char *)AllocateBuffer(p_sys->internalBufferSizeComputed);
+ if (p_sys->internalBuffer == NULL)
+ {
+ msg_Err(p_dec, "Allocate internal output buffer FAILED");
+ goto error;
+ }
+ else
+ {
+ p_sys->internalBufferSize = p_sys->internalBufferSizeComputed;
+
+#if ENABLE_STATS == 1
+ char fcc[5];
+ printf("INTERNAL SDK BUFFER PARAMETERS\n");
+ printf("- buffer width: %i x height: %i (%i bpp)\n", p_sys->internalBufferWidth, p_sys->internalBufferHeight, p_sys->sourcePixelSize);
+ printf("- buffer pitch: %d\n", p_sys->internalBufferPitch);
+ printf("- buffer size: %.2f KB\n", p_sys->internalBufferSize / 1000.0);
+ printf("- encoded pixel format: '%s'\n", getFourccStr_be(p_sys->decFormat, fcc));
+ printf("- buffer pixel format: '%s'\n", getFourccStr_be(p_sys->internalBufferPixelFormat, fcc));
+#endif // ENABLE_STATS
+ }
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+/*
+ CFHD_MetadataTrack metadataTrack = METADATATYPE_MODIFIED;
+ errorCode = CFHD_InitSampleMetadata(p_sys->metadataRef, metadataTrack, packet.sampleData, packet.sampleSize);
+
+ if (errorCode != CFHD_ERROR_OKAY)
+ {
+ // Not critical...
+ msg_Warn(p_dec, "CFHD_InitSampleMetadata(error '%i' / '%s')", errorCode, getErrorString(errorCode));
+ }
+ else
+ {
+ // Read some metadata here!
+ }
+*/
+ ////////////////////////////////////////////////////////////////////////////
+
+#if ENABLE_STATS == 1
+ timer_pic_start = clock();
+#endif
+
+ // Ask VLC for a picture buffer
+ decoder_UpdateVideoFormat(p_dec);
+ p_pic = decoder_NewPicture(p_dec);
+
+ if (p_pic == NULL)
+ {
+ char fcc[5];
+ msg_Err(p_dec, "CineForm DECODER plugin (unable to get an %i * %i picture_t '%s' output buffer)",
+ p_dec->fmt_out.video.i_width, p_dec->fmt_out.video.i_height, getFourccStr_le(p_dec->fmt_out.i_codec, fcc));
+ goto error;
+ }
+ else
+ {
+ p_pic->date = packet.samplePTS;
+ }
+
+
+#if ENABLE_STATS == 1
+ timer_pic_end = clock() - timer_pic_start;
+ ////////////////////////////////////////////////////////////////////////////
+ timer_dec_start = clock();
+#endif
+
+ if (p_sys->directMapping == true)
+ {
+ // 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 ENABLE_STATS == 1
+ timer_dec_end = clock() - timer_dec_start;
+#endif
+ }
+ else
+ {
+ // Use the CineForm SDK to do the decoding into our internal buffer
+ errorCode = CFHD_DecodeSample(p_sys->decoderRef,
+ packet.sampleData, packet.sampleSize,
+ p_sys->internalBuffer, p_sys->internalBufferPitch);
+
+#if ENABLE_STATS == 1
+ timer_dec_end = clock() - timer_dec_start;
+ timer_conv_start = clock();
+#endif
+
+ // Convert our internal buffer to VLC picture_t buffer format
+ pictureConvertion(p_sys, p_pic);
+
+#if ENABLE_STATS == 1
+ timer_conv_end = clock() - timer_conv_start;
+#endif
+ }
+
+ if (errorCode != CFHD_ERROR_OKAY)
+ {
+ msg_Err(p_dec, "CFHD_DecodeSample(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+ goto error;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Make sure this block will not comme back on the next round
+ if (p_block)
+ {
+ block_Release(p_block);
+ *pp_block = NULL;
+ }
+
+#if ENABLE_STATS == 1
+ timer_fn_end = clock() - timer_fn_start;
+
+ diff_fn = timer_fn_end * 1000 / CLOCKS_PER_SEC;
+ diff_pic = timer_pic_end * 1000 / CLOCKS_PER_SEC;
+ diff_dec = timer_dec_end * 1000 / CLOCKS_PER_SEC;
+ diff_conv = timer_conv_end * 1000 / CLOCKS_PER_SEC;
+
+ p_sys->total_fn += diff_fn;
+ p_sys->total_pic += diff_pic;
+ p_sys->total_dec += diff_dec;
+ p_sys->total_conv += diff_conv;
+/*
+ printf(">--- Decode callback (%lli ms)\n", diff_fn);
+ printf("- Frame decoding : %lli ms\n", diff_dec);
+ printf("- Pic creation : %lli ms\n", diff_pic);
+ printf("- Pic convertion : %lli ms\n", diff_conv);
+*/
+#endif // ENABLE_STATS
+
+ // Decoding successfull!
+ p_sys->sampleDecoded++;
+ return p_pic;
+
+skip:
+ p_sys->sampleSkipped++;
+ if (p_block)
+ {
+ block_Release(p_block);
+ *pp_block = NULL;
+ }
+ return NULL;
+
+error:
+ p_sys->sampleFailed++;
+ if (p_block)
+ {
+ block_Release(p_block);
+ *pp_block = NULL;
+ }
+ return NULL;
+}
+
+CFHD_Error printPreferedOutputFormats(decoder_sys_t *p_sys, cf_packet_t *packet)
+{
+ CFHD_Error errorCode = CFHD_ERROR_OKAY;
+
+ // Get the list of preferred output formats
+ int formatCount = 0;
+ int formatListLength = 4;
+ CFHD_PixelFormat formatList[4];
+
+ errorCode = CFHD_GetOutputFormats(p_sys->decoderRef, packet->sampleData, packet->sampleSize,
+ formatList, formatListLength, &formatCount);
+
+ if (errorCode != CFHD_ERROR_OKAY)
+ {
+ printf("CFHD_GetOutputFormats(error: '%i' / '%s')\n", errorCode, getErrorString(errorCode));
+ return errorCode;
+ }
+ else
+ {
+ char fcc[5];
+ printf("Output formats prefered by the CineForm SDK:\n");
+ for (int i = 0; i < formatListLength; i++)
+ {
+ printf("- %s\n", getFourccStr_be(formatList[i], fcc));
+ }
+ }
+
+ return errorCode;
+}
+
+CFHD_Error prepareDecoding(decoder_t *p_dec, decoder_sys_t *p_sys, cf_packet_t *packet)
+{
+ CFHD_Error errorCode = CFHD_ERROR_OKAY;
+/*
+ // Descriptors available:
+ CFHD_SAMPLE_INFO_CHANNELS
+ CFHD_SAMPLE_DISPLAY_WIDTH
+ CFHD_SAMPLE_DISPLAY_HEIGHT
+ CFHD_SAMPLE_KEY_FRAME
+ CFHD_SAMPLE_PROGRESSIVE
+ CFHD_SAMPLE_ENCODED_FORMAT
+*/
+ // 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 != CFHD_ERROR_OKAY)
+ {
+ printf("CFHD_GetSampleInfo(CFHD_SAMPLE_INFO_CHANNELS)(error: '%i' / '%s')\n", errorCode, getErrorString(errorCode));
+ return errorCode;
+ }
+ else
+ {
+ if (p_sys->sourceChannels < 1)
+ {
+ p_sys->sourceChannels = 1;
+ }
+ else if (p_sys->sourceChannels > 1)
+ {
+ printf("This video has more than one video channel (3d video?) and it's not supported by VLC.\n");
+ }
+ }
+
+ // 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 != CFHD_ERROR_OKAY)
+ {
+ printf("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 != CFHD_ERROR_OKAY)
+ {
+ printf("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 != CFHD_ERROR_OKAY)
+ {
+ printf("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;
+ p_sys->directMapping = true;
+ }
+ else if (p_sys->sourcePixelFormat == CFHD_ENCODED_FORMAT_RGB_444)
+ {
+ p_sys->decFormat = CFHD_PIXEL_FORMAT_RG24;
+ p_dec->fmt_out.i_codec = VLC_CODEC_RGB24;
+ p_sys->directMapping = false;
+ }
+ else if (p_sys->sourcePixelFormat == CFHD_ENCODED_FORMAT_RGBA_4444)
+ {
+ p_sys->decFormat = CFHD_PIXEL_FORMAT_BGRa;
+ p_dec->fmt_out.i_codec = VLC_CODEC_BGRA;
+ p_sys->directMapping = true;
+ }
+ else if (p_sys->sourcePixelFormat == CFHD_ENCODED_FORMAT_BAYER)
+ {
+ msg_Err(p_dec, "Cannot decode video in BAYER format... No known color convertion...");
+ return CFHD_ERROR_BADFORMAT;
+
+ p_sys->decFormat = CFHD_PIXEL_FORMAT_BYR2;
+ p_dec->fmt_out.i_codec = VLC_CODEC_BGRA;
+ p_sys->directMapping = false;
+ }
+ else if (p_sys->sourcePixelFormat == CFHD_ENCODED_FORMAT_YUVA_4444)
+ {
+ msg_Err(p_dec, "Cannot decode video in YUVA 4444 format... Not supposed to be supported...");
+ return CFHD_ERROR_BADFORMAT;
+
+ p_sys->decFormat = CFHD_PIXEL_FORMAT_YU64;
+ p_dec->fmt_out.i_codec = VLC_CODEC_YUVA;
+ p_sys->directMapping = false;
+ }
+ }
+
+ // Get sample size/format infos
+ errorCode = CFHD_PrepareToDecode(p_sys->decoderRef,
+ 0, 0, // if we want custom width & height? like decode in a lower resolution?
+ p_sys->decFormat,
+ p_sys->decSize,
+ p_sys->decFlags,
+ packet->sampleData,
+ packet->sampleSize,
+ &(p_sys->sourceWidth),
+ &(p_sys->sourceHeight),
+ &(p_sys->internalBufferPixelFormat));
+
+ if (errorCode != CFHD_ERROR_OKAY)
+ {
+ if (errorCode == CFHD_ERROR_BADFORMAT)
+ {
+ // Fallback
+ p_dec->fmt_out.i_codec = VLC_CODEC_BGRA;
+ p_sys->decFormat = CFHD_PIXEL_FORMAT_BGRa;
+ p_sys->directMapping = true;
+ }
+
+ printf("CFHD_PrepareToDecode(error: '%i' / '%s')\n", errorCode, getErrorString(errorCode));
+ return errorCode;
+ }
+
+ // Get the size of ONE pixel
+ errorCode = CFHD_GetPixelSize(p_sys->internalBufferPixelFormat, &(p_sys->sourcePixelSize));
+
+ if (errorCode != CFHD_ERROR_OKAY)
+ {
+ printf("CFHD_GetPixelSize(error: %i)\n", errorCode);
+ return errorCode;
+ }
+
+ // To decode GoPro 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)
+ {
+ printf("* Video width is not a multiple of 16. This will go poorly.\n");
+ //p_sys->directmapping = false;
+
+ // Get buffer pitch and round the width to a multiple of 16 bytes
+ p_sys->internalBufferWidth = (int)(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)
+ {
+ printf("* Video height is not a multiple of 8. This will go poorly.\n");
+ //p_sys->directmapping = false;
+
+ p_sys->internalBufferHeight = (int)(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;
+/*
+ // Get image pitch (or image stride) // note: funcion symbol from the SDK is not available
+ errorCode = CFHD_GetImagePitch(p_sys->sourceWidth, p_sys->sourcePixelFormat, &(p_sys->internalBufferPitch));
+
+ if (errorCode != CFHD_ERROR_OKAY)
+ {
+ printf("CFHD_GetImagePitch(error: %i)\n", errorCode);
+ return errorCode;
+ }
+
+ // Get image size // note: function symbol from the SDK is not available
+ errorCode = CFHD_GetImageSize(p_sys->sourceWidth, p_sys->sourceHeight, p_sys->sourcePixelFormat,
+ p_sys->stereoChannelSelection, p_sys->stereo3Dtype, &(p_sys->internalBufferSizeComputed));
+
+ if (errorCode != CFHD_ERROR_OKAY)
+ {
+ printf("CFHD_GetImageSize(error: %i)\n", errorCode);
+ return errorCode;
+ }
+*/
+ return errorCode;
+}
+
+bool pictureConvertion(decoder_sys_t *p_sys, picture_t *p_pic)
+{
+ bool supported = false;
+
+ if (p_sys->internalBufferPixelFormat == CFHD_PIXEL_FORMAT_RG24 &&
+ p_pic->format.i_chroma == VLC_CODEC_RGB24)
+ {
+ //printf("pictureConvertion(rgb convertion RG24 > RGB24)\n");
+
+ // Read input buffer from bottom to top; write to output buffer
+ int ii = 0;
+ for (int i = (p_sys->sourceHeight - 1); i >= 0; i--)
+ {
+ uint8_t *input_line = (uint8_t *)((p_sys->internalBuffer) + (i * p_sys->internalBufferPitch));
+ uint8_t *output_line = p_pic->p[0].p_pixels + (ii * p_pic->p[0].i_pitch);
+
+ memcpy(output_line, input_line, p_sys->internalBufferPitch);
+ ii++;
+ }
+ }
+ else if (p_sys->internalBufferPixelFormat == CFHD_PIXEL_FORMAT_RG24 &&
+ p_pic->format.i_chroma == VLC_CODEC_GBR_PLANAR)
+ {
+ //printf("pictureConvertion(rgb convertion RG24 > GBR planar)\n");
+
+ // Read input buffer from bottom to top; write to output buffer
+ int ii = 0;
+ for (int i = (p_sys->sourceHeight - 1); i >= 0; i--)
+ {
+ uint8_t *input_line = (uint8_t *)((p_sys->internalBuffer) + (i * p_sys->internalBufferPitch));
+
+ uint8_t *output_line_1 = p_pic->p[0].p_pixels + (ii * p_pic->p[0].i_pitch); // b
+ uint8_t *output_line_0 = p_pic->p[1].p_pixels + (ii * p_pic->p[1].i_pitch); // g
+ uint8_t *output_line_2 = p_pic->p[2].p_pixels + (ii * p_pic->p[2].i_pitch); // r
+ ii++;
+
+ for (int j = 0; j < p_sys->sourceWidth; j++)
+ {
+ *(output_line_0)++ = *(input_line)++;
+ *(output_line_1)++ = *(input_line)++;
+ *(output_line_2)++ = *(input_line)++;
+ }
+ }
+ }
+ else if (p_sys->internalBufferPixelFormat == CFHD_PIXEL_FORMAT_BGRa &&
+ p_pic->format.i_chroma == VLC_CODEC_BGRA)
+ {
+ //printf("pictureConvertion(rgb convertion BGRa > BGRA)\n");
+
+ // Read input buffer from top to bottom; write to output buffer
+ for (int i = 0; i < p_sys->sourceHeight; i++)
+ {
+ uint8_t *input_line = (uint8_t *)((p_sys->internalBuffer) + (i * p_sys->internalBufferPitch));
+ uint8_t *output_line = (uint8_t *)((p_pic->p[0].p_pixels) + (i * p_pic->p[0].i_pitch));
+
+ for (int j = 0; j < p_sys->sourceWidth; j++)
+ {
+ *(output_line)++ = *(input_line)++;
+ *(output_line)++ = *(input_line)++;
+ *(output_line)++ = *(input_line)++;
+ *(output_line)++ = *(input_line)++;
+ }
+ }
+ }
+ else if (p_sys->internalBufferPixelFormat == CFHD_PIXEL_FORMAT_BGRa &&
+ p_pic->format.i_chroma == VLC_CODEC_GBR_PLANAR)
+ {
+ //printf("pictureConvertion(rgb convertion BGRa > GBR planar)\n");
+
+ // Read input buffer from top to bottom; write to output buffer
+ for (int i = 0; i < p_sys->sourceHeight; i++)
+ {
+ uint8_t *input_line = (uint8_t *)((p_sys->internalBuffer) + (i * p_sys->internalBufferPitch));
+
+ uint8_t *p_dst1 = p_pic->p[0].p_pixels + (i * p_pic->p[0].i_pitch); // b
+ uint8_t *p_dst0 = p_pic->p[1].p_pixels + (i * p_pic->p[1].i_pitch); // g
+ uint8_t *p_dst2 = p_pic->p[2].p_pixels + (i * p_pic->p[2].i_pitch); // r
+
+ for (int j = 0; j < p_sys->sourceWidth; j++)
+ {
+ *(p_dst0)++ = *(input_line)++;
+ *(p_dst1)++ = *(input_line)++;
+ *(p_dst2)++ = *(input_line)++;
+ input_line++; // skip alpha component from input buffer
+ }
+ }
+ }
+ else if (p_sys->internalBufferPixelFormat == CFHD_PIXEL_FORMAT_YUYV &&
+ p_pic->format.i_chroma == VLC_CODEC_YUYV)
+ {
+ //printf("pictureConvertion(ycbcr convertion YUYV > YUYV)\n");
+
+ // Read input buffer from top to bottom; write to output buffer
+ for (int i = 0; i < p_sys->sourceHeight - 1; i++) // FIXME why the -1?
+ {
+ uint8_t *input_line = (uint8_t *)((p_sys->internalBuffer) + (i * p_sys->internalBufferPitch));
+ uint8_t *output_line = (uint8_t *)((p_pic->p[0].p_pixels) + (i * p_pic->p[0].i_pitch));
+
+ for (int j = 0; j < p_sys->sourceWidth; j++)
+ {
+ *(output_line)++ = *(input_line)++; // y0
+ *(output_line)++ = *(input_line)++; // u0
+ *(output_line)++ = *(input_line)++; // y1
+ *(output_line)++ = *(input_line)++; // v0
+ }
+ }
+ }
+ else if (p_sys->internalBufferPixelFormat == CFHD_PIXEL_FORMAT_YUYV &&
+ p_pic->format.i_chroma == VLC_CODEC_I422)
+ {
+ //printf("pictureConvertion(ycbcr convertion YUYV > I422)\n");
+ // TODO thread that
+
+ // Read input buffer from top to bottom; write to output buffer
+ for (int i = 0; i < p_sys->sourceHeight - 1; i++) // FIXME why the -1?
+ {
+ uint8_t *input_line = (uint8_t *)((p_sys->internalBuffer) + (i * p_sys->internalBufferPitch));
+
+ uint8_t *p_dst0 = p_pic->p[0].p_pixels + (i * p_pic->p[0].i_pitch); // y
+ uint8_t *p_dst1 = p_pic->p[1].p_pixels + (i * p_pic->p[1].i_pitch); // cb
+ uint8_t *p_dst2 = p_pic->p[2].p_pixels + (i * p_pic->p[2].i_pitch); // cr
+
+ for (int j = 0; j < p_sys->sourceWidth; j++)
+ {
+ *(p_dst0)++ = *(input_line)++; // y0
+ *(p_dst1)++ = *(input_line)++; // u0
+ *(p_dst0)++ = *(input_line)++; // y1
+ *(p_dst2)++ = *(input_line)++; // v0
+ }
+ }
+ }
+ else if (p_sys->internalBufferPixelFormat == CFHD_PIXEL_FORMAT_YU64 &&
+ p_pic->format.i_chroma == VLC_CODEC_I444)
+ {
+ //printf("pictureConvertion(ycbcr convertion YU64 > I444)\n");
+ // TODO implement this one
+ printf("pictureConvertion(no known convertion available)\n");
+
+ //p_pic->p[0].p_pixels = (uint8_t *)(p_sys->internalBuffer);
+ supported = false;
+ }
+ else
+ {
+ printf("pictureConvertion(no known convertion available)\n");
+
+ //p_pic->p[0].p_pixels = (uint8_t *)(p_sys->internalBuffer);
+
+ memcpy(p_pic->p[0].p_pixels, p_sys->internalBuffer, p_sys->internalBufferSize);
+ supported = false;
+ }
+
+ return supported;
+}
+
+/*****************************************************************************
+ * Encoder
+ *****************************************************************************/
+
+#if ENABLE_ENCODER == 1
+
+/**
+ * @brief Starts and init the CineForm encoder plugin.
+ * @param obj A pointer to a encoder_t structure allocated by VLC.
+ * @return VLC_SUCCESS or an error code.
+ *
+ * Note: this function will be called a first time for VLC to validate the encoder
+ * "presence", then closed. It will be called a second time for encoding the video.
+ */
+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)
+ {
+ return VLC_EGENERIC;
+ }
+ else
+ {
+ char fcc[5];
+ msg_Info(p_enc, "CineForm ENCODER plugin (OpenEncoder with fourCC '%s')",
+ getFourccStr_le(p_enc->fmt_out.i_codec, fcc));
+ }
+
+ 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_I422;
+
+ // Init encoder_sys_t // Allocate the memory needed to store the encoder's private context
+ if ((p_enc->p_sys = p_sys = (encoder_sys_t *)malloc(sizeof(*p_sys))) == NULL)
+ {
+ msg_Err(p_enc, "CineForm ENCODER 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 by VLC anyway
+
+ if (p_enc->fmt_in.video.i_frame_rate_base == 0)
+ p_sys->videoFrameRate = 25.0;
+ else if (p_enc->fmt_in.video.i_frame_rate_base == 1)
+ p_sys->videoFrameRate = p_enc->fmt_in.video.i_frame_rate;
+ else
+ {
+ p_sys->videoFrameRate = (double)(p_enc->fmt_in.video.i_frame_rate) / (double)(p_enc->fmt_in.video.i_frame_rate_base);
+ }
+
+ p_sys->directMapping = false;
+
+ 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 (I422) 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;
+ }
+
+#if ENABLE_STATS == 1
+ p_sys->total_fn = 0;
+ p_sys->total_conv = 0;
+ p_sys->total_enc = 0;
+#endif
+
+ // Init allocator
+ if ((p_sys->allocator.vtable = (struct cfhd_allocator_vtable *)malloc(sizeof(struct cfhd_allocator_vtable))) == NULL)
+ {
+ return VLC_ENOMEM;
+ }
+ p_sys->allocator.vtable->aligned_malloc = AlignedAlloc;
+ p_sys->allocator.vtable->aligned_free = AlignedFree;
+ p_sys->allocator.vtable->unaligned_malloc = UnalignedAlloc;
+ p_sys->allocator.vtable->unaligned_free = UnalignedFree;
+
+ // Init CineForm HD encoder
+ CFHD_Error errorCode = CFHD_OpenEncoder(&(p_sys->encoderRef), &(p_sys->allocator));
+ if (errorCode)
+ {
+ msg_Err(p_enc, "CFHD_OpenEncoder(error %i / %s)", errorCode, getErrorString(errorCode));
+ return VLC_EGENERIC;
+ }
+
+ // Open an interface to the CineForm HD 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;
+
+ msg_Info(p_enc, "CineForm ENCODER plugin (CloseEncoder)");
+
+#if ENABLE_STATS == 1
+ printf("CineForm ENCODER plugin (stats: %i samples)\n", p_sys->sampleCount);
+ if (p_sys->sampleCount > 0)
+ {
+ printf("- mean function time: %.2f ms\n", (double)(p_sys->total_fn) / (double)(p_sys->sampleCount));
+ printf("- mean pic conv time: %.2f ms\n", (double)(p_sys->total_conv) / (double)(p_sys->sampleCount));
+ printf("- mean encoding time: %.2f ms\n", (double)(p_sys->total_enc) / (double)(p_sys->sampleCount));
+ }
+#endif
+
+ // Cleanup
+ if (p_sys)
+ {
+ CFHD_CloseEncoder(p_sys->encoderRef);
+ CFHD_CloseMetadata(p_sys->metadataRef);
+
+ if (p_sys->internalBuffer && !p_sys->directMapping)
+ {
+ DeallocateBuffer(p_sys->internalBuffer);
+ p_sys->internalBuffer = NULL;
+ }
+
+ free(p_sys);
+ p_sys = NULL;
+ }
+}
+
+/**
+ * @brief EncodeBlock
+ * @param p_enc
+ * @param p_pic
+ * @return block_t
+ */
+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;
+
+ // Start timer
+ clock_t timer_fn_start = clock();
+
+ // Check picture datas
+ if (p_pic == NULL)
+ return NULL;
+
+ // Start 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 != CFHD_ERROR_OKAY)
+ {
+ printf("CFHD_GetPixelSize(error: '%i' / '%s')\n", errorCode, getErrorString(errorCode));
+ return NULL;
+ }
+
+ // To encode GoPro 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)
+ {
+ printf("* Video width is not a multiple of 16. Fixing that.\n");
+ p_sys->internalBufferWidth = (int)(ceil((float)(p_sys->videoWidth) / 16.0)) * 16;
+ }
+ else
+ p_sys->internalBufferWidth = p_sys->videoWidth;
+
+ if (p_sys->videoHeight % 8 != 0)
+ {
+ printf("* Video height is not a multiple of 8. Fixing that.\n");
+ p_sys->internalBufferHeight = (int)(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;
+ }
+
+#if ENABLE_STATS == 1
+ printEncodingFormats(level, p_sys->encFormat);
+#endif // ENABLE_STATS
+
+ // Allocate a buffer for the decoded frame
+ if (p_sys->internalBufferSizeComputed > p_sys->internalBufferSize)
+ {
+ if (p_sys->internalBuffer && !p_sys->directMapping)
+ {
+ DeallocateBuffer(p_sys->internalBuffer);
+ p_sys->internalBuffer = NULL;
+ }
+
+ // Allocate a new one
+ p_sys->internalBuffer = (char *)AllocateBuffer(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;
+
+#if ENABLE_STATS == 1
+ char fcc[5];
+ printf("INTERNAL SDK BUFFER PARAMETERS\n");
+ printf("- buffer width: %i x height: %i (%i bpp)\n", p_sys->internalBufferWidth, p_sys->internalBufferHeight, p_sys->internalBufferPixelSize);
+ printf("- buffer pitch: %d\n", p_sys->internalBufferPitch);
+ printf("- buffer size: %.2f KB\n", p_sys->internalBufferSize / 1000.0);
+ printf("- buffer pixel format: '%s'\n", getFourccStr_be(p_sys->internalBufferPixelFormat, fcc));
+#endif // ENABLE_STATS
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+/*
+ // Fill in metadatas here!
+ TAG_TIMECODE
+ TAG_TIMECODE_BASE
+ TAG_UNIQUE_FRAMENUM
+ TAG_VIDEO_CHANNELS
+*/
+ ////////////////////////////////////////////////////////////////////////////
+
+ clock_t timer_conv_start = clock();
+
+ if (p_enc->fmt_in.i_codec == VLC_CODEC_I422 && p_sys->internalBufferPixelFormat == CFHD_PIXEL_FORMAT_YUY2)
+ {
+ // I422 to YUY2 // Read input buffer from top to bottom; write to output buffer
+ for (int i = 0; i < p_sys->videoHeight - 1; i++)
+ {
+ uint8_t *output_line = (uint8_t *)((p_sys->internalBuffer) + (i * p_sys->internalBufferPitch));
+
+ uint8_t *p_src_y = p_pic->p[0].p_pixels + (i * p_pic->p[0].i_pitch); // y
+ uint8_t *p_src_cb = p_pic->p[1].p_pixels + (i * p_pic->p[1].i_pitch); // cb
+ uint8_t *p_src_cr = p_pic->p[2].p_pixels + (i * p_pic->p[2].i_pitch); // cr
+
+ for (int j = 0; j < p_pic->p[0].i_pitch; j++)
+ {
+ *(output_line)++ = *(p_src_y)++; // y0
+ *(output_line)++ = *(p_src_cb)++; // u0
+ *(output_line)++ = *(p_src_y)++; // y1
+ *(output_line)++ = *(p_src_cr)++; // v0
+ }
+ }
+ }
+ 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 if (p_enc->fmt_in.i_codec == VLC_CODEC_I444 && p_sys->internalBufferPixelFormat == CFHD_PIXEL_FORMAT_YU64)
+ {
+ //
+ }
+ else if (p_enc->fmt_in.i_codec == VLC_CODEC_GBR_PLANAR && p_sys->internalBufferPixelFormat == CFHD_PIXEL_FORMAT_BGRa)
+ {
+ // p_pic and internalbuffer pitch matches?
+ if (p_sys->internalBufferPitch == p_pic->p[0].i_pitch)
+ {
+ memcpy(p_sys->internalBuffer, p_pic->p[0].p_pixels, p_pic->p[0].i_pitch * p_pic->p[0].i_lines);
+ memcpy(p_sys->internalBuffer, p_pic->p[1].p_pixels, p_pic->p[1].i_pitch * p_pic->p[1].i_lines);
+ memcpy(p_sys->internalBuffer, p_pic->p[2].p_pixels, p_pic->p[2].i_pitch * p_pic->p[2].i_lines);
+ }
+ }
+ else
+ {
+ printf("pictureConvertion(no known conversion)\n");
+ p_sys->internalBuffer = (char *)(p_pic->p[0].p_pixels);
+ p_sys->directMapping = true;
+
+ //memcpy(p_sys->internalBuffer, p_pic->p[0].p_pixels, sizeof(p_pic->p[0].p_pixels));
+ }
+
+ clock_t timer_conv_end = clock() - timer_conv_start;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ clock_t timer_enc_start = clock();
+
+ // Encode the video frame
+ errorCode = CFHD_EncodeSample(p_sys->encoderRef, p_sys->internalBuffer, p_sys->internalBufferPitch);
+
+ if (errorCode != CFHD_ERROR_OKAY)
+ {
+ msg_Err(p_enc, "CFHD_EncodeSample(error: '%i' / '%s')", errorCode, getErrorString(errorCode));
+ return NULL;
+ }
+
+ clock_t timer_enc_end = clock() - timer_enc_start;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // 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;
+
+ // 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;
+ p_enc->fmt_in.video.i_width = p_sys->internalBufferWidth;
+ p_enc->fmt_in.video.i_height = p_sys->internalBufferHeight;
+ p_enc->fmt_in.video.i_visible_width = p_sys->videoWidth;
+ p_enc->fmt_in.video.i_visible_height = p_sys->videoHeight;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+#if ENABLE_STATS == 1
+ clock_t timer_fn_end = clock() - timer_fn_start;
+
+ int64_t diff_fn = timer_fn_end * 1000 / CLOCKS_PER_SEC;
+ int64_t diff_conv = timer_conv_end * 1000 / CLOCKS_PER_SEC;
+ int64_t diff_enc = timer_enc_end * 1000 / CLOCKS_PER_SEC;
+
+ p_sys->total_fn += diff_fn;
+ p_sys->total_conv += diff_conv;
+ p_sys->total_enc += diff_enc;
+/*
+ printf(">--- Encode callback (%lli ms)\n", diff_fn);
+ printf("Frame number: %d, encoded sample size: %i\n", p_sys->sampleCount, sampleSize);
+ printf("- Frame convertion : %lli ms\n", diff_conv);
+ printf("- Frame encoding : %lli ms\n", diff_enc);
+*/
+#endif // ENABLE_STATS
+
+ p_sys->sampleCount++;
+ return p_block;
+}
+
+#endif // ENABLE_ENCODER
diff --git a/modules/codec/cineformsdk/cineform_plugin.h b/modules/codec/cineformsdk/cineform_plugin.h
new file mode 100755
index 0000000000..b4630a80ea
--- /dev/null
+++ b/modules/codec/cineformsdk/cineform_plugin.h
@@ -0,0 +1,173 @@
+/*****************************************************************************
+ * cineform_plugin.h : CineForm decoder and encoder
+ *****************************************************************************
+ * Copyright (C) 2017 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Emeric Grange <egrange at gopro.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
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef MODULE_STRING
+#define MODULE_STRING "cineformsdk"
+#endif
+
+#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 <cineformsdk/CFHDDecoder.h>
+#include <cineformsdk/CFHDEncoder.h>
+#include <cineformsdk/CFHDTypes.h>
+#include <cineformsdk/CFHDError.h>
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct decoder_sys_t
+{
+ CFHD_DecoderRef decoderRef;
+ CFHD_MetadataRef metadataRef;
+ CFHD_ALLOCATOR allocator;
+
+ int SDKversion;
+ int SAMPLEversion;
+
+ // Flow control, mostly used for stats
+ uint64_t sampleCount;
+ uint64_t sampleDecoded;
+ uint64_t sampleSkipped;
+ 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
+
+ bool directMapping; ///< Indicate if we can decode directly into the VLC picture, or if we need an intermediate internalBuffer
+
+ // Internal decoding buffer
+ char *internalBuffer;
+ 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 skipFrames; ///< Indicate if we can skip the decoding of a frame already late for display
+ 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)
+
+ bool decSizeAuto;
+ bool decFormatAuto;
+
+ CFHD_Stereo3DType stereo3Dtype;
+ CFHD_StereoFlags stereoFlags;
+ CFHD_VideoSelect stereoChannelSelection;
+
+#if ENABLE_STATS == 1
+ int64_t total_fn;
+ int64_t total_dec;
+ int64_t total_pic;
+ int64_t total_conv;
+#endif
+};
+
+typedef struct cf_packet_t {
+ unsigned char *sampleData;
+ size_t sampleSize;
+ int samplePTS;
+} cf_packet_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_sys_t *, picture_t *);
+ CFHD_Error prepareDecoding(decoder_t *p_dec, decoder_sys_t *p_sys, cf_packet_t *packet);
+ CFHD_Error printPreferedOutputFormats(decoder_sys_t *p_sys, cf_packet_t *packet);
+ void printPictureInfos(picture_t *);
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+#if ENABLE_ENCODER == 1
+
+struct encoder_sys_t
+{
+ 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;
+ double videoFrameRate;
+
+ 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;
+
+#if ENABLE_STATS == 1
+ int64_t total_fn;
+ int64_t total_conv;
+ int64_t total_enc;
+#endif
+};
+
+int OpenEncoder(vlc_object_t *);
+void CloseEncoder(vlc_object_t *);
+block_t *EncodeBlock(encoder_t *, picture_t *);
+
+#endif // ENABLE_ENCODER
+
+////////////////////////////////////////////////////////////////////////////////
+#endif // CINEFORM_PLUGIN_H
diff --git a/modules/codec/cineformsdk/cineform_settings.c b/modules/codec/cineformsdk/cineform_settings.c
new file mode 100755
index 0000000000..a5fb94ac32
--- /dev/null
+++ b/modules/codec/cineformsdk/cineform_settings.c
@@ -0,0 +1,427 @@
+/*****************************************************************************
+ * cineform_settings.c : CineForm decoder and encoder
+ *****************************************************************************
+ * Copyright (C) 2017 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Emeric Grange <egrange at gopro.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_Info(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;
+ }
+ else if (strcmp("AUTO", string) == 0)
+ {
+ p_dec->p_sys->decSizeAuto = true;
+ }
+
+ 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_Info(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)
+{
+ CFHD_PixelFormat setting = CFHD_PIXEL_FORMAT_UNKNOWN;
+
+ char *string = var_InheritString(p_dec, "cineform-output-formats");
+ if (string)
+ {
+ msg_Info(p_dec, "> cineform-output-formats: '%s'", string);
+
+ if (strcmp("YUYV", string) == 0)
+ {
+ // YUYV is also known as YUY2
+ setting = CFHD_PIXEL_FORMAT_YUYV;
+ p_dec->fmt_out.i_codec = VLC_CODEC_YUYV;
+
+ p_dec->p_sys->decFormatAuto = false;
+ p_dec->p_sys->directMapping = true;
+ }
+ else if (strcmp("I422", string) == 0)
+ {
+ setting = CFHD_PIXEL_FORMAT_YUYV;
+ p_dec->fmt_out.i_codec = VLC_CODEC_I422;
+
+ p_dec->p_sys->decFormatAuto = false;
+ p_dec->p_sys->directMapping = false; // software convertion will be used
+ }
+ else if (strcmp("I444", string) == 0)
+ {
+ setting = CFHD_PIXEL_FORMAT_YU64;
+ p_dec->fmt_out.i_codec = VLC_CODEC_I444;
+
+ p_dec->p_sys->decFormatAuto = false;
+ p_dec->p_sys->directMapping = false; // software convertion will be used
+ }
+ else if (strcmp("BGRa", string) == 0)
+ {
+ setting = CFHD_PIXEL_FORMAT_BGRa;
+ p_dec->fmt_out.i_codec = VLC_CODEC_BGRA;
+
+ p_dec->p_sys->decFormatAuto = false;
+ p_dec->p_sys->directMapping = true;
+ }
+ else if (strcmp("RG24", string) == 0)
+ {
+ setting = CFHD_PIXEL_FORMAT_RG24;
+ p_dec->fmt_out.i_codec = VLC_CODEC_RGB24;
+
+ p_dec->p_sys->decFormatAuto = false;
+ p_dec->p_sys->directMapping = true;
+ }
+ else if (strcmp("AUTO", string) == 0)
+ {
+ setting = CFHD_PIXEL_FORMAT_UNKNOWN;
+ p_dec->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_Info(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_Info(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;
+ }
+/*
+ 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_Info(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_Info(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_Info(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_Info(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/cineformsdk/cineform_settings.h b/modules/codec/cineformsdk/cineform_settings.h
new file mode 100755
index 0000000000..d761f6efc8
--- /dev/null
+++ b/modules/codec/cineformsdk/cineform_settings.h
@@ -0,0 +1,94 @@
+/*****************************************************************************
+ * cineform_settings.h : CineForm decoder and encoder
+ *****************************************************************************
+ * Copyright (C) 2017 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Emeric Grange <egrange at gopro.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 <cineformsdk/CFHDTypes.h>
+
+// Decoder
+
+#define DEC_CFG_PREFIX "cineform-"
+
+#define SKIP_FRAMES_TEXT "Skip late frames?"
+#define SKIP_FRAMES_LONGTEXT "You can choose to drop late frames (keeping correct video speed) instead of forcing to draw them (slowing down the video speed)."
+
+#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[] = {"AUTO", "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);
+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 quality you want."
+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.15.0
More information about the vlc-devel
mailing list