#813: More Matroska polishing (work-in-progress).

v0.27.3
Andreas Huggel 13 years ago
parent c6bdee1743
commit 245285f9b1

@ -39,6 +39,7 @@ EXIV2_RCSID("@(#) $Id$")
// + standard includes // + standard includes
#include <cmath> #include <cmath>
#include <cassert>
// ***************************************************************************** // *****************************************************************************
// class member definitions // class member definitions
@ -46,7 +47,7 @@ namespace Exiv2 {
namespace Internal { namespace Internal {
//! List of composite tags. They are skipped and the child tags are read immediately //! List of composite tags. They are skipped and the child tags are read immediately
uint32_t compositeTagsList[] = { uint64_t compositeTagsList[] = {
0x0000, 0x000e, 0x000f, 0x0020, 0x0026, 0x002e, 0x0036, 0x0000, 0x000e, 0x000f, 0x0020, 0x0026, 0x002e, 0x0036,
0x0037, 0x003b, 0x005b, 0x0060, 0x0061, 0x0068, 0x05b9, 0x0037, 0x003b, 0x005b, 0x0060, 0x0061, 0x0068, 0x05b9,
0x0dbb, 0x1034, 0x1035, 0x1854, 0x21a7, 0x2240, 0x23c0, 0x0dbb, 0x1034, 0x1035, 0x1854, 0x21a7, 0x2240, 0x23c0,
@ -57,7 +58,7 @@ namespace Exiv2 {
}; };
//! List of tags which are ignored, i.e., tag and value won't be read //! List of tags which are ignored, i.e., tag and value won't be read
uint32_t ignoredTagsList[] = { uint64_t ignoredTagsList[] = {
0x0021, 0x0023, 0x0033, 0x0071, 0x0077, 0x006c, 0x0067, 0x007b, 0x02f2, 0x02f3, 0x0021, 0x0023, 0x0033, 0x0071, 0x0077, 0x006c, 0x0067, 0x007b, 0x02f2, 0x02f3,
0x1031, 0x1032, 0x13ab, 0x13ac, 0x15ee, 0x23a2, 0x23c6, 0x2e67, 0x33a4, 0x33c5, 0x1031, 0x1032, 0x13ab, 0x13ac, 0x15ee, 0x23a2, 0x23c6, 0x2e67, 0x33a4, 0x33c5,
0x3446, 0x2de7, 0x2df8, 0x26bf, 0x28ca, 0x3384, 0x13b8, 0x037e, 0x0485, 0x18d7, 0x3446, 0x2de7, 0x2df8, 0x26bf, 0x28ca, 0x3384, 0x13b8, 0x037e, 0x0485, 0x18d7,
@ -80,7 +81,7 @@ namespace Exiv2 {
u -- Tag used directly for storing metadata u -- Tag used directly for storing metadata
ui -- Tag used only internally ui -- Tag used only internally
*/ */
extern const TagDetails matroskaTags[] = { extern const MatroskaTags matroskaTags[] = {
{ 0x0000, "ChapterDisplay" }, //s { 0x0000, "ChapterDisplay" }, //s
{ 0x0003, "TrackType" }, //ui { 0x0003, "TrackType" }, //ui
{ 0x0005, "ChapterString" }, //sd { 0x0005, "ChapterString" }, //sd
@ -281,7 +282,7 @@ namespace Exiv2 {
{ 0xf43b675, "Cluster" }, //s { 0xf43b675, "Cluster" }, //s
}; };
extern const TagDetails matroskaTrackType[] = { extern const MatroskaTags matroskaTrackType[] = {
{ 0x1, "Video" }, { 0x1, "Video" },
{ 0x2, "Audio" }, { 0x2, "Audio" },
{ 0x3, "Complex" }, { 0x3, "Complex" },
@ -291,27 +292,27 @@ namespace Exiv2 {
{ 0x20, "Control" } { 0x20, "Control" }
}; };
extern const TagDetails compressionAlgorithm[] = { extern const MatroskaTags compressionAlgorithm[] = {
{ 0, "zlib " }, { 0, "zlib " },
{ 1, "bzlib" }, { 1, "bzlib" },
{ 2, "lzo1x" }, { 2, "lzo1x" },
{ 3, "Header Stripping" } { 3, "Header Stripping" }
}; };
extern const TagDetails audioChannels[] = { extern const MatroskaTags audioChannels[] = {
{ 1, "Mono" }, { 1, "Mono" },
{ 2, "Stereo" }, { 2, "Stereo" },
{ 5, "5.1 Surround Sound" }, { 5, "5.1 Surround Sound" },
{ 7, "7.1 Surround Sound" } { 7, "7.1 Surround Sound" }
}; };
extern const TagDetails displayUnit[] = { extern const MatroskaTags displayUnit[] = {
{ 0x0, "Pixels" }, { 0x0, "Pixels" },
{ 0x1, "cm" }, { 0x1, "cm" },
{ 0x2, "inches" } { 0x2, "inches" }
}; };
extern const TagDetails encryptionAlgorithm[] = { extern const MatroskaTags encryptionAlgorithm[] = {
{ 0, "Not Encrypted" }, { 0, "Not Encrypted" },
{ 1, "DES" }, { 1, "DES" },
{ 2, "3DES" }, { 2, "3DES" },
@ -320,7 +321,7 @@ namespace Exiv2 {
{ 5, "AES" } { 5, "AES" }
}; };
extern const TagDetails chapterPhysicalEquivalent[] = { extern const MatroskaTags chapterPhysicalEquivalent[] = {
{ 10, "Index" }, { 10, "Index" },
{ 20, "Track" }, { 20, "Track" },
{ 30, "Session" }, { 30, "Session" },
@ -330,129 +331,134 @@ namespace Exiv2 {
{ 70, "Set / Package" }, { 70, "Set / Package" },
}; };
extern const TagDetails encodingType[] = { extern const MatroskaTags encodingType[] = {
{ 0, "Compression" }, { 0, "Compression" },
{ 1, "Encryption" } { 1, "Encryption" }
}; };
extern const TagDetails videoScanType[] = { extern const MatroskaTags videoScanType[] = {
{ 0, "Progressive" }, { 0, "Progressive" },
{ 1, "Interlaced" } { 1, "Interlaced" }
}; };
extern const TagDetails chapterTranslateCodec[] = { extern const MatroskaTags chapterTranslateCodec[] = {
{ 0, "Matroska Script" }, { 0, "Matroska Script" },
{ 1, "DVD Menu" } { 1, "DVD Menu" }
}; };
extern const TagDetails aspectRatioType[] = { extern const MatroskaTags aspectRatioType[] = {
{ 0, "Free Resizing" }, { 0, "Free Resizing" },
{ 1, "Keep Aspect Ratio" }, { 1, "Keep Aspect Ratio" },
{ 2, "Fixed" } { 2, "Fixed" }
}; };
extern const TagDetails contentSignatureAlgorithm[] = { extern const MatroskaTags contentSignatureAlgorithm[] = {
{ 0, "Not Signed" }, { 0, "Not Signed" },
{ 1, "RSA" } { 1, "RSA" }
}; };
extern const TagDetails contentSignatureHashAlgorithm[] = { extern const MatroskaTags contentSignatureHashAlgorithm[] = {
{ 0, "Not Signed" }, { 0, "Not Signed" },
{ 1, "SHA1-160" }, { 1, "SHA1-160" },
{ 2, "MD5" } { 2, "MD5" }
}; };
extern const TagDetails trackEnable[] = { extern const MatroskaTags trackEnable[] = {
{ 0x1, "Xmp.video.Enabled" }, { 0x1, "Xmp.video.Enabled" },
{ 0x2, "Xmp.audio.Enabled" }, { 0x2, "Xmp.audio.Enabled" },
{ 0x11, "Xmp.video.SubTEnabled" } { 0x11, "Xmp.video.SubTEnabled" }
}; };
extern const TagDetails defaultOn[] = { extern const MatroskaTags defaultOn[] = {
{ 0x1, "Xmp.video.DefaultOn" }, { 0x1, "Xmp.video.DefaultOn" },
{ 0x2, "Xmp.audio.DefaultOn" }, { 0x2, "Xmp.audio.DefaultOn" },
{ 0x11, "Xmp.video.SubTDefaultOn" } { 0x11, "Xmp.video.SubTDefaultOn" }
}; };
extern const TagDetails trackForced[] = { extern const MatroskaTags trackForced[] = {
{ 0x1, "Xmp.video.TrackForced" }, { 0x1, "Xmp.video.TrackForced" },
{ 0x2, "Xmp.audio.TrackForced" }, { 0x2, "Xmp.audio.TrackForced" },
{ 0x11, "Xmp.video.SubTTrackForced" } { 0x11, "Xmp.video.SubTTrackForced" }
}; };
extern const TagDetails trackLacing[] = { extern const MatroskaTags trackLacing[] = {
{ 0x1, "Xmp.video.TrackLacing" }, { 0x1, "Xmp.video.TrackLacing" },
{ 0x2, "Xmp.audio.TrackLacing" }, { 0x2, "Xmp.audio.TrackLacing" },
{ 0x11, "Xmp.video.SubTTrackLacing" } { 0x11, "Xmp.video.SubTTrackLacing" }
}; };
extern const TagDetails codecDecodeAll[] = { extern const MatroskaTags codecDecodeAll[] = {
{ 0x1, "Xmp.video.CodecDecodeAll" }, { 0x1, "Xmp.video.CodecDecodeAll" },
{ 0x2, "Xmp.audio.CodecDecodeAll" }, { 0x2, "Xmp.audio.CodecDecodeAll" },
{ 0x11, "Xmp.video.SubTCodecDecodeAll" } { 0x11, "Xmp.video.SubTCodecDecodeAll" }
}; };
extern const TagDetails codecDownloadUrl[] = { extern const MatroskaTags codecDownloadUrl[] = {
{ 0x1, "Xmp.video.CodecDownloadUrl" }, { 0x1, "Xmp.video.CodecDownloadUrl" },
{ 0x2, "Xmp.audio.CodecDownloadUrl" }, { 0x2, "Xmp.audio.CodecDownloadUrl" },
{ 0x11, "Xmp.video.SubTCodecDownloadUrl" } { 0x11, "Xmp.video.SubTCodecDownloadUrl" }
}; };
extern const TagDetails codecSettings[] = { extern const MatroskaTags codecSettings[] = {
{ 0x1, "Xmp.video.CodecSettings" }, { 0x1, "Xmp.video.CodecSettings" },
{ 0x2, "Xmp.audio.CodecSettings" }, { 0x2, "Xmp.audio.CodecSettings" },
{ 0x11, "Xmp.video.SubTCodecSettings" } { 0x11, "Xmp.video.SubTCodecSettings" }
}; };
extern const TagDetails trackCodec[] = { extern const MatroskaTags trackCodec[] = {
{ 0x1, "Xmp.video.Codec" }, { 0x1, "Xmp.video.Codec" },
{ 0x2, "Xmp.audio.Compressor" }, { 0x2, "Xmp.audio.Compressor" },
{ 0x11, "Xmp.video.SubTCodec" } { 0x11, "Xmp.video.SubTCodec" }
}; };
extern const TagDetails trackLanguage[] = { extern const MatroskaTags trackLanguage[] = {
{ 0x1, "Xmp.video.TrackLang" }, { 0x1, "Xmp.video.TrackLang" },
{ 0x2, "Xmp.audio.TrackLang" }, { 0x2, "Xmp.audio.TrackLang" },
{ 0x11, "Xmp.video.SubTLang" } { 0x11, "Xmp.video.SubTLang" }
}; };
extern const TagDetails codecInfo[] = { extern const MatroskaTags codecInfo[] = {
{ 0x1, "Xmp.video.CodecInfo" }, { 0x1, "Xmp.video.CodecInfo" },
{ 0x2, "Xmp.audio.CodecInfo" }, { 0x2, "Xmp.audio.CodecInfo" },
{ 0x11, "Xmp.video.SubTCodecInfo" } { 0x11, "Xmp.video.SubTCodecInfo" }
}; };
extern const TagDetails streamRate[] = { extern const MatroskaTags streamRate[] = {
{ 0x1, "Xmp.video.FrameRate" }, { 0x1, "Xmp.video.FrameRate" },
{ 0x2, "Xmp.audio.DefaultDuration" } { 0x2, "Xmp.audio.DefaultDuration" }
}; };
/*! /*!
@brief Function used to calulate Tags, Tags may comprise of more than @brief Function used to calculate Tags, Tags may comprise of more than
one byte, that is why two buffers are to be provided. one byte. The first byte calculates size of the Tag and the remaining
The first buffer calculates size of the Tag and the second buffer bytes are used to calculate the rest of the Tag.
is used to calculate the rest of the Tag. Returns Tag Value.
Returns Tag Value in unsinged long.
*/ */
unsigned long returnTagValue(byte b, Exiv2::DataBuf& buf2, int n ) { uint64_t returnTagValue(byte* buf, uint size)
long temp = 0; {
long reg1 = 0; assert(size > 0 && size <= 8);
reg1 = (b & (int)(pow(2,8-n)-1));
for(int i = n-2; i >= 0; i--) { byte b0 = buf[0] & (0xff >> size);
temp = temp + buf2.pData_[i]*(pow(256,n-i-2)); uint64_t ret = b0 << ((size - 1) * 8);
} for (uint i = 1; i < size; ++i) ret |= buf[i] << ((size - i - 1) * 8);
temp += reg1 * pow(256,n-1); return ret;
return temp;
} }
//! Function used to convert buffer data into numerical information, information stored in BigEndian format /*!
int64_t returnValue(Exiv2::DataBuf& buf, int n ) { @brief Function used to convert buffer data into numerical information,
information stored in BigEndian format
*/
int64_t returnValue(DataBuf& buf, int n)
{
int64_t temp = 0; int64_t temp = 0;
for(int i = n-1; i >= 0; i--) { for(int i = n-1; i >= 0; i--) {
temp = temp + buf.pData_[i]*(pow(256,n-i-1)); temp = temp + buf.pData_[i]*(pow(256,n-i-1));
} }
std::cerr << "n = " << n << ", val = " << temp << std::hex << " (0x" << temp << std::dec << ")\n";
return temp; return temp;
} }
@ -501,142 +507,140 @@ namespace Exiv2 {
void MatroskaVideo::decodeBlock() void MatroskaVideo::decodeBlock()
{ {
const long bufMinSize = 200; byte buf[8];
DataBuf buf2(bufMinSize); io_->read(buf, 1);
byte b;
io_->read(&b, 1);
if(io_->eof()) { if(io_->eof()) {
continueTraversing_ = false; continueTraversing_ = false;
return; return;
} }
long sz = findBlockSize(b); uint sz = findBlockSize(buf[0]); // 0-8
if (sz > 0) io_->read(buf2.pData_, sz - 1); if (sz > 0) io_->read(buf + 1, sz - 1);
const TagDetails* td; const MatroskaTags* mt = find(matroskaTags, returnTagValue(buf, sz));
td = find(matroskaTags, returnTagValue(b, buf2, sz));
if(td->val_ == 0xc53bb6b || td->val_ == 0xf43b675) { if(mt->val_ == 0xc53bb6b || mt->val_ == 0xf43b675) {
continueTraversing_ = false; continueTraversing_ = false;
return; return;
} }
bool skip = find(compositeTagsList, (uint32_t)td->val_); bool skip = find(compositeTagsList, mt->val_);
bool ignore = find(ignoredTagsList, (uint32_t)td->val_); bool ignore = find(ignoredTagsList, mt->val_);
io_->read(&b, 1); io_->read(buf, 1);
sz = findBlockSize(b); sz = findBlockSize(buf[0]); // 0-8
if (sz > 0) io_->read(buf2.pData_, sz - 1); if (sz > 0) io_->read(buf + 1, sz - 1);
long size = returnTagValue(b, buf2, sz); uint64_t size = returnTagValue(buf, sz);
if (skip && !ignore) return; if (skip && !ignore) return;
const uint64_t bufMinSize = 200;
if (ignore || size > bufMinSize) { if (ignore || size > bufMinSize) {
io_->seek(size, BasicIo::cur); io_->seek(size, BasicIo::cur);
return; return;
} }
DataBuf buf(bufMinSize); DataBuf buf2(bufMinSize);
std::memset(buf.pData_, 0x0, buf.size_); std::memset(buf2.pData_, 0x0, buf2.size_);
io_->read(buf.pData_, size); io_->read(buf2.pData_, size);
contentManagement(td, buf, size); contentManagement(mt, buf2, size);
} // MatroskaVideo::decodeBlock } // MatroskaVideo::decodeBlock
void MatroskaVideo::contentManagement(const TagDetails* td, Exiv2::DataBuf& buf, long size) void MatroskaVideo::contentManagement(const MatroskaTags* mt, DataBuf& buf, long size)
{ {
int64_t duration_in_ms = 0; int64_t duration_in_ms = 0;
static double time_code_scale = 1.0, temp = 0; static double time_code_scale = 1.0, temp = 0;
static long stream = 0, track_count = 0; static long stream = 0, track_count = 0;
char str[4] = "No"; char str[4] = "No";
const TagDetails* internal_td = NULL; const MatroskaTags* internalMt = 0;
switch (td->val_) { switch (mt->val_) {
case 0x0282: case 0x0d80: case 0x1741: case 0x3ba9: case 0x066e: case 0x0660: 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 0x065c: case 0x067e: case 0x047a: case 0x0487: case 0x05a3: case 0x136e:
case 0x23ca: case 0xeb524: case 0x23ca: case 0xeb524:
xmpData_[exvGettext(td->label_)] = buf.pData_; xmpData_[mt->label_] = buf.pData_;
break; break;
case 0x0030: case 0x003a: case 0x0287: case 0x14b0: case 0x14ba: case 0x285: 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 0x06ae: case 0x0286: case 0x02f7: case 0x2264: case 0x14aa: case 0x14bb:
case 0x14cc: case 0x14dd: case 0x14cc: case 0x14dd:
xmpData_[exvGettext(td->label_)] = returnValue(buf, size); xmpData_[mt->label_] = returnValue(buf, size);
if(td->val_ == 0x0030 || td->val_ == 0x14b0) if (mt->val_ == 0x0030 || mt->val_ == 0x14b0) {
width_ = returnValue(buf, size); width_ = returnValue(buf, size);
else if(td->val_ == 0x003a || td->val_ == 0x14ba) }
else if (mt->val_ == 0x003a || mt->val_ == 0x14ba) {
height_ = returnValue(buf, size); height_ = returnValue(buf, size);
}
break; break;
case 0x001a: case 0x001f: case 0x0254: case 0x07e1: case 0x07e5: case 0x07e6: 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 0x1033: case 0x14b2: case 0x14b3: case 0x23c3: case 0x29bf: case 0x3e8a:
case 0x3e9a: case 0x3e9a:
switch (td->val_) { switch (mt->val_) {
case 0x001a: internal_td = find(videoScanType, returnValue(buf, size)); break; case 0x001a: internalMt = find(videoScanType, returnValue(buf, size)); break;
case 0x001f: internal_td = find(audioChannels, returnValue(buf, size)); break; case 0x001f: internalMt = find(audioChannels, returnValue(buf, size)); break;
case 0x0254: internal_td = find(compressionAlgorithm, returnValue(buf, size)); break; case 0x0254: internalMt = find(compressionAlgorithm, returnValue(buf, size)); break;
case 0x07e1: internal_td = find(encryptionAlgorithm, returnValue(buf, size)); break; case 0x07e1: internalMt = find(encryptionAlgorithm, returnValue(buf, size)); break;
case 0x1033: internal_td = find(encodingType, returnValue(buf, size)); break; case 0x1033: internalMt = find(encodingType, returnValue(buf, size)); break;
case 0x3e8a: case 0x3e8a:
case 0x07e5: internal_td = find(contentSignatureAlgorithm, returnValue(buf, size)); break; case 0x07e5: internalMt = find(contentSignatureAlgorithm, returnValue(buf, size)); break;
case 0x3e9a: case 0x3e9a:
case 0x07e6: internal_td = find(contentSignatureHashAlgorithm, returnValue(buf, size)); break; case 0x07e6: internalMt = find(contentSignatureHashAlgorithm, returnValue(buf, size)); break;
case 0x14b2: internal_td = find(displayUnit, returnValue(buf, size)); break; case 0x14b2: internalMt = find(displayUnit, returnValue(buf, size)); break;
case 0x14b3: internal_td = find(aspectRatioType, returnValue(buf, size)); break; case 0x14b3: internalMt = find(aspectRatioType, returnValue(buf, size)); break;
case 0x23c3: internal_td = find(chapterPhysicalEquivalent, returnValue(buf, size)); break; case 0x23c3: internalMt = find(chapterPhysicalEquivalent, returnValue(buf, size)); break;
case 0x29bf: internal_td = find(chapterTranslateCodec, returnValue(buf, size)); break; case 0x29bf: internalMt = find(chapterTranslateCodec, returnValue(buf, size)); break;
} }
if(internal_td) if (internalMt) xmpData_[mt->label_] = internalMt->label_;
xmpData_[exvGettext(td->label_)] = exvGettext(internal_td->label_);
break; break;
case 0x0035: case 0x38b5: case 0x0035: case 0x38b5:
xmpData_[exvGettext(td->label_)] = Exiv2::getFloat(buf.pData_, bigEndian); xmpData_[mt->label_] = getFloat(buf.pData_, bigEndian);
break; break;
case 0x0039: case 0x0008: case 0x15aa: case 0x001c: case 0x002a: case 0x1a9697: case 0x0039: case 0x0008: case 0x15aa: case 0x001c: case 0x002a: case 0x1a9697:
case 0x0484: case 0x0484:
if (returnValue(buf, size)) strcpy(str, "Yes"); if (returnValue(buf, size)) strcpy(str, "Yes");
switch (td->val_) { switch (mt->val_) {
case 0x0039: internal_td = find(trackEnable, stream); break; case 0x0039: internalMt = find(trackEnable, stream); break;
case 0x0008: internal_td = find(defaultOn, stream); break; case 0x0008: internalMt = find(defaultOn, stream); break;
case 0x15aa: internal_td = find(trackForced, stream); break; case 0x15aa: internalMt = find(trackForced, stream); break;
case 0x001c: internal_td = find(trackLacing, stream); break; case 0x001c: internalMt = find(trackLacing, stream); break;
case 0x002a: internal_td = find(codecDecodeAll, stream); break; case 0x002a: internalMt = find(codecDecodeAll, stream); break;
case 0x1a9697: internal_td = find(codecSettings, stream); break; case 0x1a9697: internalMt = find(codecSettings, stream); break;
case 0x0484: internal_td = td; break; case 0x0484: internalMt = mt; break;
} }
if (internal_td) xmpData_[exvGettext(internal_td->label_)] = str; if (internalMt) xmpData_[internalMt->label_] = str;
break; break;
case 0x0006: case 0x2b59c: case 0x58688: case 0x6b240: case 0x1b4040: case 0x0006: case 0x2b59c: case 0x58688: case 0x6b240: case 0x1b4040:
switch (td->val_) { switch (mt->val_) {
case 0x0006: internal_td = find(trackCodec, stream); break; case 0x0006: internalMt = find(trackCodec, stream); break;
case 0x2b59c: internal_td = find(trackLanguage, stream); break; case 0x2b59c: internalMt = find(trackLanguage, stream); break;
case 0x58688: internal_td = find(codecInfo, stream); break; case 0x58688: internalMt = find(codecInfo, stream); break;
case 0x6b240: case 0x6b240:
case 0x1b4040: internal_td = find(codecDownloadUrl, stream); break; case 0x1b4040: internalMt = find(codecDownloadUrl, stream); break;
} }
if (internal_td) xmpData_[exvGettext(internal_td->label_)] = buf.pData_; if (internalMt) xmpData_[internalMt->label_] = buf.pData_;
break; break;
case 0x0489: case 0x0461: case 0x0489: case 0x0461:
switch (td->val_) { switch (mt->val_) {
case 0x0489: case 0x0489:
if(size <= 4) { if(size <= 4) {
duration_in_ms = Exiv2::getFloat(buf.pData_, bigEndian) * time_code_scale * 1000; duration_in_ms = getFloat(buf.pData_, bigEndian) * time_code_scale * 1000;
} }
else { else {
duration_in_ms = Exiv2::getDouble(buf.pData_, bigEndian) * time_code_scale * 1000; duration_in_ms = getDouble(buf.pData_, bigEndian) * time_code_scale * 1000;
} }
break; break;
case 0x0461: duration_in_ms = returnValue(buf, size)/1000000000; break; case 0x0461: duration_in_ms = returnValue(buf, size)/1000000000; break;
} }
xmpData_[exvGettext(td->label_)] = duration_in_ms; xmpData_[mt->label_] = duration_in_ms;
break; break;
case 0x0057: case 0x0057:
@ -650,21 +654,21 @@ namespace Exiv2 {
break; break;
case 0x0003: case 0x0003:
internal_td = find(matroskaTrackType, returnValue(buf, size)); internalMt = find(matroskaTrackType, returnValue(buf, size));
stream = internal_td->val_; stream = internalMt->val_;
break; break;
case 0x3e383: case 0x383e3: case 0x3e383: case 0x383e3:
internal_td = find(streamRate, stream); internalMt = find(streamRate, stream);
if (returnValue(buf, size)) { if (returnValue(buf, size)) {
switch (stream) { switch (stream) {
case 1: temp = (double)1000000000/(double)returnValue(buf, size); break; case 1: temp = (double)1000000000/(double)returnValue(buf, size); break;
case 2: temp = returnValue(buf, size)/1000; break; case 2: temp = returnValue(buf, size)/1000; break;
} }
if (internal_td) xmpData_[exvGettext(internal_td->label_)] = temp; if (internalMt) xmpData_[internalMt->label_] = temp;
} }
else else
if (internal_td) xmpData_[exvGettext(internal_td->label_)] = "Variable Bit Rate"; if (internalMt) xmpData_[internalMt->label_] = "Variable Bit Rate";
break; break;
default: default:
@ -690,7 +694,7 @@ namespace Exiv2 {
else xmpData_["Xmp.video.AspectRatio"] = aspectRatio; else xmpData_["Xmp.video.AspectRatio"] = aspectRatio;
} // MatroskaVideo::aspectRatio } // MatroskaVideo::aspectRatio
long MatroskaVideo::findBlockSize(byte b) uint MatroskaVideo::findBlockSize(byte b)
{ {
if (b & 128) return 1; if (b & 128) return 1;
else if (b & 64) return 2; else if (b & 64) return 2;

@ -47,6 +47,18 @@ namespace Exiv2 {
const int mkv = 21; //!< Treating mkv as an image type> const int mkv = 21; //!< Treating mkv as an image type>
} }
// Todo: Should be hidden
/*!
@brief Helper structure for the Matroska tags lookup table.
*/
struct MatroskaTags {
uint64_t val_; //!< Tag value
const char* label_; //!< Translation of the tag value
//! 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. @brief Class to access Matroska video files.
*/ */
@ -89,7 +101,7 @@ namespace Exiv2 {
@param b The byte, which stores the information to calculate the size @param b The byte, which stores the information to calculate the size
@return Return the size of the block. @return Return the size of the block.
*/ */
long findBlockSize(byte b); uint findBlockSize(byte b);
/*! /*!
@brief Check for a valid tag and decode the block at the current IO position. @brief Check for a valid tag and decode the block at the current IO position.
Calls contentManagement() or skips to next tag, if required. Calls contentManagement() or skips to next tag, if required.
@ -97,11 +109,11 @@ namespace Exiv2 {
void decodeBlock(); void decodeBlock();
/*! /*!
@brief Interpret tag information, and save it in the respective XMP container. @brief Interpret tag information, and save it in the respective XMP container.
@param td Pointer to current tag, @param mt Pointer to current tag,
@param buf Data buffer with the tag information. @param buf Data buffer with the tag information.
@param size Size of buf. @param size Size of buf.
*/ */
void contentManagement(const Exiv2::Internal::TagDetails* td, Exiv2::DataBuf& buf, long size); void contentManagement(const MatroskaTags* mt, DataBuf& buf, long size);
/*! /*!
@brief Calculates Aspect Ratio of a video, and stores it in the @brief Calculates Aspect Ratio of a video, and stores it in the
respective XMP container. respective XMP container.

Loading…
Cancel
Save