Remove deprecated Matroska support

main
Luis Díaz Más 4 years ago
parent 94b87a8dec
commit 8dcc07887a

@ -19,7 +19,6 @@ install(FILES
iptc.hpp
jp2image.hpp
jpgimage.hpp
matroskavideo.hpp
metadatum.hpp
mrwimage.hpp
orfimage.hpp

@ -1,148 +0,0 @@
// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004-2021 Exiv2 authors
* This program is part of the Exiv2 distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MATROSKAVIDEO_HPP_
#define MATROSKAVIDEO_HPP_
// *****************************************************************************
#include "exiv2lib_export.h"
// included header files
#include "image.hpp"
// *****************************************************************************
// namespace extensions
namespace Exiv2 {
// *****************************************************************************
// class definitions
// Add MKV to the supported image formats
namespace ImageType {
const int mkv = 21; //!< Treating mkv as an image type>
}
// Todo: Should be hidden
/*!
@brief Helper structure for the Matroska tags lookup table.
*/
struct EXIV2LIB_DEPRECATED MatroskaTags {
uint64_t val_; //!< Tag value
const char* label_; //!< Translation of the tag value
//! Comparison operator for use with the find template
bool operator==(uint64_t key) const { return val_ == key; }
}; // struct TagDetails
/*!
@brief Class to access Matroska video files.
*/
class EXIV2LIB_DEPRECATED_EXPORT MatroskaVideo : public Image {
public:
//! @name Creators
//@{
/*!
@brief Constructor for a Matroska video. Since the constructor
can not return a result, callers should check the good() method
after object construction to determine success or failure.
@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.
*/
MatroskaVideo(BasicIo::UniquePtr io);
//@}
//! @name Manipulators
//@{
void readMetadata();
void writeMetadata();
//@}
//! @name Accessors
//@{
std::string mimeType() const;
//@}
protected:
/*!
@brief Function used to calulate the size of a block.
This information is only stored in one byte.
The size of the block is calculated by counting
the number of leading zeros in the binary code of the byte.
Size = (No. of leading zeros + 1) bytes
@param b The byte, which stores the information to calculate the size
@return Return the size of the block.
*/
uint32_t findBlockSize(byte b);
/*!
@brief Check for a valid tag and decode the block at the current IO position.
Calls contentManagement() or skips to next tag, if required.
*/
void decodeBlock();
/*!
@brief Interpret tag information, and save it in the respective XMP container.
@param mt Pointer to current tag,
@param buf Pointer to the memory area with the tag information.
@param size Size of \em buf.
*/
void contentManagement(const MatroskaTags* mt, const byte* buf, long size);
/*!
@brief Calculates Aspect Ratio of a video, and stores it in the
respective XMP container.
*/
void aspectRatio();
private:
//! @name NOT Implemented
//@{
//! Copy constructor
MatroskaVideo(const MatroskaVideo& rhs);
//! Assignment operator
MatroskaVideo& operator=(const MatroskaVideo& rhs);
//@}
private:
//! Variable to check the end of metadata traversing.
bool continueTraversing_;
//! Variable to store height and width of a video frame.
uint64_t height_, width_;
}; // class MatroskaVideo
// *****************************************************************************
// template, inline and free functions
// These could be static private functions on Image subclasses but then
// ImageFactory needs to be made a friend.
/*!
@brief Create a new MatroskaVideo instance and return an auto-pointer to it.
Caller owns the returned object and the auto-pointer ensures that
it will be deleted.
*/
EXIV2LIB_DEPRECATED_EXPORT Image::UniquePtr newMkvInstance(BasicIo::UniquePtr io, bool create);
//! Check if the file iIo is a Matroska Video.
EXIV2LIB_DEPRECATED_EXPORT bool isMkvType(BasicIo& iIo, bool advance);
} // namespace Exiv2
#endif // #ifndef MATROSKAVIDEO_HPP_

@ -105,7 +105,6 @@ endif()
if( EXIV2_ENABLE_VIDEO )
target_sources(exiv2lib PRIVATE
matroskavideo.cpp ../include/exiv2/matroskavideo.hpp
quicktimevideo.cpp ../include/exiv2/quicktimevideo.hpp
riffvideo.cpp ../include/exiv2/riffvideo.hpp
utilsvideo.cpp ../include/exiv2/utilsvideo.hpp

@ -53,10 +53,8 @@
#include "nikonmn_int.hpp"
#ifdef EXV_ENABLE_VIDEO
#include "matroskavideo.hpp"
#include "quicktimevideo.hpp"
#include "riffvideo.hpp"
#include "asfvideo.hpp"
#endif// EXV_ENABLE_VIDEO
#include "rw2image.hpp"
#include "pgfimage.hpp"

@ -1,759 +0,0 @@
// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004-2021 Exiv2 authors
* This program is part of the Exiv2 distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
*/
// *****************************************************************************
// included header files
#include "config.h"
#ifdef EXV_ENABLE_VIDEO
#include "matroskavideo.hpp"
#include "error.hpp"
#include "futils.hpp"
#include "basicio.hpp"
#include "tags.hpp"
#include "tags_int.hpp"
// + standard includes
#include <cmath>
#include <cassert>
// *****************************************************************************
// class member definitions
namespace Exiv2 {
namespace Internal {
//! List of composite tags. They are skipped and the child tags are read immediately
uint64_t compositeTagsList[] = {
0x0000, 0x000e, 0x000f, 0x0020, 0x0026, 0x002e, 0x0036,
0x0037, 0x003b, 0x005b, 0x0060, 0x0061, 0x0068, 0x05b9,
0x0dbb, 0x1034, 0x1035, 0x1854, 0x21a7, 0x2240, 0x23c0,
0x2624, 0x27c8, 0x2911, 0x2924, 0x2944, 0x2d80, 0x3373,
0x35a1, 0x3e5b, 0x3e7b,
0x14d9b74, 0x254c367, 0x549a966, 0x654ae6b, 0x8538067,
0x941a469, 0xa45dfa3, 0xb538667, 0xc53bb6b, 0xf43b675
};
//! List of tags which are ignored, i.e., tag and value won't be read
uint64_t ignoredTagsList[] = {
0x0021, 0x0023, 0x0033, 0x0071, 0x0077, 0x006c, 0x0067, 0x007b, 0x02f2, 0x02f3,
0x1031, 0x1032, 0x13ab, 0x13ac, 0x15ee, 0x23a2, 0x23c6, 0x2e67, 0x33a4, 0x33c5,
0x3446, 0x2de7, 0x2df8, 0x26bf, 0x28ca, 0x3384, 0x13b8, 0x037e, 0x0485, 0x18d7,
0x0005, 0x0009, 0x0011, 0x0012, 0x0016, 0x0017, 0x0018, 0x0022, 0x0024, 0x0025,
0x0027, 0x002b, 0x002f, 0x003f, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x006a,
0x006b, 0x006e, 0x007a, 0x007d, 0x0255, 0x3eb5, 0x3ea5, 0x3d7b, 0x33c4, 0x2fab,
0x2ebc, 0x29fc, 0x29a5, 0x2955, 0x2933, 0x135f, 0x2922, 0x26a5, 0x26fc, 0x2532,
0x23c9, 0x23c4, 0x23c5, 0x137f, 0x1378, 0x07e2, 0x07e3, 0x07e4, 0x0675, 0x05bc,
0x05bd, 0x05db, 0x05dd, 0x0598, 0x050d, 0x0444, 0x037c,
0x3314f, 0x43a770, 0x1eb923, 0x1cb923, 0xeb524, 0x1c83ab, 0x1e83bb
};
/*!
Tag Look-up list for Matroska Type Video Files
The Tags have been categorized in 4 categories. Which are
mentioned as a comment in front of them.
s -- Tag to be Skipped
sd -- Tag to be Skipped along with its data
u -- Tag used directly for storing metadata
ui -- Tag used only internally
*/
extern const MatroskaTags matroskaTags[] = {
{ 0x0000, "ChapterDisplay" }, //s
{ 0x0003, "TrackType" }, //ui
{ 0x0005, "ChapterString" }, //sd
{ 0x0006, "VideoCodecID/AudioCodecID/CodecID" }, //ui
{ 0x0008, "TrackDefault" }, //ui
{ 0x0009, "ChapterTrackNumber" }, //sd
{ 0x000e, "Slices" }, //s
{ 0x000f, "ChapterTrack" }, //s
{ 0x0011, "ChapterTimeStart" }, //sd
{ 0x0012, "ChapterTimeEnd" }, //sd
{ 0x0016, "CueRefTime" }, //sd
{ 0x0017, "CueRefCluster" }, //sd
{ 0x0018, "ChapterFlagHidden" }, //sd
{ 0x001a, "Xmp.video.VideoScanTpye" }, //u
{ 0x001b, "BlockDuration" }, //s
{ 0x001c, "TrackLacing" }, //ui
{ 0x001f, "Xmp.audio.ChannelType" }, //u
{ 0x0020, "BlockGroup" }, //s
{ 0x0021, "Block" }, //sd
{ 0x0022, "BlockVirtual" }, //sd
{ 0x0023, "SimpleBlock" }, //sd
{ 0x0024, "CodecState" }, //sd
{ 0x0025, "BlockAdditional" }, //sd
{ 0x0026, "BlockMore" }, //s
{ 0x0027, "Position" }, //sd
{ 0x002a, "CodecDecodeAll" }, //ui
{ 0x002b, "PrevSize" }, //sd
{ 0x002e, "TrackEntry" }, //s
{ 0x002f, "EncryptedBlock" }, //sd
{ 0x0030, "Xmp.video.Width" }, //u
{ 0x0033, "CueTime" }, //sd
{ 0x0035, "Xmp.audio.SampleRate" }, //u
{ 0x0036, "ChapterAtom" }, //s
{ 0x0037, "CueTrackPositions" }, //s
{ 0x0039, "TrackUsed" }, //ui
{ 0x003a, "Xmp.video.Height" }, //u
{ 0x003b, "CuePoint" }, //s
{ 0x003f, "CRC-32" }, //sd
{ 0x004b, "BlockAdditionalID" }, //sd
{ 0x004c, "LaceNumber" }, //sd
{ 0x004d, "FrameNumber" }, //sd
{ 0x004e, "Delay" }, //sd
{ 0x004f, "ClusterDuration" }, //sd
{ 0x0057, "TrackNumber" }, //ui
{ 0x005b, "CueReference" }, //s
{ 0x0060, "Video" }, //s
{ 0x0061, "Audio" }, //s
{ 0x0067, "Timecode" }, //sd
{ 0x0068, "TimeSlice" }, //s
{ 0x006a, "CueCodecState" }, //sd
{ 0x006b, "CueRefCodecState" }, //sd
{ 0x006c, "Void" }, //sd
{ 0x006e, "BlockAddID" }, //sd
{ 0x0071, "CueClusterPosition" }, //sd
{ 0x0077, "CueTrack" }, //sd
{ 0x007a, "ReferencePriority" }, //sd
{ 0x007b, "ReferenceBlock" }, //sd
{ 0x007d, "ReferenceVirtual" }, //sd
{ 0x0254, "Xmp.video.ContentCompressAlgo" }, //u
{ 0x0255, "ContentCompressionSettings" }, //sd
{ 0x0282, "Xmp.video.DocType" }, //u
{ 0x0285, "Xmp.video.DocTypeReadVersion" }, //u
{ 0x0286, "Xmp.video.EBMLVersion" }, //u
{ 0x0287, "Xmp.video.DocTypeVersion" }, //u
{ 0x02f2, "EBMLMaxIDLength" }, //sd
{ 0x02f3, "EBMLMaxSizeLength" }, //sd
{ 0x02f7, "Xmp.video.EBMLReadVersion" }, //u
{ 0x037c, "ChapterLanguage" }, //sd
{ 0x037e, "ChapterCountry" }, //sd
{ 0x0444, "SegmentFamily" }, //sd
{ 0x0461, "Xmp.video.DateUTC" }, //Date Time Original - measured in seconds relatively to Jan 01, 2001, 0:00:00 GMT+0h
{ 0x047a, "Xmp.video.TagLanguage" }, //u
{ 0x0484, "Xmp.video.TagDefault" }, //u
{ 0x0485, "TagBinary" }, //sd
{ 0x0487, "Xmp.video.TagString" }, //u
{ 0x0489, "Xmp.video.Duration" }, //u
{ 0x050d, "ChapterProcessPrivate" }, //sd
{ 0x0598, "ChapterFlagEnabled" }, //sd
{ 0x05a3, "Xmp.video.TagName" }, //u
{ 0x05b9, "EditionEntry" }, //s
{ 0x05bc, "EditionUID" }, //sd
{ 0x05bd, "EditionFlagHidden" }, //sd
{ 0x05db, "EditionFlagDefault" }, //sd
{ 0x05dd, "EditionFlagOrdered" }, //sd
{ 0x065c, "Xmp.video.AttachFileData" }, //u
{ 0x0660, "Xmp.video.AttachFileMIME" }, //u
{ 0x066e, "Xmp.video.AttachFileName" }, //u
{ 0x0675, "AttachedFileReferral" }, //sd
{ 0x067e, "Xmp.video.AttachFileDesc" }, //u
{ 0x06ae, "Xmp.video.AttachFileUID" }, //u
{ 0x07e1, "Xmp.video.ContentEncryptAlgo" }, //u
{ 0x07e2, "ContentEncryptionKeyID" }, //sd
{ 0x07e3, "ContentSignature" }, //sd
{ 0x07e4, "ContentSignatureKeyID" }, //sd
{ 0x07e5, "Xmp.video.ContentSignAlgo" }, //u
{ 0x07e6, "Xmp.video.ContentSignHashAlgo" }, //u
{ 0x0d80, "Xmp.video.MuxingApp" }, //u
{ 0x0dbb, "Seek" }, //s
{ 0x1031, "ContentEncodingOrder" }, //sd
{ 0x1032, "ContentEncodingScope" }, //sd
{ 0x1033, "Xmp.video.ContentEncodingType" }, //u
{ 0x1034, "ContentCompression" }, //s
{ 0x1035, "ContentEncryption" }, //s
{ 0x135f, "CueRefNumber" }, //sd
{ 0x136e, "Xmp.video.TrackName" }, //u
{ 0x1378, "CueBlockNumber" }, //sd
{ 0x137f, "TrackOffset" }, //sd
{ 0x13ab, "SeekID" }, //sd
{ 0x13ac, "SeekPosition" }, //sd
{ 0x13b8, "Stereo3DMode" }, //sd
{ 0x14aa, "Xmp.video.CropBottom" }, //ui
{ 0x14b0, "Xmp.video.Width" }, //u
{ 0x14b2, "Xmp.video.DisplayUnit" }, //u
{ 0x14b3, "Xmp.video.AspectRatioType" }, //u
{ 0x14ba, "Xmp.video.Height" }, //u
{ 0x14bb, "Xmp.video.CropTop" }, //ui
{ 0x14cc, "Xmp.video.CropLeft" }, //ui
{ 0x14dd, "Xmp.video.CropRight" }, //ui
{ 0x15aa, "TrackForced" }, //ui
{ 0x15ee, "MaxBlockAdditionID" }, //sd
{ 0x1741, "Xmp.video.WritingApp" }, //u
{ 0x1854, "SilentTracks" }, //s
{ 0x18d7, "SilentTrackNumber" }, //sd
{ 0x21a7, "AttachedFile" }, //s
{ 0x2240, "ContentEncoding" }, //s
{ 0x2264, "Xmp.audio.BitsPerSample" }, //u
{ 0x23a2, "CodecPrivate" }, //sd
{ 0x23c0, "Targets" }, //s
{ 0x23c3, "Xmp.video.PhysicalEquivalent" }, //u
{ 0x23c4, "TagChapterUID" }, //sd
{ 0x23c5, "TagTrackUID" }, //sd
{ 0x23c6, "TagAttachmentUID" }, //sd
{ 0x23c9, "TagEditionUID" }, //sd
{ 0x23ca, "Xmp.video.TargetType" }, //u
{ 0x2532, "SignedElement" }, //sd
{ 0x2624, "TrackTranslate" }, //s
{ 0x26a5, "TrackTranslateTrackID" }, //sd
{ 0x26bf, "TrackTranslateCodec" }, //sd
{ 0x26fc, "TrackTranslateEditionUID" }, //sd
{ 0x27c8, "SimpleTag" }, //s
{ 0x28ca, "TargetTypeValue" }, //sd
{ 0x2911, "ChapterProcessCommand" }, //s
{ 0x2922, "ChapterProcessTime" }, //sd
{ 0x2924, "ChapterTranslate" }, //s
{ 0x2933, "ChapterProcessData" }, //sd
{ 0x2944, "ChapterProcess" }, //s
{ 0x2955, "ChapterProcessCodecID" }, //sd
{ 0x29a5, "ChapterTranslateID" }, //sd
{ 0x29bf, "Xmp.video.TranslateCodec" }, //u
{ 0x29fc, "ChapterTranslateEditionUID" }, //sd
{ 0x2d80, "ContentEncodings" }, //s
{ 0x2de7, "MinCache" }, //sd
{ 0x2df8, "MaxCache" }, //sd
{ 0x2e67, "ChapterSegmentUID" }, //sd
{ 0x2ebc, "ChapterSegmentEditionUID" }, //sd
{ 0x2fab, "TrackOverlay" }, //sd
{ 0x3373, "Tag" }, //s
{ 0x3384, "SegmentFileName" }, //sd
{ 0x33a4, "SegmentUID" }, //sd
{ 0x33c4, "ChapterUID" }, //sd
{ 0x33c5, "TrackUID" }, //sd
{ 0x3446, "TrackAttachmentUID" }, //sd
{ 0x35a1, "BlockAdditions" }, //s
{ 0x38b5, "Xmp.audio.OutputSampleRate" }, //u
{ 0x3ba9, "Xmp.video.Title" }, //u
{ 0x3d7b, "ChannelPositions" }, //sd
{ 0x3e5b, "SignatureElements" }, //s
{ 0x3e7b, "SignatureElementList" }, //s
{ 0x3e8a, "Xmp.video.ContentSignAlgo" }, //u
{ 0x3e9a, "Xmp.video.ContentSignHashAlgo" }, //u
{ 0x3ea5, "SignaturePublicKey" }, //sd
{ 0x3eb5, "Signature" }, //sd
{ 0x2b59c, "TrackLanguage" }, //ui
{ 0x3314f, "TrackTimecodeScale" }, //sd
{ 0x383e3, "Xmp.video.FrameRate" }, //u
{ 0x3e383, "VideoFrameRate/DefaultDuration" }, //ui
{ 0x58688, "VideoCodecName/AudioCodecName/CodecName" }, //ui
{ 0x6b240, "CodecDownloadURL" }, //ui
{ 0xad7b1, "TimecodeScale" }, //ui
{ 0xeb524, "ColorSpace" }, //sd
{ 0xfb523, "Xmp.video.OpColor" }, //u
{ 0x1a9697, "CodecSettings" }, //ui
{ 0x1b4040, "CodecInfoURL" }, //ui
{ 0x1c83ab, "PrevFileName" }, //sd
{ 0x1cb923, "PrevUID" }, //sd
{ 0x1e83bb, "NextFileName" }, //sd
{ 0x1eb923, "NextUID" }, //sd
{ 0x43a770, "Chapters" }, //sd
{ 0x14d9b74, "SeekHead" }, //s
{ 0x254c367, "Tags" }, //s
{ 0x549a966, "Info" }, //s
{ 0x654ae6b, "Tracks" }, //s
{ 0x8538067, "SegmentHeader" }, //s
{ 0x941a469, "Attachments" }, //s
{ 0xa45dfa3, "EBMLHeader" }, //s
{ 0xb538667, "SignatureSlot" }, //s
{ 0xc53bb6b, "Cues" }, //s
{ 0xf43b675, "Cluster" }, //s
};
extern const MatroskaTags matroskaTrackType[] = {
{ 0x1, "Video" },
{ 0x2, "Audio" },
{ 0x3, "Complex" },
{ 0x10, "Logo" },
{ 0x11, "Subtitle" },
{ 0x12, "Buttons" },
{ 0x20, "Control" }
};
extern const MatroskaTags compressionAlgorithm[] = {
{ 0, "zlib " },
{ 1, "bzlib" },
{ 2, "lzo1x" },
{ 3, "Header Stripping" }
};
extern const MatroskaTags audioChannels[] = {
{ 1, "Mono" },
{ 2, "Stereo" },
{ 5, "5.1 Surround Sound" },
{ 7, "7.1 Surround Sound" }
};
extern const MatroskaTags displayUnit[] = {
{ 0x0, "Pixels" },
{ 0x1, "cm" },
{ 0x2, "inches" }
};
extern const MatroskaTags encryptionAlgorithm[] = {
{ 0, "Not Encrypted" },
{ 1, "DES" },
{ 2, "3DES" },
{ 3, "Twofish" },
{ 4, "Blowfish" },
{ 5, "AES" }
};
extern const MatroskaTags chapterPhysicalEquivalent[] = {
{ 10, "Index" },
{ 20, "Track" },
{ 30, "Session" },
{ 40, "Layer" },
{ 50, "Side" },
{ 60, "CD / DVD" },
{ 70, "Set / Package" },
};
extern const MatroskaTags encodingType[] = {
{ 0, "Compression" },
{ 1, "Encryption" }
};
extern const MatroskaTags videoScanType[] = {
{ 0, "Progressive" },
{ 1, "Interlaced" }
};
extern const MatroskaTags chapterTranslateCodec[] = {
{ 0, "Matroska Script" },
{ 1, "DVD Menu" }
};
extern const MatroskaTags aspectRatioType[] = {
{ 0, "Free Resizing" },
{ 1, "Keep Aspect Ratio" },
{ 2, "Fixed" }
};
extern const MatroskaTags contentSignatureAlgorithm[] = {
{ 0, "Not Signed" },
{ 1, "RSA" }
};
extern const MatroskaTags contentSignatureHashAlgorithm[] = {
{ 0, "Not Signed" },
{ 1, "SHA1-160" },
{ 2, "MD5" }
};
extern const MatroskaTags trackEnable[] = {
{ 0x1, "Xmp.video.Enabled" },
{ 0x2, "Xmp.audio.Enabled" },
{ 0x11, "Xmp.video.SubTEnabled" }
};
extern const MatroskaTags defaultOn[] = {
{ 0x1, "Xmp.video.DefaultOn" },
{ 0x2, "Xmp.audio.DefaultOn" },
{ 0x11, "Xmp.video.SubTDefaultOn" }
};
extern const MatroskaTags trackForced[] = {
{ 0x1, "Xmp.video.TrackForced" },
{ 0x2, "Xmp.audio.TrackForced" },
{ 0x11, "Xmp.video.SubTTrackForced" }
};
extern const MatroskaTags trackLacing[] = {
{ 0x1, "Xmp.video.TrackLacing" },
{ 0x2, "Xmp.audio.TrackLacing" },
{ 0x11, "Xmp.video.SubTTrackLacing" }
};
extern const MatroskaTags codecDecodeAll[] = {
{ 0x1, "Xmp.video.CodecDecodeAll" },
{ 0x2, "Xmp.audio.CodecDecodeAll" },
{ 0x11, "Xmp.video.SubTCodecDecodeAll" }
};
extern const MatroskaTags codecDownloadUrl[] = {
{ 0x1, "Xmp.video.CodecDownloadUrl" },
{ 0x2, "Xmp.audio.CodecDownloadUrl" },
{ 0x11, "Xmp.video.SubTCodecDownloadUrl" }
};
extern const MatroskaTags codecSettings[] = {
{ 0x1, "Xmp.video.CodecSettings" },
{ 0x2, "Xmp.audio.CodecSettings" },
{ 0x11, "Xmp.video.SubTCodecSettings" }
};
extern const MatroskaTags trackCodec[] = {
{ 0x1, "Xmp.video.Codec" },
{ 0x2, "Xmp.audio.Compressor" },
{ 0x11, "Xmp.video.SubTCodec" }
};
extern const MatroskaTags trackLanguage[] = {
{ 0x1, "Xmp.video.TrackLang" },
{ 0x2, "Xmp.audio.TrackLang" },
{ 0x11, "Xmp.video.SubTLang" }
};
extern const MatroskaTags codecInfo[] = {
{ 0x1, "Xmp.video.CodecInfo" },
{ 0x2, "Xmp.audio.CodecInfo" },
{ 0x11, "Xmp.video.SubTCodecInfo" }
};
extern const MatroskaTags streamRate[] = {
{ 0x1, "Xmp.video.FrameRate" },
{ 0x2, "Xmp.audio.DefaultDuration" }
};
/*!
@brief Function used to calculate Tags, Tags may comprise of more than
one byte. The first byte calculates size of the Tag and the remaining
bytes are used to calculate the rest of the Tag.
Returns Tag Value.
*/
uint64_t returnTagValue(const byte* buf, long size)
{
assert(size > 0 && size <= 8);
uint64_t b0 = buf[0] & (0xff >> size);
uint64_t tag = b0 << ((size - 1) * 8);
for (long i = 1; i < size; ++i) {
tag |= static_cast<uint64_t>(buf[i]) << ((size - i - 1) * 8);
}
return tag;
}
/*!
@brief Function used to convert buffer data into numerical information,
information stored in BigEndian format
*/
int64_t returnValue(const byte* buf, long size)
{
int64_t temp = 0;
for(int i = size-1; i >= 0; i--) {
temp = temp + static_cast<int64_t>(buf[i]*(pow(256.0, (double)size-i-1)));
}
// Todo: remove debug output
// std::cerr << "size = " << size << ", val = " << temp << std::hex << " (0x" << temp << std::dec << ")";
uint64_t ret = 0;
for (long i = 0; i < size; ++i) {
ret |= static_cast<uint64_t>(buf[i]) << ((size - i - 1) * 8);
}
// Todo: remove debug output
// std::cerr << ", ret = " << ret << std::hex << " (0x" << ret << std::dec << ")\n";
return ret;
}
}} // namespace Internal, Exiv2
namespace Exiv2 {
using namespace Exiv2::Internal;
MatroskaVideo::MatroskaVideo(BasicIo::AutoPtr io)
: Image(ImageType::mkv, mdNone, io)
{
} // MatroskaVideo::MatroskaVideo
std::string MatroskaVideo::mimeType() const
{
return "video/matroska";
}
void MatroskaVideo::writeMetadata()
{
}
void MatroskaVideo::readMetadata()
{
if (io_->open() != 0) throw Error(kerDataSourceOpenFailed, io_->path(), strError());
// Ensure that this is the correct image type
if (!isMkvType(*io_, false)) {
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData);
throw Error(kerNotAnImage, "Matroska");
}
IoCloser closer(*io_);
clearMetadata();
continueTraversing_ = true;
height_ = width_ = 1;
xmpData_["Xmp.video.FileName"] = io_->path();
xmpData_["Xmp.video.FileSize"] = (double)io_->size()/(double)1048576;
xmpData_["Xmp.video.MimeType"] = mimeType();
while (continueTraversing_) decodeBlock();
aspectRatio();
} // MatroskaVideo::readMetadata
void MatroskaVideo::decodeBlock()
{
byte buf[8];
io_->read(buf, 1);
if(io_->eof()) {
continueTraversing_ = false;
return;
}
uint32_t sz = findBlockSize(buf[0]); // 0-8
if (sz > 0) io_->read(buf + 1, sz - 1);
const MatroskaTags* mt = find(matroskaTags, returnTagValue(buf, sz));
if ( !mt ) {
continueTraversing_ = false;
return;
}
if(mt->val_ == 0xc53bb6b || mt->val_ == 0xf43b675) {
continueTraversing_ = false;
return;
}
bool skip = find(compositeTagsList, mt->val_) != 0;
bool ignore = find(ignoredTagsList, mt->val_) != 0;
io_->read(buf, 1);
sz = findBlockSize(buf[0]); // 0-8
if (sz > 0) io_->read(buf + 1, sz - 1);
uint64_t size = returnTagValue(buf, sz);
if (skip && !ignore) return;
const uint64_t bufMinSize = 200;
#ifndef SUPPRESS_WARNINGS
if (!ignore && size > bufMinSize) {
EXV_WARNING << "Size " << size << " of Matroska tag 0x"
<< std::hex << mt->val_ << std::dec
<< " is greater than " << bufMinSize << ": ignoring it.\n";
}
#endif
if (ignore || size > bufMinSize) {
io_->seek(size, BasicIo::cur);
return;
}
DataBuf buf2(bufMinSize+1);
std::memset(buf2.pData_, 0x0, buf2.size_);
long s = static_cast<long>(size) ;
io_->read(buf2.pData_,s);
contentManagement(mt, buf2.pData_,s);
} // MatroskaVideo::decodeBlock
void MatroskaVideo::contentManagement(const MatroskaTags* mt, const byte* buf, long size)
{
int64_t duration_in_ms = 0;
static double time_code_scale = 1.0, temp = 0;
static long stream = 0, track_count = 0;
char str[4] = "No";
const MatroskaTags* internalMt = 0;
switch (mt->val_) {
case 0x0282: case 0x0d80: case 0x1741: case 0x3ba9: case 0x066e: case 0x0660:
case 0x065c: case 0x067e: case 0x047a: case 0x0487: case 0x05a3: case 0x136e:
case 0x23ca: case 0xeb524:
xmpData_[mt->label_] = buf;
break;
case 0x0030: case 0x003a: case 0x0287: case 0x14b0: case 0x14ba: case 0x285:
case 0x06ae: case 0x0286: case 0x02f7: case 0x2264: case 0x14aa: case 0x14bb:
case 0x14cc: case 0x14dd:
xmpData_[mt->label_] = returnValue(buf, size);
if (mt->val_ == 0x0030 || mt->val_ == 0x14b0) {
width_ = returnValue(buf, size);
}
else if (mt->val_ == 0x003a || mt->val_ == 0x14ba) {
height_ = returnValue(buf, size);
}
break;
case 0x001a: case 0x001f: case 0x0254: case 0x07e1: case 0x07e5: case 0x07e6:
case 0x1033: case 0x14b2: case 0x14b3: case 0x23c3: case 0x29bf: case 0x3e8a:
case 0x3e9a:
switch (mt->val_) {
case 0x001a: internalMt = find(videoScanType, returnValue(buf, size)); break;
case 0x001f: internalMt = find(audioChannels, returnValue(buf, size)); break;
case 0x0254: internalMt = find(compressionAlgorithm, returnValue(buf, size)); break;
case 0x07e1: internalMt = find(encryptionAlgorithm, returnValue(buf, size)); break;
case 0x1033: internalMt = find(encodingType, returnValue(buf, size)); break;
case 0x3e8a:
case 0x07e5: internalMt = find(contentSignatureAlgorithm, returnValue(buf, size)); break;
case 0x3e9a:
case 0x07e6: internalMt = find(contentSignatureHashAlgorithm, returnValue(buf, size)); break;
case 0x14b2: internalMt = find(displayUnit, returnValue(buf, size)); break;
case 0x14b3: internalMt = find(aspectRatioType, returnValue(buf, size)); break;
case 0x23c3: internalMt = find(chapterPhysicalEquivalent, returnValue(buf, size)); break;
case 0x29bf: internalMt = find(chapterTranslateCodec, returnValue(buf, size)); break;
}
if (internalMt) xmpData_[mt->label_] = internalMt->label_;
break;
case 0x0035: case 0x38b5:
xmpData_[mt->label_] = getFloat(buf, bigEndian);
break;
case 0x0039: case 0x0008: case 0x15aa: case 0x001c: case 0x002a: case 0x1a9697:
case 0x0484:
if (returnValue(buf, size)) strcpy(str, "Yes");
switch (mt->val_) {
case 0x0039: internalMt = find(trackEnable, stream); break;
case 0x0008: internalMt = find(defaultOn, stream); break;
case 0x15aa: internalMt = find(trackForced, stream); break;
case 0x001c: internalMt = find(trackLacing, stream); break;
case 0x002a: internalMt = find(codecDecodeAll, stream); break;
case 0x1a9697: internalMt = find(codecSettings, stream); break;
case 0x0484: internalMt = mt; break;
}
if (internalMt) xmpData_[internalMt->label_] = str;
break;
case 0x0006: case 0x2b59c: case 0x58688: case 0x6b240: case 0x1b4040:
switch (mt->val_) {
case 0x0006: internalMt = find(trackCodec, stream); break;
case 0x2b59c: internalMt = find(trackLanguage, stream); break;
case 0x58688: internalMt = find(codecInfo, stream); break;
case 0x6b240:
case 0x1b4040: internalMt = find(codecDownloadUrl, stream); break;
}
if (internalMt) xmpData_[internalMt->label_] = buf;
break;
case 0x0489: case 0x0461:
switch (mt->val_) {
case 0x0489:
if(size <= 4) {
duration_in_ms = static_cast<int64_t>(getFloat(buf, bigEndian) * static_cast<float>(time_code_scale) * 1000.0f);
}
else {
duration_in_ms = static_cast<int64_t>(getDouble(buf, bigEndian) * time_code_scale * 1000);
}
break;
case 0x0461: {
duration_in_ms = returnValue(buf, size)/1000000000; break;
}
}
xmpData_[mt->label_] = duration_in_ms;
break;
case 0x0057:
track_count++;
xmpData_["Xmp.video.TotalStream"] = track_count;
break;
case 0xad7b1:
time_code_scale = (double)returnValue(buf, size)/(double)1000000000;
xmpData_["Xmp.video.TimecodeScale"] = time_code_scale;
break;
case 0x0003:
internalMt = find(matroskaTrackType, returnValue(buf, size));
stream = static_cast<long>(internalMt->val_);
break;
case 0x3e383: case 0x383e3:
internalMt = find(streamRate, stream);
if (returnValue(buf, size)) {
switch (stream) {
case 1: temp = (double)1000000000/(double)returnValue(buf, size); break;
case 2: temp = static_cast<double>(returnValue(buf, size) / 1000); break;
}
if (internalMt) xmpData_[internalMt->label_] = temp;
}
else
if (internalMt) xmpData_[internalMt->label_] = "Variable Bit Rate";
break;
default:
break;
}
} // MatroskaVideo::contentManagement
void MatroskaVideo::aspectRatio()
{
//TODO - Make a better unified method to handle all cases of Aspect Ratio
double aspectRatio = (double)width_ / (double)height_;
aspectRatio = floor(aspectRatio*10) / 10;
xmpData_["Xmp.video.AspectRatio"] = aspectRatio;
int aR = (int) ((aspectRatio*10.0)+0.1);
switch (aR) {
case 13 : xmpData_["Xmp.video.AspectRatio"] = "4:3" ; break;
case 17 : xmpData_["Xmp.video.AspectRatio"] = "16:9" ; break;
case 10 : xmpData_["Xmp.video.AspectRatio"] = "1:1" ; break;
case 16 : xmpData_["Xmp.video.AspectRatio"] = "16:10" ; break;
case 22 : xmpData_["Xmp.video.AspectRatio"] = "2.21:1" ; break;
case 23 : xmpData_["Xmp.video.AspectRatio"] = "2.35:1" ; break;
case 12 : xmpData_["Xmp.video.AspectRatio"] = "5:4" ; break;
default : xmpData_["Xmp.video.AspectRatio"] = aspectRatio;break;
}
} // MatroskaVideo::aspectRatio
uint32_t MatroskaVideo::findBlockSize(byte b)
{
if (b & 128) return 1;
else if (b & 64) return 2;
else if (b & 32) return 3;
else if (b & 16) return 4;
else if (b & 8) return 5;
else if (b & 4) return 6;
else if (b & 2) return 7;
else if (b & 1) return 8;
else return 0;
} // MatroskaVideo::findBlockSize
Image::AutoPtr newMkvInstance(BasicIo::AutoPtr io, bool /*create*/)
{
Image::AutoPtr image(new MatroskaVideo(io));
if (!image->good()) {
image.reset();
}
return image;
}
bool isMkvType(BasicIo& iIo, bool advance)
{
bool result = true;
byte tmpBuf[4];
iIo.read(tmpBuf, 4);
if (iIo.error() || iIo.eof()) return false;
if (0x1a != tmpBuf[0] || 0x45 != tmpBuf[1] || 0xdf != tmpBuf[2] || 0xa3 != tmpBuf[3]) {
result = false;
}
if (!advance || !result ) iIo.seek(0, BasicIo::beg);
return result;
}
} // namespace Exiv2
#endif // EXV_ENABLE_VIDEO
Loading…
Cancel
Save