improved format detection for MP4 tracks

This commit is contained in:
Martchus 2015-07-13 00:57:38 +02:00
parent 78c23779a6
commit 15a03a0029
9 changed files with 48 additions and 16 deletions

View File

@ -186,6 +186,7 @@ public:
void validateSubsequentElementStructure(NotificationList &gatheredNotifications, uint64 *paddingSize = nullptr);
static constexpr uint32 maximumIdLengthSupported();
static constexpr uint32 maximumSizeLengthSupported();
static constexpr byte minimumElementSize();
void copyHeader(std::ostream &targetStream);
void copyWithoutChilds(std::ostream &targetStream);
void copyEntirely(std::ostream &targetStream);
@ -833,7 +834,7 @@ void GenericFileElement<ImplementationType>::copyInternal(std::ostream &targetSt
template <class ImplementationType>
typename GenericFileElement<ImplementationType>::implementationType *GenericFileElement<ImplementationType>::denoteFirstChild(uint32 relativeFirstChildOffset)
{
if(relativeFirstChildOffset + 4 < dataSize()) {
if(relativeFirstChildOffset + minimumElementSize() <= totalSize()) {
m_firstChild.reset(new implementationType(static_cast<implementationType &>(*this), startOffset() + relativeFirstChildOffset));
} else {
m_firstChild.reset();
@ -859,6 +860,15 @@ inline constexpr uint32 GenericFileElement<ImplementationType>::maximumSizeLengt
return sizeof(dataSizeType);
}
/*!
* \brief Returns the mimimum element size.
*/
template <class ImplementationType>
inline constexpr byte GenericFileElement<ImplementationType>::minimumElementSize()
{
return FileElementTraits<ImplementationType>::minimumElementSize();
}
/*!
* \fn GenericFileElement<ImplementationType>::internalParse()
* \brief This method is called to perform parsing.

View File

@ -196,7 +196,11 @@ const char *MediaFormat::name() const
case GeneralMediaFormat::Smv: return "SMV";
case GeneralMediaFormat::StreamingTextStream: return "Streaming Text Stream";
case GeneralMediaFormat::SynthesizedTextureStream: return "Synthesized Texture Stream";
case GeneralMediaFormat::Systems: return "Systems";
case GeneralMediaFormat::Systems:
switch(sub) {
case 2: return "Systems v2";
default: return "Systems";
}
case GeneralMediaFormat::TextSubtitle:
switch(sub) {
case SubFormats::TextSubBasicUtf8: return "UTF-8 Plain Text subtitles";

View File

@ -57,7 +57,7 @@ void Mp4Atom::internalParse()
{
invalidateStatus();
static const string context("parsing MP4 atom");
if(maxTotalSize() < 8) {
if(maxTotalSize() < minimumElementSize()) {
addNotification(NotificationType::Critical, "Atom is smaller then 8 byte and hence invalid. The maximum size within the parent atom is " + numberToString(maxTotalSize()) + ".", context);
throw TruncatedDataException();
}
@ -95,7 +95,7 @@ void Mp4Atom::internalParse()
m_dataSize -= headerSize();
Mp4Atom *child = nullptr;
if(uint64 firstChildOffset = this->firstChildOffset()) {
if(firstChildOffset + 8 <= totalSize()) {
if(firstChildOffset + minimumElementSize() <= totalSize()) {
child = new Mp4Atom(static_cast<Mp4Atom &>(*this), startOffset() + firstChildOffset);
}
}

View File

@ -44,6 +44,14 @@ public:
* \brief The implementation type is Mp4Atom.
*/
typedef Mp4Atom implementationType;
/*!
* \brief Returns the minimal atom size which is 8 byte.
*/
static constexpr byte minimumElementSize()
{
return 8;
}
};
class LIB_EXPORT Mp4Atom : public GenericFileElement<Mp4Atom>

View File

@ -56,8 +56,7 @@ MediaFormat fourccToMediaFormat(uint32 fourccId)
case Avc1: case Avc2: case Avc3: case Avc4: case H264Decoder1: case H264Decoder2:
case H264Decoder3: case H264Decoder4: case H264Decoder5: case H264Decoder6:
return MediaFormat(GeneralMediaFormat::Avc);
case Divx4Decoder1: case Divx4Decoder2: case Divx4Decoder3:
case Divx4Decoder4: case Divx4Decoder5: case Divx4Decoder6: case Divx4Decoder7:
case Divx4Decoder1: case Divx4Decoder2:
case H263Quicktime: case H2633GPP: case XvidDecoder1: case XvidDecoder2:
case XvidDecoder3: case XvidDecoder4: case XvidDecoder5: case Divx5Decoder:
return MediaFormat(GeneralMediaFormat::Mpeg4Video, SubFormats::Mpeg4AdvancedSimpleProfile0);

View File

@ -246,12 +246,7 @@ enum KnownValue : uint32 {
Divx3Decoder8 = 0x4D503433,
Divx3Decoder9 = 0x4D504733,
Divx4Decoder1 = 0x44495658,
Divx4Decoder2 = 0x4D345332,
Divx4Decoder3 = 0x4D503453,
Divx4Decoder4 = 0x554D5034,
Divx4Decoder5 = 0x64697678,
Divx4Decoder6 = 0x6D347332,
Divx4Decoder7 = 0x6D703473,
Divx4Decoder2 = 0x64697678,
Divx5Decoder = 0x44583530,
Drms = 0x64726D73,
Drmi = 0x64726D69,
@ -324,7 +319,7 @@ enum KnownValue : uint32 {
Mpeg4Decoder1 = 0x464D5034,
Mpeg4Decoder2 = 0x53454447,
Mpeg4Decoder3 = 0x57563146,
Mpeg4Stream = 0x6d703473, /**< MPEG-4 stream (other then video/audio) */
Mpeg4Sample = 0x6d703473, /**< MPEG-4 stream (other then video/audio) */
Mpeg4Video = 0x6d703476, /**< MPEG-4 video */
MsMpeg4V1Decoder1 = 0x44495631,
MsMpeg4V1Decoder2 = 0x4D504734,

View File

@ -595,6 +595,7 @@ unique_ptr<Mpeg4AudioSpecificConfig> Mp4Track::parseAudioSpecificConfig(Mpeg4Des
auto buff = make_unique<char []>(decSpecInfoDesc->dataSize());
m_istream->read(buff.get(), decSpecInfoDesc->dataSize());
BitReader bitReader(buff.get(), decSpecInfoDesc->dataSize());
cout << "buff: " << reinterpret_cast<uint64>(buff.get()) << ", " << decSpecInfoDesc->dataSize() << endl;
auto audioCfg = make_unique<Mpeg4AudioSpecificConfig>();
try {
// read audio object type
@ -1334,6 +1335,13 @@ void Mp4Track::internalParseHeader()
esDescParentAtom = codecConfigContainerAtom;
}
break;
case FourccIds::Mpeg4Sample:
//m_istream->seekg(6 + 2, ios_base::cur); // skip reserved bytes and data reference index
codecConfigContainerAtom->denoteFirstChild(codecConfigContainerAtom->headerSize() + 8);
if(!esDescParentAtom) {
esDescParentAtom = codecConfigContainerAtom;
}
break;
case Mp4AtomIds::PixalAspectRatio:
break; // TODO
case Mp4AtomIds::CleanAperature:

View File

@ -54,8 +54,8 @@ std::string Mpeg4Descriptor::idToString() const
void Mpeg4Descriptor::internalParse()
{
invalidateStatus();
if(maxTotalSize() < 4) {
addNotification(NotificationType::Critical, "Descriptor is smaller then 4 byte and hence invalid. The maximum size within the encloding element is " + numberToString(maxTotalSize()) + ".", "parsing MPEG-4 descriptor");
if(maxTotalSize() < minimumElementSize()) {
addNotification(NotificationType::Critical, "Descriptor is smaller then 2 byte and hence invalid. The maximum size within the encloding element is " + numberToString(maxTotalSize()) + ".", "parsing MPEG-4 descriptor");
throw TruncatedDataException();
}
stream().seekg(startOffset());
@ -63,7 +63,7 @@ void Mpeg4Descriptor::internalParse()
m_idLength = m_sizeLength = 1;
m_id = reader().readByte();
// read data size
byte tmp = reader().readByte() & 0x80;
byte tmp = reader().readByte();
m_dataSize = tmp & 0x7F;
while(tmp & 0x80) {
m_dataSize = (m_dataSize << 7) | ((tmp = reader().readByte()) & 0x7F);

View File

@ -36,6 +36,14 @@ public:
* \brief The implementation type is Mp4Atom.
*/
typedef Mpeg4Descriptor implementationType;
/*!
* \brief Returns the minimal descriptor size which is 2 byte.
*/
static constexpr byte minimumElementSize()
{
return 2;
}
};
class LIB_EXPORT Mpeg4Descriptor : public GenericFileElement<Mpeg4Descriptor>