# HG changeset patch # User Bhavna Hariharan <bha...@multicorewareinc.com> # Date 1490173400 -19800 # Wed Mar 22 14:33:20 2017 +0530 # Node ID f0545a714a70c18bc462e477ce5ce962b9253cb7 # Parent 94d59c325e975888e4f7b152cc90b4199d9d24c4 dhdr10-info: add tone-mapping parser files
diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/BasicStructures.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/BasicStructures.cpp Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,40 @@ +/** + * @file BasicStructures.cpp + * @brief Defines the structure of metadata parameters + * @author Daniel Maximiliano Valenzuela, Seongnam Oh. + * @create date 03/01/2017 + * @version 0.0.1 + * + * Copyright @ 2017 Samsung Electronics, DMS Lab, Samsung Research America and Samsung Research Tijuana + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 "BasicStructures.h" +#include "vector" + +struct PercentileLuminance{ + + float averageLuminance = 0.0; + float maxRLuminance = 0.0; + float maxGLuminance = 0.0; + float maxBLuminance = 0.0; + int order; + std::vector<unsigned int> percentiles; +}; + + + diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/BasicStructures.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/BasicStructures.h Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,50 @@ +/** + * @file BasicStructures.h + * @brief Defines the structure of metadata parameters + * @author Daniel Maximiliano Valenzuela, Seongnam Oh. + * @create date 03/01/2017 + * @version 0.0.1 + * + * Copyright @ 2017 Samsung Electronics, DMS Lab, Samsung Research America and Samsung Research Tijuana + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 BASICSTRUCTURES_H +#define BASICSTRUCTURES_H + +#include <vector> + + +struct LuminanceParameters +{ + float averageLuminance = 0.0; + float maxRLuminance = 0.0; + float maxGLuminance = 0.0; + float maxBLuminance = 0.0; + int order; + std::vector<unsigned int> percentiles; +}; + +struct BezierCurveData +{ + int order; + int sPx; + int sPy; + std::vector<int> coeff; +}; + +#endif // BASICSTRUCTURES_H diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/CMakeLists.txt Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,175 @@ +# vim: syntax=cmake +if(ENABLE_DYNAMIC_HDR10) + +add_library(dynamicHDR10 OBJECT + BasicStructures.cpp BasicStructures.h + json11/json11.cpp json11/json11.h + JsonHelper.cpp JsonHelper.h + metadataFromJson.cpp metadataFromJson.h + SeiMetadataDictionary.cpp SeiMetadataDictionary.h + hdr10plus.h + api.cpp ) + +else() +cmake_minimum_required (VERSION 2.8.11) +project(dynamicHDR10) +include(CheckIncludeFiles) +include(CheckFunctionExists) +include(CheckSymbolExists) +include(CheckCXXCompilerFlag) + +SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}") + +if(GCC) + add_definitions(-Wall -Wextra -Wshadow) + add_definitions(-D__STDC_LIMIT_MACROS=1) + add_definitions(-std=c++11) + if(ENABLE_PIC) + add_definitions(-fPIC) + endif(ENABLE_PIC) + if(NATIVE_BUILD) + if(INTEL_CXX) + add_definitions(-xhost) + else() + add_definitions(-march=native) + endif() + elseif(X86 AND NOT X64) + string(FIND "${CMAKE_CXX_FLAGS}" "-march" marchPos) + if(marchPos LESS "0") + add_definitions(-march=i686) + if(WIN32 AND NOT INTEL_CXX AND NOT CLANG AND + CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6.0 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0) + add_definitions(-mpreferred-stack-boundary=2) + endif() + endif() + endif() + if(ARM AND CROSS_COMPILE_ARM) + set(ARM_ARGS -march=armv6 -mfloat-abi=soft -mfpu=vfp -marm -fPIC) + elseif(ARM) + find_package(Neon) + if(CPU_HAS_NEON) + set(ARM_ARGS -mcpu=native -mfloat-abi=hard -mfpu=neon -marm -fPIC) + add_definitions(-DHAVE_NEON) + else() + set(ARM_ARGS -mcpu=native -mfloat-abi=hard -mfpu=vfp -marm) + endif() + endif() + add_definitions(${ARM_ARGS}) + if(FPROFILE_GENERATE) + if(INTEL_CXX) + add_definitions(-prof-gen -prof-dir="${CMAKE_CURRENT_BINARY_DIR}") + list(APPEND LINKER_OPTIONS "-prof-gen") + else() + check_cxx_compiler_flag(-fprofile-generate CC_HAS_PROFILE_GENERATE) + if(CC_HAS_PROFILE_GENERATE) + add_definitions(-fprofile-generate) + list(APPEND LINKER_OPTIONS "-fprofile-generate") + endif(CC_HAS_PROFILE_GENERATE) + endif(INTEL_CXX) + endif(FPROFILE_GENERATE) + if(FPROFILE_USE) + if(INTEL_CXX) + add_definitions(-prof-use -prof-dir="${CMAKE_CURRENT_BINARY_DIR}") + list(APPEND LINKER_OPTIONS "-prof-use") + else() + check_cxx_compiler_flag(-fprofile-use CC_HAS_PROFILE_USE) + check_cxx_compiler_flag(-fprofile-correction CC_HAS_PROFILE_CORRECTION) + check_cxx_compiler_flag(-Wno-error=coverage-mismatch CC_HAS_COVMISMATCH) + if(CC_HAS_PROFILE_USE) + add_definitions(-fprofile-use) + list(APPEND LINKER_OPTIONS "-fprofile-use") + endif(CC_HAS_PROFILE_USE) + if(CC_HAS_PROFILE_CORRECTION) + # auto-correct corrupted counters (happens a lot with x265) + add_definitions(-fprofile-correction) + endif(CC_HAS_PROFILE_CORRECTION) + if(CC_HAS_COVMISMATCH) + # ignore coverage mismatches (also happens a lot) + add_definitions(-Wno-error=coverage-mismatch) + endif(CC_HAS_COVMISMATCH) + endif(INTEL_CXX) + endif(FPROFILE_USE) + if(STATIC_LINK_CRT) + add_definitions(-static) + list(APPEND LINKER_OPTIONS "-static") + endif(STATIC_LINK_CRT) + check_cxx_compiler_flag(-Wno-strict-overflow CC_HAS_NO_STRICT_OVERFLOW) + check_cxx_compiler_flag(-Wno-narrowing CC_HAS_NO_NARROWING) + check_cxx_compiler_flag(-Wno-array-bounds CC_HAS_NO_ARRAY_BOUNDS) + if (CC_HAS_NO_ARRAY_BOUNDS) + add_definitions(-Wno-array-bounds) # these are unhelpful + endif() + check_cxx_compiler_flag(-ffast-math CC_HAS_FAST_MATH) + if (CC_HAS_FAST_MATH) + add_definitions(-ffast-math) + endif() + check_cxx_compiler_flag(-mstackrealign CC_HAS_STACK_REALIGN) + if (CC_HAS_STACK_REALIGN) + add_definitions(-mstackrealign) + endif() + # Disable exceptions. Reduce executable size, increase compability. + check_cxx_compiler_flag(-fno-exceptions CC_HAS_FNO_EXCEPTIONS_FLAG) + if(CC_HAS_FNO_EXCEPTIONS_FLAG) + add_definitions(-fno-exceptions) + endif() + set(FSANITIZE "" CACHE STRING "-fsanitize options for GCC/clang") + if(FSANITIZE) + add_definitions(-fsanitize=${FSANITIZE}) + # clang and gcc need the sanitize options to be passed at link + # time so the appropriate ASAN/TSAN runtime libraries can be + # linked. + list(APPEND LINKER_OPTIONS "-fsanitize=${FSANITIZE}") + endif() + option(ENABLE_AGGRESSIVE_CHECKS "Enable stack protection and -ftrapv" OFF) + if(ENABLE_AGGRESSIVE_CHECKS) + # use with care, -ftrapv can cause testbench SIGILL exceptions + # since it is testing corner cases of signed integer math + add_definitions(-DUSING_FTRAPV=1) + check_cxx_compiler_flag(-fsanitize=undefined-trap CC_HAS_CATCH_UNDEFINED) # clang + check_cxx_compiler_flag(-ftrapv CC_HAS_FTRAPV) # gcc + check_cxx_compiler_flag(-fstack-protector-all CC_HAS_STACK_PROTECT) # gcc + if(CC_HAS_FTRAPV) + add_definitions(-ftrapv) + endif() + if(CC_HAS_CATCH_UNDEFINED) + add_definitions(-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error) + endif() + if(CC_HAS_STACK_PROTECT) + add_definitions(-fstack-protector-all) + if(MINGW) + list(APPEND PLATFORM_LIBS ssp) + endif() + endif() + endif(ENABLE_AGGRESSIVE_CHECKS) + execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE CC_VERSION) +endif(GCC) + +# Build options +set(LIB_INSTALL_DIR lib CACHE STRING "Install location of libraries") +set(BIN_INSTALL_DIR bin CACHE STRING "Install location of executables") + +option(ENABLE_SHARED "Build shared library" OFF) + +if(ENABLE_SHARED) + add_library(dynamicHDR10 SHARED + json11/json11.cpp json11/json11.h + BasicStructures.cpp BasicStructures.h + JsonHelper.cpp JsonHelper.h + metadataFromJson.cpp metadataFromJson.h + SeiMetadataDictionary.cpp SeiMetadataDictionary.h + hdr10plus.h api.cpp ) +else() + add_library(dynamicHDR10 STATIC + json11/json11.cpp json11/json11.h + BasicStructures.cpp BasicStructures.h + JsonHelper.cpp JsonHelper.h + metadataFromJson.cpp metadataFromJson.h + SeiMetadataDictionary.cpp SeiMetadataDictionary.h + hdr10plus.h api.cpp ) +endif() + +install (TARGETS dynamicHDR10 + LIBRARY DESTINATION ${LIB_INSTALL_DIR} + ARCHIVE DESTINATION ${LIB_INSTALL_DIR}) +install(FILES hdr10plus.h DESTINATION include) +endif() \ No newline at end of file diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/JsonHelper.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/JsonHelper.cpp Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,221 @@ +/** + * @file JsonHelper.cpp + * @brief Helper class for JSON parsing + * @author Daniel Maximiliano Valenzuela, Seongnam Oh. + * @create date 03/01/2017 + * @version 0.0.1 + * + * Copyright @ 2017 Samsung Electronics, DMS Lab, Samsung Research America and Samsung Research Tijuana + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 "JsonHelper.h" +#include "sys/stat.h" +#include <fstream> +#include <iostream> +using namespace std; + +JsonObject JsonHelper::add(string key, string value, JsonObject &json) +{ + + json[key] = value; + return json; +} + +bool JsonHelper::writeJson(JsonObject json, string path) +{ + if(!validatePathExtension(path)) + { + return false; + } + + ofstream JsonSaveFile(path); + string jsonString; + jsonString = dump(json); + JsonSaveFile << jsonString; + JsonSaveFile.close(); + return true; +} + +bool JsonHelper::writeJson(JsonArray json, string path) +{ + if(!validatePathExtension(path)) + { + return false; + } + + string arrayString = "["; + size_t jsonSize = json.size(); + for(size_t i = 0; i < jsonSize; ++i) + { + arrayString += "\n" + dump(json.at(i).object_items(), 1); + if(i != jsonSize - 1) + { + arrayString += ","; + } + } + arrayString += "\n]"; + + ofstream JsonSaveFile(path); + JsonSaveFile << arrayString; + JsonSaveFile.close(); + return true; +} + +string JsonHelper::dump(JsonObject json, int extraTab) +{ + string dump = Json(json).dump(); + //[defensive programming] possibly check if dump returns a invalid string + string out = ""; + unsigned int tabCounter = extraTab; + printTabs(out,tabCounter); + for(unsigned int i = 0; i < dump.size(); ++i) + { + if(dump[i] == '{' || dump[i] == '[') + { + out += dump[i]; + out += '\n'; + ++tabCounter; + printTabs(out, tabCounter); + } + else if(dump[i] == '}' || dump[i] == ']') + { + out += '\n'; + --tabCounter; + printTabs(out, tabCounter); + out += dump[i]; + } + else if(dump[i] == ',') + { + out += dump[i]; + out += '\n'; + printTabs(out, tabCounter); + ++i; //skip blank space following comma + } + else + { + out += dump[i]; + } + } + return out; +} + +void JsonHelper::printTabs(string &out, int tabCounter) +{ + for(int i = 0; i < tabCounter; ++i) + { + out += '\t'; + } +} + +JsonObject JsonHelper::readJson(string path) +{ + std::size_t ext = path.find_last_of('.'); + std::string extension = path.substr(ext+1); + + if(extension.compare("json") && extension.compare("JSON")) + { + std::cout << "Fail open file, extension not valid!" << std::endl; + return JsonObject(); + } + + struct stat buffer; + if(stat(path.c_str(),&buffer)) + { + std::cout << "Fail open file, file doesn't exist" << std::endl; + return JsonObject(); + } + + ifstream tfile; + string json_str; + string json_str2; + string err = ""; + tfile.open(path); + while(tfile) + { + std::getline(tfile, json_str); + json_str2.append(json_str); + } + + tfile.close(); + size_t beginning = json_str2.find_first_of("{"); + int fixchar = json_str2[json_str2.size() - 2] == '}' ? 1 : 0; + return Json::parse(json_str2.substr(beginning,json_str2.size() - fixchar),err).object_items(); +} + +JsonArray JsonHelper::readJsonArray(const string &path) +{ + std::size_t ext = path.find_last_of('.'); + std::string extension = path.substr(ext+1); + + if(extension.compare("json") && extension.compare("JSON")) + { + std::cout << "Fail open file, extension not valid!" << std::endl; + return JsonArray(); + } + + struct stat buffer; + if(stat(path.c_str(),&buffer)) + { + std::cout << "Fail open file, file doesn't exist" << std::endl; + return JsonArray(); + } + + ifstream tfile; + string json_str; + string json_str2; + string err = ""; + tfile.open(path); + while(tfile) + { + std::getline(tfile, json_str); + json_str2.append(json_str); + } + + tfile.close(); + + size_t beginning = json_str2.find_first_of("["); + int fixchar = json_str2[json_str2.size() - 2] == ']' ? 1 : 0; + return Json::parse(json_str2.substr(beginning,json_str2.size() - fixchar),err).array_items(); +} + +bool JsonHelper::validatePathExtension(string &path) +{ + + if(path.empty()) + { + std::cout << "Fail saving json file" << std::endl; + return false; + } + std::size_t ext = path.find_last_of('.'); + std::string realFilePath = path; + if(ext == std::string::npos) + { + realFilePath += ".json"; + } + else + { + std::string extension = path.substr(ext+1); + if(extension.compare("json") && extension.compare("JSON")) + { + std::cout << "Fail saving file, extension not valid!" << std::endl; + return false; + } + } + path = realFilePath; + return true; +} diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/JsonHelper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/JsonHelper.h Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,54 @@ +/** + * @file JsonHelper.h + * @brief Helper class for JSON parsing + * @author Daniel Maximiliano Valenzuela, Seongnam Oh. + * @create date 03/01/2017 + * @version 0.0.1 + * + * Copyright @ 2017 Samsung Electronics, DMS Lab, Samsung Research America and Samsung Research Tijuana + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 JSON_H +#define JSON_H +#include <string> +#include <iostream> +#include "json11/json11.h" + +using std::string; +using namespace json11; +typedef Json::object JsonObject; +typedef Json::array JsonArray; + +class JsonHelper +{ +public: + static JsonObject readJson(string path); + static JsonArray readJsonArray(const string &path); + static string dump(JsonArray json); + static string dump(JsonObject json, int extraTab = 0); + + static bool writeJson(JsonObject json , string path); + static bool writeJson(JsonArray json, string path); + static JsonObject add(string key, string value, JsonObject &json); +private: + static void printTabs(string &out, int tabCounter); + JsonObject mJson; + static bool validatePathExtension(string &path); +}; + +#endif // JSON_H diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/LICENSE.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/LICENSE.txt Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,20 @@ +Copyright @ 2017 Samsung Electronics, DMS Lab, Samsung Research America and Samsung Research Tijuana + +This software is the confidential and proprietary information of Samsung Electronics, Inc. ("Confidential Information"). +You shall not disclose such Confidential Information and shall use it only in accordance with the terms of the license agreement +you entered into with Samsung. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +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 General Public License for more details. + +You should have received a copy of the GNU 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. \ No newline at end of file diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/SeiMetadataDictionary.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/SeiMetadataDictionary.cpp Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,113 @@ +/** + * @file SeiMetadataDictionary.cpp + * @brief Defines the tagname for each metadata value in a JSON dynamic tone mapping file. + * @author Daniel Maximiliano Valenzuela, Seongnam Oh. + * @create date 03/01/2017 + * @version 0.0.1 + * + * Copyright @ 2017 Samsung Electronics, DMS Lab, Samsung Research America and Samsung Research Tijuana + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 "SeiMetadataDictionary.h" + +using namespace SeiMetadataDictionary; + +const std::string JsonDataKeys::LocalParameters = std::string("LocalParameters"); +const std::string JsonDataKeys::TargetDisplayLuminance = std::string("TargetedSystemDisplayMaximumLuminance"); + +const std::string BezierCurveNames::TagName = std::string("BezierCurveData"); +const std::string BezierCurveNames::NumberOfAnchors = std::string("NumberOfAnchors"); +const std::string BezierCurveNames::KneePointX = std::string("KneePointX"); +const std::string BezierCurveNames::KneePointY = std::string("KneePointY"); +const std::string BezierCurveNames::Anchors[] = {std::string("Anchor0"), + std::string("Anchor1"), + std::string("Anchor2"), + std::string("Anchor3"), + std::string("Anchor4"), + std::string("Anchor5"), + std::string("Anchor6"), + std::string("Anchor7"), + std::string("Anchor8"), + std::string("Anchor9"), + std::string("Anchor10"), + std::string("Anchor11"), + std::string("Anchor12"), + std::string("Anchor13")}; + + +const std::string EllipseSelectionNames::WindowUpperLeftCornerX = std::string("WindowUpperLeftCornerX"); +const std::string EllipseSelectionNames::WindowUpperLeftCornerY = std::string("WindowUpperLeftCornerY"); +const std::string EllipseSelectionNames::WindowLowerRightCornerX = std::string("WindowLowerRightCornerX"); +const std::string EllipseSelectionNames::WindowLowerRightCornerY = std::string("WindowLowerRightCornerY"); +const std::string EllipseSelectionNames::WindowData = std::string("WindowData"); + + +const std::string EllipseNames::TagName = std::string("EllipseData"); +const std::string EllipseNames::RotationAngle = std::string("RotationAngle"); +const std::string EllipseNames::CenterOfEllipseX = std::string("CenterOfEllipseX"); +const std::string EllipseNames::CenterOfEllipseY = std::string("CenterOfEllipseY"); +const std::string EllipseNames::OverlapProcessOption = std::string("OverlapProcessOption"); +const std::string EllipseNames::SemiMajorAxisExternalEllipse = std::string("SemimajorAxisExternalEllipse"); +const std::string EllipseNames::SemiMinorAxisExternalEllipse = std::string("SemiminorAxisExternalEllipse"); +const std::string EllipseNames::SemiMajorAxisInternalEllipse = std::string("SemimajorAxisInternalEllipse"); + + +const std::string PercentileNames::TagName = std::string("PercentileLuminance"); +const std::string PercentileNames::NumberOfPercentiles = std::string("NumberOfPercentiles"); +const std::string PercentileNames::PercentilePercentageValue[] = {std::string("PercentilePercentage0"), + std::string("PercentilePercentage1"), + std::string("PercentilePercentage2"), + std::string("PercentilePercentage3"), + std::string("PercentilePercentage4"), + std::string("PercentilePercentage5"), + std::string("PercentilePercentage6"), + std::string("PercentilePercentage7"), + std::string("PercentilePercentage8"), + std::string("PercentilePercentage9"), + std::string("PercentilePercentage10"), + std::string("PercentilePercentage11"), + std::string("PercentilePercentage12"), + std::string("PercentilePercentage13"), + std::string("PercentilePercentage14")}; + +const std::string PercentileNames::PercentileLuminanceValue[] = {std::string("PercentileLuminance0"), + std::string("PercentileLuminance1"), + std::string("PercentileLuminance2"), + std::string("PercentileLuminance3"), + std::string("PercentileLuminance4"), + std::string("PercentileLuminance5"), + std::string("PercentileLuminance6"), + std::string("PercentileLuminance7"), + std::string("PercentileLuminance8"), + std::string("PercentileLuminance9"), + std::string("PercentileLuminance10"), + std::string("PercentileLuminance11"), + std::string("PercentileLuminance12"), + std::string("PercentileLuminance13"), + std::string("PercentileLuminance14")}; + + + +const std::string LuminanceNames::TagName = std::string("LuminanceParameters"); +const std::string LuminanceNames::AverageRGB = std::string("AverageRGB"); +const std::string LuminanceNames::MaxSCL0 = std::string("MaxScl0"); +const std::string LuminanceNames::MaxSCL1 = std::string("MaxScl1"); +const std::string LuminanceNames::MaxSCL2 = std::string("MaxScl2"); + + + diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/SeiMetadataDictionary.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/SeiMetadataDictionary.h Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,97 @@ +/** + * @file SeiMetadataDictionary.h + * @brief Defines the tagname for each metadata value in a JSON dynamic tone mapping file. + * @author Daniel Maximiliano Valenzuela, Seongnam Oh. + * @create date 03/01/2017 + * @version 0.0.1 + * + * Copyright @ 2017 Samsung Electronics, DMS Lab, Samsung Research America and Samsung Research Tijuana + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 SEIMETADATADICTIONARY_H +#define SEIMETADATADICTIONARY_H + +#include "SeiMetadataDictionary.h" + +#include <string> + +namespace SeiMetadataDictionary +{ + + class JsonDataKeys + { + public: + static const std::string LocalParameters; + static const std::string TargetDisplayLuminance; + }; + + //Bezier Curve Data + class BezierCurveNames + { + public: + static const std::string TagName; + static const std::string NumberOfAnchors; + static const std::string KneePointX; + static const std::string KneePointY; + static const std::string Anchors[14]; + }; + //Ellipse Selection Data + class EllipseSelectionNames + { + public: + static const std::string WindowUpperLeftCornerX; + static const std::string WindowUpperLeftCornerY; + static const std::string WindowLowerRightCornerX; + static const std::string WindowLowerRightCornerY; + static const std::string WindowData; + }; + //Ellipse Data + class EllipseNames + { + public: + static const std::string TagName; + static const std::string RotationAngle; + static const std::string CenterOfEllipseX; + static const std::string CenterOfEllipseY; + static const std::string OverlapProcessOption; + static const std::string SemiMajorAxisExternalEllipse; + static const std::string SemiMinorAxisExternalEllipse; + static const std::string SemiMajorAxisInternalEllipse; + }; + //Percentile Luminance + class PercentileNames + { + public: + static const std::string TagName; + static const std::string NumberOfPercentiles; + static const std::string PercentilePercentageValue[15]; + static const std::string PercentileLuminanceValue[15]; + }; + //Luminance Parameters + class LuminanceNames + { + public: + static const std::string TagName; + static const std::string AverageRGB; + static const std::string MaxSCL0; + static const std::string MaxSCL1; + static const std::string MaxSCL2; + }; +} + +#endif // SEIMETADATADICTIONARY_H diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/api.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/api.cpp Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,79 @@ +/** + * @file api.cpp + * @brief Implementation of hdr10plus API functions. + * @author Daniel Maximiliano Valenzuela, Seongnam Oh. + * @create date 03/01/2017 + * @version 0.0.1 + * + * Copyright @ 2017 Samsung Electronics, DMS Lab, Samsung Research America and Samsung Research Tijuana + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 "hdr10plus.h" +#include "metadataFromJson.h" + +bool hdr10plus_json_to_frame_cim(const char* path, uint32_t frameNumber, uint8_t *&cim) +{ + metadataFromJson meta; + return meta.frameMetadataFromJson(path, + frameNumber, + cim); +} + +int hdr10plus_json_to_movie_cim(const char* path, uint8_t **&cim) +{ + metadataFromJson meta; + return meta.movieMetadataFromJson(path, cim); +} + +bool hdr10plus_json_to_frame_eif(const char* path, uint32_t frameNumber, uint8_t *&eif) +{ + metadataFromJson meta; + return meta.extendedInfoFrameMetadataFromJson(path, + frameNumber, + eif); +} + +int hdr10plus_json_to_movie_eif(const char* path, uint8_t **&eif) +{ + metadataFromJson meta; + return meta.movieExtendedInfoFrameMetadataFromJson(path, eif); +} + + +void hdr10plus_clear_movie(uint8_t **&metadata, const int numberOfFrames) +{ + if(metadata) + { + metadataFromJson meta; + meta.clear(metadata, numberOfFrames); + } +} + +static const hdr10plus_api libapi = +{ + &hdr10plus_json_to_frame_cim, + &hdr10plus_json_to_movie_cim, + &hdr10plus_json_to_frame_eif, + &hdr10plus_json_to_movie_eif, + &hdr10plus_clear_movie, +}; + +const hdr10plus_api* hdr10plus_api_get() +{ + return &libapi; +} diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/hdr10plus.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/hdr10plus.h Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,101 @@ +/** + * @file hdr10plus.h + * @brief Definition of hdr10plus functions. + * @author Daniel Maximiliano Valenzuela, Seongnam Oh. + * @create date 03/01/2017 + * @version 0.0.1 + * + * Copyright @ 2017 Samsung Electronics, DMS Lab, Samsung Research America and Samsung Research Tijuana + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 <stdint.h> + +#ifndef HDR10PLUS_H +#define HDR10PLUS_H + + +/* hdr10plus_json_to_frame_cim: + * Parses the json file containing the Creative Intent Metadata DTM for a frame of + * video into a bytestream to be encoded into the resulting video stream. + * path is the file path of the JSON file containing the DTM for the video. + * frameNumber is the number of the frame to get the metadata for. + * cim will get filled with the byte array containing the actual metadata. + * Returns true in case of success. + */ +bool hdr10plus_json_to_frame_cim(const char* path, uint32_t frameNumber, uint8_t *&cim); + +/* hdr10plus_json_to_movie_cim: + * Parses the json file containing the Creative Intent Metadata DTM for the video + * into a bytestream to be encoded into the resulting video stream. + * path is the file path of the JSON file containing the DTM for the video. + * frameNumber is the number of the frame to get the metadata for. + * cim will get filled with the byte array containing the actual metadata. + * return int: number of frames in the movie, -1 if the process fails to obtain the metadata. + */ +int hdr10plus_json_to_movie_cim(const char* path, uint8_t **&cim); + +/* hdr10plus_json_to_frame_eif: +* Parses the json file containing the Extended InfoFrame metadata for a frame of video +* into a bytestream to be encoded into the resulting video stream. +* path is the file path of the JSON file containing the Extended InfoFrame metadata for the video. +* frameNumber is the number of the frame to get the metadata for. +* Extended InfoFrame will get filled with the byte array containing the actual metadata. +* Returns true in case of success. +*/ +bool hdr10plus_json_to_frame_eif(const char* path, uint32_t frameNumber, uint8_t *&eif); + +/* hdr10plus_json_to_movie_eif: +* Parses the json file containing the Extended InfoFrame metadata for the video +* into a bytestream to be encoded into the resulting video stream. +* path is the file path of the JSON file containing the Extended InfoFrame metadata for the video. +* frameNumber is the number of the frame to get the metadata for. +* cim will get filled with the byte array containing the actual metadata. +* return int: number of frames in the movie, -1 if the process fails to obtain the metadata. +*/ +int hdr10plus_json_to_movie_eif(const char* path, uint8_t **&eif); + + +/* hdr10plus_clear_movie_cim: +* This function clears the allocated memory for the movie metadata array +* clear: Clears the memory of the given array and size. +* metadata: metadata array to be cleared. +* numberOfFrames: number of frames in the metadata array. +* @return +*/ + +void hdr10plus_clear_movie(uint8_t**& metadata, const int numberOfFrames); + + +typedef struct hdr10plus_api +{ + /* hdr10plus public API functions, documented above with hdr10plus_ prefixes */ + bool (*hdr10plus_json_to_frame_cim)(const char *, uint32_t, uint8_t *&); + int (*hdr10plus_json_to_movie_cim)(const char *, uint8_t **&); + bool (*hdr10plus_json_to_frame_eif)(const char *, uint32_t, uint8_t *&); + int (*hdr10plus_json_to_movie_eif)(const char *, uint8_t **&); + void (*hdr10plus_clear_movie)(uint8_t **&, const int); +} hdr10plus_api; + +/* hdr10plus_api: + * Retrieve the programming interface for the linked hdr10plus library. + */ +const hdr10plus_api* hdr10plus_api_get(); + + +#endif // HDR10PLUS_H + diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/json11/LICENSE.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/json11/LICENSE.txt Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,19 @@ +Copyright (c) 2013 Dropbox, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/json11/json11.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/json11/json11.cpp Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,780 @@ +/* Copyright (c) 2013 Dropbox, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "json11.h" +#include <cassert> +#include <cmath> +#include <cstdlib> +#include <cstdio> +#include <limits> + +namespace json11 { + +static const int max_depth = 200; + +using std::string; +using std::vector; +using std::map; +using std::make_shared; +using std::initializer_list; +using std::move; + +/* * * * * * * * * * * * * * * * * * * * + * Serialization + */ + +static void dump(std::nullptr_t, string &out) { + out += "null"; +} + +static void dump(double value, string &out) { + if (std::isfinite(value)) { + char buf[32]; + snprintf(buf, sizeof buf, "%.17g", value); + out += buf; + } else { + out += "null"; + } +} + +static void dump(int value, string &out) { + char buf[32]; + snprintf(buf, sizeof buf, "%d", value); + out += buf; +} + +static void dump(bool value, string &out) { + out += value ? "true" : "false"; +} + +static void dump(const string &value, string &out) { + out += '"'; + for (size_t i = 0; i < value.length(); i++) { + const char ch = value[i]; + if (ch == '\\') { + out += "\\\\"; + } else if (ch == '"') { + out += "\\\""; + } else if (ch == '\b') { + out += "\\b"; + } else if (ch == '\f') { + out += "\\f"; + } else if (ch == '\n') { + out += "\\n"; + } else if (ch == '\r') { + out += "\\r"; + } else if (ch == '\t') { + out += "\\t"; + } else if (static_cast<uint8_t>(ch) <= 0x1f) { + char buf[8]; + snprintf(buf, sizeof buf, "\\u%04x", ch); + out += buf; + } else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i+1]) == 0x80 + && static_cast<uint8_t>(value[i+2]) == 0xa8) { + out += "\\u2028"; + i += 2; + } else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i+1]) == 0x80 + && static_cast<uint8_t>(value[i+2]) == 0xa9) { + out += "\\u2029"; + i += 2; + } else { + out += ch; + } + } + out += '"'; +} + +static void dump(const Json::array &values, string &out) { + bool first = true; + out += "["; + for (const auto &value : values) { + if (!first) + out += ", "; + value.dump(out); + first = false; + } + out += "]"; +} + +static void dump(const Json::object &values, string &out) { + bool first = true; + out += "{"; + for (const auto &kv : values) { + if (!first) + out += ", "; + dump(kv.first, out); + out += ": "; + kv.second.dump(out); + first = false; + } + out += "}"; +} + +void Json::dump(string &out) const { + m_ptr->dump(out); +} + +/* * * * * * * * * * * * * * * * * * * * + * Value wrappers + */ + +template <Json::Type tag, typename T> +class Value : public JsonValue { +protected: + + // Constructors + explicit Value(const T &value) : m_value(value) {} + explicit Value(T &&value) : m_value(move(value)) {} + + // Get type tag + Json::Type type() const override { + return tag; + } + + // Comparisons + bool equals(const JsonValue * other) const override { + return m_value == static_cast<const Value<tag, T> *>(other)->m_value; + } + bool less(const JsonValue * other) const override { + return m_value < static_cast<const Value<tag, T> *>(other)->m_value; + } + + const T m_value; + void dump(string &out) const override { json11::dump(m_value, out); } +}; + +class JsonDouble final : public Value<Json::NUMBER, double> { + double number_value() const override { return m_value; } + int int_value() const override { return static_cast<int>(m_value); } + bool equals(const JsonValue * other) const override { return m_value == other->number_value(); } + bool less(const JsonValue * other) const override { return m_value < other->number_value(); } +public: + explicit JsonDouble(double value) : Value(value) {} +}; + +class JsonInt final : public Value<Json::NUMBER, int> { + double number_value() const override { return m_value; } + int int_value() const override { return m_value; } + bool equals(const JsonValue * other) const override { return m_value == other->number_value(); } + bool less(const JsonValue * other) const override { return m_value < other->number_value(); } +public: + explicit JsonInt(int value) : Value(value) {} +}; + +class JsonBoolean final : public Value<Json::BOOL, bool> { + bool bool_value() const override { return m_value; } +public: + explicit JsonBoolean(bool value) : Value(value) {} +}; + +class JsonString final : public Value<Json::STRING, string> { + const string &string_value() const override { return m_value; } +public: + explicit JsonString(const string &value) : Value(value) {} + explicit JsonString(string &&value) : Value(move(value)) {} +}; + +class JsonArray final : public Value<Json::ARRAY, Json::array> { + const Json::array &array_items() const override { return m_value; } + const Json & operator[](size_t i) const override; +public: + explicit JsonArray(const Json::array &value) : Value(value) {} + explicit JsonArray(Json::array &&value) : Value(move(value)) {} +}; + +class JsonObject final : public Value<Json::OBJECT, Json::object> { + const Json::object &object_items() const override { return m_value; } + const Json & operator[](const string &key) const override; +public: + explicit JsonObject(const Json::object &value) : Value(value) {} + explicit JsonObject(Json::object &&value) : Value(move(value)) {} +}; + +class JsonNull final : public Value<Json::NUL, std::nullptr_t> { +public: + JsonNull() : Value(nullptr) {} +}; + +/* * * * * * * * * * * * * * * * * * * * + * Static globals - static-init-safe + */ +struct Statics { + const std::shared_ptr<JsonValue> null = make_shared<JsonNull>(); + const std::shared_ptr<JsonValue> t = make_shared<JsonBoolean>(true); + const std::shared_ptr<JsonValue> f = make_shared<JsonBoolean>(false); + const string empty_string; + const vector<Json> empty_vector; + const map<string, Json> empty_map; + Statics() {} +}; + +static const Statics & statics() { + static const Statics s {}; + return s; +} + +static const Json & static_null() { + // This has to be separate, not in Statics, because Json() accesses statics().null. + static const Json json_null; + return json_null; +} + +/* * * * * * * * * * * * * * * * * * * * + * Constructors + */ + +Json::Json() noexcept : m_ptr(statics().null) {} +Json::Json(std::nullptr_t) noexcept : m_ptr(statics().null) {} +Json::Json(double value) : m_ptr(make_shared<JsonDouble>(value)) {} +Json::Json(int value) : m_ptr(make_shared<JsonInt>(value)) {} +Json::Json(bool value) : m_ptr(value ? statics().t : statics().f) {} +Json::Json(const string &value) : m_ptr(make_shared<JsonString>(value)) {} +Json::Json(string &&value) : m_ptr(make_shared<JsonString>(move(value))) {} +Json::Json(const char * value) : m_ptr(make_shared<JsonString>(value)) {} +Json::Json(const Json::array &values) : m_ptr(make_shared<JsonArray>(values)) {} +Json::Json(Json::array &&values) : m_ptr(make_shared<JsonArray>(move(values))) {} +Json::Json(const Json::object &values) : m_ptr(make_shared<JsonObject>(values)) {} +Json::Json(Json::object &&values) : m_ptr(make_shared<JsonObject>(move(values))) {} + +/* * * * * * * * * * * * * * * * * * * * + * Accessors + */ + +Json::Type Json::type() const { return m_ptr->type(); } +double Json::number_value() const { return m_ptr->number_value(); } +int Json::int_value() const { return m_ptr->int_value(); } +bool Json::bool_value() const { return m_ptr->bool_value(); } +const string & Json::string_value() const { return m_ptr->string_value(); } +const vector<Json> & Json::array_items() const { return m_ptr->array_items(); } +const map<string, Json> & Json::object_items() const { return m_ptr->object_items(); } +const Json & Json::operator[] (size_t i) const { return (*m_ptr)[i]; } +const Json & Json::operator[] (const string &key) const { return (*m_ptr)[key]; } + +double JsonValue::number_value() const { return 0; } +int JsonValue::int_value() const { return 0; } +bool JsonValue::bool_value() const { return false; } +const string & JsonValue::string_value() const { return statics().empty_string; } +const vector<Json> & JsonValue::array_items() const { return statics().empty_vector; } +const map<string, Json> & JsonValue::object_items() const { return statics().empty_map; } +const Json & JsonValue::operator[] (size_t) const { return static_null(); } +const Json & JsonValue::operator[] (const string &) const { return static_null(); } + +const Json & JsonObject::operator[] (const string &key) const { + auto iter = m_value.find(key); + return (iter == m_value.end()) ? static_null() : iter->second; +} +const Json & JsonArray::operator[] (size_t i) const { + if (i >= m_value.size()) return static_null(); + else return m_value[i]; +} + +/* * * * * * * * * * * * * * * * * * * * + * Comparison + */ + +bool Json::operator== (const Json &other) const { + if (m_ptr->type() != other.m_ptr->type()) + return false; + + return m_ptr->equals(other.m_ptr.get()); +} + +bool Json::operator< (const Json &other) const { + if (m_ptr->type() != other.m_ptr->type()) + return m_ptr->type() < other.m_ptr->type(); + + return m_ptr->less(other.m_ptr.get()); +} + +/* * * * * * * * * * * * * * * * * * * * + * Parsing + */ + +/* esc(c) + * + * Format char c suitable for printing in an error message. + */ +static inline string esc(char c) { + char buf[12]; + if (static_cast<uint8_t>(c) >= 0x20 && static_cast<uint8_t>(c) <= 0x7f) { + snprintf(buf, sizeof buf, "'%c' (%d)", c, c); + } else { + snprintf(buf, sizeof buf, "(%d)", c); + } + return string(buf); +} + +static inline bool in_range(long x, long lower, long upper) { + return (x >= lower && x <= upper); +} + +namespace { +/* JsonParser + * + * Object that tracks all state of an in-progress parse. + */ +struct JsonParser final { + + /* State + */ + const string &str; + size_t i; + string &err; + bool failed; + const JsonParse strategy; + + /* fail(msg, err_ret = Json()) + * + * Mark this parse as failed. + */ + Json fail(string &&msg) { + return fail(move(msg), Json()); + } + + template <typename T> + T fail(string &&msg, const T err_ret) { + if (!failed) + err = std::move(msg); + failed = true; + return err_ret; + } + + /* consume_whitespace() + * + * Advance until the current character is non-whitespace. + */ + void consume_whitespace() { + while (str[i] == ' ' || str[i] == '\r' || str[i] == '\n' || str[i] == '\t') + i++; + } + + /* consume_comment() + * + * Advance comments (c-style inline and multiline). + */ + bool consume_comment() { + bool comment_found = false; + if (str[i] == '/') { + i++; + if (i == str.size()) + return fail("unexpected end of input inside comment", false); + if (str[i] == '/') { // inline comment + i++; + if (i == str.size()) + return fail("unexpected end of input inside inline comment", false); + // advance until next line + while (str[i] != '\n') { + i++; + if (i == str.size()) + return fail("unexpected end of input inside inline comment", false); + } + comment_found = true; + } + else if (str[i] == '*') { // multiline comment + i++; + if (i > str.size()-2) + return fail("unexpected end of input inside multi-line comment", false); + // advance until closing tokens + while (!(str[i] == '*' && str[i+1] == '/')) { + i++; + if (i > str.size()-2) + return fail( + "unexpected end of input inside multi-line comment", false); + } + i += 2; + if (i == str.size()) + return fail( + "unexpected end of input inside multi-line comment", false); + comment_found = true; + } + else + return fail("malformed comment", false); + } + return comment_found; + } + + /* consume_garbage() + * + * Advance until the current character is non-whitespace and non-comment. + */ + void consume_garbage() { + consume_whitespace(); + if(strategy == JsonParse::COMMENTS) { + bool comment_found = false; + do { + comment_found = consume_comment(); + consume_whitespace(); + } + while(comment_found); + } + } + + /* get_next_token() + * + * Return the next non-whitespace character. If the end of the input is reached, + * flag an error and return 0. + */ + char get_next_token() { + consume_garbage(); + if (i == str.size()) + return fail("unexpected end of input", 0); + + return str[i++]; + } + + /* encode_utf8(pt, out) + * + * Encode pt as UTF-8 and add it to out. + */ + void encode_utf8(long pt, string & out) { + if (pt < 0) + return; + + if (pt < 0x80) { + out += static_cast<char>(pt); + } else if (pt < 0x800) { + out += static_cast<char>((pt >> 6) | 0xC0); + out += static_cast<char>((pt & 0x3F) | 0x80); + } else if (pt < 0x10000) { + out += static_cast<char>((pt >> 12) | 0xE0); + out += static_cast<char>(((pt >> 6) & 0x3F) | 0x80); + out += static_cast<char>((pt & 0x3F) | 0x80); + } else { + out += static_cast<char>((pt >> 18) | 0xF0); + out += static_cast<char>(((pt >> 12) & 0x3F) | 0x80); + out += static_cast<char>(((pt >> 6) & 0x3F) | 0x80); + out += static_cast<char>((pt & 0x3F) | 0x80); + } + } + + /* parse_string() + * + * Parse a string, starting at the current position. + */ + string parse_string() { + string out; + long last_escaped_codepoint = -1; + while (true) { + if (i == str.size()) + return fail("unexpected end of input in string", ""); + + char ch = str[i++]; + + if (ch == '"') { + encode_utf8(last_escaped_codepoint, out); + return out; + } + + if (in_range(ch, 0, 0x1f)) + return fail("unescaped " + esc(ch) + " in string", ""); + + // The usual case: non-escaped characters + if (ch != '\\') { + encode_utf8(last_escaped_codepoint, out); + last_escaped_codepoint = -1; + out += ch; + continue; + } + + // Handle escapes + if (i == str.size()) + return fail("unexpected end of input in string", ""); + + ch = str[i++]; + + if (ch == 'u') { + // Extract 4-byte escape sequence + string esc = str.substr(i, 4); + // Explicitly check length of the substring. The following loop + // relies on std::string returning the terminating NUL when + // accessing str[length]. Checking here reduces brittleness. + if (esc.length() < 4) { + return fail("bad \\u escape: " + esc, ""); + } + for (int j = 0; j < 4; j++) { + if (!in_range(esc[j], 'a', 'f') && !in_range(esc[j], 'A', 'F') + && !in_range(esc[j], '0', '9')) + return fail("bad \\u escape: " + esc, ""); + } + + long codepoint = strtol(esc.data(), nullptr, 16); + + // JSON specifies that characters outside the BMP shall be encoded as a pair + // of 4-hex-digit \u escapes encoding their surrogate pair components. Check + // whether we're in the middle of such a beast: the previous codepoint was an + // escaped lead (high) surrogate, and this is a trail (low) surrogate. + if (in_range(last_escaped_codepoint, 0xD800, 0xDBFF) + && in_range(codepoint, 0xDC00, 0xDFFF)) { + // Reassemble the two surrogate pairs into one astral-plane character, per + // the UTF-16 algorithm. + encode_utf8((((last_escaped_codepoint - 0xD800) << 10) + | (codepoint - 0xDC00)) + 0x10000, out); + last_escaped_codepoint = -1; + } else { + encode_utf8(last_escaped_codepoint, out); + last_escaped_codepoint = codepoint; + } + + i += 4; + continue; + } + + encode_utf8(last_escaped_codepoint, out); + last_escaped_codepoint = -1; + + if (ch == 'b') { + out += '\b'; + } else if (ch == 'f') { + out += '\f'; + } else if (ch == 'n') { + out += '\n'; + } else if (ch == 'r') { + out += '\r'; + } else if (ch == 't') { + out += '\t'; + } else if (ch == '"' || ch == '\\' || ch == '/') { + out += ch; + } else { + return fail("invalid escape character " + esc(ch), ""); + } + } + } + + /* parse_number() + * + * Parse a double. + */ + Json parse_number() { + size_t start_pos = i; + + if (str[i] == '-') + i++; + + // Integer part + if (str[i] == '0') { + i++; + if (in_range(str[i], '0', '9')) + return fail("leading 0s not permitted in numbers"); + } else if (in_range(str[i], '1', '9')) { + i++; + while (in_range(str[i], '0', '9')) + i++; + } else { + return fail("invalid " + esc(str[i]) + " in number"); + } + + if (str[i] != '.' && str[i] != 'e' && str[i] != 'E' + && (i - start_pos) <= static_cast<size_t>(std::numeric_limits<int>::digits10)) { + return std::atoi(str.c_str() + start_pos); + } + + // Decimal part + if (str[i] == '.') { + i++; + if (!in_range(str[i], '0', '9')) + return fail("at least one digit required in fractional part"); + + while (in_range(str[i], '0', '9')) + i++; + } + + // Exponent part + if (str[i] == 'e' || str[i] == 'E') { + i++; + + if (str[i] == '+' || str[i] == '-') + i++; + + if (!in_range(str[i], '0', '9')) + return fail("at least one digit required in exponent"); + + while (in_range(str[i], '0', '9')) + i++; + } + + return std::strtod(str.c_str() + start_pos, nullptr); + } + + /* expect(str, res) + * + * Expect that 'str' starts at the character that was just read. If it does, advance + * the input and return res. If not, flag an error. + */ + Json expect(const string &expected, Json res) { + assert(i != 0); + i--; + if (str.compare(i, expected.length(), expected) == 0) { + i += expected.length(); + return res; + } else { + return fail("parse error: expected " + expected + ", got " + str.substr(i, expected.length())); + } + } + + /* parse_json() + * + * Parse a JSON object. + */ + Json parse_json(int depth) { + if (depth > max_depth) { + return fail("exceeded maximum nesting depth"); + } + + char ch = get_next_token(); + if (failed) + return Json(); + + if (ch == '-' || (ch >= '0' && ch <= '9')) { + i--; + return parse_number(); + } + + if (ch == 't') + return expect("true", true); + + if (ch == 'f') + return expect("false", false); + + if (ch == 'n') + return expect("null", Json()); + + if (ch == '"') + return parse_string(); + + if (ch == '{') { + map<string, Json> data; + ch = get_next_token(); + if (ch == '}') + return data; + + while (1) { + if (ch != '"') + return fail("expected '\"' in object, got " + esc(ch)); + + string key = parse_string(); + if (failed) + return Json(); + + ch = get_next_token(); + if (ch != ':') + return fail("expected ':' in object, got " + esc(ch)); + + data[std::move(key)] = parse_json(depth + 1); + if (failed) + return Json(); + + ch = get_next_token(); + if (ch == '}') + break; + if (ch != ',') + return fail("expected ',' in object, got " + esc(ch)); + + ch = get_next_token(); + } + return data; + } + + if (ch == '[') { + vector<Json> data; + ch = get_next_token(); + if (ch == ']') + return data; + + while (1) { + i--; + data.push_back(parse_json(depth + 1)); + if (failed) + return Json(); + + ch = get_next_token(); + if (ch == ']') + break; + if (ch != ',') + return fail("expected ',' in list, got " + esc(ch)); + + ch = get_next_token(); + (void)ch; + } + return data; + } + + return fail("expected value, got " + esc(ch)); + } +}; +}//namespace { + +Json Json::parse(const string &in, string &err, JsonParse strategy) { + JsonParser parser { in, 0, err, false, strategy }; + Json result = parser.parse_json(0); + + // Check for any trailing garbage + parser.consume_garbage(); + if (parser.i != in.size()) + return parser.fail("unexpected trailing " + esc(in[parser.i])); + + return result; +} + +// Documented in json11.hpp +vector<Json> Json::parse_multi(const string &in, + std::string::size_type &parser_stop_pos, + string &err, + JsonParse strategy) { + JsonParser parser { in, 0, err, false, strategy }; + parser_stop_pos = 0; + vector<Json> json_vec; + while (parser.i != in.size() && !parser.failed) { + json_vec.push_back(parser.parse_json(0)); + // Check for another object + parser.consume_garbage(); + if (!parser.failed) + parser_stop_pos = parser.i; + } + return json_vec; +} + +/* * * * * * * * * * * * * * * * * * * * + * Shape-checking + */ + +bool Json::has_shape(const shape & types, string & err) const { + if (!is_object()) { + err = "expected JSON object, got " + dump(); + return false; + } + + for (auto & item : types) { + if ((*this)[item.first].type() != item.second) { + err = "bad type for " + item.first + " in " + dump(); + return false; + } + } + + return true; +} +//void Json::add(std::string &key, std::string value) +//{ +// (*m_ptr)[key] = value; +//} + +} // namespace json11 + + diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/json11/json11.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/json11/json11.h Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,235 @@ +/* json11 + * + * json11 is a tiny JSON library for C++11, providing JSON parsing and serialization. + * + * The core object provided by the library is json11::Json. A Json object represents any JSON + * value: null, bool, number (int or double), string (std::string), array (std::vector), or + * object (std::map). + * + * Json objects act like values: they can be assigned, copied, moved, compared for equality or + * order, etc. There are also helper methods Json::dump, to serialize a Json to a string, and + * Json::parse (static) to parse a std::string as a Json object. + * + * Internally, the various types of Json object are represented by the JsonValue class + * hierarchy. + * + * A note on numbers - JSON specifies the syntax of number formatting but not its semantics, + * so some JSON implementations distinguish between integers and floating-point numbers, while + * some don't. In json11, we choose the latter. Because some JSON implementations (namely + * Javascript itself) treat all numbers as the same type, distinguishing the two leads + * to JSON that will be *silently* changed by a round-trip through those implementations. + * Dangerous! To avoid that risk, json11 stores all numbers as double internally, but also + * provides integer helpers. + * + * Fortunately, double-precision IEEE754 ('double') can precisely store any integer in the + * range +/-2^53, which includes every 'int' on most systems. (Timestamps often use int64 + * or long long to avoid the Y2038K problem; a double storing microseconds since some epoch + * will be exact for +/- 275 years.) + */ + +/* Copyright (c) 2013 Dropbox, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include <string> +#include <vector> +#include <map> +#include <memory> +#include <initializer_list> + +#ifdef _MSC_VER + #if _MSC_VER <= 1800 // VS 2013 + #ifndef noexcept + #define noexcept throw() + #endif + + #ifndef snprintf + #define snprintf _snprintf_s + #endif + #endif +#endif + +namespace json11 { + +enum JsonParse { + STANDARD, COMMENTS +}; + +class JsonValue; + +class Json final{ //final +public: + // Types + enum Type { + NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT + }; + + // Array and object typedefs + typedef std::vector<Json> array; + typedef std::map<std::string, Json> object; + + // Constructors for the various types of JSON value. + Json() noexcept; // NUL + Json(std::nullptr_t) noexcept; // NUL + Json(double value); // NUMBER + Json(int value); // NUMBER + Json(bool value); // BOOL + Json(const std::string &value); // STRING + Json(std::string &&value); // STRING + Json(const char * value); // STRING + Json(const array &values); // ARRAY + Json(array &&values); // ARRAY + Json(const object &values); // OBJECT + Json(object &&values); // OBJECT + void add(std::string &key, std::string value); + + // Implicit constructor: anything with a to_json() function. + template <class T, class = decltype(&T::to_json)> + Json(const T & t) : Json(t.to_json()) {} + + // Implicit constructor: map-like objects (std::map, std::unordered_map, etc) + template <class M, typename std::enable_if< + std::is_constructible<std::string, typename M::key_type>::value + && std::is_constructible<Json, typename M::mapped_type>::value, + int>::type = 0> + Json(const M & m) : Json(object(m.begin(), m.end())) {} + + // Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc) + template <class V, typename std::enable_if< + std::is_constructible<Json, typename V::value_type>::value, + int>::type = 0> + Json(const V & v) : Json(array(v.begin(), v.end())) {} + + // This prevents Json(some_pointer) from accidentally producing a bool. Use + // Json(bool(some_pointer)) if that behavior is desired. + Json(void *) = delete; + + // Accessors + Type type() const; + + bool is_null() const { return type() == NUL; } + bool is_number() const { return type() == NUMBER; } + bool is_bool() const { return type() == BOOL; } + bool is_string() const { return type() == STRING; } + bool is_array() const { return type() == ARRAY; } + bool is_object() const { return type() == OBJECT; } + + + // Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not + // distinguish between integer and non-integer numbers - number_value() and int_value() + // can both be applied to a NUMBER-typed object. + double number_value() const; + int int_value() const; + + // Return the enclosed value if this is a boolean, false otherwise. + bool bool_value() const; + // Return the enclosed string if this is a string, "" otherwise. + const std::string &string_value() const; + // Return the enclosed std::vector if this is an array, or an empty vector otherwise. + const array &array_items() const; + // Return the enclosed std::map if this is an object, or an empty map otherwise. + const object &object_items() const; + + // Return a reference to arr[i] if this is an array, Json() otherwise. + const Json & operator[](size_t i) const; + // Return a reference to obj[key] if this is an object, Json() otherwise. + const Json & operator[](const std::string &key) const; + + // Serialize. + void dump(std::string &out) const; + std::string dump() const { + std::string out; + dump(out); + return out; + } + + // Parse. If parse fails, return Json() and assign an error message to err. + static Json parse(const std::string & in, + std::string & err, + JsonParse strategy = JsonParse::STANDARD); + static Json parse(const char * in, + std::string & err, + JsonParse strategy = JsonParse::STANDARD) { + if (in) { + return parse(std::string(in), err, strategy); + } else { + err = "null input"; + return nullptr; + } + } + // Parse multiple objects, concatenated or separated by whitespace + static std::vector<Json> parse_multi( + const std::string & in, + std::string::size_type & parser_stop_pos, + std::string & err, + JsonParse strategy = JsonParse::STANDARD); + + static inline std::vector<Json> parse_multi( + const std::string & in, + std::string & err, + JsonParse strategy = JsonParse::STANDARD) { + std::string::size_type parser_stop_pos; + return parse_multi(in, parser_stop_pos, err, strategy); + } + + bool operator== (const Json &rhs) const; + bool operator< (const Json &rhs) const; + bool operator!= (const Json &rhs) const { return !(*this == rhs); } + bool operator<= (const Json &rhs) const { return !(rhs < *this); } + bool operator> (const Json &rhs) const { return (rhs < *this); } + bool operator>= (const Json &rhs) const { return !(*this < rhs); } + + /* has_shape(types, err) + * + * Return true if this is a JSON object and, for each item in types, has a field of + * the given type. If not, return false and set err to a descriptive message. + */ + typedef std::initializer_list<std::pair<std::string, Type>> shape; + bool has_shape(const shape & types, std::string & err) const; + +private: + std::shared_ptr<JsonValue> m_ptr; +}; + +// Internal class hierarchy - JsonValue objects are not exposed to users of this API. +class JsonValue { +protected: + friend class Json; + friend class JsonInt; + friend class JsonDouble; + virtual Json::Type type() const = 0; + virtual bool equals(const JsonValue * other) const = 0; + virtual bool less(const JsonValue * other) const = 0; + virtual void dump(std::string &out) const = 0; + virtual double number_value() const; + virtual int int_value() const; + virtual bool bool_value() const; + virtual const std::string &string_value() const; + virtual const Json::array &array_items() const; + virtual const Json &operator[](size_t i) const; + virtual const Json::object &object_items() const; + virtual const Json &operator[](const std::string &key) const; + virtual ~JsonValue() {} + +}; + +} // namespace json11 diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/metadataFromJson.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/metadataFromJson.cpp Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,578 @@ +/** + * @file metadataFromJson.cpp + * @brief Reads a JSON file and produces a byte array containing the metadata to be embedded in different ways. + * @author Daniel Maximiliano Valenzuela, Seongnam Oh. + * @create date 03/01/2017 + * @version 0.0.1 + * + * Copyright @ 2017 Samsung Electronics, DMS Lab, Samsung Research America and Samsung Research Tijuana + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 "metadataFromJson.h" + +#include <fstream> +#include <iostream> +#include <math.h> +#include "sstream" +#include "sys/stat.h" + +#include "BasicStructures.h" +#include "SeiMetadataDictionary.h" + +#define M_PI 3.14159265358979323846 + +using namespace SeiMetadataDictionary; + +class metadataFromJson::DynamicMetaIO +{ +public: + DynamicMetaIO() : + mCurrentStreamBit(8), + mCurrentStreamByte(0) + {} + + ~DynamicMetaIO(){} + + int mCurrentStreamBit; + int mCurrentStreamByte; + + bool luminanceParamFromJson(const Json &data, LuminanceParameters &obj) + { + JsonObject lumJsonData = data.object_items(); + if(!lumJsonData.empty()) + { + JsonObject percentileData = lumJsonData[PercentileNames::TagName].object_items(); + obj.order = percentileData[PercentileNames::NumberOfPercentiles].int_value(); + + obj.averageLuminance = static_cast<float>(lumJsonData[LuminanceNames::AverageRGB].number_value()); + obj.maxRLuminance = static_cast<float>(lumJsonData[LuminanceNames::MaxSCL0].number_value()); + obj.maxGLuminance = static_cast<float>(lumJsonData[LuminanceNames::MaxSCL1].number_value()); + obj.maxBLuminance = static_cast<float>(lumJsonData[LuminanceNames::MaxSCL2].number_value()); + + if(!percentileData.empty()) + { + obj.percentiles.resize(obj.order); + for(int i = 0; i < obj.order; ++i) + { + std::string percentileTag = PercentileNames::TagName; + percentileTag += std::to_string(i); + obj.percentiles[i] = static_cast<unsigned int>(percentileData[percentileTag].int_value()); + } + } + + return true; + } + return false; + } + + bool percentagesFromJson(const Json &data, std::vector<unsigned int> &percentages) + { + JsonObject jsonData = data.object_items(); + if(!jsonData.empty()) + { + JsonObject percentileData = jsonData[PercentileNames::TagName].object_items(); + int order = percentileData[PercentileNames::NumberOfPercentiles].int_value(); + + percentages.resize(order); + for(int i = 0; i < order; ++i) + { + std::string percentileTag = PercentileNames::PercentilePercentageValue[i]; + percentages[i] = static_cast<unsigned int>(percentileData[percentileTag].int_value()); + } + + return true; + } + return false; + } + + bool percentagesFromJson(const Json &data, unsigned int *percentages) + { + JsonObject jsonData = data.object_items(); + if(!jsonData.empty()) + { + JsonObject percentileData = jsonData[PercentileNames::TagName].object_items(); + int order = percentileData[PercentileNames::NumberOfPercentiles].int_value(); + + for(int i = 0; i < order; ++i) + { + std::string percentileTag = PercentileNames::PercentilePercentageValue[i]; + percentages[i] = static_cast<unsigned int>(percentileData[percentileTag].int_value()); + } + + return true; + } + return false; + } + + bool bezierCurveFromJson(const Json &data, BezierCurveData &obj) + { + JsonObject jsonData = data.object_items(); + if(!jsonData.empty()) + { + obj.order = jsonData[BezierCurveNames::NumberOfAnchors].int_value(); + obj.coeff.resize(obj.order); + obj.sPx = jsonData[BezierCurveNames::KneePointX].int_value(); + obj.sPy = jsonData[BezierCurveNames::KneePointY].int_value(); + for(int i = 0; i < obj.order; ++i) + { + obj.coeff[i] = jsonData[BezierCurveNames::Anchors[i]].int_value(); + } + + return true; + } + return false; + } + + template<typename T> + void appendBits(uint8_t *dataStream, T data, int bitsToWrite) + { + //TODO: Check if bitsToWrite is <= sizeOf(T); + while (bitsToWrite > 0) + { + /* if all data to write fits inside the current byte */ + if (bitsToWrite < mCurrentStreamBit ) + { + int bitshift = mCurrentStreamBit - bitsToWrite; + dataStream[mCurrentStreamByte] += static_cast<uint8_t>(data << bitshift); + mCurrentStreamBit -= bitsToWrite; + bitsToWrite = 0; + } + /* if all data to write needs more than the current byte space */ + else + { + int bitshift = bitsToWrite - mCurrentStreamBit; + dataStream[mCurrentStreamByte] += static_cast<uint8_t>(data >> bitshift); + bitsToWrite -= mCurrentStreamBit ; + mCurrentStreamBit = 8; + mCurrentStreamByte++; + } + } + } + + void setPayloadSize(uint8_t *dataStream, int positionOnStream, int payload) + { + int payloadBytes = 1; + + for(;payload > 0xFF; payload -= 0xFF, ++payloadBytes); + + if(payloadBytes > 1) + { + shiftData(dataStream, payloadBytes-1, mCurrentStreamByte, positionOnStream); + mCurrentStreamByte += payloadBytes-1; + + for(int i = 0; i < payloadBytes; ++i) + { + if(payloadBytes-1 == i) + { + dataStream[positionOnStream++] = static_cast<uint8_t>(payload); + } + else + { + dataStream[positionOnStream++] = 0xFF; + } + } + } + else + { + dataStream[positionOnStream] = static_cast<uint8_t>(payload); + } + } + + void shiftData(uint8_t *dataStream, int shiftSize, int streamSize, int startPoint = 0) + { + for(int i = streamSize; i > startPoint; --i) + { + dataStream[i + shiftSize] = dataStream[i]; + } + } + +// const std::string LocalParameters = std::string("LocalParameters"); +// const std::string TargetDisplayLuminance = std::string("TargetedSystemDisplayMaximumLuminance"); +}; + +metadataFromJson::metadataFromJson() : + mPimpl(new DynamicMetaIO()) +{ + +} + +metadataFromJson::~metadataFromJson() +{ + delete mPimpl; +} + + +bool metadataFromJson::frameMetadataFromJson(const char* filePath, + int frame, + uint8_t *&metadata) +{ + std::string path(filePath); + JsonArray fileData = JsonHelper::readJsonArray(path); + + if(fileData.empty()) + { + return false; + } + +// frame = frame + 1; //index on the array start at 0 frames starts at 1 + int numFrames = static_cast<int>(fileData.size()); + + if(frame >= numFrames) + { + return false; + } + + int mSEIBytesToRead = 509; + + if(metadata) + { + delete(metadata); + } + metadata = new uint8_t[mSEIBytesToRead]; + mPimpl->mCurrentStreamBit = 8; + mPimpl->mCurrentStreamByte = 1; + + for(int j = 0; j < mSEIBytesToRead; ++j) + { + (metadata)[j] = 0; + } + + fillMetadataArray(fileData, frame, metadata); + mPimpl->setPayloadSize(metadata, 0, mPimpl->mCurrentStreamByte); + return true; +} + +int metadataFromJson::movieMetadataFromJson(const char* filePath, uint8_t **&metadata) +{ + std::string path(filePath); + JsonArray fileData = JsonHelper::readJsonArray(path); + if (fileData.empty()) + { + return -1; + } + + int numFrames = static_cast<int>(fileData.size()); + metadata = new uint8_t*[numFrames]; + for (int frame = 0; frame < numFrames; ++frame) + { + metadata[frame] = new uint8_t[509]; + for (int i = 0; i < 509; ++i) + { + metadata[frame][i] = 0; + } + mPimpl->mCurrentStreamBit = 8; + mPimpl->mCurrentStreamByte = 1; + + fillMetadataArray(fileData, frame, metadata[frame]); + + mPimpl->setPayloadSize(metadata[frame], 0, mPimpl->mCurrentStreamByte); + + } + + return numFrames; +} + +bool metadataFromJson::extendedInfoFrameMetadataFromJson(const char* filePath, + int frame, + uint8_t *&metadata) +{ + std::string path(filePath); + JsonArray fileData = JsonHelper::readJsonArray(path); + + if (fileData.empty()) + { + return false; + } + + int numFrames = static_cast<int>(fileData.size()); + if (frame >= numFrames) + { + return false; + } + + int mSEIBytesToRead = 509; + + if (metadata) + { + delete(metadata); + } + metadata = new uint8_t[mSEIBytesToRead]; + mPimpl->mCurrentStreamBit = 8; + mPimpl->mCurrentStreamByte = 0; + + for (int j = 0; j < mSEIBytesToRead; ++j) + { + (metadata)[j] = 0; + } + + const uint16_t extendedInfoframeType = 0x0004; + mPimpl->appendBits(metadata, extendedInfoframeType, 16); + + /* NOTE: We leave TWO BYTES of space for the payload */ + mPimpl->mCurrentStreamByte += 2; + + fillMetadataArray(fileData, frame, metadata); + + /* Set payload in bytes 2 & 3 as indicated in Extended InfoFrame Type syntax */ + metadata[2] = (mPimpl->mCurrentStreamByte & 0xFF00) >> 8; + metadata[3] = (mPimpl->mCurrentStreamByte & 0x00FF); + return true; +} + +int metadataFromJson::movieExtendedInfoFrameMetadataFromJson(const char* filePath, uint8_t **&metadata) +{ + std::string path(filePath); + JsonArray fileData = JsonHelper::readJsonArray(path); + if(fileData.empty()) + { + return -1; + } + + int numFrames = static_cast<int>(fileData.size()); + metadata = new uint8_t*[numFrames]; + for(int frame = 0; frame < numFrames; ++frame) + { + metadata[frame] = new uint8_t[509]; + for(int i = 0; i < 509; ++i) + { + metadata[frame][i] = 0; + } + mPimpl->mCurrentStreamBit = 8; + mPimpl->mCurrentStreamByte = 0; + + const uint16_t extendedInfoframeType = 0x0004; + mPimpl->appendBits(metadata[frame], extendedInfoframeType, 16); + + /* NOTE: We leave TWO BYTES of space for the payload */ + mPimpl->mCurrentStreamByte += 2; + + fillMetadataArray(fileData, frame, metadata[frame]); + + /* Set payload in bytes 2 & 3 as indicated in Extended InfoFrame Type syntax */ + metadata[frame][2] = (mPimpl->mCurrentStreamByte & 0xFF00) >> 8; + metadata[frame][3] = (mPimpl->mCurrentStreamByte & 0x00FF); + } + + return numFrames; +} + +void metadataFromJson::fillMetadataArray(const JsonArray &fileData, int frame, uint8_t *&metadata) +{ + const uint8_t countryCode = 0xB5; + const uint16_t terminalProviderCode = 0x003C; + const uint16_t terminalProviderOrientedCode = 0x0001; + const uint8_t applicationIdentifier = 4; + const uint8_t applicationVersion = 0; + + mPimpl->appendBits(metadata, countryCode, 8); + mPimpl->appendBits(metadata, terminalProviderCode, 16); + mPimpl->appendBits(metadata, terminalProviderOrientedCode, 16); + + mPimpl->appendBits(metadata, applicationIdentifier, 8); + mPimpl->appendBits(metadata, applicationVersion, 8); + + //Note: Validated only add up to two local selections, ignore the rest + JsonArray jsonArray = fileData[frame][JsonDataKeys::LocalParameters].array_items(); + int ellipsesNum = static_cast<int>(jsonArray.size() > 2 ? 2 : jsonArray.size()); + + uint16_t numWindows = 1 + static_cast<uint16_t>(ellipsesNum); + + mPimpl->appendBits(metadata, numWindows, 2); + for (int i = 0; i < ellipsesNum; ++i) + { + mPimpl->appendBits(metadata, jsonArray[i][EllipseSelectionNames::WindowData] + [EllipseSelectionNames::WindowUpperLeftCornerX].int_value(), 16); + mPimpl->appendBits(metadata, jsonArray[i][EllipseSelectionNames::WindowData] + [EllipseSelectionNames::WindowUpperLeftCornerY].int_value(), 16); + mPimpl->appendBits(metadata, jsonArray[i][EllipseSelectionNames::WindowData] + [EllipseSelectionNames::WindowLowerRightCornerX].int_value(), 16); + mPimpl->appendBits(metadata, jsonArray[i][EllipseSelectionNames::WindowData] + [EllipseSelectionNames::WindowLowerRightCornerY].int_value(), 16); + + JsonObject ellipseJsonObject = jsonArray[i][EllipseNames::TagName].object_items(); + + mPimpl->appendBits(metadata, + static_cast<uint16_t>(ellipseJsonObject[EllipseNames::CenterOfEllipseX].int_value()), + 16); + + mPimpl->appendBits(metadata, + static_cast<uint16_t>(ellipseJsonObject[EllipseNames::CenterOfEllipseY].int_value()), + 16); + + int angle = ellipseJsonObject[EllipseNames::RotationAngle].int_value(); + uint8_t rotationAngle = static_cast<uint8_t>((angle > 180.0) ? angle - 180.0 : angle); + mPimpl->appendBits(metadata, rotationAngle, 8); + + uint16_t semimajorExternalAxis = + static_cast<uint16_t>(ellipseJsonObject[EllipseNames::SemiMajorAxisExternalEllipse].int_value()); + + uint16_t semiminorExternalAxis = + static_cast<uint16_t>(ellipseJsonObject[EllipseNames::SemiMinorAxisExternalEllipse].int_value()); + + uint16_t semimajorInternalEllipse = + static_cast<uint16_t>(ellipseJsonObject[EllipseNames::SemiMajorAxisInternalEllipse].int_value()); + + mPimpl->appendBits(metadata, semimajorInternalEllipse, 16); + + mPimpl->appendBits(metadata, semimajorExternalAxis, 16); + mPimpl->appendBits(metadata, semiminorExternalAxis, 16); + /*bool*/ uint8_t overlapProcessOption = static_cast<uint8_t>(ellipseJsonObject[EllipseNames::OverlapProcessOption].int_value()); //1; + //TODO: Uses Layering method, the value is "1" + mPimpl->appendBits(metadata, overlapProcessOption, 1); + } + /* Targeted System Display Data */ + uint32_t TEMPmonitorPeak = fileData[frame][JsonDataKeys::TargetDisplayLuminance].int_value(); //500; + mPimpl->appendBits(metadata, TEMPmonitorPeak, 27); + + //NOTE: Set as false for now, as requested + /*bool*/uint8_t targetedSystemDisplayActualPeakLuminanceFlag = 0; /*false*/ + mPimpl->appendBits(metadata, targetedSystemDisplayActualPeakLuminanceFlag, 1); + if (targetedSystemDisplayActualPeakLuminanceFlag) + { + //TODO + } + + /* Max rgb values (maxScl)*/ + /* Luminance values/percentile for each window */ + for (int w = 0; w < numWindows; ++w) + { + Json lumObj = fileData[frame][LuminanceNames::TagName]; + LuminanceParameters luminanceData; + if (!mPimpl->luminanceParamFromJson(lumObj, luminanceData)) + { + std::cout << "error parsing luminance parameters frame: " << w << std::endl; + } + + /* NOTE: Maxscl from 0 t 100,000 based on data that says in values of 0.00001 + * one for each channel R,G,B + */ + + mPimpl->appendBits(metadata, static_cast<uint8_t>(((int)luminanceData.maxRLuminance & 0x10000) >> 16), 1); + mPimpl->appendBits(metadata, static_cast<uint16_t>((int)luminanceData.maxRLuminance & 0xFFFF), 16); + mPimpl->appendBits(metadata, static_cast<uint8_t>(((int)luminanceData.maxGLuminance & 0x10000) >> 16), 1); + mPimpl->appendBits(metadata, static_cast<uint16_t>((int)luminanceData.maxGLuminance & 0xFFFF), 16); + mPimpl->appendBits(metadata, static_cast<uint8_t>(((int)luminanceData.maxBLuminance & 0x10000) >> 16), 1); + mPimpl->appendBits(metadata, static_cast<uint16_t>((int)luminanceData.maxBLuminance & 0xFFFF), 16); + /* changed from maxRGBLuminance to average luminance to match stms implementation */ + mPimpl->appendBits(metadata, static_cast<uint8_t>(((int)luminanceData.averageLuminance & 0x10000) >> 16), 1); + mPimpl->appendBits(metadata, static_cast<uint16_t>((int)luminanceData.averageLuminance & 0xFFFF), 16); + + /* Percentiles */ + uint8_t numDistributionMaxrgbPercentiles = static_cast<uint8_t>(luminanceData.order); + mPimpl->appendBits(metadata, numDistributionMaxrgbPercentiles, 4); + + std::vector<unsigned int>percentilPercentages; + mPimpl->percentagesFromJson(lumObj, percentilPercentages); + for (int i = 0; i < numDistributionMaxrgbPercentiles; ++i) + { + uint8_t distributionMaxrgbPercentage = static_cast<uint8_t>(percentilPercentages.at(i)); + mPimpl->appendBits(metadata, distributionMaxrgbPercentage, 7); + + // 17bits: 1bit then 16 + unsigned int ithPercentile = luminanceData.percentiles.at(i); + uint8_t highValue = static_cast<uint8_t>((ithPercentile & 0x10000) >> 16); + uint16_t lowValue = static_cast<uint16_t>(ithPercentile & 0xFFFF); + mPimpl->appendBits(metadata, highValue, 1); + mPimpl->appendBits(metadata, lowValue, 16); + } + + /* 10bits: Fraction bright pixels */ + uint16_t fractionBrightPixels = 1; + mPimpl->appendBits(metadata, fractionBrightPixels, 10); + + } + + /* Note: Set to false by now as requested */ + uint8_t masteringDisplayActualPeakLuminanceFlag = 0; + mPimpl->appendBits(metadata, masteringDisplayActualPeakLuminanceFlag, 1); + if (masteringDisplayActualPeakLuminanceFlag) + { + //TODO + } + // BEZIER CURVE DATA + for (int w = 0; w < numWindows; ++w) + { + //TODO: + uint8_t toneMappingFlag = 1; + mPimpl->appendBits(metadata, toneMappingFlag, 1); + if (toneMappingFlag) + { + Json bezierData = fileData[frame][BezierCurveNames::TagName]; + BezierCurveData curveData; + + /* Select curve data based on global window or local window */ + if (w == 0) + { + if (!mPimpl->bezierCurveFromJson(bezierData, curveData)) + { + std::cout << "error parsing bezierCurve frame: " << w << std::endl; + } + } + else + { + if (!mPimpl->bezierCurveFromJson(jsonArray[w - 1][BezierCurveNames::TagName], curveData)) + { + std::cout << "error parsing bezierCurve ellipse: " << w - 1 << std::endl; + } + } + + uint16_t kneePointX = static_cast<uint16_t>(curveData.sPx); + mPimpl->appendBits(metadata, kneePointX, 12); + uint16_t kneePointY = static_cast<uint16_t>(curveData.sPy); + mPimpl->appendBits(metadata, kneePointY, 12); + + uint8_t numBezierCurveAnchors = static_cast<uint8_t>(curveData.order);// - 1; + mPimpl->appendBits(metadata, numBezierCurveAnchors, 4); + + /* Curve anchors 10bits */ + for (int i = 0; i < numBezierCurveAnchors; ++i) + { + uint16_t anchor = static_cast<uint16_t>(curveData.coeff.at(i)); + mPimpl->appendBits(metadata, anchor, 10); + } + } + } + /* Set to false as requested */ + bool colorSaturationMappingFlag = 0; + mPimpl->appendBits(metadata, colorSaturationMappingFlag, 1); + if (colorSaturationMappingFlag) + { + //TODO + } + + if (mPimpl->mCurrentStreamBit == 8) + { + mPimpl->mCurrentStreamByte -= 1; + } +} + +void metadataFromJson::clear(uint8_t **&metadata, const int numberOfFrames) +{ + if (metadata && numberOfFrames > 0) + { + for (int i = 0; i < numberOfFrames; ++i) + { + if (metadata[i]) + { + delete[] metadata[i]; + } + } + delete[] metadata; + metadata = NULL; + } +} diff -r 94d59c325e97 -r f0545a714a70 source/dynamicHDR10/metadataFromJson.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/dynamicHDR10/metadataFromJson.h Wed Mar 22 14:33:20 2017 +0530 @@ -0,0 +1,106 @@ +/** + * @file metadataFromJson.h + * @brief Reads a JSON file and produces a byte array containing the metadata to be embedded for a frame. + * @author Daniel Maximiliano Valenzuela, Seongnam Oh. + * @create date 03/01/2017 + * @version 0.0.1 + * + * Copyright @ 2017 Samsung Electronics, DMS Lab, Samsung Research America and Samsung Research Tijuana + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 METADATAFROMJSON_H +#define METADATAFROMJSON_H + +#include<stdint.h> +#include "string" +#include "JsonHelper.h" + +class metadataFromJson +{ + +public: + metadataFromJson(); + ~metadataFromJson(); + + + /** + * @brief frameMetadataFromJson: Generates a sigle frame metadata array from Json file with all + * metadata information from movie. + * @param filePath: path to Json file containing movie metadata information. + * @param frame: frame Id number in respect to the movie. + * @param metadata (output): receives an empty pointer that will be set to point to metadata + * array. Note: if pointer is set it will be deleted. + * @return True if succesful + */ + bool frameMetadataFromJson(const char* filePath, + int frame, + uint8_t *&metadata); + + /** + * @brief movieMetadataFromJson: Generates metadata array from Json file with all metadata + * information from movie. + * @param filePath: path to Json file containing movie metadata information. + * @param metadata (output): receives an empty pointer that will be set to point to metadata + * array. Note: if pointer is set it will be deleted. + * @return int: number of frames in the movie, -1 if the process fails to obtain the metadata. + */ + int movieMetadataFromJson(const char* filePath, + uint8_t **&metadata); + + /** + * @brief extendedInfoFrameMetadataFromJson: Generates Extended InfoFrame metadata array from Json file + * with all metadata information from movie. + * @param filePath: path to Json file containing movie metadata information. + * @param metadata (output): receives an empty pointer that will be set to point to metadata + * array. Note: if pointer is set it will be deleted. + * @return int: number of frames in the movie, -1 if the process fails to obtain the metadata. + */ + bool extendedInfoFrameMetadataFromJson(const char* filePath, + int frame, + uint8_t *&metadata); + + /** + * @brief movieMetadataFromJson: Generates Extended InfoFrame metadata array from Json file with all metadata + * information from movie. + * @param filePath: path to Json file containing movie Extended InfoFrame metadata information. + * @param metadata (output): receives an empty pointer that will be set to point to metadata + * array. Note: if pointer is set it will be deleted. + * @return int: number of frames in the movie, -1 if the process fails to obtain the metadata. + */ + int movieExtendedInfoFrameMetadataFromJson(const char* filePath, + uint8_t **&metadata); + + /** + + * @brief clear: Clears the memory of the given array and size. + * @param metadata: metadata array to be cleared. + * @param numberOfFrames: number of frames in the metadata array. + * @return + */ + void clear(uint8_t **&metadata, + const int numberOfFrames); + +private: + + class DynamicMetaIO; + DynamicMetaIO *mPimpl; + void fillMetadataArray(const JsonArray &fileData, int frame, uint8_t *&metadata); +}; + +#endif // METADATAFROMJSON_H _______________________________________________ x265-devel mailing list x265-devel@videolan.org https://mailman.videolan.org/listinfo/x265-devel