From 3456f3098897330ea3a3efff9b19f624e407c22e Mon Sep 17 00:00:00 2001 From: Christoph Hasse Date: Mon, 22 Aug 2022 17:01:25 +0200 Subject: [PATCH] fix(video) clang-format quicktimevideo --- include/exiv2/quicktimevideo.hpp | 393 ++-- src/image.cpp | 4 +- src/quicktimevideo.cpp | 3075 +++++++++++++++--------------- 3 files changed, 1719 insertions(+), 1753 deletions(-) diff --git a/include/exiv2/quicktimevideo.hpp b/include/exiv2/quicktimevideo.hpp index 5946dc5f..78eb1dd0 100644 --- a/include/exiv2/quicktimevideo.hpp +++ b/include/exiv2/quicktimevideo.hpp @@ -34,207 +34,206 @@ namespace Exiv2 { // ***************************************************************************** // class definitions - /*! - @brief Class to access QuickTime video files. - */ - class QuickTimeVideo:public Image - { - 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. - @param io An auto-pointer that owns a BasicIo instance used for - reading and writing image metadata. \b Important: The constructor - takes ownership of the passed in BasicIo instance through the - auto-pointer. Callers should not continue to use the BasicIo - instance after it is passed to this method. Use the Image::io() - method to get a temporary reference. - */ - QuickTimeVideo(BasicIo::UniquePtr io); - //@} - - //! @name Manipulators - //@{ - void readMetadata(); - void writeMetadata(); - //@} - - //! @name Accessors - //@{ - std::string mimeType() const; - //@} - - 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); - - 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); - /*! - @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); - /*! - @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); - /*! - @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); - /*! - @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); - /*! - @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); - /*! - @brief Interpret Tag which contain other sub-tags, - and save it in the respective XMP container. - */ - void multipleEntriesDecoder(); - /*! - @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); - /*! - @brief Interpret Image Description Tag, and save it - in the respective XMP container. - */ - 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); - /*! - @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); - /*! - @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); - /*! - @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); - /*! - @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); - /*! - @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); - /*! - @brief Interpret Audio Description Tag, and save it - in the respective XMP container. - */ - void audioDescDecoder(); - /*! - @brief Helps to calculate Frame Rate from timeToSample chunk, - and save it in the respective XMP container. - */ - void timeToSampleDecoder(); - /*! - @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); - /*! - @brief Calculates Aspect Ratio of a video, and stores it in the - respective XMP container. - */ - void aspectRatio(); - - private: - //! @name NOT Implemented - //@{ - //! Copy constructor - QuickTimeVideo(const QuickTimeVideo& rhs); - //! Assignment operator - QuickTimeVideo& operator=(const QuickTimeVideo& rhs); - //@} - - 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_; - - }; //QuickTimeVideo End +/*! + @brief Class to access QuickTime video files. + */ +class QuickTimeVideo : public Image { + 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. + @param io An auto-pointer that owns a BasicIo instance used for + reading and writing image metadata. \b Important: The constructor + takes ownership of the passed in BasicIo instance through the + auto-pointer. Callers should not continue to use the BasicIo + instance after it is passed to this method. Use the Image::io() + method to get a temporary reference. + */ + QuickTimeVideo(BasicIo::UniquePtr io); + //@} + + //! @name Manipulators + //@{ + void readMetadata(); + void writeMetadata(); + //@} + + //! @name Accessors + //@{ + std::string mimeType() const; + //@} + + 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, uint64_t size); + + 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(uint64_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(uint64_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(uint64_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(uint64_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(uint64_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(uint64_t size); + /*! + @brief Interpret Tag which contain other sub-tags, + and save it in the respective XMP container. + */ + void multipleEntriesDecoder(); + /*! + @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(uint64_t size); + /*! + @brief Interpret Image Description Tag, and save it + in the respective XMP container. + */ + 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(uint64_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(uint64_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(uint64_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(uint64_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(uint64_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(uint64_t size); + /*! + @brief Interpret Audio Description Tag, and save it + in the respective XMP container. + */ + void audioDescDecoder(); + /*! + @brief Helps to calculate Frame Rate from timeToSample chunk, + and save it in the respective XMP container. + */ + void timeToSampleDecoder(); + /*! + @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(uint64_t size); + /*! + @brief Calculates Aspect Ratio of a video, and stores it in the + respective XMP container. + */ + void aspectRatio(); + + private: + //! @name NOT Implemented + //@{ + //! Copy constructor + QuickTimeVideo(const QuickTimeVideo& rhs); + //! Assignment operator + QuickTimeVideo& operator=(const QuickTimeVideo& rhs); + //@} + + 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_; + +}; // 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. - /*! - @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. - */ - Image::UniquePtr newQTimeInstance(BasicIo::UniquePtr io, bool create); +// 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. + */ +Image::UniquePtr newQTimeInstance(BasicIo::UniquePtr io, bool create); - //! Check if the file iIo is a Quick Time Video. - bool isQTimeType(BasicIo& iIo, bool advance); +//! Check if the file iIo is a Quick Time Video. +bool isQTimeType(BasicIo& iIo, bool advance); -} // namespace Exiv2 +} // namespace Exiv2 -#endif // QUICKTIMEVIDEO_HPP +#endif // QUICKTIMEVIDEO_HPP diff --git a/src/image.cpp b/src/image.cpp index f83f67a3..91cb6f41 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -29,6 +29,7 @@ #include "orfimage.hpp" #include "pgfimage.hpp" #include "psdimage.hpp" +#include "quicktimevideo.hpp" #include "rafimage.hpp" #include "rw2image.hpp" #include "tags_int.hpp" @@ -36,7 +37,6 @@ #include "tiffimage.hpp" #include "webpimage.hpp" #include "xmpsidecar.hpp" -#include "quicktimevideo.hpp" // + standard includes #include @@ -99,7 +99,7 @@ constexpr auto registry = std::array{ Registry{ImageType::jp2, newJp2Instance, isJp2Type, amReadWrite, amReadWrite, amReadWrite, amNone}, // needs to be before bmff because some ftyp files are handled as qt and // the rest should fall through to bmff - Registry{ ImageType::qtime,newQTimeInstance,isQTimeType,amRead,amNone, amRead, amNone}, + Registry{ImageType::qtime, newQTimeInstance, isQTimeType, amRead, amNone, amRead, amNone}, #ifdef EXV_ENABLE_BMFF Registry{ImageType::bmff, newBmffInstance, isBmffType, amRead, amRead, amRead, amNone}, #endif // EXV_ENABLE_BMFF diff --git a/src/quicktimevideo.cpp b/src/quicktimevideo.cpp index 5c4cd482..36ca3814 100644 --- a/src/quicktimevideo.cpp +++ b/src/quicktimevideo.cpp @@ -21,1634 +21,1601 @@ // included header files #include "config.h" +#include "basicio.hpp" #include "error.hpp" +#include "futils.hpp" +#include "quicktimevideo.hpp" #include "tags.hpp" #include "tags_int.hpp" -#include "quicktimevideo.hpp" -#include "futils.hpp" -#include "basicio.hpp" // + standard includes +#include #include #include -#include #include // ***************************************************************************** // class member definitions 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" } - }; - - extern const TagVocabulary handlerClassTags[] = { - { "dhlr", "Data Handler" }, - { "mhlr", "Media Handler" } - }; - - 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" } - }; - - 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" } - }; - - 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.data()[i]) != tolower(str[i])) - return false; - return true; - } - - /*! - @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", - }; - - for(int i = 0 ; i < 13 ; ++i) - if(equalsQTimeTag(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", - }; - - for(int i = 0 ; i < 8 ; ++i) - if(equalsQTimeTag(buf, ignoreList[i])) - return true; - - return false; - } - - /*! - @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--) +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"}}; + +extern const TagVocabulary handlerClassTags[] = {{"dhlr", "Data Handler"}, {"mhlr", "Media Handler"}}; + +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"}}; + +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"}}; + +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.data()[i]) != tolower(str[i])) + return false; + return true; +} + +/*! + @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", + }; + + for (int i = 0; i < 13; ++i) + if (equalsQTimeTag(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", + }; + + for (int i = 0; i < 8; ++i) + if (equalsQTimeTag(buf, ignoreList[i])) + return true; + + return false; +} + +/*! + @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.data()[i]*(pow(static_cast(256), n-i-1))); + temp = temp + static_cast(buf.data()[i] * (pow(static_cast(256), n - i - 1))); #else - temp = temp + buf.data()[i]*(pow((float)256,n-i-1)); + temp = temp + buf.data()[i] * (pow((float)256, n - i - 1)); #endif - return temp; - } + return temp; +} - /*! - @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 + @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--) #if _MSC_VER - temp = temp + static_cast(buf.data()[i]*(pow(static_cast(256), n-i-1))); + temp = temp + static_cast(buf.data()[i] * (pow(static_cast(256), n - i - 1))); #else - temp = temp + buf.data()[i]*(pow((float)256,n-i-1)); + temp = temp + buf.data()[i] * (pow((float)256, n - i - 1)); #endif - return temp; - } + return temp; +} -}} // namespace Internal, Exiv2 +} // namespace Internal +} // namespace Exiv2 namespace Exiv2 { - using namespace Exiv2::Internal; +using namespace Exiv2::Internal; - QuickTimeVideo::QuickTimeVideo(BasicIo::UniquePtr io) - : Image(ImageType::qtime, mdNone, std::move(io)) - , timeScale_(1) - { - } // QuickTimeVideo::QuickTimeVideo +QuickTimeVideo::QuickTimeVideo(BasicIo::UniquePtr io) : Image(ImageType::qtime, mdNone, std::move(io)), timeScale_(1) { +} // QuickTimeVideo::QuickTimeVideo - std::string QuickTimeVideo::mimeType() const - { - return "video/quicktime"; - } +std::string QuickTimeVideo::mimeType() const { + return "video/quicktime"; +} - void QuickTimeVideo::writeMetadata() - { - } +void QuickTimeVideo::writeMetadata() { +} +void QuickTimeVideo::readMetadata() { + if (io_->open() != 0) + throw Error(ErrorCode::kerDataSourceOpenFailed, io_->path(), strError()); - void QuickTimeVideo::readMetadata() - { - if (io_->open() != 0) throw Error(ErrorCode::kerDataSourceOpenFailed, io_->path(), strError()); + // Ensure that this is the correct image type + if (!isQTimeType(*io_, false)) { + if (io_->error() || io_->eof()) + throw Error(ErrorCode::kerFailedToReadImageData); + throw Error(ErrorCode::kerNotAnImage, "QuickTime"); + } - // Ensure that this is the correct image type - if (!isQTimeType(*io_, false)) { - if (io_->error() || io_->eof()) throw Error(ErrorCode::kerFailedToReadImageData); - throw Error(ErrorCode::kerNotAnImage, "QuickTime"); - } + IoCloser closer(*io_); + clearMetadata(); + continueTraversing_ = true; + height_ = width_ = 1; - IoCloser closer(*io_); - clearMetadata(); - continueTraversing_ = true; - height_ = width_ = 1; + xmpData_["Xmp.video.FileSize"] = (double)io_->size() / (double)1048576; + xmpData_["Xmp.video.MimeType"] = mimeType(); - xmpData_["Xmp.video.FileSize"] = (double)io_->size()/(double)1048576; - xmpData_["Xmp.video.MimeType"] = mimeType(); + while (continueTraversing_) + decodeBlock(); - while (continueTraversing_) decodeBlock(); + aspectRatio(); +} // QuickTimeVideo::readMetadata - aspectRatio(); - } // QuickTimeVideo::readMetadata +void QuickTimeVideo::decodeBlock() { + const long bufMinSize = 4; + DataBuf buf(bufMinSize + 1); + uint64_t size = 0; + buf.data()[4] = '\0'; - void QuickTimeVideo::decodeBlock() - { - const long bufMinSize = 4; - DataBuf buf(bufMinSize+1); - uint64_t size = 0; - buf.data()[4] = '\0' ; + io_->read(buf.data(), 4); + if (io_->eof()) { + continueTraversing_ = false; + return; + } + size = Exiv2::getULong(buf.data(), bigEndian); - io_->read(buf.data(), 4); - if(io_->eof()) { - continueTraversing_ = false; - return; - } + io_->read(buf.data(), 4); - size = Exiv2::getULong(buf.data(), bigEndian); + if (size == 1) { + // The box size is encoded as a uint64_t, so we need to read another 8 bytes. + DataBuf data(8); + io_->read(data.data(), data.size()); + size = data.read_uint64(0, bigEndian); + } + if (size < 8) + return; - io_->read(buf.data(), 4); + // std::cerr<<"\nTag=>"<"<read(data.data(), data.size()); - size = data.read_uint64(0, bigEndian); - } - if(size < 8) - return; +void QuickTimeVideo::tagDecoder(Exiv2::DataBuf& buf, uint64_t size) { + if (ignoreList(buf)) + discard(size); - // std::cerr<<"\nTag=>"<"<read(buf.data(), size); + if (currentStream_ == Video) + xmpData_["Xmp.video.URL"] = Exiv2::toString(buf.data()); + else if (currentStream_ == Audio) + xmpData_["Xmp.audio.URL"] = Exiv2::toString(buf.data()); + } + + else if (equalsQTimeTag(buf, "urn ")) { + io_->read(buf.data(), size); + if (currentStream_ == Video) + xmpData_["Xmp.video.URN"] = Exiv2::toString(buf.data()); + else if (currentStream_ == Audio) + xmpData_["Xmp.audio.URN"] = Exiv2::toString(buf.data()); + } + + else if (equalsQTimeTag(buf, "dcom")) { + io_->read(buf.data(), size); + xmpData_["Xmp.video.Compressor"] = Exiv2::toString(buf.data()); + } + + else if (equalsQTimeTag(buf, "smhd")) { + io_->read(buf.data(), 4); + io_->read(buf.data(), 4); + xmpData_["Xmp.audio.Balance"] = returnBufValue(buf, 2); + } + + else { + discard(size); + } +} // QuickTimeVideo::tagDecoder + +void QuickTimeVideo::discard(uint64_t size) { + uint64_t cur_pos = io_->tell(); + io_->seek(cur_pos + size, BasicIo::beg); +} // QuickTimeVideo::discard + +void QuickTimeVideo::previewTagDecoder(uint64_t size) { + DataBuf buf(4); + uint64_t cur_pos = io_->tell(); + io_->read(buf.data(), 4); + xmpData_["Xmp.video.PreviewDate"] = getULong(buf.data(), bigEndian); + io_->read(buf.data(), 2); + xmpData_["Xmp.video.PreviewVersion"] = getShort(buf.data(), bigEndian); + + io_->read(buf.data(), 4); + if (equalsQTimeTag(buf, "PICT")) + xmpData_["Xmp.video.PreviewAtomType"] = "QuickDraw Picture"; + else + xmpData_["Xmp.video.PreviewAtomType"] = Exiv2::toString(buf.data()); + + io_->seek(cur_pos + size, BasicIo::beg); +} // QuickTimeVideo::previewTagDecoder + +void QuickTimeVideo::keysTagDecoder(uint64_t size) { + DataBuf buf(4); + uint64_t cur_pos = io_->tell(); + io_->read(buf.data(), 4); + xmpData_["Xmp.video.PreviewDate"] = getULong(buf.data(), bigEndian); + io_->read(buf.data(), 2); + xmpData_["Xmp.video.PreviewVersion"] = getShort(buf.data(), bigEndian); + + io_->read(buf.data(), 4); + if (equalsQTimeTag(buf, "PICT")) + xmpData_["Xmp.video.PreviewAtomType"] = "QuickDraw Picture"; + else + xmpData_["Xmp.video.PreviewAtomType"] = Exiv2::toString(buf.data()); + + io_->seek(cur_pos + size, BasicIo::beg); +} // QuickTimeVideo::keysTagDecoder + +void QuickTimeVideo::trackApertureTagDecoder(uint64_t size) { + DataBuf buf(4), buf2(2); + uint64_t cur_pos = io_->tell(); + byte n = 3; + + while (n--) { + io_->seek(static_cast(4), BasicIo::cur); + io_->read(buf.data(), 4); + + if (equalsQTimeTag(buf, "clef")) { + io_->seek(static_cast(4), BasicIo::cur); + io_->read(buf.data(), 2); + io_->read(buf2.data(), 2); + xmpData_["Xmp.video.CleanApertureWidth"] = + Exiv2::toString(getUShort(buf.data(), bigEndian)) + "." + Exiv2::toString(getUShort(buf2.data(), bigEndian)); + io_->read(buf.data(), 2); + io_->read(buf2.data(), 2); + xmpData_["Xmp.video.CleanApertureHeight"] = + Exiv2::toString(getUShort(buf.data(), bigEndian)) + "." + Exiv2::toString(getUShort(buf2.data(), bigEndian)); + } - else if (equalsQTimeTag(buf, "stsd")) - sampleDesc(size); + else if (equalsQTimeTag(buf, "prof")) { + io_->seek(static_cast(4), BasicIo::cur); + io_->read(buf.data(), 2); + io_->read(buf2.data(), 2); + xmpData_["Xmp.video.ProductionApertureWidth"] = + Exiv2::toString(getUShort(buf.data(), bigEndian)) + "." + Exiv2::toString(getUShort(buf2.data(), bigEndian)); + io_->read(buf.data(), 2); + io_->read(buf2.data(), 2); + xmpData_["Xmp.video.ProductionApertureHeight"] = + Exiv2::toString(getUShort(buf.data(), bigEndian)) + "." + Exiv2::toString(getUShort(buf2.data(), bigEndian)); + } - else if (equalsQTimeTag(buf, "stts")) - timeToSampleDecoder(); + else if (equalsQTimeTag(buf, "enof")) { + io_->seek(static_cast(4), BasicIo::cur); + io_->read(buf.data(), 2); + io_->read(buf2.data(), 2); + xmpData_["Xmp.video.EncodedPixelsWidth"] = + Exiv2::toString(getUShort(buf.data(), bigEndian)) + "." + Exiv2::toString(getUShort(buf2.data(), bigEndian)); + io_->read(buf.data(), 2); + io_->read(buf2.data(), 2); + xmpData_["Xmp.video.EncodedPixelsHeight"] = + Exiv2::toString(getUShort(buf.data(), bigEndian)) + "." + Exiv2::toString(getUShort(buf2.data(), bigEndian)); + } + } + io_->seek(static_cast(cur_pos + size), BasicIo::beg); +} // QuickTimeVideo::trackApertureTagDecoder + +void QuickTimeVideo::CameraTagsDecoder(uint64_t size_external) { + uint64_t cur_pos = io_->tell(); + DataBuf buf(50), buf2(4); + const TagDetails* td; + + io_->read(buf.data(), 4); + if (equalsQTimeTag(buf, "NIKO")) { + io_->seek(cur_pos, BasicIo::beg); + + io_->read(buf.data(), 24); + xmpData_["Xmp.video.Make"] = Exiv2::toString(buf.data()); + io_->read(buf.data(), 14); + xmpData_["Xmp.video.Model"] = Exiv2::toString(buf.data()); + io_->read(buf.data(), 4); + xmpData_["Xmp.video.ExposureTime"] = "1/" + Exiv2::toString(ceil(getULong(buf.data(), littleEndian) / (double)10)); + io_->read(buf.data(), 4); + io_->read(buf2.data(), 4); + xmpData_["Xmp.video.FNumber"] = getULong(buf.data(), littleEndian) / (double)getULong(buf2.data(), littleEndian); + io_->read(buf.data(), 4); + io_->read(buf2.data(), 4); + xmpData_["Xmp.video.ExposureCompensation"] = + getULong(buf.data(), littleEndian) / (double)getULong(buf2.data(), littleEndian); + io_->read(buf.data(), 10); + io_->read(buf.data(), 4); + td = find(whiteBalance, getULong(buf.data(), littleEndian)); + if (td) + xmpData_["Xmp.video.WhiteBalance"] = exvGettext(td->label_); + io_->read(buf.data(), 4); + io_->read(buf2.data(), 4); + xmpData_["Xmp.video.FocalLength"] = + getULong(buf.data(), littleEndian) / (double)getULong(buf2.data(), littleEndian); + io_->seek(static_cast(95), BasicIo::cur); + io_->read(buf.data(), 48); + xmpData_["Xmp.video.Software"] = Exiv2::toString(buf.data()); + io_->read(buf.data(), 4); + xmpData_["Xmp.video.ISO"] = getULong(buf.data(), littleEndian); + } + + io_->seek(cur_pos + size_external, BasicIo::beg); +} // QuickTimeVideo::CameraTagsDecoder + +void QuickTimeVideo::userDataDecoder(uint64_t 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.data(), 0x0, buf.size()); + + while ((size_internal / 4 != 0) && (size_internal > 0)) { + buf.data()[4] = '\0'; + io_->read(buf.data(), 4); + size = Exiv2::getULong(buf.data(), bigEndian); + if (size > size_internal) + break; + size_internal -= size; + io_->read(buf.data(), 4); + + if (buf.data()[0] == 169) + buf.data()[0] = ' '; + td = find(userDatatags, Exiv2::toString(buf.data())); + + tv = find(userDataReferencetags, Exiv2::toString(buf.data())); + + 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.data(), size - 8); + xmpData_[exvGettext(tv->label_)] = Exiv2::toString(buf.data()); + } - else if (equalsQTimeTag(buf, "pnot")) - previewTagDecoder(size); + else if (equalsQTimeTag(buf, "CMbo") || equalsQTimeTag(buf, "Cmbo")) { + io_->read(buf.data(), 2); + buf.data()[2] = '\0'; + tv_internal = find(cameraByteOrderTags, Exiv2::toString(buf.data())); - else if (equalsQTimeTag(buf, "tapt")) - trackApertureTagDecoder(size); + if (tv_internal) + xmpData_[exvGettext(tv->label_)] = exvGettext(tv_internal->label_); + else + xmpData_[exvGettext(tv->label_)] = Exiv2::toString(buf.data()); + } - else if (equalsQTimeTag(buf, "keys")) - keysTagDecoder(size); + else if (tv) { + io_->read(buf.data(), 4); + io_->read(buf.data(), size - 12); + xmpData_[exvGettext(tv->label_)] = Exiv2::toString(buf.data()); + } - else if (equalsQTimeTag(buf, "url ")) { - io_->read(buf.data(), size); - if (currentStream_ == Video) - xmpData_["Xmp.video.URL"] = Exiv2::toString(buf.data()); - else if (currentStream_ == Audio) - xmpData_["Xmp.audio.URL"] = Exiv2::toString(buf.data()); - } + else if (td) + tagDecoder(buf, size - 8); + } + + io_->seek(cur_pos + size_external, BasicIo::beg); +} // QuickTimeVideo::userDataDecoder + +void QuickTimeVideo::NikonTagsDecoder(uint64_t 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; + + for (int i = 0; i < 100; i++) { + io_->read(buf.data(), 4); + TagID = Exiv2::getULong(buf.data(), bigEndian); + td = find(NikonNCTGTags, TagID); + + io_->read(buf.data(), 2); + dataType = Exiv2::getUShort(buf.data(), bigEndian); + + std::memset(buf.data(), 0x0, buf.size()); + io_->read(buf.data(), 2); + + if (TagID == 0x2000023) { + uint64_t local_pos = io_->tell(); + dataLength = Exiv2::getUShort(buf.data(), bigEndian); + std::memset(buf.data(), 0x0, buf.size()); + + io_->read(buf.data(), 4); + xmpData_["Xmp.video.PictureControlVersion"] = Exiv2::toString(buf.data()); + io_->read(buf.data(), 20); + xmpData_["Xmp.video.PictureControlName"] = Exiv2::toString(buf.data()); + io_->read(buf.data(), 20); + xmpData_["Xmp.video.PictureControlBase"] = Exiv2::toString(buf.data()); + io_->read(buf.data(), 4); + std::memset(buf.data(), 0x0, buf.size()); + + io_->read(buf.data(), 1); + td2 = find(PictureControlAdjust, (int)buf.data()[0] & 7); + if (td2) + xmpData_["Xmp.video.PictureControlAdjust"] = exvGettext(td2->label_); + else + xmpData_["Xmp.video.PictureControlAdjust"] = (int)buf.data()[0] & 7; + + io_->read(buf.data(), 1); + td2 = find(NormalSoftHard, (int)buf.data()[0] & 7); + if (td2) + xmpData_["Xmp.video.PictureControlQuickAdjust"] = exvGettext(td2->label_); + + io_->read(buf.data(), 1); + td2 = find(NormalSoftHard, (int)buf.data()[0] & 7); + if (td2) + xmpData_["Xmp.video.Sharpness"] = exvGettext(td2->label_); + else + xmpData_["Xmp.video.Sharpness"] = (int)buf.data()[0] & 7; + + io_->read(buf.data(), 1); + td2 = find(NormalSoftHard, (int)buf.data()[0] & 7); + if (td2) + xmpData_["Xmp.video.Contrast"] = exvGettext(td2->label_); + else + xmpData_["Xmp.video.Contrast"] = (int)buf.data()[0] & 7; + + io_->read(buf.data(), 1); + td2 = find(NormalSoftHard, (int)buf.data()[0] & 7); + if (td2) + xmpData_["Xmp.video.Brightness"] = exvGettext(td2->label_); + else + xmpData_["Xmp.video.Brightness"] = (int)buf.data()[0] & 7; + + io_->read(buf.data(), 1); + td2 = find(Saturation, (int)buf.data()[0] & 7); + if (td2) + xmpData_["Xmp.video.Saturation"] = exvGettext(td2->label_); + else + xmpData_["Xmp.video.Saturation"] = (int)buf.data()[0] & 7; + + io_->read(buf.data(), 1); + xmpData_["Xmp.video.HueAdjustment"] = (int)buf.data()[0] & 7; + + io_->read(buf.data(), 1); + td2 = find(FilterEffect, (int)buf.data()[0]); + if (td2) + xmpData_["Xmp.video.FilterEffect"] = exvGettext(td2->label_); + else + xmpData_["Xmp.video.FilterEffect"] = (int)buf.data()[0]; + + io_->read(buf.data(), 1); + td2 = find(ToningEffect, (int)buf.data()[0]); + if (td2) + xmpData_["Xmp.video.ToningEffect"] = exvGettext(td2->label_); + else + xmpData_["Xmp.video.ToningEffect"] = (int)buf.data()[0]; + + io_->read(buf.data(), 1); + xmpData_["Xmp.video.ToningSaturation"] = (int)buf.data()[0]; + + io_->seek(local_pos + dataLength, BasicIo::beg); + } - else if (equalsQTimeTag(buf, "urn ")) { - io_->read(buf.data(), size); - if (currentStream_ == Video) - xmpData_["Xmp.video.URN"] = Exiv2::toString(buf.data()); - else if (currentStream_ == Audio) - xmpData_["Xmp.audio.URN"] = Exiv2::toString(buf.data()); - } + else if (TagID == 0x2000024) { + uint64_t local_pos = io_->tell(); + dataLength = Exiv2::getUShort(buf.data(), bigEndian); + std::memset(buf.data(), 0x0, buf.size()); - else if (equalsQTimeTag(buf, "dcom")) { - io_->read(buf.data(), size); - xmpData_["Xmp.video.Compressor"] = Exiv2::toString(buf.data()); - } + io_->read(buf.data(), 2); + xmpData_["Xmp.video.TimeZone"] = Exiv2::getShort(buf.data(), bigEndian); + io_->read(buf.data(), 1); + td2 = find(YesNo, (int)buf.data()[0]); + if (td2) + xmpData_["Xmp.video.DayLightSavings"] = exvGettext(td2->label_); - else if (equalsQTimeTag(buf, "smhd")) { - io_->read(buf.data(), 4); - io_->read(buf.data(), 4); - xmpData_["Xmp.audio.Balance"] = returnBufValue(buf, 2); - } + io_->read(buf.data(), 1); + td2 = find(DateDisplayFormat, (int)buf.data()[0]); + if (td2) + xmpData_["Xmp.video.DateDisplayFormat"] = exvGettext(td2->label_); - 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(); - io_->read(buf.data(), 4); - xmpData_["Xmp.video.PreviewDate"] = getULong(buf.data(), bigEndian); - io_->read(buf.data(), 2); - xmpData_["Xmp.video.PreviewVersion"] = getShort(buf.data(), bigEndian); - - io_->read(buf.data(), 4); - if(equalsQTimeTag(buf, "PICT")) - xmpData_["Xmp.video.PreviewAtomType"] = "QuickDraw Picture"; - else - xmpData_["Xmp.video.PreviewAtomType"] = Exiv2::toString(buf.data()); - - io_->seek(cur_pos + size, BasicIo::beg); - } // QuickTimeVideo::previewTagDecoder - - void QuickTimeVideo::keysTagDecoder(unsigned long size) - { - DataBuf buf(4); - uint64_t cur_pos = io_->tell(); - io_->read(buf.data(), 4); - xmpData_["Xmp.video.PreviewDate"] = getULong(buf.data(), bigEndian); - io_->read(buf.data(), 2); - xmpData_["Xmp.video.PreviewVersion"] = getShort(buf.data(), bigEndian); - - io_->read(buf.data(), 4); - if(equalsQTimeTag(buf, "PICT")) - xmpData_["Xmp.video.PreviewAtomType"] = "QuickDraw Picture"; - else - xmpData_["Xmp.video.PreviewAtomType"] = Exiv2::toString(buf.data()); - - io_->seek(cur_pos + size, BasicIo::beg); - } // QuickTimeVideo::keysTagDecoder - - void QuickTimeVideo::trackApertureTagDecoder(unsigned long size) - { - DataBuf buf(4), buf2(2); - uint64_t cur_pos = io_->tell(); - byte n = 3; - - while(n--) { - io_->seek(static_cast(4), BasicIo::cur); io_->read(buf.data(), 4); - - if(equalsQTimeTag(buf, "clef")) { - io_->seek(static_cast(4), BasicIo::cur); - io_->read(buf.data(), 2); io_->read(buf2.data(), 2); - xmpData_["Xmp.video.CleanApertureWidth"] = Exiv2::toString(getUShort(buf.data(), bigEndian)) - + "." + Exiv2::toString(getUShort(buf2.data(), bigEndian)); - io_->read(buf.data(), 2); io_->read(buf2.data(), 2); - xmpData_["Xmp.video.CleanApertureHeight"] = Exiv2::toString(getUShort(buf.data(), bigEndian)) - + "." + Exiv2::toString(getUShort(buf2.data(), bigEndian)); - } - - else if(equalsQTimeTag(buf, "prof")) { - io_->seek(static_cast(4), BasicIo::cur); - io_->read(buf.data(), 2); io_->read(buf2.data(), 2); - xmpData_["Xmp.video.ProductionApertureWidth"] = Exiv2::toString(getUShort(buf.data(), bigEndian)) - + "." + Exiv2::toString(getUShort(buf2.data(), bigEndian)); - io_->read(buf.data(), 2); io_->read(buf2.data(), 2); - xmpData_["Xmp.video.ProductionApertureHeight"] = Exiv2::toString(getUShort(buf.data(), bigEndian)) - + "." + Exiv2::toString(getUShort(buf2.data(), bigEndian)); - } - - else if(equalsQTimeTag(buf, "enof")) { - io_->seek(static_cast(4), BasicIo::cur); - io_->read(buf.data(), 2); io_->read(buf2.data(), 2); - xmpData_["Xmp.video.EncodedPixelsWidth"] = Exiv2::toString(getUShort(buf.data(), bigEndian)) - + "." + Exiv2::toString(getUShort(buf2.data(), bigEndian)); - io_->read(buf.data(), 2); io_->read(buf2.data(), 2); - xmpData_["Xmp.video.EncodedPixelsHeight"] = Exiv2::toString(getUShort(buf.data(), bigEndian)) - + "." + Exiv2::toString(getUShort(buf2.data(), bigEndian)); - } - } - io_->seek(static_cast(cur_pos + size), BasicIo::beg); - } // QuickTimeVideo::trackApertureTagDecoder - - void QuickTimeVideo::CameraTagsDecoder(unsigned long size_external) - { - uint64_t cur_pos = io_->tell(); - DataBuf buf(50), buf2(4); - const TagDetails* td; - - io_->read(buf.data(), 4); - if(equalsQTimeTag(buf, "NIKO")) { - io_->seek(cur_pos, BasicIo::beg); - - io_->read(buf.data(), 24); - xmpData_["Xmp.video.Make"] = Exiv2::toString(buf.data()); - io_->read(buf.data(), 14); - xmpData_["Xmp.video.Model"] = Exiv2::toString(buf.data()); - io_->read(buf.data(), 4); - xmpData_["Xmp.video.ExposureTime"] = "1/" + Exiv2::toString( ceil( getULong(buf.data(), littleEndian) / (double)10)); - io_->read(buf.data(), 4); io_->read(buf2.data(), 4); - xmpData_["Xmp.video.FNumber"] = getULong(buf.data(), littleEndian) / (double)getULong(buf2.data(), littleEndian) ; - io_->read(buf.data(), 4); io_->read(buf2.data(), 4); - xmpData_["Xmp.video.ExposureCompensation"] = getULong(buf.data(), littleEndian) / (double)getULong(buf2.data(), littleEndian) ; - io_->read(buf.data(), 10); io_->read(buf.data(), 4); - td = find(whiteBalance, getULong(buf.data(), littleEndian)); - if (td) - xmpData_["Xmp.video.WhiteBalance"] = exvGettext(td->label_); - io_->read(buf.data(), 4); io_->read(buf2.data(), 4); - xmpData_["Xmp.video.FocalLength"] = getULong(buf.data(), littleEndian) / (double)getULong(buf2.data(), littleEndian) ; - io_->seek(static_cast(95), BasicIo::cur); - io_->read(buf.data(), 48); - xmpData_["Xmp.video.Software"] = Exiv2::toString(buf.data()); - io_->read(buf.data(), 4); - xmpData_["Xmp.video.ISO"] = getULong(buf.data(), littleEndian); - } + io_->seek(local_pos + dataLength, BasicIo::beg); + } - 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.data(), 0x0, buf.size()); - - while((size_internal/4 != 0) && (size_internal > 0)) { - - buf.data()[4] = '\0' ; - io_->read(buf.data(), 4); - size = Exiv2::getULong(buf.data(), bigEndian); - if(size > size_internal) - break; - size_internal -= size; - io_->read(buf.data(), 4); - - if(buf.data()[0] == 169) - buf.data()[0] = ' '; - td = find(userDatatags, Exiv2::toString( buf.data())); - - tv = find(userDataReferencetags, Exiv2::toString( buf.data())); - - 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.data(), size - 8); - xmpData_[exvGettext(tv->label_)] = Exiv2::toString(buf.data()); - } - - else if(equalsQTimeTag(buf, "CMbo") || equalsQTimeTag(buf, "Cmbo")) { - io_->read(buf.data(), 2); - buf.data()[2] = '\0' ; - tv_internal = find(cameraByteOrderTags, Exiv2::toString( buf.data())); - - if (tv_internal) - xmpData_[exvGettext(tv->label_)] = exvGettext(tv_internal->label_); - else - xmpData_[exvGettext(tv->label_)] = Exiv2::toString(buf.data()); - } - - else if(tv) { - io_->read(buf.data(), 4); - io_->read(buf.data(), size-12); - xmpData_[exvGettext(tv->label_)] = Exiv2::toString(buf.data()); - } - - else if(td) - tagDecoder(buf,size-8); - } + else if (dataType == 2 || dataType == 7) { + dataLength = Exiv2::getUShort(buf.data(), bigEndian); + std::memset(buf.data(), 0x0, buf.size()); - io_->seek(cur_pos + size_external, BasicIo::beg); - } // QuickTimeVideo::userDataDecoder - - 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; - - for(int i = 0 ; i < 100 ; i++) { - io_->read(buf.data(), 4); - TagID = Exiv2::getULong(buf.data(), bigEndian); - td = find(NikonNCTGTags, TagID); - - io_->read(buf.data(), 2); - dataType = Exiv2::getUShort(buf.data(), bigEndian); - - std::memset(buf.data(), 0x0, buf.size()); - io_->read(buf.data(), 2); - - if(TagID == 0x2000023) { - uint64_t local_pos = io_->tell(); - dataLength = Exiv2::getUShort(buf.data(), bigEndian); - std::memset(buf.data(), 0x0, buf.size()); - - io_->read(buf.data(), 4); xmpData_["Xmp.video.PictureControlVersion"] = Exiv2::toString(buf.data()); - io_->read(buf.data(), 20); xmpData_["Xmp.video.PictureControlName"] = Exiv2::toString(buf.data()); - io_->read(buf.data(), 20); xmpData_["Xmp.video.PictureControlBase"] = Exiv2::toString(buf.data()); - io_->read(buf.data(), 4); std::memset(buf.data(), 0x0, buf.size()); - - io_->read(buf.data(), 1); - td2 = find(PictureControlAdjust, (int)buf.data()[0] & 7 ); - if(td2) - xmpData_["Xmp.video.PictureControlAdjust"] = exvGettext(td2->label_); - else - xmpData_["Xmp.video.PictureControlAdjust"] = (int)buf.data()[0] & 7 ; - - io_->read(buf.data(), 1); - td2 = find(NormalSoftHard, (int)buf.data()[0] & 7 ); - if(td2) - xmpData_["Xmp.video.PictureControlQuickAdjust"] = exvGettext(td2->label_); - - io_->read(buf.data(), 1); - td2 = find(NormalSoftHard, (int)buf.data()[0] & 7 ); - if(td2) - xmpData_["Xmp.video.Sharpness"] = exvGettext(td2->label_); - else - xmpData_["Xmp.video.Sharpness"] = (int)buf.data()[0] & 7; - - io_->read(buf.data(), 1); - td2 = find(NormalSoftHard, (int)buf.data()[0] & 7 ); - if(td2) - xmpData_["Xmp.video.Contrast"] = exvGettext(td2->label_); - else - xmpData_["Xmp.video.Contrast"] = (int)buf.data()[0] & 7; - - io_->read(buf.data(), 1); - td2 = find(NormalSoftHard, (int)buf.data()[0] & 7 ); - if(td2) - xmpData_["Xmp.video.Brightness"] = exvGettext(td2->label_); - else - xmpData_["Xmp.video.Brightness"] = (int)buf.data()[0] & 7; - - io_->read(buf.data(), 1); - td2 = find(Saturation, (int)buf.data()[0] & 7 ); - if(td2) - xmpData_["Xmp.video.Saturation"] = exvGettext(td2->label_); - else - xmpData_["Xmp.video.Saturation"] = (int)buf.data()[0] & 7; - - io_->read(buf.data(), 1); - xmpData_["Xmp.video.HueAdjustment"] = (int)buf.data()[0] & 7; - - io_->read(buf.data(), 1); - td2 = find(FilterEffect, (int)buf.data()[0]); - if(td2) - xmpData_["Xmp.video.FilterEffect"] = exvGettext(td2->label_); - else - xmpData_["Xmp.video.FilterEffect"] = (int)buf.data()[0]; - - io_->read(buf.data(), 1); - td2 = find(ToningEffect, (int)buf.data()[0]); - if(td2) - xmpData_["Xmp.video.ToningEffect"] = exvGettext(td2->label_); - else - xmpData_["Xmp.video.ToningEffect"] = (int)buf.data()[0]; - - io_->read(buf.data(), 1); xmpData_["Xmp.video.ToningSaturation"] = (int)buf.data()[0]; - - io_->seek(local_pos + dataLength, BasicIo::beg); - } - - else if(TagID == 0x2000024) { - uint64_t local_pos = io_->tell(); - dataLength = Exiv2::getUShort(buf.data(), bigEndian); - std::memset(buf.data(), 0x0, buf.size()); - - io_->read(buf.data(), 2); xmpData_["Xmp.video.TimeZone"] = Exiv2::getShort(buf.data(), bigEndian); - io_->read(buf.data(), 1); - td2 = find(YesNo, (int)buf.data()[0]); - if(td2) - xmpData_["Xmp.video.DayLightSavings"] = exvGettext(td2->label_); - - io_->read(buf.data(), 1); - td2 = find(DateDisplayFormat, (int)buf.data()[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.data(), bigEndian); - std::memset(buf.data(), 0x0, buf.size()); - - // Sanity check with an "unreasonably" large number - if (dataLength > 200) { + // 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"; + 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.data(), dataLength); - } - - if(td) { - xmpData_[exvGettext(td->label_)] = Exiv2::toString(buf.data()); - } - } - else if(dataType == 4) { - dataLength = Exiv2::getUShort(buf.data(), bigEndian) * 4; - std::memset(buf.data(), 0x0, buf.size()); - io_->read(buf.data(), 4); - if(td) - xmpData_[exvGettext(td->label_)] = Exiv2::toString(Exiv2::getULong( buf.data(), bigEndian)); - - // Sanity check with an "unreasonably" large number - if (dataLength > 200 || dataLength < 4) { + io_->seek(io_->tell() + dataLength, BasicIo::beg); + } else { + io_->read(buf.data(), dataLength); + } + + if (td) { + xmpData_[exvGettext(td->label_)] = Exiv2::toString(buf.data()); + } + } else if (dataType == 4) { + dataLength = Exiv2::getUShort(buf.data(), bigEndian) * 4; + std::memset(buf.data(), 0x0, buf.size()); + io_->read(buf.data(), 4); + if (td) + xmpData_[exvGettext(td->label_)] = Exiv2::toString(Exiv2::getULong(buf.data(), 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"; + 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.data(), dataLength - 4); - } - else if(dataType == 3) { - dataLength = Exiv2::getUShort(buf.data(), bigEndian) * 2; - std::memset(buf.data(), 0x0, buf.size()); - io_->read(buf.data(), 2); - if(td) - xmpData_[exvGettext(td->label_)] = Exiv2::toString(Exiv2::getUShort( buf.data(), bigEndian)); - - // Sanity check with an "unreasonably" large number - if (dataLength > 200 || dataLength < 2) { + io_->seek(io_->tell() + dataLength - 4, BasicIo::beg); + } else + io_->read(buf.data(), dataLength - 4); + } else if (dataType == 3) { + dataLength = Exiv2::getUShort(buf.data(), bigEndian) * 2; + std::memset(buf.data(), 0x0, buf.size()); + io_->read(buf.data(), 2); + if (td) + xmpData_[exvGettext(td->label_)] = Exiv2::toString(Exiv2::getUShort(buf.data(), 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"; + 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.data(), dataLength - 2); - } - else if(dataType == 5) { - dataLength = Exiv2::getUShort(buf.data(), bigEndian) * 8; - std::memset(buf.data(), 0x0, buf.size()); - io_->read(buf.data(), 4); - io_->read(buf2.data(), 4); - if(td) - xmpData_[exvGettext(td->label_)] = Exiv2::toString((double)Exiv2::getULong( buf.data(), bigEndian) / (double)Exiv2::getULong( buf2.data(), bigEndian)); - - // Sanity check with an "unreasonably" large number - if (dataLength > 200 || dataLength < 8) { + io_->seek(io_->tell() + dataLength - 2, BasicIo::beg); + } else + io_->read(buf.data(), dataLength - 2); + } else if (dataType == 5) { + dataLength = Exiv2::getUShort(buf.data(), bigEndian) * 8; + std::memset(buf.data(), 0x0, buf.size()); + io_->read(buf.data(), 4); + io_->read(buf2.data(), 4); + if (td) + xmpData_[exvGettext(td->label_)] = Exiv2::toString((double)Exiv2::getULong(buf.data(), bigEndian) / + (double)Exiv2::getULong(buf2.data(), 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"; + 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.data(), dataLength - 8); - } - else if(dataType == 8) { - dataLength = Exiv2::getUShort(buf.data(), bigEndian) * 2; - std::memset(buf.data(), 0x0, buf.size()); - io_->read(buf.data(), 2); - io_->read(buf2.data(), 2); - if(td) - xmpData_[exvGettext(td->label_)] = Exiv2::toString(Exiv2::getUShort( buf.data(), bigEndian) ) + " " + Exiv2::toString(Exiv2::getUShort( buf2.data(), bigEndian)); - - // Sanity check with an "unreasonably" large number - if (dataLength > 200 || dataLength < 4) { + io_->seek(io_->tell() + dataLength - 8, BasicIo::beg); + } else + io_->read(buf.data(), dataLength - 8); + } else if (dataType == 8) { + dataLength = Exiv2::getUShort(buf.data(), bigEndian) * 2; + std::memset(buf.data(), 0x0, buf.size()); + io_->read(buf.data(), 2); + io_->read(buf2.data(), 2); + if (td) + xmpData_[exvGettext(td->label_)] = Exiv2::toString(Exiv2::getUShort(buf.data(), bigEndian)) + " " + + Exiv2::toString(Exiv2::getUShort(buf2.data(), 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"; + 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.data(), dataLength - 4); - } - } + io_->seek(io_->tell() + dataLength - 4, BasicIo::beg); + } else + io_->read(buf.data(), dataLength - 4); + } + } - io_->seek(cur_pos + size_external, BasicIo::beg); - } // QuickTimeVideo::NikonTagsDecoder - - void QuickTimeVideo::setMediaStream() - { - uint64_t current_position = io_->tell(); - DataBuf buf(4+1); - - while(!io_->eof()) { - io_->read(buf.data(), 4); - if (equalsQTimeTag(buf, "hdlr")) { - io_->read(buf.data(), 4); - io_->read(buf.data(), 4); - io_->read(buf.data(), 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; - } - } + io_->seek(cur_pos + size_external, BasicIo::beg); +} // QuickTimeVideo::NikonTagsDecoder - io_->seek(current_position, BasicIo::beg); - } // QuickTimeVideo::setMediaStream - - void QuickTimeVideo::timeToSampleDecoder() - { - DataBuf buf(4+1); - io_->read(buf.data(), 4); - io_->read(buf.data(), 4); - uint64_t noOfEntries, totalframes = 0, timeOfFrames = 0; - noOfEntries = returnUnsignedBufValue(buf); - uint64_t temp; - - for(unsigned long i = 1; i <= noOfEntries; i++) { - io_->read(buf.data(), 4); - temp = returnBufValue(buf); - totalframes += temp; - io_->read(buf.data(), 4); - timeOfFrames += temp * returnBufValue(buf); - } - 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.data(), 4); - io_->read(buf.data(), 4); - uint64_t noOfEntries; - noOfEntries = returnUnsignedBufValue(buf); - - 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); - std::memset(buf.data(), 0x0, buf.size()); - buf.data()[4] = '\0'; - io_->read(buf.data(), 4); - uint64_t size = 82; - - const TagVocabulary* td; - - for (int i = 0; size/4 != 0 ; size -= 4, i++) { - io_->read(buf.data(), 4); - switch(i) { - case AudioFormat: - td = find(qTimeFileType, Exiv2::toString( buf.data())); - if(td) - xmpData_["Xmp.audio.Compressor"] = exvGettext(td->label_); - else - xmpData_["Xmp.audio.Compressor"] = Exiv2::toString( buf.data()); - break; - case AudioVendorID: - td = find(vendorIDTags, Exiv2::toString( buf.data())); - if(td) - xmpData_["Xmp.audio.VendorID"] = exvGettext(td->label_); - break; - case AudioChannels: - xmpData_["Xmp.audio.ChannelType"] = returnBufValue(buf, 2); - xmpData_["Xmp.audio.BitsPerSample"] = (buf.data()[2] * 256 + buf.data()[3]); - break; - case AudioSampleRate: - xmpData_["Xmp.audio.SampleRate"] = returnBufValue(buf, 2) + ((buf.data()[2] * 256 + buf.data()[3]) * 0.01); - break; - default: - break; - } - } - io_->read(buf.data(), static_cast(size % 4)); //cause size is so small, this cast should be right. - } // QuickTimeVideo::audioDescDecoder - - void QuickTimeVideo::imageDescDecoder() - { - DataBuf buf(40); - std::memset(buf.data(), 0x0, buf.size()); - buf.data()[4] = '\0'; - io_->read(buf.data(), 4); - uint64_t size = 82; - - const TagVocabulary* td; - - for (int i = 0; size/4 != 0 ; size -= 4, i++) { - io_->read(buf.data(), 4); - - switch(i) { - case codec: - td = find(qTimeFileType, Exiv2::toString( buf.data())); - if(td) - xmpData_["Xmp.video.Codec"] = exvGettext(td->label_); - else - xmpData_["Xmp.video.Codec"] = Exiv2::toString( buf.data()); - break; - case VendorID: - td = find(vendorIDTags, Exiv2::toString( buf.data())); - 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.data()[2] * 256 + buf.data()[3]); - break; - case XResolution: - xmpData_["Xmp.video.XResolution"] = returnBufValue(buf, 2) + ((buf.data()[2] * 256 + buf.data()[3]) * 0.01); - break; - case YResolution: - xmpData_["Xmp.video.YResolution"] = returnBufValue(buf, 2) + ((buf.data()[2] * 256 + buf.data()[3]) * 0.01); - io_->read(buf.data(), 3); size -= 3; - break; - case CompressorName: - io_->read(buf.data(), 32); size -= 32; - xmpData_["Xmp.video.Compressor"] = Exiv2::toString( buf.data()); - break; - default: - break; - } - } - io_->read(buf.data(), static_cast(size % 4)); - xmpData_["Xmp.video.BitDepth"] = returnBufValue(buf, 1); - } // QuickTimeVideo::imageDescDecoder - - void QuickTimeVideo::multipleEntriesDecoder() - { - DataBuf buf(4+1); - io_->read(buf.data(), 4); - io_->read(buf.data(), 4); - uint64_t noOfEntries; - - noOfEntries = returnUnsignedBufValue(buf); - - for(unsigned long i = 1; i <= noOfEntries; i++) - decodeBlock(); - } // QuickTimeVideo::multipleEntriesDecoder - - void QuickTimeVideo::videoHeaderDecoder(unsigned long size) { - DataBuf buf(3); - std::memset(buf.data(), 0x0, buf.size()); - buf.data()[2] = '\0'; - currentStream_ = Video; +void QuickTimeVideo::setMediaStream() { + uint64_t current_position = io_->tell(); + DataBuf buf(4 + 1); - const TagDetails* td; - - for (int i = 0; size/2 != 0 ; size -= 2, i++) { - io_->read(buf.data(), 2); - - switch(i) { - case GraphicsMode: - td = find(graphicsModetags, returnBufValue(buf,2)); - 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.data(), size % 2); - } // QuickTimeVideo::videoHeaderDecoder - - void QuickTimeVideo::handlerDecoder(unsigned long size) - { - uint64_t cur_pos = io_->tell(); - DataBuf buf(100); - std::memset(buf.data(), 0x0, buf.size()); - buf.data()[4] = '\0'; - - const TagVocabulary* tv; - - for (int i = 0; i < 5 ; i++) { - io_->read(buf.data(), 4); - - switch(i) { - case HandlerClass: - tv = find(handlerClassTags, Exiv2::toString( buf.data())); - if(tv) { - if (currentStream_ == Video) - xmpData_["Xmp.video.HandlerClass"] = exvGettext(tv->label_); - else if (currentStream_ == Audio) - xmpData_["Xmp.audio.HandlerClass"] = exvGettext(tv->label_); - } - break; - case HandlerType: - tv = find(handlerTypeTags, Exiv2::toString( buf.data())); - if(tv) { - if (currentStream_ == Video) - xmpData_["Xmp.video.HandlerType"] = exvGettext(tv->label_); - else if (currentStream_ == Audio) - xmpData_["Xmp.audio.HandlerType"] = exvGettext(tv->label_); - } - break; - case HandlerVendorID: - tv = find(vendorIDTags, Exiv2::toString( buf.data())); - if(tv) { - if (currentStream_ == Video) - xmpData_["Xmp.video.HandlerVendorID"] = exvGettext(tv->label_); - else if (currentStream_ == Audio) - xmpData_["Xmp.audio.HandlerVendorID"] = exvGettext(tv->label_); - } - break; - } - } - io_->seek(cur_pos + size, BasicIo::beg); - } // QuickTimeVideo::handlerDecoder - - void QuickTimeVideo::fileTypeDecoder(unsigned long size) { - DataBuf buf(5); - std::memset(buf.data(), 0x0, buf.size()); - buf.data()[4] = '\0'; - Exiv2::Value::UniquePtr v = Exiv2::Value::create(Exiv2::xmpSeq); - const TagVocabulary* td; - - for (int i = 0; size/4 != 0; size -=4, i++) { - io_->read(buf.data(), 4); - td = find(qTimeFileType, Exiv2::toString( buf.data())); - - 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.data())); - break; - } - } - xmpData_.add(Exiv2::XmpKey("Xmp.video.CompatibleBrands"), v.get()); - io_->read(buf.data(), size%4); - } // QuickTimeVideo::fileTypeDecoder - - void QuickTimeVideo::mediaHeaderDecoder(unsigned long size) { - DataBuf buf(5); - std::memset(buf.data(), 0x0, buf.size()); - buf.data()[4] = '\0'; - int64_t time_scale = 1; - - for (int i = 0; size/4 != 0 ; size -=4, i++) { - io_->read(buf.data(), 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); - 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); - 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); - break; - case MediaTimeScale: - if(currentStream_ == Video) - xmpData_["Xmp.video.MediaTimeScale"] = returnBufValue(buf); - else if (currentStream_ == Audio) - xmpData_["Xmp.audio.MediaTimeScale"] = returnBufValue(buf); - time_scale = returnBufValue(buf); - if (time_scale <= 0) - time_scale = 1; - break; - case MediaDuration: - if(currentStream_ == Video) - xmpData_["Xmp.video.MediaDuration"] = time_scale ? returnBufValue(buf)/time_scale : 0 ; - else if (currentStream_ == Audio) - xmpData_["Xmp.audio.MediaDuration"] = time_scale ? returnBufValue(buf)/time_scale : 0; - break; - case MediaLanguageCode: - if(currentStream_ == Video) - xmpData_["Xmp.video.MediaLangCode"] = returnUnsignedBufValue(buf,2); - else if (currentStream_ == Audio) - xmpData_["Xmp.audio.MediaLangCode"] = returnUnsignedBufValue(buf,2); - break; - - default: - break; - } - } - io_->read(buf.data(), size%4); - } // QuickTimeVideo::mediaHeaderDecoder - - void QuickTimeVideo::trackHeaderDecoder(unsigned long size) { - DataBuf buf(5); - std::memset(buf.data(), 0x0, buf.size()); - buf.data()[4] = '\0'; - int64_t temp = 0; - - for (int i = 0; size/4 != 0 ; size -=4, i++) { - io_->read(buf.data(), 4); - - 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"] = timeScale_ ? returnBufValue(buf)/timeScale_ : 0; - else if(currentStream_ == Audio) - xmpData_["Xmp.audio.TrackDuration"] = timeScale_ ? returnBufValue(buf)/timeScale_ : 0; - 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.data()[2] * 0.1)) * 100; - else if(currentStream_ == Audio) - xmpData_["Xmp.video.TrackVolume"] = (returnBufValue(buf, 1) + (buf.data()[2] * 0.1)) * 100; - break; - case ImageWidth: - if(currentStream_ == Video) { - temp = returnBufValue(buf, 2) + static_cast((buf.data()[2] * 256 + buf.data()[3]) * 0.01); - xmpData_["Xmp.video.Width"] = temp; - width_ = temp; - } - break; - case ImageHeight: - if(currentStream_ == Video) { - temp = returnBufValue(buf, 2) + static_cast((buf.data()[2] * 256 + buf.data()[3]) * 0.01); - xmpData_["Xmp.video.Height"] = temp; - height_ = temp; - } - break; - default: - break; - } + while (!io_->eof()) { + io_->read(buf.data(), 4); + if (equalsQTimeTag(buf, "hdlr")) { + io_->read(buf.data(), 4); + io_->read(buf.data(), 4); + io_->read(buf.data(), 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; + } + } + + io_->seek(current_position, BasicIo::beg); +} // QuickTimeVideo::setMediaStream + +void QuickTimeVideo::timeToSampleDecoder() { + DataBuf buf(4 + 1); + io_->read(buf.data(), 4); + io_->read(buf.data(), 4); + uint64_t noOfEntries, totalframes = 0, timeOfFrames = 0; + noOfEntries = returnUnsignedBufValue(buf); + uint64_t temp; + + for (unsigned long i = 1; i <= noOfEntries; i++) { + io_->read(buf.data(), 4); + temp = returnBufValue(buf); + totalframes += temp; + io_->read(buf.data(), 4); + timeOfFrames += temp * returnBufValue(buf); + } + if (currentStream_ == Video) + xmpData_["Xmp.video.FrameRate"] = (double)totalframes * (double)timeScale_ / (double)timeOfFrames; +} // QuickTimeVideo::timeToSampleDecoder + +void QuickTimeVideo::sampleDesc(uint64_t size) { + DataBuf buf(100); + uint64_t cur_pos = io_->tell(); + io_->read(buf.data(), 4); + io_->read(buf.data(), 4); + uint64_t noOfEntries; + noOfEntries = returnUnsignedBufValue(buf); + + 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); + std::memset(buf.data(), 0x0, buf.size()); + buf.data()[4] = '\0'; + io_->read(buf.data(), 4); + uint64_t size = 82; + + const TagVocabulary* td; + + for (int i = 0; size / 4 != 0; size -= 4, i++) { + io_->read(buf.data(), 4); + switch (i) { + case AudioFormat: + td = find(qTimeFileType, Exiv2::toString(buf.data())); + if (td) + xmpData_["Xmp.audio.Compressor"] = exvGettext(td->label_); + else + xmpData_["Xmp.audio.Compressor"] = Exiv2::toString(buf.data()); + break; + case AudioVendorID: + td = find(vendorIDTags, Exiv2::toString(buf.data())); + if (td) + xmpData_["Xmp.audio.VendorID"] = exvGettext(td->label_); + break; + case AudioChannels: + xmpData_["Xmp.audio.ChannelType"] = returnBufValue(buf, 2); + xmpData_["Xmp.audio.BitsPerSample"] = (buf.data()[2] * 256 + buf.data()[3]); + break; + case AudioSampleRate: + xmpData_["Xmp.audio.SampleRate"] = returnBufValue(buf, 2) + ((buf.data()[2] * 256 + buf.data()[3]) * 0.01); + break; + default: + break; + } + } + io_->read(buf.data(), static_cast(size % 4)); // cause size is so small, this cast should be right. +} // QuickTimeVideo::audioDescDecoder + +void QuickTimeVideo::imageDescDecoder() { + DataBuf buf(40); + std::memset(buf.data(), 0x0, buf.size()); + buf.data()[4] = '\0'; + io_->read(buf.data(), 4); + uint64_t size = 82; + + const TagVocabulary* td; + + for (int i = 0; size / 4 != 0; size -= 4, i++) { + io_->read(buf.data(), 4); + + switch (i) { + case codec: + td = find(qTimeFileType, Exiv2::toString(buf.data())); + if (td) + xmpData_["Xmp.video.Codec"] = exvGettext(td->label_); + else + xmpData_["Xmp.video.Codec"] = Exiv2::toString(buf.data()); + break; + case VendorID: + td = find(vendorIDTags, Exiv2::toString(buf.data())); + 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.data()[2] * 256 + buf.data()[3]); + break; + case XResolution: + xmpData_["Xmp.video.XResolution"] = returnBufValue(buf, 2) + ((buf.data()[2] * 256 + buf.data()[3]) * 0.01); + break; + case YResolution: + xmpData_["Xmp.video.YResolution"] = returnBufValue(buf, 2) + ((buf.data()[2] * 256 + buf.data()[3]) * 0.01); + io_->read(buf.data(), 3); + size -= 3; + break; + case CompressorName: + io_->read(buf.data(), 32); + size -= 32; + xmpData_["Xmp.video.Compressor"] = Exiv2::toString(buf.data()); + break; + default: + break; + } + } + io_->read(buf.data(), static_cast(size % 4)); + xmpData_["Xmp.video.BitDepth"] = returnBufValue(buf, 1); +} // QuickTimeVideo::imageDescDecoder + +void QuickTimeVideo::multipleEntriesDecoder() { + DataBuf buf(4 + 1); + io_->read(buf.data(), 4); + io_->read(buf.data(), 4); + uint64_t noOfEntries; + + noOfEntries = returnUnsignedBufValue(buf); + + for (unsigned long i = 1; i <= noOfEntries; i++) + decodeBlock(); +} // QuickTimeVideo::multipleEntriesDecoder + +void QuickTimeVideo::videoHeaderDecoder(uint64_t size) { + DataBuf buf(3); + std::memset(buf.data(), 0x0, buf.size()); + buf.data()[2] = '\0'; + currentStream_ = Video; + + const TagDetails* td; + + for (int i = 0; size / 2 != 0; size -= 2, i++) { + io_->read(buf.data(), 2); + + switch (i) { + case GraphicsMode: + td = find(graphicsModetags, returnBufValue(buf, 2)); + 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.data(), size % 2); +} // QuickTimeVideo::videoHeaderDecoder + +void QuickTimeVideo::handlerDecoder(uint64_t size) { + uint64_t cur_pos = io_->tell(); + DataBuf buf(100); + std::memset(buf.data(), 0x0, buf.size()); + buf.data()[4] = '\0'; + + const TagVocabulary* tv; + + for (int i = 0; i < 5; i++) { + io_->read(buf.data(), 4); + + switch (i) { + case HandlerClass: + tv = find(handlerClassTags, Exiv2::toString(buf.data())); + if (tv) { + if (currentStream_ == Video) + xmpData_["Xmp.video.HandlerClass"] = exvGettext(tv->label_); + else if (currentStream_ == Audio) + xmpData_["Xmp.audio.HandlerClass"] = exvGettext(tv->label_); } - io_->read(buf.data(), size%4); - } // QuickTimeVideo::trackHeaderDecoder - - void QuickTimeVideo::movieHeaderDecoder(unsigned long size) { - DataBuf buf(5); - std::memset(buf.data(), 0x0, buf.size()); - buf.data()[4] = '\0'; - - for (int i = 0; size/4 != 0 ; size -=4, i++) { - io_->read(buf.data(), 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; - case TimeScale: - xmpData_["Xmp.video.TimeScale"] = returnBufValue(buf); - timeScale_ = returnBufValue(buf); - if (timeScale_ <= 0) timeScale_ = 1; - 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.data()[2] * 256 + buf.data()[3]) * 0.01); break; - case PreferredVolume: - xmpData_["Xmp.video.PreferredVolume"] = (returnBufValue(buf, 1) + (buf.data()[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: - break; - } + break; + case HandlerType: + tv = find(handlerTypeTags, Exiv2::toString(buf.data())); + if (tv) { + if (currentStream_ == Video) + xmpData_["Xmp.video.HandlerType"] = exvGettext(tv->label_); + else if (currentStream_ == Audio) + xmpData_["Xmp.audio.HandlerType"] = exvGettext(tv->label_); } - io_->read(buf.data(), size%4); - } // QuickTimeVideo::movieHeaderDecoder - - void QuickTimeVideo::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; + break; + case HandlerVendorID: + tv = find(vendorIDTags, Exiv2::toString(buf.data())); + if (tv) { + if (currentStream_ == Video) + xmpData_["Xmp.video.HandlerVendorID"] = exvGettext(tv->label_); + else if (currentStream_ == Audio) + xmpData_["Xmp.audio.HandlerVendorID"] = exvGettext(tv->label_); } - } // QuickTimeVideo::aspectRatio - + break; + } + } + io_->seek(cur_pos + size, BasicIo::beg); +} // QuickTimeVideo::handlerDecoder + +void QuickTimeVideo::fileTypeDecoder(uint64_t size) { + DataBuf buf(5); + std::memset(buf.data(), 0x0, buf.size()); + buf.data()[4] = '\0'; + Exiv2::Value::UniquePtr v = Exiv2::Value::create(Exiv2::xmpSeq); + const TagVocabulary* td; + + for (int i = 0; size / 4 != 0; size -= 4, i++) { + io_->read(buf.data(), 4); + td = find(qTimeFileType, Exiv2::toString(buf.data())); + + 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.data())); + break; + } + } + xmpData_.add(Exiv2::XmpKey("Xmp.video.CompatibleBrands"), v.get()); + io_->read(buf.data(), size % 4); +} // QuickTimeVideo::fileTypeDecoder + +void QuickTimeVideo::mediaHeaderDecoder(uint64_t size) { + DataBuf buf(5); + std::memset(buf.data(), 0x0, buf.size()); + buf.data()[4] = '\0'; + int64_t time_scale = 1; + + for (int i = 0; size / 4 != 0; size -= 4, i++) { + io_->read(buf.data(), 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); + 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); + 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); + break; + case MediaTimeScale: + if (currentStream_ == Video) + xmpData_["Xmp.video.MediaTimeScale"] = returnBufValue(buf); + else if (currentStream_ == Audio) + xmpData_["Xmp.audio.MediaTimeScale"] = returnBufValue(buf); + time_scale = returnBufValue(buf); + if (time_scale <= 0) + time_scale = 1; + break; + case MediaDuration: + if (currentStream_ == Video) + xmpData_["Xmp.video.MediaDuration"] = time_scale ? returnBufValue(buf) / time_scale : 0; + else if (currentStream_ == Audio) + xmpData_["Xmp.audio.MediaDuration"] = time_scale ? returnBufValue(buf) / time_scale : 0; + break; + case MediaLanguageCode: + if (currentStream_ == Video) + xmpData_["Xmp.video.MediaLangCode"] = returnUnsignedBufValue(buf, 2); + else if (currentStream_ == Audio) + xmpData_["Xmp.audio.MediaLangCode"] = returnUnsignedBufValue(buf, 2); + break; - Image::UniquePtr newQTimeInstance(BasicIo::UniquePtr io, bool /*create*/) { - Image::UniquePtr image(new QuickTimeVideo(std::move(io))); - if (!image->good()) { - image.reset(); - } - return image; + default: + break; } + } + io_->read(buf.data(), size % 4); +} // QuickTimeVideo::mediaHeaderDecoder + +void QuickTimeVideo::trackHeaderDecoder(uint64_t size) { + DataBuf buf(5); + std::memset(buf.data(), 0x0, buf.size()); + buf.data()[4] = '\0'; + int64_t temp = 0; - bool isQTimeType(BasicIo& iIo, bool advance) { - auto buf = iIo.read(12); + for (int i = 0; size / 4 != 0; size -= 4, i++) { + io_->read(buf.data(), 4); - if (iIo.error() || iIo.eof()) { - return false; + 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"] = timeScale_ ? returnBufValue(buf) / timeScale_ : 0; + else if (currentStream_ == Audio) + xmpData_["Xmp.audio.TrackDuration"] = timeScale_ ? returnBufValue(buf) / timeScale_ : 0; + 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.data()[2] * 0.1)) * 100; + else if (currentStream_ == Audio) + xmpData_["Xmp.video.TrackVolume"] = (returnBufValue(buf, 1) + (buf.data()[2] * 0.1)) * 100; + break; + case ImageWidth: + if (currentStream_ == Video) { + temp = returnBufValue(buf, 2) + static_cast((buf.data()[2] * 256 + buf.data()[3]) * 0.01); + xmpData_["Xmp.video.Width"] = temp; + width_ = temp; } - auto qTimeTags = - std::array{"PICT", "free", "ftyp", "junk", "mdat", "moov", "pict", "pnot", "skip", "uuid", "wide"}; - - bool matched = false; - - for (auto const& tag : qTimeTags) { - auto tmp = buf.cmpBytes(4, tag, 4); - if (tmp == 0) { - // we only match if we actually know the video type. This is done - // to avoid matching just on ftyp because bmffimage also has that - // header. - auto td = find(qTimeFileType, std::string{buf.c_str(8), 4} ); - if (td){ - matched = true; - } - break; - } + break; + case ImageHeight: + if (currentStream_ == Video) { + temp = returnBufValue(buf, 2) + static_cast((buf.data()[2] * 256 + buf.data()[3]) * 0.01); + xmpData_["Xmp.video.Height"] = temp; + height_ = temp; } - - if (!advance || !matched) { - iIo.seek(static_cast(0), BasicIo::beg); + break; + default: + break; + } + } + io_->read(buf.data(), size % 4); +} // QuickTimeVideo::trackHeaderDecoder + +void QuickTimeVideo::movieHeaderDecoder(uint64_t size) { + DataBuf buf(5); + std::memset(buf.data(), 0x0, buf.size()); + buf.data()[4] = '\0'; + + for (int i = 0; size / 4 != 0; size -= 4, i++) { + io_->read(buf.data(), 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; + case TimeScale: + xmpData_["Xmp.video.TimeScale"] = returnBufValue(buf); + timeScale_ = returnBufValue(buf); + if (timeScale_ <= 0) + timeScale_ = 1; + break; + case Duration: + if (timeScale_ != 0) { // To prevent division by zero + xmpData_["Xmp.video.Duration"] = returnBufValue(buf) * 1000 / timeScale_; } - - return matched; + break; + case PreferredRate: + xmpData_["Xmp.video.PreferredRate"] = returnBufValue(buf, 2) + ((buf.data()[2] * 256 + buf.data()[3]) * 0.01); + break; + case PreferredVolume: + xmpData_["Xmp.video.PreferredVolume"] = (returnBufValue(buf, 1) + (buf.data()[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: + break; } + } + io_->read(buf.data(), size % 4); +} // QuickTimeVideo::movieHeaderDecoder + +void QuickTimeVideo::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; + } +} // QuickTimeVideo::aspectRatio + +Image::UniquePtr newQTimeInstance(BasicIo::UniquePtr io, bool /*create*/) { + Image::UniquePtr image(new QuickTimeVideo(std::move(io))); + if (!image->good()) { + image.reset(); + } + return image; +} + +bool isQTimeType(BasicIo& iIo, bool advance) { + auto buf = iIo.read(12); + + if (iIo.error() || iIo.eof()) { + return false; + } + auto qTimeTags = std::array{"PICT", "free", "ftyp", "junk", "mdat", "moov", "pict", "pnot", "skip", "uuid", "wide"}; + + bool matched = false; + + for (auto const& tag : qTimeTags) { + auto tmp = buf.cmpBytes(4, tag, 4); + if (tmp == 0) { + // we only match if we actually know the video type. This is done + // to avoid matching just on ftyp because bmffimage also has that + // header. + auto td = find(qTimeFileType, std::string{buf.c_str(8), 4}); + if (td) { + matched = true; + } + break; + } + } + + if (!advance || !matched) { + iIo.seek(static_cast(0), BasicIo::beg); + } + + return matched; +} -} // namespace Exiv2 +} // namespace Exiv2