diff --git a/CMakeLists.txt b/CMakeLists.txt
index a386903b..73de6c25 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -187,7 +187,7 @@ ENDIF()
ADD_CUSTOM_TARGET(tests COMMAND make test "EXIV2_BINDIR=${CMAKE_BINARY_DIR}/bin" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/test/" )
ADD_CUSTOM_TARGET(teste COMMAND make teste "EXIV2_BINDIR=${CMAKE_BINARY_DIR}/bin" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/test/" )
ADD_CUSTOM_TARGET(testv COMMAND make testv "EXIV2_BINDIR=${CMAKE_BINARY_DIR}/bin" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/test/" )
-
+ADD_CUSTOM_TARGET(testvw COMMAND make testvw "EXIV2_BINDIR=${CMAKE_BINARY_DIR}/bin" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/test/" )
##
# http://dev.exiv2.org/boards/3/topics/1364
# effectively does a make doc on the root directory
diff --git a/Makefile b/Makefile
index 2d6be127..1d96c11e 100644
--- a/Makefile
+++ b/Makefile
@@ -79,6 +79,9 @@ teste:
testv:
cd test && $(MAKE) testv
+testvw:
+ cd test && $(MAKE) testvw
+
MAJOR=$(shell grep "define.*EXIV2_.*_VERSION .*\\d*" src/version.hpp | grep MAJOR | sed -e 's/EXIV2//g' | tr -dC [:digit:])
MINOR=$(shell grep "define.*EXIV2_.*_VERSION .*\\d*" src/version.hpp | grep MINOR | sed -e 's/EXIV2//g' | tr -dC [:digit:])
VERSION=exiv2-$(MAJOR).$(MINOR)
diff --git a/config/Makefile.in b/config/Makefile.in
index d3fec78e..ecae1d0d 100644
--- a/config/Makefile.in
+++ b/config/Makefile.in
@@ -79,6 +79,9 @@ teste:
testv:
cd test && $(MAKE) testv
+testvw:
+ cd test && $(MAKE) testvw
+
MAJOR=$(shell grep "define.*EXIV2_.*_VERSION .*\\d*" src/version.hpp | grep MAJOR | sed -e 's/EXIV2//g' | tr -dC [:digit:])
MINOR=$(shell grep "define.*EXIV2_.*_VERSION .*\\d*" src/version.hpp | grep MINOR | sed -e 's/EXIV2//g' | tr -dC [:digit:])
VERSION=exiv2-$(MAJOR).$(MINOR)
diff --git a/msvc2003/exiv2lib/exiv2lib.vcproj b/msvc2003/exiv2lib/exiv2lib.vcproj
index 1ce2b9f3..66fd2094 100644
--- a/msvc2003/exiv2lib/exiv2lib.vcproj
+++ b/msvc2003/exiv2lib/exiv2lib.vcproj
@@ -1,3 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/msvc2005/exiv2/exiv2.vcproj b/msvc2005/exiv2/exiv2.vcproj
index 13e99dac..af472da4 100644
--- a/msvc2005/exiv2/exiv2.vcproj
+++ b/msvc2005/exiv2/exiv2.vcproj
@@ -1,793 +1 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/msvc2005/exiv2lib/exiv2lib.vcproj b/msvc2005/exiv2lib/exiv2lib.vcproj
index 9899984d..26cde850 100644
--- a/msvc2005/exiv2lib/exiv2lib.vcproj
+++ b/msvc2005/exiv2lib/exiv2lib.vcproj
@@ -1,104 +1 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/msvc2012/exiv2lib/exiv2lib.vcxproj b/msvc2012/exiv2lib/exiv2lib.vcxproj
index 511d87e2..5555c69c 100644
--- a/msvc2012/exiv2lib/exiv2lib.vcxproj
+++ b/msvc2012/exiv2lib/exiv2lib.vcxproj
@@ -1,118 +1 @@
-
-DebugDLLWin32DebugDLLx64DebugWin32Debugx64ReleaseDLLWin32ReleaseDLLx64ReleaseWin32Releasex64{831EF580-92C8-4CA8-B0CE-3D906280A54D}exiv2libWin32ProjDynamicLibraryv110MultiByteDynamicLibraryv110MultiByteStaticLibraryv110MultiByteStaticLibraryv110MultiByteDynamicLibraryv110MultiByteDynamicLibraryv110MultiByteStaticLibraryv110MultiByteStaticLibraryv110MultiByte
- <_ProjectFileVersion>11.0.50727.1$(Platform)\$(Configuration)\build\$(Platform)\$(Configuration)\$(Platform)\$(Configuration)\build\$(Platform)\$(Configuration)\$(Platform)\$(Configuration)\build\$(Platform)\$(Configuration)\$(Platform)\$(Configuration)\build\$(Platform)\$(Configuration)\$(Platform)\$(Configuration)\build\$(Platform)\$(Configuration)\$(Platform)\$(Configuration)\build\$(Platform)\$(Configuration)\$(Platform)\$(Configuration)\build\$(Platform)\$(Configuration)\$(Platform)\$(Configuration)\build\$(Platform)\$(Configuration)\if exist ..\include\exiv2 goto :jail
-mkdir ..\include\exiv2\
-copy/y ..\..\src\*.h ..\include\exiv2\
-copy/y ..\..\src\*.hpp ..\include\exiv2\
-cd ..\include\exiv2
-del *_int.hpp
-cd ..\..\exiv2lib
-:jail
-Disabled../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories)WIN32;_DEBUG;%(PreprocessorDefinitions)trueEnableFastChecksMultiThreadedDebugtruetruetrueLevel3falseProgramDatabase$(OutDir)exiv2sd.lib..\xmpsdk\$(Platform)\$(Configuration);..\expat\(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)msvcrtd;%(IgnoreSpecificDefaultLibraries)if exist ..\include\exiv2 goto :jail
-mkdir ..\include\exiv2\
-copy/y ..\..\src\*.h ..\include\exiv2\
-copy/y ..\..\src\*.hpp ..\include\exiv2\
-cd ..\include\exiv2
-del *_int.hpp
-cd ..\..\exiv2lib
-:jail
-X64Disabled../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories)WIN32;_DEBUG;%(PreprocessorDefinitions)trueEnableFastChecksMultiThreadedDebugtruetruetrueLevel3falseProgramDatabase$(OutDir)exiv2sd.lib..\xmpsdk\$(Platform)\$(Configuration);..\expat\(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)msvcrtd;%(IgnoreSpecificDefaultLibraries)copy expat and zlib binariesif exist ..\include\exiv2 goto :jail
-mkdir ..\include\exiv2\
-copy/y ..\..\src\*.h ..\include\exiv2\
-copy/y ..\..\src\*.hpp ..\include\exiv2\
-cd ..\include\exiv2
-del *_int.hpp
-cd ..\..\exiv2lib
-:jail
-
-../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories)WIN32;_NDEBUG;%(PreprocessorDefinitions)MultiThreadedtruetrueLevel3falseProgramDatabase$(OutDir)exiv2s.lib..\xmpsdk\$(Platform)\$(Configuration);..\expat\(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)msvcrt;%(IgnoreSpecificDefaultLibraries)copy expat and zlib binariesif exist ..\include\exiv2 goto :jail
-mkdir ..\include\exiv2\
-copy/y ..\..\src\*.h ..\include\exiv2\
-copy/y ..\..\src\*.hpp ..\include\exiv2\
-cd ..\include\exiv2
-del *_int.hpp
-cd ..\..\exiv2lib
-:jail
-
-X64../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories)WIN32;_NDEBUG;%(PreprocessorDefinitions)MultiThreadedtruetrueLevel3falseProgramDatabase$(OutDir)exiv2s.lib..\xmpsdk\$(Platform)\$(Configuration);..\expat\(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)msvcrt;%(IgnoreSpecificDefaultLibraries)copy expat and zlib dllsif exist ..\include\exiv2 goto :jail
-mkdir ..\include\exiv2\
-copy/y ..\..\src\*.h ..\include\exiv2\
-copy/y ..\..\src\*.hpp ..\include\exiv2\
-cd ..\include\exiv2
-del *_int.hpp
-cd ..\..\exiv2lib
-:jail
-if NOT EXIST "$(OutDir)" mkdir "$(OutDir)"
-copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "$(OutDir)"
-copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "$(OutDir)"
-Disabled../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories)WIN32;_DEBUG;EXV_HAVE_DLL;EXV_BUILDING_LIB;%(PreprocessorDefinitions)trueEnableFastChecksMultiThreadedDebugDLLtruetruetrueLevel3falseProgramDatabasefalse/NODEFAULTLIB:LIBMTD %(AdditionalOptions)..\xmpsdk\$(Platform)\$(Configuration)\xmpsdk.lib;..\expat\$(Platform)\$(Configuration)\libexpat.lib;..\zlib\$(Platform)\$(Configuration)\zlib1d.lib;%(AdditionalDependencies)$(OutDir)exiv2d.dlltrue$(TargetDir)\exiv2d.libMachineX86copy dlls to the build directorysetlocal
-set X=$(TargetDir)
-copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "%25X%25"
-copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.lib" "%25X%25"
-copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "%25X%25"
-copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.lib" "%25X%25"
-
-
-copy expat and zlib dllsif exist ..\include\exiv2 goto :jail
-mkdir ..\include\exiv2\
-copy/y ..\..\src\*.h ..\include\exiv2\
-copy/y ..\..\src\*.hpp ..\include\exiv2\
-cd ..\include\exiv2
-del *_int.hpp
-cd ..\..\exiv2lib
-:jail
-if NOT EXIST "$(OutDir)" mkdir "$(OutDir)"
-copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "$(OutDir)"
-copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "$(OutDir)"
-
-X64Disabled../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories)WIN32;_DEBUG;EXV_HAVE_DLL;EXV_BUILDING_LIB;%(PreprocessorDefinitions)trueEnableFastChecksMultiThreadedDebugDLLtruetruetrueLevel3falseProgramDatabasefalse/NODEFAULTLIB:LIBMTD %(AdditionalOptions)..\xmpsdk\$(Platform)\$(Configuration)\xmpsdk.lib;..\expat\$(Platform)\$(Configuration)\libexpat.lib;..\zlib\$(Platform)\$(Configuration)\zlib1d.lib;%(AdditionalDependencies)$(OutDir)exiv2d.dlltrue$(TargetDir)\exiv2d.libMachineX64copy dlls to the build directorysetlocal
-set X=$(TargetDir)
-copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "%25X%25"
-copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.lib" "%25X%25"
-copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "%25X%25"
-copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.lib" "%25X%25"
-
-copy expat and zlib dllsif exist ..\include\exiv2 goto :jail
-mkdir ..\include\exiv2\
-copy/y ..\..\src\*.h ..\include\exiv2\
-copy/y ..\..\src\*.hpp ..\include\exiv2\
-cd ..\include\exiv2
-del *_int.hpp
-cd ..\..\exiv2lib
-:jail
-if NOT EXIST "$(OutDir)" mkdir "$(OutDir)"
-copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "$(OutDir)"
-copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "$(OutDir)"
-
-MinSpace../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories)WIN32;_NDEBUG;EXV_HAVE_DLL;EXV_BUILDING_LIB;%(PreprocessorDefinitions)trueDefaultMultiThreadedDLLtruetruetrueLevel3falseProgramDatabasefalse..\xmpsdk\$(Platform)\$(Configuration)\xmpsdk.lib;..\expat\$(Platform)\$(Configuration)\libexpat.lib;..\zlib\$(Platform)\$(Configuration)\zlib1.lib;%(AdditionalDependencies)$(OutDir)exiv2.dllfalse$(TargetDir)\exiv2.libMachineX86copy dlls to the build directorysetlocal
-set X=$(TargetDir)
-copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "%25X%25"
-copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.lib" "%25X%25"
-copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "%25X%25"
-copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.lib" "%25X%25"
-
-copy expat and zlib dllsif exist ..\include\exiv2 goto :jail
-mkdir ..\include\exiv2\
-copy/y ..\..\src\*.h ..\include\exiv2\
-copy/y ..\..\src\*.hpp ..\include\exiv2\
-cd ..\include\exiv2
-del *_int.hpp
-cd ..\..\exiv2lib
-:jail
-if NOT EXIST "$(OutDir)" mkdir "$(OutDir)"
-copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "$(OutDir)"
-copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "$(OutDir)"
-
-
-X64MinSpace../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories)WIN32;_NDEBUG;EXV_HAVE_DLL;EXV_BUILDING_LIB;%(PreprocessorDefinitions)trueDefaultMultiThreadedDLLtruetruetrueLevel3falseProgramDatabasefalse..\xmpsdk\$(Platform)\$(Configuration)\xmpsdk.lib;..\expat\$(Platform)\$(Configuration)\libexpat.lib;..\zlib\$(Platform)\$(Configuration)\zlib1.lib;%(AdditionalDependencies)$(OutDir)exiv2.dllfalse$(TargetDir)\exiv2.libMachineX64copy dlls to the build directorysetlocal
-set X=$(TargetDir)
-copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "%25X%25"
-copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.lib" "%25X%25"
-copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "%25X%25"
-copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.lib" "%25X%25"
-
-
-
-
-{6c4c06a3-6f8f-4067-aa4c-d5f41e1fff9a}false{09877cf4-83b6-44fe-a2e2-629aa5c8093e}false{8308c68d-e12b-4c71-96f4-7137f6beb654}false
-
+ DebugDLL Win32 DebugDLL x64 Debug Win32 Debug x64 ReleaseDLL Win32 ReleaseDLL x64 Release Win32 Release x64 {831EF580-92C8-4CA8-B0CE-3D906280A54D} exiv2lib Win32Proj DynamicLibrary v110 MultiByte DynamicLibrary v110 MultiByte StaticLibrary v110 MultiByte StaticLibrary v110 MultiByte DynamicLibrary v110 MultiByte DynamicLibrary v110 MultiByte StaticLibrary v110 MultiByte StaticLibrary v110 MultiByte <_ProjectFileVersion>11.0.50727.1 $(Platform)\$(Configuration)\ build\$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ build\$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ build\$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ build\$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ build\$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ build\$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ build\$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ build\$(Platform)\$(Configuration)\ if exist ..\include\exiv2 goto :jailmkdir ..\include\exiv2\copy/y ..\..\src\*.h ..\include\exiv2\copy/y ..\..\src\*.hpp ..\include\exiv2\cd ..\include\exiv2del *_int.hppcd ..\..\exiv2lib:jail Disabled ../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories) WIN32;_DEBUG;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug true true true Level3 false ProgramDatabase $(OutDir)exiv2sd.lib ..\xmpsdk\$(Platform)\$(Configuration);..\expat\(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) msvcrtd;%(IgnoreSpecificDefaultLibraries) if exist ..\include\exiv2 goto :jailmkdir ..\include\exiv2\copy/y ..\..\src\*.h ..\include\exiv2\copy/y ..\..\src\*.hpp ..\include\exiv2\cd ..\include\exiv2del *_int.hppcd ..\..\exiv2lib:jail X64 Disabled ../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories) WIN32;_DEBUG;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug true true true Level3 false ProgramDatabase $(OutDir)exiv2sd.lib ..\xmpsdk\$(Platform)\$(Configuration);..\expat\(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) msvcrtd;%(IgnoreSpecificDefaultLibraries) copy expat and zlib binaries if exist ..\include\exiv2 goto :jailmkdir ..\include\exiv2\copy/y ..\..\src\*.h ..\include\exiv2\copy/y ..\..\src\*.hpp ..\include\exiv2\cd ..\include\exiv2del *_int.hppcd ..\..\exiv2lib:jail ../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories) WIN32;_NDEBUG;%(PreprocessorDefinitions) MultiThreaded true true Level3 false ProgramDatabase $(OutDir)exiv2s.lib ..\xmpsdk\$(Platform)\$(Configuration);..\expat\(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) msvcrt;%(IgnoreSpecificDefaultLibraries) copy expat and zlib binaries if exist ..\include\exiv2 goto :jailmkdir ..\include\exiv2\copy/y ..\..\src\*.h ..\include\exiv2\copy/y ..\..\src\*.hpp ..\include\exiv2\cd ..\include\exiv2del *_int.hppcd ..\..\exiv2lib:jail X64 ../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories) WIN32;_NDEBUG;%(PreprocessorDefinitions) MultiThreaded true true Level3 false ProgramDatabase $(OutDir)exiv2s.lib ..\xmpsdk\$(Platform)\$(Configuration);..\expat\(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories) msvcrt;%(IgnoreSpecificDefaultLibraries) copy expat and zlib dlls if exist ..\include\exiv2 goto :jailmkdir ..\include\exiv2\copy/y ..\..\src\*.h ..\include\exiv2\copy/y ..\..\src\*.hpp ..\include\exiv2\cd ..\include\exiv2del *_int.hppcd ..\..\exiv2lib:jailif NOT EXIST "$(OutDir)" mkdir "$(OutDir)"copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "$(OutDir)"copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "$(OutDir)" Disabled ../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories) WIN32;_DEBUG;EXV_HAVE_DLL;EXV_BUILDING_LIB;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL true true true Level3 false ProgramDatabase false /NODEFAULTLIB:LIBMTD %(AdditionalOptions) ..\xmpsdk\$(Platform)\$(Configuration)\xmpsdk.lib;..\expat\$(Platform)\$(Configuration)\libexpat.lib;..\zlib\$(Platform)\$(Configuration)\zlib1d.lib;%(AdditionalDependencies) $(OutDir)exiv2d.dll true $(TargetDir)\exiv2d.lib MachineX86 copy dlls to the build directory setlocalset X=$(TargetDir)copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "%25X%25"copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.lib" "%25X%25"copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "%25X%25"copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.lib" "%25X%25" copy expat and zlib dlls if exist ..\include\exiv2 goto :jailmkdir ..\include\exiv2\copy/y ..\..\src\*.h ..\include\exiv2\copy/y ..\..\src\*.hpp ..\include\exiv2\cd ..\include\exiv2del *_int.hppcd ..\..\exiv2lib:jailif NOT EXIST "$(OutDir)" mkdir "$(OutDir)"copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "$(OutDir)"copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "$(OutDir)" X64 Disabled ../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories) WIN32;_DEBUG;EXV_HAVE_DLL;EXV_BUILDING_LIB;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL true true true Level3 false ProgramDatabase false /NODEFAULTLIB:LIBMTD %(AdditionalOptions) ..\xmpsdk\$(Platform)\$(Configuration)\xmpsdk.lib;..\expat\$(Platform)\$(Configuration)\libexpat.lib;..\zlib\$(Platform)\$(Configuration)\zlib1d.lib;%(AdditionalDependencies) $(OutDir)exiv2d.dll true $(TargetDir)\exiv2d.lib MachineX64 copy dlls to the build directory setlocalset X=$(TargetDir)copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "%25X%25"copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.lib" "%25X%25"copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "%25X%25"copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.lib" "%25X%25" copy expat and zlib dlls if exist ..\include\exiv2 goto :jailmkdir ..\include\exiv2\copy/y ..\..\src\*.h ..\include\exiv2\copy/y ..\..\src\*.hpp ..\include\exiv2\cd ..\include\exiv2del *_int.hppcd ..\..\exiv2lib:jailif NOT EXIST "$(OutDir)" mkdir "$(OutDir)"copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "$(OutDir)"copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "$(OutDir)" MinSpace ../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories) WIN32;_NDEBUG;EXV_HAVE_DLL;EXV_BUILDING_LIB;%(PreprocessorDefinitions) true Default MultiThreadedDLL true true true Level3 false ProgramDatabase false ..\xmpsdk\$(Platform)\$(Configuration)\xmpsdk.lib;..\expat\$(Platform)\$(Configuration)\libexpat.lib;..\zlib\$(Platform)\$(Configuration)\zlib1.lib;%(AdditionalDependencies) $(OutDir)exiv2.dll false $(TargetDir)\exiv2.lib MachineX86 copy dlls to the build directory setlocalset X=$(TargetDir)copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "%25X%25"copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.lib" "%25X%25"copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "%25X%25"copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.lib" "%25X%25" copy expat and zlib dlls if exist ..\include\exiv2 goto :jailmkdir ..\include\exiv2\copy/y ..\..\src\*.h ..\include\exiv2\copy/y ..\..\src\*.hpp ..\include\exiv2\cd ..\include\exiv2del *_int.hppcd ..\..\exiv2lib:jailif NOT EXIST "$(OutDir)" mkdir "$(OutDir)"copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "$(OutDir)"copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "$(OutDir)" X64 MinSpace ../include;../include/exiv2;../../src;../../xmpsdk/include;../../xmpsdk/src;../../../expat-2.1.0/lib;../../../zlib-1.2.7;%(AdditionalIncludeDirectories) WIN32;_NDEBUG;EXV_HAVE_DLL;EXV_BUILDING_LIB;%(PreprocessorDefinitions) true Default MultiThreadedDLL true true true Level3 false ProgramDatabase false ..\xmpsdk\$(Platform)\$(Configuration)\xmpsdk.lib;..\expat\$(Platform)\$(Configuration)\libexpat.lib;..\zlib\$(Platform)\$(Configuration)\zlib1.lib;%(AdditionalDependencies) $(OutDir)exiv2.dll false $(TargetDir)\exiv2.lib MachineX64 copy dlls to the build directory setlocalset X=$(TargetDir)copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.dll" "%25X%25"copy/y "$(SolutionDir)expat\$(Platform)\$(Configuration)\*.lib" "%25X%25"copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.dll" "%25X%25"copy/y "$(SolutionDir)zlib\$(Platform)\$(Configuration)\*.lib" "%25X%25" {6c4c06a3-6f8f-4067-aa4c-d5f41e1fff9a} false {09877cf4-83b6-44fe-a2e2-629aa5c8093e} false {8308c68d-e12b-4c71-96f4-7137f6beb654} false
\ No newline at end of file
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9879f836..b9815fe0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -72,10 +72,12 @@ SET( LIBEXIV2_HDR asfvideo.hpp
tgaimage.hpp
tiffimage.hpp
types.hpp
+ utilsvideo.hpp
value.hpp
version.hpp
xmp.hpp
xmpsidecar.hpp
+ utilsvideo.hpp
)
# Add library C++ source files to this list
@@ -127,10 +129,12 @@ SET( LIBEXIV2_SRC asfvideo.cpp
tiffimage.cpp
tiffvisitor.cpp
types.cpp
+ utilsvideo.cpp
value.cpp
version.cpp
xmp.cpp
xmpsidecar.cpp
+ utilsvideo.cpp
)
##
diff --git a/src/Makefile b/src/Makefile
index 72fe0ded..99ff9750 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -117,6 +117,7 @@ CCSRC += preview.cpp \
tiffimage.cpp \
tiffvisitor.cpp \
types.cpp \
+ utilsvideo.cpp \
value.cpp \
version.cpp \
xmp.cpp \
diff --git a/src/actions.hpp b/src/actions.hpp
index bf0c8547..1cf8d275 100644
--- a/src/actions.hpp
+++ b/src/actions.hpp
@@ -159,7 +159,11 @@ namespace Action {
public:
virtual ~Print();
virtual int run(const std::string& path);
- typedef std::auto_ptr AutoPtr;
+ typedef std::auto_ptr AutoPtr; //!< TODO
+ /*!
+ * \brief clone TODO
+ * \return
+ */
AutoPtr clone() const;
//! Print the Jpeg comment
@@ -212,10 +216,18 @@ namespace Action {
public:
virtual ~Rename();
virtual int run(const std::string& path);
- typedef std::auto_ptr AutoPtr;
+ typedef std::auto_ptr AutoPtr; //!< TODO
+ /*!
+ * \brief clone TODO
+ * \return
+ */
AutoPtr clone() const;
private:
+ /*!
+ * \brief clone TODO
+ * \return
+ */
virtual Rename* clone_() const;
}; // class Rename
@@ -224,10 +236,18 @@ namespace Action {
public:
virtual ~Adjust();
virtual int run(const std::string& path);
- typedef std::auto_ptr AutoPtr;
+ typedef std::auto_ptr AutoPtr; //!< TODO
+ /*!
+ * \brief clone TODO
+ * \return
+ */
AutoPtr clone() const;
private:
+ /*!
+ * \brief clone TODO
+ * \return
+ */
virtual Adjust* clone_() const;
int adjustDateTime(Exiv2::ExifData& exifData,
const std::string& key,
@@ -247,7 +267,11 @@ namespace Action {
public:
virtual ~Erase();
virtual int run(const std::string& path);
- typedef std::auto_ptr AutoPtr;
+ typedef std::auto_ptr AutoPtr; //!< TODO
+ /*!
+ * \brief clone TODO
+ * \return
+ */
AutoPtr clone() const;
/*!
@@ -272,8 +296,12 @@ namespace Action {
int eraseXmpData(Exiv2::Image* image) const;
private:
+ /*!
+ * \brief clone TODO
+ * \return
+ */
virtual Erase* clone_() const;
- std::string path_;
+ std::string path_; //!< TODO
}; // class Erase
@@ -284,7 +312,11 @@ namespace Action {
public:
virtual ~Extract();
virtual int run(const std::string& path);
- typedef std::auto_ptr AutoPtr;
+ typedef std::auto_ptr AutoPtr; //!< TODO
+ /*!
+ * \brief clone TODO
+ * \return
+ */
AutoPtr clone() const;
/*!
@@ -307,8 +339,12 @@ namespace Action {
void writePreviewFile(const Exiv2::PreviewImage& pvImg, int num) const;
private:
+ /*!
+ * \brief clone TODO
+ * \return
+ */
virtual Extract* clone_() const;
- std::string path_;
+ std::string path_; //!< TODO
}; // class Extract
@@ -319,7 +355,11 @@ namespace Action {
public:
virtual ~Insert();
virtual int run(const std::string& path);
- typedef std::auto_ptr AutoPtr;
+ typedef std::auto_ptr AutoPtr; //!< TODO
+ /*!
+ * \brief clone TODO
+ * \return
+ */
AutoPtr clone() const;
/*!
@@ -348,7 +388,11 @@ namespace Action {
public:
virtual ~Modify();
virtual int run(const std::string& path);
- typedef std::auto_ptr AutoPtr;
+ typedef std::auto_ptr AutoPtr; //!< TODO
+ /*!
+ * \brief clone TODO
+ * \return
+ */
AutoPtr clone() const;
Modify() {}
//! Apply modification commands to the \em pImage, return 0 if successful.
@@ -381,12 +425,20 @@ namespace Action {
public:
virtual ~FixIso();
virtual int run(const std::string& path);
- typedef std::auto_ptr AutoPtr;
+ typedef std::auto_ptr AutoPtr; //!< TODO
+ /*!
+ * \brief clone TODO
+ * \return
+ */
AutoPtr clone() const;
private:
+ /*!
+ * \brief clone TODO
+ * \return
+ */
virtual FixIso* clone_() const;
- std::string path_;
+ std::string path_; //!< TODO
}; // class FixIso
@@ -399,12 +451,20 @@ namespace Action {
public:
virtual ~FixCom();
virtual int run(const std::string& path);
- typedef std::auto_ptr AutoPtr;
+ typedef std::auto_ptr AutoPtr; //!< TODO
+ /*!
+ * \brief clone TODO
+ * \return
+ */
AutoPtr clone() const;
private:
+ /*!
+ * \brief clone TODO
+ * \return
+ */
virtual FixCom* clone_() const;
- std::string path_;
+ std::string path_; //!< TODO
}; // class FixCom
diff --git a/src/asfvideo.cpp b/src/asfvideo.cpp
index e296a0be..29e14ded 100644
--- a/src/asfvideo.cpp
+++ b/src/asfvideo.cpp
@@ -160,6 +160,7 @@ namespace Exiv2 {
{ 0x7A22, "GSM-AMR (VBR including SID)" }
};
+ //! File properties.
extern const TagDetails filePropertiesTags[] = {
{ 7, "Xmp.video.FileLength" },
{ 6, "Xmp.video.CreationDate" },
@@ -170,6 +171,7 @@ namespace Exiv2 {
{ 1, "Xmp.video.MaxBitRate" }
};
+ //!Contents Description.
extern const TagDetails contentDescriptionTags[] = {
{ 0, "Xmp.video.Title" },
{ 1, "Xmp.video.Author" },
@@ -293,11 +295,37 @@ namespace Exiv2 {
using namespace Exiv2::Internal;
+ class AsfVideo::Private
+ {
+ public:
+ Private()
+ {
+ continueTraversing_ = true;
+ localPosition_ = 1;
+ streamNumber_ = 0;
+ height_ = 1;
+ width_ = 1;
+ }
+ //! Variable to check the end of metadata traversing.
+ bool continueTraversing_;
+ //! Variable which stores current position of the read pointer.
+ uint64_t localPosition_;
+ //! Variable which stores current stream being processsed.
+ int streamNumber_;
+ //! Variable to store height and width of a video frame.
+ uint64_t height_, width_;
+ };
+
AsfVideo::AsfVideo(BasicIo::AutoPtr io)
- : Image(ImageType::asf, mdNone, io)
+ : Image(ImageType::asf, mdNone, io),d(new Private)
{
} // AsfVideo::AsfVideo
+ AsfVideo::~AsfVideo()
+ {
+ delete d;
+ }
+
std::string AsfVideo::mimeType() const
{
return "video/asf";
@@ -319,15 +347,15 @@ namespace Exiv2 {
IoCloser closer(*io_);
clearMetadata();
- continueTraversing_ = true;
+ d->continueTraversing_ = true;
io_->seek(0, BasicIo::beg);
- height_ = width_ = 1;
+ d->height_ = d->width_ = 1;
xmpData_["Xmp.video.FileSize"] = (double)io_->size()/(double)1048576;
xmpData_["Xmp.video.FileName"] = io_->path();
xmpData_["Xmp.video.MimeType"] = mimeType();
- while (continueTraversing_) decodeBlock();
+ while (d->continueTraversing_) decodeBlock();
aspectRatio();
} // AsfVideo::readMetadata
@@ -337,7 +365,6 @@ namespace Exiv2 {
const long bufMinSize = 9;
DataBuf buf(bufMinSize);
unsigned long size = 0;
- buf.pData_[8] = '\0' ;
const TagVocabulary* tv;
uint64_t cur_pos = io_->tell();
@@ -345,7 +372,7 @@ namespace Exiv2 {
io_->read(guidBuf, 16);
if(io_->eof()) {
- continueTraversing_ = false;
+ d->continueTraversing_ = false;
return;
}
@@ -354,7 +381,6 @@ namespace Exiv2 {
getGUID(guidBuf, GUID);
tv = find( GUIDReferenceTags, GUID);
- std::memset(buf.pData_, 0x0, buf.size_);
io_->read(buf.pData_, 8);
size = static_cast(getUint64_t(buf));
@@ -364,7 +390,7 @@ namespace Exiv2 {
else
io_->seek(cur_pos + size, BasicIo::beg);
- localPosition_ = io_->tell();
+ d->localPosition_ = io_->tell();
} // AsfVideo::decodeBlock
void AsfVideo::tagDecoder(const TagVocabulary *tv, uint64_t size)
@@ -376,11 +402,11 @@ namespace Exiv2 {
Exiv2::Value::AutoPtr v = Exiv2::Value::create(Exiv2::xmpSeq);
if(compareTag( exvGettext(tv->label_), "Header")) {
- localPosition_ = 0;
+ d->localPosition_ = 0;
io_->read(buf.pData_, 4);
io_->read(buf.pData_, 2);
- while(localPosition_ < cur_pos + size) decodeBlock();
+ while(d->localPosition_ < cur_pos + size) decodeBlock();
}
else if(compareTag( exvGettext(tv->label_), "File_Properties"))
@@ -408,7 +434,7 @@ namespace Exiv2 {
extendedStreamProperties(size);
else if(compareTag( exvGettext(tv->label_), "Header_Extension")) {
- localPosition_ = 0;
+ d->localPosition_ = 0;
headerExtension(size);
}
@@ -428,7 +454,7 @@ namespace Exiv2 {
}
io_->seek(cur_pos + size, BasicIo::beg);
- localPosition_ = io_->tell();
+ d->localPosition_ = io_->tell();
} // AsfVideo::tagDecoder
void AsfVideo::extendedStreamProperties(uint64_t size)
@@ -440,16 +466,16 @@ namespace Exiv2 {
std::memset(buf.pData_, 0x0, buf.size_);
io_->read(buf.pData_, 2);
- streamNumber_ = Exiv2::getUShort(buf.pData_, littleEndian);
+ d->streamNumber_ = Exiv2::getUShort(buf.pData_, littleEndian);
io_->read(buf.pData_, 2);
io_->read(buf.pData_, 8);
avgTimePerFrame = getUint64_t(buf);
- if(previousStream < streamNumber_ && avgTimePerFrame != 0)
+ if(previousStream < d->streamNumber_ && avgTimePerFrame != 0)
xmpData_["Xmp.video.FrameRate"] = (double)10000000/(double)avgTimePerFrame;
- previousStream = streamNumber_;
+ previousStream = d->streamNumber_;
io_->seek(cur_pos + size, BasicIo::beg);
} // AsfVideo::extendedStreamProperties
@@ -466,7 +492,6 @@ namespace Exiv2 {
}
for (int i = 0 ; i < 5 ; ++i) {
DataBuf buf(length[i]);
- std::memset(buf.pData_, 0x0, buf.size_);
io_->read(buf.pData_, length[i]);
if (io_->error() || io_->eof()) throw Error(14);
const TagDetails* td = find(contentDescriptionTags, i);
@@ -510,7 +535,7 @@ namespace Exiv2 {
io_->read(buf.pData_, 8);
std::memset(buf.pData_, 0x0, buf.size_);
io_->read(buf.pData_, 1);
- streamNumber_ = (int)buf.pData_[0] & 127;
+ d->streamNumber_ = (int)buf.pData_[0] & 127;
io_->read(buf.pData_, 5);
std::memset(buf.pData_, 0x0, buf.size_);
@@ -519,7 +544,7 @@ namespace Exiv2 {
if(stream == 2) {
xmpData_["Xmp.video.Width"] = temp;
- width_ = temp;
+ d->width_ = temp;
}
else if(stream == 1) {
xmpData_["Xmp.audio.Codec"] = test->printAudioEncoding(temp);
@@ -535,7 +560,7 @@ namespace Exiv2 {
if(stream == 2) {
xmpData_["Xmp.video.Height"] = temp;
- height_ = temp;
+ d->height_ = temp;
}
else if(stream == 1) {
xmpData_["Xmp.audio.SampleRate"] = temp;
@@ -615,7 +640,7 @@ namespace Exiv2 {
buf.pData_[4] = '\0' ;
io_->read(buf.pData_, 4);
- while(localPosition_ < cur_pos + size) decodeBlock();
+ while(d->localPosition_ < cur_pos + size) decodeBlock();
io_->seek(cur_pos + size, BasicIo::beg);
} // AsfVideo::headerExtension
@@ -768,7 +793,7 @@ namespace Exiv2 {
{
//TODO - Make a better unified method to handle all cases of Aspect Ratio
- double aspectRatio = (double)width_ / (double)height_;
+ double aspectRatio = (double)d->width_ / (double)d->height_;
aspectRatio = floor(aspectRatio*10) / 10;
xmpData_["Xmp.video.AspectRatio"] = aspectRatio;
diff --git a/src/asfvideo.hpp b/src/asfvideo.hpp
index 79515b9c..32ea14ce 100644
--- a/src/asfvideo.hpp
+++ b/src/asfvideo.hpp
@@ -69,6 +69,7 @@ namespace Exiv2 {
method to get a temporary reference.
*/
AsfVideo(BasicIo::AutoPtr io);
+ ~AsfVideo();
//@}
//! @name Manipulators
@@ -154,14 +155,9 @@ namespace Exiv2 {
//@}
private:
- //! Variable to check the end of metadata traversing.
- bool continueTraversing_;
- //! Variable which stores current position of the read pointer.
- uint64_t localPosition_;
- //! Variable which stores current stream being processsed.
- int streamNumber_;
- //! Variable to store height and width of a video frame.
- uint64_t height_, width_;
+
+ class Private;
+ Private * const d;
}; //Class AsfVideo
diff --git a/src/error.hpp b/src/error.hpp
index b8df55d2..58686421 100644
--- a/src/error.hpp
+++ b/src/error.hpp
@@ -274,6 +274,11 @@ namespace Exiv2 {
}
template template
+ /*!
+ * \brief BasicError::BasicError TODO
+ * \param code
+ * \param arg1
+ */
BasicError::BasicError(int code, const A& arg1)
: code_(code), count_(1), arg1_(toBasicString(arg1))
{
@@ -281,6 +286,12 @@ namespace Exiv2 {
}
template template
+ /*!
+ * \brief BasicError::BasicError TODO
+ * \param code
+ * \param arg1
+ * \param arg2
+ */
BasicError::BasicError(int code, const A& arg1, const B& arg2)
: code_(code), count_(2),
arg1_(toBasicString(arg1)),
@@ -290,6 +301,13 @@ namespace Exiv2 {
}
template template
+ /*!
+ * \brief BasicError::BasicError TODO
+ * \param code
+ * \param arg1
+ * \param arg2
+ * \param arg3
+ */
BasicError::BasicError(int code, const A& arg1, const B& arg2, const C& arg3)
: code_(code), count_(3),
arg1_(toBasicString(arg1)),
diff --git a/src/image.cpp b/src/image.cpp
index bedad72a..14538366 100644
--- a/src/image.cpp
+++ b/src/image.cpp
@@ -131,8 +131,8 @@ namespace {
{ ImageType::tga, newTgaInstance, isTgaType, amNone, amNone, amNone, amNone },
{ ImageType::bmp, newBmpInstance, isBmpType, amNone, amNone, amNone, amNone },
{ ImageType::jp2, newJp2Instance, isJp2Type, amReadWrite, amReadWrite, amReadWrite, amNone },
- { ImageType::qtime,newQTimeInstance,isQTimeType,amRead, amNone, amRead, amNone },
- { ImageType::riff, newRiffInstance, isRiffType, amRead, amNone, amRead, amNone },
+ { ImageType::qtime,newQTimeInstance,isQTimeType,amRead, amNone, amReadWrite, amNone },
+ { ImageType::riff, newRiffInstance, isRiffType, amRead, amNone, amReadWrite, amNone },
{ ImageType::asf, newAsfInstance, isAsfType, amNone, amNone, amRead, amNone },
{ ImageType::mkv, newMkvInstance, isMkvType, amNone, amNone, amRead, amNone },
// End of list marker
diff --git a/src/matroskavideo.cpp b/src/matroskavideo.cpp
index 78d335c1..9b726667 100644
--- a/src/matroskavideo.cpp
+++ b/src/matroskavideo.cpp
@@ -36,43 +36,49 @@ EXIV2_RCSID("@(#) $Id$")
#include "basicio.hpp"
#include "tags.hpp"
#include "tags_int.hpp"
-
+#include "types.hpp"
+#include "tiffimage_int.hpp"
// + standard includes
#include
#include
+#define lengthof(x) (sizeof(x)/sizeof(x[0]))
+
+using namespace std;
// *****************************************************************************
// class member definitions
-namespace Exiv2 {
- namespace Internal {
+namespace Exiv2
+{
+namespace Internal
+{
- //! List of composite tags. They are skipped and the child tags are read immediately
- uint64_t compositeTagsList[] = {
- 0x0000, 0x000e, 0x000f, 0x0020, 0x0026, 0x002e, 0x0036,
- 0x0037, 0x003b, 0x005b, 0x0060, 0x0061, 0x0068, 0x05b9,
- 0x0dbb, 0x1034, 0x1035, 0x1854, 0x21a7, 0x2240, 0x23c0,
- 0x2624, 0x27c8, 0x2911, 0x2924, 0x2944, 0x2d80, 0x3373,
- 0x35a1, 0x3e5b, 0x3e7b,
- 0x14d9b74, 0x254c367, 0x549a966, 0x654ae6b, 0x8538067,
- 0x941a469, 0xa45dfa3, 0xb538667, 0xc53bb6b, 0xf43b675
- };
+//! List of composite tags. They are skipped and the child tags are read immediately
+uint64_t compositeTagsList[] ={
+ 0x0000, 0x000e, 0x000f, 0x0020, 0x0026, 0x002e, 0x0036,
+ 0x0037, 0x003b, 0x005b, 0x0060, 0x0061, 0x0068, 0x05b9,
+ 0x0dbb, 0x1034, 0x1035, 0x1854, 0x21a7, 0x2240, 0x23c0,
+ 0x2624, 0x27c8, 0x2911, 0x2924, 0x2944, 0x2d80, 0x3373,
+ 0x35a1, 0x3e5b, 0x3e7b,
+ 0x14d9b74, 0x254c367, 0x549a966, 0x654ae6b, 0x8538067,
+ 0x941a469, 0xa45dfa3, 0xb538667, 0xc53bb6b, 0xf43b675
+};
- //! List of tags which are ignored, i.e., tag and value won't be read
- uint64_t ignoredTagsList[] = {
- 0x0021, 0x0023, 0x0033, 0x0071, 0x0077, 0x006c, 0x0067, 0x007b, 0x02f2, 0x02f3,
- 0x1031, 0x1032, 0x13ab, 0x13ac, 0x15ee, 0x23a2, 0x23c6, 0x2e67, 0x33a4, 0x33c5,
- 0x3446, 0x2de7, 0x2df8, 0x26bf, 0x28ca, 0x3384, 0x13b8, 0x037e, 0x0485, 0x18d7,
- 0x0005, 0x0009, 0x0011, 0x0012, 0x0016, 0x0017, 0x0018, 0x0022, 0x0024, 0x0025,
- 0x0027, 0x002b, 0x002f, 0x003f, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x006a,
- 0x006b, 0x006e, 0x007a, 0x007d, 0x0255, 0x3eb5, 0x3ea5, 0x3d7b, 0x33c4, 0x2fab,
- 0x2ebc, 0x29fc, 0x29a5, 0x2955, 0x2933, 0x135f, 0x2922, 0x26a5, 0x26fc, 0x2532,
- 0x23c9, 0x23c4, 0x23c5, 0x137f, 0x1378, 0x07e2, 0x07e3, 0x07e4, 0x0675, 0x05bc,
- 0x05bd, 0x05db, 0x05dd, 0x0598, 0x050d, 0x0444, 0x037c,
+//! List of tags which are ignored, i.e., tag and value won't be read
+uint64_t ignoredTagsList[] ={
+ 0x0021, 0x0023, 0x0033, 0x0071, 0x0077, 0x006c, 0x0067, 0x007b, 0x02f2, 0x02f3,
+ 0x1031, 0x1032, 0x13ab, 0x13ac, 0x15ee, 0x23a2, 0x23c6, 0x2e67, 0x33a4, 0x33c5,
+ 0x3446, 0x2de7, 0x2df8, 0x26bf, 0x28ca, 0x3384, 0x13b8, 0x037e, 0x0485, 0x18d7,
+ 0x0005, 0x0009, 0x0011, 0x0012, 0x0016, 0x0017, 0x0018, 0x0022, 0x0024, 0x0025,
+ 0x0027, 0x002b, 0x002f, 0x003f, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x006a,
+ 0x006b, 0x006e, 0x007a, 0x007d, 0x0255, 0x3eb5, 0x3ea5, 0x3d7b, 0x33c4, 0x2fab,
+ 0x2ebc, 0x29fc, 0x29a5, 0x2955, 0x2933, 0x135f, 0x2922, 0x26a5, 0x26fc, 0x2532,
+ 0x23c9, 0x23c4, 0x23c5, 0x137f, 0x1378, 0x07e2, 0x07e3, 0x07e4, 0x0675, 0x05bc,
+ 0x05bd, 0x05db, 0x05dd, 0x0598, 0x050d, 0x0444, 0x037c,
- 0x3314f, 0x43a770, 0x1eb923, 0x1cb923, 0xeb524, 0x1c83ab, 0x1e83bb
- };
+ 0x3314f, 0x43a770, 0x1eb923, 0x1cb923, 0xeb524, 0x1c83ab, 0x1e83bb
+};
- /*!
+/*!
Tag Look-up list for Matroska Type Video Files
The Tags have been categorized in 4 categories. Which are
mentioned as a comment in front of them.
@@ -81,682 +87,913 @@ namespace Exiv2 {
u -- Tag used directly for storing metadata
ui -- Tag used only internally
*/
- extern const MatroskaTags matroskaTags[] = {
- { 0x0000, "ChapterDisplay" }, //s
- { 0x0003, "TrackType" }, //ui
- { 0x0005, "ChapterString" }, //sd
- { 0x0006, "VideoCodecID/AudioCodecID/CodecID" }, //ui
- { 0x0008, "TrackDefault" }, //ui
- { 0x0009, "ChapterTrackNumber" }, //sd
- { 0x000e, "Slices" }, //s
- { 0x000f, "ChapterTrack" }, //s
- { 0x0011, "ChapterTimeStart" }, //sd
- { 0x0012, "ChapterTimeEnd" }, //sd
- { 0x0016, "CueRefTime" }, //sd
- { 0x0017, "CueRefCluster" }, //sd
- { 0x0018, "ChapterFlagHidden" }, //sd
- { 0x001a, "Xmp.video.VideoScanTpye" }, //u
- { 0x001b, "BlockDuration" }, //s
- { 0x001c, "TrackLacing" }, //ui
- { 0x001f, "Xmp.audio.ChannelType" }, //u
- { 0x0020, "BlockGroup" }, //s
- { 0x0021, "Block" }, //sd
- { 0x0022, "BlockVirtual" }, //sd
- { 0x0023, "SimpleBlock" }, //sd
- { 0x0024, "CodecState" }, //sd
- { 0x0025, "BlockAdditional" }, //sd
- { 0x0026, "BlockMore" }, //s
- { 0x0027, "Position" }, //sd
- { 0x002a, "CodecDecodeAll" }, //ui
- { 0x002b, "PrevSize" }, //sd
- { 0x002e, "TrackEntry" }, //s
- { 0x002f, "EncryptedBlock" }, //sd
- { 0x0030, "Xmp.video.Width" }, //u
- { 0x0033, "CueTime" }, //sd
- { 0x0035, "Xmp.audio.SampleRate" }, //u
- { 0x0036, "ChapterAtom" }, //s
- { 0x0037, "CueTrackPositions" }, //s
- { 0x0039, "TrackUsed" }, //ui
- { 0x003a, "Xmp.video.Height" }, //u
- { 0x003b, "CuePoint" }, //s
- { 0x003f, "CRC-32" }, //sd
- { 0x004b, "BlockAdditionalID" }, //sd
- { 0x004c, "LaceNumber" }, //sd
- { 0x004d, "FrameNumber" }, //sd
- { 0x004e, "Delay" }, //sd
- { 0x004f, "ClusterDuration" }, //sd
- { 0x0057, "TrackNumber" }, //ui
- { 0x005b, "CueReference" }, //s
- { 0x0060, "Video" }, //s
- { 0x0061, "Audio" }, //s
- { 0x0067, "Timecode" }, //sd
- { 0x0068, "TimeSlice" }, //s
- { 0x006a, "CueCodecState" }, //sd
- { 0x006b, "CueRefCodecState" }, //sd
- { 0x006c, "Void" }, //sd
- { 0x006e, "BlockAddID" }, //sd
- { 0x0071, "CueClusterPosition" }, //sd
- { 0x0077, "CueTrack" }, //sd
- { 0x007a, "ReferencePriority" }, //sd
- { 0x007b, "ReferenceBlock" }, //sd
- { 0x007d, "ReferenceVirtual" }, //sd
- { 0x0254, "Xmp.video.ContentCompressAlgo" }, //u
- { 0x0255, "ContentCompressionSettings" }, //sd
- { 0x0282, "Xmp.video.DocType" }, //u
- { 0x0285, "Xmp.video.DocTypeReadVersion" }, //u
- { 0x0286, "Xmp.video.EBMLVersion" }, //u
- { 0x0287, "Xmp.video.DocTypeVersion" }, //u
- { 0x02f2, "EBMLMaxIDLength" }, //sd
- { 0x02f3, "EBMLMaxSizeLength" }, //sd
- { 0x02f7, "Xmp.video.EBMLReadVersion" }, //u
- { 0x037c, "ChapterLanguage" }, //sd
- { 0x037e, "ChapterCountry" }, //sd
- { 0x0444, "SegmentFamily" }, //sd
- { 0x0461, "Xmp.video.DateUTC" }, //Date Time Original - measured in seconds relatively to Jan 01, 2001, 0:00:00 GMT+0h
- { 0x047a, "Xmp.video.TagLanguage" }, //u
- { 0x0484, "Xmp.video.TagDefault" }, //u
- { 0x0485, "TagBinary" }, //sd
- { 0x0487, "Xmp.video.TagString" }, //u
- { 0x0489, "Xmp.video.Duration" }, //u
- { 0x050d, "ChapterProcessPrivate" }, //sd
- { 0x0598, "ChapterFlagEnabled" }, //sd
- { 0x05a3, "Xmp.video.TagName" }, //u
- { 0x05b9, "EditionEntry" }, //s
- { 0x05bc, "EditionUID" }, //sd
- { 0x05bd, "EditionFlagHidden" }, //sd
- { 0x05db, "EditionFlagDefault" }, //sd
- { 0x05dd, "EditionFlagOrdered" }, //sd
- { 0x065c, "Xmp.video.AttachFileData" }, //u
- { 0x0660, "Xmp.video.AttachFileMIME" }, //u
- { 0x066e, "Xmp.video.AttachFileName" }, //u
- { 0x0675, "AttachedFileReferral" }, //sd
- { 0x067e, "Xmp.video.AttachFileDesc" }, //u
- { 0x06ae, "Xmp.video.AttachFileUID" }, //u
- { 0x07e1, "Xmp.video.ContentEncryptAlgo" }, //u
- { 0x07e2, "ContentEncryptionKeyID" }, //sd
- { 0x07e3, "ContentSignature" }, //sd
- { 0x07e4, "ContentSignatureKeyID" }, //sd
- { 0x07e5, "Xmp.video.ContentSignAlgo" }, //u
- { 0x07e6, "Xmp.video.ContentSignHashAlgo" }, //u
- { 0x0d80, "Xmp.video.MuxingApp" }, //u
- { 0x0dbb, "Seek" }, //s
- { 0x1031, "ContentEncodingOrder" }, //sd
- { 0x1032, "ContentEncodingScope" }, //sd
- { 0x1033, "Xmp.video.ContentEncodingType" }, //u
- { 0x1034, "ContentCompression" }, //s
- { 0x1035, "ContentEncryption" }, //s
- { 0x135f, "CueRefNumber" }, //sd
- { 0x136e, "Xmp.video.TrackName" }, //u
- { 0x1378, "CueBlockNumber" }, //sd
- { 0x137f, "TrackOffset" }, //sd
- { 0x13ab, "SeekID" }, //sd
- { 0x13ac, "SeekPosition" }, //sd
- { 0x13b8, "Stereo3DMode" }, //sd
- { 0x14aa, "Xmp.video.CropBottom" }, //ui
- { 0x14b0, "Xmp.video.Width" }, //u
- { 0x14b2, "Xmp.video.DisplayUnit" }, //u
- { 0x14b3, "Xmp.video.AspectRatioType" }, //u
- { 0x14ba, "Xmp.video.Height" }, //u
- { 0x14bb, "Xmp.video.CropTop" }, //ui
- { 0x14cc, "Xmp.video.CropLeft" }, //ui
- { 0x14dd, "Xmp.video.CropRight" }, //ui
- { 0x15aa, "TrackForced" }, //ui
- { 0x15ee, "MaxBlockAdditionID" }, //sd
- { 0x1741, "Xmp.video.WritingApp" }, //u
- { 0x1854, "SilentTracks" }, //s
- { 0x18d7, "SilentTrackNumber" }, //sd
- { 0x21a7, "AttachedFile" }, //s
- { 0x2240, "ContentEncoding" }, //s
- { 0x2264, "Xmp.audio.BitsPerSample" }, //u
- { 0x23a2, "CodecPrivate" }, //sd
- { 0x23c0, "Targets" }, //s
- { 0x23c3, "Xmp.video.PhysicalEquivalent" }, //u
- { 0x23c4, "TagChapterUID" }, //sd
- { 0x23c5, "TagTrackUID" }, //sd
- { 0x23c6, "TagAttachmentUID" }, //sd
- { 0x23c9, "TagEditionUID" }, //sd
- { 0x23ca, "Xmp.video.TargetType" }, //u
- { 0x2532, "SignedElement" }, //sd
- { 0x2624, "TrackTranslate" }, //s
- { 0x26a5, "TrackTranslateTrackID" }, //sd
- { 0x26bf, "TrackTranslateCodec" }, //sd
- { 0x26fc, "TrackTranslateEditionUID" }, //sd
- { 0x27c8, "SimpleTag" }, //s
- { 0x28ca, "TargetTypeValue" }, //sd
- { 0x2911, "ChapterProcessCommand" }, //s
- { 0x2922, "ChapterProcessTime" }, //sd
- { 0x2924, "ChapterTranslate" }, //s
- { 0x2933, "ChapterProcessData" }, //sd
- { 0x2944, "ChapterProcess" }, //s
- { 0x2955, "ChapterProcessCodecID" }, //sd
- { 0x29a5, "ChapterTranslateID" }, //sd
- { 0x29bf, "Xmp.video.TranslateCodec" }, //u
- { 0x29fc, "ChapterTranslateEditionUID" }, //sd
- { 0x2d80, "ContentEncodings" }, //s
- { 0x2de7, "MinCache" }, //sd
- { 0x2df8, "MaxCache" }, //sd
- { 0x2e67, "ChapterSegmentUID" }, //sd
- { 0x2ebc, "ChapterSegmentEditionUID" }, //sd
- { 0x2fab, "TrackOverlay" }, //sd
- { 0x3373, "Tag" }, //s
- { 0x3384, "SegmentFileName" }, //sd
- { 0x33a4, "SegmentUID" }, //sd
- { 0x33c4, "ChapterUID" }, //sd
- { 0x33c5, "TrackUID" }, //sd
- { 0x3446, "TrackAttachmentUID" }, //sd
- { 0x35a1, "BlockAdditions" }, //s
- { 0x38b5, "Xmp.audio.OutputSampleRate" }, //u
- { 0x3ba9, "Xmp.video.Title" }, //u
- { 0x3d7b, "ChannelPositions" }, //sd
- { 0x3e5b, "SignatureElements" }, //s
- { 0x3e7b, "SignatureElementList" }, //s
- { 0x3e8a, "Xmp.video.ContentSignAlgo" }, //u
- { 0x3e9a, "Xmp.video.ContentSignHashAlgo" }, //u
- { 0x3ea5, "SignaturePublicKey" }, //sd
- { 0x3eb5, "Signature" }, //sd
- { 0x2b59c, "TrackLanguage" }, //ui
- { 0x3314f, "TrackTimecodeScale" }, //sd
- { 0x383e3, "Xmp.video.FrameRate" }, //u
- { 0x3e383, "VideoFrameRate/DefaultDuration" }, //ui
- { 0x58688, "VideoCodecName/AudioCodecName/CodecName" }, //ui
- { 0x6b240, "CodecDownloadURL" }, //ui
- { 0xad7b1, "TimecodeScale" }, //ui
- { 0xeb524, "ColorSpace" }, //sd
- { 0xfb523, "Xmp.video.OpColor" }, //u
- { 0x1a9697, "CodecSettings" }, //ui
- { 0x1b4040, "CodecInfoURL" }, //ui
- { 0x1c83ab, "PrevFileName" }, //sd
- { 0x1cb923, "PrevUID" }, //sd
- { 0x1e83bb, "NextFileName" }, //sd
- { 0x1eb923, "NextUID" }, //sd
- { 0x43a770, "Chapters" }, //sd
- { 0x14d9b74, "SeekHead" }, //s
- { 0x254c367, "Tags" }, //s
- { 0x549a966, "Info" }, //s
- { 0x654ae6b, "Tracks" }, //s
- { 0x8538067, "SegmentHeader" }, //s
- { 0x941a469, "Attachments" }, //s
- { 0xa45dfa3, "EBMLHeader" }, //s
- { 0xb538667, "SignatureSlot" }, //s
- { 0xc53bb6b, "Cues" }, //s
- { 0xf43b675, "Cluster" }, //s
- };
+extern const MatroskaTags matroskaTags[] ={
+ { 0x0000, "ChapterDisplay" }, //s
+ { 0x0003, "TrackType" }, //ui
+ { 0x0005, "ChapterString" }, //sd
+ { 0x0006, "VideoCodecID/AudioCodecID/CodecID" }, //ui
+ { 0x0008, "TrackDefault" }, //ui
+ { 0x0009, "ChapterTrackNumber" }, //sd
+ { 0x000e, "Slices" }, //s
+ { 0x000f, "ChapterTrack" }, //s
+ { 0x0011, "ChapterTimeStart" }, //sd
+ { 0x0012, "ChapterTimeEnd" }, //sd
+ { 0x0016, "CueRefTime" }, //sd
+ { 0x0017, "CueRefCluster" }, //sd
+ { 0x0018, "ChapterFlagHidden" }, //sd
+ { 0x001a, "Xmp.video.VideoScanTpye" }, //u
+ { 0x001b, "BlockDuration" }, //s
+ { 0x001c, "TrackLacing" }, //ui
+ { 0x001f, "Xmp.audio.ChannelType" }, //u
+ { 0x0020, "BlockGroup" }, //s
+ { 0x0021, "Block" }, //sd
+ { 0x0022, "BlockVirtual" }, //sd
+ { 0x0023, "SimpleBlock" }, //sd
+ { 0x0024, "CodecState" }, //sd
+ { 0x0025, "BlockAdditional" }, //sd
+ { 0x0026, "BlockMore" }, //s
+ { 0x0027, "Position" }, //sd
+ { 0x002a, "CodecDecodeAll" }, //ui
+ { 0x002b, "PrevSize" }, //sd
+ { 0x002e, "TrackEntry" }, //s
+ { 0x002f, "EncryptedBlock" }, //sd
+ { 0x0030, "Xmp.video.Width" }, //u
+ { 0x0033, "CueTime" }, //sd
+ { 0x0035, "Xmp.audio.SampleRate" }, //u
+ { 0x0036, "ChapterAtom" }, //s
+ { 0x0037, "CueTrackPositions" }, //s
+ { 0x0039, "TrackUsed" }, //ui
+ { 0x003a, "Xmp.video.Height" }, //u
+ { 0x003b, "CuePoint" }, //s
+ { 0x003f, "CRC-32" }, //sd
+ { 0x004b, "BlockAdditionalID" }, //sd
+ { 0x004c, "LaceNumber" }, //sd
+ { 0x004d, "FrameNumber" }, //sd
+ { 0x004e, "Delay" }, //sd
+ { 0x004f, "ClusterDuration" }, //sd
+ { 0x0057, "TrackNumber" }, //ui
+ { 0x005b, "CueReference" }, //s
+ { 0x0060, "Video" }, //s
+ { 0x0061, "Audio" }, //s
+ { 0x0067, "Timecode" }, //sd
+ { 0x0068, "TimeSlice" }, //s
+ { 0x006a, "CueCodecState" }, //sd
+ { 0x006b, "CueRefCodecState" }, //sd
+ { 0x006c, "Void" }, //sd
+ { 0x006e, "BlockAddID" }, //sd
+ { 0x0071, "CueClusterPosition" }, //sd
+ { 0x0077, "CueTrack" }, //sd
+ { 0x007a, "ReferencePriority" }, //sd
+ { 0x007b, "ReferenceBlock" }, //sd
+ { 0x007d, "ReferenceVirtual" }, //sd
+ { 0x0254, "Xmp.video.ContentCompressAlgo" }, //u
+ { 0x0255, "ContentCompressionSettings" }, //sd
+ { 0x0282, "Xmp.video.DocType" }, //u
+ { 0x0285, "Xmp.video.DocTypeReadVersion" }, //u
+ { 0x0286, "Xmp.video.EBMLVersion" }, //u
+ { 0x0287, "Xmp.video.DocTypeVersion" }, //u
+ { 0x02f2, "EBMLMaxIDLength" }, //sd
+ { 0x02f3, "EBMLMaxSizeLength" }, //sd
+ { 0x02f7, "Xmp.video.EBMLReadVersion" }, //u
+ { 0x037c, "ChapterLanguage" }, //sd
+ { 0x037e, "ChapterCountry" }, //sd
+ { 0x0444, "SegmentFamily" }, //sd
+ { 0x0461, "Xmp.video.DateUTC" }, //Date Time Original - measured in seconds relatively to Jan 01, 2001, 0:00:00 GMT+0h
+ { 0x047a, "Xmp.video.TagLanguage" }, //u
+ { 0x0484, "Xmp.video.TagDefault" }, //u
+ { 0x0485, "TagBinary" }, //sd
+ { 0x0487, "Xmp.video.TagString" }, //u
+ { 0x0489, "Xmp.video.Duration" }, //u
+ { 0x050d, "ChapterProcessPrivate" }, //sd
+ { 0x0598, "ChapterFlagEnabled" }, //sd
+ { 0x05a3, "Xmp.video.TagName" }, //u
+ { 0x05b9, "EditionEntry" }, //s
+ { 0x05bc, "EditionUID" }, //sd
+ { 0x05bd, "EditionFlagHidden" }, //sd
+ { 0x05db, "EditionFlagDefault" }, //sd
+ { 0x05dd, "EditionFlagOrdered" }, //sd
+ { 0x065c, "Xmp.video.AttachFileData" }, //u
+ { 0x0660, "Xmp.video.AttachFileMIME" }, //u
+ { 0x066e, "Xmp.video.AttachFileName" }, //u
+ { 0x0675, "AttachedFileReferral" }, //sd
+ { 0x067e, "Xmp.video.AttachFileDesc" }, //u
+ { 0x06ae, "Xmp.video.AttachFileUID" }, //u
+ { 0x07e1, "Xmp.video.ContentEncryptAlgo" }, //u
+ { 0x07e2, "ContentEncryptionKeyID" }, //sd
+ { 0x07e3, "ContentSignature" }, //sd
+ { 0x07e4, "ContentSignatureKeyID" }, //sd
+ { 0x07e5, "Xmp.video.ContentSignAlgo" }, //u
+ { 0x07e6, "Xmp.video.ContentSignHashAlgo" }, //u
+ { 0x0d80, "Xmp.video.MuxingApp" }, //u
+ { 0x0dbb, "Seek" }, //s
+ { 0x1031, "ContentEncodingOrder" }, //sd
+ { 0x1032, "ContentEncodingScope" }, //sd
+ { 0x1033, "Xmp.video.ContentEncodingType" }, //u
+ { 0x1034, "ContentCompression" }, //s
+ { 0x1035, "ContentEncryption" }, //s
+ { 0x135f, "CueRefNumber" }, //sd
+ { 0x136e, "Xmp.video.TrackName" }, //u
+ { 0x1378, "CueBlockNumber" }, //sd
+ { 0x137f, "TrackOffset" }, //sd
+ { 0x13ab, "SeekID" }, //sd
+ { 0x13ac, "SeekPosition" }, //sd
+ { 0x13b8, "Stereo3DMode" }, //sd
+ { 0x14aa, "Xmp.video.CropBottom" }, //ui
+ { 0x14b0, "Xmp.video.Width" }, //u
+ { 0x14b2, "Xmp.video.DisplayUnit" }, //u
+ { 0x14b3, "Xmp.video.AspectRatioType" }, //u
+ { 0x14ba, "Xmp.video.Height" }, //u
+ { 0x14bb, "Xmp.video.CropTop" }, //ui
+ { 0x14cc, "Xmp.video.CropLeft" }, //ui
+ { 0x14dd, "Xmp.video.CropRight" }, //ui
+ { 0x15aa, "TrackForced" }, //ui
+ { 0x15ee, "MaxBlockAdditionID" }, //sd
+ { 0x1741, "Xmp.video.WritingApp" }, //u
+ { 0x1854, "SilentTracks" }, //s
+ { 0x18d7, "SilentTrackNumber" }, //sd
+ { 0x21a7, "AttachedFile" }, //s
+ { 0x2240, "ContentEncoding" }, //s
+ { 0x2264, "Xmp.audio.BitsPerSample" }, //u
+ { 0x23a2, "CodecPrivate" }, //sd
+ { 0x23c0, "Targets" }, //s
+ { 0x23c3, "Xmp.video.PhysicalEquivalent" }, //u
+ { 0x23c4, "TagChapterUID" }, //sd
+ { 0x23c5, "TagTrackUID" }, //sd
+ { 0x23c6, "TagAttachmentUID" }, //sd
+ { 0x23c9, "TagEditionUID" }, //sd
+ { 0x23ca, "Xmp.video.TargetType" }, //u
+ { 0x2532, "SignedElement" }, //sd
+ { 0x2624, "TrackTranslate" }, //s
+ { 0x26a5, "TrackTranslateTrackID" }, //sd
+ { 0x26bf, "TrackTranslateCodec" }, //sd
+ { 0x26fc, "TrackTranslateEditionUID" }, //sd
+ { 0x27c8, "SimpleTag" }, //s
+ { 0x28ca, "TargetTypeValue" }, //sd
+ { 0x2911, "ChapterProcessCommand" }, //s
+ { 0x2922, "ChapterProcessTime" }, //sd
+ { 0x2924, "ChapterTranslate" }, //s
+ { 0x2933, "ChapterProcessData" }, //sd
+ { 0x2944, "ChapterProcess" }, //s
+ { 0x2955, "ChapterProcessCodecID" }, //sd
+ { 0x29a5, "ChapterTranslateID" }, //sd
+ { 0x29bf, "Xmp.video.TranslateCodec" }, //u
+ { 0x29fc, "ChapterTranslateEditionUID" }, //sd
+ { 0x2d80, "ContentEncodings" }, //s
+ { 0x2de7, "MinCache" }, //sd
+ { 0x2df8, "MaxCache" }, //sd
+ { 0x2e67, "ChapterSegmentUID" }, //sd
+ { 0x2ebc, "ChapterSegmentEditionUID" }, //sd
+ { 0x2fab, "TrackOverlay" }, //sd
+ { 0x3373, "Tag" }, //s
+ { 0x3384, "SegmentFileName" }, //sd
+ { 0x33a4, "SegmentUID" }, //sd
+ { 0x33c4, "ChapterUID" }, //sd
+ { 0x33c5, "TrackUID" }, //sd
+ { 0x3446, "TrackAttachmentUID" }, //sd
+ { 0x35a1, "BlockAdditions" }, //s
+ { 0x38b5, "Xmp.audio.OutputSampleRate" }, //u
+ { 0x3ba9, "Xmp.video.Title" }, //u
+ { 0x3d7b, "ChannelPositions" }, //sd
+ { 0x3e5b, "SignatureElements" }, //s
+ { 0x3e7b, "SignatureElementList" }, //s
+ { 0x3e8a, "Xmp.video.ContentSignAlgo" }, //u
+ { 0x3e9a, "Xmp.video.ContentSignHashAlgo" }, //u
+ { 0x3ea5, "SignaturePublicKey" }, //sd
+ { 0x3eb5, "Signature" }, //sd
+ { 0x2b59c, "TrackLanguage" }, //ui
+ { 0x3314f, "TrackTimecodeScale" }, //sd
+ { 0x383e3, "Xmp.video.FrameRate" }, //u
+ { 0x3e383, "VideoFrameRate/DefaultDuration" }, //ui
+ { 0x58688, "VideoCodecName/AudioCodecName/CodecName" }, //ui
+ { 0x6b240, "CodecDownloadURL" }, //ui
+ { 0xad7b1, "TimecodeScale" }, //ui
+ { 0xeb524, "ColorSpace" }, //sd
+ { 0xfb523, "Xmp.video.OpColor" }, //u
+ { 0x1a9697, "CodecSettings" }, //ui
+ { 0x1b4040, "CodecInfoURL" }, //ui
+ { 0x1c83ab, "PrevFileName" }, //sd
+ { 0x1cb923, "PrevUID" }, //sd
+ { 0x1e83bb, "NextFileName" }, //sd
+ { 0x1eb923, "NextUID" }, //sd
+ { 0x43a770, "Chapters" }, //sd
+ { 0x14d9b74, "SeekHead" }, //s
+ { 0x254c367, "Tags" }, //s
+ { 0x549a966, "Info" }, //s
+ { 0x654ae6b, "Tracks" }, //s
+ { 0x8538067, "SegmentHeader" }, //s
+ { 0x941a469, "Attachments" }, //s
+ { 0xa45dfa3, "EBMLHeader" }, //s
+ { 0xb538667, "SignatureSlot" }, //s
+ { 0xc53bb6b, "Cues" }, //s
+ { 0xf43b675, "Cluster" }, //s
+};
- extern const MatroskaTags matroskaTrackType[] = {
- { 0x1, "Video" },
- { 0x2, "Audio" },
- { 0x3, "Complex" },
- { 0x10, "Logo" },
- { 0x11, "Subtitle" },
- { 0x12, "Buttons" },
- { 0x20, "Control" }
- };
+//! Multimedia type.
+extern const MatroskaTags matroskaTrackType[] ={
+ { 0x1, "Video" },
+ { 0x2, "Audio" },
+ { 0x3, "Complex" },
+ { 0x10, "Logo" },
+ { 0x11, "Subtitle" },
+ { 0x12, "Buttons" },
+ { 0x20, "Control" }
+};
- extern const MatroskaTags compressionAlgorithm[] = {
- { 0, "zlib " },
- { 1, "bzlib" },
- { 2, "lzo1x" },
- { 3, "Header Stripping" }
- };
+//! Algorith information.
+extern const MatroskaTags compressionAlgorithm[] ={
+ { 0, "zlib " },
+ { 1, "bzlib" },
+ { 2, "lzo1x" },
+ { 3, "Header Stripping" }
+};
- extern const MatroskaTags audioChannels[] = {
- { 1, "Mono" },
- { 2, "Stereo" },
- { 5, "5.1 Surround Sound" },
- { 7, "7.1 Surround Sound" }
- };
+//! Channel Type Information.
+extern const MatroskaTags audioChannels[] ={
+ { 1, "Mono" },
+ { 2, "Stereo" },
+ { 5, "5.1 Surround Sound" },
+ { 7, "7.1 Surround Sound" }
+};
- extern const MatroskaTags displayUnit[] = {
- { 0x0, "Pixels" },
- { 0x1, "cm" },
- { 0x2, "inches" }
- };
+//! Display Information.
+extern const MatroskaTags displayUnit[] ={
+ { 0x0, "Pixels" },
+ { 0x1, "cm" },
+ { 0x2, "inches" }
+};
- extern const MatroskaTags encryptionAlgorithm[] = {
- { 0, "Not Encrypted" },
- { 1, "DES" },
- { 2, "3DES" },
- { 3, "Twofish" },
- { 4, "Blowfish" },
- { 5, "AES" }
- };
+//! Encryption Algorithm.
+extern const MatroskaTags encryptionAlgorithm[] ={
+ { 0, "Not Encrypted" },
+ { 1, "DES" },
+ { 2, "3DES" },
+ { 3, "Twofish" },
+ { 4, "Blowfish" },
+ { 5, "AES" }
+};
- extern const MatroskaTags chapterPhysicalEquivalent[] = {
- { 10, "Index" },
- { 20, "Track" },
- { 30, "Session" },
- { 40, "Layer" },
- { 50, "Side" },
- { 60, "CD / DVD" },
- { 70, "Set / Package" },
- };
+//! Chapter Information.
+extern const MatroskaTags chapterPhysicalEquivalent[] ={
+ { 10, "Index" },
+ { 20, "Track" },
+ { 30, "Session" },
+ { 40, "Layer" },
+ { 50, "Side" },
+ { 60, "CD / DVD" },
+ { 70, "Set / Package" },
+};
- extern const MatroskaTags encodingType[] = {
- { 0, "Compression" },
- { 1, "Encryption" }
- };
+//! Encoding Information.
+extern const MatroskaTags encodingType[] ={
+ { 0, "Compression" },
+ { 1, "Encryption" }
+};
- extern const MatroskaTags videoScanType[] = {
- { 0, "Progressive" },
- { 1, "Interlaced" }
- };
+//! VideoScan Information.
+extern const MatroskaTags videoScanType[] =
+{
+ { 0, "Progressive" },
+ { 1, "Interlaced" }
+};
- extern const MatroskaTags chapterTranslateCodec[] = {
- { 0, "Matroska Script" },
- { 1, "DVD Menu" }
- };
+//! Chapter related Information.
+extern const MatroskaTags chapterTranslateCodec[] ={
+ { 0, "Matroska Script" },
+ { 1, "DVD Menu" }
+};
- extern const MatroskaTags aspectRatioType[] = {
- { 0, "Free Resizing" },
- { 1, "Keep Aspect Ratio" },
- { 2, "Fixed" }
- };
+//! Aspect Ratio Information.
+extern const MatroskaTags aspectRatioType[] ={
+ { 0, "Free Resizing" },
+ { 1, "Keep Aspect Ratio" },
+ { 2, "Fixed" }
+};
- extern const MatroskaTags contentSignatureAlgorithm[] = {
- { 0, "Not Signed" },
- { 1, "RSA" }
- };
+//! Content Signature Information.
+extern const MatroskaTags contentSignatureAlgorithm[] ={
+ { 0, "Not Signed" },
+ { 1, "RSA" }
+};
- extern const MatroskaTags contentSignatureHashAlgorithm[] = {
- { 0, "Not Signed" },
- { 1, "SHA1-160" },
- { 2, "MD5" }
- };
+//! Content SIgnature Hash Information.
+extern const MatroskaTags contentSignatureHashAlgorithm[] ={
+ { 0, "Not Signed" },
+ { 1, "SHA1-160" },
+ { 2, "MD5" }
+};
- extern const MatroskaTags trackEnable[] = {
- { 0x1, "Xmp.video.Enabled" },
- { 0x2, "Xmp.audio.Enabled" },
- { 0x11, "Xmp.video.SubTEnabled" }
- };
+//! Track Information.
+extern const MatroskaTags trackEnable[] ={
+ { 0x1, "Xmp.video.Enabled" },
+ { 0x2, "Xmp.audio.Enabled" },
+ { 0x11, "Xmp.video.SubTEnabled" }
+};
- extern const MatroskaTags defaultOn[] = {
- { 0x1, "Xmp.video.DefaultOn" },
- { 0x2, "Xmp.audio.DefaultOn" },
- { 0x11, "Xmp.video.SubTDefaultOn" }
- };
+//! Default Action Information.
+extern const MatroskaTags defaultOn[] ={
+ { 0x1, "Xmp.video.DefaultOn" },
+ { 0x2, "Xmp.audio.DefaultOn" },
+ { 0x11, "Xmp.video.SubTDefaultOn" }
+};
- extern const MatroskaTags trackForced[] = {
- { 0x1, "Xmp.video.TrackForced" },
- { 0x2, "Xmp.audio.TrackForced" },
- { 0x11, "Xmp.video.SubTTrackForced" }
- };
+//! Track Information.
+extern const MatroskaTags trackForced[] ={
+ { 0x1, "Xmp.video.TrackForced" },
+ { 0x2, "Xmp.audio.TrackForced" },
+ { 0x11, "Xmp.video.SubTTrackForced" }
+};
- extern const MatroskaTags trackLacing[] = {
- { 0x1, "Xmp.video.TrackLacing" },
- { 0x2, "Xmp.audio.TrackLacing" },
- { 0x11, "Xmp.video.SubTTrackLacing" }
- };
+//! Track Information.
+extern const MatroskaTags trackLacing[] ={
+ { 0x1, "Xmp.video.TrackLacing" },
+ { 0x2, "Xmp.audio.TrackLacing" },
+ { 0x11, "Xmp.video.SubTTrackLacing" }
+};
- extern const MatroskaTags codecDecodeAll[] = {
- { 0x1, "Xmp.video.CodecDecodeAll" },
- { 0x2, "Xmp.audio.CodecDecodeAll" },
- { 0x11, "Xmp.video.SubTCodecDecodeAll" }
- };
+//! Codec Information.
+extern const MatroskaTags codecDecodeAll[] ={
+ { 0x1, "Xmp.video.CodecDecodeAll" },
+ { 0x2, "Xmp.audio.CodecDecodeAll" },
+ { 0x11, "Xmp.video.SubTCodecDecodeAll" }
+};
- extern const MatroskaTags codecDownloadUrl[] = {
- { 0x1, "Xmp.video.CodecDownloadUrl" },
- { 0x2, "Xmp.audio.CodecDownloadUrl" },
- { 0x11, "Xmp.video.SubTCodecDownloadUrl" }
- };
+//! Codec Information.
+extern const MatroskaTags codecDownloadUrl[] ={
+ { 0x1, "Xmp.video.CodecDownloadUrl" },
+ { 0x2, "Xmp.audio.CodecDownloadUrl" },
+ { 0x11, "Xmp.video.SubTCodecDownloadUrl" }
+};
- extern const MatroskaTags codecSettings[] = {
- { 0x1, "Xmp.video.CodecSettings" },
- { 0x2, "Xmp.audio.CodecSettings" },
- { 0x11, "Xmp.video.SubTCodecSettings" }
- };
+//! Codec Information.
+extern const MatroskaTags codecSettings[] ={
+ { 0x1, "Xmp.video.CodecSettings" },
+ { 0x2, "Xmp.audio.CodecSettings" },
+ { 0x11, "Xmp.video.SubTCodecSettings" }
+};
- extern const MatroskaTags trackCodec[] = {
- { 0x1, "Xmp.video.Codec" },
- { 0x2, "Xmp.audio.Compressor" },
- { 0x11, "Xmp.video.SubTCodec" }
- };
+//! Track Information.
+extern const MatroskaTags trackCodec[] ={
+ { 0x1, "Xmp.video.Codec" },
+ { 0x2, "Xmp.audio.Compressor" },
+ { 0x11, "Xmp.video.SubTCodec" }
+};
- extern const MatroskaTags trackLanguage[] = {
- { 0x1, "Xmp.video.TrackLang" },
- { 0x2, "Xmp.audio.TrackLang" },
- { 0x11, "Xmp.video.SubTLang" }
- };
+//! Track Language Information.
+extern const MatroskaTags trackLanguage[] ={
+ { 0x1, "Xmp.video.TrackLang" },
+ { 0x2, "Xmp.audio.TrackLang" },
+ { 0x11, "Xmp.video.SubTLang" }
+};
- extern const MatroskaTags codecInfo[] = {
- { 0x1, "Xmp.video.CodecInfo" },
- { 0x2, "Xmp.audio.CodecInfo" },
- { 0x11, "Xmp.video.SubTCodecInfo" }
- };
+//! Codec Information.
+extern const MatroskaTags codecInfo[] ={
+ { 0x1, "Xmp.video.CodecInfo" },
+ { 0x2, "Xmp.audio.CodecInfo" },
+ { 0x11, "Xmp.video.SubTCodecInfo" }
+};
- extern const MatroskaTags streamRate[] = {
- { 0x1, "Xmp.video.FrameRate" },
- { 0x2, "Xmp.audio.DefaultDuration" }
- };
+//! Stream Rate Information.
+extern const MatroskaTags streamRate[] ={
+ { 0x1, "Xmp.video.FrameRate" },
+ { 0x2, "Xmp.audio.DefaultDuration" }
+};
- /*!
+/*!
+ * \brief reverseMatroskaTag reverse the members of a structure
+ * \param inputMatroskaTag
+ * \param outputMatroskaTag
+ * \param size
+ */
+void reverseMatroskaTag(const MatroskaTags inputMatroskaTag[],RevMatroskaTags outputMatroskaTag[] ,int size){
+ for (int64_t i=0; i 0 && size <= 8);
+uint64_t returnTagValue(const Exiv2::byte* buf, int32_t size){
+ assert(size > 0 && size <= 8);
- uint64_t b0 = buf[0] & (0xff >> size);
- uint64_t tag = b0 << ((size - 1) * 8);
- for (long i = 1; i < size; ++i) {
- tag |= static_cast(buf[i]) << ((size - i - 1) * 8);
- }
+ uint64_t b0 = buf[0] & (0xff >> size);
+ uint64_t tag = b0 << ((size - 1) * 8);
+ for (int32_t i = 1; i < size; ++i) tag |= static_cast(buf[i]) << ((size - i - 1) * 8);
+ return tag;
+}
- return tag;
- }
-
- /*!
+/*!
@brief Function used to convert buffer data into numerical information,
information stored in BigEndian format
*/
- int64_t returnValue(const byte* buf, long size)
- {
+int64_t returnValue(const Exiv2::byte* buf, int32_t size){
- int64_t temp = 0;
+ int64_t temp = 0;
+ for(int64_t i = size-1; i >= 0; i--) temp = temp + static_cast(buf[i]*(pow(256.0, (double)size-i-1)));
+ // Todo: remove debug output
+ // std::cerr << "size = " << size << ", val = " << temp << std::hex << " (0x" << temp << std::dec << ")";
- for(int i = size-1; i >= 0; i--) {
- temp = temp + static_cast(buf[i]*(pow(256.0, (double)size-i-1)));
- }
-// Todo: remove debug output
-// std::cerr << "size = " << size << ", val = " << temp << std::hex << " (0x" << temp << std::dec << ")";
+ uint64_t ret = 0;
+ for (int32_t i = 0; i < size; ++i) ret |= static_cast(buf[i]) << ((size - i - 1) * 8);
- uint64_t ret = 0;
- for (long i = 0; i < size; ++i) {
- ret |= static_cast(buf[i]) << ((size - i - 1) * 8);
- }
+ // Todo: remove debug output
+ // std::cerr << ", ret = " << ret << std::hex << " (0x" << ret << std::dec << ")\n";
-// Todo: remove debug output
-// std::cerr << ", ret = " << ret << std::hex << " (0x" << ret << std::dec << ")\n";
+ return ret;
+}
- return ret;
+/*!
+ * \brief returnBuf Return raw byte,ready to be written to the file,from value.
+ * \param numValue
+ * \param size size of rawData in number of bytes.
+ * \return
+ */
+Exiv2::byte* returnBuf(uint64_t numValue,int32_t size)
+{
+ Exiv2::byte* retVal;
+ retVal = (Exiv2::byte* )malloc(size*sizeof(8));
+ for (int32_t i = 0; i < size; i++) {
+ retVal[size-i-1] = (Exiv2::byte)(((uint32_t)numValue)%(uint32_t)256);
+ numValue = numValue/256;
}
+ return retVal;
+} // returnBuf
-}} // namespace Internal, Exiv2
+}
+} // namespace Internal, Exiv2
-namespace Exiv2 {
+namespace Exiv2
+{
- using namespace Exiv2::Internal;
+using namespace Exiv2::Internal;
- MatroskaVideo::MatroskaVideo(BasicIo::AutoPtr io)
- : Image(ImageType::mkv, mdNone, io)
+class MatroskaVideo::Private
+{
+public:
+ Private()
{
- } // MatroskaVideo::MatroskaVideo
-
- std::string MatroskaVideo::mimeType() const
- {
- return "video/matroska";
- }
-
- void MatroskaVideo::writeMetadata()
- {
- }
-
- void MatroskaVideo::readMetadata()
- {
- if (io_->open() != 0) throw Error(9, io_->path(), strError());
-
- // Ensure that this is the correct image type
- if (!isMkvType(*io_, false)) {
- if (io_->error() || io_->eof()) throw Error(14);
- throw Error(3, "Matroska");
- }
-
- IoCloser closer(*io_);
- clearMetadata();
continueTraversing_ = true;
- height_ = width_ = 1;
+ height_ = 1;
+ width_ = 1;
+ m_modifyMetadata = false;
+ mtLocation = 1;
+ }
- xmpData_["Xmp.video.FileName"] = io_->path();
- xmpData_["Xmp.video.FileSize"] = (double)io_->size()/(double)1048576;
- xmpData_["Xmp.video.MimeType"] = mimeType();
+public:
+ //! Variable to check the end of metadata traversing.
+ bool continueTraversing_;
+ //! Variable to store height and width of a video frame.
+ uint64_t height_, width_;
+ //! Variable to decide whether to modify the metada
+ bool m_modifyMetadata;
+ int32_t mtLocation;
+};
- while (continueTraversing_) decodeBlock();
+MatroskaVideo::MatroskaVideo(BasicIo::AutoPtr io)
+ : Image(ImageType::mkv, mdNone, io),d(new Private)
+{
+} // MatroskaVideo::MatroskaVideo
- aspectRatio();
- } // MatroskaVideo::readMetadata
+MatroskaVideo::~MatroskaVideo()
+{
+ delete d;
+}
- void MatroskaVideo::decodeBlock()
- {
- byte buf[8];
- io_->read(buf, 1);
+std::string MatroskaVideo::mimeType() const
+{
+ return "video/matroska";
+}
- if(io_->eof()) {
- continueTraversing_ = false;
- return;
- }
+void MatroskaVideo::writeMetadata()
+{
+ if (io_->open() != 0) throw Error(9, io_->path(), strError());
+ IoCloser closer(*io_);
- uint32_t sz = findBlockSize(buf[0]); // 0-8
- if (sz > 0) io_->read(buf + 1, sz - 1);
+ doWriteMetadata();
- const MatroskaTags* mt = find(matroskaTags, returnTagValue(buf, sz));
+ io_->close();
+}
- if(mt->val_ == 0xc53bb6b || mt->val_ == 0xf43b675) {
- continueTraversing_ = false;
- return;
- }
+void MatroskaVideo::doWriteMetadata()
+{
+ if (!io_->isopen()) throw Error(20);
+ if (!isMkvType(*io_, false)){
+ if (io_->error() || io_->eof()) throw Error(14);
+ throw Error(3, "Matroska");
+ }
+ d->m_modifyMetadata = true;
+ d->continueTraversing_ = true;
+ while (d->continueTraversing_) decodeBlock();
+}
- bool skip = find(compositeTagsList, mt->val_) != 0;
- bool ignore = find(ignoredTagsList, mt->val_) != 0;
+void MatroskaVideo::readMetadata()
+{
+ if (io_->open() != 0) throw Error(9, io_->path(), strError());
- io_->read(buf, 1);
- sz = findBlockSize(buf[0]); // 0-8
+ // Ensure that this is the correct image type
+ if (!isMkvType(*io_, false)){
+ if (io_->error() || io_->eof()) throw Error(14);
+ throw Error(3, "Matroska");
+ }
- if (sz > 0) io_->read(buf + 1, sz - 1);
- uint64_t size = returnTagValue(buf, sz);
+ IoCloser closer(*io_);
+ clearMetadata();
+ d->continueTraversing_ = true;
+ d->height_ = d->width_ = 1;
- if (skip && !ignore) return;
+ xmpData_["Xmp.video.FileName"] = io_->path();
+ xmpData_["Xmp.video.FileSize"] = (double)io_->size()/(double)1048576;
+ xmpData_["Xmp.video.MimeType"] = mimeType();
- const uint64_t bufMinSize = 200;
+ while (d->continueTraversing_) decodeBlock();
+
+ aspectRatio();
+} // MatroskaVideo::readMetadata
+
+void MatroskaVideo::decodeBlock()
+{
+ Exiv2::byte buf[8];
+ d->mtLocation = io_->tell();
+ io_->read(buf, 1);
+
+ if(io_->eof()){
+ d->continueTraversing_ = false;
+ return;
+ }
+
+ uint32_t sz = findBlockSize(buf[0]); // 0-8
+ if (sz > 0) io_->read(buf + 1, sz - 1);
+
+
+ const MatroskaTags* mt = find(matroskaTags, returnTagValue(buf, sz));
+
+ if(mt->val_ == 0xc53bb6b || mt->val_ == 0xf43b675){
+ d->continueTraversing_ = false;
+ return;
+ }
+
+ bool skip = find(compositeTagsList, mt->val_) != 0;
+ bool ignore = find(ignoredTagsList, mt->val_) != 0;
+
+ io_->read(buf, 1);
+ sz = findBlockSize(buf[0]); // 0-8
+
+ if (sz > 0) io_->read(buf + 1, sz - 1);
+ uint64_t size = returnTagValue(buf, sz);
+
+ if (skip && !ignore) return;
+
+ const uint64_t bufMinSize = 200;
#ifndef SUPPRESS_WARNINGS
- if (!ignore && size > bufMinSize) {
- EXV_WARNING << "Size " << size << " of Matroska tag 0x"
- << std::hex << mt->val_ << std::dec
- << " is greater than " << bufMinSize << ": ignoring it.\n";
- }
+ if (!ignore && size > bufMinSize){
+ EXV_WARNING << "Size " << size << " of Matroska tag 0x"
+ << std::hex << mt->val_ << std::dec
+ << " is greater than " << bufMinSize << ": ignoring it.\n";
+ }
#endif
- if (ignore || size > bufMinSize) {
- io_->seek(size, BasicIo::cur);
- return;
+ if (ignore || size > bufMinSize){
+ io_->seek(size, BasicIo::cur);
+ return;
+ }
+
+ DataBuf buf2(bufMinSize+1);
+ int32_t s = static_cast(size) ;
+ io_->read(buf2.pData_,s);
+ contentManagement(mt, buf2.pData_,s);
+} // MatroskaVideo::decodeBlock
+
+void MatroskaVideo::contentManagement(const MatroskaTags* mt, const Exiv2::byte* buf, int32_t size)
+{
+ int64_t duration_in_ms = 0;
+ static double time_code_scale = 1.0, temp = 0;
+ static int32_t stream = 0, track_count = 0;
+ char str[4] = "No";
+ const RevMatroskaTags* rtd = 0;
+ const MatroskaTags* internalMt = 0;
+ const RevMatroskaTags* revTagStructure = 0;
+
+ if(d->m_modifyMetadata){
+ }
+ switch (mt->val_) {
+
+ case 0x0282: case 0x0d80: case 0x1741: case 0x3ba9: case 0x066e: case 0x0660:
+ case 0x065c: case 0x067e: case 0x047a: case 0x0487: case 0x05a3: case 0x136e:
+ case 0x23ca: case 0xeb524:
+ if(!d->m_modifyMetadata) xmpData_[mt->label_] = buf;
+ else{
+ if(xmpData_[mt->label_].count() > 0){
+ Exiv2::byte* rawTagData = new byte[size];
+ std::string tagData = xmpData_[mt->label_].toString();
+ for(int32_t i=0; i (int32_t) tagData.size())
+ for(int32_t i=(int32_t) tagData.size(); iseek(-size,BasicIo::cur);
+ io_->write(rawTagData,size);
+ delete[] rawTagData;
+ }
}
+ break;
- DataBuf buf2(bufMinSize+1);
- std::memset(buf2.pData_, 0x0, buf2.size_);
- long s = static_cast(size) ;
- io_->read(buf2.pData_,s);
- contentManagement(mt, buf2.pData_,s);
- } // MatroskaVideo::decodeBlock
-
- void MatroskaVideo::contentManagement(const MatroskaTags* mt, const byte* buf, long size)
- {
- int64_t duration_in_ms = 0;
- static double time_code_scale = 1.0, temp = 0;
- static long stream = 0, track_count = 0;
- char str[4] = "No";
- const MatroskaTags* internalMt = 0;
-
- switch (mt->val_) {
-
- case 0x0282: case 0x0d80: case 0x1741: case 0x3ba9: case 0x066e: case 0x0660:
- case 0x065c: case 0x067e: case 0x047a: case 0x0487: case 0x05a3: case 0x136e:
- case 0x23ca: case 0xeb524:
- xmpData_[mt->label_] = buf;
- break;
-
- case 0x0030: case 0x003a: case 0x0287: case 0x14b0: case 0x14ba: case 0x285:
- case 0x06ae: case 0x0286: case 0x02f7: case 0x2264: case 0x14aa: case 0x14bb:
- case 0x14cc: case 0x14dd:
- xmpData_[mt->label_] = returnValue(buf, size);
-
- if (mt->val_ == 0x0030 || mt->val_ == 0x14b0) {
- width_ = returnValue(buf, size);
+ case 0x0030: case 0x003a: case 0x0287: case 0x14b0: case 0x14ba: case 0x285:
+ case 0x06ae: case 0x0286: case 0x02f7: case 0x2264: case 0x14aa: case 0x14bb:
+ case 0x14cc: case 0x14dd:
+ if(!d->m_modifyMetadata) xmpData_[mt->label_] = returnValue(buf, size);
+ else{
+ if(xmpData_[mt->label_].count() > 0){
+ Exiv2::byte* rawTagData = returnBuf((uint64_t)xmpData_[mt->label_].toFloat(),size);
+ io_->seek(-size,BasicIo::cur);
+ io_->write(rawTagData,size);
+ free(rawTagData);
}
- else if (mt->val_ == 0x003a || mt->val_ == 0x14ba) {
- height_ = returnValue(buf, size);
- }
- break;
+ }
+ if (mt->val_ == 0x0030 || mt->val_ == 0x14b0) d->width_ = returnValue(buf, size);
+ else if (mt->val_ == 0x003a || mt->val_ == 0x14ba) d->height_ = returnValue(buf, size);
+ break;
- case 0x001a: case 0x001f: case 0x0254: case 0x07e1: case 0x07e5: case 0x07e6:
- case 0x1033: case 0x14b2: case 0x14b3: case 0x23c3: case 0x29bf: case 0x3e8a:
+ case 0x001a: case 0x001f: case 0x0254: case 0x07e1: case 0x07e5: case 0x07e6:
+ case 0x1033: case 0x14b2: case 0x14b3: case 0x23c3: case 0x29bf: case 0x3e8a:
+ case 0x3e9a:
+ switch (mt->val_){
+ case 0x001a: internalMt = find(videoScanType, returnValue(buf, size)); break;
+ case 0x001f: internalMt = find(audioChannels, returnValue(buf, size)); break;
+ case 0x0254: internalMt = find(compressionAlgorithm, returnValue(buf, size)); break;
+ case 0x07e1: internalMt = find(encryptionAlgorithm, returnValue(buf, size)); break;
+ case 0x1033: internalMt = find(encodingType, returnValue(buf, size)); break;
+ case 0x3e8a:
+ case 0x07e5: internalMt = find(contentSignatureAlgorithm, returnValue(buf, size)); break;
case 0x3e9a:
- switch (mt->val_) {
- case 0x001a: internalMt = find(videoScanType, returnValue(buf, size)); break;
- case 0x001f: internalMt = find(audioChannels, returnValue(buf, size)); break;
- case 0x0254: internalMt = find(compressionAlgorithm, returnValue(buf, size)); break;
- case 0x07e1: internalMt = find(encryptionAlgorithm, returnValue(buf, size)); break;
- case 0x1033: internalMt = find(encodingType, returnValue(buf, size)); break;
- case 0x3e8a:
- case 0x07e5: internalMt = find(contentSignatureAlgorithm, returnValue(buf, size)); break;
- case 0x3e9a:
- case 0x07e6: internalMt = find(contentSignatureHashAlgorithm, returnValue(buf, size)); break;
- case 0x14b2: internalMt = find(displayUnit, returnValue(buf, size)); break;
- case 0x14b3: internalMt = find(aspectRatioType, returnValue(buf, size)); break;
- case 0x23c3: internalMt = find(chapterPhysicalEquivalent, returnValue(buf, size)); break;
- case 0x29bf: internalMt = find(chapterTranslateCodec, returnValue(buf, size)); break;
+ case 0x07e6: internalMt = find(contentSignatureHashAlgorithm, returnValue(buf, size)); break;
+ case 0x14b2: internalMt = find(displayUnit, returnValue(buf, size)); break;
+ case 0x14b3: internalMt = find(aspectRatioType, returnValue(buf, size)); break;
+ case 0x23c3: internalMt = find(chapterPhysicalEquivalent, returnValue(buf, size)); break;
+ case 0x29bf: internalMt = find(chapterTranslateCodec, returnValue(buf, size)); break;
+ }
+ if(!d->m_modifyMetadata) if (internalMt) xmpData_[mt->label_] = internalMt->label_;
+ else if(internalMt){
+ if(xmpData_[mt->label_].count() >0){
+ const int32_t videoTagSize = lengthof(videoScanType);
+ const int32_t audioTagSize = lengthof(audioChannels);
+ const int32_t compressionTagSize = lengthof(compressionAlgorithm);
+ const int32_t encryptionTagSize = lengthof(encryptionAlgorithm);
+ const int32_t encodingTagSize = lengthof(encodingType);
+ const int32_t contentTagSize = lengthof(contentSignatureAlgorithm);
+ const int32_t contentHashTagSize = lengthof(contentSignatureHashAlgorithm);
+ const int32_t displayTagSize = lengthof(displayUnit);
+ const int32_t aspectTagSize = lengthof(aspectRatioType);
+ const int32_t physicalTagSize = lengthof(chapterPhysicalEquivalent);
+ const int32_t translateTagSize = lengthof(chapterTranslateCodec);
+
+ switch (mt->val_){
+ case 0x001a:
+ RevMatroskaTags revVidStructure[videoTagSize];
+ reverseMatroskaTag(videoScanType,revVidStructure,videoTagSize);
+ rtd = find(revVidStructure,xmpData_[mt->label_].toString());
+ writeMatroskaKey(rtd,size);break;
+ case 0x001f:
+ RevMatroskaTags revAudStructure[audioTagSize];
+ reverseMatroskaTag(audioChannels,revAudStructure,audioTagSize);
+ rtd = find(revAudStructure,xmpData_[mt->label_].toString());
+ writeMatroskaKey(rtd,size);break;
+ case 0x0254:
+ RevMatroskaTags revComStructure[compressionTagSize];
+ reverseMatroskaTag(compressionAlgorithm,revComStructure,compressionTagSize);
+ rtd = find(revComStructure,xmpData_[mt->label_].toString());
+ writeMatroskaKey(rtd,size);break;
+ case 0x07e1:
+ RevMatroskaTags revEnrStructure[encryptionTagSize];
+ reverseMatroskaTag(encryptionAlgorithm,revEnrStructure,encryptionTagSize);
+ rtd = find(revEnrStructure,xmpData_[mt->label_].toString());
+ writeMatroskaKey(rtd,size);break;
+ case 0x1033:
+ RevMatroskaTags revEncStructure[encodingTagSize];
+ reverseMatroskaTag(encodingType,revEncStructure,encodingTagSize);
+ rtd = find(revEncStructure,xmpData_[mt->label_].toString());
+ writeMatroskaKey(rtd,size);break;
+ case 0x07e5:
+ RevMatroskaTags revConStructure[contentTagSize];
+ reverseMatroskaTag(contentSignatureAlgorithm,revConStructure,contentTagSize);
+ rtd = find(revConStructure,xmpData_[mt->label_].toString());
+ writeMatroskaKey(rtd,size);break;
+ case 0x07e6:
+ RevMatroskaTags revHasStructure[contentHashTagSize];
+ reverseMatroskaTag(contentSignatureHashAlgorithm,revHasStructure,contentHashTagSize);
+ rtd = find(revHasStructure,xmpData_[mt->label_].toString());
+ writeMatroskaKey(rtd,size);break;
+ case 0x14b2:
+ RevMatroskaTags revDisStructure[displayTagSize];
+ reverseMatroskaTag(displayUnit,revDisStructure,displayTagSize);
+ rtd = find(revDisStructure,xmpData_[mt->label_].toString());
+ writeMatroskaKey(rtd,size);break;
+ case 0x14b3:
+ RevMatroskaTags revAspStructure[aspectTagSize];
+ reverseMatroskaTag(aspectRatioType,revAspStructure,aspectTagSize);
+ rtd = find(revAspStructure,xmpData_[mt->label_].toString());
+ writeMatroskaKey(rtd,size);break;
+ case 0x23c3:
+ RevMatroskaTags revPhyStructure[physicalTagSize];
+ reverseMatroskaTag(chapterPhysicalEquivalent,revPhyStructure,physicalTagSize);
+ rtd = find(revPhyStructure,xmpData_[mt->label_].toString());
+ writeMatroskaKey(rtd,size);break;
+ case 0x29bf:
+ RevMatroskaTags revTraStructure[translateTagSize];
+ reverseMatroskaTag(chapterTranslateCodec,revTraStructure,translateTagSize);
+ rtd = find(revTraStructure,xmpData_[mt->label_].toString());
+ writeMatroskaKey(rtd,size);break;
+ }
}
- if (internalMt) xmpData_[mt->label_] = internalMt->label_;
- break;
-
- case 0x0035: case 0x38b5:
- xmpData_[mt->label_] = getFloat(buf, bigEndian);
- break;
-
- case 0x0039: case 0x0008: case 0x15aa: case 0x001c: case 0x002a: case 0x1a9697:
- case 0x0484:
- if (returnValue(buf, size)) strcpy(str, "Yes");
- switch (mt->val_) {
- case 0x0039: internalMt = find(trackEnable, stream); break;
- case 0x0008: internalMt = find(defaultOn, stream); break;
- case 0x15aa: internalMt = find(trackForced, stream); break;
- case 0x001c: internalMt = find(trackLacing, stream); break;
- case 0x002a: internalMt = find(codecDecodeAll, stream); break;
- case 0x1a9697: internalMt = find(codecSettings, stream); break;
- case 0x0484: internalMt = mt; break;
+ }
+ break;
+ case 0x0035: case 0x38b5:
+ if(!d->m_modifyMetadata) xmpData_[mt->label_] = getFloat(buf, bigEndian);
+ else if(xmpData_[mt->label_].count() > 0){
+ Exiv2::byte *rawFloatValue = new byte[size];
+ float floatValue = xmpData_[mt->label_].toFloat();
+ memcpy(rawFloatValue,&floatValue,sizeof(float));
+ // io_->seek(-size,BasicIo::cur);//Tobe tested
+ // io_->write(rawFloatValue,size);
}
- if (internalMt) xmpData_[internalMt->label_] = str;
- break;
+ break;
- case 0x0006: case 0x2b59c: case 0x58688: case 0x6b240: case 0x1b4040:
- switch (mt->val_) {
- case 0x0006: internalMt = find(trackCodec, stream); break;
- case 0x2b59c: internalMt = find(trackLanguage, stream); break;
- case 0x58688: internalMt = find(codecInfo, stream); break;
- case 0x6b240:
- case 0x1b4040: internalMt = find(codecDownloadUrl, stream); break;
- }
- if (internalMt) xmpData_[internalMt->label_] = buf;
- break;
+ case 0x0039: case 0x0008: case 0x15aa: case 0x001c: case 0x002a: case 0x1a9697:
+ case 0x0484:
+ if (returnValue(buf, size)) strcpy(str, "Yes");
+ switch (mt->val_){
+ case 0x0039: internalMt = find(trackEnable, stream); break;
+ case 0x0008: internalMt = find(defaultOn, stream); break;
+ case 0x15aa: internalMt = find(trackForced, stream); break;
+ case 0x001c: internalMt = find(trackLacing, stream); break;
+ case 0x002a: internalMt = find(codecDecodeAll, stream); break;
+ case 0x1a9697: internalMt = find(codecSettings, stream); break;
+ case 0x0484: internalMt = mt; break;
+ }
+ if (internalMt) xmpData_[internalMt->label_] = str;
+ break;
- case 0x0489: case 0x0461:
- switch (mt->val_) {
+ case 0x0006: case 0x2b59c: case 0x58688: case 0x6b240: case 0x1b4040:
+ switch (mt->val_){
+ case 0x0006: internalMt = find(trackCodec, stream); break;
+ case 0x2b59c: internalMt = find(trackLanguage, stream); break;
+ case 0x58688: internalMt = find(codecInfo, stream); break;
+ case 0x6b240:
+ case 0x1b4040: internalMt = find(codecDownloadUrl, stream); break;
+ }
+ if (internalMt) xmpData_[internalMt->label_] = buf;
+ break;
+
+ case 0x0489: case 0x0461:
+ if(!d->m_modifyMetadata){
+ switch (mt->val_){
case 0x0489:
- if(size <= 4) {
- duration_in_ms = static_cast(getFloat(buf, bigEndian) * time_code_scale * 1000);
- }
- else {
- duration_in_ms = static_cast(getDouble(buf, bigEndian) * time_code_scale * 1000);
- }
+ if(size <= 4) duration_in_ms = static_cast(getFloat(buf, bigEndian) * time_code_scale * 1000);
+ else duration_in_ms = static_cast(getDouble(buf, bigEndian) * time_code_scale * 1000);
break;
- case 0x0461: {
- duration_in_ms = returnValue(buf, size)/1000000000; break;
- }
+ case 0x0461: duration_in_ms = returnValue(buf, size)/1000000000; break;
}
xmpData_[mt->label_] = duration_in_ms;
- break;
+ }
+ else{
+ Exiv2::byte *rawDuration;
+ switch (mt->val_){
+ case 0x0489:
+ rawDuration = returnBuf( (uint64_t) (xmpData_[mt->label_].toFloat() /(time_code_scale*1000.0)),size);
+ io_->seek(-size,BasicIo::cur);
+ io_->write(rawDuration,size);
+ break;
+ case 0x0461:
+ rawDuration = returnBuf( (uint64_t) (xmpData_[mt->label_].toFloat() / 1000000000.0),size);
+ io_->seek(-size,BasicIo::cur);
+ io_->write(rawDuration,size);
+ break;
+ }
+ free(rawDuration);
+ }
+ break;
- case 0x0057:
- track_count++;
- xmpData_["Xmp.video.TotalStream"] = track_count;
- break;
+ case 0x0057:
+ track_count++;
+ xmpData_["Xmp.video.TotalStream"] = track_count;
+ break;
- case 0xad7b1:
+ case 0xad7b1:
+ if(!d->m_modifyMetadata){
time_code_scale = (double)returnValue(buf, size)/(double)1000000000;
xmpData_["Xmp.video.TimecodeScale"] = time_code_scale;
- break;
+ }
+ else{
+ Exiv2::byte *rawTimeCodeScale = returnBuf((uint64_t)(xmpData_["Xmp.video.TimecodeScale"]
+ .toFloat()*1000000000),size);
+ io_->seek(size,BasicIo::cur);
+ io_->write(rawTimeCodeScale,size);
+ free(rawTimeCodeScale);
+ }
+ break;
- case 0x0003:
- internalMt = find(matroskaTrackType, returnValue(buf, size));
- stream = static_cast(internalMt->val_);
- break;
+ case 0x0003:
+ internalMt = find(matroskaTrackType, returnValue(buf, size));
+ stream = static_cast(internalMt->val_);
+ break;
- case 0x3e383: case 0x383e3:
- internalMt = find(streamRate, stream);
- if (returnValue(buf, size)) {
- switch (stream) {
- case 1: temp = (double)1000000000/(double)returnValue(buf, size); break;
- case 2: temp = static_cast(returnValue(buf, size) / 1000); break;
- }
- if (internalMt) xmpData_[internalMt->label_] = temp;
+ case 0x3e383: case 0x383e3:
+ internalMt = find(streamRate, stream);
+ if (returnValue(buf, size)){
+ switch (stream)
+ {
+ case 1: temp = (double)1000000000/(double)returnValue(buf, size); break;
+ case 2: temp = static_cast(returnValue(buf, size) / 1000); break;
}
- else
- if (internalMt) xmpData_[internalMt->label_] = "Variable Bit Rate";
- break;
-
- default:
- break;
+ if (internalMt) xmpData_[internalMt->label_] = temp;
}
- } // MatroskaVideo::contentManagement
+ else if (internalMt) xmpData_[internalMt->label_] = "Variable Bit Rate"; break;
- void MatroskaVideo::aspectRatio()
- {
- //TODO - Make a better unified method to handle all cases of Aspect Ratio
-
- double aspectRatio = (double)width_ / (double)height_;
- aspectRatio = floor(aspectRatio*10) / 10;
- xmpData_["Xmp.video.AspectRatio"] = aspectRatio;
-
- int aR = (int) ((aspectRatio*10.0)+0.1);
-
- switch (aR) {
- case 13 : xmpData_["Xmp.video.AspectRatio"] = "4:3" ; break;
- case 17 : xmpData_["Xmp.video.AspectRatio"] = "16:9" ; break;
- case 10 : xmpData_["Xmp.video.AspectRatio"] = "1:1" ; break;
- case 16 : xmpData_["Xmp.video.AspectRatio"] = "16:10" ; break;
- case 22 : xmpData_["Xmp.video.AspectRatio"] = "2.21:1" ; break;
- case 23 : xmpData_["Xmp.video.AspectRatio"] = "2.35:1" ; break;
- case 12 : xmpData_["Xmp.video.AspectRatio"] = "5:4" ; break;
- default : xmpData_["Xmp.video.AspectRatio"] = aspectRatio;break;
- }
- } // MatroskaVideo::aspectRatio
-
- uint32_t MatroskaVideo::findBlockSize(byte b)
- {
- if (b & 128) return 1;
- else if (b & 64) return 2;
- else if (b & 32) return 3;
- else if (b & 16) return 4;
- else if (b & 8) return 5;
- else if (b & 4) return 6;
- else if (b & 2) return 7;
- else if (b & 1) return 8;
- else return 0;
- } // MatroskaVideo::findBlockSize
-
- Image::AutoPtr newMkvInstance(BasicIo::AutoPtr io, bool /*create*/)
- {
- Image::AutoPtr image(new MatroskaVideo(io));
- if (!image->good()) {
- image.reset();
- }
- return image;
+ default: break;
}
+} // MatroskaVideo::contentManagement
- bool isMkvType(BasicIo& iIo, bool advance)
- {
- bool result = true;
- byte tmpBuf[4];
- iIo.read(tmpBuf, 4);
+void MatroskaVideo::aspectRatio()
+{
+ //TODO - Make a better unified method to handle all cases of Aspect Ratio
- if (iIo.error() || iIo.eof()) return false;
+ double aspectRatio = (double)d->width_ / (double)d->height_;
+ aspectRatio = floor(aspectRatio*10) / 10;
+ xmpData_["Xmp.video.AspectRatio"] = aspectRatio;
- if (0x1a != tmpBuf[0] || 0x45 != tmpBuf[1] || 0xdf != tmpBuf[2] || 0xa3 != tmpBuf[3]) {
- result = false;
- }
+ int aR = (int) ((aspectRatio*10.0)+0.1);
- if (!advance || !result ) iIo.seek(0, BasicIo::beg);
- return result;
+ switch (aR) {
+ case 13 : xmpData_["Xmp.video.AspectRatio"] = "4:3" ; break;
+ case 17 : xmpData_["Xmp.video.AspectRatio"] = "16:9" ; break;
+ case 10 : xmpData_["Xmp.video.AspectRatio"] = "1:1" ; break;
+ case 16 : xmpData_["Xmp.video.AspectRatio"] = "16:10" ; break;
+ case 22 : xmpData_["Xmp.video.AspectRatio"] = "2.21:1" ; break;
+ case 23 : xmpData_["Xmp.video.AspectRatio"] = "2.35:1" ; break;
+ case 12 : xmpData_["Xmp.video.AspectRatio"] = "5:4" ; break;
+ default : xmpData_["Xmp.video.AspectRatio"] = aspectRatio;break;
}
+} // MatroskaVideo::aspectRatio
+
+uint32_t MatroskaVideo::findBlockSize(Exiv2::byte b)
+{
+ if (b & 128) return 1;
+ else if (b & 64) return 2;
+ else if (b & 32) return 3;
+ else if (b & 16) return 4;
+ else if (b & 8) return 5;
+ else if (b & 4) return 6;
+ else if (b & 2) return 7;
+ else if (b & 1) return 8;
+ else return 0;
+} // MatroskaVideo::findBlockSize
+
+Image::AutoPtr newMkvInstance(BasicIo::AutoPtr io, bool /*create*/)
+{
+ Image::AutoPtr image(new MatroskaVideo(io));
+ if (!image->good()) image.reset();
+ return image;
+}
+
+void MatroskaVideo::writeStringData(Exiv2::Xmpdatum xmpStringData, int32_t size, int32_t skipOffset)
+{
+ if(xmpStringData.count() > 0){
+ std::string dataString = xmpStringData.toString();
+ Exiv2::byte* rawData = new byte[(uint8_t)size];
+ int32_t newSize = (int32_t)dataString.size();
+ for(int32_t i=0; i newSize)
+ for(int32_t i=newSize; iwrite(rawData,size);
+ io_->seek((int)skipOffset,BasicIo::cur);
+ delete[] rawData;
+ }
+ else io_->seek((size+skipOffset),BasicIo::cur);
+}
+
+void MatroskaVideo::writeMatroskaKey(const RevMatroskaTags* revInternalMt,int32_t size)
+{
+ if(revInternalMt){
+ Exiv2::byte* rawMatroskaKey = returnBuf(revInternalMt->val_,size);
+ io_->seek(-size,BasicIo::cur);
+ io_->write(rawMatroskaKey,size);
+ free(rawMatroskaKey);
+ }
+}
+
+bool isMkvType(BasicIo& iIo, bool advance)
+{
+ bool result = true;
+ Exiv2::byte tmpBuf[4];
+ iIo.read(tmpBuf, 4);
+
+ if (iIo.error() || iIo.eof()) return false;
+
+ if (0x1a != tmpBuf[0] || 0x45 != tmpBuf[1] || 0xdf != tmpBuf[2] || 0xa3 != tmpBuf[3]) result = false;
+
+ if (!advance || !result ) iIo.seek(0, BasicIo::beg);
+ return result;
+}
} // namespace Exiv2
diff --git a/src/matroskavideo.hpp b/src/matroskavideo.hpp
index a86fb0c5..43827f61 100644
--- a/src/matroskavideo.hpp
+++ b/src/matroskavideo.hpp
@@ -37,36 +37,51 @@
// *****************************************************************************
// namespace extensions
-namespace Exiv2 {
+namespace Exiv2
+{
// *****************************************************************************
// class definitions
- // Add MKV to the supported image formats
- namespace ImageType {
- const int mkv = 21; //!< Treating mkv as an image type>
- }
+// Add MKV to the supported image formats
+namespace ImageType
+{
+const int mkv = 21; //!< Treating mkv as an image type>
+}
- // Todo: Should be hidden
- /*!
+// Todo: Should be hidden
+/*!
@brief Helper structure for the Matroska tags lookup table.
*/
- struct MatroskaTags {
- uint64_t val_; //!< Tag value
- const char* label_; //!< Translation of the tag value
+struct MatroskaTags
+{
+ uint64_t val_; //!< Tag value
+ const char* label_; //!< Translation of the tag value
- //! Comparison operator for use with the find template
- bool operator==(uint64_t key) const { return val_ == key; }
- }; // struct TagDetails
+ //! Comparison operator for use with the find template
+ bool operator==(uint64_t key) const { return val_ == key; }
+}; // struct TagDetails
- /*!
+/*!
+ * \brief The RevMatroskaTags struct reverse the matroskatag structure.
+ */
+struct RevMatroskaTags
+{
+ const char* label_; //!< Translation of the tag value
+ uint64_t val_; //!< Tag value
+
+ //! Comparison operator for use with the find template
+ bool operator==(const std::string& key) const{return label_ == key;}
+};
+/*!
@brief Class to access Matroska video files.
*/
- class EXIV2API MatroskaVideo : public Image {
- public:
- //! @name Creators
- //@{
- /*!
+class EXIV2API MatroskaVideo : public Image
+{
+public:
+ //! @name Creators
+ //@{
+ /*!
@brief Constructor for a Matroska video. Since the constructor
can not return a result, callers should check the good() method
after object construction to determine success or failure.
@@ -77,22 +92,22 @@ namespace Exiv2 {
instance after it is passed to this method. Use the Image::io()
method to get a temporary reference.
*/
- MatroskaVideo(BasicIo::AutoPtr io);
- //@}
+ MatroskaVideo(BasicIo::AutoPtr io);
+ //@}
- //! @name Manipulators
- //@{
- void readMetadata();
- void writeMetadata();
- //@}
+ //! @name Manipulators
+ //@{
+ void readMetadata();
+ void writeMetadata();
+ //@}
- //! @name Accessors
- //@{
- std::string mimeType() const;
- //@}
+ //! @name Accessors
+ //@{
+ std::string mimeType() const;
+ //@}
- protected:
- /*!
+protected:
+ /*!
@brief Function used to calulate the size of a block.
This information is only stored in one byte.
The size of the block is calculated by counting
@@ -101,56 +116,79 @@ namespace Exiv2 {
@param b The byte, which stores the information to calculate the size
@return Return the size of the block.
*/
- uint32_t findBlockSize(byte b);
- /*!
+ uint32_t findBlockSize(byte b);
+ /*!
@brief Check for a valid tag and decode the block at the current IO position.
Calls contentManagement() or skips to next tag, if required.
*/
- void decodeBlock();
- /*!
+ void decodeBlock();
+ /*!
@brief Interpret tag information, and save it in the respective XMP container.
@param mt Pointer to current tag,
@param buf Pointer to the memory area with the tag information.
@param size Size of \em buf.
*/
- void contentManagement(const MatroskaTags* mt, const byte* buf, long size);
- /*!
+ void contentManagement(const MatroskaTags* mt, const Exiv2::byte* buf, int32_t size);
+ /*!
@brief Calculates Aspect Ratio of a video, and stores it in the
respective XMP container.
*/
- void aspectRatio();
+ void aspectRatio();
- private:
- //! @name NOT Implemented
- //@{
- //! Copy constructor
- MatroskaVideo(const MatroskaVideo& rhs);
- //! Assignment operator
- MatroskaVideo& operator=(const MatroskaVideo& rhs);
- //@}
+private:
+ //! @name NOT Implemented
+ //@{
+ //! Copy constructor
+ MatroskaVideo(const MatroskaVideo& rhs);
+ //! Assignment operator
+ MatroskaVideo& operator=(const MatroskaVideo& rhs);
+ ~MatroskaVideo();
+ //@}
+ /*!
+ @brief Provides the main implementation of writeMetadata() by
+ writing all buffered metadata to the provided BasicIo.
+ @param oIo BasicIo instance to write to (a temporary location).
- private:
- //! Variable to check the end of metadata traversing.
- bool continueTraversing_;
- //! Variable to store height and width of a video frame.
- uint64_t height_, width_;
+ @return 4 if opening or writing to the associated BasicIo fails
+ */
+ EXV_DLLLOCAL void doWriteMetadata();
- }; // class MatroskaVideo
+ /*!
+ * \brief writeStringData
+ * \param xmpStringData
+ * \param size
+ * \param skipOffset
+ */
+ void writeStringData(Exiv2::Xmpdatum xmpStringData, int32_t size, int32_t skipOffset=0);
+
+ /*!
+ * \brief writeMatroskaKey
+ * \param inputStruct
+ * \param size
+ */
+ void writeMatroskaKey(const RevMatroskaTags *revInternalMt, int32_t size);
+
+private:
+
+ class Private;
+ Private * const d;
+
+}; // class MatroskaVideo
// *****************************************************************************
// template, inline and free functions
- // These could be static private functions on Image subclasses but then
- // ImageFactory needs to be made a friend.
- /*!
+// These could be static private functions on Image subclasses but then
+// ImageFactory needs to be made a friend.
+/*!
@brief Create a new MatroskaVideo instance and return an auto-pointer to it.
Caller owns the returned object and the auto-pointer ensures that
it will be deleted.
*/
- EXIV2API Image::AutoPtr newMkvInstance(BasicIo::AutoPtr io, bool create);
+EXIV2API Image::AutoPtr newMkvInstance(BasicIo::AutoPtr io, bool create);
- //! Check if the file iIo is a Matroska Video.
- EXIV2API bool isMkvType(BasicIo& iIo, bool advance);
+//! Check if the file iIo is a Matroska Video.
+EXIV2API bool isMkvType(BasicIo& iIo, bool advance);
} // namespace Exiv2
diff --git a/src/quicktimevideo.cpp b/src/quicktimevideo.cpp
index 7878314c..9fc17849 100644
--- a/src/quicktimevideo.cpp
+++ b/src/quicktimevideo.cpp
@@ -11,7 +11,7 @@
*
* 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
+ * 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
@@ -19,11 +19,12 @@
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
*/
/*
- File: quicktimevideo.cpp
- Version: $Rev$
+ File: quicktimevideo.cpp
+ Version: $Rev$
Author(s): Abhinav Badola for GSoC 2012 (AB)
- History: 28-Jun-12, AB: created
- Credits: See header file
+ Mahesh Hegde for GSoC 2013
+ History: 28-Jun-12, AB: created
+ Credits: See header file
*/
// *****************************************************************************
#include "rcsid_int.hpp"
@@ -35,924 +36,1599 @@ EXIV2_RCSID("@(#) $Id$")
#include "futils.hpp"
#include "basicio.hpp"
#include "tags.hpp"
+#include "utilsvideo.hpp"
+
// + standard includes
#include
+#include
+
+#ifndef _MSC_VER
+#define stricmp strcasecmp
+#endif
+
+typedef void (Exiv2::QuickTimeVideo::*decFunc)(uint32_t);
// *****************************************************************************
// class member definitions
-namespace Exiv2 {
- namespace Internal {
+namespace Exiv2{
+namespace Internal{
- extern const TagVocabulary qTimeFileType[] = {
- { "3g2a", "3GPP2 Media (.3G2) compliant with 3GPP2 C.S0050-0 V1.0" },
- { "3g2b", "3GPP2 Media (.3G2) compliant with 3GPP2 C.S0050-A V1.0.0" },
- { "3g2c", "3GPP2 Media (.3G2) compliant with 3GPP2 C.S0050-B v1.0" },
- { "3ge6", "3GPP (.3GP) Release 6 MBMS Extended Presentations" },
- { "3ge7", "3GPP (.3GP) Release 7 MBMS Extended Presentations" },
- { "3gg6", "3GPP Release 6 General Profile" },
- { "3gp1", "3GPP Media (.3GP) Release 1 (probably non-existent)" },
- { "3gp2", "3GPP Media (.3GP) Release 2 (probably non-existent)" },
- { "3gp3", "3GPP Media (.3GP) Release 3 (probably non-existent)" },
- { "3gp4", "3GPP Media (.3GP) Release 4" },
- { "3gp5", "3GPP Media (.3GP) Release 5" },
- { "3gp6", "3GPP Media (.3GP) Release 6 Streaming Servers" },
- { "3gs7", "3GPP Media (.3GP) Release 7 Streaming Servers" },
- { "CAEP", "Canon Digital Camera" },
- { "CDes", "Convergent Design" },
- { "F4A ", "Audio for Adobe Flash Player 9+ (.F4A)" },
- { "F4B ", "Audio Book for Adobe Flash Player 9+ (.F4B)" },
- { "F4P ", "Protected Video for Adobe Flash Player 9+ (.F4P)" },
- { "F4V ", "Video for Adobe Flash Player 9+ (.F4V)" },
- { "JP2 ", "JPEG 2000 Image (.JP2) [ISO 15444-1 ?]" },
- { "JP20", "Unknown, from GPAC samples (prob non-existent)" },
- { "KDDI", "3GPP2 EZmovie for KDDI 3G cellphones" },
- { "M4A ", "Apple iTunes AAC-LC (.M4A) Audio" },
- { "M4B ", "Apple iTunes AAC-LC (.M4B) Audio Book" },
- { "M4P ", "Apple iTunes AAC-LC (.M4P) AES Protected Audio" },
- { "M4V ", "Apple iTunes Video (.M4V) Video" },
- { "M4VH", "Apple TV (.M4V)" },
- { "M4VP", "Apple iPhone (.M4V)" },
- { "MPPI", "Photo Player, MAF [ISO/IEC 23000-3]" },
- { "MSNV", "MPEG-4 (.MP4) for SonyPSP" },
- { "NDAS", "MP4 v2 [ISO 14496-14] Nero Digital AAC Audio" },
- { "NDSC", "MPEG-4 (.MP4) Nero Cinema Profile" },
- { "NDSH", "MPEG-4 (.MP4) Nero HDTV Profile" },
- { "NDSM", "MPEG-4 (.MP4) Nero Mobile Profile" },
- { "NDSP", "MPEG-4 (.MP4) Nero Portable Profile" },
- { "NDSS", "MPEG-4 (.MP4) Nero Standard Profile" },
- { "NDXC", "H.264/MPEG-4 AVC (.MP4) Nero Cinema Profile" },
- { "NDXH", "H.264/MPEG-4 AVC (.MP4) Nero HDTV Profile" },
- { "NDXM", "H.264/MPEG-4 AVC (.MP4) Nero Mobile Profile" },
- { "NDXP", "H.264/MPEG-4 AVC (.MP4) Nero Portable Profile" },
- { "NDXS", "H.264/MPEG-4 AVC (.MP4) Nero Standard Profile" },
- { "NIKO", "Nikon" },
- { "ROSS", "Ross Video" },
- { "avc1", "MP4 Base w/ AVC ext [ISO 14496-12:2005]" },
- { "caqv", "Casio Digital Camera" },
- { "da0a", "DMB MAF w/ MPEG Layer II aud, MOT slides, DLS, JPG/PNG/MNG images" },
- { "da0b", "DMB MAF, extending DA0A, with 3GPP timed text, DID, TVA, REL, IPMP" },
- { "da1a", "DMB MAF audio with ER-BSAC audio, JPG/PNG/MNG images" },
- { "da1b", "DMB MAF, extending da1a, with 3GPP timed text, DID, TVA, REL, IPMP" },
- { "da2a", "DMB MAF aud w/ HE-AAC v2 aud, MOT slides, DLS, JPG/PNG/MNG images" },
- { "da2b", "DMB MAF, extending da2a, with 3GPP timed text, DID, TVA, REL, IPMP" },
- { "da3a", "DMB MAF aud with HE-AAC aud, JPG/PNG/MNG images" },
- { "da3b", "DMB MAF, extending da3a w/ BIFS, 3GPP timed text, DID, TVA, REL, IPMP" },
- { "dmb1", "DMB MAF supporting all the components defined in the specification" },
- { "dmpf", "Digital Media Project" },
- { "drc1", "Dirac (wavelet compression), encapsulated in ISO base media (MP4)" },
- { "dv1a", "DMB MAF vid w/ AVC vid, ER-BSAC aud, BIFS, JPG/PNG/MNG images, TS" },
- { "dv1b", "DMB MAF, extending dv1a, with 3GPP timed text, DID, TVA, REL, IPMP" },
- { "dv2a", "DMB MAF vid w/ AVC vid, HE-AAC v2 aud, BIFS, JPG/PNG/MNG images, TS" },
- { "dv2b", "DMB MAF, extending dv2a, with 3GPP timed text, DID, TVA, REL, IPMP" },
- { "dv3a", "DMB MAF vid w/ AVC vid, HE-AAC aud, BIFS, JPG/PNG/MNG images, TS" },
- { "dv3b", "DMB MAF, extending dv3a, with 3GPP timed text, DID, TVA, REL, IPMP" },
- { "dvr1", "DVB (.DVB) over RTP" },
- { "dvt1", "DVB (.DVB) over MPEG-2 Transport Stream" },
- { "isc2", "ISMACryp 2.0 Encrypted File" },
- { "iso2", "MP4 Base Media v2 [ISO 14496-12:2005]" },
- { "isom", "MP4 Base Media v1 [IS0 14496-12:2003]" },
- { "jpm ", "JPEG 2000 Compound Image (.JPM) [ISO 15444-6]" },
- { "jpx ", "JPEG 2000 with extensions (.JPX) [ISO 15444-2]" },
- { "mj2s", "Motion JPEG 2000 [ISO 15444-3] Simple Profile" },
- { "mjp2", "Motion JPEG 2000 [ISO 15444-3] General Profile" },
- { "mmp4", "MPEG-4/3GPP Mobile Profile (.MP4/3GP) (for NTT)" },
- { "mp21", "MPEG-21 [ISO/IEC 21000-9]" },
- { "mp41", "MP4 v1 [ISO 14496-1:ch13]" },
- { "mp42", "MP4 v2 [ISO 14496-14]" },
- { "mp71", "MP4 w/ MPEG-7 Metadata [per ISO 14496-12]" },
- { "mqt ", "Sony / Mobile QuickTime (.MQV) US Patent 7,477,830 (Sony Corp)" },
- { "niko", "Nikon" },
- { "odcf", "OMA DCF DRM Format 2.0 (OMA-TS-DRM-DCF-V2_0-20060303-A)" },
- { "opf2", "OMA PDCF DRM Format 2.1 (OMA-TS-DRM-DCF-V2_1-20070724-C)" },
- { "opx2", "OMA PDCF DRM + XBS extensions (OMA-TS-DRM_XBS-V1_0-20070529-C)" },
- { "pana", "Panasonic Digital Camera" },
- { "qt ", "Apple QuickTime (.MOV/QT)" },
- { "sdv ", "SD Memory Card Video" },
- { "ssc1", "Samsung stereoscopic, single stream" },
- { "ssc2", "Samsung stereoscopic, dual stream" }
+//! File type information.
+extern const TagVocabulary qTimeFileType[] = {
+ { "3g2a", "3GPP2 Media (.3G2) compliant with 3GPP2 C.S0050-0 V1.0" },
+ { "3g2b", "3GPP2 Media (.3G2) compliant with 3GPP2 C.S0050-A V1.0.0" },
+ { "3g2c", "3GPP2 Media (.3G2) compliant with 3GPP2 C.S0050-B v1.0" },
+ { "3ge6", "3GPP (.3GP) Release 6 MBMS Extended Presentations" },
+ { "3ge7", "3GPP (.3GP) Release 7 MBMS Extended Presentations" },
+ { "3gg6", "3GPP Release 6 General Profile" },
+ { "3gp1", "3GPP Media (.3GP) Release 1 (probably non-existent)" },
+ { "3gp2", "3GPP Media (.3GP) Release 2 (probably non-existent)" },
+ { "3gp3", "3GPP Media (.3GP) Release 3 (probably non-existent)" },
+ { "3gp4", "3GPP Media (.3GP) Release 4" },
+ { "3gp5", "3GPP Media (.3GP) Release 5" },
+ { "3gp6", "3GPP Media (.3GP) Release 6 Streaming Servers" },
+ { "3gs7", "3GPP Media (.3GP) Release 7 Streaming Servers" },
+ { "CAEP", "Canon Digital Camera" },
+ { "CDes", "Convergent Design" },
+ { "F4A ", "Audio for Adobe Flash Player 9+ (.F4A)" },
+ { "F4B ", "Audio Book for Adobe Flash Player 9+ (.F4B)" },
+ { "F4P ", "Protected Video for Adobe Flash Player 9+ (.F4P)" },
+ { "F4V ", "Video for Adobe Flash Player 9+ (.F4V)" },
+ { "JP2 ", "JPEG 2000 Image (.JP2) [ISO 15444-1 ?]" },
+ { "JP20", "Unknown, from GPAC samples (prob non-existent)" },
+ { "KDDI", "3GPP2 EZmovie for KDDI 3G cellphones" },
+ { "M4A ", "Apple iTunes AAC-LC (.M4A) Audio" },
+ { "M4B ", "Apple iTunes AAC-LC (.M4B) Audio Book" },
+ { "M4P ", "Apple iTunes AAC-LC (.M4P) AES Protected Audio" },
+ { "M4V ", "Apple iTunes Video (.M4V) Video" },
+ { "M4VH", "Apple TV (.M4V)" },
+ { "M4VP", "Apple iPhone (.M4V)" },
+ { "MPPI", "Photo Player, MAF [ISO/IEC 23000-3]" },
+ { "MSNV", "MPEG-4 (.MP4) for SonyPSP" },
+ { "NDAS", "MP4 v2 [ISO 14496-14] Nero Digital AAC Audio" },
+ { "NDSC", "MPEG-4 (.MP4) Nero Cinema Profile" },
+ { "NDSH", "MPEG-4 (.MP4) Nero HDTV Profile" },
+ { "NDSM", "MPEG-4 (.MP4) Nero Mobile Profile" },
+ { "NDSP", "MPEG-4 (.MP4) Nero Portable Profile" },
+ { "NDSS", "MPEG-4 (.MP4) Nero Standard Profile" },
+ { "NDXC", "H.264/MPEG-4 AVC (.MP4) Nero Cinema Profile" },
+ { "NDXH", "H.264/MPEG-4 AVC (.MP4) Nero HDTV Profile" },
+ { "NDXM", "H.264/MPEG-4 AVC (.MP4) Nero Mobile Profile" },
+ { "NDXP", "H.264/MPEG-4 AVC (.MP4) Nero Portable Profile" },
+ { "NDXS", "H.264/MPEG-4 AVC (.MP4) Nero Standard Profile" },
+ { "NIKO", "Nikon" },
+ { "ROSS", "Ross Video" },
+ { "avc1", "MP4 Base w/ AVC ext [ISO 14496-12:2005]" },
+ { "caqv", "Casio Digital Camera" },
+ { "da0a", "DMB MAF w/ MPEG Layer II aud, MOT slides, DLS, JPG/PNG/MNG images" },
+ { "da0b", "DMB MAF, extending DA0A, with 3GPP timed text, DID, TVA, REL, IPMP" },
+ { "da1a", "DMB MAF audio with ER-BSAC audio, JPG/PNG/MNG images" },
+ { "da1b", "DMB MAF, extending da1a, with 3GPP timed text, DID, TVA, REL, IPMP" },
+ { "da2a", "DMB MAF aud w/ HE-AAC v2 aud, MOT slides, DLS, JPG/PNG/MNG images" },
+ { "da2b", "DMB MAF, extending da2a, with 3GPP timed text, DID, TVA, REL, IPMP" },
+ { "da3a", "DMB MAF aud with HE-AAC aud, JPG/PNG/MNG images" },
+ { "da3b", "DMB MAF, extending da3a w/ BIFS, 3GPP timed text, DID, TVA, REL, IPMP" },
+ { "dmb1", "DMB MAF supporting all the components defined in the specification" },
+ { "dmpf", "Digital Media Project" },
+ { "drc1", "Dirac (wavelet compression), encapsulated in ISO base media (MP4)" },
+ { "dv1a", "DMB MAF vid w/ AVC vid, ER-BSAC aud, BIFS, JPG/PNG/MNG images, TS" },
+ { "dv1b", "DMB MAF, extending dv1a, with 3GPP timed text, DID, TVA, REL, IPMP" },
+ { "dv2a", "DMB MAF vid w/ AVC vid, HE-AAC v2 aud, BIFS, JPG/PNG/MNG images, TS" },
+ { "dv2b", "DMB MAF, extending dv2a, with 3GPP timed text, DID, TVA, REL, IPMP" },
+ { "dv3a", "DMB MAF vid w/ AVC vid, HE-AAC aud, BIFS, JPG/PNG/MNG images, TS" },
+ { "dv3b", "DMB MAF, extending dv3a, with 3GPP timed text, DID, TVA, REL, IPMP" },
+ { "dvr1", "DVB (.DVB) over RTP" },
+ { "dvt1", "DVB (.DVB) over MPEG-2 Transport Stream" },
+ { "isc2", "ISMACryp 2.0 Encrypted File" },
+ { "iso2", "MP4 Base Media v2 [ISO 14496-12:2005]" },
+ { "isom", "MP4 Base Media v1 [IS0 14496-12:2003]" },
+ { "jpm ", "JPEG 2000 Compound Image (.JPM) [ISO 15444-6]" },
+ { "jpx ", "JPEG 2000 with extensions (.JPX) [ISO 15444-2]" },
+ { "mj2s", "Motion JPEG 2000 [ISO 15444-3] Simple Profile" },
+ { "mjp2", "Motion JPEG 2000 [ISO 15444-3] General Profile" },
+ { "mmp4", "MPEG-4/3GPP Mobile Profile (.MP4/3GP) (for NTT)" },
+ { "mp21", "MPEG-21 [ISO/IEC 21000-9]" },
+ { "mp41", "MP4 v1 [ISO 14496-1:ch13]" },
+ { "mp42", "MP4 v2 [ISO 14496-14]" },
+ { "mp71", "MP4 w/ MPEG-7 Metadata [per ISO 14496-12]" },
+ { "mqt ", "Sony / Mobile QuickTime (.MQV) US Patent 7,477,830 (Sony Corp)" },
+ { "niko", "Nikon" },
+ { "odcf", "OMA DCF DRM Format 2.0 (OMA-TS-DRM-DCF-V2_0-20060303-A)" },
+ { "opf2", "OMA PDCF DRM Format 2.1 (OMA-TS-DRM-DCF-V2_1-20070724-C)" },
+ { "opx2", "OMA PDCF DRM + XBS extensions (OMA-TS-DRM_XBS-V1_0-20070529-C)" },
+ { "pana", "Panasonic Digital Camera" },
+ { "qt ", "Apple QuickTime (.MOV/QT)" },
+ { "sdv ", "SD Memory Card Video" },
+ { "ssc1", "Samsung stereoscopic, single stream" },
+ { "ssc2", "Samsung stereoscopic, dual stream" },
+};
+
+//! hadler Class Information.
+extern const TagVocabulary handlerClassTags[] ={
+ { "dhlr", "Data Handler" },
+ { "mhlr", "Media Handler" }
+};
+
+//! Handler Type Information.
+extern const TagVocabulary handlerTypeTags[] ={
+ { "alis", "Alias Data" },
+ { "crsm", "Clock Reference" },
+ { "hint", "Hint Track" },
+ { "ipsm", "IPMP" },
+ { "m7sm", "MPEG-7 Stream" },
+ { "mdir", "Metadata" },
+ { "mdta", "Metadata Tags" },
+ { "mjsm", "MPEG-J" },
+ { "ocsm", "Object Content" },
+ { "odsm", "Object Descriptor" },
+ { "sdsm", "Scene Description" },
+ { "soun", "Audio Track" },
+ { "text", "Text" },
+ { "tmcd", "Time Code" },
+ { "url ", "URL" },
+ { "vide", "Video Track" }
+};
+
+//! Vendor Id information.
+extern const TagVocabulary vendorIDTags[] ={
+ { "FFMP", "FFmpeg" },
+ { "appl", "Apple" },
+ { "olym", "Olympus" },
+ { "GIC ", "General Imaging Co." },
+ { "fe20", "Olympus (fe20)" },
+ { "pana", "Panasonic" },
+ { "KMPI", "Konica-Minolta" },
+ { "kdak", "Kodak" },
+ { "pent", "Pentax" },
+ { "NIKO", "Nikon" },
+ { "leic", "Leica" },
+ { "pr01", "Olympus (pr01)" },
+ { "SMI ", "Sorenson Media Inc." },
+ { "mino", "Minolta" },
+ { "sany", "Sanyo" },
+ { "ZORA", "Zoran Corporation" },
+ { "niko", "Nikon" }
+};
+
+//! Camera Information.
+extern const TagVocabulary cameraByteOrderTags[] ={
+ { "II", "Little-endian (Intel, II)" },
+ { "MM", "Big-endian (Motorola, MM)" }
+};
+
+//! Graphics related Information.
+extern const TagDetails graphicsModetags[] ={
+ { 0x0, "srcCopy" },
+ { 0x1, "srcOr" },
+ { 0x2, "srcXor" },
+ { 0x3, "srcBic" },
+ { 0x4, "notSrcCopy" },
+ { 0x5, "notSrcOr" },
+ { 0x6, "notSrcXor" },
+ { 0x7, "notSrcBic" },
+ { 0x8, "patCopy" },
+ { 0x9, "patOr" },
+ { 0xa, "patXor" },
+ { 0xb, "patBic" },
+ { 0xc, "notPatCopy" },
+ { 0xd, "notPatOr" },
+ { 0xe, "notPatXor" },
+ { 0xf, "notPatBic" },
+ { 0x20, "blend" },
+ { 0x21, "addPin" },
+ { 0x22, "addOver" },
+ { 0x23, "subPin" },
+ { 0x24, "transparent" },
+ { 0x25, "addMax" },
+ { 0x26, "subOver" },
+ { 0x27, "addMin" },
+ { 0x31, "grayishTextOr" },
+ { 0x32, "hilite" },
+ { 0x40, "ditherCopy" },
+ { 0x100, "Alpha" },
+ { 0x101, "White Alpha" },
+ { 0x102, "Pre-multiplied Black Alpha" },
+ { 0x110, "Component Alpha" }
+};
+
+//! Media Language Codes.
+extern const TagDetails mediaLanguageCode[] ={
+ { 0x0, "English" },
+ { 0x1, "French" },
+ { 0x2, "German" },
+ { 0x3, "Italian" },
+ { 0x4, "Dutch" },
+ { 0x5, "Swedish" },
+ { 0x6, "Spanish" },
+ { 0x7, "Danish" },
+ { 0x8, "Portuguese" },
+ { 0x9, "Norwegian" },
+ { 0xa, "Hebrew" },
+ { 0xb, "Japanese" },
+ { 0xc, "Arabic" },
+ { 0xd, "Finnish" },
+ { 0xe, "Greek" },
+ { 0xf, "Icelandic" },
+ { 0x10, "Maltese" },
+ { 0x11, "Turkish" },
+ { 0x12, "Croatian" },
+ { 0x13, "Traditional Chinese" },
+ { 0x14, "Urdu" },
+ { 0x15, "Hindi" },
+ { 0x16, "Thai" },
+ { 0x17, "Korean" },
+ { 0x18, "Lithuanian" },
+ { 0x19, "Polish" },
+ { 0x1a, "Hungarian" },
+ { 0x1b, "Estonian" },
+ { 0x1c, "Lettish" },
+ { 0x1c, "Latvian" },
+ { 0x1d, "Saami" },
+ { 0x1d, "Sami" },
+ { 0x1e, "Faroese" },
+ { 0x1f, "Farsi" },
+ { 0x20, "Russian" },
+ { 0x21, "Simplified Chinese" },
+ { 0x22, "Flemish" },
+ { 0x23, "Irish" },
+ { 0x24, "Albanian" },
+ { 0x25, "Romanian" },
+ { 0x26, "Czech" },
+ { 0x27, "Slovak" },
+ { 0x28, "Slovenian" },
+ { 0x29, "Yiddish" },
+ { 0x2a, "Serbian" },
+ { 0x2b, "Macedonian" },
+ { 0x2c, "Bulgarian" },
+ { 0x2d, "Ukrainian" },
+ { 0x2e, "Belarusian" },
+ { 0x2f, "Uzbek" },
+ { 0x30, "Kazakh" },
+ { 0x31, "Azerbaijani" },
+ { 0x32, "AzerbaijanAr" },
+ { 0x33, "Armenian" },
+ { 0x34, "Georgian" },
+ { 0x35, "Moldavian" },
+ { 0x36, "Kirghiz" },
+ { 0x37, "Tajiki" },
+ { 0x38, "Turkmen" },
+ { 0x39, "Mongolian" },
+ { 0x3a, "MongolianCyr" },
+ { 0x3b, "Pashto" },
+ { 0x3c, "Kurdish" },
+ { 0x3d, "Kashmiri" },
+ { 0x3e, "Sindhi" },
+ { 0x3f, "Tibetan" },
+ { 0x40, "Nepali" },
+ { 0x41, "Sanskrit" },
+ { 0x42, "Marathi" },
+ { 0x43, "Bengali" },
+ { 0x44, "Assamese" },
+ { 0x45, "Gujarati" },
+ { 0x46, "Punjabi" },
+ { 0x47, "Oriya" },
+ { 0x48, "Malayalam" },
+ { 0x49, "Kannada" },
+ { 0x4a, "Tamil" },
+ { 0x4b, "Telugu" },
+ { 0x4c, "Sinhala" },
+ { 0x4d, "Burmese" },
+ { 0x4e, "Khmer" },
+ { 0x4f, "Lao" },
+ { 0x50, "Vietnamese" },
+ { 0x51, "Indonesian" },
+ { 0x52, "Tagalog" },
+ { 0x53, "MalayRoman" },
+ { 0x54, "MalayArabic" },
+ { 0x55, "Amharic" },
+ { 0x56, "Galla" },
+ { 0x57, "Oromo" },
+ { 0x58, "Somali" },
+ { 0x59, "Swahili" },
+ { 0x5a, "Kinyarwanda" },
+ { 0x5b, "Rundi" },
+ { 0x5c, "Nyanja" },
+ { 0x5d, "Malagasy" },
+ { 0x5e, "Esperanto" },
+ { 0x80, "Welsh" },
+ { 0x81, "Basque" },
+ { 0x82, "Catalan" },
+ { 0x83, "Latin" },
+ { 0x84, "Quechua" },
+ { 0x85, "Guarani" },
+ { 0x86, "Aymara" },
+ { 0x87, "Tatar" },
+ { 0x88, "Uighur" },
+ { 0x89, "Dzongkha" },
+ { 0x8a, "JavaneseRom" }
+};
+
+//! User Date related Information.
+extern const TagVocabulary userDatatags[] ={
+ { "AllF", "PlayAllFrames" },
+ { "CNCV", "CompressorVersion" },
+ { "CNFV", "FirmwareVersion" },
+ { "CNMN", "Model" },
+ { "CNTH", "CanonCNTH" },
+ { "DcMD", "DcMD" },
+ { "FFMV", "FujiFilmFFMV" },
+ { "INFO", "SamsungINFO" },
+ { "LOOP", "LoopStyle" },
+ { "MMA0", "MinoltaMMA0" },
+ { "MMA1", "MinoltaMMA1" },
+ { "MVTG", "FujiFilmMVTG" },
+ { "NCDT", "NikonNCDT" },
+ { "PANA", "PanasonicPANA" },
+ { "PENT", "PentaxPENT" },
+ { "PXMN", "MakerNotePentax5b" },
+ { "PXTH", "PentaxPreview" },
+ { "QVMI", "CasioQVMI" },
+ { "SDLN", "PlayMode" },
+ { "SelO", "PlaySelection" },
+ { "TAGS", "KodakTags/KonicaMinoltaTags/MinoltaTags/NikonTags/OlympusTags/PentaxTags/SamsungTags/SanyoMOV/SanyoMP4" },
+ { "WLOC", "WindowLocation" },
+ { "XMP_", "XMP" },
+ { "Xtra", "Xtra" },
+ { "hinf", "HintTrackInfo" },
+ { "hinv", "HintVersion" },
+ { "hnti", "Hint" },
+ { "meta", "Meta" },
+ { "name", "Name" },
+ { "ptv ", "PrintToVideo" },
+ { "scrn", "OlympusPreview" },
+ { "thmb", "MakerNotePentax5a/OlympusThumbnail" },
+};
+
+//! User Data related Information.
+extern const TagVocabulary userDataReferencetags[] ={
+ { "CNCV", "Xmp.video.CompressorVersion" },
+ { "CNFV", "Xmp.video.FirmwareVersion" },
+ { "CNMN", "Xmp.video.Model" },
+ { "NCHD", "Xmp.video.MakerNoteType" },
+ { "WLOC", "Xmp.video.WindowLocation" },
+ { "SDLN", "Xmp.video.PlayMode" },
+ { "FFMV", "Xmp.video.StreamName" },
+ { "SelO", "Xmp.video.PlaySelection" },
+ { "name", "Xmp.video.Name" },
+ { "vndr", "Xmp.video.Vendor" },
+ { " ART", "Xmp.video.Artist" },
+ { " alb", "Xmp.video.Album" },
+ { " arg", "Xmp.video.Arranger" },
+ { " ark", "Xmp.video.ArrangerKeywords" },
+ { " cmt", "Xmp.video.Comment" },
+ { " cok", "Xmp.video.ComposerKeywords" },
+ { " com", "Xmp.video.Composer" },
+ { " cpy", "Xmp.video.Copyright" },
+ { " day", "Xmp.video.CreateDate" },
+ { " dir", "Xmp.video.Director" },
+ { " ed1", "Xmp.video.Edit1" },
+ { " ed2", "Xmp.video.Edit2" },
+ { " ed3", "Xmp.video.Edit3" },
+ { " ed4", "Xmp.video.Edit4" },
+ { " ed5", "Xmp.video.Edit5" },
+ { " ed6", "Xmp.video.Edit6" },
+ { " ed7", "Xmp.video.Edit7" },
+ { " ed8", "Xmp.video.Edit8" },
+ { " ed9", "Xmp.video.Edit9" },
+ { " enc", "Xmp.video.Encoder" },
+ { " fmt", "Xmp.video.Format" },
+ { " gen", "Xmp.video.Genre" },
+ { " grp", "Xmp.video.Grouping" },
+ { " inf", "Xmp.video.Information" },
+ { " isr", "Xmp.video.ISRCCode" },
+ { " lab", "Xmp.video.RecordLabelName" },
+ { " lal", "Xmp.video.RecordLabelURL" },
+ { " lyr", "Xmp.video.Lyrics" },
+ { " mak", "Xmp.video.Make" },
+ { " mal", "Xmp.video.MakerURL" },
+ { " mod", "Xmp.video.Model" },
+ { " nam", "Xmp.video.Title" },
+ { " pdk", "Xmp.video.ProducerKeywords" },
+ { " phg", "Xmp.video.RecordingCopyright" },
+ { " prd", "Xmp.video.Producer" },
+ { " prf", "Xmp.video.Performers" },
+ { " prk", "Xmp.video.PerformerKeywords" },
+ { " prl", "Xmp.video.PerformerURL" },
+ { " req", "Xmp.video.Requirements" },
+ { " snk", "Xmp.video.SubtitleKeywords" },
+ { " snm", "Xmp.video.Subtitle" },
+ { " src", "Xmp.video.SourceCredits" },
+ { " swf", "Xmp.video.SongWriter" },
+ { " swk", "Xmp.video.SongWriterKeywords" },
+ { " swr", "Xmp.video.SoftwareVersion" },
+ { " too", "Xmp.video.Encoder" },
+ { " trk", "Xmp.video.Track" },
+ { " wrt", "Xmp.video.Composer" },
+ { " xyz", "Xmp.video.GPSCoordinates" },
+ { "CMbo", "Xmp.video.CameraByteOrder" },
+ { "Cmbo", "Xmp.video.CameraByteOrder" },
+};
+
+//! Nikon Tags Information.
+extern const TagDetails NikonNCTGTags[] ={
+ { 0x0001, "Xmp.video.Make" },
+ { 0x0002, "Xmp.video.Model" },
+ { 0x0003, "Xmp.video.Software" },
+ { 0x0011, "Xmp.video.CreationDate" },
+ { 0x0012, "Xmp.video.DateTimeOriginal" },
+ { 0x0013, "Xmp.video.FrameCount" },
+ { 0x0016, "Xmp.video.FrameRate" },
+ { 0x0022, "Xmp.video.FrameWidth" },
+ { 0x0023, "Xmp.video.FrameHeight" },
+ { 0x0032, "Xmp.audio.channelType" },
+ { 0x0033, "Xmp.audio.BitsPerSample" },
+ { 0x0034, "Xmp.audio.sampleRate" },
+ { 0x1108822, "Xmp.video.ExposureProgram" },
+ { 0x1109204, "Xmp.video.ExposureCompensation" },
+ { 0x1109207, "Xmp.video.MeteringMode" },
+ { 0x110a434, "Xmp.video.LensModel" },
+ { 0x1200000, "Xmp.video.GPSVersionID" },
+ { 0x1200001, "Xmp.video.GPSLatitudeRef" },
+ { 0x1200002, "Xmp.video.GPSLatitude" },
+ { 0x1200003, "Xmp.video.GPSLongitudeRef" },
+ { 0x1200004, "Xmp.video.GPSLongitude" },
+ { 0x1200005, "Xmp.video.GPSAltitudeRef" },
+ { 0x1200006, "Xmp.video.GPSAltitude" },
+ { 0x1200007, "Xmp.video.GPSTimeStamp" },
+ { 0x1200008, "Xmp.video.GPSSatellites" },
+ { 0x1200010, "Xmp.video.GPSImgDirectionRef" },
+ { 0x1200011, "Xmp.video.GPSImgDirection" },
+ { 0x1200012, "Xmp.video.GPSMapDatum" },
+ { 0x120001d, "Xmp.video.GPSDateStamp" },
+ { 0x2000001, "Xmp.video.MakerNoteVersion" },
+ { 0x2000005, "Xmp.video.WhiteBalance" },
+ { 0x200000b, "Xmp.video.WhiteBalanceFineTune" },
+ { 0x200001e, "Xmp.video.ColorSpace" },
+ { 0x2000023, "Xmp.video.PictureControlData" },
+ { 0x2000024, "Xmp.video.WorldTime" },
+ { 0x200002c, "Xmp.video.UnknownInfo" },
+ { 0x2000032, "Xmp.video.UnknownInfo2" },
+ { 0x2000039, "Xmp.video.LocationInfo" },
+ { 0x2000083, "Xmp.video.LensType" },
+ { 0x2000084, "Xmp.video.LensModel" },
+ { 0x20000ab, "Xmp.video.VariProgram" },
+};
+
+//! Nikon Color space Information.
+extern const TagDetails NikonColorSpace[] ={
+ { 1, "sRGB" },
+ { 2, "Adobe RGB" },
+};
+
+//! Nikon Tags.
+extern const TagVocabulary NikonGPS_Latitude_Longitude_ImgDirection_Reference[] =
+{
+ { "N", "North" },
+ { "S", "South" },
+ { "E", "East" },
+ { "W", "West" },
+ { "M", "Magnetic North" },
+ { "T", "True North" },
+};
+
+//! Nikon Tags
+extern const TagDetails NikonGPSAltitudeRef[] ={
+ { 0, "Above Sea Level" },
+ { 1, "Below Sea Level" },
+};
+
+//! Nikon Tags.
+extern const TagDetails NikonExposureProgram[] ={
+ { 0, "Not Defined" },
+ { 1, "Manual" },
+ { 2, "Program AE" },
+ { 3, "Aperture-priority AE" },
+ { 4, "Shutter speed priority AE" },
+ { 5, "Creative (Slow speed)" },
+ { 6, "Action (High speed)" },
+ { 7, "Portrait" },
+ { 8, "Landscape" },
+};
+
+//! Nikon Tags.
+extern const TagDetails NikonMeteringMode[] ={
+ { 0, "Unknown" },
+ { 1, "Average" },
+ { 2, "Center-weighted average" },
+ { 3, "Spot" },
+ { 4, "Multi-spot" },
+ { 5, "Multi-segment" },
+ { 6, "Partial" },
+ { 255, "Other" },
+};
+
+//! picture tags.
+extern const TagDetails PictureControlAdjust[] ={
+ { 0, "Default Settings" },
+ { 1, "Quick Adjust" },
+ { 2, "Full Control" },
+};
+
+//! Contrast and Sharpness
+extern const TagDetails NormalSoftHard[] ={
+ { 0, "Normal" },
+ { 1, "Soft" },
+ { 2, "Hard" }
+};
+
+//! Saturation
+extern const TagDetails Saturation[] ={
+ { 0, "Normal" },
+ { 1, "Low" },
+ { 2, "High" }
+};
+
+//! YesNo, used for DaylightSavings
+extern const TagDetails YesNo[] ={
+ { 0, "No" },
+ { 1, "Yes" }
+};
+
+//! DateDisplayFormat
+extern const TagDetails DateDisplayFormat[] ={
+ { 0, "Y/M/D" },
+ { 1, "M/D/Y" },
+ { 2, "D/M/Y" }
+};
+
+//! Filter Effects.
+extern const TagDetails FilterEffect[] ={
+ { 0x80, "Off" },
+ { 0x81, "Yellow" },
+ { 0x82, "Orange" },
+ { 0x83, "Red" },
+ { 0x84, "Green" },
+ { 0xff, "n/a" },
+};
+
+//! Toning Effect.
+extern const TagDetails ToningEffect[] ={
+ { 0x80, "B&W" },
+ { 0x81, "Sepia" },
+ { 0x82, "Cyanotype" },
+ { 0x83, "Red" },
+ { 0x84, "Yellow" },
+ { 0x85, "Green" },
+ { 0x86, "Blue-green" },
+ { 0x87, "Blue" },
+ { 0x88, "Purple-blue" },
+ { 0x89, "Red-purple" },
+ { 0xff, "n/a" },
+};
+
+//! White balance Information.
+extern const TagDetails whiteBalance[] ={
+ { 0, "Auto" },
+ { 1, "Daylight" },
+ { 2, "Shade" },
+ { 3, "Fluorescent" },
+ { 4, "Tungsten" },
+ { 5, "Manual" },
+};
+
+//! To select specific bytes with in a chunk.
+enum movieHeaderTags{
+ MovieHeaderVersion, CreateDate, ModifyDate, TimeScale, Duration, PreferredRate, PreferredVolume,
+ PreviewTime = 18, PreviewDuration,PosterTime, SelectionTime, SelectionDuration, CurrentTime, NextTrackID
+};
+
+//! To select specific bytes with in a chunk.
+enum trackHeaderTags{
+ TrackHeaderVersion, TrackCreateDate, TrackModifyDate, TrackID, TrackDuration = 5, TrackLayer = 8,
+ TrackVolume, ImageWidth = 19, ImageHeight
+};
+
+//! To select specific bytes with in a chunk.
+enum mediaHeaderTags{
+ MediaHeaderVersion, MediaCreateDate, MediaModifyDate, MediaTimeScale, MediaDuration, MediaLanguageCode
+};
+
+//! To select specific bytes with in a chunk.
+enum handlerTags{
+ HandlerClass = 1, HandlerType, HandlerVendorID
+};
+
+//! To select specific bytes with in a chunk.
+enum videoHeaderTags{
+ GraphicsMode = 2, OpColor
+};
+
+//! To select specific bytes with in a chunk.
+enum stream{
+ Video, Audio, Hint, Null, GenMediaHeader
+};
+
+//! To select specific bytes with in a chunk.
+enum imageDescTags{
+ codec, VendorID = 4, SourceImageWidth_Height = 7, XResolution,
+ YResolution, CompressorName = 10, BitDepth
+};
+
+//! To select specific bytes with in a chunk.
+enum audioDescTags{
+ AudioFormat, AudioVendorID = 4, AudioChannels, AudioSampleRate = 7, MOV_AudioFormat = 13
+};
+
+/*!
+ * \brief equalsQTimeTag overloaded function to handle tag Array
+ * It will compare all the tags in a array.
+ * \param buf Data buffer that will contain Tag to compare.
+ * \param arr Contains multiple tags to compare from.
+ * \param arraysize Number of tags in arr.
+ * \return true if buf matches any one tag in arr.
+ */
+bool equalsQTimeTag(Exiv2::DataBuf& buf,const char arr[][5],int32_t arraysize)
+{
+ bool result = false;
+ for ( int32_t i=0; !result && i< arraysize; i++)
+ result = (bool)(stricmp((const char*)buf.pData_,arr[i+1])==0);
+ return result;
+}
+
+/*!
+ @brief Function used to ignore Tags and values stored in them,
+ since they are not necessary as metadata information
+ @param buf Data buffer that will contain Tag to compare
+ @return Returns true, if Tag is found in the ignoreList[]
+ */
+bool ignoreList (Exiv2::DataBuf& buf)
+{
+ const char ignoreList[13][5] ={
+ "mdat", "edts", "junk", "iods", "alis", "stsc", "stsz", "stco", "ctts", "stss",
+ "skip", "wide", "cmvd",
};
- extern const TagVocabulary handlerClassTags[] = {
- { "dhlr", "Data Handler" },
- { "mhlr", "Media Handler" }
+ int32_t i;
+ for(i = 0 ; i < 13 ; ++i)
+ if(UtilsVideo::compareTagValue(buf, ignoreList[i]))
+ return true;
+
+ return false;
+}
+
+/*!
+ @brief Function used to ignore Tags, basically Tags which
+ contain other tags inside them, since they are not necessary
+ as metadata information
+ @param buf Data buffer that will contain Tag to compare
+ @return Returns true, if Tag is found in the ignoreList[]
+ */
+bool dataIgnoreList (Exiv2::DataBuf& buf)
+{
+ const char ignoreList[8][5] ={
+ "moov", "mdia", "minf", "dinf", "alis", "stbl", "cmov",
+ "meta",
};
- extern const TagVocabulary handlerTypeTags[] = {
- { "alis", "Alias Data" },
- { "crsm", "Clock Reference" },
- { "hint", "Hint Track" },
- { "ipsm", "IPMP" },
- { "m7sm", "MPEG-7 Stream" },
- { "mdir", "Metadata" },
- { "mdta", "Metadata Tags" },
- { "mjsm", "MPEG-J" },
- { "ocsm", "Object Content" },
- { "odsm", "Object Descriptor" },
- { "sdsm", "Scene Description" },
- { "soun", "Audio Track" },
- { "text", "Text" },
- { "tmcd", "Time Code" },
- { "url ", "URL" },
- { "vide", "Video Track" }
- };
+ int32_t i;
+ for(i = 0 ; i < 8 ; ++i)
+ if(UtilsVideo::compareTagValue(buf, ignoreList[i]))
+ return true;
- extern const TagVocabulary vendorIDTags[] = {
- { "FFMP", "FFmpeg" },
- { "appl", "Apple" },
- { "olym", "Olympus" },
- { "GIC ", "General Imaging Co." },
- { "fe20", "Olympus (fe20)" },
- { "pana", "Panasonic" },
- { "KMPI", "Konica-Minolta" },
- { "kdak", "Kodak" },
- { "pent", "Pentax" },
- { "NIKO", "Nikon" },
- { "leic", "Leica" },
- { "pr01", "Olympus (pr01)" },
- { "SMI ", "Sorenson Media Inc." },
- { "mino", "Minolta" },
- { "sany", "Sanyo" },
- { "ZORA", "Zoran Corporation" },
- { "niko", "Nikon" }
- };
+ return false;
+}
- extern const TagVocabulary cameraByteOrderTags[] = {
- { "II", "Little-endian (Intel, II)" },
- { "MM", "Big-endian (Motorola, MM)" }
- };
-
- extern const TagDetails graphicsModetags[] = {
- { 0x0, "srcCopy" },
- { 0x1, "srcOr" },
- { 0x2, "srcXor" },
- { 0x3, "srcBic" },
- { 0x4, "notSrcCopy" },
- { 0x5, "notSrcOr" },
- { 0x6, "notSrcXor" },
- { 0x7, "notSrcBic" },
- { 0x8, "patCopy" },
- { 0x9, "patOr" },
- { 0xa, "patXor" },
- { 0xb, "patBic" },
- { 0xc, "notPatCopy" },
- { 0xd, "notPatOr" },
- { 0xe, "notPatXor" },
- { 0xf, "notPatBic" },
- { 0x20, "blend" },
- { 0x21, "addPin" },
- { 0x22, "addOver" },
- { 0x23, "subPin" },
- { 0x24, "transparent" },
- { 0x25, "addMax" },
- { 0x26, "subOver" },
- { 0x27, "addMin" },
- { 0x31, "grayishTextOr" },
- { 0x32, "hilite" },
- { 0x40, "ditherCopy" },
- { 0x100, "Alpha" },
- { 0x101, "White Alpha" },
- { 0x102, "Pre-multiplied Black Alpha" },
- { 0x110, "Component Alpha" }
- };
-
-
- extern const TagVocabulary userDatatags[] = {
- { "AllF", "PlayAllFrames" },
- { "CNCV", "CompressorVersion" },
- { "CNFV", "FirmwareVersion" },
- { "CNMN", "Model" },
- { "CNTH", "CanonCNTH" },
- { "DcMD", "DcMD" },
- { "FFMV", "FujiFilmFFMV" },
- { "INFO", "SamsungINFO" },
- { "LOOP", "LoopStyle" },
- { "MMA0", "MinoltaMMA0" },
- { "MMA1", "MinoltaMMA1" },
- { "MVTG", "FujiFilmMVTG" },
- { "NCDT", "NikonNCDT" },
- { "PANA", "PanasonicPANA" },
- { "PENT", "PentaxPENT" },
- { "PXMN", "MakerNotePentax5b" },
- { "PXTH", "PentaxPreview" },
- { "QVMI", "CasioQVMI" },
- { "SDLN", "PlayMode" },
- { "SelO", "PlaySelection" },
- { "TAGS", "KodakTags/KonicaMinoltaTags/MinoltaTags/NikonTags/OlympusTags/PentaxTags/SamsungTags/SanyoMOV/SanyoMP4" },
- { "WLOC", "WindowLocation" },
- { "XMP_", "XMP" },
- { "Xtra", "Xtra" },
- { "hinf", "HintTrackInfo" },
- { "hinv", "HintVersion" },
- { "hnti", "Hint" },
- { "meta", "Meta" },
- { "name", "Name" },
- { "ptv ", "PrintToVideo" },
- { "scrn", "OlympusPreview" },
- { "thmb", "MakerNotePentax5a/OlympusThumbnail" },
- };
-
- extern const TagVocabulary userDataReferencetags[] = {
- { "CNCV", "Xmp.video.CompressorVersion" },
- { "CNFV", "Xmp.video.FirmwareVersion" },
- { "CNMN", "Xmp.video.Model" },
- { "NCHD", "Xmp.video.MakerNoteType" },
- { "WLOC", "Xmp.video.WindowLocation" },
- { "SDLN", "Xmp.video.PlayMode" },
- { "FFMV", "Xmp.video.StreamName" },
- { "SelO", "Xmp.video.PlaySelection" },
- { "name", "Xmp.video.Name" },
- { "vndr", "Xmp.video.Vendor" },
- { " ART", "Xmp.video.Artist" },
- { " alb", "Xmp.video.Album" },
- { " arg", "Xmp.video.Arranger" },
- { " ark", "Xmp.video.ArrangerKeywords" },
- { " cmt", "Xmp.video.Comment" },
- { " cok", "Xmp.video.ComposerKeywords" },
- { " com", "Xmp.video.Composer" },
- { " cpy", "Xmp.video.Copyright" },
- { " day", "Xmp.video.CreateDate" },
- { " dir", "Xmp.video.Director" },
- { " ed1", "Xmp.video.Edit1" },
- { " ed2", "Xmp.video.Edit2" },
- { " ed3", "Xmp.video.Edit3" },
- { " ed4", "Xmp.video.Edit4" },
- { " ed5", "Xmp.video.Edit5" },
- { " ed6", "Xmp.video.Edit6" },
- { " ed7", "Xmp.video.Edit7" },
- { " ed8", "Xmp.video.Edit8" },
- { " ed9", "Xmp.video.Edit9" },
- { " enc", "Xmp.video.Encoder" },
- { " fmt", "Xmp.video.Format" },
- { " gen", "Xmp.video.Genre" },
- { " grp", "Xmp.video.Grouping" },
- { " inf", "Xmp.video.Information" },
- { " isr", "Xmp.video.ISRCCode" },
- { " lab", "Xmp.video.RecordLabelName" },
- { " lal", "Xmp.video.RecordLabelURL" },
- { " lyr", "Xmp.video.Lyrics" },
- { " mak", "Xmp.video.Make" },
- { " mal", "Xmp.video.MakerURL" },
- { " mod", "Xmp.video.Model" },
- { " nam", "Xmp.video.Title" },
- { " pdk", "Xmp.video.ProducerKeywords" },
- { " phg", "Xmp.video.RecordingCopyright" },
- { " prd", "Xmp.video.Producer" },
- { " prf", "Xmp.video.Performers" },
- { " prk", "Xmp.video.PerformerKeywords" },
- { " prl", "Xmp.video.PerformerURL" },
- { " req", "Xmp.video.Requirements" },
- { " snk", "Xmp.video.SubtitleKeywords" },
- { " snm", "Xmp.video.Subtitle" },
- { " src", "Xmp.video.SourceCredits" },
- { " swf", "Xmp.video.SongWriter" },
- { " swk", "Xmp.video.SongWriterKeywords" },
- { " swr", "Xmp.video.SoftwareVersion" },
- { " too", "Xmp.video.Encoder" },
- { " trk", "Xmp.video.Track" },
- { " wrt", "Xmp.video.Composer" },
- { " xyz", "Xmp.video.GPSCoordinates" },
- { "CMbo", "Xmp.video.CameraByteOrder" },
- { "Cmbo", "Xmp.video.CameraByteOrder" },
- };
-
- extern const TagDetails NikonNCTGTags[] = {
- { 0x0001, "Xmp.video.Make" },
- { 0x0002, "Xmp.video.Model" },
- { 0x0003, "Xmp.video.Software" },
- { 0x0011, "Xmp.video.CreationDate" },
- { 0x0012, "Xmp.video.DateTimeOriginal" },
- { 0x0013, "Xmp.video.FrameCount" },
- { 0x0016, "Xmp.video.FrameRate" },
- { 0x0022, "Xmp.video.FrameWidth" },
- { 0x0023, "Xmp.video.FrameHeight" },
- { 0x0032, "Xmp.audio.channelType" },
- { 0x0033, "Xmp.audio.BitsPerSample" },
- { 0x0034, "Xmp.audio.sampleRate" },
- { 0x1108822, "Xmp.video.ExposureProgram" },
- { 0x1109204, "Xmp.video.ExposureCompensation" },
- { 0x1109207, "Xmp.video.MeteringMode" },
- { 0x110a434, "Xmp.video.LensModel" },
- { 0x1200000, "Xmp.video.GPSVersionID" },
- { 0x1200001, "Xmp.video.GPSLatitudeRef" },
- { 0x1200002, "Xmp.video.GPSLatitude" },
- { 0x1200003, "Xmp.video.GPSLongitudeRef" },
- { 0x1200004, "Xmp.video.GPSLongitude" },
- { 0x1200005, "Xmp.video.GPSAltitudeRef" },
- { 0x1200006, "Xmp.video.GPSAltitude" },
- { 0x1200007, "Xmp.video.GPSTimeStamp" },
- { 0x1200008, "Xmp.video.GPSSatellites" },
- { 0x1200010, "Xmp.video.GPSImgDirectionRef" },
- { 0x1200011, "Xmp.video.GPSImgDirection" },
- { 0x1200012, "Xmp.video.GPSMapDatum" },
- { 0x120001d, "Xmp.video.GPSDateStamp" },
- { 0x2000001, "Xmp.video.MakerNoteVersion" },
- { 0x2000005, "Xmp.video.WhiteBalance" },
- { 0x200000b, "Xmp.video.WhiteBalanceFineTune" },
- { 0x200001e, "Xmp.video.ColorSpace" },
- { 0x2000023, "Xmp.video.PictureControlData" },
- { 0x2000024, "Xmp.video.WorldTime" },
- { 0x200002c, "Xmp.video.UnknownInfo" },
- { 0x2000032, "Xmp.video.UnknownInfo2" },
- { 0x2000039, "Xmp.video.LocationInfo" },
- { 0x2000083, "Xmp.video.LensType" },
- { 0x2000084, "Xmp.video.LensModel" },
- { 0x20000ab, "Xmp.video.VariProgram" },
- };
-
- extern const TagDetails NikonColorSpace[] = {
- { 1, "sRGB" },
- { 2, "Adobe RGB" },
- };
-
- extern const TagVocabulary NikonGPS_Latitude_Longitude_ImgDirection_Reference[] = {
- { "N", "North" },
- { "S", "South" },
- { "E", "East" },
- { "W", "West" },
- { "M", "Magnetic North" },
- { "T", "True North" },
- };
-
- extern const TagDetails NikonGPSAltitudeRef[] = {
- { 0, "Above Sea Level" },
- { 1, "Below Sea Level" },
- };
-
- extern const TagDetails NikonExposureProgram[] = {
- { 0, "Not Defined" },
- { 1, "Manual" },
- { 2, "Program AE" },
- { 3, "Aperture-priority AE" },
- { 4, "Shutter speed priority AE" },
- { 5, "Creative (Slow speed)" },
- { 6, "Action (High speed)" },
- { 7, "Portrait" },
- { 8, "Landscape" },
- };
-
- extern const TagDetails NikonMeteringMode[] = {
- { 0, "Unknown" },
- { 1, "Average" },
- { 2, "Center-weighted average" },
- { 3, "Spot" },
- { 4, "Multi-spot" },
- { 5, "Multi-segment" },
- { 6, "Partial" },
- { 255, "Other" },
- };
-
- extern const TagDetails PictureControlAdjust[] = {
- { 0, "Default Settings" },
- { 1, "Quick Adjust" },
- { 2, "Full Control" },
- };
-
- //! Contrast and Sharpness
- extern const TagDetails NormalSoftHard[] = {
- { 0, "Normal" },
- { 1, "Soft" },
- { 2, "Hard" }
- };
-
- //! Saturation
- extern const TagDetails Saturation[] = {
- { 0, "Normal" },
- { 1, "Low" },
- { 2, "High" }
- };
-
- //! YesNo, used for DaylightSavings
- extern const TagDetails YesNo[] = {
- { 0, "No" },
- { 1, "Yes" }
- };
-
- //! DateDisplayFormat
- extern const TagDetails DateDisplayFormat[] = {
- { 0, "Y/M/D" },
- { 1, "M/D/Y" },
- { 2, "D/M/Y" }
- };
-
- extern const TagDetails FilterEffect[] = {
- { 0x80, "Off" },
- { 0x81, "Yellow" },
- { 0x82, "Orange" },
- { 0x83, "Red" },
- { 0x84, "Green" },
- { 0xff, "n/a" },
- };
-
- extern const TagDetails ToningEffect[] = {
- { 0x80, "B&W" },
- { 0x81, "Sepia" },
- { 0x82, "Cyanotype" },
- { 0x83, "Red" },
- { 0x84, "Yellow" },
- { 0x85, "Green" },
- { 0x86, "Blue-green" },
- { 0x87, "Blue" },
- { 0x88, "Purple-blue" },
- { 0x89, "Red-purple" },
- { 0xff, "n/a" },
- };
-
- extern const TagDetails whiteBalance[] = {
- { 0, "Auto" },
- { 1, "Daylight" },
- { 2, "Shade" },
- { 3, "Fluorescent" },
- { 4, "Tungsten" },
- { 5, "Manual" },
- };
-
- enum movieHeaderTags {
- MovieHeaderVersion, CreateDate, ModifyDate, TimeScale, Duration, PreferredRate, PreferredVolume,
- PreviewTime = 18, PreviewDuration,PosterTime, SelectionTime, SelectionDuration, CurrentTime, NextTrackID
- };
- enum trackHeaderTags {
- TrackHeaderVersion, TrackCreateDate, TrackModifyDate, TrackID, TrackDuration = 5, TrackLayer = 8,
- TrackVolume, ImageWidth = 19, ImageHeight
- };
- enum mediaHeaderTags {
- MediaHeaderVersion, MediaCreateDate, MediaModifyDate, MediaTimeScale, MediaDuration, MediaLanguageCode
- };
- enum handlerTags {
- HandlerClass = 1, HandlerType, HandlerVendorID
- };
- enum videoHeaderTags {
- GraphicsMode = 2, OpColor
- };
- enum stream {
- Video, Audio, Hint, Null, GenMediaHeader
- };
- enum imageDescTags {
- codec, VendorID = 4, SourceImageWidth_Height = 7, XResolution,
- YResolution, CompressorName = 10, BitDepth
- };
- enum audioDescTags {
- AudioFormat, AudioVendorID = 4, AudioChannels, AudioSampleRate = 7, MOV_AudioFormat = 13
- };
-
- /*!
- @brief Function used to check equality of a Tags with a
- particular string (ignores case while comparing).
- @param buf Data buffer that will contain Tag to compare
- @param str char* Pointer to string
- @return Returns true if the buffer value is equal to string.
- */
- bool equalsQTimeTag(Exiv2::DataBuf& buf ,const char* str) {
- for(int i = 0; i < 4; ++i)
- if(tolower(buf.pData_[i]) != tolower(str[i]))
- return false;
- return true;
+/*!
+ * \brief reverseTagVocabulary: reverse attributed of array elements.To perform reverse
+ * operation of getting keys from description
+ * \param inputTagVocabulary
+ * \param outputTagVocabulary
+ * \param size
+ */
+void reverseTagVocabulary(const TagVocabulary inputTagVocabulary[],TagVocabulary outputTagVocabulary[] ,int size)
+{
+ int32_t i;
+ for (i=0; i getNumberFromString(const std::string stringData,char seperator )
+{
+ int32_t counter = (stringData.size() - 1);
+ vector shortValues;
+ int32_t i;
+ for(i=0; i<2; i++){
+ int32_t tmpValueIndex = 3;
+ Exiv2::byte tmpValue[4] = {};
+ while((counter >= 0) && (stringData[counter] != seperator) && (tmpValueIndex >=0)){
+ tmpValue[tmpValueIndex] = stringData[counter];
+ counter--;tmpValueIndex--;
+ }
+ counter--;
+ shortValues.push_back((int16_t)Exiv2::getShort(tmpValue, bigEndian));
}
+ return shortValues;
+}
- /*!
- @brief Function used to ignore Tags, basically Tags which
- contain other tags inside them, since they are not necessary
- as metadata information
- @param buf Data buffer that will contain Tag to compare
- @return Returns true, if Tag is found in the ignoreList[]
- */
- bool dataIgnoreList (Exiv2::DataBuf& buf) {
- const char ignoreList[8][5] = {
- "moov", "mdia", "minf", "dinf", "alis", "stbl", "cmov",
- "meta",
- };
-
- for(int i = 0 ; i < 8 ; ++i)
- if(equalsQTimeTag(buf, ignoreList[i]))
- return true;
-
- return false;
+/*!
+ * \brief getLongFromString functionality is same as above method,with return type
+ * long vector
+ * \param stringData: stringdata which is formed by concatinating two distinct
+ * numerical values
+ * \param seperator: seperation character like . , etc
+ * \return
+ */
+const std::vector getLongFromString(const std::string stringData,char seperator )
+{
+ int32_t counter = (stringData.size() - 1);
+ vector longValues;
+ for(int32_t i=0; i<2; i++){
+ int32_t tmpValueIndex = 3;
+ Exiv2::byte tmpValue[4]={};
+ while((counter >= 0) && (stringData[counter] != seperator) && (tmpValueIndex >=0)){
+ tmpValue[tmpValueIndex] = stringData[counter];
+ counter--;tmpValueIndex--;
+ }
+ counter--;
+ longValues.push_back((int32_t)Exiv2::getLong(tmpValue, bigEndian));
}
+ return longValues;
+}
- /*!
- @brief Function used to convert buffer data into 64-bit
- signed integer, information stored in Big Endian format
- @param buf Data buffer that will contain data to be converted
- @return Returns a signed 64-bit integer
- */
- int64_t returnBufValue(Exiv2::DataBuf& buf, int n = 4) {
- int64_t temp = 0;
- for(int i = n - 1; i >= 0; i--)
-#ifdef _MSC_VER
- temp = temp + static_cast(buf.pData_[i]*(pow(static_cast(256), n-i-1)));
+/*!
+ @brief Function used to convert buffer data into 64-bit
+ signed integer, information stored in Big Endian format
+ @param buf Data buffer that will contain data to be converted
+ @param n
+ @return Returns a signed 64-bit integer
+ */
+int64_t returnBufValue(Exiv2::DataBuf& buf, int32_t n = 4)
+{
+ int64_t temp = 0;
+ for(int32_t i = n - 1; i >= 0; i--)
+ temp +=
+ #ifdef _MSC_VER
+ static_cast(buf.pData_[i]*(pow(256.0, n-i-1)));
#else
- temp = temp + buf.pData_[i]*(pow((float)256,n-i-1));
+ buf.pData_[i]*(pow((float)256,n-i-1));
#endif
+ return temp;
+}
- return temp;
- }
+/*!
+ * \brief returnBuf: converts integer value to byte value
+ * which can be written to the file.
+ * \param intValue
+ * \param n
+ * \return
+ */
+DataBuf returnBuf(int64_t intValue,int32_t n=4)
+{
+ DataBuf buf((uint32_t)(n+1));
+ for(int32_t i = n - 1; i >= 0; i--)
+ buf.pData_[i] = (Exiv2::byte)(int16_t) ((int32_t)(intValue / (int32_t)pow(256.0,n-i-1)) % 256);
+ return buf;
+}
- /*!
- @brief Function used to convert buffer data into 64-bit
- unsigned integer, information stored in Big Endian format
- @param buf Data buffer that will contain data to be converted
- @return Returns an unsigned 64-bit integer
- */
- uint64_t returnUnsignedBufValue(Exiv2::DataBuf& buf, int n = 4) {
- uint64_t temp = 0;
- for(int i = n-1; i >= 0; i--)
+/*!
+ @brief Function used to convert buffer data into 64-bit
+ unsigned integer, information stored in Big Endian format
+ @param buf Data buffer that will contain data to be converted
+ @param n
+ @return Returns an unsigned 64-bit integer
+ */
+uint64_t returnUnsignedBufValue(Exiv2::DataBuf& buf, int32_t n = 4)
+{
+ uint64_t temp = 0;
+ for(int32_t i = n-1; i >= 0; i--)
#if _MSC_VER
- temp = temp + static_cast(buf.pData_[i]*(pow(static_cast(256), n-i-1)));
+ temp = temp + static_cast(buf.pData_[i]*(pow(static_cast(256), n-i-1)));
#else
- temp = temp + buf.pData_[i]*(pow((float)256,n-i-1));
+ temp = temp + buf.pData_[i]*(pow((float)256,n-i-1));
#endif
- return temp;
- }
+ return temp;
+}
- /*!
- @brief Function used to quicktime files, by checking the
- the tags at the start of the file. If the Tag is any one
- of the tags listed below, then it is of Quicktime Type.
- @param a, b, c, d - characters used to compare
- @return Returns true, if Tag is found in the list qTimeTags
- */
- bool isQuickTimeType (char a, char b, char c, char d) {
- char qTimeTags[][5] = {
- "PICT", "free", "ftyp", "junk", "mdat",
- "moov", "pict", "pnot", "skip", "uuid", "wide"
- };
+/*!
+ * \brief returnUnsignedBuf converts integer value to byte value
+ * which can be written to the file.
+ * \param intValue
+ * \param n
+ * \return
+ */
+DataBuf returnUnsignedBuf(uint64_t intValue,int32_t n=4)
+{
+ DataBuf buf(n+1);
+ for(int32_t i = n - 1; i >= 0; i--)
+ buf.pData_[i] = (Exiv2::byte)(uint16_t) ((int32_t)(intValue / (int32_t)pow(256.0,n-i-1)) % 256);
+ return buf;
+}
+/*!
+ @brief Function used to quicktime files, by checking the
+ the tags at the start of the file. If the Tag is any one
+ of the tags listed below, then it is of Quicktime Type.
+ @param a, b, c, d - characters used to compare
+ @return Returns true, if Tag is found in the list qTimeTags
+ */
+bool isQuickTimeType (char a, char b, char c, char d)
+{
+ char qTimeTags[][5] ={
+ "PICT", "free", "ftyp", "junk", "mdat",
+ "moov", "pict", "pnot", "skip", "uuid", "wide"
+ };
- for(int i = 0; i <= 10; i++)
- if(a == qTimeTags[i][0] && b == qTimeTags[i][1] && c == qTimeTags[i][2] && d == qTimeTags[i][3])
- return true;
- return false;
- }
+ int32_t i;
+ for( i = 0; i <= 10; i++)
+ if(a == qTimeTags[i][0] && b == qTimeTags[i][1] && c == qTimeTags[i][2] && d == qTimeTags[i][3])
+ return true;
+ return false;
+} // isQuickTime
+} // namespace Internal
+} // namespace Exiv2
-}} // namespace Internal, Exiv2
+namespace Exiv2{
-namespace Exiv2 {
+using namespace Exiv2::Internal;
- using namespace Exiv2::Internal;
-
- QuickTimeVideo::QuickTimeVideo(BasicIo::AutoPtr io)
- : Image(ImageType::qtime, mdNone, io)
- {
- } // QuickTimeVideo::QuickTimeVideo
-
- std::string QuickTimeVideo::mimeType() const
- {
- return "video/quicktime";
- }
-
- void QuickTimeVideo::writeMetadata()
- {
- }
-
-
- void QuickTimeVideo::readMetadata()
- {
- if (io_->open() != 0) throw Error(9, io_->path(), strError());
-
- // Ensure that this is the correct image type
- if (!isQTimeType(*io_, false)) {
- if (io_->error() || io_->eof()) throw Error(14);
- throw Error(3, "QuickTime");
- }
-
- IoCloser closer(*io_);
- clearMetadata();
+class QuickTimeVideo::Private
+{
+public:
+ Private(){
+ timeScale_ = 0;
+ currentStream_ = 0;
continueTraversing_ = true;
- height_ = width_ = 1;
+ height_ = 1;
+ width_ = 1;
+ m_modifyMetadata = false;
+ m_decodeMetadata = true;
- xmpData_["Xmp.video.FileSize"] = (double)io_->size()/(double)1048576;
- xmpData_["Xmp.video.FileName"] = io_->path();
- xmpData_["Xmp.video.MimeType"] = mimeType();
+ decoders.insert(std::make_pair("ftyp",&QuickTimeVideo::fileTypeDecoder));
+ decoders.insert(std::make_pair("trak",&QuickTimeVideo::setMediaStream));
+ decoders.insert(std::make_pair("mvhd",&QuickTimeVideo::movieHeaderDecoder));
+ decoders.insert(std::make_pair("tkhd",&QuickTimeVideo::trackHeaderDecoder));
+ decoders.insert(std::make_pair("mdhd",&QuickTimeVideo::mediaHeaderDecoder));
+ decoders.insert(std::make_pair("hdlr",&QuickTimeVideo::handlerDecoder));
+ decoders.insert(std::make_pair("vmhd",&QuickTimeVideo::videoHeaderDecoder));
+ decoders.insert(std::make_pair("udta",&QuickTimeVideo::userDataDecoder));
+ decoders.insert(std::make_pair("stsd",&QuickTimeVideo::sampleDesc));
+ decoders.insert(std::make_pair("dref",&QuickTimeVideo::multipleEntriesDecoder));
+ decoders.insert(std::make_pair("stts",&QuickTimeVideo::timeToSampleDecoder));
+ decoders.insert(std::make_pair("pnot",&QuickTimeVideo::previewTagDecoder));
+ decoders.insert(std::make_pair("tapt",&QuickTimeVideo::trackApertureTagDecoder));
+ decoders.insert(std::make_pair("keys",&QuickTimeVideo::keysTagDecoder));
+ }
- while (continueTraversing_) decodeBlock();
+public:
+ //! Variable which stores Time Scale unit, used to calculate time.
+ uint64_t timeScale_;
+ //! Variable which stores current stream being processsed.
+ int currentStream_;
+ //! Variable to check the end of metadata traversing.
+ bool continueTraversing_;
+ //! Variable to store height and width of a video frame.
+ uint64_t height_, width_;
+ //! Variable to decide write(True)/read(False) metadata
+ bool m_modifyMetadata;
+ //! Variable to decide decode/skip metadata
+ bool m_decodeMetadata;
- aspectRatio();
- } // QuickTimeVideo::readMetadata
+ std::map decoders;
+ /*!
+ * \brief m_QuickSkeleton
+ * A container which hold the entire information about all premitive atoms inside quicktime
+ * structure
+ */
+ std::vector m_QuickSkeleton;
+}; // class QuickTimeVideo::Private
- void QuickTimeVideo::decodeBlock()
- {
- const long bufMinSize = 4;
- DataBuf buf(bufMinSize+1);
- unsigned long size = 0;
- buf.pData_[4] = '\0' ;
+QuickTimeVideo::QuickTimeVideo(BasicIo::AutoPtr io)
+ : Image(ImageType::qtime, mdNone, io), d(new Private)
+{
+ d->m_decodeMetadata = true;
+ d->m_modifyMetadata = false;
+}
- std::memset(buf.pData_, 0x0, buf.size_);
+QuickTimeVideo::~QuickTimeVideo()
+{
+ delete d;
+}
- io_->read(buf.pData_, 4);
- if(io_->eof()) {
- continueTraversing_ = false;
- return;
+/*!
+ * \brief QuickTimeVideo::findAtomPositions:
+ * This method can be called only after read operation,it will return
+ * list atom(multiple atoms with same atom Id)
+ * location and atom size,for a given atomId
+ * \param atomId
+ * \return
+ */
+std::vector< pair > QuickTimeVideo::findAtomPositions(const char* atomId)
+{
+ DataBuf hdrId((uint32_t)5);
+ hdrId.pData_[4] = '\0';
+
+ std::vector< pair > atomsDetails;
+ for (uint32_t i=0; i < d->m_QuickSkeleton.size();i++){
+ io_->seek((d->m_QuickSkeleton[i]->m_AtomLocation - 4),BasicIo::beg);
+ io_->read(hdrId.pData_,4);
+ if(UtilsVideo::compareTagValue(hdrId,atomId))
+ atomsDetails.push_back(make_pair((uint32_t)io_->tell(),
+ (uint32_t)(d->m_QuickSkeleton[i]->m_AtomSize)));
+ }
+ return atomsDetails;
+}
+
+std::string QuickTimeVideo::mimeType() const
+{
+ return "video/quicktime";
+}
+
+void QuickTimeVideo::writeMetadata()
+{
+ if (io_->open() != 0) throw Error(9, io_->path(), strError());
+
+ IoCloser closer(*io_);
+ doWriteMetadata();
+ io_->close();
+}
+
+/*!
+ * \brief QuickTimeVideo::doWriteMetadata
+ * Search for all the tags(effectively all supported tags in Exiv2)
+ * present in a file(in m_riffskeleton) and call corresponding handler
+ * method to write modified metadata.
+ */
+void QuickTimeVideo::doWriteMetadata()
+{
+ if (!io_->isopen()) throw Error(20);
+
+ // Ensure that this is the correct image type
+ if (!isQTimeType(*io_, false)){
+ if (io_->error() || io_->eof()) throw Error(14);
+ throw Error(3, "QuickTime");
+ }
+
+ d->m_decodeMetadata = false;
+ d->m_modifyMetadata = true;
+
+ std::vector atomFlags;
+
+ //Add new tags to the beginning of the container prmitiveFlags and handle conditions to the end of case statements.
+
+ atomFlags.push_back("stsd");
+ atomFlags.push_back("keys");
+ atomFlags.push_back("tapt");
+ atomFlags.push_back("pnot");
+ atomFlags.push_back("udta");
+ atomFlags.push_back("vmhd");
+ atomFlags.push_back("hdlr");
+ atomFlags.push_back("mdhd");
+ atomFlags.push_back("tkhd");
+ atomFlags.push_back("mvhd");
+ atomFlags.push_back("ftyp");
+
+ uint32_t iMaxCount = atomFlags.size();
+ std::vector< pair > trakPositions = findAtomPositions("trak");
+
+ for (uint32_t j=0; j > atomPositions = findAtomPositions(atomFlags.back().c_str());
+ atomFlags.pop_back();
+
+ for (uint32_t i=0; i< atomPositions.size(); i++){
+ if(j == 2 || j == 3 || j == 4 || j == 10){
+ io_->seek(trakPositions[i].first,BasicIo::beg);
+ setMediaStream(0);
+ }
+ io_->seek(atomPositions[i].first,BasicIo::beg);
+
+ uint32_t uiAtomPosition = atomPositions[i].second;
+ switch (j){
+ case 0: fileTypeDecoder(uiAtomPosition) ; break;
+ case 1: movieHeaderDecoder(uiAtomPosition) ; break;
+ case 2: trackHeaderDecoder(uiAtomPosition) ; break;
+ case 3: mediaHeaderDecoder(uiAtomPosition) ; break;
+ case 4: break;
+ // Fixme:Editing dandler data is known to corrupt file data
+ // handlerDecoder(hdlrPositions[i].second);
+ case 5: videoHeaderDecoder(uiAtomPosition) ; break;
+ case 6: userDataDecoder(uiAtomPosition) ; break;
+ case 7: previewTagDecoder(uiAtomPosition) ; break;
+ case 8: trackApertureTagDecoder(uiAtomPosition); break;
+ case 9:keysTagDecoder(uiAtomPosition) ; break;
+ case 10: sampleDesc(uiAtomPosition) ; break;
+ }
}
+ atomPositions.clear();
+ }
+}
- size = Exiv2::getULong(buf.pData_, bigEndian);
+void QuickTimeVideo::readMetadata()
+{
+ if (io_->open() != 0) throw Error(9, io_->path(), strError());
- io_->read(buf.pData_, 4);
- if(size < 8)
- return;
+ // Ensure that this is the correct image type
+ if (!isQTimeType(*io_, false)){
+ if (io_->error() || io_->eof()) throw Error(14);
+ throw Error(3, "QuickTime");
+ }
-// std::cerr<<"\nTag=>"<"<continueTraversing_ = true;
+ d->height_ = d->width_ = 1;
- void QuickTimeVideo::tagDecoder(Exiv2::DataBuf &buf, unsigned long size)
- {
- if (ignoreList(buf))
- discard(size);
+ xmpData_["Xmp.video.FileSize"] = (double)io_->size()/(double)1048576;
+ xmpData_["Xmp.video.FileName"] = io_->path();
+ xmpData_["Xmp.video.MimeType"] = mimeType();
- else if (dataIgnoreList(buf))
- decodeBlock();
+ while (d->continueTraversing_) decodeBlock();
+ aspectRatio();
+}
- else if (equalsQTimeTag(buf, "ftyp"))
- fileTypeDecoder(size);
+void QuickTimeVideo::decodeBlock()
+{
+ const int32_t bufMinSize = 4;
+ DataBuf buf(bufMinSize+1);
- else if (equalsQTimeTag(buf, "trak"))
- setMediaStream();
+ io_->read(buf.pData_, 4);
+ if(io_->eof()){
+ d->continueTraversing_ = false;
+ return;
+ }
- else if (equalsQTimeTag(buf, "mvhd"))
- movieHeaderDecoder(size);
+ uint32_t size = Exiv2::getULong(buf.pData_, bigEndian);
+ io_->read(buf.pData_, 4);
+ if(size < 8) return;
- else if (equalsQTimeTag(buf, "tkhd"))
- trackHeaderDecoder(size);
+ tagDecoder(buf,size-8);
+}
- else if (equalsQTimeTag(buf, "mdhd"))
- mediaHeaderDecoder(size);
+void QuickTimeVideo::tagDecoder(Exiv2::DataBuf &buf, uint32_t size)
+{
+ const char allAtomFlags[][5]={"ftyp","mvhd","trak","tkhd","mdhd","hdlr","vmhd","udta","dref","stsd","stts","pnot",
+ "tapt","keys","url ","urn ","dcom","smhd"};
+ if(equalsQTimeTag(buf,allAtomFlags,(int)(sizeof(allAtomFlags)/5))){
+ QuickAtom* tmpAtom = new QuickAtom();
+ tmpAtom->m_AtomLocation = io_->tell();
+ tmpAtom->m_AtomSize = size;
+ memcpy((Exiv2::byte* )tmpAtom->m_AtomId,(const Exiv2::byte*)buf.pData_,5);
+ d->m_QuickSkeleton.push_back(tmpAtom);
+ }
- else if (equalsQTimeTag(buf, "hdlr"))
- handlerDecoder(size);
+ decFunc decodetIter = d->decoders[std::string(reinterpret_cast(buf.pData_))];
- else if (equalsQTimeTag(buf, "vmhd"))
- videoHeaderDecoder(size);
+ if (ignoreList(buf) ) io_->seek(size, BasicIo::cur);
+ else if (dataIgnoreList(buf)) decodeBlock();
+ else if (decodetIter ) (this->*decodetIter)(size);
- else if (equalsQTimeTag(buf, "udta"))
- userDataDecoder(size);
-
- else if (equalsQTimeTag(buf, "dref"))
- multipleEntriesDecoder();
-
- else if (equalsQTimeTag(buf, "stsd"))
- sampleDesc(size);
-
- else if (equalsQTimeTag(buf, "stts"))
- timeToSampleDecoder();
-
- else if (equalsQTimeTag(buf, "pnot"))
- previewTagDecoder(size);
-
- else if (equalsQTimeTag(buf, "tapt"))
- trackApertureTagDecoder(size);
-
- else if (equalsQTimeTag(buf, "keys"))
- keysTagDecoder(size);
-
- else if (equalsQTimeTag(buf, "url ")) {
- io_->read(buf.pData_, size);
- if (currentStream_ == Video)
- xmpData_["Xmp.video.URL"] = Exiv2::toString(buf.pData_);
- else if (currentStream_ == Audio)
- xmpData_["Xmp.audio.URL"] = Exiv2::toString(buf.pData_);
+ // Decoders with lesser metadata
+ else if (UtilsVideo::compareTagValue(buf, "url ")){
+ if(!d->m_modifyMetadata) readAudVidStrData("URL", size);
+ else {
+ if(xmpData_["Xmp.video.URL"].count() > 0) writeStringData(xmpData_["Xmp.video.URL"],size);
+ else if ((d->currentStream_ == Audio) && (xmpData_["Xmp.audio.URL"].count() >0))
+ writeStringData(xmpData_["Xmp.audio.URL"],size);
+ else io_->seek(size,BasicIo::cur);
}
-
- else if (equalsQTimeTag(buf, "urn ")) {
- io_->read(buf.pData_, size);
- if (currentStream_ == Video)
- xmpData_["Xmp.video.URN"] = Exiv2::toString(buf.pData_);
- else if (currentStream_ == Audio)
- xmpData_["Xmp.audio.URN"] = Exiv2::toString(buf.pData_);
+ }
+ else if (UtilsVideo::compareTagValue(buf, "urn ")){
+ if(!d->m_modifyMetadata) readAudVidStrData("URN", size);
+ else {
+ if ((d->currentStream_ == Video) && (xmpData_["Xmp.video.URN"].count() >0)) writeStringData(xmpData_["Xmp.video.URN"],size);
+ else if ((d->currentStream_ == Audio) && (xmpData_["Xmp.audio.URN"].count() >0)) writeStringData(xmpData_["Xmp.audio.URN"],size);
+ else io_->seek(size,BasicIo::cur);
}
-
- else if (equalsQTimeTag(buf, "dcom")) {
+ }
+ else if (UtilsVideo::compareTagValue(buf, "dcom")){
+ if(!d->m_modifyMetadata){
io_->read(buf.pData_, size);
xmpData_["Xmp.video.Compressor"] = Exiv2::toString(buf.pData_);
}
-
- else if (equalsQTimeTag(buf, "smhd")) {
- io_->read(buf.pData_, 4);
+ else writeStringData(xmpData_["Xmp.video.Compressor"],size);
+ }
+ else if (UtilsVideo::compareTagValue(buf, "smhd")){
+ io_->seek(4,BasicIo::cur);
+ if(!d->m_modifyMetadata){
io_->read(buf.pData_, 4);
xmpData_["Xmp.audio.Balance"] = returnBufValue(buf, 2);
+ } else {
+ DataBuf tmpBuf = returnBuf(xmpData_["Xmp.audio.Balance"].toLong());
+ io_->write(tmpBuf.pData_,2);
}
+ }
+ else io_->seek(size, BasicIo::cur);
+}
- else {
- discard(size);
- }
- } // QuickTimeVideo::tagDecoder
-
- void QuickTimeVideo::discard(unsigned long size)
- {
- uint64_t cur_pos = io_->tell();
- io_->seek(cur_pos + size, BasicIo::beg);
- } // QuickTimeVideo::discard
-
- void QuickTimeVideo::previewTagDecoder(unsigned long size)
- {
- DataBuf buf(4);
- uint64_t cur_pos = io_->tell();
+void QuickTimeVideo::previewTagDecoder(uint32_t size)
+{
+ DataBuf buf(4);
+ uint64_t cur_pos = io_->tell();
+ if(!d->m_modifyMetadata){
io_->read(buf.pData_, 4);
xmpData_["Xmp.video.PreviewDate"] = getULong(buf.pData_, bigEndian);
io_->read(buf.pData_, 2);
xmpData_["Xmp.video.PreviewVersion"] = getShort(buf.pData_, bigEndian);
io_->read(buf.pData_, 4);
- if(equalsQTimeTag(buf, "PICT"))
+ if(UtilsVideo::compareTagValue(buf, "PICT"))
xmpData_["Xmp.video.PreviewAtomType"] = "QuickDraw Picture";
else
xmpData_["Xmp.video.PreviewAtomType"] = Exiv2::toString(buf.pData_);
io_->seek(cur_pos + size, BasicIo::beg);
- } // QuickTimeVideo::previewTagDecoder
+ } else {
+ writeLongData(xmpData_["Xmp.video.PreviewDate"]);
+ writeShortData(xmpData_["Xmp.video.PreviewVersion"]);
- void QuickTimeVideo::keysTagDecoder(unsigned long size)
- {
- DataBuf buf(4);
- uint64_t cur_pos = io_->tell();
+ //Variation
+ if(xmpData_["Xmp.video.PreviewAtomType"].count() >0){
+ Exiv2::byte rawPreviewAtomType[4] = {'P','I','C','T'};
+ const std::string previewAtomType = xmpData_["Xmp.video.PreviewAtomType"].toString();
+ if(!(previewAtomType.compare("QuickDraw Picture") == 0))
+ for(int32_t j=0; j<4; j++) rawPreviewAtomType[j] = previewAtomType[j];
+
+ writeMultibyte(rawPreviewAtomType, 4);
+ }
+ io_->seek(cur_pos + size, BasicIo::beg);
+ }
+}
+
+void QuickTimeVideo::keysTagDecoder(uint32_t size)
+{
+ DataBuf buf(4);
+ uint64_t cur_pos = io_->tell();
+
+ if(!d->m_modifyMetadata){
io_->read(buf.pData_, 4);
xmpData_["Xmp.video.PreviewDate"] = getULong(buf.pData_, bigEndian);
io_->read(buf.pData_, 2);
xmpData_["Xmp.video.PreviewVersion"] = getShort(buf.pData_, bigEndian);
io_->read(buf.pData_, 4);
- if(equalsQTimeTag(buf, "PICT"))
- xmpData_["Xmp.video.PreviewAtomType"] = "QuickDraw Picture";
- else
- xmpData_["Xmp.video.PreviewAtomType"] = Exiv2::toString(buf.pData_);
-
+ if(UtilsVideo::compareTagValue(buf, "PICT")) xmpData_["Xmp.video.PreviewAtomType"] = "QuickDraw Picture";
+ else xmpData_["Xmp.video.PreviewAtomType"] = Exiv2::toString(buf.pData_);
io_->seek(cur_pos + size, BasicIo::beg);
- } // QuickTimeVideo::keysTagDecoder
+ } else {
+ writeLongData(xmpData_["Xmp.video.PreviewDate"]);
+ writeShortData(xmpData_["Xmp.video.PreviewVersion"]);
- void QuickTimeVideo::trackApertureTagDecoder(unsigned long size)
- {
- DataBuf buf(4), buf2(2);
- uint64_t cur_pos = io_->tell();
- byte n = 3;
+ //Variation
+ if(xmpData_["Xmp.video.PreviewAtomType"].count() >0){
+ Exiv2::byte rawPreviewAtomType[4] = {'P','I','C','T'};
+ const std::string previewAtomType = xmpData_["Xmp.video.PreviewAtomType"].toString();
+ if(!(previewAtomType.compare("QuickDraw Picture") == 0))
+ for(int32_t j=0; j<4; j++)
+ rawPreviewAtomType[j] = previewAtomType[j];
- while(n--) {
- io_->seek(static_cast(4), BasicIo::cur); io_->read(buf.pData_, 4);
+ writeMultibyte(rawPreviewAtomType, 4);
+ }
+ io_->seek(cur_pos + size, BasicIo::beg);
+ }
+}
- if(equalsQTimeTag(buf, "clef")) {
- io_->seek(static_cast(4), BasicIo::cur);
+void QuickTimeVideo::trackApertureTagDecoder(uint32_t size)
+{
+ DataBuf buf(4), buf2(2);
+ uint64_t cur_pos = io_->tell();
+ if(!d->m_modifyMetadata){
+ Exiv2::byte n = 3;
+ while(n--){
+ io_->seek(static_cast(4), BasicIo::cur); io_->read(buf.pData_, 4);
+
+ if(UtilsVideo::compareTagValue(buf, "clef")){
+ io_->seek(static_cast(4), BasicIo::cur);
io_->read(buf.pData_, 2); io_->read(buf2.pData_, 2);
- xmpData_["Xmp.video.CleanApertureWidth"] = Exiv2::toString(getUShort(buf.pData_, bigEndian))
- + "." + Exiv2::toString(getUShort(buf2.pData_, bigEndian));
+ xmpData_["Xmp.video.CleanApertureWidth"] = Exiv2::toString(getUShort(buf.pData_, bigEndian))
+ + "." + Exiv2::toString(getUShort(buf2.pData_, bigEndian));
io_->read(buf.pData_, 2); io_->read(buf2.pData_, 2);
- xmpData_["Xmp.video.CleanApertureHeight"] = Exiv2::toString(getUShort(buf.pData_, bigEndian))
- + "." + Exiv2::toString(getUShort(buf2.pData_, bigEndian));
+ xmpData_["Xmp.video.CleanApertureHeight"] = Exiv2::toString(getUShort(buf.pData_, bigEndian))
+ + "." + Exiv2::toString(getUShort(buf2.pData_, bigEndian));
}
-
- else if(equalsQTimeTag(buf, "prof")) {
- io_->seek(static_cast(4), BasicIo::cur);
+ else if(UtilsVideo::compareTagValue(buf, "prof")){
+ io_->seek(static_cast(4), BasicIo::cur);
io_->read(buf.pData_, 2); io_->read(buf2.pData_, 2);
- xmpData_["Xmp.video.ProductionApertureWidth"] = Exiv2::toString(getUShort(buf.pData_, bigEndian))
- + "." + Exiv2::toString(getUShort(buf2.pData_, bigEndian));
+ xmpData_["Xmp.video.ProductionApertureWidth"] = Exiv2::toString(getUShort(buf.pData_, bigEndian))
+ + "." + Exiv2::toString(getUShort(buf2.pData_, bigEndian));
io_->read(buf.pData_, 2); io_->read(buf2.pData_, 2);
- xmpData_["Xmp.video.ProductionApertureHeight"] = Exiv2::toString(getUShort(buf.pData_, bigEndian))
- + "." + Exiv2::toString(getUShort(buf2.pData_, bigEndian));
+ xmpData_["Xmp.video.ProductionApertureHeight"] = Exiv2::toString(getUShort(buf.pData_, bigEndian))
+ + "." + Exiv2::toString(getUShort(buf2.pData_, bigEndian));
}
-
- else if(equalsQTimeTag(buf, "enof")) {
- io_->seek(static_cast(4), BasicIo::cur);
+ else if(UtilsVideo::compareTagValue(buf, "enof")){
+ io_->seek(static_cast(4), BasicIo::cur);
io_->read(buf.pData_, 2); io_->read(buf2.pData_, 2);
- xmpData_["Xmp.video.EncodedPixelsWidth"] = Exiv2::toString(getUShort(buf.pData_, bigEndian))
- + "." + Exiv2::toString(getUShort(buf2.pData_, bigEndian));
+ xmpData_["Xmp.video.EncodedPixelsWidth"] = Exiv2::toString(getUShort(buf.pData_, bigEndian))
+ + "." + Exiv2::toString(getUShort(buf2.pData_, bigEndian));
io_->read(buf.pData_, 2); io_->read(buf2.pData_, 2);
- xmpData_["Xmp.video.EncodedPixelsHeight"] = Exiv2::toString(getUShort(buf.pData_, bigEndian))
- + "." + Exiv2::toString(getUShort(buf2.pData_, bigEndian));
+ xmpData_["Xmp.video.EncodedPixelsHeight"] = Exiv2::toString(getUShort(buf.pData_, bigEndian))
+ + "." + Exiv2::toString(getUShort(buf2.pData_, bigEndian));
}
}
- io_->seek(static_cast(cur_pos + size), BasicIo::beg);
- } // QuickTimeVideo::trackApertureTagDecoder
+ io_->seek(static_cast(cur_pos + size), BasicIo::beg);
+ } else {
+ Exiv2::byte n = 3;
+ while(n--){
+ io_->seek(static_cast(4), BasicIo::cur); io_->read(buf.pData_, 4);
- void QuickTimeVideo::CameraTagsDecoder(unsigned long size_external)
- {
- uint64_t cur_pos = io_->tell();
- DataBuf buf(50), buf2(4);
- const TagDetails* td;
+ if(UtilsVideo::compareTagValue(buf, "clef")){
+ io_->seek(static_cast(4), BasicIo::cur);
+ writeApertureData(xmpData_["Xmp.video.CleanApertureWidth"],4);
+ writeApertureData(xmpData_["Xmp.video.CleanApertureHeight"],4);
+ }
+ else if(UtilsVideo::compareTagValue(buf, "prof")){
+ io_->seek(static_cast(4), BasicIo::cur);
+ writeApertureData(xmpData_["Xmp.video.ProductionApertureWidth"],4);
+ writeApertureData(xmpData_["Xmp.video.ProductionApertureHeight"],4);
+ }
+ else if(UtilsVideo::compareTagValue(buf, "enof")){
+ io_->seek(static_cast(4), BasicIo::cur);
+ writeApertureData(xmpData_["Xmp.video.EncodedPixelsWidth"],4);
+ writeApertureData(xmpData_["Xmp.video.EncodedPixelsHeight"],4);
+ }
+ }
+ io_->seek(static_cast(cur_pos + size), BasicIo::beg);
+ }
+}
- io_->read(buf.pData_, 4);
- if(equalsQTimeTag(buf, "NIKO")) {
- io_->seek(cur_pos, BasicIo::beg);
-
- io_->read(buf.pData_, 24);
- xmpData_["Xmp.video.Make"] = Exiv2::toString(buf.pData_);
- io_->read(buf.pData_, 14);
- xmpData_["Xmp.video.Model"] = Exiv2::toString(buf.pData_);
+void QuickTimeVideo::CameraTagsDecoder(uint32_t size_external)
+{
+ uint64_t cur_pos = io_->tell();
+ DataBuf buf(50), buf2(4);
+ const TagDetails* td;
+ const RevTagDetails* rtd;
+ io_->read(buf.pData_, 4);
+ if(UtilsVideo::compareTagValue(buf, "NIKO")){
+ io_->seek(cur_pos, BasicIo::beg);
+ if(!d->m_modifyMetadata){
+ readStrData("Xmp.video.Make", 24);
+ readStrData("Xmp.video.Model", 14);
io_->read(buf.pData_, 4);
xmpData_["Xmp.video.ExposureTime"] = "1/" + Exiv2::toString( ceil( getULong(buf.pData_, littleEndian) / (double)10));
- io_->read(buf.pData_, 4); io_->read(buf2.pData_, 4);
- xmpData_["Xmp.video.FNumber"] = getULong(buf.pData_, littleEndian) / (double)getULong(buf2.pData_, littleEndian) ;
- io_->read(buf.pData_, 4); io_->read(buf2.pData_, 4);
+ io_->read(buf.pData_, 4);
+ io_->read(buf2.pData_, 4);
+ xmpData_["Xmp.video.FNumber"] = getULong(buf.pData_, littleEndian) / (double)getULong(buf2.pData_, littleEndian) ;
+ io_->read(buf.pData_, 4);
+ io_->read(buf2.pData_, 4);
xmpData_["Xmp.video.ExposureCompensation"] = getULong(buf.pData_, littleEndian) / (double)getULong(buf2.pData_, littleEndian) ;
- io_->read(buf.pData_, 10); io_->read(buf.pData_, 4);
+ io_->read(buf.pData_, 10);
+ io_->read(buf.pData_, 4);
td = find(whiteBalance, getULong(buf.pData_, littleEndian));
- if (td)
- xmpData_["Xmp.video.WhiteBalance"] = exvGettext(td->label_);
- io_->read(buf.pData_, 4); io_->read(buf2.pData_, 4);
- xmpData_["Xmp.video.FocalLength"] = getULong(buf.pData_, littleEndian) / (double)getULong(buf2.pData_, littleEndian) ;
- io_->seek(static_cast(95), BasicIo::cur);
- io_->read(buf.pData_, 48);
- xmpData_["Xmp.video.Software"] = Exiv2::toString(buf.pData_);
+ if (td) xmpData_["Xmp.video.WhiteBalance"] = exvGettext(td->label_);
+ io_->read(buf.pData_, 4);
+ io_->read(buf2.pData_, 4);
+ xmpData_["Xmp.video.FocalLength"] = getULong(buf.pData_, littleEndian) / (double)getULong(buf2.pData_, littleEndian) ;
+ io_->seek(static_cast(95), BasicIo::cur);
+ readStrData("Xmp.video.Software", 48);
io_->read(buf.pData_, 4);
xmpData_["Xmp.video.ISO"] = getULong(buf.pData_, littleEndian);
+ io_->seek(cur_pos + size_external, BasicIo::beg);
+ } else {
+ bool bDataWritten = false;
+ RevTagDetails revTagDetails[(sizeof(whiteBalance)/sizeof(whiteBalance[0]))];
+ reverseTagDetails(whiteBalance,revTagDetails,((sizeof(whiteBalance)/sizeof(whiteBalance[0]))));
+
+ writeShortData(xmpData_["Xmp.video.Make"],24);
+ writeShortData(xmpData_["Xmp.video.Model"],24);
+
+ //Variation
+ if(xmpData_["Xmp.video.ExposureTime"].count() >0){
+ const std::vector d_exposureTime =
+ getLongFromString(xmpData_["Xmp.video.ExposureTime"].toString(),'/');
+ const int32_t tmpValue = (d_exposureTime.at(1)*10);
+ io_->write((Exiv2::byte*)&tmpValue,4);
+ }
+ else io_->seek(4,BasicIo::cur);
+
+ //Variation
+ if(xmpData_["Xmp.video.FNumber"].count() >0){
+ io_->seek(4,BasicIo::cur);
+ io_->read(buf2.pData_,4);
+ io_->seek(-8,BasicIo::cur);
+ const int32_t fNumber =(int32_t)
+ ((double)xmpData_["Xmp.video.FNumber"].toLong()
+ *(double)getULong(buf2.pData_, littleEndian));
+ writeMultibyte((Exiv2::byte*)&fNumber, 4, 4);
+ }
+ else io_->seek(8,BasicIo::cur);
+
+ if(xmpData_["Xmp.video.ExposureCompensation"].count() >0){
+ io_->seek(4,BasicIo::cur);
+ io_->read(buf2.pData_,4);
+ io_->seek(-8,BasicIo::cur);
+ const int32_t exposureCompensation =(int32_t)
+ ((double)xmpData_["Xmp.video.ExposureCompensation"].toLong()
+ *(double)getULong(buf2.pData_, littleEndian));
+ writeMultibyte((Exiv2::byte*)&exposureCompensation, 4, 14);
+ }
+ else io_->seek(18,BasicIo::cur);
+
+ if(xmpData_["Xmp.video.WhiteBalance"].count() >0){
+ rtd = find(revTagDetails,xmpData_["Xmp.video.WhiteBalance"].toString());
+ if(rtd){
+ const int32_t sWhiteBalance = (int32_t)rtd->val_;
+ bDataWritten = writeMultibyte((Exiv2::byte*)&sWhiteBalance,4);
+ }
+ }
+ if(!bDataWritten) io_->seek(4,BasicIo::cur);
+
+ if(xmpData_["Xmp.video.FocalLength"].count() >0){
+ io_->seek(4,BasicIo::cur);
+ io_->read(buf2.pData_,4);
+ io_->seek(-8,BasicIo::cur);
+ const int32_t focalLength =(int32_t)((double)xmpData_["Xmp.video.FocalLength"].toLong()
+ *(double)getULong(buf2.pData_, littleEndian));
+ writeMultibyte((Exiv2::byte*)&focalLength, 4, 99);
+ }
+ else io_->seek(103,BasicIo::cur);
+
+ writeStringData(xmpData_["Xmp.video.Software"],48);
+ writeLongData(xmpData_["Xmp.video.ISO"]);
}
io_->seek(cur_pos + size_external, BasicIo::beg);
- } // QuickTimeVideo::CameraTagsDecoder
+ }
+}
- void QuickTimeVideo::userDataDecoder(unsigned long size_external)
- {
- uint64_t cur_pos = io_->tell();
- const TagVocabulary* td;
- const TagVocabulary* tv, *tv_internal;
-
- const long bufMinSize = 100;
- DataBuf buf(bufMinSize);
- unsigned long size = 0, size_internal = size_external;
- std::memset(buf.pData_, 0x0, buf.size_);
-
- while((size_internal/4 != 0) && (size_internal > 0)) {
+void QuickTimeVideo::userDataDecoder(uint32_t size_external)
+{
+ uint64_t cur_pos = io_->tell();
+ const TagVocabulary* td;
+ const TagVocabulary* tv;
+ const TagVocabulary* tv_internal;
+ const int32_t bufMinSize = 100;
+ DataBuf buf(bufMinSize);
+ uint32_t size = 0;
+ uint32_t size_internal = size_external;
+ if(!d->m_modifyMetadata){
+ while((size_internal/4 != 0) && (size_internal > 0)){
buf.pData_[4] = '\0' ;
io_->read(buf.pData_, 4);
size = Exiv2::getULong(buf.pData_, bigEndian);
- if(size > size_internal)
- break;
+ if(size > size_internal) break;
size_internal -= size;
io_->read(buf.pData_, 4);
- if(buf.pData_[0] == 169)
- buf.pData_[0] = ' ';
+ if(buf.pData_[0] == 169) buf.pData_[0] = ' ';
td = find(userDatatags, Exiv2::toString( buf.pData_));
tv = find(userDataReferencetags, Exiv2::toString( buf.pData_));
- if(size == 0 || (size - 12) <= 0)
- break;
-
- else if(equalsQTimeTag(buf, "DcMD") || equalsQTimeTag(buf, "NCDT"))
- userDataDecoder(size - 8);
-
- else if(equalsQTimeTag(buf, "NCTG"))
- NikonTagsDecoder(size - 8);
-
- else if(equalsQTimeTag(buf, "TAGS"))
- CameraTagsDecoder(size - 8);
-
- else if(equalsQTimeTag(buf, "CNCV") || equalsQTimeTag(buf, "CNFV")
- || equalsQTimeTag(buf, "CNMN") || equalsQTimeTag(buf, "NCHD")
- || equalsQTimeTag(buf, "FFMV")) {
- io_->read(buf.pData_, size - 8);
- xmpData_[exvGettext(tv->label_)] = Exiv2::toString(buf.pData_);
+ if (size == 0 || (size - 12) <= 0) break;
+ else if(UtilsVideo::compareTagValue(buf, "DcMD") || UtilsVideo::compareTagValue(buf, "NCDT")) userDataDecoder(size - 8);
+ else if(UtilsVideo::compareTagValue(buf, "NCTG")) NikonTagsDecoder(size - 8);
+ else if(UtilsVideo::compareTagValue(buf, "TAGS")) CameraTagsDecoder(size - 8);
+ else if(UtilsVideo::compareTagValue(buf, "CNCV") || UtilsVideo::compareTagValue(buf, "CNFV")
+ || UtilsVideo::compareTagValue(buf, "CNMN") || UtilsVideo::compareTagValue(buf, "NCHD")
+ || UtilsVideo::compareTagValue(buf, "FFMV")){
+ readStrData((std::string)exvGettext(tv->label_) , size - 8);
}
-
- else if(equalsQTimeTag(buf, "CMbo") || equalsQTimeTag(buf, "Cmbo")) {
+ else if(UtilsVideo::compareTagValue(buf, "CMbo") || UtilsVideo::compareTagValue(buf, "Cmbo")){
io_->read(buf.pData_, 2);
buf.pData_[2] = '\0' ;
tv_internal = find(cameraByteOrderTags, Exiv2::toString( buf.pData_));
- if (tv_internal)
- xmpData_[exvGettext(tv->label_)] = exvGettext(tv_internal->label_);
- else
- xmpData_[exvGettext(tv->label_)] = Exiv2::toString(buf.pData_);
+ if (tv_internal) xmpData_[exvGettext(tv->label_)] = exvGettext(tv_internal->label_);
+ else xmpData_[exvGettext(tv->label_)] = Exiv2::toString(buf.pData_);
}
-
- else if(tv) {
- io_->read(buf.pData_, 4);
- io_->read(buf.pData_, size-12);
+ else if(tv){
+ io_->read(buf.pData_, size-8);
xmpData_[exvGettext(tv->label_)] = Exiv2::toString(buf.pData_);
}
-
- else if(td)
- tagDecoder(buf,size-8);
+ else if(td) tagDecoder(buf,size-8);
}
-
io_->seek(cur_pos + size_external, BasicIo::beg);
- } // QuickTimeVideo::userDataDecoder
+ } else {
+ while((size_internal/4 != 0) && (size_internal > 0)){
+ buf.pData_[4] = '\0' ;
+ io_->read(buf.pData_, 4);
+ size = Exiv2::getULong(buf.pData_, bigEndian);
+ if(size > size_internal) break;
+ size_internal -= size;
+ io_->read(buf.pData_, 4);
+ if(buf.pData_[0] == 169) buf.pData_[0] = ' ';
+ td = find(userDatatags, Exiv2::toString( buf.pData_));
+ tv = find(userDataReferencetags, Exiv2::toString( buf.pData_));
+ if (size == 0 || (size - 12) <= 0) break; // size <= 12?
+ else if(UtilsVideo::compareTagValue(buf, "DcMD") || UtilsVideo::compareTagValue(buf, "NCDT")) userDataDecoder(size - 8);
+ else if(UtilsVideo::compareTagValue(buf, "NCTG")) NikonTagsDecoder(size - 8);
+ else if(UtilsVideo::compareTagValue(buf, "TAGS")) CameraTagsDecoder(size - 8);
+ else if(UtilsVideo::compareTagValue(buf, "CNCV") || UtilsVideo::compareTagValue(buf, "CNFV")
+ || UtilsVideo::compareTagValue(buf, "CNMN") || UtilsVideo::compareTagValue(buf, "NCHD")
+ || UtilsVideo::compareTagValue(buf, "FFMV")
+ ) writeShortData(xmpData_[exvGettext(tv->label_)],(size-8));
+ else if(UtilsVideo::compareTagValue(buf, "CMbo") || UtilsVideo::compareTagValue(buf, "Cmbo")) io_->seek(2,BasicIo::cur);
+ else if(tv) writeShortData(xmpData_[exvGettext(tv->label_)],(size-8));
+ }
+ io_->seek(cur_pos + size_external, BasicIo::beg);
+ }
+}
- void QuickTimeVideo::NikonTagsDecoder(unsigned long size_external)
- {
- uint64_t cur_pos = io_->tell();
- DataBuf buf(200), buf2(4+1);
- unsigned long TagID = 0;
- unsigned short dataLength = 0, dataType = 2;
- const TagDetails* td, *td2;
+void QuickTimeVideo::NikonTagsDecoder(uint32_t size_external)
+{
+ uint64_t cur_pos = io_->tell();
+ DataBuf buf(200);
+ DataBuf buf2(4+1);
+ uint64_t TagID = 0 ;
+ uint16_t dataLength = 0 ;
+ uint16_t dataType = 2 ;
+ const TagDetails* td ;
+ const TagDetails* td2 ;
+ const RevTagDetails* rtd2;
- for(int i = 0 ; i < 100 ; i++) {
+ if(!d->m_modifyMetadata){
+ for(int32_t i = 0 ; i < 100 ; i++){
+ io_->read(buf.pData_, 4);
+ TagID = Exiv2::getULong(buf.pData_, bigEndian);
+ td = find(NikonNCTGTags, TagID);
+
+ io_->read(buf.pData_, 2);
+ dataType = Exiv2::getUShort(buf.pData_, bigEndian);
+
+ io_->read(buf.pData_, 2);
+
+ if(TagID == 0x2000023){
+ uint64_t local_pos = io_->tell();
+ dataLength = Exiv2::getUShort(buf.pData_, bigEndian);
+ std::memset(buf.pData_, 0x0, buf.size_);
+
+ io_->read(buf.pData_, 4); xmpData_["Xmp.video.PictureControlVersion"] = Exiv2::toString(buf.pData_);
+ io_->read(buf.pData_, 20); xmpData_["Xmp.video.PictureControlName"] = Exiv2::toString(buf.pData_);
+ io_->read(buf.pData_, 20); xmpData_["Xmp.video.PictureControlBase"] = Exiv2::toString(buf.pData_);
+ io_->read(buf.pData_, 4);
+ std::memset(buf.pData_, 0x0, buf.size_);
+
+ io_->read(buf.pData_, 1);
+ td2 = find(PictureControlAdjust, (int)buf.pData_[0] & 7 );
+ if(td2) xmpData_["Xmp.video.PictureControlAdjust"] = exvGettext(td2->label_);
+ else xmpData_["Xmp.video.PictureControlAdjust"] = (int)buf.pData_[0] & 7 ;
+
+ io_->read(buf.pData_, 1);
+ td2 = find(NormalSoftHard, (int)buf.pData_[0] & 7 );
+ if(td2) xmpData_["Xmp.video.PictureControlQuickAdjust"] = exvGettext(td2->label_);
+
+ io_->read(buf.pData_, 1);
+ td2 = find(NormalSoftHard, (int)buf.pData_[0] & 7 );
+ if(td2) xmpData_["Xmp.video.Sharpness"] = exvGettext(td2->label_);
+ else xmpData_["Xmp.video.Sharpness"] = (int)buf.pData_[0] & 7;
+
+ io_->read(buf.pData_, 1);
+ td2 = find(NormalSoftHard, (int)buf.pData_[0] & 7 );
+ if(td2) xmpData_["Xmp.video.Contrast"] = exvGettext(td2->label_);
+ else xmpData_["Xmp.video.Contrast"] = (int)buf.pData_[0] & 7;
+
+ io_->read(buf.pData_, 1);
+ td2 = find(NormalSoftHard, (int)buf.pData_[0] & 7 );
+ if(td2) xmpData_["Xmp.video.Brightness"] = exvGettext(td2->label_);
+ else xmpData_["Xmp.video.Brightness"] = (int)buf.pData_[0] & 7;
+
+ io_->read(buf.pData_, 1);
+ td2 = find(Saturation, (int)buf.pData_[0] & 7 );
+ if(td2) xmpData_["Xmp.video.Saturation"] = exvGettext(td2->label_);
+ else xmpData_["Xmp.video.Saturation"] = (int)buf.pData_[0] & 7;
+
+ io_->read(buf.pData_, 1);
+ xmpData_["Xmp.video.HueAdjustment"] = (int)buf.pData_[0] & 7;
+
+ io_->read(buf.pData_, 1);
+ td2 = find(FilterEffect, (int)buf.pData_[0]);
+ if(td2) xmpData_["Xmp.video.FilterEffect"] = exvGettext(td2->label_);
+ else xmpData_["Xmp.video.FilterEffect"] = (int)buf.pData_[0];
+
+ io_->read(buf.pData_, 1);
+ td2 = find(ToningEffect, (int)buf.pData_[0]);
+ if(td2) xmpData_["Xmp.video.ToningEffect"] = exvGettext(td2->label_);
+ else xmpData_["Xmp.video.ToningEffect"] = (int)buf.pData_[0];
+ io_->read(buf.pData_, 1); xmpData_["Xmp.video.ToningSaturation"] = (int)buf.pData_[0];
+ io_->seek(local_pos + dataLength, BasicIo::beg);
+ }
+ else if(TagID == 0x2000024){
+ uint64_t local_pos = io_->tell();
+ dataLength = Exiv2::getUShort(buf.pData_, bigEndian);
+ std::memset(buf.pData_, 0x0, buf.size_);
+
+ io_->read(buf.pData_, 2);
+ xmpData_["Xmp.video.TimeZone"] = Exiv2::getShort(buf.pData_, bigEndian);
+ io_->read(buf.pData_, 1);
+ td2 = find(YesNo, (int)buf.pData_[0]);
+ if(td2) xmpData_["Xmp.video.DayLightSavings"] = exvGettext(td2->label_);
+
+ io_->read(buf.pData_, 1);
+ td2 = find(DateDisplayFormat, (int)buf.pData_[0]);
+ if(td2) xmpData_["Xmp.video.DateDisplayFormat"] = exvGettext(td2->label_);
+
+ io_->seek(local_pos + dataLength, BasicIo::beg);
+ }
+ else if(dataType == 2 || dataType == 7){
+ dataLength = Exiv2::getUShort(buf.pData_, bigEndian);
+ std::memset(buf.pData_, 0x0, buf.size_);
+
+ // Sanity check with an "unreasonably" large number
+ if (dataLength > 200){
+#ifndef SUPPRESS_WARNINGS
+ EXV_ERROR << "Xmp.video Nikon Tags, dataLength was found to be larger than 200."
+ << " Entries considered invalid. Not Processed.\n";
+#endif
+ io_->seek(io_->tell() + dataLength, BasicIo::beg);
+ }
+ else io_->read(buf.pData_, dataLength);
+
+ if(td) xmpData_[exvGettext(td->label_)] = Exiv2::toString(buf.pData_);
+ }
+ else if(dataType == 4){
+ dataLength = Exiv2::getUShort(buf.pData_, bigEndian) * 4;
+ std::memset(buf.pData_, 0x0, buf.size_);
+ io_->read(buf.pData_, 4);
+ if(td) xmpData_[exvGettext(td->label_)] = Exiv2::toString(Exiv2::getULong( buf.pData_, bigEndian));
+
+ // Sanity check with an "unreasonably" large number
+ if (dataLength > 200 || dataLength < 4){
+#ifndef SUPPRESS_WARNINGS
+ EXV_ERROR << "Xmp.video Nikon Tags, dataLength was found to be of inapropriate size."
+ << " Entries considered invalid. Not Processed.\n";
+#endif
+ io_->seek(io_->tell() + dataLength - 4, BasicIo::beg);
+ }
+ else io_->read(buf.pData_, dataLength - 4);
+ }
+ else if(dataType == 3){
+ dataLength = Exiv2::getUShort(buf.pData_, bigEndian) * 2;
+ std::memset(buf.pData_, 0x0, buf.size_);
+ io_->read(buf.pData_, 2);
+ if(td) xmpData_[exvGettext(td->label_)] = Exiv2::toString(Exiv2::getUShort( buf.pData_, bigEndian));
+
+ // Sanity check with an "unreasonably" large number
+ if (dataLength > 200 || dataLength < 2){
+#ifndef SUPPRESS_WARNINGS
+ EXV_ERROR << "Xmp.video Nikon Tags, dataLength was found to be of inapropriate size."
+ << " Entries considered invalid. Not Processed.\n";
+#endif
+ io_->seek(io_->tell() + dataLength - 2, BasicIo::beg);
+ }
+ else io_->read(buf.pData_, dataLength - 2);
+ }
+ else if(dataType == 5){
+ dataLength = Exiv2::getUShort(buf.pData_, bigEndian) * 8;
+ std::memset(buf.pData_, 0x0, buf.size_);
+ io_->read(buf.pData_, 4);
+ io_->read(buf2.pData_, 4);
+ if(td) xmpData_[exvGettext(td->label_)] = Exiv2::toString((double)Exiv2::getULong( buf.pData_, bigEndian)
+ / (double)Exiv2::getULong( buf2.pData_, bigEndian));
+
+ // Sanity check with an "unreasonably" large number
+ if (dataLength > 200 || dataLength < 8){
+#ifndef SUPPRESS_WARNINGS
+ EXV_ERROR << "Xmp.video Nikon Tags, dataLength was found to be of inapropriate size."
+ << " Entries considered invalid. Not Processed.\n";
+#endif
+ io_->seek(io_->tell() + dataLength - 8, BasicIo::beg);
+ }
+ else io_->read(buf.pData_, dataLength - 8);
+ }
+ else if(dataType == 8){
+ dataLength = Exiv2::getUShort(buf.pData_, bigEndian) * 2;
+ std::memset(buf.pData_, 0x0, buf.size_);
+ io_->read(buf.pData_, 2);
+ io_->read(buf2.pData_, 2);
+ if(td) xmpData_[exvGettext(td->label_)] = Exiv2::toString(Exiv2::getUShort( buf.pData_, bigEndian) )
+ + " " + Exiv2::toString(Exiv2::getUShort( buf2.pData_, bigEndian));
+
+ // Sanity check with an "unreasonably" large number
+ if (dataLength > 200 || dataLength < 4){
+#ifndef SUPPRESS_WARNINGS
+ EXV_ERROR << "Xmp.video Nikon Tags, dataLength was found to be of inapropriate size."
+ << " Entries considered invalid. Not Processed.\n";
+#endif
+ io_->seek(io_->tell() + dataLength - 4, BasicIo::beg);
+ }
+ else io_->read(buf.pData_, dataLength - 4);
+ }
+ }
+ io_->seek(cur_pos + size_external, BasicIo::beg);
+ } else {
+ RevTagDetails revNikonNCTGTags[(sizeof(NikonNCTGTags)/sizeof(NikonNCTGTags[0]))];
+ reverseTagDetails(NikonNCTGTags,revNikonNCTGTags,((sizeof(NikonNCTGTags)/sizeof(NikonNCTGTags[0]))));
+
+ bool bDataWriten = false;
+ for(int32_t i = 0 ; i < 100 ; i++){
io_->read(buf.pData_, 4);
TagID = Exiv2::getULong(buf.pData_, bigEndian);
td = find(NikonNCTGTags, TagID);
@@ -963,691 +1639,1273 @@ namespace Exiv2 {
std::memset(buf.pData_, 0x0, buf.size_);
io_->read(buf.pData_, 2);
- if(TagID == 0x2000023) {
+ if(TagID == 0x2000023){
+ uint64_t local_pos = io_->tell();
+ dataLength = Exiv2::getUShort(buf.pData_, bigEndian);
+ writeShortData(xmpData_["Xmp.video.PictureControlVersion"],4);
+ writeShortData(xmpData_["Xmp.video.PictureControlName"],20);
+ writeShortData(xmpData_["Xmp.video.PictureControlBase"],20);
+ io_->seek(4,BasicIo::cur);
+ std::memset(buf.pData_, 0x0, buf.size_);
+
+ if(xmpData_["Xmp.video.PictureControlAdjust"].count() >0){
+ RevTagDetails revTagDetails[(sizeof(PictureControlAdjust)/sizeof(PictureControlAdjust[0]))];
+ reverseTagDetails(PictureControlAdjust,revTagDetails,((sizeof(PictureControlAdjust)/sizeof(PictureControlAdjust[0]))));
+
+ rtd2 = find(revTagDetails,xmpData_["Xmp.video.PictureControlAdjust"].toString());
+ if(rtd2){
+ Exiv2::byte rawPictureControlAdjust = (Exiv2::byte)rtd2->val_;
+ bDataWriten = writeMultibyte(&rawPictureControlAdjust, 1);
+ }
+ }
+ if(!bDataWriten) io_->seek(1,BasicIo::cur);
+ bDataWriten = false;
+
+ if(xmpData_["Xmp.video.PictureControlQuickAdjust"].count() >0){
+ RevTagDetails revTagDetails[(sizeof(NormalSoftHard)/sizeof(NormalSoftHard[0]))];
+ reverseTagDetails(NormalSoftHard,revTagDetails,((sizeof(NormalSoftHard)/sizeof(NormalSoftHard[0]))));
+
+ rtd2 = find(revTagDetails, xmpData_["Xmp.video.PictureControlQuickAdjust"].toString() );
+ if(rtd2){
+ Exiv2::byte rawPictureControlQuickAdjust = (Exiv2::byte)rtd2->val_;
+ bDataWriten = writeMultibyte(&rawPictureControlQuickAdjust,1);
+ }
+ }
+ if(!bDataWriten) io_->seek(1,BasicIo::cur);
+ bDataWriten = false;
+
+ if(xmpData_["Xmp.video.Sharpness"].count() >0){
+ RevTagDetails revTagDetails[(sizeof(NormalSoftHard)/sizeof(NormalSoftHard[0]))];
+ reverseTagDetails(NormalSoftHard,revTagDetails,((sizeof(NormalSoftHard)/sizeof(NormalSoftHard[0]))));
+
+ rtd2 = find(revTagDetails, xmpData_["Xmp.video.Sharpness"].toString() );
+ if(rtd2){
+ Exiv2::byte rawSharpness = (Exiv2::byte)rtd2->val_;
+ bDataWriten = writeMultibyte(&rawSharpness,1);
+ }
+ }
+ if(!bDataWriten) io_->seek(1,BasicIo::cur);
+ bDataWriten = false;
+
+ if(xmpData_["Xmp.video.Contrast"].count() >0){
+ RevTagDetails revTagDetails[(sizeof(NormalSoftHard)/sizeof(NormalSoftHard[0]))];
+ reverseTagDetails(NormalSoftHard,revTagDetails,((sizeof(NormalSoftHard)/sizeof(NormalSoftHard[0]))));
+
+ rtd2 = find(revTagDetails, xmpData_["Xmp.video.Contrast"].toString() );
+ if(rtd2){
+ Exiv2::byte rawContrast = (Exiv2::byte)rtd2->val_;
+ bDataWriten = writeMultibyte(&rawContrast,1);
+ }
+ }
+ if(!bDataWriten) io_->seek(1,BasicIo::cur);
+ bDataWriten = false;
+
+ if(xmpData_["Xmp.video.Brightness"].count() >0){
+ RevTagDetails revTagDetails[(sizeof(NormalSoftHard)/sizeof(NormalSoftHard[0]))];
+ reverseTagDetails(NormalSoftHard,revTagDetails,((sizeof(NormalSoftHard)/sizeof(NormalSoftHard[0]))));
+
+ rtd2 = find(revTagDetails, xmpData_["Xmp.video.Brightness"].toString() );
+ if(rtd2){
+ Exiv2::byte rawBrightness = (Exiv2::byte)rtd2->val_;
+ bDataWriten = writeMultibyte(&rawBrightness,1);
+ }
+ }
+ if(!bDataWriten) io_->seek(1,BasicIo::cur);
+ bDataWriten = false;
+
+ if(xmpData_["Xmp.video.Saturation"].count() >0){
+ RevTagDetails revTagDetails[(sizeof(Saturation)/sizeof(Saturation[0]))];
+ reverseTagDetails(Saturation,revTagDetails,((sizeof(Saturation)/sizeof(Saturation[0]))));
+
+ rtd2 = find(revTagDetails, xmpData_["Xmp.video.Saturation"].toString() );
+ if(rtd2){
+ Exiv2::byte rawSaturation = (Exiv2::byte)rtd2->val_;
+ bDataWriten = writeMultibyte(&rawSaturation,1);
+ }
+ }
+ if(!bDataWriten) io_->seek(1,BasicIo::cur);
+ bDataWriten = false;
+
+ if(xmpData_["Xmp.video.HueAdjustment"].count() >0){
+ Exiv2::byte rawHueAdjustment = (Exiv2::byte)xmpData_["Xmp.video.HueAdjustment"].toString()[0];
+ bDataWriten = writeMultibyte(&rawHueAdjustment,1);
+ }
+ if(!bDataWriten) io_->seek(1,BasicIo::cur);
+ bDataWriten = false;
+
+ if(xmpData_["Xmp.video.FilterEffect"].count() >0){
+ RevTagDetails revTagDetails[(sizeof(FilterEffect)/sizeof(FilterEffect[0]))];
+ reverseTagDetails(FilterEffect,revTagDetails,((sizeof(FilterEffect)/sizeof(FilterEffect[0]))));
+
+ rtd2 = find(revTagDetails, xmpData_["Xmp.video.FilterEffect"].toString() );
+ if(rtd2){
+ Exiv2::byte rawFilterEffect = (Exiv2::byte)rtd2->val_;
+ bDataWriten = writeMultibyte(&rawFilterEffect,1);
+ }
+ }
+ if(!bDataWriten) io_->seek(1,BasicIo::cur);
+ bDataWriten = false;
+
+ if(xmpData_["Xmp.video.ToningEffect"].count() >0){
+ RevTagDetails revTagDetails[(sizeof(ToningEffect)/sizeof(ToningEffect[0]))];
+ reverseTagDetails(ToningEffect,revTagDetails,((sizeof(ToningEffect)/sizeof(ToningEffect[0]))));
+
+ rtd2 = find(revTagDetails, xmpData_["Xmp.video.ToningEffect"].toString() );
+ if(rtd2){
+ Exiv2::byte rawToningEffect = (Exiv2::byte)rtd2->val_;
+ bDataWriten = writeMultibyte(&rawToningEffect,1);
+ }
+ }
+ if(!bDataWriten) io_->seek(1,BasicIo::cur);
+ bDataWriten = false;
+
+ if(xmpData_["Xmp.video.ToningSaturation"].count() >0){
+ Exiv2::byte rawToningSaturation = (Exiv2::byte)xmpData_["Xmp.video.ToningSaturation"].toString()[0];
+ bDataWriten = writeMultibyte(&rawToningSaturation,1);
+ }
+ io_->seek(local_pos + dataLength, BasicIo::beg);
+ }
+ else if(TagID == 0x2000024){
uint64_t local_pos = io_->tell();
dataLength = Exiv2::getUShort(buf.pData_, bigEndian);
std::memset(buf.pData_, 0x0, buf.size_);
- io_->read(buf.pData_, 4); xmpData_["Xmp.video.PictureControlVersion"] = Exiv2::toString(buf.pData_);
- io_->read(buf.pData_, 20); xmpData_["Xmp.video.PictureControlName"] = Exiv2::toString(buf.pData_);
- io_->read(buf.pData_, 20); xmpData_["Xmp.video.PictureControlBase"] = Exiv2::toString(buf.pData_);
- io_->read(buf.pData_, 4); std::memset(buf.pData_, 0x0, buf.size_);
+ writeShortData(xmpData_["Xmp.video.TimeZone"]);
- io_->read(buf.pData_, 1);
- td2 = find(PictureControlAdjust, (int)buf.pData_[0] & 7 );
- if(td2)
- xmpData_["Xmp.video.PictureControlAdjust"] = exvGettext(td2->label_);
- else
- xmpData_["Xmp.video.PictureControlAdjust"] = (int)buf.pData_[0] & 7 ;
+ if(xmpData_["Xmp.video.DayLightSavings"].count() >0){
+ RevTagDetails revTagDetails[(sizeof(YesNo)/sizeof(YesNo[0]))];
+ reverseTagDetails(YesNo,revTagDetails,((sizeof(YesNo)/sizeof(YesNo[0]))));
- io_->read(buf.pData_, 1);
- td2 = find(NormalSoftHard, (int)buf.pData_[0] & 7 );
- if(td2)
- xmpData_["Xmp.video.PictureControlQuickAdjust"] = exvGettext(td2->label_);
+ rtd2 = find(revTagDetails, xmpData_["Xmp.video.DayLightSavings"].toString() );
+ if(rtd2){
+ Exiv2::byte rawDayLightSavings = (Exiv2::byte)rtd2->val_;
+ bDataWriten = writeMultibyte(&rawDayLightSavings,1);
+ }
+ }
+ if(!bDataWriten) io_->seek(1,BasicIo::cur);
+ bDataWriten = false;
- io_->read(buf.pData_, 1);
- td2 = find(NormalSoftHard, (int)buf.pData_[0] & 7 );
- if(td2)
- xmpData_["Xmp.video.Sharpness"] = exvGettext(td2->label_);
- else
- xmpData_["Xmp.video.Sharpness"] = (int)buf.pData_[0] & 7;
-
- io_->read(buf.pData_, 1);
- td2 = find(NormalSoftHard, (int)buf.pData_[0] & 7 );
- if(td2)
- xmpData_["Xmp.video.Contrast"] = exvGettext(td2->label_);
- else
- xmpData_["Xmp.video.Contrast"] = (int)buf.pData_[0] & 7;
-
- io_->read(buf.pData_, 1);
- td2 = find(NormalSoftHard, (int)buf.pData_[0] & 7 );
- if(td2)
- xmpData_["Xmp.video.Brightness"] = exvGettext(td2->label_);
- else
- xmpData_["Xmp.video.Brightness"] = (int)buf.pData_[0] & 7;
-
- io_->read(buf.pData_, 1);
- td2 = find(Saturation, (int)buf.pData_[0] & 7 );
- if(td2)
- xmpData_["Xmp.video.Saturation"] = exvGettext(td2->label_);
- else
- xmpData_["Xmp.video.Saturation"] = (int)buf.pData_[0] & 7;
-
- io_->read(buf.pData_, 1);
- xmpData_["Xmp.video.HueAdjustment"] = (int)buf.pData_[0] & 7;
-
- io_->read(buf.pData_, 1);
- td2 = find(FilterEffect, (int)buf.pData_[0]);
- if(td2)
- xmpData_["Xmp.video.FilterEffect"] = exvGettext(td2->label_);
- else
- xmpData_["Xmp.video.FilterEffect"] = (int)buf.pData_[0];
-
- io_->read(buf.pData_, 1);
- td2 = find(ToningEffect, (int)buf.pData_[0]);
- if(td2)
- xmpData_["Xmp.video.ToningEffect"] = exvGettext(td2->label_);
- else
- xmpData_["Xmp.video.ToningEffect"] = (int)buf.pData_[0];
-
- io_->read(buf.pData_, 1); xmpData_["Xmp.video.ToningSaturation"] = (int)buf.pData_[0];
+ if(xmpData_["Xmp.video.DateDisplayFormat"].count() >0){
+ RevTagDetails revTagDetails[(sizeof(DateDisplayFormat)/sizeof(DateDisplayFormat[0]))];
+ reverseTagDetails(DateDisplayFormat,revTagDetails,((sizeof(DateDisplayFormat)/sizeof(DateDisplayFormat[0]))));
+ rtd2 = find(revTagDetails, xmpData_["Xmp.video.DateDisplayFormat"].toString() );
+ if(rtd2){
+ Exiv2::byte rawDateDisplayFormat = (Exiv2::byte)rtd2->val_;
+ bDataWriten = writeMultibyte(&rawDateDisplayFormat,1);
+ }
+ }
io_->seek(local_pos + dataLength, BasicIo::beg);
}
-
- else if(TagID == 0x2000024) {
- uint64_t local_pos = io_->tell();
- dataLength = Exiv2::getUShort(buf.pData_, bigEndian);
- std::memset(buf.pData_, 0x0, buf.size_);
-
- io_->read(buf.pData_, 2); xmpData_["Xmp.video.TimeZone"] = Exiv2::getShort(buf.pData_, bigEndian);
- io_->read(buf.pData_, 1);
- td2 = find(YesNo, (int)buf.pData_[0]);
- if(td2)
- xmpData_["Xmp.video.DayLightSavings"] = exvGettext(td2->label_);
-
- io_->read(buf.pData_, 1);
- td2 = find(DateDisplayFormat, (int)buf.pData_[0]);
- if(td2)
- xmpData_["Xmp.video.DateDisplayFormat"] = exvGettext(td2->label_);
-
- io_->seek(local_pos + dataLength, BasicIo::beg);
- }
-
- else if(dataType == 2 || dataType == 7) {
+ else if(dataType == 2 || dataType == 7){
dataLength = Exiv2::getUShort(buf.pData_, bigEndian);
std::memset(buf.pData_, 0x0, buf.size_);
// Sanity check with an "unreasonably" large number
- if (dataLength > 200) {
+ if (dataLength > 200){
#ifndef SUPPRESS_WARNINGS
EXV_ERROR << "Xmp.video Nikon Tags, dataLength was found to be larger than 200."
<< " Entries considered invalid. Not Processed.\n";
#endif
io_->seek(io_->tell() + dataLength, BasicIo::beg);
+ } else {
+ if(td && (xmpData_[exvGettext(td->label_)].count() >0)) writeStringData(xmpData_[exvGettext(td->label_)],dataLength);
+ else io_->seek(dataLength,BasicIo::cur);
}
- else
- io_->read(buf.pData_, dataLength);
-
- if(td)
- xmpData_[exvGettext(td->label_)] = Exiv2::toString(buf.pData_);
}
- else if(dataType == 4) {
+ else if(dataType == 4){ // what is 4? would it be better to have an enum with a name for each dataType?
dataLength = Exiv2::getUShort(buf.pData_, bigEndian) * 4;
- std::memset(buf.pData_, 0x0, buf.size_);
- io_->read(buf.pData_, 4);
- if(td)
- xmpData_[exvGettext(td->label_)] = Exiv2::toString(Exiv2::getULong( buf.pData_, bigEndian));
-
- // Sanity check with an "unreasonably" large number
- if (dataLength > 200 || dataLength < 4) {
-#ifndef SUPPRESS_WARNINGS
- EXV_ERROR << "Xmp.video Nikon Tags, dataLength was found to be of inapropriate size."
- << " Entries considered invalid. Not Processed.\n";
-#endif
- io_->seek(io_->tell() + dataLength - 4, BasicIo::beg);
- }
- else
- io_->read(buf.pData_, dataLength - 4);
+ if(td && (xmpData_[exvGettext(td->label_)].count() >0) && (dataLength < 200)) writeLongData(xmpData_[exvGettext(td->label_)],4,dataLength-4);
+ else io_->seek(dataLength,BasicIo::cur);
}
- else if(dataType == 3) {
+ else if(dataType == 3){
dataLength = Exiv2::getUShort(buf.pData_, bigEndian) * 2;
std::memset(buf.pData_, 0x0, buf.size_);
io_->read(buf.pData_, 2);
- if(td)
- xmpData_[exvGettext(td->label_)] = Exiv2::toString(Exiv2::getUShort( buf.pData_, bigEndian));
-
- // Sanity check with an "unreasonably" large number
- if (dataLength > 200 || dataLength < 2) {
-#ifndef SUPPRESS_WARNINGS
- EXV_ERROR << "Xmp.video Nikon Tags, dataLength was found to be of inapropriate size."
- << " Entries considered invalid. Not Processed.\n";
-#endif
- io_->seek(io_->tell() + dataLength - 2, BasicIo::beg);
- }
- else
- io_->read(buf.pData_, dataLength - 2);
+ if(td &&(xmpData_[exvGettext(td->label_)].count() >0) && (dataLength < 200)) writeShortData(xmpData_[exvGettext(td->label_)],2,dataLength-2);
+ else io_->seek(dataLength,BasicIo::cur);
}
- else if(dataType == 5) {
+ else if(dataType == 5){
dataLength = Exiv2::getUShort(buf.pData_, bigEndian) * 8;
std::memset(buf.pData_, 0x0, buf.size_);
io_->read(buf.pData_, 4);
io_->read(buf2.pData_, 4);
- if(td)
- xmpData_[exvGettext(td->label_)] = Exiv2::toString((double)Exiv2::getULong( buf.pData_, bigEndian) / (double)Exiv2::getULong( buf2.pData_, bigEndian));
-
- // Sanity check with an "unreasonably" large number
- if (dataLength > 200 || dataLength < 8) {
-#ifndef SUPPRESS_WARNINGS
- EXV_ERROR << "Xmp.video Nikon Tags, dataLength was found to be of inapropriate size."
- << " Entries considered invalid. Not Processed.\n";
-#endif
- io_->seek(io_->tell() + dataLength - 8, BasicIo::beg);
+ if(td && (xmpData_[exvGettext(td->label_)].count() >0) &&(dataLength < 200)){
+ io_->seek(-8,BasicIo::cur);
+ const int32_t tagData = (int32_t)((double)xmpData_[exvGettext(td->label_)].toLong()*
+ (double)Exiv2::getULong( buf2.pData_, bigEndian));
+ io_->write((Exiv2::byte*)&tagData,4);
+ io_->seek((dataLength-4),BasicIo::cur);
}
- else
- io_->read(buf.pData_, dataLength - 8);
+ else io_->seek(dataLength,BasicIo::cur);
}
- else if(dataType == 8) {
+ else if(dataType == 8){
dataLength = Exiv2::getUShort(buf.pData_, bigEndian) * 2;
std::memset(buf.pData_, 0x0, buf.size_);
- io_->read(buf.pData_, 2);
- io_->read(buf2.pData_, 2);
- if(td)
- xmpData_[exvGettext(td->label_)] = Exiv2::toString(Exiv2::getUShort( buf.pData_, bigEndian) ) + " " + Exiv2::toString(Exiv2::getUShort( buf2.pData_, bigEndian));
-
- // Sanity check with an "unreasonably" large number
- if (dataLength > 200 || dataLength < 4) {
-#ifndef SUPPRESS_WARNINGS
- EXV_ERROR << "Xmp.video Nikon Tags, dataLength was found to be of inapropriate size."
- << " Entries considered invalid. Not Processed.\n";
-#endif
- io_->seek(io_->tell() + dataLength - 4, BasicIo::beg);
+ if(td && (xmpData_[exvGettext(td->label_)].count() >0) &&(dataLength < 200)){
+ vector dataEight = getNumberFromString(xmpData_[exvGettext(td->label_)].toString(),' ');
+ io_->write((Exiv2::byte*)&dataEight[0],2);
+ io_->write((Exiv2::byte*)&dataEight[1],2);
+ io_->seek(dataLength - 4,BasicIo::cur);
}
- else
- io_->read(buf.pData_, dataLength - 4);
+ else io_->seek(dataLength - 4,BasicIo::cur);
}
}
-
io_->seek(cur_pos + size_external, BasicIo::beg);
- } // QuickTimeVideo::NikonTagsDecoder
+ }
+}
- void QuickTimeVideo::setMediaStream()
- {
- uint64_t current_position = io_->tell();
- DataBuf buf(4+1);
+void QuickTimeVideo::setMediaStream(uint32_t /* iDummySize*/)
+{
+ uint64_t current_position = io_->tell();
+ DataBuf buf(4+1);
- while(!io_->eof()) {
+ while( !io_->eof() ) {
+ io_->read(buf.pData_, 4);
+ if (UtilsVideo::compareTagValue(buf, "hdlr")) {
+ io_->seek(8,BasicIo::cur);
io_->read(buf.pData_, 4);
- if (equalsQTimeTag(buf, "hdlr")) {
- io_->read(buf.pData_, 4);
- io_->read(buf.pData_, 4);
- io_->read(buf.pData_, 4);
- if (equalsQTimeTag(buf, "vide"))
- currentStream_ = Video;
- else if(equalsQTimeTag(buf, "soun"))
- currentStream_ = Audio;
- else if (equalsQTimeTag(buf, "hint"))
- currentStream_ = Hint;
- else
- currentStream_ = GenMediaHeader;
- break;
- }
+ if (UtilsVideo::compareTagValue(buf, "vide")) d->currentStream_ = Video;
+ else if (UtilsVideo::compareTagValue(buf, "soun")) d->currentStream_ = Audio;
+ else if (UtilsVideo::compareTagValue(buf, "hint")) d->currentStream_ = Hint;
+ else d->currentStream_ = GenMediaHeader;
+ break;
}
+ }
+ io_->seek(current_position, BasicIo::beg);
+}
- io_->seek(current_position, BasicIo::beg);
- } // QuickTimeVideo::setMediaStream
+void QuickTimeVideo::timeToSampleDecoder(uint32_t/* iDummySize*/)
+{
+ DataBuf buf(4+1);
+ io_->read(buf.pData_, 4);
+ io_->read(buf.pData_, 4);
+ uint64_t totalframes = 0;
+ uint64_t timeOfFrames = 0;
- void QuickTimeVideo::timeToSampleDecoder()
- {
- DataBuf buf(4+1);
+ uint64_t noOfEntries = returnUnsignedBufValue(buf);
+ for(uint32_t i=1; i <= noOfEntries; i++){
io_->read(buf.pData_, 4);
+ uint64_t temp = returnBufValue(buf);
+ totalframes += temp;
io_->read(buf.pData_, 4);
- uint64_t noOfEntries, totalframes = 0, timeOfFrames = 0;
- noOfEntries = returnUnsignedBufValue(buf);
- uint64_t temp;
+ timeOfFrames += temp * returnBufValue(buf);
+ }
- for(unsigned long i = 1; i <= noOfEntries; i++) {
- io_->read(buf.pData_, 4);
- temp = returnBufValue(buf);
- totalframes += temp;
- io_->read(buf.pData_, 4);
- timeOfFrames += temp * returnBufValue(buf);
+ if(!d->m_modifyMetadata) {
+ if (d->currentStream_ == Video) {
+ xmpData_["Xmp.video.FrameRate"] = (double)totalframes * (double)d->timeScale_ / (double)timeOfFrames;
+ } else {
+ if(xmpData_["Xmp.video.FrameRate"].count() >0) { /* TODO:implement write */ }
+ // Really? We're not modifying!!
}
- if (currentStream_ == Video)
- xmpData_["Xmp.video.FrameRate"] = (double)totalframes * (double)timeScale_ / (double)timeOfFrames;
- } // QuickTimeVideo::timeToSampleDecoder
+ }
+}
- void QuickTimeVideo::sampleDesc(unsigned long size)
- {
- DataBuf buf(100);
- uint64_t cur_pos = io_->tell();
- io_->read(buf.pData_, 4);
- io_->read(buf.pData_, 4);
- uint64_t noOfEntries;
- noOfEntries = returnUnsignedBufValue(buf);
+void QuickTimeVideo::sampleDesc(uint32_t size)
+{
+ DataBuf buf(100);
+ uint64_t cur_pos = io_->tell();
+ io_->read(buf.pData_, 4);
+ io_->read(buf.pData_, 4);
+ uint32_t noOfEntries = returnUnsignedBufValue(buf);
+ for(uint32_t i = 1; i <= noOfEntries; i++){
+ if (d->currentStream_ == Video) imageDescDecoder();
+ else if (d->currentStream_ == Audio) audioDescDecoder();
+ }
+ io_->seek(cur_pos + size, BasicIo::beg);
+}
- for(unsigned long i = 1; i <= noOfEntries; i++) {
- if (currentStream_ == Video)
- imageDescDecoder();
- else if (currentStream_ == Audio)
- audioDescDecoder();
- }
- io_->seek(cur_pos + size, BasicIo::beg);
- } // QuickTimeVideo::sampleDesc
+void QuickTimeVideo::audioDescDecoder()
+{
+ DataBuf buf(40);
+ io_->read(buf.pData_, 4);
+ uint64_t size = 82;
- void QuickTimeVideo::audioDescDecoder()
- {
- DataBuf buf(40);
- std::memset(buf.pData_, 0x0, buf.size_);
- buf.pData_[4] = '\0';
- io_->read(buf.pData_, 4);
- uint64_t size = 82;
+ const TagVocabulary* td;
- const TagVocabulary* td;
-
- for (int i = 0; size/4 != 0 ; size -= 4, i++) {
+ if(!d->m_modifyMetadata){
+ for (int32_t i = 0; size/4 != 0 ; size -= 4, i++){
io_->read(buf.pData_, 4);
- switch(i) {
+ switch(i){
case AudioFormat:
td = find(qTimeFileType, Exiv2::toString( buf.pData_));
- if(td)
- xmpData_["Xmp.audio.Compressor"] = exvGettext(td->label_);
- else
- xmpData_["Xmp.audio.Compressor"] = Exiv2::toString( buf.pData_);
+ if(td) xmpData_["Xmp.audio.Compressor"] = exvGettext(td->label_);
+ else xmpData_["Xmp.audio.Compressor"] = Exiv2::toString( buf.pData_);
break;
+
case AudioVendorID:
td = find(vendorIDTags, Exiv2::toString( buf.pData_));
- if(td)
- xmpData_["Xmp.audio.VendorID"] = exvGettext(td->label_);
+ if(td) xmpData_["Xmp.audio.VendorID"] = exvGettext(td->label_);
break;
+
case AudioChannels:
- xmpData_["Xmp.audio.ChannelType"] = returnBufValue(buf, 2);
+ xmpData_["Xmp.audio.ChannelType"] = returnBufValue(buf, 2);
xmpData_["Xmp.audio.BitsPerSample"] = (buf.pData_[2] * 256 + buf.pData_[3]);
break;
+
case AudioSampleRate:
xmpData_["Xmp.audio.SampleRate"] = returnBufValue(buf, 2) + ((buf.pData_[2] * 256 + buf.pData_[3]) * 0.01);
break;
- default:
- break;
+
+ default: break;
}
}
- io_->read(buf.pData_, static_cast(size % 4)); //cause size is so small, this cast should be right.
- } // QuickTimeVideo::audioDescDecoder
+ io_->read(buf.pData_, static_cast(size % 4)); //cause size is so small, this cast should be right.
+ } else {
+ TagVocabulary revTagVocabulary[(sizeof(qTimeFileType)/sizeof(qTimeFileType[0]))];
+ reverseTagVocabulary(qTimeFileType,revTagVocabulary,((sizeof(qTimeFileType)/sizeof(qTimeFileType[0]))));
- void QuickTimeVideo::imageDescDecoder()
- {
- DataBuf buf(40);
- std::memset(buf.pData_, 0x0, buf.size_);
- buf.pData_[4] = '\0';
- io_->read(buf.pData_, 4);
- uint64_t size = 82;
+ TagVocabulary revVendorIDTags[(sizeof(vendorIDTags)/sizeof(vendorIDTags[0]))];
+ reverseTagVocabulary(vendorIDTags,revVendorIDTags,((sizeof(vendorIDTags)/sizeof(vendorIDTags[0]))));
- const TagVocabulary* td;
+ for (int32_t i = 0; size/4 != 0 ; size -= 4, i++){
+ bool bDataWriten = false;
+ switch(i){
+ case AudioFormat:
+ if(xmpData_["Xmp.audio.Compressor"].count() > 0){
+ Exiv2::byte rawCompressor[4];
+ td = find(revTagVocabulary,xmpData_["Xmp.audio.Compressor"].toString());
+ if(td){
+ const char* compressor = td->label_;
+ for(int32_t j=0; j<4; j++) rawCompressor[j] = compressor[j];
+ bDataWriten = writeMultibyte(rawCompressor, 4);
+ }
+ }
+ break;
- for (int i = 0; size/4 != 0 ; size -= 4, i++) {
+ case AudioVendorID:
+ if(xmpData_["Xmp.audio.VendorID"].count() >0){
+ Exiv2::byte rawVendorID[4];
+ td = find(revVendorIDTags,xmpData_["Xmp.audio.VendorID"].toString());
+ if(td){
+ const char* vendorID = td->label_;
+ for(int32_t j=0; j<4; j++) rawVendorID[j] = vendorID[j];
+ bDataWriten = writeMultibyte(rawVendorID, 4);
+ }
+ }
+ break;
+
+ case AudioChannels:
+ if(xmpData_["Xmp.audio.ChannelType"].count() >0){
+ DataBuf rawBuf(2);
+ rawBuf = returnBuf((int64_t)xmpData_["Xmp.audio.ChannelType"].toLong(),2);
+ bDataWriten = writeMultibyte(rawBuf.pData_, 2);
+ }
+ if(!bDataWriten) io_->seek(2, BasicIo::cur);
+ bDataWriten = false;
+
+ if(xmpData_["Xmp.audio.BitsPerSample"].count() >0){
+ DataBuf rawBuf(2);
+ rawBuf = returnBuf((int64_t)xmpData_["Xmp.audio.BitsPerSample"].toLong(),2);
+ bDataWriten = writeMultibyte(rawBuf.pData_,2);
+ }
+ if(!bDataWriten) io_->seek(2, BasicIo::cur);
+ bDataWriten = true;
+ break;
+
+ case AudioSampleRate:
+ if(xmpData_["Xmp.audio.SampleRate"].count() >0){
+ DataBuf rawSampleRate(5);
+ rawSampleRate.pData_[4] = '\0';
+ const int64_t sampleRate = (int64_t)xmpData_["Xmp.audio.SampleRate"].toLong();
+ rawSampleRate = returnBuf(sampleRate,4);
+
+ bDataWriten = writeMultibyte(rawSampleRate.pData_+2,2);
+ bDataWriten = writeMultibyte(rawSampleRate.pData_,2);
+ }
+ break;
+
+ default:
+ io_->seek(4,BasicIo::cur);
+ bDataWriten = true;
+ break;
+ }
+ if(!bDataWriten) io_->seek(4, BasicIo::cur);
+ }
+ io_->seek(static_cast(size % 4),BasicIo::cur);
+ }
+}
+
+void QuickTimeVideo::imageDescDecoder()
+{
+ DataBuf buf(40);
+ io_->read(buf.pData_, 4);
+ uint64_t size = 82;
+
+ const TagVocabulary* td;
+
+ if(!d->m_modifyMetadata){
+ for (int32_t i = 0; size/4 != 0 ; size -= 4, i++){
io_->read(buf.pData_, 4);
- switch(i) {
+ switch(i){
case codec:
td = find(qTimeFileType, Exiv2::toString( buf.pData_));
- if(td)
- xmpData_["Xmp.video.Codec"] = exvGettext(td->label_);
- else
- xmpData_["Xmp.video.Codec"] = Exiv2::toString( buf.pData_);
+ if(td) xmpData_["Xmp.video.Codec"] = exvGettext(td->label_);
+ else xmpData_["Xmp.video.Codec"] = Exiv2::toString( buf.pData_);
break;
- case VendorID:
- td = find(vendorIDTags, Exiv2::toString( buf.pData_));
- if(td)
- xmpData_["Xmp.video.VendorID"] = exvGettext(td->label_);
+
+ case VendorID: td = find(vendorIDTags, Exiv2::toString( buf.pData_));
+ if(td) xmpData_["Xmp.video.VendorID"] = exvGettext(td->label_);
break;
+
case SourceImageWidth_Height:
xmpData_["Xmp.video.SourceImageWidth"] = returnBufValue(buf, 2);
xmpData_["Xmp.video.SourceImageHeight"] = (buf.pData_[2] * 256 + buf.pData_[3]);
break;
+
case XResolution:
xmpData_["Xmp.video.XResolution"] = returnBufValue(buf, 2) + ((buf.pData_[2] * 256 + buf.pData_[3]) * 0.01);
break;
+
case YResolution:
xmpData_["Xmp.video.YResolution"] = returnBufValue(buf, 2) + ((buf.pData_[2] * 256 + buf.pData_[3]) * 0.01);
- io_->read(buf.pData_, 3); size -= 3;
+ io_->read(buf.pData_, 3);
+ size -= 3;
break;
+
case CompressorName:
io_->read(buf.pData_, 32); size -= 32;
xmpData_["Xmp.video.Compressor"] = Exiv2::toString( buf.pData_);
break;
- default:
- break;
}
}
- io_->read(buf.pData_, static_cast(size % 4));
+ io_->read(buf.pData_, static_cast(size % 4));
xmpData_["Xmp.video.BitDepth"] = returnBufValue(buf, 1);
- } // QuickTimeVideo::imageDescDecoder
+ } else {
+ TagVocabulary revTagVocabulary[(sizeof(qTimeFileType)/sizeof(qTimeFileType[0]))];
+ reverseTagVocabulary(qTimeFileType,revTagVocabulary,((sizeof(qTimeFileType)/sizeof(qTimeFileType[0]))));
- void QuickTimeVideo::multipleEntriesDecoder()
- {
- DataBuf buf(4+1);
- io_->read(buf.pData_, 4);
- io_->read(buf.pData_, 4);
- uint64_t noOfEntries;
+ TagVocabulary revVendorIDTags[(sizeof(vendorIDTags)/sizeof(vendorIDTags[0]))];
+ reverseTagVocabulary(vendorIDTags,revVendorIDTags,((sizeof(vendorIDTags)/sizeof(vendorIDTags[0]))));
- noOfEntries = returnUnsignedBufValue(buf);
+ for (int32_t i = 0; size/4 != 0 ; size -= 4, i++){
+ bool bDataWritten = false;
+ switch(i){
+ case codec:
+ if(xmpData_["Xmp.video.Codec"].count() >0){
+ std::string codecName = xmpData_["Xmp.video.Codec"].toString();
+ td = find(revTagVocabulary, codecName);
+ Exiv2::byte rawCodec[4];
+ if(td){
+ const char* codecNameTag = td->label_;
+ for(int32_t j=0; j<4 ;j++) rawCodec[j] = (Exiv2::byte)codecNameTag[j];
+ }
+ else for(int32_t j=0; j<4 ;j++) rawCodec[j] = (Exiv2::byte)codecName[j];
+ bDataWritten = writeMultibyte(rawCodec, 4);
+ }
+ break;
- for(unsigned long i = 1; i <= noOfEntries; i++)
- decodeBlock();
- } // QuickTimeVideo::multipleEntriesDecoder
+ case VendorID:
+ if(xmpData_["Xmp.video.VendorID"].count() >0){
+ td = find(revVendorIDTags, xmpData_["Xmp.video.VendorID"].toString());
+ if(td){
+ Exiv2::byte rawVendorID[4];
+ const char* vendorID = td->label_;
+ for(int32_t j=0; j<4 ;j++) rawVendorID[j] = vendorID[j];
+ bDataWritten = writeMultibyte(rawVendorID,4);
+ }
+ }
+ break;
- void QuickTimeVideo::videoHeaderDecoder(unsigned long size) {
- DataBuf buf(3);
- std::memset(buf.pData_, 0x0, buf.size_);
- buf.pData_[2] = '\0';
- currentStream_ = Video;
+ case SourceImageWidth_Height:
+ if(xmpData_["Xmp.video.SourceImageWidth"].count() >0){
+ DataBuf imageWidth = returnBuf((int64_t)xmpData_["Xmp.video.SourceImageWidth"].toLong(),2);
+ bDataWritten = writeMultibyte(imageWidth.pData_,2);
+ }
+ if(!bDataWritten) io_->seek(2,BasicIo::cur);
+ bDataWritten = false;
- const TagDetails* td;
+ if(xmpData_["Xmp.video.SourceImageHeight"].count() >0){
+ DataBuf imageHeight = returnBuf(((int64_t)(xmpData_["Xmp.video.SourceImageHeight"].toLong() -
+ xmpData_["Xmp.video.SourceImageHeight"].toLong()/65536)*65536));
+ bDataWritten = writeMultibyte(imageHeight.pData_,2);
+ }
+ if(!bDataWritten) io_->seek(2,BasicIo::cur);
+ bDataWritten = true;
+ break;
- for (int i = 0; size/2 != 0 ; size -= 2, i++) {
+ case XResolution:
+ //This field should not be edited
+ break;
+
+ case YResolution:
+ io_->seek(7,BasicIo::cur);
+ size -= 3;
+ bDataWritten = true;
+ break;
+
+ case CompressorName:
+ if(xmpData_["Xmp.video.Compressor"].count() >0){
+ Exiv2::byte rawCompressor[32] = {};
+ const std::string compressor = xmpData_["Xmp.video.Compressor"].toString();
+ for(int32_t j=0;jseek(4,BasicIo::cur);
+ bDataWritten = writeMultibyte(rawCompressor,32);
+ } else io_->seek(36,BasicIo::cur);
+ size -= 32;
+ bDataWritten = true;
+ break;
+ }
+ if(!bDataWritten) io_->seek(4,BasicIo::cur);
+ }
+
+ if(xmpData_["Xmp.video.BitDepth"].count() > 0)
+ {
+ DataBuf rawBitDepth(1);
+ rawBitDepth = returnBuf((int64_t)xmpData_["Xmp.video.BitDepth"].toLong(),1);
+ io_->write(rawBitDepth.pData_,1);
+ }
+ io_->seek(static_cast(size % 4),BasicIo::cur);
+ }
+}
+
+void QuickTimeVideo::multipleEntriesDecoder(uint32_t /*iDummySize*/)
+{
+ DataBuf buf(5);
+ io_->read(buf.pData_, 4);
+ io_->read(buf.pData_, 4);
+
+ uint64_t noOfEntries = returnUnsignedBufValue(buf);
+ for(uint32_t i = 1; i <= noOfEntries; i++) decodeBlock();
+}
+
+void QuickTimeVideo::videoHeaderDecoder(uint32_t size)
+{
+ DataBuf buf(3);
+ d->currentStream_ = Video;
+
+ const RevTagDetails* rtd;
+ const TagDetails* td;
+
+ if(!d->m_modifyMetadata){
+ for (int32_t i = 0; size/2 != 0 ; size -= 2, i++){
io_->read(buf.pData_, 2);
- switch(i) {
+ switch(i){
case GraphicsMode:
td = find(graphicsModetags, returnBufValue(buf,2));
- if(td)
- xmpData_["Xmp.video.GraphicsMode"] = exvGettext(td->label_);
+ if(td) xmpData_["Xmp.video.GraphicsMode"] = exvGettext(td->label_);
break;
+
case OpColor:
xmpData_["Xmp.video.OpColor"] = returnBufValue(buf,2);
break;
- default:
- break;
}
}
io_->read(buf.pData_, size % 2);
- } // QuickTimeVideo::videoHeaderDecoder
+ } else {
+ RevTagDetails revTagDetails[(sizeof(graphicsModetags)/sizeof(graphicsModetags[0]))];
+ reverseTagDetails(graphicsModetags,revTagDetails,((sizeof(graphicsModetags)/sizeof(graphicsModetags[0]))));
- void QuickTimeVideo::handlerDecoder(unsigned long size)
- {
- uint64_t cur_pos = io_->tell();
- DataBuf buf(100);
- std::memset(buf.pData_, 0x0, buf.size_);
- buf.pData_[4] = '\0';
+ for (int32_t i = 0; size/2 != 0 ; size -= 2, i++){
+ bool bDataWritten = false;
+ switch(i){
+ case GraphicsMode:
+ if(xmpData_["Xmp.video.GraphicsMode"].count() >0){
+ DataBuf rawGraphicsMode(2);
+ rtd = find(revTagDetails,xmpData_["Xmp.video.GraphicsMode"].toString());
+ if(rtd){
+ rawGraphicsMode = returnBuf((int64_t)rtd->val_,2);
+ bDataWritten = writeMultibyte(rawGraphicsMode.pData_,2);
+ }
+ }
+ break;
- const TagVocabulary* tv;
+ case OpColor:
+ if(xmpData_["Xmp.video.OpColor"].count() >0){
+ DataBuf rawOpColor((uint32_t)3);
+ rawOpColor.pData_[2] = '\0';
+ const int64_t opColor = xmpData_["Xmp.video.OpColor"].toLong();
+ rawOpColor = returnBuf(opColor,2);
+ bDataWritten = writeMultibyte(rawOpColor.pData_,2);
+ }
+ break;
+ }
+ if(!bDataWritten) io_->seek(2,BasicIo::cur);
+ }
+ io_->seek(size % 2,BasicIo::cur);
+ }
+}
- for (int i = 0; i < 5 ; i++) {
+void QuickTimeVideo::handlerDecoder(uint32_t size)
+{
+ uint64_t cur_pos = io_->tell();
+ DataBuf buf(100);
+ const TagVocabulary* tv;
+
+ if(!d->m_modifyMetadata){
+ for (int32_t i = 0; i < 5 ; i++){
io_->read(buf.pData_, 4);
- switch(i) {
+ switch(i){
case HandlerClass:
tv = find(handlerClassTags, Exiv2::toString( buf.pData_));
- if(tv) {
- if (currentStream_ == Video)
- xmpData_["Xmp.video.HandlerClass"] = exvGettext(tv->label_);
- else if (currentStream_ == Audio)
- xmpData_["Xmp.audio.HandlerClass"] = exvGettext(tv->label_);
+ if(tv){
+ if (d->currentStream_ == Video) xmpData_["Xmp.video.HandlerClass"] = exvGettext(tv->label_);
+ else if (d->currentStream_ == Audio) xmpData_["Xmp.audio.HandlerClass"] = exvGettext(tv->label_);
}
break;
+
case HandlerType:
tv = find(handlerTypeTags, Exiv2::toString( buf.pData_));
- if(tv) {
- if (currentStream_ == Video)
- xmpData_["Xmp.video.HandlerType"] = exvGettext(tv->label_);
- else if (currentStream_ == Audio)
- xmpData_["Xmp.audio.HandlerType"] = exvGettext(tv->label_);
+ if(tv){
+ if (d->currentStream_ == Video) xmpData_["Xmp.video.HandlerType"] = exvGettext(tv->label_);
+ else if (d->currentStream_ == Audio) xmpData_["Xmp.audio.HandlerType"] = exvGettext(tv->label_);
}
break;
+
case HandlerVendorID:
tv = find(vendorIDTags, Exiv2::toString( buf.pData_));
- if(tv) {
- if (currentStream_ == Video)
- xmpData_["Xmp.video.HandlerVendorID"] = exvGettext(tv->label_);
- else if (currentStream_ == Audio)
- xmpData_["Xmp.audio.HandlerVendorID"] = exvGettext(tv->label_);
+ if(tv){
+ if (d->currentStream_ == Video) xmpData_["Xmp.video.HandlerVendorID"] = exvGettext(tv->label_);
+ else if (d->currentStream_ == Audio) xmpData_["Xmp.audio.HandlerVendorID"] = exvGettext(tv->label_);
}
break;
}
}
io_->seek(cur_pos + size, BasicIo::beg);
- } // QuickTimeVideo::handlerDecoder
+ } else {
+ for (int32_t i = 0; i < 5 ; i++){
+ bool bDataWritten = false;
+ switch(i){
+ case HandlerClass : bDataWritten = writeAudVidData(0); break;
+ case HandlerType : bDataWritten = writeAudVidData(1); break;
+ case HandlerVendorID: bDataWritten = writeAudVidData(2); break;
+ }
+ if(!bDataWritten) io_->seek(4, BasicIo::cur);
+ }
+ io_->seek(cur_pos + size, BasicIo::beg);
+ }
+}
- void QuickTimeVideo::fileTypeDecoder(unsigned long size) {
- DataBuf buf(5);
- std::memset(buf.pData_, 0x0, buf.size_);
- buf.pData_[4] = '\0';
- Exiv2::Value::AutoPtr v = Exiv2::Value::create(Exiv2::xmpSeq);
- const TagVocabulary* td;
+bool QuickTimeVideo::writeAudVidData(int64_t iTagType)
+{
+ bool bReturnVal = false;
+ const TagVocabulary* tv;
- for (int i = 0; size/4 != 0; size -=4, i++) {
+ TagVocabulary revTagVocabulary[(sizeof(handlerClassTags)/sizeof(handlerClassTags[0]))];
+ reverseTagVocabulary(handlerClassTags,revTagVocabulary,((sizeof(handlerClassTags)/sizeof(handlerClassTags[0]))));
+
+ TagVocabulary revHandlerType[(sizeof(handlerTypeTags)/sizeof(handlerTypeTags[0]))];
+ reverseTagVocabulary(handlerTypeTags,revHandlerType,((sizeof(handlerTypeTags)/sizeof(handlerTypeTags[0]))));
+
+ TagVocabulary revVendorIDTags[(sizeof(vendorIDTags)/sizeof(vendorIDTags[0]))];
+ reverseTagVocabulary(vendorIDTags,revVendorIDTags,((sizeof(vendorIDTags)/sizeof(vendorIDTags[0]))));
+
+ if(d->currentStream_ == Video){
+ switch (iTagType) {
+ case 0: tv = find(revTagVocabulary, xmpData_["Xmp.video.HandlerClass"].toString()) ; break;
+ case 1: tv = find(revHandlerType, xmpData_["Xmp.video.HandlerType"].toString()) ; break;
+ case 2: tv = find(revVendorIDTags, xmpData_["Xmp.video.HandlerVendorID"].toString()) ; break;
+ }
+ }
+ if(d->currentStream_ == Audio){
+ switch (iTagType) {
+ case 0: tv = find(revTagVocabulary, xmpData_["Xmp.audio.HandlerClass"].toString()) ; break;
+ case 1: tv = find(revHandlerType, xmpData_["Xmp.audio.HandlerType"].toString()) ; break;
+ case 2: tv = find(revVendorIDTags, xmpData_["Xmp.audio.HandlerVendorID"].toString()) ; break;
+ }
+ }
+ if(tv){
+ Exiv2::byte sRawXmpTagVal[4];
+ const std::string sXmpTagVal = tv->label_;
+ for(int32_t j=0; j<4; j++) sRawXmpTagVal[j] = sXmpTagVal[j];
+ bReturnVal = writeMultibyte(sRawXmpTagVal,4);
+ }
+ return bReturnVal;
+}
+
+void QuickTimeVideo::fileTypeDecoder(uint32_t size)
+{
+ DataBuf buf(5);
+ Exiv2::Value::AutoPtr v = Exiv2::Value::create(Exiv2::xmpSeq);
+ const TagVocabulary* td;
+
+ if(!d->m_modifyMetadata){
+ for (int32_t i = 0; size/4 != 0; size -=4, i++){
io_->read(buf.pData_, 4);
td = find(qTimeFileType, Exiv2::toString( buf.pData_));
-
- switch(i) {
- case 0:
- if(td)
- xmpData_["Xmp.video.MajorBrand"] = exvGettext(td->label_);
- break;
- case 1:
- xmpData_["Xmp.video.MinorVersion"] = returnBufValue(buf);
- break;
- default:
- if(td)
- v->read(exvGettext(td->label_));
- else
- v->read(Exiv2::toString(buf.pData_));
+ switch(i){
+ case 0: if(td) xmpData_["Xmp.video.MajorBrand"] = exvGettext(td->label_); break;
+ case 1: xmpData_["Xmp.video.MinorVersion"] = returnBufValue(buf); break;
+ default: if(td) v->read(exvGettext(td->label_));
+ else v->read(Exiv2::toString(buf.pData_));
break;
}
+ xmpData_.add(Exiv2::XmpKey("Xmp.video.CompatibleBrands"), v.get());
+ io_->read(buf.pData_, size%4);
}
- xmpData_.add(Exiv2::XmpKey("Xmp.video.CompatibleBrands"), v.get());
- io_->read(buf.pData_, size%4);
- } // QuickTimeVideo::fileTypeDecoder
-
- void QuickTimeVideo::mediaHeaderDecoder(unsigned long size) {
- DataBuf buf(5);
- std::memset(buf.pData_, 0x0, buf.size_);
- buf.pData_[4] = '\0';
- int64_t time_scale = 1;
-
- for (int i = 0; size/4 != 0 ; size -=4, i++) {
- io_->read(buf.pData_, 4);
-
- switch(i) {
- case MediaHeaderVersion:
- if(currentStream_ == Video)
- xmpData_["Xmp.video.MediaHeaderVersion"] = returnBufValue(buf,1);
- else if (currentStream_ == Audio)
- xmpData_["Xmp.audio.MediaHeaderVersion"] = returnBufValue(buf,1);
+ } else {
+ TagVocabulary revTagVocabulary[(sizeof(qTimeFileType)/sizeof(qTimeFileType[0]))];
+ reverseTagVocabulary(qTimeFileType,revTagVocabulary,((sizeof(qTimeFileType)/sizeof(qTimeFileType[0]))));
+ DataBuf buf;
+ for (int32_t i = 0; size/4 != 0; size -=4, i++){
+ bool bDataWritten = false;
+ switch(i){
+ case 0:
+ if(xmpData_["Xmp.video.MajorBrand"].count() > 0){
+ Exiv2::byte rawMajorBrand[4];
+ td = find(revTagVocabulary, xmpData_["Xmp.video.MajorBrand"].toString());
+ const char* majorBrandVoc = td->label_;
+ for(int32_t j=0; j<4 ;j++)rawMajorBrand[j] = majorBrandVoc[i];
+ bDataWritten = writeMultibyte(rawMajorBrand,4);
+ }
break;
- case MediaCreateDate:
- //A 32-bit integer that specifies (in seconds since midnight, January 1, 1904) when the movie atom was created.
- if(currentStream_ == Video)
- xmpData_["Xmp.video.MediaCreateDate"] = returnUnsignedBufValue(buf);
- else if (currentStream_ == Audio)
- xmpData_["Xmp.audio.MediaCreateDate"] = returnUnsignedBufValue(buf);
+
+ case 1:
+ if(xmpData_["Xmp.video.MinorVersion"].count() >0){
+ buf = returnBuf((int64_t)xmpData_["Xmp.video.MinorVersion"].toLong());
+ bDataWritten = writeMultibyte(buf.pData_,4);
+ }
break;
- case MediaModifyDate:
- //A 32-bit integer that specifies (in seconds since midnight, January 1, 1904) when the movie atom was created.
- if(currentStream_ == Video)
- xmpData_["Xmp.video.MediaModifyDate"] = returnUnsignedBufValue(buf);
- else if (currentStream_ == Audio)
- xmpData_["Xmp.audio.MediaModifyDate"] = returnUnsignedBufValue(buf);
+
+ default:
+ if(xmpData_["Xmp.video.CompatibleBrands"].count() >0){
+ Exiv2::byte rawCompatibleBrand[4];
+ td = find(revTagVocabulary, xmpData_["Xmp.video.CompatibleBrands"].toString());
+ if(td){
+ const char* compatibleBrandVoc = td->label_;
+ for(int32_t j=0; j<4 ;j++) rawCompatibleBrand[i] = compatibleBrandVoc[i];
+ } else {
+ const std::string compatibleBrand = xmpData_["Xmp.video.CompatibleBrands"].toString();
+ for(int32_t j=0; j<4; j++) rawCompatibleBrand[i] = compatibleBrand[i];
+ }
+ bDataWritten = writeMultibyte(rawCompatibleBrand,4);
+ }
break;
- case MediaTimeScale:
- if(currentStream_ == Video)
- xmpData_["Xmp.video.MediaTimeScale"] = returnBufValue(buf);
- else if (currentStream_ == Audio)
- xmpData_["Xmp.audio.MediaTimeScale"] = returnBufValue(buf);
+ }
+ if(!bDataWritten) io_->seek(4, BasicIo::cur);
+ io_->seek(size%4,BasicIo::cur);
+ }
+ }
+}
+
+void QuickTimeVideo::mediaHeaderDecoder(uint32_t size)
+{
+ DataBuf buf(5);
+ int64_t time_scale = 1;
+ const TagDetails* td;
+ const RevTagDetails* rtd;
+
+ if(!d->m_modifyMetadata){
+ for (int32_t i = 0; size/4 != 0 ; size -=4, i++){
+
+ switch(i){
+ case MediaHeaderVersion: readAudVidData("MediaHeaderVersion", 1, 1, 0); break;
+ case MediaCreateDate: //A 32-bit integer that specifies (in seconds since midnight, January 1, 1904) when the movie atom was created.
+ readAudVidData("MediaCreateDate", 4, 1, 1); break;
+ case MediaModifyDate: //A 32-bit integer that specifies (in seconds since midnight, January 1, 1904) when the movie atom was created.
+ readAudVidData("MediaModifyDate", 4, 1, 1); break;
+ case MediaTimeScale: io_->read(buf.pData_, 4) ;if(d->currentStream_ == Video) xmpData_["Xmp.video.MediaTimeScale"] = returnBufValue(buf);
+ else if (d->currentStream_ == Audio) xmpData_["Xmp.audio.MediaTimeScale"] = returnBufValue(buf);
time_scale = returnBufValue(buf);
break;
- case MediaDuration:
- if(currentStream_ == Video)
- xmpData_["Xmp.video.MediaDuration"] = returnBufValue(buf)/time_scale;
- else if (currentStream_ == Audio)
- xmpData_["Xmp.audio.MediaDuration"] = returnBufValue(buf)/time_scale;
+
+ case MediaDuration: io_->read(buf.pData_, 4);
+ if(d->currentStream_ == Video) xmpData_["Xmp.video.MediaDuration"] = returnBufValue(buf)/time_scale;
+ else if (d->currentStream_ == Audio) xmpData_["Xmp.audio.MediaDuration"] = returnBufValue(buf)/time_scale;
break;
- case MediaLanguageCode:
- if(currentStream_ == Video)
+ case MediaLanguageCode: io_->read(buf.pData_, 4);
+ if(d->currentStream_ == Video){
+ DataBuf tmpBuf((uint32_t)5);
+ tmpBuf.pData_[1] = buf.pData_[2];
+ tmpBuf.pData_[0] = buf.pData_[3];
+ xmpData_["Xmp.video.Quality"] = returnUnsignedBufValue(tmpBuf,2);
xmpData_["Xmp.video.MediaLangCode"] = returnUnsignedBufValue(buf,2);
- else if (currentStream_ == Audio)
+ td = find(mediaLanguageCode,returnUnsignedBufValue(buf,2));
+ if(td) xmpData_["Xmp.video.MediaLanguage"] = Exiv2::StringValue(td->label_);
+ } else if (d->currentStream_ == Audio){
+ DataBuf tmpBuf((uint32_t)5);
+ tmpBuf.pData_[1] = buf.pData_[2];
+ tmpBuf.pData_[0] = buf.pData_[3];
+ xmpData_["Xmp.audio.Quality"] = returnUnsignedBufValue(tmpBuf,2);
xmpData_["Xmp.audio.MediaLangCode"] = returnUnsignedBufValue(buf,2);
+ td = find(mediaLanguageCode,returnUnsignedBufValue(buf,2));
+ if(td) xmpData_["Xmp.audio.MediaLanguage"] = Exiv2::StringValue(td->label_);
+ }
break;
-
- default:
- break;
+ default: io_->seek(4, BasicIo::cur); break;
}
}
io_->read(buf.pData_, size%4);
- } // QuickTimeVideo::mediaHeaderDecoder
+ } else {
+ RevTagDetails revTagDetails[(sizeof(mediaLanguageCode)/sizeof(mediaLanguageCode[0]))];
+ reverseTagDetails(mediaLanguageCode,revTagDetails,((sizeof(mediaLanguageCode)/sizeof(mediaLanguageCode[0]))));
- void QuickTimeVideo::trackHeaderDecoder(unsigned long size) {
- DataBuf buf(5);
- std::memset(buf.pData_, 0x0, buf.size_);
- buf.pData_[4] = '\0';
- int64_t temp = 0;
+ for (int32_t i = 0; size/4 != 0 ; size -=4, i++){
+ bool bDataWritten = false;
+ switch(i){
+ case MediaHeaderVersion:
+ bDataWritten = writeAudVidData("MediaHeaderVersion", 1, 1, 3, 0);
+ break;
+ case MediaCreateDate: bDataWritten = writeAudVidData("MediaCreateDate", 1, 4, 0, 1); break;
+ case MediaModifyDate: bDataWritten = writeAudVidData("MediaModifyDate", 1, 4, 0, 1); break;
+ case MediaTimeScale: bDataWritten = writeAudVidData("MediaTimeScale", 1, 4, -4, 0); break;
+ case MediaDuration:
+ io_->read(buf.pData_,4);
+ time_scale = returnBufValue(buf);
+ bDataWritten = writeAudVidData("MediaDuration", time_scale, 4, 0, 0); break;
+ case MediaLanguageCode:
+ if(d->currentStream_ == Video){
+ if(xmpData_["Xmp.video.MediaLanguage"].count() > 0){
+ rtd = find(revTagDetails,xmpData_["Xmp.video.MediaLanguage"].toString());
+ if(rtd){
+ buf = returnBuf(rtd->val_,2);
+ bDataWritten = writeMultibyte(buf.pData_,2);
+ }
+ }
+ if(!bDataWritten) io_->seek(2,BasicIo::cur);
+ bDataWritten = false;
+ if(xmpData_["Xmp.video.Quality"].count() >0){
+ buf = returnBuf((uint64_t)xmpData_["Xmp.video.Quality"].toLong(),2);
+ bDataWritten = writeMultibyte(&buf.pData_[1],1);
+ bDataWritten = writeMultibyte(&buf.pData_[0],1);
+ }
+ if(!bDataWritten) io_->seek(2,BasicIo::cur);
+ bDataWritten = true;
+ } else if (d->currentStream_ == Audio){
+ if(xmpData_["Xmp.audio.MediaLanguage"].count() > 0){
+ rtd = find(revTagDetails,xmpData_["Xmp.audio.MediaLanguage"].toString());
+ if(rtd){
+ buf = returnBuf(rtd->val_,2);
+ bDataWritten = writeMultibyte(buf.pData_,2);
+ }
+ }
+ if(!bDataWritten) io_->seek(2,BasicIo::cur);
+ bDataWritten = false;
- for (int i = 0; size/4 != 0 ; size -=4, i++) {
- io_->read(buf.pData_, 4);
+ if(xmpData_["Xmp.audio.Quality"].count() >0){
+ buf = returnBuf((uint64_t)xmpData_["Xmp.audio.Quality"].toLong(),2);
+ bDataWritten = writeMultibyte(&buf.pData_[1],1);
+ bDataWritten = writeMultibyte(&buf.pData_[0],1);
+ }
+ }
+ if(!bDataWritten) io_->seek(2,BasicIo::cur);
+ bDataWritten = true;
+ break;
+ }
+ if(!bDataWritten) io_->seek(4, BasicIo::cur);
+ }
+ io_->seek(size%4,BasicIo::cur);
+ }
+}
- switch(i) {
- case TrackHeaderVersion:
- if(currentStream_ == Video)
- xmpData_["Xmp.video.TrackHeaderVersion"] = returnBufValue(buf,1);
- else if(currentStream_ == Audio)
- xmpData_["Xmp.audio.TrackHeaderVersion"] = returnBufValue(buf,1);
- break;
- case TrackCreateDate:
- //A 32-bit integer that specifies (in seconds since midnight, January 1, 1904) when the movie atom was created.
- if(currentStream_ == Video)
- xmpData_["Xmp.video.TrackCreateDate"] = returnUnsignedBufValue(buf);
- else if(currentStream_ == Audio)
- xmpData_["Xmp.audio.TrackCreateDate"] = returnUnsignedBufValue(buf);
- break;
- case TrackModifyDate:
- //A 32-bit integer that specifies (in seconds since midnight, January 1, 1904) when the movie atom was created.
- if(currentStream_ == Video)
- xmpData_["Xmp.video.TrackModifyDate"] = returnUnsignedBufValue(buf);
- else if(currentStream_ == Audio)
- xmpData_["Xmp.audio.TrackModifyDate"] = returnUnsignedBufValue(buf);
- break;
- case TrackID:
- if(currentStream_ == Video)
- xmpData_["Xmp.video.TrackID"] = returnBufValue(buf);
- else if(currentStream_ == Audio)
- xmpData_["Xmp.audio.TrackID"] = returnBufValue(buf);
- break;
- case TrackDuration:
- if(currentStream_ == Video)
- xmpData_["Xmp.video.TrackDuration"] = returnBufValue(buf)/timeScale_;
- else if(currentStream_ == Audio)
- xmpData_["Xmp.audio.TrackDuration"] = returnBufValue(buf)/timeScale_;
- break;
- case TrackLayer:
- if(currentStream_ == Video)
- xmpData_["Xmp.video.TrackLayer"] = returnBufValue(buf, 2);
- else if(currentStream_ == Audio)
- xmpData_["Xmp.audio.TrackLayer"] = returnBufValue(buf, 2);
- break;
- case TrackVolume:
- if(currentStream_ == Video)
- xmpData_["Xmp.video.TrackVolume"] = (returnBufValue(buf, 1) + (buf.pData_[2] * 0.1)) * 100;
- else if(currentStream_ == Audio)
- xmpData_["Xmp.video.TrackVolume"] = (returnBufValue(buf, 1) + (buf.pData_[2] * 0.1)) * 100;
- break;
- case ImageWidth:
- if(currentStream_ == Video) {
- temp = returnBufValue(buf, 2) + static_cast((buf.pData_[2] * 256 + buf.pData_[3]) * 0.01);
+void QuickTimeVideo::trackHeaderDecoder(uint32_t size)
+{
+ DataBuf buf(5);
+ int64_t temp = 0;
+
+ if(!d->m_modifyMetadata){
+ for (int32_t i = 0; size/4 != 0 ; size -=4, i++){
+
+ switch(i){
+ case TrackHeaderVersion: readAudVidData("TrackHeaderVersion", 1, 1, 0); break;
+ case TrackCreateDate://A 32-bit integer that specifies (in seconds since midnight, January 1, 1904) when the movie atom was created.
+ readAudVidData("TrackCreateDate", 4, 1, 1); break;
+ case TrackModifyDate: //A 32-bit integer that specifies (in seconds since midnight, January 1, 1904) when the movie atom was created.
+ readAudVidData("TrackModifyDate", 4, 1, 1); break;
+ case TrackID: readAudVidData("TrackID", 4, 1, 0); break;
+ case TrackDuration: readAudVidData("TrackDuration", 4, (double)(1000/(double)d->timeScale_), 0); break;
+ case TrackLayer: readAudVidData("TrackLayer", 2, 1, 0); break;
+ case TrackVolume: readAudVidData("TrackVolume", 2, (double)(1/(double)2), 0); break;
+ case ImageWidth: io_->read(buf.pData_, 4);
+ if(d->currentStream_ == Video){
+ temp = (returnBufValue(buf, 4)/(256*256));
xmpData_["Xmp.video.Width"] = temp;
- width_ = temp;
+ d->width_ = temp;
}
break;
- case ImageHeight:
- if(currentStream_ == Video) {
- temp = returnBufValue(buf, 2) + static_cast((buf.pData_[2] * 256 + buf.pData_[3]) * 0.01);
+
+ case ImageHeight: io_->read(buf.pData_, 4);
+ if(d->currentStream_ == Video){
+ temp = (returnBufValue(buf, 4)/(256*256));
xmpData_["Xmp.video.Height"] = temp;
- height_ = temp;
+ d->height_ = temp;
}
break;
- default:
- break;
+ default: io_->seek(4 ,BasicIo::cur); break;
}
}
io_->read(buf.pData_, size%4);
- } // QuickTimeVideo::trackHeaderDecoder
- void QuickTimeVideo::movieHeaderDecoder(unsigned long size) {
- DataBuf buf(5);
- std::memset(buf.pData_, 0x0, buf.size_);
- buf.pData_[4] = '\0';
+ } else {
+ for (int32_t i = 0; size/4 != 0 ; size -=4, i++){
+ bool bDataWritten = false;
+ bool bVideo = d->currentStream_ == Video;
+ switch(i){
+ case TrackHeaderVersion: bDataWritten = writeAudVidData("TrackHeaderVersion", 1, 1, 3, 0); break;
+ case TrackCreateDate: bDataWritten = writeAudVidData("TrackCreateDate", 1, 4, 0, 1) ; break;
+ case TrackModifyDate: bDataWritten = writeAudVidData("TrackModifyDate", 1, 4, 0, 1) ; break;
+ case TrackID: bDataWritten = writeAudVidData("TrackID", 1, 4, 0, 0) ; break;
+ case TrackDuration: bDataWritten = writeAudVidData("TrackDuration", (double)(d->timeScale_/1000), 4, 0, 0); break;
+ case TrackLayer: bDataWritten = writeAudVidData("TrackLayer", 11, 2, 2, 0) ; break;
+ case TrackVolume: bDataWritten = writeAudVidData("TrackVolume", 2, 2, 2, 0) ; break;
+ case ImageWidth: if( bVideo ) bDataWritten = writeAudVidData("Width", (256*256), 4, 0, 0) ; break;
+ case ImageHeight:if( bVideo ) bDataWritten = writeAudVidData("Height", (256*256), 4, 0, 0) ; break;
+ }
+ if(!bDataWritten) io_->seek(4,BasicIo::cur);
+ }
+ io_->read(buf.pData_, size%4);
+ }
+}
- for (int i = 0; size/4 != 0 ; size -=4, i++) {
+bool QuickTimeVideo::writeAudVidData
+( std::string sXmpTag, double iMulFactor, int64_t iBytCnt, int64_t iOffset, int64_t iRetFuncCall)
+{
+ DataBuf buf(5);
+ bool bRetVal = false;
+ int64_t iXmpTagVal = 0;
+
+ if(d->currentStream_ == Video){
+ if(xmpData_["Xmp.video." + sXmpTag].count() > 0){
+ iXmpTagVal = xmpData_["Xmp.video." + sXmpTag].toLong()*iMulFactor;
+ if(iRetFuncCall == 0) buf = returnBuf(iXmpTagVal, iBytCnt);
+ else buf = returnUnsignedBuf(iXmpTagVal);
+ bRetVal = writeMultibyte(buf.pData_, iBytCnt ,iOffset);
+ }
+ }
+ else if(d->currentStream_ == Audio){
+ if(xmpData_["Xmp.audio." + sXmpTag].count() > 0){
+ iXmpTagVal = xmpData_["Xmp.audio." + sXmpTag].toLong()*iMulFactor;
+ if(iRetFuncCall == 0) buf = returnBuf(iXmpTagVal, iBytCnt);
+ else buf = returnUnsignedBuf(iXmpTagVal);
+ bRetVal = writeMultibyte(buf.pData_, iBytCnt ,iOffset);
+ }
+ }
+ return bRetVal;
+}
+
+void QuickTimeVideo::readAudVidData(std::string sTag, int32_t iNumRdBytes, double dMulFact ,int32_t iFunc2Call){
+ DataBuf buf(5);
+ io_->read(buf.pData_, 4);
+ if(d->currentStream_ == Video){
+ if(iFunc2Call == 0) xmpData_["Xmp.video."+ sTag] = (int64_t)(returnBufValue(buf, iNumRdBytes) * dMulFact) ;
+ else if(iFunc2Call == 1) xmpData_["Xmp.video."+ sTag] = (uint64_t)(returnUnsignedBufValue(buf, iNumRdBytes) * dMulFact);
+ }
+ else if(d->currentStream_ == Audio){
+ if(iFunc2Call == 0) xmpData_["Xmp.audio."+ sTag] = (int64_t)(returnBufValue(buf, iNumRdBytes) * dMulFact);
+ else if(iFunc2Call == 1)xmpData_["Xmp.audio."+ sTag] = (uint64_t)(returnUnsignedBufValue(buf, iNumRdBytes) * dMulFact);
+ }
+}
+
+void QuickTimeVideo::readAudVidStrData(std::string sTag, int32_t iNumRdBytes){
+ DataBuf buf(iNumRdBytes);
+ io_->read(buf.pData_, iNumRdBytes);
+ if(d->currentStream_ == Video) xmpData_["Xmp.video."+ sTag] = Exiv2::toString(buf.pData_);
+ else if(d->currentStream_ == Audio) xmpData_["Xmp.audio."+ sTag] = Exiv2::toString(buf.pData_);
+}
+
+void QuickTimeVideo::readStrData(std::string sTag, int32_t iNumRdBytes){
+ DataBuf buf(iNumRdBytes);
+ io_->read(buf.pData_, iNumRdBytes);
+ xmpData_[sTag] = Exiv2::toString(buf.pData_);
+}
+
+void QuickTimeVideo::movieHeaderDecoder(uint32_t size)
+{
+ DataBuf buf(5);
+
+ if(!d->m_modifyMetadata){
+ for (int32_t i = 0; size/4 != 0 ; size -=4, i++){
io_->read(buf.pData_, 4);
-
- switch(i) {
- case MovieHeaderVersion:
- xmpData_["Xmp.video.MovieHeaderVersion"] = returnBufValue(buf,1); break;
- case CreateDate:
- //A 32-bit integer that specifies (in seconds since midnight, January 1, 1904) when the movie atom was created.
- xmpData_["Xmp.video.DateUTC"] = returnUnsignedBufValue(buf); break;
- case ModifyDate:
- //A 32-bit integer that specifies (in seconds since midnight, January 1, 1904) when the movie atom was created.
- xmpData_["Xmp.video.ModificationDate"] = returnUnsignedBufValue(buf); break;
+ switch(i){
+ case MovieHeaderVersion: xmpData_["Xmp.video.MovieHeaderVersion"] = returnBufValue(buf,1) ; break;
+ case CreateDate: xmpData_["Xmp.video.DateUTC"] = returnUnsignedBufValue(buf) ; break;
+ case ModifyDate: xmpData_["Xmp.video.ModificationDate"] = returnUnsignedBufValue(buf) ; break;
+ case Duration: xmpData_["Xmp.video.Duration"] = (int64_t)((double)returnBufValue(buf)
+ * (double)1000/ (double)d->timeScale_); break;
+ case PreferredRate: xmpData_["Xmp.video.PreferredRate"] = returnBufValue(buf, 4)/(256*256) ; break;
+ case PreferredVolume: xmpData_["Xmp.video.PreferredVolume"] = (returnUnsignedBufValue(buf, 2)/2) ; break;
+ case PreviewTime: xmpData_["Xmp.video.PreviewTime"] = (int64_t)((double)returnBufValue(buf)
+ * (double)1000/ (double)d->timeScale_); break;
+ case PreviewDuration: xmpData_["Xmp.video.PreviewDuration"] = (int64_t)((double)returnBufValue(buf)
+ * (double)1000/ (double)d->timeScale_); break;
+ case PosterTime: xmpData_["Xmp.video.PosterTime"] = returnBufValue(buf) ; break;
+ case SelectionTime: xmpData_["Xmp.video.SelectionTime"] = returnBufValue(buf) ; break;
+ case SelectionDuration: xmpData_["Xmp.video.SelectionDuration"] = returnBufValue(buf)*1000/ d->timeScale_; break;
+ case CurrentTime: xmpData_["Xmp.video.CurrentTime"] = returnBufValue(buf) ; break;
+ case NextTrackID: xmpData_["Xmp.video.NextTrackID"] = returnBufValue(buf) ; break;
case TimeScale:
xmpData_["Xmp.video.TimeScale"] = returnBufValue(buf);
- timeScale_ = returnBufValue(buf); break;
- case Duration:
- if(timeScale_ != 0) // To prevent division by zero
- xmpData_["Xmp.video.Duration"] = returnBufValue(buf) * 1000 / timeScale_; break;
- case PreferredRate:
- xmpData_["Xmp.video.PreferredRate"] = returnBufValue(buf, 2) + ((buf.pData_[2] * 256 + buf.pData_[3]) * 0.01); break;
- case PreferredVolume:
- xmpData_["Xmp.video.PreferredVolume"] = (returnBufValue(buf, 1) + (buf.pData_[2] * 0.1)) * 100; break;
- case PreviewTime:
- xmpData_["Xmp.video.PreviewTime"] = returnBufValue(buf); break;
- case PreviewDuration:
- xmpData_["Xmp.video.PreviewDuration"] = returnBufValue(buf); break;
- case PosterTime:
- xmpData_["Xmp.video.PosterTime"] = returnBufValue(buf); break;
- case SelectionTime:
- xmpData_["Xmp.video.SelectionTime"] = returnBufValue(buf); break;
- case SelectionDuration:
- xmpData_["Xmp.video.SelectionDuration"] = returnBufValue(buf); break;
- case CurrentTime:
- xmpData_["Xmp.video.CurrentTime"] = returnBufValue(buf); break;
- case NextTrackID:
- xmpData_["Xmp.video.NextTrackID"] = returnBufValue(buf); break;
- default:
+ d->timeScale_ = returnBufValue(buf);
break;
}
}
io_->read(buf.pData_, size%4);
- } // QuickTimeVideo::movieHeaderDecoder
+ } else {
+ for (int32_t i = 0; size/4 != 0 ; size -=4, i++){
+ bool bDataWritten = false;
+ std::memset(buf.pData_, 0x0, buf.size_);
+ switch(i){
+ //Fixme:There are known roundoff error while typecasting the number to int64_t
+ //for example Duration (double to int64_t)
+ case MovieHeaderVersion:
+ if(xmpData_["Xmp.video.MovieHeaderVersion"].count() > 0){
+ int64_t movieHeaderVersion = (int64_t)xmpData_["Xmp.video.MovieHeaderVersion"].toLong();
+ buf = returnBuf(movieHeaderVersion,1);
+ bDataWritten = writeMultibyte(&buf.pData_[0], 1, 3);
+ }
+ break;
- void QuickTimeVideo::aspectRatio()
- {
- //TODO - Make a better unified method to handle all cases of Aspect Ratio
+ case CreateDate:
+ if(xmpData_["Xmp.video.DateUTC"].count() > 0){
+ uint64_t dateUTC = (uint64_t)xmpData_["Xmp.video.DateUTC"].toLong();
+ buf = returnUnsignedBuf(dateUTC);
+ bDataWritten = writeMultibyte(buf.pData_,4);
+ }
+ break;
- double aspectRatio = (double)width_ / (double)height_;
- aspectRatio = floor(aspectRatio*10) / 10;
- xmpData_["Xmp.video.AspectRatio"] = aspectRatio;
+ case ModifyDate:
+ if(xmpData_["Xmp.video.ModificationDate"].count() > 0){
+ uint64_t modificationDate = (uint64_t)xmpData_["Xmp.video.ModificationDate"].toLong();
+ buf = returnUnsignedBuf(modificationDate);
+ bDataWritten = writeMultibyte(buf.pData_,4);
+ }
+ break;
- int aR = (int) ((aspectRatio*10.0)+0.1);
+ case TimeScale:
+ if(xmpData_["Xmp.video.TimeScale"].count() > 0){
+ io_->read(buf.pData_,4);
+ d->timeScale_ = returnBufValue(buf);
+ io_->seek(-4,BasicIo::cur);
+ int64_t tmpTimeScale = (int64_t)xmpData_["Xmp.video.TimeScale"].toLong();
+ buf = returnBuf(tmpTimeScale);
+ bDataWritten = writeMultibyte(buf.pData_,4);
+ } else {
+ io_->read(buf.pData_,4);
+ d->timeScale_ = returnBufValue(buf);
+ bDataWritten = true;
+ }
+ break;
- switch (aR) {
- case 13 : xmpData_["Xmp.video.AspectRatio"] = "4:3" ; break;
- case 17 : xmpData_["Xmp.video.AspectRatio"] = "16:9" ; break;
- case 10 : xmpData_["Xmp.video.AspectRatio"] = "1:1" ; break;
- case 16 : xmpData_["Xmp.video.AspectRatio"] = "16:10" ; break;
- case 22 : xmpData_["Xmp.video.AspectRatio"] = "2.21:1" ; break;
- case 23 : xmpData_["Xmp.video.AspectRatio"] = "2.35:1" ; break;
- case 12 : xmpData_["Xmp.video.AspectRatio"] = "5:4" ; break;
- default : xmpData_["Xmp.video.AspectRatio"] = aspectRatio;break;
- }
- } // QuickTimeVideo::aspectRatio
+ case Duration:
+ if(xmpData_["Xmp.video.Duration"].count() > 0){
+ int64_t duration = (int64_t)((double)xmpData_["Xmp.video.Duration"].
+ toLong()*(double)d->timeScale_/(double)1000);
+ buf = returnBuf(duration);
+ bDataWritten = writeMultibyte(buf.pData_,4);
+ }
+ break;
+ case PreferredRate:
+ if(xmpData_["Xmp.video.PreferredRate"].count() > 0){
+ buf = returnBuf((int64_t)xmpData_["Xmp.video.PreferredRate"].toLong()
+ *(256*256),4);
+ bDataWritten = writeMultibyte(buf.pData_,4);
+ }
+ break;
- Image::AutoPtr newQTimeInstance(BasicIo::AutoPtr io, bool /*create*/) {
- Image::AutoPtr image(new QuickTimeVideo(io));
- if (!image->good()) {
- image.reset();
+ case PreferredVolume:
+ if(xmpData_["Xmp.video.PreferredVolume"].count() > 0){
+ uint64_t preferredVolume = (uint64_t)(xmpData_["Xmp.video.PreferredVolume"]
+ .toLong()*2);//128 = 100%
+ buf = returnBuf(preferredVolume,2);
+ bDataWritten = writeMultibyte(buf.pData_, 2, 2);
+ }
+ break;
+
+ case PreviewTime:
+ if(xmpData_["Xmp.video.PreviewTime"].count() > 0){
+ int64_t previewTime = (int64_t)((double)xmpData_["Xmp.video.PreviewTime"].toLong()
+ *(double)d->timeScale_/(double)1000);//1024= 1 second
+ buf = returnBuf(previewTime);
+ bDataWritten = writeMultibyte(buf.pData_,4);
+ }
+ break;
+
+ case PreviewDuration:
+ if(xmpData_["Xmp.video.PreviewDuration"].count() > 0){
+ int64_t previewDuration = (int64_t)((double)xmpData_["Xmp.video.PreviewDuration"]
+ .toLong()*(double)d->timeScale_/(double)1000);
+ buf = returnBuf(previewDuration);
+ bDataWritten = writeMultibyte(buf.pData_,4);
+ }
+ break;
+
+ case PosterTime:
+ if(xmpData_["Xmp.video.PosterTime"].count() > 0){
+ int64_t posterTime = (int64_t)xmpData_["Xmp.video.PosterTime"].toLong();
+ buf = returnBuf(posterTime);
+ bDataWritten = writeMultibyte(buf.pData_,4);
+ }
+ break;
+
+ case SelectionTime:
+ if(xmpData_["Xmp.video.SelectionTime"].count() > 0){
+ int64_t selectionTime = (int64_t)xmpData_["Xmp.video.SelectionTime"].toLong();
+ buf = returnBuf(selectionTime);
+ bDataWritten = writeMultibyte(buf.pData_,4);
+ }
+ break;
+
+ case SelectionDuration:
+ if(xmpData_["Xmp.video.SelectionDuration"].count() > 0){
+ int64_t selectionDuration = (int64_t)((double)xmpData_["Xmp.video.SelectionDuration"]
+ .toLong()*(double)d->timeScale_/(double)1000);
+ buf = returnBuf(selectionDuration);
+ bDataWritten = writeMultibyte(buf.pData_,4);
+ }
+ break;
+
+ case CurrentTime:
+ if(xmpData_["Xmp.video.CurrentTime"].count() > 0){
+ int64_t currentTime = (int64_t)xmpData_["Xmp.video.CurrentTime"].toLong();
+ buf = returnBuf(currentTime);
+ bDataWritten = writeMultibyte(buf.pData_,4);
+ }
+ break;
+
+ case NextTrackID:
+ if(xmpData_["Xmp.video.NextTrackID"].count() > 0){
+ int64_t nextTrackID = (int64_t)xmpData_["Xmp.video.NextTrackID"].toLong();
+ buf = returnBuf(nextTrackID);
+ bDataWritten = writeMultibyte(buf.pData_,4);
+ }
+ break;
+ }
+ if(!bDataWritten) io_->seek(4, BasicIo::cur);
}
- return image;
+ io_->seek(size%4,BasicIo::cur);
+ }
+}
+
+void QuickTimeVideo::aspectRatio()
+{
+ //TODO - Make a better unified method to handle all cases of Aspect Ratio
+
+ double aspectRatio = (double)d->width_ / (double)d->height_;
+ aspectRatio = floor(aspectRatio*10) / 10;
+ xmpData_["Xmp.video.AspectRatio"] = aspectRatio;
+
+ int32_t aR = (int32_t) ((aspectRatio*10.0)+0.1);
+
+ switch (aR) {
+ case 13 : xmpData_["Xmp.video.AspectRatio"] = "4:3" ; break;
+ case 17 : xmpData_["Xmp.video.AspectRatio"] = "16:9" ; break;
+ case 10 : xmpData_["Xmp.video.AspectRatio"] = "1:1" ; break;
+ case 16 : xmpData_["Xmp.video.AspectRatio"] = "16:10" ; break;
+ case 22 : xmpData_["Xmp.video.AspectRatio"] = "2.21:1" ; break;
+ case 23 : xmpData_["Xmp.video.AspectRatio"] = "2.35:1" ; break;
+ case 12 : xmpData_["Xmp.video.AspectRatio"] = "5:4" ; break;
+ default : xmpData_["Xmp.video.AspectRatio"] = aspectRatio;break; // needed?
+ }
+}
+
+void QuickTimeVideo::reverseTagDetails
+(const TagDetails inputTagVocabulary[], RevTagDetails outputTagVocabulary[] ,int32_t size)
+{
+ for (int32_t i=0; igood()) image.reset();
+ return image;
+}
+
+void QuickTimeVideo::writeStringData(Exiv2::Xmpdatum xmpStringData, int32_t size, int32_t skipOffset)
+{
+ if(xmpStringData.count() > 0){
+ std::string dataString = xmpStringData.toString();
+ Exiv2::byte* rawData = new byte[(uint8_t)size];
+ int32_t newSize = (int32_t)dataString.size();
+
+ for(int32_t i=0; iwrite(rawData,size);
+ io_->seek((int)skipOffset,BasicIo::cur);
+ delete[] rawData;
+ } else io_->seek((size+skipOffset),BasicIo::cur);
+}
+
+void QuickTimeVideo::writeLongData(Exiv2::Xmpdatum xmpIntData, int32_t size, int32_t skipOffset)
+{
+ if(xmpIntData.count() > 0){
+ int32_t rawIntData = (int32_t)xmpIntData.toLong();
+ io_->write((Exiv2::byte*)&rawIntData,size);
+ io_->seek(skipOffset,BasicIo::cur);
+ }
+ else io_->seek((size+skipOffset),BasicIo::cur);
+}
+
+void QuickTimeVideo::writeShortData(Exiv2::Xmpdatum xmpIntData, int16_t size, int32_t skipOffset)
+{
+ if(xmpIntData.count() > 0){
+ int16_t rawIntData = (int16_t)xmpIntData.toLong();
+ io_->write((Exiv2::byte*)&rawIntData,size);
+ io_->seek(skipOffset,BasicIo::cur);
+ }
+ else io_->seek((size+skipOffset),BasicIo::cur);
+}
+
+/*!
+ * \brief QuickTimeVideo::writeMultibyte Write data directly from acurrent position of basicIo poiter with the bRawData upto size number of bytes
+ * and then skips iOffset bytes.
+ * \param bRawData
+ * \param iSize
+ * \param iOffset
+ * \return
+ */
+bool QuickTimeVideo::writeMultibyte(Exiv2::byte * bRawData ,int64_t iSize, int64_t iOffset)
+{
+ int32_t iCurrPos = io_->tell();
+ if (iSize != 0 && bRawData != NULL){
+ if ((io_->write(bRawData, iSize) > 0)) io_->seek(iOffset , BasicIo::cur);
+ else io_->seek(iCurrPos + iSize + iOffset, BasicIo::beg);
+ }
+ else io_->seek(iCurrPos + iOffset, BasicIo::beg);
+
+ //Return value is just for assignment to a variable at calling location.
+ return true;
+}
+
+void QuickTimeVideo::writeApertureData(Exiv2::Xmpdatum xmpApertureData, int16_t size, int32_t skipOffset)
+{
+ if(xmpApertureData.count() >0){
+ Exiv2::byte rawApertureData[4];
+ Exiv2::byte rawApertureDataTmp[2];
+ const std::string apertureData = xmpApertureData.toString();
+ vector apertureDataValue = getNumberFromString(apertureData,'.');
+ memcpy(rawApertureDataTmp,&apertureDataValue.at(0),2);
+ rawApertureData[0] = rawApertureDataTmp[0];
+ rawApertureData[1] = rawApertureDataTmp[1];
+ memcpy(rawApertureDataTmp,&apertureDataValue.at(1),2);
+ rawApertureData[2] = rawApertureDataTmp[0];
+ rawApertureData[3] = rawApertureDataTmp[1];
+ io_->write(rawApertureData,size);
+ io_->seek(skipOffset,BasicIo::cur);
+ }
+ else io_->seek((size+skipOffset),BasicIo::cur);
+}
+
+/*!
+ * \brief isQTimeType Cheecks if file belongs to Quicktime container type.
+ * \param iIo
+ * \param advance
+ * \return
+ */
+bool isQTimeType(BasicIo& iIo, bool advance){
+ const int32_t len = 4;
+ Exiv2::byte* buf = new byte[len];
+ iIo.read(buf, len);
+ iIo.read(buf, len);
+
+ if (iIo.error() || iIo.eof()){
+ delete[] buf;
+ return false;
}
- bool isQTimeType(BasicIo& iIo, bool advance) {
- const int32_t len = 4;
- byte buf[len];
- iIo.read(buf, len);
- iIo.read(buf, len);
-
- if (iIo.error() || iIo.eof()) {
- return false;
- }
-
- bool matched = isQuickTimeType(buf[0], buf[1], buf[2], buf[3]);
- if (!advance || !matched) {
- iIo.seek(static_cast(0), BasicIo::beg);
- }
-
- return matched;
- }
-
-} // namespace Exiv2
-
+ bool matched = isQuickTimeType(buf[0], buf[1], buf[2], buf[3]);
+ if (!advance || !matched) iIo.seek(static_cast(0), BasicIo::beg);
+ delete[] buf;
+ return matched;
+} // isQTimeType
+} // namespace Exiv2
diff --git a/src/quicktimevideo.hpp b/src/quicktimevideo.hpp
index 9a8b1d47..4ae2ef45 100644
--- a/src/quicktimevideo.hpp
+++ b/src/quicktimevideo.hpp
@@ -22,13 +22,16 @@
@file quicktimevideo.hpp
@brief An Image subclass to support Quick Time video files
@version $Rev$
- @author Abhinav Badola for GSoC 2012
+ @authors Abhinav Badola for GSoC 2012
mail.abu.to@gmail.com
+ Mahesh Hegde for GSoC 2013
+ maheshmhegade@gmail.com
@date 28-Jun-12, AB: created
*/
#ifndef QUICKTIMEVIDEO_HPP
#define QUICKTIMEVIDEO_HPP
-
+#include
+using namespace std;
// *****************************************************************************
// included header files
#include "exif.hpp"
@@ -42,20 +45,36 @@ namespace Exiv2 {
// *****************************************************************************
// class definitions
- // Add qtime to the supported image formats
- namespace ImageType {
- const int qtime = 22; //!< Treating qtime as an image type>
- }
+// Add qtime to the supported image formats
+namespace ImageType {
+const int qtime = 22; //!< Treating qtime as an image type>
+}
- /*!
+/*!
@brief Class to access QuickTime video files.
*/
- class EXIV2API QuickTimeVideo:public Image
+class EXIV2API QuickTimeVideo:public Image
+{
+public:
+ /*!
+ * \brief The QuickAtom class:
+ *Object of this class is intended to contain data about the premitive atom inside
+ *any atom
+ */
+ class QuickAtom
{
public:
- //! @name Creators
- //@{
- /*!
+ QuickAtom(){}
+ ~QuickAtom(){}
+ public:
+ byte m_AtomId[5]; //!< Id of the Atom.
+ unsigned long m_AtomLocation; //!< Location of atom inside a file
+ unsigned long m_AtomSize; //!< Size of atom
+ };
+public:
+ //! @name Creators
+ //@{
+ /*!
@brief Constructor for a QuickTime video. Since the constructor
can not return a result, callers should check the good() method
after object construction to determine success or failure.
@@ -66,27 +85,28 @@ namespace Exiv2 {
instance after it is passed to this method. Use the Image::io()
method to get a temporary reference.
*/
- QuickTimeVideo(BasicIo::AutoPtr io);
- //@}
+ QuickTimeVideo(BasicIo::AutoPtr io);
+ //@}
- //! @name Manipulators
- //@{
- void readMetadata();
- void writeMetadata();
- //@}
+ ~QuickTimeVideo();
+ //! @name Manipulators
+ //@{
+ void readMetadata();
+ void writeMetadata();
+ //@}
- //! @name Accessors
- //@{
- std::string mimeType() const;
- //@}
+ //! @name Accessors
+ //@{
+ std::string mimeType() const;
+ //@}
- protected:
- /*!
+protected:
+ /*!
@brief Check for a valid tag and decode the block at the current IO
position. Calls tagDecoder() or skips to next tag, if required.
*/
- void decodeBlock();
- /*!
+ void decodeBlock();
+ /*!
@brief Interpret tag information, and call the respective function
to save it in the respective XMP container. Decodes a Tag
Information and saves it in the respective XMP container, if
@@ -94,159 +114,236 @@ namespace Exiv2 {
@param buf Data buffer which cotains tag ID.
@param size Size of the data block used to store Tag Information.
*/
- void tagDecoder(Exiv2::DataBuf & buf, unsigned long size);
+ void tagDecoder(Exiv2::DataBuf & buf, uint32_t size);
- private:
- /*!
+private:
+ /*!
@brief Interpret file type of the video, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void fileTypeDecoder(unsigned long size);
- /*!
+ void fileTypeDecoder(uint32_t size);
+ /*!
@brief Interpret Media Header Tag, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void mediaHeaderDecoder(unsigned long size);
- /*!
+ void mediaHeaderDecoder(uint32_t size);
+ /*!
@brief Interpret Video Header Tag, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void videoHeaderDecoder(unsigned long size);
- /*!
+ void videoHeaderDecoder(uint32_t size);
+ /*!
@brief Interpret Movie Header Tag, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void movieHeaderDecoder(unsigned long size);
- /*!
+ void movieHeaderDecoder(uint32_t size);
+ /*!
@brief Interpret Track Header Tag, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void trackHeaderDecoder(unsigned long size);
- /*!
+ void trackHeaderDecoder(uint32_t size);
+ /*!
@brief Interpret Handler Tag, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void handlerDecoder(unsigned long size);
- /*!
+ void handlerDecoder(uint32_t size);
+ /*!
@brief Interpret Tag which contain other sub-tags,
and save it in the respective XMP container.
*/
- void multipleEntriesDecoder();
- /*!
+ void multipleEntriesDecoder(uint32_t iDummySize);
+ /*!
@brief Interpret Sample Description Tag, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void sampleDesc(unsigned long size);
- /*!
+ void sampleDesc(uint32_t size);
+ /*!
@brief Interpret Image Description Tag, and save it
in the respective XMP container.
*/
- void imageDescDecoder();
- /*!
+ void imageDescDecoder();
+ /*!
@brief Interpret User Data Tag, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void userDataDecoder(unsigned long size);
- /*!
+ void userDataDecoder(uint32_t size);
+ /*!
@brief Interpret Preview Tag, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void previewTagDecoder(unsigned long size);
- /*!
+ void previewTagDecoder(uint32_t size);
+ /*!
@brief Interpret Meta Keys Tags, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void keysTagDecoder(unsigned long size);
- /*!
+ void keysTagDecoder(uint32_t size);
+ /*!
@brief Interpret Track Aperture Tags, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void trackApertureTagDecoder(unsigned long size);
- /*!
+ void trackApertureTagDecoder(uint32_t size);
+ /*!
@brief Interpret Nikon Tag, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void NikonTagsDecoder(unsigned long size);
- /*!
+ void NikonTagsDecoder(uint32_t size);
+ /*!
@brief Interpret Tags from Different Camera make, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void CameraTagsDecoder(unsigned long size);
- /*!
+ void CameraTagsDecoder(uint32_t size);
+ /*!
@brief Interpret Audio Description Tag, and save it
in the respective XMP container.
*/
- void audioDescDecoder();
- /*!
+ void audioDescDecoder();
+ /*!
@brief Helps to calculate Frame Rate from timeToSample chunk,
and save it in the respective XMP container.
*/
- void timeToSampleDecoder();
- /*!
+ void timeToSampleDecoder(uint32_t iDummySize);
+ /*!
@brief Recognizes which stream is currently under processing,
and save its information in currentStream_ .
*/
- void setMediaStream();
- /*!
- @brief Used to discard a tag along with its data. The Tag will
- be skipped and not decoded.
- @param size Size of the data block that is to skipped.
- */
- void discard(unsigned long size);
- /*!
+ void setMediaStream(uint32_t iDummySize);
+ /*!
@brief Calculates Aspect Ratio of a video, and stores it in the
respective XMP container.
*/
- void aspectRatio();
+ void aspectRatio();
+ /*!
+ * \brief reverseTagDetails
+ * \param inputTagVocabulary
+ * \param outputTagVocabulary
+ * \param size
+ */
+ void reverseTagDetails(const Internal::TagDetails inputTagVocabulary[],
+ Internal::RevTagDetails outputTagVocabulary[] , int32_t size);
- private:
- //! @name NOT Implemented
- //@{
- //! Copy constructor
- QuickTimeVideo(const QuickTimeVideo& rhs);
- //! Assignment operator
- QuickTimeVideo& operator=(const QuickTimeVideo& rhs);
- //@}
+private:
+ //! @name NOT Implemented
+ //@{
+ //! Copy constructor
+ QuickTimeVideo(const QuickTimeVideo& rhs);
+ //! Assignment operator
+ QuickTimeVideo& operator=(const QuickTimeVideo& rhs);
+ //@}
+ /*!
+ @brief Provides the main implementation of writeMetadata() by
+ writing all buffered metadata to the provided BasicIo.
+ @param oIo BasicIo instance to write to (a temporary location).
- private:
- //! Variable which stores Time Scale unit, used to calculate time.
- uint64_t timeScale_;
- //! Variable which stores current stream being processsed.
- int currentStream_;
- //! Variable to check the end of metadata traversing.
- bool continueTraversing_;
- //! Variable to store height and width of a video frame.
- uint64_t height_, width_;
+ @return 4 if opening or writing to the associated BasicIo fails
+ */
+ EXV_DLLLOCAL void doWriteMetadata();
+ /*!
+ * \brief findAtomPositions
+ * \param atomId
+ * \return all the locations where atoms with atomId exist.
+ */
+ std::vector< pair > findAtomPositions(const char *atomId);
- }; //QuickTimeVideo End
+ /*!
+ * \brief writeStringData
+ * \param xmpStringData
+ * \param size
+ * \param skipOffset
+ */
+ void writeStringData(Exiv2::Xmpdatum xmpStringData, int32_t size, int32_t skipOffset=0);
+
+ /*!
+ * \brief writeLongData
+ * \param xmpIntData
+ * \param size
+ * \param skipOffset
+ */
+ void writeLongData(Exiv2::Xmpdatum xmpIntData, int32_t size=4, int32_t skipOffset=0);
+
+ /*!
+ * \brief writeShortData
+ * \param xmpIntData
+ * \param size
+ * \param skipOffset
+ */
+ void writeShortData(Exiv2::Xmpdatum xmpIntData, int16_t size=2, int32_t skipOffset=0);
+
+ /*!
+ * \brief writeMultibyte
+ * \param bRawData
+ * \param size
+ */
+ bool writeMultibyte(Exiv2::byte * bRawData = NULL , int64_t iSize = 0, int64_t iOffset = 0);
+
+ /*!
+ * \brief writeApertureData
+ * \param xmpIntData
+ * \param size
+ * \param skipOffset
+ */
+ void writeApertureData(Exiv2::Xmpdatum xmpIntData, int16_t size, int32_t skipOffset=0);
+
+ /*!
+ * \brief writeAudVidData
+ * \param iTagType
+ * \return
+ */
+ bool writeAudVidData(int64_t iTagType);
+
+ /*!
+ * \brief writeAudVidData
+ * \param sXmpTag
+ * \param iOffset
+ * \return
+ */
+ bool writeAudVidData( std::string sXmpTag, double iMulFactor, int64_t iBytCnt, int64_t iOffset, int64_t iRetFuncCall);
+
+ /*!
+ * \brief readAudVidData
+ * \param sTag
+ * \param iNumRdBytes
+ * \param dMulFact
+ * \param iFunc2Call
+ */
+ void readAudVidData(std::string sTag, int32_t iNumRdBytes, double dMulFact ,int32_t iFunc2Call);
+
+ void readAudVidStrData(std::string sTag, int32_t iNumRdBytes);
+ void readStrData(std::string sTag, int32_t iNumRdBytes);
+
+private:
+
+ class Private;
+ Private * const d;
+
+}; //QuickTimeVideo End
// *****************************************************************************
// template, inline and free functions
- // These could be static private functions on Image subclasses but then
- // ImageFactory needs to be made a friend.
- /*!
+// These could be static private functions on Image subclasses but then
+// ImageFactory needs to be made a friend.
+/*!
@brief Create a new QuicktimeVideo instance and return an auto-pointer to it.
Caller owns the returned object and the auto-pointer ensures that
it will be deleted.
*/
- EXIV2API Image::AutoPtr newQTimeInstance(BasicIo::AutoPtr io, bool create);
+EXIV2API Image::AutoPtr newQTimeInstance(BasicIo::AutoPtr io, bool create);
- //! Check if the file iIo is a Quick Time Video.
- EXIV2API bool isQTimeType(BasicIo& iIo, bool advance);
+//! Check if the file iIo is a Quick Time Video.
+EXIV2API bool isQTimeType(BasicIo& iIo, bool advance);
} // namespace Exiv2
diff --git a/src/riffvideo.cpp b/src/riffvideo.cpp
index 0dcd291c..b8a424b8 100644
--- a/src/riffvideo.cpp
+++ b/src/riffvideo.cpp
@@ -1,6 +1,6 @@
// ***************************************************************** -*- C++ -*-
/*
- * Copyright (C) 2004-2013 Andreas Huggel
+ * Copyright (C) 2004-2012 Andreas Huggel
*
* This program is part of the Exiv2 distribution.
*
@@ -22,6 +22,7 @@
File: riffvideo.cpp
Version: $Rev$
Author(s): Abhinav Badola for GSoC 2012 (AB)
+ Mahesh Hegde for GSoC 2013 mailto:maheshmhegade at gmail dot com
History: 18-Jun-12, AB: created
Credits: See header file
*/
@@ -38,18 +39,21 @@ EXIV2_RCSID("@(#) $Id$")
#include "tags_int.hpp"
#include "types.hpp"
#include "tiffimage_int.hpp"
+#include "string.h"
+#include "utilsvideo.hpp"
+
// + standard includes
#include
// *****************************************************************************
// class member definitions
-namespace Exiv2 {
- namespace Internal {
+namespace Exiv2{
+ namespace Internal{
/*!
@brief Dummy TIFF header structure.
*/
- class DummyTiffHeader : public TiffHeaderBase {
+ class DummyTiffHeader : public TiffHeaderBase{
public:
//! @name Creators
//@{
@@ -62,26 +66,24 @@ namespace Exiv2 {
//! @name Manipulators
//@{
//! Dummy read function. Does nothing and returns true.
- bool read(const byte* pData, uint32_t size);
+ bool read(const byte* pData, uint64_t size);
//@}
}; // class TiffHeader
DummyTiffHeader::DummyTiffHeader(ByteOrder byteOrder)
- : TiffHeaderBase(42, 0, byteOrder, 0)
- {
+ : TiffHeaderBase(42, 0, byteOrder, 0){
}
- DummyTiffHeader::~DummyTiffHeader()
- {
+ DummyTiffHeader::~DummyTiffHeader(){
}
- bool DummyTiffHeader::read(const byte* /*pData*/, uint32_t /*size*/)
- {
+ bool DummyTiffHeader::read(const byte* /*pData*/, uint64_t /*size*/){
return true;
}
- extern const TagVocabulary infoTags[] = {
+ //! RIFF INFO tags supported Under Exiv2.
+ extern const TagVocabulary infoTags[] ={
{ "AGES", "Xmp.video.Rated" },
{ "CMNT", "Xmp.video.Comment" },
{ "CODE", "Xmp.video.EncodedBy" },
@@ -168,7 +170,8 @@ namespace Exiv2 {
{ "YEAR", "Xmp.video.Year" }
};
- extern const TagDetails audioEncodingValues[] = {
+ //! Audio Encoding Information.
+ extern const TagDetails audioEncodingValues[] ={
{ 0x1, "Microsoft PCM" },
{ 0x2, "Microsoft ADPCM" },
{ 0x3, "Microsoft IEEE float" },
@@ -414,7 +417,8 @@ namespace Exiv2 {
{ 0xffff, "Development" }
};
- extern const TagDetails nikonAVITags[] = {
+ //! Nikon tags.
+ extern const TagDetails nikonAVITags[] ={
{ 0x0003, "Xmp.video.Make" },
{ 0x0004, "Xmp.video.Model" },
{ 0x0005, "Xmp.video.Software" },
@@ -452,7 +456,8 @@ namespace Exiv2 {
{ 8, "Rotate 270 CW" }
};
*/
- extern const TagDetails meteringMode[] = {
+ //! Metering tags.
+ extern const TagDetails meteringMode[] ={
{ 0, "Unknown" },
{ 1, "Average" },
{ 2, "Center-weighted average" },
@@ -463,335 +468,624 @@ namespace Exiv2 {
{ 255, "Other" }
};
- extern const TagDetails resolutionUnit[] = {
+ //!Resolution tag.
+ extern const TagDetails resolutionUnit[] ={
{ 1, "None" },
{ 2, "inches" },
{ 3, "cm" }
};
- /*!
- @brief Function used to check equality of a Tags with a
- particular string (ignores case while comparing).
- @param buf Data buffer that will contain Tag to compare
- @param str char* Pointer to string
- @return Returns true if the buffer value is equal to string.
- */
- bool equalsRiffTag(Exiv2::DataBuf& buf ,const char* str) {
- for(int i = 0; i < 4; i++ )
- if(toupper(buf.pData_[i]) != str[i])
- return false;
- return true;
- }
+ int64_t i; //!< temporary variable.
+ int64_t j; //!< temporary variable.
- enum streamTypeInfo {
+ //! To select specific bytes with in a chunk.
+ enum streamTypeInfo{
Audio = 1, MIDI, Text, Video
};
- enum streamHeaderTags {
+
+ //! To select specific bytes with in a chunk.
+ enum streamHeaderTags{
codec = 1, sampleRate = 5, sampleCount = 8, quality = 10, sampleSize
};
- enum bmptags {
+
+ //! To select specific bytes with in a chunk.
+ enum bmptags{
imageWidth, imageHeight, planes, bitDepth, compression, imageLength, pixelsPerMeterX, pixelsPerMeterY, numColors, numImportantColors
};
- enum audioFormatTags {
+
+ //! To select specific bytes with in a chunk.
+ enum audioFormatTags{
encoding, numberOfChannels, audioSampleRate, avgBytesPerSec = 4, bitsPerSample = 7
};
- enum aviHeaderTags {
- frameRate, maxDataRate, frameCount = 4, streamCount = 6, imageWidth_h = 8, imageHeight_h
+
+ //! To select specific bytes with in a chunk.
+ enum aviHeaderTags{
+ frameRate, maxDataRate, frameCount = 4, initialFrames ,streamCount, suggestedBufferSize ,imageWidth_h, imageHeight_h
};
-}} // namespace Internal, Exiv2
+ }
+} // namespace Internal, Exiv2
-namespace Exiv2 {
- using namespace Exiv2::Internal;
+namespace Exiv2{
+using namespace Exiv2::Internal;
- RiffVideo::RiffVideo(BasicIo::AutoPtr io)
- : Image(ImageType::riff, mdNone, io)
- {
- } // RiffVideo::RiffVideo
+class RiffVideo::Private{
+public:
+ Private(){
+ streamType_ = 0;
+ m_decodeMetaData = true;
+ }
+ //! Variable which stores current stream being processsed.
+ int streamType_;
+ //! Variable to decide whether to decode the metadata or just reveal file structure (Lists inside RIFF)
+ bool m_decodeMetaData;
+ //!variable to decide whether write metadata is possible or not (by default false)
+ bool m_modifyMetadata;
+ //!abstract metadata holding variable (its data about data about data!)
+ RiffMetaSkeleton m_riffFileSkeleton;
+};
- std::string RiffVideo::mimeType() const
- {
- return "video/riff";
+RiffVideo::RiffVideo(BasicIo::AutoPtr io)
+ : Image(ImageType::riff, mdNone, io), d(new Private){
+ d->m_modifyMetadata = false;
+ d->m_decodeMetaData = true;
+} // RiffVideo::RiffVideo
+
+RiffVideo::~RiffVideo(){
+ delete d;
+}
+
+std::string RiffVideo::mimeType() const{
+ return "video/riff";
+}
+
+/*!
+ * \brief RiffVideo::findChunkPositions:
+ * Return a list of chunk positions for a given chunk Id
+ * \param chunkId
+ * \return: if No chunk of chunkId exists,then size of returned
+ * vector will be zero
+ */
+std::vector RiffVideo::findChunkPositions(const char* chunkId){
+ DataBuf chkId((uint64_t)5);
+ chkId.pData_[4] = '\0';
+ uint64_t i;
+
+ std::vector positions;
+ for ( i=0; im_riffFileSkeleton.m_primitiveChunks.size(); i++){
+ io_->seek(d->m_riffFileSkeleton.m_primitiveChunks[i]->m_chunkLocation,BasicIo::beg);
+ io_->read(chkId.pData_,4);
+ if(UtilsVideo::compareTagValue(chkId,chunkId)) positions.push_back((int32_t)io_->tell());
+ }
+ return positions;
+}
+
+//Same as above but returns only header locations
+std::vector RiffVideo::findHeaderPositions(const char* headerId){
+ DataBuf hdrId((uint64_t)5);
+ hdrId.pData_[4] = '\0';
+ uint64_t i;
+
+ std::vector positions;
+ for (i=0;im_riffFileSkeleton.m_headerChunks.size();i++){
+ io_->seek((d->m_riffFileSkeleton.m_headerChunks[i]->m_headerLocation + 4),BasicIo::beg);
+ io_->read(hdrId.pData_,4);
+ if(UtilsVideo::compareTagValue(hdrId,headerId)) positions.push_back((int32_t)io_->tell() - 8);
+ }
+ return positions;
+}
+
+void RiffVideo::writeMetadata(){
+ if (io_->open() != 0) throw Error(9, io_->path(), strError());
+ IoCloser closer(*io_);
+ doWriteMetadata();
+ io_->close();
+ return;
+} // RiffVideo::writeMetadata
+
+/*!
+ * \brief RiffVideo::doWriteMetadata:
+ * Search for all the supported ChunkIds in Exiv2 and
+ * write the modified data to the file.
+ */
+void RiffVideo::doWriteMetadata(){
+ //pre-write checks to make sure that we are writing to provided Riff file only
+ if (!io_->isopen()) throw Error(20);
+ if (!isRiffType(*io_, false)){
+ if (io_->error() || io_->eof()) throw Error(14);
+ throw Error(3, "RIFF");
}
- void RiffVideo::writeMetadata()
- {
- } // RiffVideo::writeMetadata
+ uint64_t bufMinSize = 4;
- void RiffVideo::readMetadata()
- {
- if (io_->open() != 0) throw Error(9, io_->path(), strError());
+ //some initial variable declarations and initialization before traversing through chunks
+ DataBuf chkId(bufMinSize+1);
+ DataBuf chkSize(bufMinSize+1);
- // Ensure that this is the correct image type
- if (!isRiffType(*io_, false)) {
- if (io_->error() || io_->eof()) throw Error(14);
- throw Error(3, "RIFF");
+ chkId.pData_[4] = '\0';
+ chkSize.pData_[4] = '\0';
+
+ //skip "RIFF" "chkSize" "AVI"
+ io_->read(chkId.pData_, bufMinSize);
+ io_->read(chkSize.pData_, bufMinSize);
+ io_->read(chkId.pData_, bufMinSize);
+
+ d->m_decodeMetaData = false;
+ d->m_modifyMetadata = true;
+
+ //write metadata in order
+
+ //find and move to avih position
+ int32_t dummyLong = 0;
+ uint64_t i,j,maxCount;
+
+ std::vector strhChunkPositions = findChunkPositions("STRH");
+
+ std::vector primitiveFlags;
+ //Add new tags to the beginning of the container prmitiveFlags and handle conditions to the end of case statements.
+ primitiveFlags.push_back("STRN");
+ primitiveFlags.push_back("FMT ");
+ primitiveFlags.push_back("STRF");
+ primitiveFlags.push_back("STRH");
+ primitiveFlags.push_back("AVIH");
+
+ maxCount = (uint64_t) primitiveFlags.size();
+ for (j=0; j primitivePositions = findChunkPositions(primitiveFlags.back().c_str());
+ primitiveFlags.pop_back();
+ for (i=0; i<(uint64_t)primitivePositions.size(); i++){
+ io_->seek(primitivePositions[i]+4,BasicIo::beg);
+ switch (j){
+ case 0: aviHeaderTagsHandler(dummyLong); break;
+ case 1: setStreamType();
+ streamHandler(dummyLong);
+ break;
+ case 2: io_->seek(strhChunkPositions[i]+4,BasicIo::beg);
+ setStreamType();
+ io_->seek(primitivePositions[i]+4,BasicIo::beg);
+ streamFormatHandler(dummyLong);
+ break;
+ case 3: d->streamType_ = Audio;
+ streamHandler(dummyLong);
+ break;
+ case 4: dateTimeOriginal(dummyLong); break;
+ default:break;
+ }
}
+ primitivePositions.clear();
+ }
- IoCloser closer(*io_);
- clearMetadata();
- continueTraversing_ = true;
+ std::vector headerFlags;
+ //Add new tags to the beginning of the container headerFlags and handle conditions to the end of case statements.
+ headerFlags.push_back("INFO");
+ headerFlags.push_back("NCDT");
+ headerFlags.push_back("ODML");
+ headerFlags.push_back("IDIT");
- xmpData_["Xmp.video.FileSize"] = (double)io_->size()/(double)1048576;
- xmpData_["Xmp.video.FileName"] = io_->path();
- xmpData_["Xmp.video.MimeType"] = mimeType();
+ maxCount = (uint64_t) headerFlags.size();
+ for (j=0; j headerPositions = findHeaderPositions(headerFlags.back().c_str());
+ headerFlags.pop_back();
- const long bufMinSize = 4;
- DataBuf buf(bufMinSize+1);
- buf.pData_[4] = '\0';
+ for (i=0; i<(uint64_t)headerPositions.size(); i++){
+ io_->seek(headerPositions[i],BasicIo::beg);
+ switch (j){
+ case 0: io_->seek(headerPositions[i]+8,BasicIo::beg);
+ dateTimeOriginal(dummyLong);
+ break;
+ case 1: odmlTagsHandler(); break;
+ case 2: nikonTagsHandler(); break;
+ case 3: infoTagsHandler(); break;
+ //TODO :implement write functionality for header chunks and exif and iptc metadata
+ default: break;
+ }
+ }
+ headerPositions.clear();
+ }
+ return;
+}// RiffVideo::doWriteMetadata
+void RiffVideo::readMetadata(){
+ if (io_->open() != 0) throw Error(9, io_->path(), strError());
+
+ // Ensure that this is the correct image type
+ if (!isRiffType(*io_, false)){
+ if (io_->error() || io_->eof()) throw Error(14);
+ throw Error(3, "RIFF");
+ }
+
+ IoCloser closer(*io_);
+ clearMetadata();
+
+ xmpData_["Xmp.video.FileSize"] = (double)io_->size()/(double)1048576;
+ xmpData_["Xmp.video.FileName"] = io_->path();
+ xmpData_["Xmp.video.MimeType"] = mimeType();
+
+ DataBuf chkId((const int32_t)5);
+ DataBuf chkSize((const int32_t)5);
+ DataBuf chkHeader((const int32_t)5);
+
+ chkId.pData_[4] = '\0';
+ chkHeader.pData_[4] = '\0';
+
+ io_->read(chkId.pData_, 4);
+ xmpData_["Xmp.video.Container"] = chkId.pData_;
+
+ //skip file size
+ io_->read(chkSize.pData_, 4);
+ io_->read(chkHeader.pData_, 4);
+ xmpData_["Xmp.video.FileType"] = chkHeader.pData_;
+
+ d->m_decodeMetaData = true;
+ decodeBlock();
+ return;
+} // RiffVideo::readMetadata
+
+void RiffVideo::decodeBlock(){
+ DataBuf chkId((const int32_t)5);
+ chkId.pData_[4] = '\0' ;
+
+ io_->read(chkId.pData_, 4);
+
+ if(io_->eof()) return;
+ else if(UtilsVideo::compareTagValue(chkId, "LIST") || UtilsVideo::compareTagValue(chkId, "JUNK")){
+ io_->seek(-4,BasicIo::cur);
+ tagDecoder();
+ }
+ return;
+} // RiffVideo::decodeBlock
+
+void RiffVideo::tagDecoder(){
+ DataBuf chkMainId((const int32_t)5);
+ chkMainId.pData_[4] = '\0';
+ io_->read(chkMainId.pData_, 4);
+
+ if(io_->eof()) return;
+
+ if (UtilsVideo::compareTagValue(chkMainId, "LIST")){
+ DataBuf listSize((const int32_t)5);
+ DataBuf chkHeader((const int32_t)5);
+
+ listSize.pData_[4] = '\0';
+ chkHeader.pData_[4] = '\0';
+
+ io_->read(listSize.pData_, 4);
+ uint64_t listsize = Exiv2::getULong(listSize.pData_, littleEndian);
+ io_->read(chkHeader.pData_, 4);
+
+ HeaderChunk* tmpHeaderChunk = new HeaderChunk();
+ memcpy((Exiv2::byte* )tmpHeaderChunk->m_headerId,(const Exiv2::byte*)chkHeader.pData_,5);
+
+ int32_t listend = io_->tell() + listsize - 4 ;
+
+ IoPosition position = PremitiveChunk;
+ while( (position == PremitiveChunk) && (io_->tell() < listend) ){
+ DataBuf chkId((const int32_t)5);
+ DataBuf chkSize((const int32_t)5);
+ chkId.pData_[4] = '\0';
+ chkSize.pData_[4] = '\0';
+
+ io_->read(chkId.pData_, 4);
+ io_->read(chkSize.pData_, 4);
+
+ uint64_t size = Exiv2::getULong(chkSize.pData_, littleEndian);
+
+ const char allPrimitiveFlags[][5]={"JUNK","AVIH","FMT ",
+ "STRH","STRF","STRN","STRD"};
+ const char allHeaderFlags[][5]={"NCDT","ODML","MOVI","INFO"};
+
+ if(UtilsVideo::compareTagValue(chkId,allPrimitiveFlags,(int32_t)(sizeof(allPrimitiveFlags)/5))){
+ PrimitiveChunk* tmpPremitiveChunk = new PrimitiveChunk();
+ memcpy((Exiv2::byte* )tmpPremitiveChunk->m_chunkId,(const Exiv2::byte*)chkId.pData_,5);
+ tmpPremitiveChunk->m_chunkLocation = io_->tell() - 8;
+ tmpPremitiveChunk->m_chunkSize = size;
+ d->m_riffFileSkeleton.m_primitiveChunks.push_back(tmpPremitiveChunk);
+ }
+
+ if(UtilsVideo::compareTagValue(chkHeader,allHeaderFlags,(int32_t)(sizeof(allHeaderFlags)/5))){
+ tmpHeaderChunk->m_headerLocation = io_->tell() - 16;
+ tmpHeaderChunk->m_headerSize = listsize ;
+ d->m_riffFileSkeleton.m_headerChunks.push_back(tmpHeaderChunk);
+ position = RiffVideo::TraversingChunk;
+ }
+ //to handle AVI file formats
+ if(!d->m_decodeMetaData && UtilsVideo::compareTagValue(chkId,allPrimitiveFlags,(int32_t)(sizeof(allPrimitiveFlags)/5))) io_->seek(size,BasicIo::cur);
+
+ else if(!d->m_decodeMetaData && UtilsVideo::compareTagValue(chkHeader,allHeaderFlags,(int)(sizeof(allHeaderFlags)/5))) io_->seek((listsize - 12),BasicIo::cur);
+
+ else if(UtilsVideo::compareTagValue(chkId, "JUNK")) junkHandler(size);
+ //primitive chunks note:compare chkId
+ else if(UtilsVideo::compareTagValue(chkId, "AVIH")) aviHeaderTagsHandler(size);
+ else if(UtilsVideo::compareTagValue(chkId, "STRH")){
+ //since strh and strf exist sequential stream type can be set once
+ setStreamType();
+ streamHandler(size);
+ }
+ else if(UtilsVideo::compareTagValue(chkId,"STRF") || UtilsVideo::compareTagValue(chkId, "FMT ")){
+ if(UtilsVideo::compareTagValue(chkId,"FMT ")) d->streamType_ = Audio;
+ streamFormatHandler(size);
+ }
+ else if(UtilsVideo::compareTagValue(chkId, "STRN")) dateTimeOriginal(size, 1);
+ else if(UtilsVideo::compareTagValue(chkId, "STRD")) streamDataTagHandler(size);
+ //add more else if to support more primitive chunks below if any
+ //TODO:add indx support
+
+ //recursive call to decode LIST by breaking out of the loop
+ else if(UtilsVideo::compareTagValue(chkId, "LIST")){
+ position = RiffVideo::TraversingChunk;
+ io_->seek(-8,BasicIo::cur);
+ }
+
+ //header chunks note:compare chkHeader
+ else if(UtilsVideo::compareTagValue(chkHeader, "INFO")){
+ io_->seek(-16,BasicIo::cur);
+ infoTagsHandler();
+ }
+ else if(UtilsVideo::compareTagValue(chkHeader, "NCDT")){
+ io_->seek(-16,BasicIo::cur);
+ nikonTagsHandler();
+ }
+ else if(UtilsVideo::compareTagValue(chkHeader, "ODML")){
+ io_->seek(-16,BasicIo::cur);
+ odmlTagsHandler();
+ }
+ //only way to exit from readMetadata()
+ else if(UtilsVideo::compareTagValue(chkHeader, "MOVI") || UtilsVideo::compareTagValue(chkMainId, "DATA")) io_->seek(listsize-12,BasicIo::cur);
+ //Add read functionality for custom chunk headers or user created tags here with more (else if) before else.
+
+ //skip block with unknown chunk ID (primitive chunk)
+ else if(io_->tell() < listend){
+ position = RiffVideo::TraversingChunk;
+ io_->seek((listend - (io_->tell()+4)) ,BasicIo::cur);
+ }
+
+ //skip chunk with unknown headerId
+ else io_->seek(io_->tell()+size, BasicIo::cur);
+
+ if(UtilsVideo::compareTagValue(chkId,allPrimitiveFlags,(int32_t)(sizeof(allPrimitiveFlags)/5)) && (size % 2 != 0)) io_->seek(1,BasicIo::cur);
+
+ if(UtilsVideo::compareTagValue(chkId,allHeaderFlags,(int32_t)(sizeof(allHeaderFlags)/5)) && (listsize % 2 != 0)) io_->seek(1,BasicIo::cur);
+ }
+ }
+
+ //AVIX can have JUNK chunk directly inside RIFF chunk
+ else if(UtilsVideo::compareTagValue(chkMainId, "JUNK")){
+ DataBuf junkSize((const int32_t)5);
+ junkSize.pData_[4] = '\0';
+ io_->read(junkSize.pData_, 4);
+ uint64_t size = Exiv2::getULong(junkSize.pData_, littleEndian);
+ if(!d->m_decodeMetaData){
+ HeaderChunk* tmpHeaderChunk = new HeaderChunk();
+ tmpHeaderChunk->m_headerLocation = io_->tell() - 8;
+ tmpHeaderChunk->m_headerSize = size;
+ d->m_riffFileSkeleton.m_headerChunks.push_back(tmpHeaderChunk);
+ io_->seek(size,BasicIo::cur);
+ }
+ else junkHandler(size);
+ }
+ else if(UtilsVideo::compareTagValue(chkMainId, "IDIT")){
+ DataBuf dataSize((const int32_t)5);
+ dataSize.pData_[4] = '\0';
+ io_->read(dataSize.pData_, 4);
+ uint64_t size = Exiv2::getULong(dataSize.pData_, littleEndian);
+ if(!d->m_decodeMetaData){
+ HeaderChunk* tmpHeaderChunk = new HeaderChunk();
+ tmpHeaderChunk->m_headerLocation = io_->tell() - 8;
+ tmpHeaderChunk->m_headerSize = size;
+ d->m_riffFileSkeleton.m_headerChunks.push_back(tmpHeaderChunk);
+ io_->seek(size,BasicIo::cur);
+ }
+ else dateTimeOriginal(size);
+
+ }
+
+ tagDecoder();
+ return;
+} // RiffVideo::tagDecoder
+
+void RiffVideo::streamDataTagHandler(int32_t size){
+ const int32_t bufMinSize = 20000;
+ DataBuf buf(bufMinSize);
+ buf.pData_[4] = '\0';
+ uint64_t cur_pos = io_->tell();
+
+ io_->read(buf.pData_, 8);
+
+ if(UtilsVideo::compareTagValue(buf, "AVIF")){
+
+ if (size - 4 < 0){
+#ifndef SUPPRESS_WARNINGS
+ EXV_ERROR << " Exif Tags found in this RIFF file are not of valid size ."
+ << " Entries considered invalid. Not Processed.\n";
+#endif
+ }
+ else{
+ io_->read(buf.pData_, size - 4);
+
+ IptcData iptcData;
+ XmpData xmpData;
+ DummyTiffHeader tiffHeader(littleEndian);
+ TiffParserWorker::decode(exifData_,
+ iptcData,
+ xmpData,
+ buf.pData_,
+ buf.size_,
+ Tag::root,
+ TiffMapping::findDecoder,
+ &tiffHeader);
+
+#ifndef SUPPRESS_WARNINGS
+ if (!iptcData.empty()) EXV_WARNING << "Ignoring IPTC information encoded in the Exif data.\n";
+ if (!xmpData.empty()) EXV_WARNING << "Ignoring XMP information encoded in the Exif data.\n";
+#endif
+ }
+ }
+ // TODO decode CasioData and ZORA Tag
+ io_->seek(cur_pos + size, BasicIo::beg);
+ return;
+} // RiffVideo::streamDataTagHandler
+
+void RiffVideo::dateTimeOriginal(int32_t size, int32_t i){
+ uint64_t cur_pos = io_->tell();
+ if(!d->m_modifyMetadata){
+ io_->seek(-4,BasicIo::cur);
+ DataBuf dataLength(2);
+ dataLength.pData_[1] = '\0';
+
+ io_->read(dataLength.pData_,1);
+ uint64_t bufMinSize = (uint64_t)Exiv2::getShort(dataLength.pData_, littleEndian);
+ DataBuf buf((uint64_t)bufMinSize);
+ io_->seek(3,BasicIo::cur);
io_->read(buf.pData_, bufMinSize);
- xmpData_["Xmp.video.Container"] = buf.pData_;
- io_->read(buf.pData_, bufMinSize);
- io_->read(buf.pData_, bufMinSize);
- xmpData_["Xmp.video.FileType"] = buf.pData_;
-
- while (continueTraversing_) decodeBlock();
- } // RiffVideo::readMetadata
-
- void RiffVideo::decodeBlock()
- {
- const long bufMinSize = 4;
- DataBuf buf(bufMinSize+1);
- DataBuf buf2(bufMinSize+1);
- unsigned long size = 0;
- buf.pData_[4] = '\0' ;
- buf2.pData_[4] = '\0' ;
-
- io_->read(buf2.pData_, 4);
-
- if(io_->eof() || equalsRiffTag(buf2, "MOVI") || equalsRiffTag(buf2, "DATA")) {
- continueTraversing_ = false;
- return;
- }
- else if(equalsRiffTag(buf2, "HDRL") || equalsRiffTag(buf2, "STRL")) {
- decodeBlock();
- }
- else {
- io_->read(buf.pData_, 4);
- size = Exiv2::getULong(buf.pData_, littleEndian);
-
- tagDecoder(buf2, size);
- }
- } // RiffVideo::decodeBlock
-
- void RiffVideo::tagDecoder(Exiv2::DataBuf& buf, unsigned long size)
- {
- uint64_t cur_pos = io_->tell();
- static bool listFlag = false, listEnd = false;
-
- if(equalsRiffTag(buf, "LIST")) {
- listFlag = true;
- listEnd = false;
-
- while((uint64_t)(io_->tell()) < cur_pos + size) decodeBlock();
-
- listEnd = true;
- io_->seek(cur_pos + size, BasicIo::beg);
- }
- else if(equalsRiffTag(buf, "JUNK") && listEnd) {
- junkHandler(size);
- }
- else if(equalsRiffTag(buf, "AVIH")) {
- listFlag = false;
- aviHeaderTagsHandler(size);
- }
- else if(equalsRiffTag(buf, "STRH")) {
- listFlag = false;
- streamHandler(size);
- }
- else if(equalsRiffTag(buf,"STRF") || equalsRiffTag(buf, "FMT ")) {
- listFlag = false;
- if(equalsRiffTag(buf,"FMT "))
- streamType_ = Audio;
- streamFormatHandler(size);
- }
- else if(equalsRiffTag(buf, "STRN")) {
- listFlag = false;
- dateTimeOriginal(size, 1);
- }
- else if(equalsRiffTag(buf, "STRD")) {
- listFlag = false;
- streamDataTagHandler(size);
- }
- else if(equalsRiffTag(buf, "IDIT")) {
- listFlag = false;
- dateTimeOriginal(size);
- }
- else if(equalsRiffTag(buf, "INFO")) {
- listFlag = false;
- infoTagsHandler();
- }
- else if(equalsRiffTag(buf, "NCDT")) {
- listFlag = false;
- nikonTagsHandler();
- }
- else if(equalsRiffTag(buf, "ODML")) {
- listFlag = false;
- odmlTagsHandler();
- }
- else if (listFlag) {
- // std::cout<<"|unprocessed|"<seek(cur_pos + size, BasicIo::beg);
- }
- } // RiffVideo::tagDecoder
-
- void RiffVideo::streamDataTagHandler(long size)
- {
- const long bufMinSize = 20000;
- DataBuf buf(bufMinSize);
- buf.pData_[4] = '\0';
- uint64_t cur_pos = io_->tell();
-
- io_->read(buf.pData_, 8);
-
- if(equalsRiffTag(buf, "AVIF")) {
-
- if (size - 4 < 0) {
- #ifndef SUPPRESS_WARNINGS
- EXV_ERROR << " Exif Tags found in this RIFF file are not of valid size ."
- << " Entries considered invalid. Not Processed.\n";
- #endif
- }
- else {
- io_->read(buf.pData_, size - 4);
-
- IptcData iptcData;
- XmpData xmpData;
- DummyTiffHeader tiffHeader(littleEndian);
- TiffParserWorker::decode(exifData_,
- iptcData,
- xmpData,
- buf.pData_,
- buf.size_,
- Tag::root,
- TiffMapping::findDecoder,
- &tiffHeader);
-
- #ifndef SUPPRESS_WARNINGS
- if (!iptcData.empty()) {
- EXV_WARNING << "Ignoring IPTC information encoded in the Exif data.\n";
- }
- if (!xmpData.empty()) {
- EXV_WARNING << "Ignoring XMP information encoded in the Exif data.\n";
- }
- #endif
- }
- }
- // TODO decode CasioData and ZORA Tag
+ if(!i) xmpData_["Xmp.video.DateUT"] = buf.pData_;
+ else xmpData_["Xmp.video.StreamName"] = buf.pData_;
io_->seek(cur_pos + size, BasicIo::beg);
+ }
+ else{
+ DataBuf dataLength(2);
+ dataLength.pData_[1] = '\0';
+ io_->read(dataLength.pData_,1);
+ io_->seek(3,BasicIo::cur);
+ int32_t bufMinSize = (uint64_t)Exiv2::getShort(dataLength.pData_, littleEndian);
- } // RiffVideo::streamDataTagHandler
-
- void RiffVideo::dateTimeOriginal(long size, int i)
- {
- uint64_t cur_pos = io_->tell();
- const long bufMinSize = 100;
- DataBuf buf(bufMinSize);
- io_->read(buf.pData_, size);
- if(!i)
- xmpData_["Xmp.video.DateUTC"] = buf.pData_;
- else
- xmpData_["Xmp.video.StreamName"] = buf.pData_;
+ if(xmpData_["Xmp.video.DateUT"].count() > 0) writeStringData(xmpData_["Xmp.video.DateUT"],bufMinSize);
+ else if(xmpData_["Xmp.video.StreamName"].count() >0) writeStringData(xmpData_["Xmp.video.StreamName"],bufMinSize);
io_->seek(cur_pos + size, BasicIo::beg);
- } // RiffVideo::dateTimeOriginal
+ }
+ return;
+} // RiffVideo::dateTimeOriginal
- void RiffVideo::odmlTagsHandler()
- {
- const long bufMinSize = 100;
- DataBuf buf(bufMinSize);
- buf.pData_[4] = '\0';
- io_->seek(-12, BasicIo::cur);
- io_->read(buf.pData_, 4);
- unsigned long size = Exiv2::getULong(buf.pData_, littleEndian);
- unsigned long size2 = size;
+void RiffVideo::odmlTagsHandler(){
+ const int32_t bufMinSize = 4;
+ DataBuf buf(bufMinSize + 1);
+ buf.pData_[4] = '\0';
+ io_->read(buf.pData_,4);
+
+ if(!d->m_modifyMetadata){
+ uint64_t size = Exiv2::getULong(buf.pData_, littleEndian);
+ uint64_t size2 = size;
uint64_t cur_pos = io_->tell();
io_->read(buf.pData_, 4); size -= 4;
- while(size > 0) {
+ while(size > 0){
io_->read(buf.pData_, 4); size -= 4;
- if(equalsRiffTag(buf,"DMLH")) {
+ if(UtilsVideo::compareTagValue(buf,"DMLH")){
io_->read(buf.pData_, 4); size -= 4;
io_->read(buf.pData_, 4); size -= 4;
xmpData_["Xmp.video.TotalFrameCount"] = Exiv2::getULong(buf.pData_, littleEndian);
}
}
io_->seek(cur_pos + size2, BasicIo::beg);
- } // RiffVideo::odmlTagsHandler
+ }
+ else{
+ if(xmpData_["Xmp.video.TotalFrameCount"].count() > 0){
+ uint64_t tmpSize = Exiv2::getULong(buf.pData_, littleEndian);
+ while(tmpSize > 0){
+ io_->read(buf.pData_,4); tmpSize -= 4;
+ if(UtilsVideo::compareTagValue(buf,"DMLH")){
+ io_->seek(4,BasicIo::cur);
+ writeLongData(xmpData_["Xmp.video.TotalFrameCount"]);
+ return;
+ }
+ }
+ }
+ }
+ return;
+} // RiffVideo::odmlTagsHandler
- void RiffVideo::skipListData()
- {
- const long bufMinSize = 4;
- DataBuf buf(bufMinSize+1);
- buf.pData_[4] = '\0';
- io_->seek(-12, BasicIo::cur);
+void RiffVideo::skipListData(){
+ const int32_t bufMinSize = 4;
+ DataBuf buf(bufMinSize+1);
+ buf.pData_[4] = '\0';
+ io_->seek(-12, BasicIo::cur);
+ io_->read(buf.pData_, 4);
+ uint64_t size = Exiv2::getULong(buf.pData_, littleEndian);
+
+ uint64_t cur_pos = io_->tell();
+ io_->seek(cur_pos + size, BasicIo::beg);
+ return;
+} // RiffVideo::skipListData
+
+void RiffVideo::nikonTagsHandler(){
+ const int32_t bufMinSize = 100;
+ DataBuf buf(bufMinSize), buf2(4+1);
+ buf.pData_[4] = '\0';
+ io_->read(buf.pData_, 4);
+
+ int32_t internal_size = 0, tagID = 0, dataSize = 0, tempSize, size = Exiv2::getULong(buf.pData_, littleEndian);
+ tempSize = size; char str[9] = " . . . ";
+ uint64_t internal_pos, cur_pos; internal_pos = cur_pos = io_->tell();
+
+ const TagDetails* td;
+ double denominator = 1;
+ io_->read(buf.pData_, 4); tempSize -= 4;
+
+ while((int32_t)tempSize > 0){
+ std::memset(buf.pData_, 0x0, buf.size_);
io_->read(buf.pData_, 4);
- unsigned long size = Exiv2::getULong(buf.pData_, littleEndian);
+ io_->read(buf2.pData_, 4);
+ int32_t temp = internal_size = Exiv2::getULong(buf2.pData_, littleEndian);
+ internal_pos = io_->tell(); tempSize -= (internal_size + 8);
- uint64_t cur_pos = io_->tell();
- io_->seek(cur_pos + size, BasicIo::beg);
- } // RiffVideo::skipListData
+ if(UtilsVideo::compareTagValue(buf, "NCVR")){
+ while((int32_t)temp > 3){
+ std::memset(buf.pData_, 0x0, buf.size_);
+ io_->read(buf.pData_, 2);
+ tagID = Exiv2::getULong(buf.pData_, littleEndian);
+ io_->read(buf.pData_, 2);
+ dataSize = Exiv2::getULong(buf.pData_, littleEndian);
+ temp -= (4 + dataSize);
- void RiffVideo::nikonTagsHandler()
- {
- const long bufMinSize = 100;
- DataBuf buf(bufMinSize), buf2(4+1);
- buf.pData_[4] = '\0';
- io_->seek(-12, BasicIo::cur);
- io_->read(buf.pData_, 4);
-
- long internal_size = 0, tagID = 0, dataSize = 0, tempSize, size = Exiv2::getULong(buf.pData_, littleEndian);
- tempSize = size; char str[9] = " . . . ";
- uint64_t internal_pos, cur_pos; internal_pos = cur_pos = io_->tell();
- const TagDetails* td;
- double denominator = 1;
- io_->read(buf.pData_, 4); tempSize -= 4;
-
- while((long)tempSize > 0) {
- std::memset(buf.pData_, 0x0, buf.size_);
- io_->read(buf.pData_, 4);
- io_->read(buf2.pData_, 4);
- int temp = internal_size = Exiv2::getULong(buf2.pData_, littleEndian);
- internal_pos = io_->tell(); tempSize -= (internal_size + 8);
-
- if(equalsRiffTag(buf, "NCVR")) {
- while((long)temp > 3) {
- std::memset(buf.pData_, 0x0, buf.size_);
- io_->read(buf.pData_, 2);
- tagID = Exiv2::getULong(buf.pData_, littleEndian);
- io_->read(buf.pData_, 2);
- dataSize = Exiv2::getULong(buf.pData_, littleEndian);
- temp -= (4 + dataSize);
-
- if(tagID == 0x0001) {
- if (dataSize <= 0) {
- #ifndef SUPPRESS_WARNINGS
- EXV_ERROR << " Makernotes found in this RIFF file are not of valid size ."
- << " Entries considered invalid. Not Processed.\n";
- #endif
- }
- else {
+ if(tagID == 0x0001){
+ if (dataSize <= 0){
+#ifndef SUPPRESS_WARNINGS
+ EXV_ERROR << " Makernotes found in this RIFF file are not of valid size ."
+ << " Entries considered invalid. Not Processed.\n";
+#endif
+ }
+ else if(!d->m_modifyMetadata){
io_->read(buf.pData_, dataSize);
xmpData_["Xmp.video.MakerNoteType"] = buf.pData_;
- }
}
- else if (tagID == 0x0002) {
- while(dataSize) {
+ else writeStringData(xmpData_["Xmp.video.MakerNoteType"],dataSize);
+ }
+ else if (tagID == 0x0002){
+ if (dataSize <= 0){
+ }
+ else if(!d->m_modifyMetadata){
+ while(dataSize){
std::memset(buf.pData_, 0x0, buf.size_); io_->read(buf.pData_, 1);
str[(4 - dataSize) * 2] = (char)(Exiv2::getULong(buf.pData_, littleEndian) + 48);
--dataSize;
}
xmpData_["Xmp.video.MakerNoteVersion"] = str;
}
+ //this is necessary block
+ else if(xmpData_["Xmp.video.MakerNoteVersion"].count() > 0){
+ int32_t originalDataSize = dataSize;
+ std::string makerNoteVersion = xmpData_["Xmp.video.MakerNoteVersion"].toString();
+ Exiv2::byte* rawMakerNoteVersion = new byte[originalDataSize];
+ int32_t tmpCounter = 0;
+ int32_t i;
+ for(i=(int32_t)min((int32_t)dataSize,(int32_t)makerNoteVersion.size());
+ i>=(int32_t)0; i--){
+ rawMakerNoteVersion[tmpCounter] = (Exiv2::byte) (makerNoteVersion[(4 - i) * 2] - 48);
+ tmpCounter++;
+ }
+ if((int32_t)originalDataSize > (int32_t)makerNoteVersion.size()){
+ for(i=(int32_t)(makerNoteVersion.size()); iwrite(rawMakerNoteVersion,originalDataSize);
+ delete[] rawMakerNoteVersion;
+ }
+ else io_->seek(dataSize,BasicIo::cur);
}
}
- else if(equalsRiffTag(buf, "NCTG")) {
- while((long)temp > 3) {
+ }
+ else if(UtilsVideo::compareTagValue(buf, "NCTG")){
+ if(!d->m_modifyMetadata){
+ while((int32_t)temp > 3){
std::memset(buf.pData_, 0x0, buf.size_);
io_->read(buf.pData_, 2);
tagID = Exiv2::getULong(buf.pData_, littleEndian);
@@ -800,119 +1094,205 @@ namespace Exiv2 {
temp -= (4 + dataSize);
td = find(nikonAVITags , tagID);
- if (dataSize <= 0) {
- #ifndef SUPPRESS_WARNINGS
- EXV_ERROR << " Makernotes found in this RIFF file are not of valid size ."
- << " Entries considered invalid. Not Processed.\n";
- #endif
+ if (dataSize <= 0){
}
- else {
- io_->read(buf.pData_, dataSize);
+ else{
+ switch (tagID)
+ {
+ case 0x0003: case 0x0004: case 0x0005: case 0x0006:
+ case 0x0013: case 0x0014: case 0x0018: case 0x001d:
+ case 0x001e: case 0x001f: case 0x0020:
+ io_->read(buf.pData_, dataSize);
+ xmpData_[exvGettext(td->label_)] = buf.pData_;
+ break;
+ case 0x0007: case 0x0010: case 0x0011: case 0x000c:
+ case 0x0012:
+ io_->read(buf.pData_, dataSize);
+ xmpData_[exvGettext(td->label_)] = Exiv2::getULong(buf.pData_, littleEndian);
+ break;
+ case 0x0008: case 0x0009: case 0x000a: case 0x000b:
+ case 0x000f: case 0x001b: case 0x0016:
- switch (tagID) {
- case 0x0003: case 0x0004: case 0x0005: case 0x0006:
- case 0x0013: case 0x0014: case 0x0018: case 0x001d:
- case 0x001e: case 0x001f: case 0x0020:
- xmpData_[exvGettext(td->label_)] = buf.pData_; break;
+ io_->read(buf.pData_, dataSize);
+ buf2.pData_[0] = buf.pData_[4];
+ buf2.pData_[1] = buf.pData_[5];
+ buf2.pData_[2] = buf.pData_[6];
+ buf2.pData_[3] = buf.pData_[7];
+ denominator = (double)Exiv2::getLong(buf2.pData_, littleEndian);
- case 0x0007: case 0x0010: case 0x0011: case 0x000c:
- case 0x0012:
- xmpData_[exvGettext(td->label_)] = Exiv2::getULong(buf.pData_, littleEndian); break;
+ if (denominator != 0) xmpData_[exvGettext(td->label_)] = (double)Exiv2::getLong(buf.pData_, littleEndian) / denominator;
+ else xmpData_[exvGettext(td->label_)] = 0;
+ break;
- case 0x0008: case 0x0009: case 0x000a: case 0x000b:
- case 0x000f: case 0x001b: case 0x0016:
- buf2.pData_[0] = buf.pData_[4]; buf2.pData_[1] = buf.pData_[5];
- buf2.pData_[2] = buf.pData_[6]; buf2.pData_[3] = buf.pData_[7];
- denominator = (double)Exiv2::getLong(buf2.pData_, littleEndian);
- if (denominator != 0)
- xmpData_[exvGettext(td->label_)] = (double)Exiv2::getLong(buf.pData_, littleEndian) / denominator;
- else
- xmpData_[exvGettext(td->label_)] = 0;
- break;
-
- default:
- break;
+ default: io_->read(buf.pData_, dataSize);
+ break;
+ }
}
+ }
+ }
+ else{
+ while((int32_t)temp > 3){
+ std::memset(buf.pData_, 0x0, buf.size_);
+ io_->read(buf.pData_, 2);
+ tagID = Exiv2::getULong(buf.pData_, littleEndian);
+ io_->read(buf.pData_, 2);
+ dataSize = Exiv2::getULong(buf.pData_, littleEndian);
+ temp -= (4 + dataSize);
+ td = find(nikonAVITags , tagID);
+
+ if (dataSize <= 0){
+ }
+ else{
+ switch (tagID){
+ case 0x0003: case 0x0004: case 0x0005: case 0x0006:
+ case 0x0013: case 0x0014: case 0x0018: case 0x001d:
+ case 0x001e: case 0x001f: case 0x0020:
+ writeStringData(xmpData_[exvGettext(td->label_)],dataSize);
+ break;
+ case 0x0007: case 0x0010: case 0x0011: case 0x000c:
+ case 0x0012:
+ writeLongData(xmpData_[exvGettext(td->label_)],dataSize);
+ break;
+ case 0x0008: case 0x0009: case 0x000a: case 0x000b:
+ case 0x000f: case 0x001b: case 0x0016:
+
+ io_->read(buf.pData_, dataSize);
+ buf2.pData_[0] = buf.pData_[4];
+ buf2.pData_[1] = buf.pData_[5];
+ buf2.pData_[2] = buf.pData_[6];
+ buf2.pData_[3] = buf.pData_[7];
+ denominator = (double)Exiv2::getLong(buf2.pData_, littleEndian);
+
+ //Variation
+ if(xmpData_[exvGettext(td->label_)].count() > 0){
+ io_->seek(-dataSize,BasicIo::cur);
+ int32_t nikonData = (int32_t)(xmpData_[exvGettext(td->label_)].toFloat()*denominator);
+ io_->write((Exiv2::byte*)&nikonData,4);
+ io_->seek((dataSize-4),BasicIo::cur);
+ }
+ else io_->seek(dataSize,BasicIo::cur);
+ break;
+
+ default: io_->read(buf.pData_, dataSize);
+ break;
+ }
}
}
}
- else if(equalsRiffTag(buf, "NCTH")) {//TODO Nikon Thumbnail Image
+ }
+
+ else if(UtilsVideo::compareTagValue(buf, "NCTH")){//TODO Nikon Thumbnail Image
+ }
+
+ else if(UtilsVideo::compareTagValue(buf, "NCVW")){//TODO Nikon Preview Image
+ }
+
+ io_->seek(internal_pos + internal_size, BasicIo::beg);
+ }
+
+ if (size ==0) io_->seek(cur_pos + 4, BasicIo::beg);
+ else io_->seek(cur_pos + size, BasicIo::beg);
+ return;
+} // RiffVideo::nikonTagsHandler
+
+void RiffVideo::infoTagsHandler(){
+ const int32_t bufMinSize = 4;
+ DataBuf buf(bufMinSize + 1);
+ buf.pData_[4] = '\0';
+ const int32_t cur_pos = io_->tell();
+ io_->read(buf.pData_, 4);
+ int32_t size = Exiv2::getULong(buf.pData_, littleEndian);
+ io_->seek(4,BasicIo::cur);
+
+ int32_t dataLenght = size;
+ const TagVocabulary* tv;
+
+ int32_t infoSize;
+ if(!d->m_modifyMetadata){
+ const char allPrimitiveFlags[][5]={"GENR","DIRC","IART","ICNM","IEDT","IENG","ILNG",
+ "IMUS","INAM","IPRO","ISRC","ISTR","LANG","LOCA",
+ "TAPE","YEAR","IPRD","IKEY","ICOP","ICNT","CMNT"};
+ while(dataLenght > 12){
+ io_->read(buf.pData_, 4);
+ if(UtilsVideo::compareTagValue(buf,allPrimitiveFlags,(int32_t)(sizeof(allPrimitiveFlags)/5))){
+ PrimitiveChunk* tmpPremitiveChunk = new PrimitiveChunk();
+ memcpy((Exiv2::byte*)tmpPremitiveChunk->m_chunkId,(const Exiv2::byte*)buf.pData_,5);
+ tmpPremitiveChunk->m_chunkLocation = io_->tell() - 4;
+ d->m_riffFileSkeleton.m_primitiveChunks.push_back(tmpPremitiveChunk);
}
- else if(equalsRiffTag(buf, "NCVW")) {//TODO Nikon Preview Image
- }
-
- io_->seek(internal_pos + internal_size, BasicIo::beg);
- }
-
- if (size ==0) {
- io_->seek(cur_pos + 4, BasicIo::beg);
- }
- else {
- io_->seek(cur_pos + size, BasicIo::beg);
- }
- } // RiffVideo::nikonTagsHandler
-
- void RiffVideo::infoTagsHandler()
- {
- const long bufMinSize = 10000;
- DataBuf buf(bufMinSize);
- buf.pData_[4] = '\0';
- io_->seek(-12, BasicIo::cur);
- io_->read(buf.pData_, 4);
- long infoSize, size = Exiv2::getULong(buf.pData_, littleEndian);
- long size_external = size;
- const TagVocabulary* tv;
-
- uint64_t cur_pos = io_->tell();
- io_->read(buf.pData_, 4); size -= 4;
-
- while(size > 3) {
- io_->read(buf.pData_, 4); size -= 4;
- if(!Exiv2::getULong(buf.pData_, littleEndian))
- break;
- tv = find(infoTags , Exiv2::toString( buf.pData_));
- io_->read(buf.pData_, 4); size -= 4;
+ tv = find(infoTags , Exiv2::toString(buf.pData_));
+ io_->read(buf.pData_, 4);
infoSize = Exiv2::getULong(buf.pData_, littleEndian);
-
- if(infoSize >= 0) {
- size -= infoSize;
- io_->read(buf.pData_, infoSize);
- if(infoSize < 4)
- buf.pData_[infoSize] = '\0';
+ dataLenght -= infoSize;
+ if(tv && infoSize > 4){
+ DataBuf tmpBuf((uint64_t)infoSize+1);
+ tmpBuf.pData_[infoSize] = '\0';
+ io_->read(tmpBuf.pData_,infoSize);
+ xmpData_[exvGettext(tv->label_)] = tmpBuf.pData_;
}
-
- if(tv)
- xmpData_[exvGettext(tv->label_)] = buf.pData_;
- else
- continue;
}
- io_->seek(cur_pos + size_external, BasicIo::beg);
- } // RiffVideo::infoTagsHandler
+ io_->seek(cur_pos + size, BasicIo::beg);
+ }
+ else{
+ //First write the tags which already exist in a file
+ std::vector existingInfoTags;
+ while(dataLenght > 0){
+ io_->read(buf.pData_, 4);
+ tv = find(infoTags , Exiv2::toString( buf.pData_));
+ io_->read(buf.pData_, 4);
+ infoSize = Exiv2::getULong(buf.pData_, littleEndian);
+ dataLenght -= infoSize;
- void RiffVideo::junkHandler(long size)
- {
- const long bufMinSize = size;
-
- if (size < 0) {
- #ifndef SUPPRESS_WARNINGS
- EXV_ERROR << " Junk Data found in this RIFF file are not of valid size ."
- << " Entries considered invalid. Not Processed.\n";
- #endif
- io_->seek(io_->tell() + 4, BasicIo::beg);
+ if(tv){
+ if(xmpData_[exvGettext(tv->label_)].count() >0){
+ existingInfoTags.push_back((std::string)tv->voc_);
+ writeStringData(xmpData_[exvGettext(tv->label_)],infoSize);
+ }
+ }
}
- else {
+ //Secondly write tags which are supported by Digikam,
+ //Note that create new LIST chunk is created if tag did not exist before
+ std::vector > writethis;
+ for(int32_t i =0; i< (int32_t)(sizeof(infoTags)/sizeof(infoTags[0])); i++){
+ const std::string infoTagData = xmpData_[infoTags[i].label_].toString();
+ const std::string infoTagFlag = (std::string)infoTags[i].voc_;
+ if((xmpData_[infoTags[i].label_].count() > 0) &&
+ ((findChunkPositions(infoTags[i].voc_)).size() == 0)
+ && !(std::find(existingInfoTags.begin(), existingInfoTags.end(), infoTagFlag) != existingInfoTags.end()))
+ writethis.push_back(make_pair(infoTagData,infoTagFlag));
+ }
+
+ if(writethis.size() > 0){
+ io_->seek(cur_pos, BasicIo::beg);
+ writeNewSubChunks(writethis);
+ }
+
+ io_->seek(cur_pos + size, BasicIo::beg);
+ }
+ return;
+} // RiffVideo::infoTagsHandler
+
+void RiffVideo::junkHandler(int32_t size){
+ const int32_t bufMinSize = size;
+
+ if (size < 0){
+#ifndef SUPPRESS_WARNINGS
+ EXV_ERROR << " Junk Data found in this RIFF file are not of valid size ."
+ << " Entries considered invalid. Not Processed.\n";
+#endif
+ io_->seek(io_->tell() + 4, BasicIo::beg);
+ }
+
+ else{
DataBuf buf(bufMinSize+1), buf2(4+1);
- std::memset(buf.pData_, 0x0, buf.size_);
- buf2.pData_[4] = '\0';
uint64_t cur_pos = io_->tell();
io_->read(buf.pData_, 4);
//! Pentax Metadata and Tags
- if(equalsRiffTag(buf, "PENT")) {
-
+ if(UtilsVideo::compareTagValue(buf, "PENT")){
io_->seek(cur_pos + 18, BasicIo::beg);
io_->read(buf.pData_, 26);
xmpData_["Xmp.video.Make"] = buf.pData_;
@@ -961,53 +1341,44 @@ namespace Exiv2 {
xmpData_.add(Exiv2::XmpKey("Xmp.xmp.Thumbnails/xmpGImg:image"), &tv);
*/
}
- else {
+ else{
io_->seek(cur_pos, BasicIo::beg);
io_->read(buf.pData_, size);
xmpData_["Xmp.video.Junk"] = buf.pData_;
}
io_->seek(cur_pos + size, BasicIo::beg);
- }
- } // RiffVideo::junkHandler
+ }
+ return;
+} // RiffVideo::junkHandler
- void RiffVideo::aviHeaderTagsHandler(long size)
- {
- const long bufMinSize = 4;
+void RiffVideo::aviHeaderTagsHandler(int32_t size){
+ if(!d->m_modifyMetadata){
+ const int32_t bufMinSize = 4;
DataBuf buf(bufMinSize+1);
buf.pData_[4] = '\0';
- long width = 0, height = 0, frame_count = 0;
+ int32_t width = 0, height = 0, frame_count = 0;
double frame_rate = 1;
- uint64_t cur_pos = io_->tell();
+ uint64_t cur_pos = io_->tell(),i;
- for(int i = 0; i <= 9; i++) {
+ for( i = 0; i <= 9; i++){
std::memset(buf.pData_, 0x0, buf.size_);
io_->read(buf.pData_, bufMinSize);
- switch(i) {
- case frameRate:
- xmpData_["Xmp.video.MicroSecPerFrame"] = Exiv2::getULong(buf.pData_, littleEndian);
- frame_rate = (double)1000000/(double)Exiv2::getULong(buf.pData_, littleEndian);
- break;
- case (maxDataRate):
- xmpData_["Xmp.video.MaxDataRate"] = (double)Exiv2::getULong(buf.pData_, littleEndian)/(double)1024;
- break;
- case frameCount:
- xmpData_["Xmp.video.FrameCount"] = Exiv2::getULong(buf.pData_, littleEndian);
- frame_count = Exiv2::getULong(buf.pData_, littleEndian);
- break;
- case streamCount:
- xmpData_["Xmp.video.StreamCount"] = Exiv2::getULong(buf.pData_, littleEndian);
- break;
- case imageWidth_h:
- width = Exiv2::getULong(buf.pData_, littleEndian);
- xmpData_["Xmp.video.Width"] = width;
- break;
- case imageHeight_h:
- height = Exiv2::getULong(buf.pData_, littleEndian);
- xmpData_["Xmp.video.Height"] = height;
- break;
+ switch(i){
+ case frameRate: xmpData_["Xmp.video.MicroSecPerFrame"] = Exiv2::getULong(buf.pData_, littleEndian);
+ frame_rate = (double)1000000/(double)Exiv2::getULong(buf.pData_, littleEndian); break;
+ case (maxDataRate): xmpData_["Xmp.video.MaxDataRate"] = (double)Exiv2::getULong(buf.pData_, littleEndian)/(double)1024; break;
+ case frameCount: xmpData_["Xmp.video.FrameCount"] = Exiv2::getULong(buf.pData_, littleEndian);
+ frame_count = Exiv2::getULong(buf.pData_, littleEndian); break;
+ case initialFrames: xmpData_["Xmp.video.InitialFrames"] = Exiv2::getULong(buf.pData_, littleEndian); break;
+ case streamCount: xmpData_["Xmp.video.StreamCount"] = Exiv2::getULong(buf.pData_, littleEndian); break;
+ case suggestedBufferSize: xmpData_["Xmp.video.SuggestedBufferSize"] = Exiv2::getULong(buf.pData_, littleEndian); break;
+ case imageWidth_h: width = Exiv2::getULong(buf.pData_, littleEndian);
+ xmpData_["Xmp.video.Width"] = width; break;
+ case imageHeight_h: height = Exiv2::getULong(buf.pData_, littleEndian);
+ xmpData_["Xmp.video.Height"] = height; break;
}
}
@@ -1015,237 +1386,502 @@ namespace Exiv2 {
fillDuration(frame_rate, frame_count);
io_->seek(cur_pos + size, BasicIo::beg);
- } // RiffVideo::aviHeaderTagsHandler
+ }
+ else//overwrite metadata from current xmpData_ container{
+ for(int32_t i = 0; i <= 9; i++){
+ switch(i){
+ case frameRate: writeLongData(xmpData_["Xmp.video.MicroSecPerFrame"]); break;
+ case (maxDataRate): if(xmpData_["Xmp.video.MaxDataRate"].count() > 0 ){
+ int32_t maxDataRate = (int32_t)(xmpData_["Xmp.video.MaxDataRate"].toFloat()*1024);
+ io_->write((Exiv2::byte*)&maxDataRate,4);
+ }
+ else io_->seek(4,BasicIo::cur);
+ break;
+ case frameCount: writeLongData(xmpData_["Xmp.video.FrameCount"]); break;
+ case initialFrames: writeLongData(xmpData_["Xmp.video.InitialFrames"]); break;
+ case streamCount: writeLongData(xmpData_["Xmp.video.StreamCount"]); break;
+ case suggestedBufferSize: writeLongData(xmpData_["Xmp.video.SuggestedBufferSize"]); break;
+ case imageWidth_h: writeLongData(xmpData_["Xmp.video.Width"]); break;
+ case imageHeight_h: writeLongData(xmpData_["Xmp.video.Height"]); break;
+ default: io_->seek(4,BasicIo::cur); break;
+ }
+ }
+ return;
+} // RiffVideo::aviHeaderTagsHandler
- void RiffVideo::streamHandler(long size)
- {
- const long bufMinSize = 4;
+void RiffVideo::setStreamType(){
+ DataBuf chkId((uint64_t)5);
+ io_->read(chkId.pData_,(uint64_t)4);
+ if(UtilsVideo::compareTagValue(chkId, "VIDS"))
+ d->streamType_ = Video;
+ else if (UtilsVideo::compareTagValue(chkId, "AUDS"))
+ d->streamType_ = Audio;
+ return;
+}//RiffVideo::setStreamType
+
+void RiffVideo::streamHandler(int32_t size){
+ if (!d->m_modifyMetadata){
+ uint64_t bufMinSize = 4;
DataBuf buf(bufMinSize+1);
- buf.pData_[4]='\0';
- long divisor = 1;
- uint64_t cur_pos = io_->tell();
+ buf.pData_[4] = '\0';
+ int32_t divisor = 1;
+ uint64_t cur_pos = io_->tell() - 4;
- io_->read(buf.pData_, bufMinSize);
- if(equalsRiffTag(buf, "VIDS"))
- streamType_ = Video;
- else if (equalsRiffTag(buf, "AUDS"))
- streamType_ = Audio;
-
- for(int i=1; i<=25; i++) {
+ int32_t i;
+ for( i=1; i<=25; i++){
std::memset(buf.pData_, 0x0, buf.size_);
io_->read(buf.pData_, bufMinSize);
- switch(i) {
+ switch(i){
case codec:
- if(streamType_ == Video)
- xmpData_["Xmp.video.Codec"] = buf.pData_;
- else if (streamType_ == Audio)
- xmpData_["Xmp.audio.Codec"] = buf.pData_;
- else
- xmpData_["Xmp.video.Codec"] = buf.pData_;
+ if(d->streamType_ == Video) xmpData_["Xmp.video.Codec"] = buf.pData_;
+ else if (d->streamType_ == Audio) xmpData_["Xmp.audio.Codec"] = buf.pData_;
+ else xmpData_["Xmp.video.Codec"] = buf.pData_;
break;
- case sampleRate:
- divisor=Exiv2::getULong(buf.pData_, littleEndian);
+ case sampleRate: divisor=Exiv2::getULong(buf.pData_, littleEndian); break;
+ case (sampleRate+1): if(d->streamType_ == Video) xmpData_["Xmp.video.FrameRate"] = returnSampleRate(buf,divisor);
+ else if (d->streamType_ == Audio) xmpData_["Xmp.audio.SampleRate"] = returnSampleRate(buf,divisor);
+ else xmpData_["Xmp.video.StreamSampleRate"] = returnSampleRate(buf,divisor);
break;
- case (sampleRate+1):
- if(streamType_ == Video)
- xmpData_["Xmp.video.FrameRate"] = returnSampleRate(buf,divisor);
- else if (streamType_ == Audio)
- xmpData_["Xmp.audio.SampleRate"] = returnSampleRate(buf,divisor);
- else
- xmpData_["Xmp.video.StreamSampleRate"] = returnSampleRate(buf,divisor);
+ case sampleCount: if(d->streamType_ == Video) xmpData_["Xmp.video.FrameCount"] = Exiv2::getULong(buf.pData_, littleEndian);
+ else if (d->streamType_ == Audio) xmpData_["Xmp.audio.SampleCount"] = Exiv2::getULong(buf.pData_, littleEndian);
+ else xmpData_["Xmp.video.StreamSampleCount"] = Exiv2::getULong(buf.pData_, littleEndian);
break;
- case sampleCount:
- if(streamType_ == Video)
- xmpData_["Xmp.video.FrameCount"] = Exiv2::getULong(buf.pData_, littleEndian);
- else if (streamType_ == Audio)
- xmpData_["Xmp.audio.SampleCount"] = Exiv2::getULong(buf.pData_, littleEndian);
- else
- xmpData_["Xmp.video.StreamSampleCount"] = Exiv2::getULong(buf.pData_, littleEndian);
+ case quality: if(d->streamType_ == Video) xmpData_["Xmp.video.VideoQuality"] = Exiv2::getULong(buf.pData_, littleEndian);
+ else if(d->streamType_ != Audio) xmpData_["Xmp.video.StreamQuality"] = Exiv2::getULong(buf.pData_, littleEndian);
break;
- case quality:
- if(streamType_ == Video)
- xmpData_["Xmp.video.VideoQuality"] = Exiv2::getULong(buf.pData_, littleEndian);
- else if(streamType_ != Audio)
- xmpData_["Xmp.video.StreamQuality"] = Exiv2::getULong(buf.pData_, littleEndian);
- break;
- case sampleSize:
- if(streamType_ == Video)
- xmpData_["Xmp.video.VideoSampleSize"] = Exiv2::getULong(buf.pData_, littleEndian);
- else if(streamType_ != Audio)
- xmpData_["Xmp.video.StreamSampleSize"] = Exiv2::getULong(buf.pData_, littleEndian);
+ case sampleSize: if(d->streamType_ == Video) xmpData_["Xmp.video.VideoSampleSize"] = Exiv2::getULong(buf.pData_, littleEndian);
+ else if(d->streamType_ != Audio) xmpData_["Xmp.video.StreamSampleSize"] = Exiv2::getULong(buf.pData_, littleEndian);
break;
}
}
io_->seek(cur_pos + size, BasicIo::beg);
- } // RiffVideo::streamHandler
+ }
+ else{
+ DataBuf chkId((uint64_t)5);
+ chkId.pData_[4] = '\0';
+ const int32_t bufMinSize = 4;
- void RiffVideo::streamFormatHandler(long size)
- {
- const long bufMinSize = 4;
+ int32_t multiplier;
+ if(d->streamType_ == Video){
+ writeStringData(xmpData_["Xmp.video.Codec"],4,12);
+ io_->read(chkId.pData_,bufMinSize);
+ multiplier = Exiv2::getULong(chkId.pData_, littleEndian);
+
+ //Variation
+ if(xmpData_["Xmp.video.FrameRate"].count() > 0){
+ int32_t frameRate = (int32_t)xmpData_["Xmp.video.FrameRate"].toFloat()*multiplier;
+ io_->write((Exiv2::byte*)&frameRate,4);
+ io_->seek(4,BasicIo::cur);
+ }
+ else io_->seek(8,BasicIo::cur);
+
+ writeLongData(xmpData_["Xmp.video.FrameCount"],4,4);
+ writeLongData(xmpData_["Xmp.video.VideoQuality"],4);
+ writeLongData(xmpData_["Xmp.video.VideoSampleSize"],4);
+ }
+ else if(d->streamType_ == Audio){
+ writeStringData(xmpData_["Xmp.audio.Codec"],4,12);
+
+ io_->read(chkId.pData_,bufMinSize);
+ multiplier = Exiv2::getULong(chkId.pData_, littleEndian);
+
+ //Variation
+ if(xmpData_["Xmp.audio.SampleRate"].count() > 0){
+ int32_t sampleRate = (int32_t)xmpData_["Xmp.audio.SampleRate"].toLong()*multiplier;
+ io_->write((Exiv2::byte*)&sampleRate,4);
+ io_->seek(4,BasicIo::cur);
+ }
+ else io_->seek(8,BasicIo::cur);
+ writeLongData(xmpData_["Xmp.audio.SampleCount"],4);
+ }
+ else{
+ writeLongData(xmpData_["Xmp.video.Codec"],4,12);
+ io_->read(chkId.pData_,bufMinSize);
+ multiplier = Exiv2::getULong(chkId.pData_, littleEndian);
+
+ //Variation
+ if(xmpData_["Xmp.video.StreamSampleRate"].count() > 0){
+ int32_t streamSampleRate = (int32_t)xmpData_["Xmp.video.StreamSampleRate"].toLong()*multiplier;
+ io_->write((Exiv2::byte*)&streamSampleRate,4);
+ io_->seek(4,BasicIo::cur);
+ }
+ else io_->seek(8,BasicIo::cur);
+
+ writeLongData(xmpData_["Xmp.video.StreamSampleCount"],4,4);
+ writeLongData(xmpData_["Xmp.video.StreamQuality"],4);
+ writeLongData(xmpData_["Xmp.video.StreamSampleSize"],4);
+ }
+ }
+ return;
+} // RiffVideo::streamHandler
+
+void RiffVideo::streamFormatHandler(int32_t size){
+ if (!d->m_modifyMetadata){
+ const int32_t bufMinSize = 4;
DataBuf buf(bufMinSize+1);
buf.pData_[4] = '\0';
uint64_t cur_pos = io_->tell();
- if(streamType_ == Video) {
+ if(d->streamType_ == Video){
io_->read(buf.pData_, bufMinSize);
-
- for(int i = 0; i <= 9; i++) {
+ for(int32_t i = 0; i <= 9; i++){
std::memset(buf.pData_, 0x0, buf.size_);
-
- switch(i) {
- case imageWidth: //Will be used in case of debugging
- io_->read(buf.pData_, bufMinSize); break;
- case imageHeight: //Will be used in case of debugging
- io_->read(buf.pData_, bufMinSize); break;
- case planes:
- io_->read(buf.pData_, 2);
+ switch(i){
+ //Will be used in case of debugging
+ case imageWidth: io_->read(buf.pData_, bufMinSize); break;
+ case imageHeight: io_->read(buf.pData_, bufMinSize); break;
+ case planes: io_->read(buf.pData_, 2);
xmpData_["Xmp.video.Planes"] = Exiv2::getUShort(buf.pData_, littleEndian); break;
- case bitDepth:
- io_->read(buf.pData_, 2);
+ case bitDepth: io_->read(buf.pData_, 2);
xmpData_["Xmp.video.PixelDepth"] = Exiv2::getUShort(buf.pData_, littleEndian); break;
- case compression:
- io_->read(buf.pData_, bufMinSize);
+ case compression: io_->read(buf.pData_, bufMinSize);
xmpData_["Xmp.video.Compressor"] = buf.pData_; break;
- case imageLength:
- io_->read(buf.pData_, bufMinSize);
+ case imageLength: io_->read(buf.pData_, bufMinSize);
xmpData_["Xmp.video.ImageLength"] = Exiv2::getULong(buf.pData_, littleEndian); break;
- case pixelsPerMeterX:
- io_->read(buf.pData_, bufMinSize);
+ case pixelsPerMeterX: io_->read(buf.pData_, bufMinSize);
xmpData_["Xmp.video.PixelPerMeterX"] = Exiv2::getULong(buf.pData_, littleEndian); break;
- case pixelsPerMeterY:
- io_->read(buf.pData_, bufMinSize);
+ case pixelsPerMeterY: io_->read(buf.pData_, bufMinSize);
xmpData_["Xmp.video.PixelPerMeterY"] = Exiv2::getULong(buf.pData_, littleEndian); break;
- case numColors:
- io_->read(buf.pData_, bufMinSize);
- if(Exiv2::getULong(buf.pData_, littleEndian) == 0) {
- xmpData_["Xmp.video.NumOfColours"] = "Unspecified";
- }
- else {
- xmpData_["Xmp.video.NumOfColours"] = Exiv2::getULong(buf.pData_, littleEndian);
- }
+ case numColors: io_->read(buf.pData_, bufMinSize);
+ if(Exiv2::getULong(buf.pData_, littleEndian) == 0) xmpData_["Xmp.video.NumOfColours"] = "Unspecified";
+ else xmpData_["Xmp.video.NumOfColours"] = Exiv2::getULong(buf.pData_, littleEndian);
break;
- case numImportantColors:
- io_->read(buf.pData_, bufMinSize);
- if(Exiv2::getULong(buf.pData_, littleEndian)) {
- xmpData_["Xmp.video.NumIfImpColours"] = Exiv2::getULong(buf.pData_, littleEndian);
- }
- else {
- xmpData_["Xmp.video.NumOfImpColours"] = "All";
- }
+ case numImportantColors: io_->read(buf.pData_, bufMinSize);
+ if(Exiv2::getULong(buf.pData_, littleEndian)) xmpData_["Xmp.video.NumIfImpColours"] = Exiv2::getULong(buf.pData_, littleEndian);
+ else xmpData_["Xmp.video.NumOfImpColours"] = "All";
break;
}
}
}
- else if(streamType_ == Audio) {
- int c = 0;
+ else if(d->streamType_ == Audio){
+ int32_t c = 0;
const TagDetails* td;
- for(int i = 0; i <= 7; i++) {
+ for(int32_t i = 0; i <= 7; i++){
io_->read(buf.pData_, 2);
- switch(i) {
- case encoding:
- td = find(audioEncodingValues , Exiv2::getUShort(buf.pData_, littleEndian));
- if(td) {
- xmpData_["Xmp.audio.Compressor"] = exvGettext(td->label_);
- }
- else {
- xmpData_["Xmp.audio.Compressor"] = Exiv2::getUShort(buf.pData_, littleEndian);
- }
+ switch(i){
+ case encoding: td = find(audioEncodingValues , Exiv2::getUShort(buf.pData_, littleEndian));
+ if(td) xmpData_["Xmp.audio.Compressor"] = exvGettext(td->label_);
+ else xmpData_["Xmp.audio.Compressor"] = Exiv2::getUShort(buf.pData_, littleEndian);
break;
- case numberOfChannels:
- c = Exiv2::getUShort(buf.pData_, littleEndian);
+ case numberOfChannels: c = Exiv2::getUShort(buf.pData_, littleEndian);
if(c == 1) xmpData_["Xmp.audio.ChannelType"] = "Mono";
else if(c == 2) xmpData_["Xmp.audio.ChannelType"] = "Stereo";
else if(c == 5) xmpData_["Xmp.audio.ChannelType"] = "5.1 Surround Sound";
else if(c == 7) xmpData_["Xmp.audio.ChannelType"] = "7.1 Surround Sound";
else xmpData_["Xmp.audio.ChannelType"] = "Mono";
break;
- case audioSampleRate:
- xmpData_["Xmp.audio.SampleRate"] = Exiv2::getUShort(buf.pData_, littleEndian);
- break;
- case avgBytesPerSec:
- xmpData_["Xmp.audio.SampleType"] = Exiv2::getUShort(buf.pData_, littleEndian);
- break;
- case bitsPerSample:
- xmpData_["Xmp.audio.BitsPerSample"] = Exiv2::getUShort(buf.pData_,littleEndian);
- io_->read(buf.pData_, 2);
- break;
+ case audioSampleRate: xmpData_["Xmp.audio.SampleRate"] = Exiv2::getUShort(buf.pData_, littleEndian); break;
+ case avgBytesPerSec: xmpData_["Xmp.audio.SampleType"] = Exiv2::getUShort(buf.pData_, littleEndian); break;
+ case bitsPerSample: xmpData_["Xmp.audio.BitsPerSample"] = Exiv2::getUShort(buf.pData_,littleEndian);
+ io_->read(buf.pData_, 2); break;
}
}
}
io_->seek(cur_pos + size, BasicIo::beg);
- } // RiffVideo::streamFormatHandler
+ }
+ else{
+ if(d->streamType_ == Video){
+ DataBuf chkId((uint64_t) 5);
+ chkId.pData_[4] = '\0';
+ io_->read(chkId.pData_,4);
- double RiffVideo::returnSampleRate(Exiv2::DataBuf& buf, long divisor)
- {
- return ((double)Exiv2::getULong(buf.pData_, littleEndian) / (double)divisor);
- } // RiffVideo::returnSampleRate
+ writeLongData(xmpData_["Xmp.video.Width"],4);
+ writeLongData(xmpData_["Xmp.video.Height"],4);
+ writeShortData(xmpData_["Xmp.video.Planes"]);
+ writeShortData(xmpData_["Xmp.video.PixelDepth"]);
+ writeStringData(xmpData_["Xmp.video.Compressor"],4);
+ writeLongData(xmpData_["Xmp.video.ImageLength"],4);
+ writeLongData(xmpData_["Xmp.video.PixelPerMeterX"],4);
+ writeLongData(xmpData_["Xmp.video.PixelPerMeterY"],4);
+ writeLongData(xmpData_["Xmp.video.NumOfColours"],4);
- const char* RiffVideo::printAudioEncoding(uint64_t i)
- {
- const TagDetails* td;
- td = find(audioEncodingValues , i);
- if(td)
- return exvGettext(td->label_);
-
- return "Undefined";
- } // RiffVideo::printAudioEncoding
-
- void RiffVideo::fillAspectRatio(long width, long height)
- {
- double aspectRatio = (double)width / (double)height;
- aspectRatio = floor(aspectRatio*10) / 10;
- xmpData_["Xmp.video.AspectRatio"] = aspectRatio;
-
- int aR = (int) ((aspectRatio*10.0)+0.1);
-
- switch (aR) {
- case 13 : xmpData_["Xmp.video.AspectRatio"] = "4:3" ; break;
- case 17 : xmpData_["Xmp.video.AspectRatio"] = "16:9" ; break;
- case 10 : xmpData_["Xmp.video.AspectRatio"] = "1:1" ; break;
- case 16 : xmpData_["Xmp.video.AspectRatio"] = "16:10" ; break;
- case 22 : xmpData_["Xmp.video.AspectRatio"] = "2.21:1" ; break;
- case 23 : xmpData_["Xmp.video.AspectRatio"] = "2.35:1" ; break;
- case 12 : xmpData_["Xmp.video.AspectRatio"] = "5:4" ; break;
- default : xmpData_["Xmp.video.AspectRatio"] = aspectRatio;break;
- }
- } // RiffVideo::fillAspectRatio
-
- void RiffVideo::fillDuration(double frame_rate, long frame_count)
- {
- if(frame_rate == 0)
- return;
-
- uint64_t duration = static_cast((double)frame_count * (double)1000 / (double)frame_rate);
- xmpData_["Xmp.video.FileDataRate"] = (double)io_->size()/(double)(1048576*duration);
- xmpData_["Xmp.video.Duration"] = duration; //Duration in number of seconds
- } // RiffVideo::fillDuration
-
- Image::AutoPtr newRiffInstance(BasicIo::AutoPtr io, bool /*create*/)
- {
- Image::AutoPtr image(new RiffVideo(io));
- if (!image->good()) {
- image.reset();
+ //Variation
+ if(xmpData_["Xmp.video.NumOfImpColours"].count() > 0){
+ if(std::strcmp(xmpData_["Xmp.video.NumOfImpColours"].toString().c_str(),"All")){
+ const int32_t numImportantColours = (int32_t) 0;
+ io_->write((Exiv2::byte*)&numImportantColours,4);
+ }
+ else writeLongData(xmpData_["Xmp.video.NumOfImpColours"],4);
+ }
+ else io_->seek(4,BasicIo::cur);
}
- return image;
+ else if(d->streamType_ == Audio){
+ const RevTagDetails* rtd;
+ //Variation
+ if(xmpData_["Xmp.audio.Compressor"].count() > 0){
+ RevTagDetails revTagDetails[(sizeof(audioEncodingValues)/
+ sizeof(audioEncodingValues[0]))];
+ reverseTagDetails(audioEncodingValues,revTagDetails,
+ (sizeof(audioEncodingValues)
+ /sizeof(audioEncodingValues[0])));
+ rtd = find(revTagDetails,xmpData_["Xmp.audio.Compressor"].toString());
+ if(rtd){
+ uint16_t compressorCode= (uint16_t)rtd->val_;
+ io_->write((Exiv2::byte*)&compressorCode,2);
+ }
+ else io_->seek(2,BasicIo::cur);
+ }
+ else io_->seek(2,BasicIo::cur);
+
+ if(xmpData_["Xmp.audio.ChannelType"].count() > 0){
+ const int32_t sizeChan = xmpData_["Xmp.audio.ChannelType"].size();
+ DataBuf tmpBuf(sizeChan+1);
+ tmpBuf.pData_[sizeChan+1] = '\0';
+ const std::string audioChannealType = xmpData_["Xmp.audio.ChannelType"].toString();
+ int32_t i;
+ for( i=0; i<=sizeChan;i++) tmpBuf.pData_[i] = (Exiv2::byte)audioChannealType[i];
+ uint16_t channelType = 0;
+ if(UtilsVideo::simpleBytesComparision(tmpBuf,"MONO",sizeChan)) channelType = 1;
+ else if(UtilsVideo::simpleBytesComparision(tmpBuf,"STEREO",sizeChan)) channelType = 2;
+ else if(UtilsVideo::simpleBytesComparision(tmpBuf,"5.1 SURROUND SOUND",sizeChan)) channelType = 5;
+ else if(UtilsVideo::simpleBytesComparision(tmpBuf,"7.1 SURROUND SOUND",sizeChan)) channelType = 7;
+ io_->write((Exiv2::byte*)&channelType,2);
+ }
+ else io_->seek(2,BasicIo::cur);
+
+ writeShortData(xmpData_["Xmp.audio.SampleRate"],2,2);
+ writeShortData(xmpData_["Xmp.audio.SampleType"],2,4);
+ writeShortData(xmpData_["Xmp.audio.BitsPerSample"],2);
+ }
+ }
+ return;
+} // RiffVideo::streamFormatHandler
+
+double RiffVideo::returnSampleRate(Exiv2::DataBuf& buf, int32_t divisor){
+ return ((double)Exiv2::getULong(buf.pData_, littleEndian) / (double)divisor);
+} // RiffVideo::returnSampleRate
+
+const char* RiffVideo::printAudioEncoding(uint64_t i){
+ const TagDetails* td;
+ td = find(audioEncodingValues , i);
+ if(td) return exvGettext(td->label_);
+
+ return "Undefined";
+} // RiffVideo::printAudioEncoding
+
+void RiffVideo::fillAspectRatio(int32_t width, int32_t height){
+ double aspectRatio = (double)width / (double)height;
+ aspectRatio = floor(aspectRatio*10) / 10;
+ xmpData_["Xmp.video.AspectRatio"] = aspectRatio;
+
+ int32_t aR = (int32_t) ((aspectRatio*10.0)+0.1);
+
+ switch (aR) {
+ case 13 : xmpData_["Xmp.video.AspectRatio"] = "4:3" ; break;
+ case 17 : xmpData_["Xmp.video.AspectRatio"] = "16:9" ; break;
+ case 10 : xmpData_["Xmp.video.AspectRatio"] = "1:1" ; break;
+ case 16 : xmpData_["Xmp.video.AspectRatio"] = "16:10" ; break;
+ case 22 : xmpData_["Xmp.video.AspectRatio"] = "2.21:1" ; break;
+ case 23 : xmpData_["Xmp.video.AspectRatio"] = "2.35:1" ; break;
+ case 12 : xmpData_["Xmp.video.AspectRatio"] = "5:4" ; break;
+ default : xmpData_["Xmp.video.AspectRatio"] = aspectRatio;break;
+ }
+ return;
+} // RiffVideo::fillAspectRatio
+
+void RiffVideo::fillDuration(double frame_rate, int32_t frame_count){
+ if(frame_rate == 0) return;
+
+ uint64_t duration = static_cast((double)frame_count * (double)1000 / (double)frame_rate);
+ xmpData_["Xmp.video.FileDataRate"] = (double)io_->size()/(double)(1048576*duration);
+ xmpData_["Xmp.video.Duration"] = duration; //Duration in number of seconds
+ return;
+} // RiffVideo::fillDuration
+
+void RiffVideo::reverseTagDetails(const TagDetails inputTagVocabulary[],
+ RevTagDetails outputTagVocabulary[] ,int32_t size){
+ for(int32_t i=0; igood()) image.reset();
+ return image;
+}
+
+/*!
+ * \brief RiffVideo::copyRestOfTheFile
+ * Move all data to next locations,Currently its blockwise copy,which is inefficient for a
+ * huge video files,and should be changed to inserting technique without moving huge data
+ * like Bundle technology as suggested by Robin.
+ * \param oldSavedData
+ * \return
+ */
+bool RiffVideo::copyRestOfTheFile(DataBuf oldSavedData){
+
+ int32_t writeSize = oldSavedData.size_;
+ int32_t readSize = writeSize;
+ DataBuf readBuf((int32_t)max(readSize,(int32_t)1024));
+ DataBuf writeBuf((int32_t)max(readSize,(int32_t)1024));
+
+ memcpy(writeBuf.pData_,oldSavedData.pData_,readSize);
+ bool lastStream = false,hasData = true;
+
+ while(hasData){
+ if((io_->size() - io_->tell()) < 1024){
+ hasData = false;
+ lastStream = true;
+ readSize = (io_->size() - io_->tell());
+ }
+
+ io_->read(readBuf.pData_,readSize);
+ io_->seek(-readSize,BasicIo::cur);
+ io_->write(writeBuf.pData_,writeSize);
+
+ memcpy(writeBuf.pData_,readBuf.pData_,readSize);
+ writeSize = readSize;
+ if(lastStream) io_->write(writeBuf.pData_,readSize);
+ }
+ return true;
+}
+
+/*!
+ * \brief RiffVideo::writeNewSubChunks
+ * precondition:INFO List chunk must exist,atleast with LIST tag,
+ * and size field with size one(INFO tag which appear next)
+ *
+ * |----LIST(Must exist before calling this method)
+ * |----Size(Must exist, atleast with size 1 if no INFO subchunks exist before)
+ * |----INFO (Must exist,exactly with same HeaderChunkId INFO)
+ *
+ * \param chunkData
+ * \return
+ */
+bool RiffVideo::writeNewSubChunks(std::vector > chunkData){
+ bool result = true;
+ int32_t addSize = 0;
+ for (vector >::iterator it = chunkData.begin();
+ it != chunkData.end(); it++){
+ std::pair unitChunk = (*it);
+ addSize += (int32_t)unitChunk.first.size() + (int32_t)8;
+ addSize += addSize%2;
+ }
+ const int32_t cur_pos = io_->tell();
+ DataBuf buf((uint64_t)5);
+ buf.pData_[4] = '\0';
+ io_->seek(4,BasicIo::beg);
+ io_->read(buf.pData_,4);
+ io_->seek(-4,BasicIo::cur);
+
+ const int32_t originalSize = Exiv2::getULong(buf.pData_, littleEndian);
+ int32_t newRiffSize = originalSize + addSize ;
+ io_->write((Exiv2::byte*)&newRiffSize,4);
+
+ io_->seek(cur_pos,BasicIo::beg);
+ io_->read(buf.pData_,4);
+ io_->seek(-4,BasicIo::cur);
+
+ const int32_t originalListSize = Exiv2::getULong(buf.pData_, littleEndian);
+ int32_t newListSize = originalListSize + addSize ;
+ io_->write((Exiv2::byte*)&newListSize,4);
+
+ io_->read(buf.pData_,4);
+ std::vector previousData;
+ uint64_t i;
+
+ for (vector >::iterator it = chunkData.begin();
+ it != chunkData.end(); it++){
+ std::pair unitChunk = (*it);
+ std::string chunkId = unitChunk.second;
+ std::string tmpChunkData = unitChunk.first;
+ uint64_t chunkSize = tmpChunkData.size();
+ chunkSize += chunkSize%2;
+
+ DataBuf copiedData((int32_t)(chunkSize+8));
+
+ io_->read(copiedData.pData_,(chunkSize+8));
+ io_->seek(((-1)*(chunkSize+8)),BasicIo::cur);
+ previousData.push_back(copiedData);
+ Exiv2::byte rawChunkId[4] = {(Exiv2::byte)chunkId[0],(Exiv2::byte)chunkId[1],
+ (Exiv2::byte)chunkId[2],(Exiv2::byte)chunkId[3]};
+ Exiv2::byte* rawChunkData = new byte[(int32_t)chunkSize];
+
+ for(i=0; i < chunkSize; i++) rawChunkData[i] = (Exiv2::byte)tmpChunkData[i];
+ if(tmpChunkData.size()%2 != 0) rawChunkData[(int32_t)(chunkSize-1)] = (Exiv2::byte)0;
+
+ io_->write(rawChunkId,4);
+ io_->write((Exiv2::byte*)&chunkSize,4);
+ io_->write(rawChunkData,chunkSize);
+ delete[] rawChunkData;
}
- bool isRiffType(BasicIo& iIo, bool advance)
- {
- const int32_t len = 2;
- const unsigned char RiffVideoId[4] = { 'R', 'I', 'F' ,'F'};
- byte buf[len];
- iIo.read(buf, len);
- if (iIo.error() || iIo.eof()) {
- return false;
+ int32_t accessIndex = 0;
+ int32_t netNewMetadataSize = 0;
+ for (i=0; i < (int32_t)previousData.size(); i++) netNewMetadataSize += previousData[i].size_;
+
+ DataBuf metadataPacket((uint64_t)netNewMetadataSize);
+ for (i=0; i < previousData.size(); i++){
+ for(int32_t assignIndex=0; assignIndex 0){
+ std::string dataString = xmpStringData.toString();
+ Exiv2::byte* rawData = new byte[(uint8_t)size];
+ int32_t newSize = (int32_t)dataString.size();
+ for(int32_t i=0; i newSize) for(int32_t i=newSize; iwrite(rawData,size);
+ io_->seek((int)skipOffset,BasicIo::cur);
+ delete[] rawData;
+ }
+ else io_->seek((size+skipOffset),BasicIo::cur);
+}
+
+void RiffVideo::writeLongData(Exiv2::Xmpdatum xmpIntData, int32_t size, int32_t skipOffset){
+ if(xmpIntData.count() > 0){
+ int32_t rawIntData = (int32_t)xmpIntData.toLong();
+ io_->write((Exiv2::byte*)&rawIntData,size);
+ io_->seek(skipOffset,BasicIo::cur);
+ }
+ else io_->seek((size+skipOffset),BasicIo::cur);
+}
+
+void RiffVideo::writeFloatData(Exiv2::Xmpdatum xmpIntData, int32_t size, int32_t skipOffset){
+ if(xmpIntData.count() > 0){
+ int32_t rawIntData = (int32_t)xmpIntData.toFloat();
+ io_->write((Exiv2::byte*)&rawIntData,size);
+ io_->seek(skipOffset,BasicIo::cur);
+ }
+ else io_->seek((size+skipOffset),BasicIo::cur);
+}
+
+void RiffVideo::writeShortData(Exiv2::Xmpdatum xmpIntData, int16_t size, int32_t skipOffset){
+ if(xmpIntData.count() > 0){
+ int16_t rawIntData = (int16_t)xmpIntData.toLong();
+ io_->write((Exiv2::byte*)&rawIntData,size);
+ io_->seek(skipOffset,BasicIo::cur);
+ }
+ else io_->seek((size+skipOffset),BasicIo::cur);
+}
+
+bool isRiffType(BasicIo& iIo, bool advance){
+ const int32_t len = 2;
+ const unsigned char RiffVideoId[4] = { 'R', 'I', 'F' ,'F'};
+ Exiv2::byte* buf = new byte[len];
+ iIo.read(buf, len);
+ if (iIo.error() || iIo.eof()){
+ delete[] buf;
+ return false;
+ }
+ bool matched = (memcmp(buf, RiffVideoId, len) == 0);
+ if (!advance || !matched) iIo.seek(-len, BasicIo::cur);
+ delete[] buf;
+ return matched;
+}
} // namespace Exiv2
+
diff --git a/src/riffvideo.hpp b/src/riffvideo.hpp
index 785d27ce..7b6f25f7 100644
--- a/src/riffvideo.hpp
+++ b/src/riffvideo.hpp
@@ -22,8 +22,11 @@
@file riffvideo.hpp
@brief An Image subclass to support RIFF video files
@version $Rev$
- @author Abhinav Badola for GSoC 2012
+ @authors Abhinav Badola for GSoC 2012
mail.abu.to@gmail.com
+
+ Mahesh Hegde for GSoC 2013
+ maheshmhegade@gmail.com
@date 18-Jun-12, AB: created
*/
#ifndef RIFFVIDEO_HPP
@@ -42,20 +45,78 @@ namespace Exiv2 {
// *****************************************************************************
// class definitions
- // Add RIFF to the supported image formats
- namespace ImageType {
- const int riff = 20; //!< Treating riff as an image type>
- }
+// Add RIFF to the supported image formats
+namespace ImageType {
+const int riff = 20; //!< Treating riff as an image type>
+}
- /*!
+using namespace std;
+/*!
@brief Class to access RIFF video files.
*/
- class EXIV2API RiffVideo:public Image
+class EXIV2API RiffVideo:public Image
+{
+public:
+
+ //List, Header,Primitive and Junk chunks inside m_riffFileSkeleton reveal entire RIFF structure
+ /*!
+ * \brief The PrimitiveChunk class Hold the information about a unit chunk.
+ */
+ class PrimitiveChunk
{
public:
- //! @name Creators
- //@{
- /*!
+ PrimitiveChunk(){}
+ ~PrimitiveChunk(){}
+
+ public:
+ byte m_chunkId[5]; //!< Primitive chunk ID.
+ uint64_t m_chunkLocation; //!< Chunk location in afile.
+ uint64_t m_chunkSize; //!< Chunk size.
+ };
+
+ /*!
+ * \brief The HeaderChunk class Hold the information about Header chunk
+ * Containing multiple primitive chunks.
+ */
+ class HeaderChunk
+ {
+ public:
+ HeaderChunk(){}
+ ~HeaderChunk(){}
+
+ public:
+ byte m_headerId[5]; //!< Chunk Header Id
+ unsigned long m_headerLocation; //!< Header Chunk Location in a file.
+ unsigned long m_headerSize; //!< Header Chunk size
+ };
+
+ /*!
+ * \brief The RiffMetaSkeleton class Hold information about all the
+ * chunks present in a file.
+ */
+ class RiffMetaSkeleton
+ {
+ public:
+ RiffMetaSkeleton(){}
+ ~RiffMetaSkeleton(){}
+
+ public:
+ vector m_headerChunks; //!< vector containing all Header chunks.
+ vector m_primitiveChunks; //!< vector Containing all the primitve chunks
+ };
+
+ /*!
+ * \brief The IoPosition enum reveal the position,while traversing the file.
+ */
+ enum IoPosition
+ {
+ LastChunk, //!< "MOVI" or "DATA"
+ TraversingChunk, //!< "AVI" "hdrl" etc which further have sub-chunks
+ PremitiveChunk //!< Remaining chunks which do not have subchunk
+ };
+ //! @name Creators
+ //@{
+ /*!
@brief Constructor for a Riff video. Since the constructor
can not return a result, callers should check the good() method
after object construction to determine success or failure.
@@ -66,149 +127,227 @@ namespace Exiv2 {
instance after it is passed to this method. Use the Image::io()
method to get a temporary reference.
*/
- RiffVideo(BasicIo::AutoPtr io);
- //@}
+ RiffVideo(BasicIo::AutoPtr io);
+ //@}
- //! @name Manipulators
- //@{
- void readMetadata();
- void writeMetadata();
- //@}
+ ~RiffVideo();
- //! @name Accessors
- //@{
- std::string mimeType() const;
- const char* printAudioEncoding(uint64_t i);
- //@}
+ //! @name Manipulators
+ //@{
+ void readMetadata();
+ void writeMetadata();
+ //@}
- protected:
- /*!
+ //! @name Accessors
+ //@{
+ std::string mimeType() const;
+ const char* printAudioEncoding(uint64_t i);
+ //@}
+
+protected:
+ /*!
@brief Check for a valid tag and decode the block at the current IO
position. Calls tagDecoder() or skips to next tag, if required.
*/
- void decodeBlock();
- /*!
- @brief Interpret tag information, and call the respective function
- to save it in the respective XMP container. Decodes a Tag
- Information and saves it in the respective XMP container, if
- the block size is small.
- @param buf Data buffer which cotains tag ID.
- @param size Size of the data block used to store Tag Information.
- */
- void tagDecoder(Exiv2::DataBuf& buf, unsigned long size);
- /*!
+ void decodeBlock();
+ /*!
+ * \brief tagDecoder Main method to call corresponding handler methos for decoding tags.
+ */
+ void tagDecoder();
+ /*!
@brief Interpret Junk tag information, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void junkHandler(long size);
- /*!
+ void junkHandler(int32_t size);
+
+ /*! find whether stream is audio or video
+ */
+ void setStreamType();
+ /*!
@brief Interpret Stream tag information, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void streamHandler(long size);
- /*!
+ void streamHandler(int32_t size);
+ /*!
@brief Interpret Stream Format tag information, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void streamFormatHandler(long size);
- /*!
+ void streamFormatHandler(int32_t size);
+ /*!
@brief Interpret Riff Header tag information, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void aviHeaderTagsHandler(long size);
- /*!
+ void aviHeaderTagsHandler(int32_t size);
+ /*!
@brief Interpret Riff List tag information, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void listHandler(long size);
- /*!
+ void listHandler(long size);
+ /*!
@brief Interpret Riff Stream Data tag information, and save it
in the respective XMP container.
@param size Size of the data block used to store Tag Information.
*/
- void streamDataTagHandler(long size);
- /*!
+ void streamDataTagHandler(int32_t size);
+ /*!
@brief Interpret INFO tag information, and save it
in the respective XMP container.
*/
- void infoTagsHandler();
- /*!
+ void infoTagsHandler();
+ /*!
@brief Interpret Nikon Tags related to Video information, and
save it in the respective XMP container.
*/
- void nikonTagsHandler();
- /*!
+ void nikonTagsHandler();
+ /*!
@brief Interpret OpenDML tag information, and save it
in the respective XMP container.
*/
- void odmlTagsHandler();
- //! @brief Skips Particular Blocks of Metadata List.
- void skipListData();
- /*!
+ void odmlTagsHandler();
+ //! @brief Skips Particular Blocks of Metadata List.
+ void skipListData();
+ /*!
@brief Interprets DateTimeOriginal tag or stream name tag
information, and save it in the respective XMP container.
@param size Size of the data block used to store Tag Information.
@param i parameter used to overload function
*/
- void dateTimeOriginal(long size, int i = 0);
- /*!
+ void dateTimeOriginal(int32_t size, int32_t i = 0);
+ /*!
@brief Calculates Sample Rate of a particular stream.
@param buf Data buffer with the dividend.
@param divisor The Divisor required to calculate sample rate.
@return Return the sample rate of the stream.
*/
- double returnSampleRate(Exiv2::DataBuf& buf, long divisor = 1);
- /*!
+ double returnSampleRate(Exiv2::DataBuf& buf, int32_t divisor = 1);
+ /*!
@brief Calculates Aspect Ratio of a video, and stores it in the
respective XMP container.
@param width Width of the video.
@param height Height of the video.
*/
- void fillAspectRatio(long width = 1,long height = 1);
- /*!
+ void fillAspectRatio(int32_t width = 1, int32_t height = 1);
+ /*!
@brief Calculates Duration of a video, and stores it in the
respective XMP container.
@param frame_rate Frame rate of the video.
@param frame_count Total number of frames present in the video.
*/
- void fillDuration(double frame_rate, long frame_count);
+ void fillDuration(double frame_rate, int32_t frame_count);
- private:
- //! @name NOT Implemented
- //@{
- //! Copy constructor
- RiffVideo(const RiffVideo& rhs);
- //! Assignment operator
- RiffVideo& operator=(const RiffVideo& rhs);
- //@}
+ /*!
+ * \brief copyRestOfTheFile copy rest of the file content as it is
+ * \param oldSavedData saved data from file, where data is already written into the file.
+ * \return
+ */
+ bool copyRestOfTheFile(DataBuf oldSavedData);
- private:
- //! Variable to check the end of metadata traversing.
- bool continueTraversing_;
- //! Variable which stores current stream being processsed.
- int streamType_;
+ /*!
+ * \brief reverseTagDetails reverse the position of members of a structure
+ * \param inputTagVocabulary
+ * \param outputTagVocabulary
+ * \param size
+ */
+ void reverseTagDetails(const Internal::TagDetails inputTagVocabulary[],
+ Internal::RevTagDetails outputTagVocabulary[] , int32_t size);
- }; //Class RiffVideo
+private:
+ //! @name NOT Implemented
+ //@{
+ //! Copy constructor
+ RiffVideo(const RiffVideo& rhs);
+ //! Assignment operator
+ RiffVideo& operator=(const RiffVideo& rhs);
+ //@}
+ /*!
+ @brief Provides the main implementation of writeMetadata() by
+ writing all buffered metadata to the provided BasicIo.
+ @param oIo BasicIo instance to write to (a temporary location).
+
+ @return 4 if opening or writing to the associated BasicIo fails
+ */
+ EXV_DLLLOCAL void doWriteMetadata();
+
+ /*!
+ * \brief findChunkPositions Finds the primitive shunk position in a file.
+ * \param chunkId Id of chunk to be searched
+ * \return
+ */
+ std::vector findChunkPositions(const char *chunkId);
+
+ /*!
+ * \brief findHeaderPositions Finds the location of Header chunk in a file.
+ * \param headerId Id of Header Chunk to be searched.
+ * \return
+ */
+ std::vector findHeaderPositions(const char* headerId);
+
+ /*!
+ * \brief writeNewSubChunks Writes the new chunk,also hold the data from overwritten
+ * location in a file.
+ * \param chunkData vector containing chunk ID and chunk Data
+ * \return
+ */
+ bool writeNewSubChunks(std::vector > chunkData);
+
+ /*!
+ * \brief writeStringData
+ * \param stringData
+ * \param skipOffset
+ */
+ void writeStringData(Exiv2::Xmpdatum xmpStringData, int32_t size, int32_t skipOffset=0);
+
+ /*!
+ * \brief writeLongData
+ * \param xmpIntData
+ * \param size
+ * \param skipOffset
+ */
+ void writeLongData(Exiv2::Xmpdatum xmpIntData, int32_t size=4, int32_t skipOffset=0);
+
+ /*!
+ * \brief writeFloatData
+ * \param xmpIntData
+ * \param size
+ * \param skipOffset
+ */
+ void writeFloatData(Exiv2::Xmpdatum xmpIntData, int32_t size=4, int32_t skipOffset=0);
+
+ /*!
+ * \brief writeShortData
+ * \param xmpIntData
+ * \param size
+ * \param skipOffset
+ */
+ void writeShortData(Exiv2::Xmpdatum xmpIntData, int16_t size=2, int32_t skipOffset=0);
+
+private:
+
+ // Good idea to use private(Refer KDE documentaion https://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++ )
+ class Private;
+ Private* const d;
+
+}; //Class RiffVideo
// *****************************************************************************
// template, inline and free functions
- // These could be static private functions on Image subclasses but then
- // ImageFactory needs to be made a friend.
- /*!
+// These could be static private functions on Image subclasses but then
+// ImageFactory needs to be made a friend.
+/*!
@brief Create a new RiffVideo instance and return an auto-pointer to it.
Caller owns the returned object and the auto-pointer ensures that
it will be deleted.
*/
- EXIV2API Image::AutoPtr newRiffInstance(BasicIo::AutoPtr io, bool create);
+EXIV2API Image::AutoPtr newRiffInstance(BasicIo::AutoPtr io, bool create);
- //! Check if the file iIo is a Riff Video.
- EXIV2API bool isRiffType(BasicIo& iIo, bool advance);
+//! Check if the file iIo is a Riff Video.
+EXIV2API bool isRiffType(BasicIo& iIo, bool advance);
} // namespace Exiv2
diff --git a/src/tags_int.hpp b/src/tags_int.hpp
index 9e8fb484..f3db507e 100644
--- a/src/tags_int.hpp
+++ b/src/tags_int.hpp
@@ -191,6 +191,18 @@ namespace Exiv2 {
bool operator==(long key) const { return val_ == key; }
}; // struct TagDetails
+ /*!
+ @brief Helper structure for lookup tables for translations of numeric
+ tag values to human readable labels.
+ */
+
+ struct RevTagDetails {
+ const char* label_; //!< Translation of the tag value
+ long val_; //!< Tag value
+
+ //! Comparison operator for use with the find template
+ bool operator==(const std::string& key) const{return label_ == key;}
+ };
/*!
@brief Helper structure for lookup tables for translations of bitmask
values to human readable labels.
diff --git a/src/types.cpp b/src/types.cpp
index c5a70151..61f3f6ac 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -125,10 +125,12 @@ namespace Exiv2 {
return tit->size_;
}
- DataBuf::DataBuf(DataBuf& rhs)
+ DataBuf::DataBuf(const DataBuf& rhs)
: pData_(rhs.pData_), size_(rhs.size_)
{
- rhs.release();
+ pData_ = new byte[rhs.size_];
+ size_ = rhs.size_;
+ std::copy(rhs.pData_,rhs.pData_+rhs.size_,pData_);
}
DataBuf::DataBuf(const byte* pData, long size)
@@ -156,6 +158,7 @@ namespace Exiv2 {
size_ = 0;
pData_ = new byte[size];
size_ = size;
+ std::memset(pData_, 0x0, size_);
}
}
diff --git a/src/types.hpp b/src/types.hpp
index 8bf258b3..42bd3355 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -54,6 +54,7 @@
#include
#include
#include
+#include
#ifdef EXV_HAVE_STDINT_H
# include
@@ -209,7 +210,7 @@ namespace Exiv2 {
//! Default constructor
DataBuf() : pData_(0), size_(0) {}
//! Constructor with an initial buffer size
- explicit DataBuf(long size) : pData_(new byte[size]), size_(size) {}
+ explicit DataBuf(long size) : pData_(new byte[size]), size_(size) { std::memset(pData_, 0x0, size_); }
//! Constructor, copies an existing buffer
DataBuf(const byte* pData, long size);
/*!
@@ -217,7 +218,7 @@ namespace Exiv2 {
object similar to std::auto_ptr, i.e., the original object is
modified.
*/
- DataBuf(DataBuf& rhs);
+ DataBuf(const DataBuf& rhs);
//! Destructor, deletes the allocated buffer
~DataBuf() { delete[] pData_; }
//@}
diff --git a/src/utilsvideo.cpp b/src/utilsvideo.cpp
new file mode 100644
index 00000000..b9f70b98
--- /dev/null
+++ b/src/utilsvideo.cpp
@@ -0,0 +1,60 @@
+// ***************************************************************** -*- C++ -*-
+/*
+ * Copyright (C) 2004-2014 Andreas Huggel
+ *
+ * This program is part of the Exiv2 distribution.
+ *
+ * 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, 5th Floor, Boston, MA 02110-1301 USA.
+ */
+/*!
+ @file utilsvideo.hpp
+ @brief An Image subclass to support RIFF video files
+ @version $Rev$
+ Mahesh Hegde 2014
+ maheshmhegade@gmail.com
+ @date 16-Aug-14, AB: created
+ */
+#include "utilsvideo.hpp"
+
+#ifndef _MSC_VER
+#define stricmp strcasecmp
+#endif
+
+namespace Exiv2
+{
+
+bool UtilsVideo::compareTagValue(Exiv2::DataBuf& buf ,const char* str){
+ bool result = true;
+ for(int32_t i=0; result && i<4; i++ )
+ if(tolower(buf.pData_[i]) != tolower(str[i]))
+ return false;
+ return true;
+}
+
+bool UtilsVideo::compareTagValue(Exiv2::DataBuf& buf,const char arr[][5],int32_t arraysize){
+ bool result = false;
+ for ( int32_t i=0; !result && i< arraysize; i++)
+ result = (bool)(stricmp((const char*)buf.pData_,arr[i])==0);
+ return result;
+}
+
+bool UtilsVideo::simpleBytesComparision(Exiv2::DataBuf& buf ,const char* str,int32_t size){
+ for(int32_t i=0; i
+ *
+ * This program is part of the Exiv2 distribution.
+ *
+ * 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, 5th Floor, Boston, MA 02110-1301 USA.
+ */
+/*!
+ @file utilsvideo.hpp
+ @brief An Image subclass to support RIFF video files
+ @version $Rev$
+ Mahesh Hegde 2014
+ maheshmhegade@gmail.com
+ @date 16-Aug-14, AB: created
+ */
+#include "tags_int.hpp"
+
+namespace Exiv2
+{
+
+class UtilsVideo
+{
+public:
+ static bool compareTagValue(Exiv2::DataBuf &buf, const char *str);
+ static bool compareTagValue(Exiv2::DataBuf& buf,const char arr[][5],int32_t arraysize);
+ static bool simpleBytesComparision(Exiv2::DataBuf& buf ,const char* str,int32_t size);
+}; // class UtilsVideo
+
+} // namespace Exiv2
diff --git a/src/version.hpp b/src/version.hpp
index 8ab16c82..55f24baa 100644
--- a/src/version.hpp
+++ b/src/version.hpp
@@ -187,6 +187,7 @@ namespace Exiv2 {
// dumpLibraryInfo is general purpose and not in the Exiv2 namespace
// used by exiv2 test suite to inspect libraries loaded at run-time
+//! TO be completed.
EXIV2API void dumpLibraryInfo(std::ostream& os);
diff --git a/src/xmp.cpp b/src/xmp.cpp
index 870aad48..5a060471 100644
--- a/src/xmp.cpp
+++ b/src/xmp.cpp
@@ -416,6 +416,8 @@ namespace Exiv2 {
SXMPMeta::RegisterNamespace("http://ns.microsoft.com/photo/1.2/t/Region#", "MPReg");
SXMPMeta::RegisterNamespace("http://www.metadataworkinggroup.com/schemas/regions/", "mwg-rs");
SXMPMeta::RegisterNamespace("http://ns.adobe.com/xmp/sType/Area#", "stArea");
+ SXMPMeta::RegisterNamespace("http://www.video/", "video");
+ SXMPMeta::RegisterNamespace("http://www.audio/", "audio");
#else
initialized_ = true;
#endif
diff --git a/test/Makefile b/test/Makefile
index a0b8e12b..328fb561 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -65,24 +65,25 @@ SVN = svn://dev.exiv2.org/svn/testdata/trunk
##
# Add test drivers to this list
-TESTS = addmoddel.sh \
- bugfixes-test.sh \
- exifdata-test.sh \
- exiv2-test.sh \
- imagetest.sh \
- iotest.sh \
- iptctest.sh \
- modify-test.sh \
- path-test.sh \
- preview-test.sh \
- stringto-test.sh \
- tiff-test.sh \
- write-test.sh \
- write2-test.sh \
- xmpparser-test.sh \
- conversions.sh
-TESTV = video-test.sh
-TESTE = eps-test.sh
+TESTS = addmoddel.sh \
+ bugfixes-test.sh \
+ exifdata-test.sh \
+ exiv2-test.sh \
+ imagetest.sh \
+ iotest.sh \
+ iptctest.sh \
+ modify-test.sh \
+ path-test.sh \
+ preview-test.sh \
+ stringto-test.sh \
+ tiff-test.sh \
+ write-test.sh \
+ write2-test.sh \
+ xmpparser-test.sh \
+ conversions.sh
+TESTV = video-test.sh
+TESTE = eps-test.sh
+TESTVW = write-video-test.sh
tests:
cd .. ; make tests
@@ -99,15 +100,26 @@ test:
testv:
@for t in /video ; do \
if [ ! -e data/$$t ]; then \
- echo svn export '$(SVN)'$$t data$$t -r 3100 ; \
- svn export '$(SVN)'$$t data$$t -r 3100 ; \
+ echo svn export '$(SVN)'$$t data$$t ; \
+ svn export '$(SVN)'$$t data$$t ; \
fi ; done
@list='$(TESTV)'; for p in $$list; do \
echo Running $$p ...; \
./$$p; \
done
+testvw:
+ @for t in /video ; do \
+ if [ ! -e data/$$t ]; then \
+ echo svn export '$(SVN)'$$t data$$t ; \
+ svn export '$(SVN)'$$t data$$t ; \
+ fi ; done
+ @list='$(TESTVW)'; for p in $$list; do \
+ echo Running $$p ...; \
+ ./$$p; \
+ done
##
+
# TODO: download eps data on demand for 0.24 (similar to testv)
teste:
@list='$(TESTE)'; for p in $$list; do \
diff --git a/test/functions.source b/test/functions.source
index 162d9594..5e6a05f3 100644
--- a/test/functions.source
+++ b/test/functions.source
@@ -52,7 +52,8 @@ copyTestFile()
if [ $# == 2 ]; then
cp -f "$here/data/$1" "$here/tmp/$2"
elif [ $# == 1 ]; then
- cp -f "$here/data/$1" "$here/tmp/$1"
+ stub=$(basename $1)
+ cp -f "$here/data/$1" "$here/tmp/$stub"
else
echo "*** error copyTestFile: illegal number of inputs = $# ***"
fi
@@ -213,14 +214,14 @@ iptcTest()
# Make sure to pass the test file first and the known good file second
diffCheck()
{
- test=$1
- good=$2
+ test=$(real_path $1)
+ good=$(real_path $2)
if [ -z "$errors" ]; then let -a errors=0; fi
#run diff and check results
- diff -q --binary $diffargs $test $good
+ diff -q --binary $diffargs "$test" "$good"
if [ $? -ne 0 ]; then
- errors=`expr $errors + 1`
+ errors=$(expr $errors + 1)
else
rm $test
fi
@@ -341,39 +342,49 @@ extendedTest()
rm $tmp
}
+
##
-# http://stackoverflow.com/questions/1055671/how-can-i-get-the-behavior-of-gnus-readlink-f-on-a-mac
+# real_path - report the absolute path to a file
real_path ()
{
- OIFS=$IFS
- IFS='/'
- for I in $1; do
- # Resolve relative path punctuation.
- if [ "$I" = "." ] || [ -z "$I" ]; then
- continue
- elif [ "$I" = ".." ]; then
- FOO="${FOO%%/${FOO##*/}}"
- continue
- else
- FOO="${FOO}/${I}"
- fi
+ which realpath 2>/dev/null >/dev/null
+ if [ $? == 0 ]; then
+ realpath "$1"
+ else
+ readlink -f "$1"
+ fi
+}
- ## Resolve symbolic links
- if [ -h "$FOO" ]; then
- IFS=$OIFS
- set `ls -l "$FOO"`
- while shift ; do
- if [ "$1" = "->" ]; then
- FOO=$2
- shift $#
- break
- fi
- done
- IFS='/'
- fi
- done
- IFS=$OIFS
- echo "$FOO"
+copyVideoFiles ()
+{
+ pushd "$testdir" 2>/dev/null >/dev/null
+
+ ##
+ # find video files data/video and copy them for testing
+ declare -a videos
+ for video in $datadir/video/* ; do
+ # http://stackoverflow.com/questions/965053/extract-filename-and-extension-in-bash
+ ext="${video##*.}"
+ if [ $ext != out ]; then
+ copyTestFile "$video"
+ videos+=($(basename "$video"))
+ fi
+ done
+
+ ##
+ # TODO: remove debugging code
+ if [ "$FACTORY" == "rmills-mbp.localXX" ]; then
+ for v in write-video-test.out video-test.out; do
+ cp ~/gnu/exiv2/testdata/trunk/video/$v ~/gnu/exiv2/video13/test/data/video/
+ done
+ fi
+
+ # http://stackoverflow.com/questions/7442417/how-to-sort-an-array-in-bash
+ readarray -t sorted < <(printf '%s\0' "${videos[@]}" | sort -z | xargs -0n1)
+ echo ${videos[*]}
+ unset videos
+
+ popd 2>/dev/null >/dev/null
}
##
diff --git a/test/video-test.sh b/test/video-test.sh
index 4f4dde90..fa14aaf5 100755
--- a/test/video-test.sh
+++ b/test/video-test.sh
@@ -8,42 +8,35 @@
source ./functions.source
+##
+# set up output and reference file
+out=$(real_path "$testdir/$this.out")
+copyTestFile "video/$this.out"
+
( cd "$testdir"
- for file in ../data/video/video-*; do
- video="`basename "$file"`"
- if [ $video != "video-test.out" ] ; then
-
- printf "." >&3
-
- echo
- echo "-----> $video <-----"
-
- copyTestFile "video/$video" "$video"
-
- echo
- echo "Command: exiv2 -u -pa $video"
- runTest exiv2 -u -pa "$video"
- exitcode="$?"
- echo "Exit code: $exitcode"
-
- if [ "$exitcode" -ne 0 -a "$exitcode" -ne 253 ] ; then
- continue
- fi
- fi
+ videos=($(copyVideoFiles))
+ for video in ${videos[*]}; do
+ printf "." >&3
+ echo
+ echo "-----> $video <-----"
+ echo
+ echo "Command: exiv2 -u -pa $video"
+ # run command | ignore binary and no Date nor NumOfColours tags
+ runTest exiv2 -u -pa "$video" | sed -E -e 's/\d128-\d255/_/g' | grep -a -v -e Date -v -e NumOfC
done
-) 3>&1 > "$testdir/video-test.out" 2>&1
-
-echo "."
+) 3>&1 2>&1 > "$out"
# ----------------------------------------------------------------------
# Result
-if ! diff -q $diffargs "$testdir/$datadir/video/video-test.out" "$testdir/video-test.out" ; then
- diff -u -a $diffargs "$testdir/$datadir/video/video-test.out" "$testdir/video-test.out"
- exit 1
+diffCheck "$out" "$testdir/$datadir/video/$this.out"
+
+if [ $errors ]; then
+ echo -e $errors 'test case(s) failed!'
+else
+ echo -e "all testcases passed."
fi
-echo "All testcases passed."
# That's all Folks!
-##
\ No newline at end of file
+##
diff --git a/test/write-video-test.sh b/test/write-video-test.sh
new file mode 100755
index 00000000..8207b8e5
--- /dev/null
+++ b/test/write-video-test.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+# Test driver for write video
+
+source ./functions.source
+
+##
+# set up output and reference file
+out=$(real_path "$testdir/$this.out")
+copyTestFile "video/$this.out"
+
+( cd "$testdir"
+
+ videos=($(copyVideoFiles))
+
+ # write metadata to videos
+ runTest exiv2 -M "set Xmp.video.MicroSecPerFrame 64" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.MaxDataRate 4096" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.FrameCount 2048" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.InitialFrames 4" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.StreamCount 2" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.SuggestedBufferSize 1024" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.Width 240" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.Height 320" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.FileDataRate 128" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.Duration 2048" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.Codec mjpg" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.FrameRate 1024" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.VideoQuality 128" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.VideoSampleSize 256" ${videos[*]}
+ runTest exiv2 -M "set Xmp.audio.Codec mpv4" ${videos[*]}
+ runTest exiv2 -M "set Xmp.audio.SampleRate 32" ${videos[*]}
+ runTest exiv2 -M "set Xmp.audio.SampleCount 32" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.DateUT $date" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.Comment Metadata was Edited Using Exiv2" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.Language Kannada" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.Country India" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.Copyright Photographer" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.Genre Sample Test Video" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.Software Exiv2 0.25" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.Junk Its a junk Data" ${videos[*]}
+ runTest exiv2 -M "set Xmp.video.MediaLanguage English" ${videos[*]}
+
+ for video in ${videos[*]}; do
+ printf "." >&3
+ echo
+ echo "-----> $video <-----"
+ echo
+ echo "Command: exiv2 -u -pa $video"
+ # run command | ignore binary and no Date nor NumOfColours tags
+ runTest exiv2 -u -pa "$video" | sed -E -e 's/\d128-\d255/_/g' | grep -a -v -e Date
+ done
+
+) 3>&1 2>&1 > "$out"
+
+echo "."
+
+# ----------------------------------------------------------------------
+# Result
+diffCheck "$out" "$testdir/$datadir/video/$this.out"
+
+if [ $errors ]; then
+ echo -e $errors 'test case(s) failed!'
+else
+ echo -e "all testcases passed."
+fi
+
+# That's all Folks!
+##