improved media format detection; other minor improvements
This commit is contained in:
parent
221a690311
commit
c452b009ae
|
@ -32,7 +32,7 @@ AbstractTrack::AbstractTrack(istream &inputStream, ostream &outputStream, uint64
|
|||
m_writer(BinaryWriter(&outputStream)),
|
||||
m_startOffset(startOffset),
|
||||
m_headerValid(false),
|
||||
m_format(MediaFormat::Unknown),
|
||||
m_format(),
|
||||
m_mediaType(MediaType::Unknown),
|
||||
m_version(0.0),
|
||||
m_size(0),
|
||||
|
@ -79,22 +79,13 @@ AbstractTrack::~AbstractTrack()
|
|||
/*!
|
||||
* \brief Returns the format of the track as C-style string if known; otherwise
|
||||
* returns the format abbreviation or an empty string.
|
||||
* \remarks
|
||||
* - The caller must not free the returned string.
|
||||
* - The string might get invalidated when the track is (re)parsed.
|
||||
*/
|
||||
const char *AbstractTrack::formatName() const
|
||||
{
|
||||
if(!m_formatName.empty()) {
|
||||
return m_formatName.c_str();
|
||||
}
|
||||
const char *formatName = mediaFormatName(m_format);
|
||||
if(*formatName == 0) {
|
||||
if(!m_formatId.empty()) {
|
||||
return m_formatId.c_str();
|
||||
} else {
|
||||
return "unknown";
|
||||
}
|
||||
} else {
|
||||
return formatName;
|
||||
}
|
||||
return m_format || m_formatName.empty() ? m_format.name() : m_formatName.c_str();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -103,43 +94,8 @@ const char *AbstractTrack::formatName() const
|
|||
*/
|
||||
const char *AbstractTrack::formatAbbreviation() const
|
||||
{
|
||||
if(!m_formatId.empty()) {
|
||||
return m_formatId.c_str();
|
||||
}
|
||||
switch(m_format) {
|
||||
case MediaFormat::Pcm:
|
||||
return "PCM";
|
||||
case MediaFormat::Mpeg1:
|
||||
return "MPEG-1";
|
||||
case MediaFormat::Mpeg2:
|
||||
return "MPEG-2";
|
||||
case MediaFormat::MpegL1:
|
||||
return "MP1";
|
||||
case MediaFormat::MpegL2:
|
||||
return "MP2";
|
||||
case MediaFormat::MpegL3:
|
||||
return "MP3";
|
||||
case MediaFormat::Aac:
|
||||
return "AAC";
|
||||
case MediaFormat::Png:
|
||||
return "PNG";
|
||||
case MediaFormat::Jpeg:
|
||||
return "JPEG";
|
||||
case MediaFormat::Mpeg4Avc:
|
||||
return "AVC";
|
||||
case MediaFormat::Mpeg4Asp:
|
||||
return "ASP";
|
||||
case MediaFormat::Mpeg4:
|
||||
return "MPEG-4";
|
||||
case MediaFormat::Gif:
|
||||
return "GIF";
|
||||
case MediaFormat::Tiff:
|
||||
return "TIFF";
|
||||
case MediaFormat::Ac3:
|
||||
return "AC3";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
const char *abbr = m_format.abbreviation();
|
||||
return *abbr || m_formatId.empty() ? m_format.abbreviation() : m_formatId.c_str();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -148,11 +104,11 @@ const char *AbstractTrack::formatAbbreviation() const
|
|||
const char *AbstractTrack::mediaTypeName() const
|
||||
{
|
||||
switch(m_mediaType) {
|
||||
case MediaType::Acoustic:
|
||||
case MediaType::Audio:
|
||||
return "Audio";
|
||||
case MediaType::Visual:
|
||||
case MediaType::Video:
|
||||
return "Video";
|
||||
case MediaType::Textual:
|
||||
case MediaType::Text:
|
||||
return "Subititle";
|
||||
case MediaType::Hint:
|
||||
return "Hint";
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "statusprovider.h"
|
||||
#include "size.h"
|
||||
#include "margin.h"
|
||||
#include "mediaformat.h"
|
||||
|
||||
#include <c++utilities/conversion/types.h>
|
||||
#include <c++utilities/io/binaryreader.h>
|
||||
|
@ -17,7 +18,7 @@
|
|||
namespace Media {
|
||||
|
||||
enum class MediaType;
|
||||
enum class MediaFormat;
|
||||
enum class GeneralMediaFormat;
|
||||
|
||||
/*!
|
||||
* \brief Specifies the track type.
|
||||
|
|
|
@ -4,6 +4,15 @@
|
|||
|
||||
namespace Media {
|
||||
|
||||
/*!
|
||||
* \struct Media::SpsInfo
|
||||
* \brief The SpsInfo struct holds the sequence parameter set.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief SpsInfo::parse
|
||||
* \param stream
|
||||
*/
|
||||
void SpsInfo::parse(std::istream &stream)
|
||||
{
|
||||
static auto highLevelProfileIds = std::unordered_map<unsigned int, bool> {
|
||||
|
|
|
@ -27,6 +27,72 @@ namespace Media {
|
|||
template <class ImplementationType>
|
||||
class GenericFileElement;
|
||||
|
||||
|
||||
/*!
|
||||
* \class Media::FileElementIterator
|
||||
* \brief The FileElementIterator class helps iterating through the childs of a FileElement.
|
||||
*/
|
||||
template<typename ImplementationType>
|
||||
class FileElementIterator
|
||||
{
|
||||
public:
|
||||
FileElementIterator(ImplementationType *element = nullptr);
|
||||
|
||||
ImplementationType *operator *();
|
||||
const ImplementationType *operator *() const;
|
||||
operator bool() const;
|
||||
FileElementIterator<ImplementationType> &operator ++();
|
||||
|
||||
private:
|
||||
ImplementationType *m_current;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new iterator for the specified \a element.
|
||||
*/
|
||||
template<typename ImplementationType>
|
||||
inline FileElementIterator<ImplementationType>::FileElementIterator(ImplementationType *element) :
|
||||
m_current(element)
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \brief Returns a reference to the current element.
|
||||
*/
|
||||
template<typename ImplementationType>
|
||||
inline ImplementationType *FileElementIterator<ImplementationType>::operator *()
|
||||
{
|
||||
return m_current;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns a reference the current element (constant).
|
||||
*/
|
||||
template<typename ImplementationType>
|
||||
inline const ImplementationType *FileElementIterator<ImplementationType>::operator *() const
|
||||
{
|
||||
return m_current;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Moves to the next sibling.
|
||||
*/
|
||||
template<typename ImplementationType>
|
||||
inline FileElementIterator<ImplementationType> &FileElementIterator<ImplementationType>::operator ++()
|
||||
{
|
||||
m_current->parse(); // ensure the current element has been parsed
|
||||
m_current = m_current->nextSibling();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns whether the iterator points to an element.
|
||||
*/
|
||||
template<typename ImplementationType>
|
||||
inline FileElementIterator<ImplementationType>::operator bool() const
|
||||
{
|
||||
return m_current != nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \class Media::FileElementTraits
|
||||
* \brief Defines traits for the specified \a ImplementationType.
|
||||
|
@ -66,7 +132,7 @@ public:
|
|||
/*!
|
||||
* \brief Specifies the type used to store data sizes.
|
||||
*/
|
||||
typedef uint64 dataSizeType;
|
||||
typedef typename FileElementTraits<ImplementationType>::dataSizeType dataSizeType;
|
||||
|
||||
/*!
|
||||
* \brief Specifies the type of the actual implementation.
|
||||
|
@ -106,6 +172,10 @@ public:
|
|||
implementationType* subelementByPath(std::list<identifierType> &path);
|
||||
implementationType* childById(const identifierType &id);
|
||||
implementationType* siblingById(const identifierType &id, bool includeThis = false);
|
||||
FileElementIterator<implementationType> begin();
|
||||
FileElementIterator<implementationType> end();
|
||||
const FileElementIterator<implementationType> begin() const;
|
||||
const FileElementIterator<implementationType> end() const;
|
||||
bool isParent() const;
|
||||
bool isPadding() const;
|
||||
uint64 firstChildOffset() const;
|
||||
|
@ -140,6 +210,7 @@ private:
|
|||
|
||||
/*!
|
||||
* \brief Constructs a new top level file element with the specified \a container at the specified \a startOffset.
|
||||
* \remarks The available size is obtained using the stream of the \a container.
|
||||
*/
|
||||
template <class ImplementationType>
|
||||
GenericFileElement<ImplementationType>::GenericFileElement(GenericFileElement<ImplementationType>::containerType &container, uint64 startOffset) :
|
||||
|
@ -339,6 +410,9 @@ inline uint64 GenericFileElement<ImplementationType>::totalSize() const
|
|||
|
||||
/*!
|
||||
* \brief Returns maximum total size.
|
||||
*
|
||||
* This is usually the size of the file for top-level elements and
|
||||
* the remaining size of the parent for non-top-level elements.
|
||||
*/
|
||||
template <class ImplementationType>
|
||||
inline uint64 GenericFileElement<ImplementationType>::maxTotalSize() const
|
||||
|
@ -528,6 +602,42 @@ typename GenericFileElement<ImplementationType>::implementationType *GenericFile
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns an iterator for iterating over the element's childs.
|
||||
*/
|
||||
template <class ImplementationType>
|
||||
FileElementIterator<typename GenericFileElement<ImplementationType>::implementationType> GenericFileElement<ImplementationType>::begin()
|
||||
{
|
||||
return FileElementIterator<implementationType>(firstChild());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns an iterator for iterating over the element's childs (constant).
|
||||
*/
|
||||
template <class ImplementationType>
|
||||
const FileElementIterator<typename GenericFileElement<ImplementationType>::implementationType> GenericFileElement<ImplementationType>::begin() const
|
||||
{
|
||||
return FileElementIterator<implementationType>(firstChild());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns an invalid iterator.
|
||||
*/
|
||||
template <class ImplementationType>
|
||||
FileElementIterator<typename GenericFileElement<ImplementationType>::implementationType> GenericFileElement<ImplementationType>::end()
|
||||
{
|
||||
return FileElementIterator<ImplementationType>();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns an invalid iterator.
|
||||
*/
|
||||
template <class ImplementationType>
|
||||
const FileElementIterator<typename GenericFileElement<ImplementationType>::implementationType> GenericFileElement<ImplementationType>::end() const
|
||||
{
|
||||
return FileElementIterator<ImplementationType>();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns an indication whether this instance is a parent element.
|
||||
*/
|
||||
|
|
|
@ -34,6 +34,13 @@ EbmlElement::EbmlElement(MatroskaContainer &container, uint64 startOffset) :
|
|||
GenericFileElement<EbmlElement>(container, startOffset)
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new top level element with the specified \a container at the specified \a startOffset.
|
||||
*/
|
||||
EbmlElement::EbmlElement(MatroskaContainer &container, uint64 startOffset, uint64 maxSize) :
|
||||
GenericFileElement<EbmlElement>(container, startOffset, maxSize)
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new sub level element with the specified \a parent at the specified \a startOffset.
|
||||
*/
|
||||
|
@ -129,7 +136,7 @@ void EbmlElement::internalParse()
|
|||
if(parent()) {
|
||||
m_nextSibling.reset(new EbmlElement(*(parent()), startOffset() + totalSize()));
|
||||
} else {
|
||||
m_nextSibling = make_unique<EbmlElement>(container(), startOffset() + totalSize());
|
||||
m_nextSibling.reset(new EbmlElement(container(), startOffset() + totalSize(), maxTotalSize() - totalSize()));
|
||||
}
|
||||
} else {
|
||||
m_nextSibling.reset();
|
||||
|
|
|
@ -35,6 +35,11 @@ public:
|
|||
*/
|
||||
typedef uint32 identifierType;
|
||||
|
||||
/*!
|
||||
* \brief The type used to store element sizes is an unsigned 64-bit integer.
|
||||
*/
|
||||
typedef uint64 dataSizeType;
|
||||
|
||||
/*!
|
||||
* \brief The implementation type is EbmlElement.
|
||||
*/
|
||||
|
@ -67,6 +72,7 @@ public:
|
|||
|
||||
protected:
|
||||
EbmlElement(EbmlElement &parent, uint64 startOffset);
|
||||
EbmlElement(MatroskaContainer &container, uint64 startOffset, uint64 maxSize);
|
||||
|
||||
void internalParse();
|
||||
|
||||
|
|
|
@ -6,7 +6,10 @@
|
|||
#include "../mediaformat.h"
|
||||
#include "../exceptions.h"
|
||||
|
||||
#include <c++utilities/conversion/stringconversion.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace ConversionUtilities;
|
||||
|
||||
namespace Media {
|
||||
|
||||
|
@ -37,6 +40,144 @@ TrackType MatroskaTrack::type() const
|
|||
return TrackType::MatroskaTrack;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the MediaFormat for the specified Matroska codec ID.
|
||||
*/
|
||||
MediaFormat MatroskaTrack::codecIdToMediaFormat(const string &codecId)
|
||||
{
|
||||
auto parts = splitString<vector<string> >(codecId, "/", EmptyPartsTreat::Keep, 3);
|
||||
parts.resize(3);
|
||||
const auto &part1 = parts[0], &part2 = parts[1], &part3 = parts[2];
|
||||
MediaFormat fmt;
|
||||
if(part1 == "V_MS" && part2 == "VFW" && part3 == "FOURCC") {
|
||||
fmt.general = GeneralMediaFormat::MicrosoftVideoCodecManager;
|
||||
} else if(part1 == "V_UNCOMPRESSED") {
|
||||
fmt.general = GeneralMediaFormat::UncompressedVideoFrames;
|
||||
} else if(part1 == "V_MPEG4") {
|
||||
fmt.general = GeneralMediaFormat::Mpeg4Video;
|
||||
if(part2 == "ISO") {
|
||||
if(part3 == "SP") {
|
||||
fmt.sub = SubFormats::Mpeg4Sp;
|
||||
} else if(part3 == "ASP") {
|
||||
fmt.sub = SubFormats::Mpeg4Asp;
|
||||
} else if(part3 == "AP") {
|
||||
fmt.sub = SubFormats::Mpeg4Avc;
|
||||
}
|
||||
} else if(part2 == "MS" && part3 == "V3") {
|
||||
fmt.sub = SubFormats::Mpeg4MsV3;
|
||||
}
|
||||
} else if(part1 == "V_MPEG1") {
|
||||
fmt.general = GeneralMediaFormat::Mpeg1Video;
|
||||
} else if(part1 == "V_MPEG2") {
|
||||
fmt.general = GeneralMediaFormat::Mpeg2Video;
|
||||
} else if(part1 == "V_REAL") {
|
||||
fmt.general = GeneralMediaFormat::RealVideo;
|
||||
} else if(part1 == "V_QUICKTIME") {
|
||||
fmt.general = GeneralMediaFormat::QuicktimeVideo;
|
||||
} else if(part1 == "V_THEORA") {
|
||||
fmt.general = GeneralMediaFormat::Theora;
|
||||
} else if(part1 == "V_PRORES") {
|
||||
fmt.general = GeneralMediaFormat::ProRes;
|
||||
} else if(part1 == "A_MPEG") {
|
||||
fmt.general = GeneralMediaFormat::Mpeg1Audio;
|
||||
if(part2 == "L1") {
|
||||
fmt.sub = SubFormats::Mpeg1Layer1;
|
||||
} else if(part2 == "L2") {
|
||||
fmt.sub = SubFormats::Mpeg1Layer2;
|
||||
} else if(part2 == "L3") {
|
||||
fmt.sub = SubFormats::Mpeg1Layer3;
|
||||
}
|
||||
} else if(part1 == "A_PCM") {
|
||||
fmt.general = GeneralMediaFormat::Pcm;
|
||||
if(part2 == "INT") {
|
||||
if(part3 == "BIG") {
|
||||
fmt.sub = SubFormats::PcmIntBe;
|
||||
} else if(part3 == "LIT") {
|
||||
fmt.sub = SubFormats::PcmIntLe;
|
||||
}
|
||||
} else if (part2 == "FLOAT" && part3 == "IEEE") {
|
||||
fmt.sub = SubFormats::PcmFloatIeee;
|
||||
}
|
||||
} else if(part1 == "A_MPC") {
|
||||
fmt.general = GeneralMediaFormat::Mpc;
|
||||
} else if(part1 == "A_AC3") {
|
||||
fmt.general = GeneralMediaFormat::Ac3;
|
||||
} else if(part1 == "A_ALAC") {
|
||||
fmt.general = GeneralMediaFormat::Alac;
|
||||
} else if(part1 == "A_DTS") {
|
||||
fmt.general = GeneralMediaFormat::Dts;
|
||||
if(part2 == "EXPRESS") {
|
||||
fmt.sub = SubFormats::DtsExpress;
|
||||
} else if(part2 == "LOSSLESS") {
|
||||
fmt.sub = SubFormats::DtsLossless;
|
||||
}
|
||||
} else if(part1 == "A_VORBIS") {
|
||||
fmt.general = GeneralMediaFormat::Vorbis;
|
||||
} else if(part1 == "A_FLAC") {
|
||||
fmt.general = GeneralMediaFormat::Flac;
|
||||
} else if(part1 == "A_REAL") {
|
||||
fmt.general = GeneralMediaFormat::RealAudio;
|
||||
} else if(part1 == "A_MS" && part2 == "ACM") {
|
||||
fmt.general = GeneralMediaFormat::MicrosoftAudioCodecManager;
|
||||
} else if(part1 == "A_AAC") {
|
||||
fmt.general = GeneralMediaFormat::Aac;
|
||||
if(part2 == "MPEG2") {
|
||||
if(part3 == "MAIN") {
|
||||
fmt.sub = SubFormats::AacMpeg2MainProfile;
|
||||
} else if(part3 == "LC") {
|
||||
fmt.sub = SubFormats::AacMpeg2LowComplexityProfile;
|
||||
} else if(part3 == "SBR") {
|
||||
fmt.sub = SubFormats::AacMpeg2SpectralBandReplicationProfile;
|
||||
} else if(part3 == "SSR") {
|
||||
fmt.sub = SubFormats::AacMpeg2ScalableSamplingRateProfile;
|
||||
}
|
||||
} else if(part2 == "MPEG4") {
|
||||
if(part3 == "MAIN") {
|
||||
fmt.sub = SubFormats::AacMpeg4MainProfile;
|
||||
} else if(part3 == "LC") {
|
||||
fmt.sub = SubFormats::AacMpeg4LowComplexityProfile;
|
||||
} else if(part3 == "SBR") {
|
||||
fmt.sub = SubFormats::AacMpeg4SpectralBandReplicationProfile;
|
||||
} else if(part3 == "SSR") {
|
||||
fmt.sub = SubFormats::AacMpeg4ScalableSamplingRateProfile;
|
||||
} else if(part3 == "LTP") {
|
||||
fmt.sub = SubFormats::AacMpeg4LongTermPredictionProfile;
|
||||
}
|
||||
}
|
||||
} else if(part1 == "A_QUICKTIME") {
|
||||
fmt.general = GeneralMediaFormat::QuicktimeAudio;
|
||||
} else if(part1 == "A_TTA1") {
|
||||
fmt.general = GeneralMediaFormat::Tta;
|
||||
} else if(part1 == "A_WAVPACK4") {
|
||||
fmt.general = GeneralMediaFormat::WavPack;
|
||||
} else if(part1 == "S_TEXT") {
|
||||
fmt.general = GeneralMediaFormat::TextSubtitle;
|
||||
if(part2 == "UTF8") {
|
||||
fmt.sub = SubFormats::TextSubBasicUtf8;
|
||||
} else if(part2 == "SSA") {
|
||||
fmt.sub = SubFormats::TextSubSubtitlesFormat;
|
||||
} else if(part2 == "ASS") {
|
||||
fmt.sub = SubFormats::TextSubAdvancedSubtitlesFormat;
|
||||
} else if(part2 == "USF") {
|
||||
fmt.sub = SubFormats::TextSubUniversalSubtitleFormat;
|
||||
}
|
||||
} else if(part1 == "S_IMAGE") {
|
||||
fmt.general = GeneralMediaFormat::ImageSubtitle;
|
||||
if(part2 == "BMP") {
|
||||
fmt.sub = SubFormats::ImgSubBmp;
|
||||
}
|
||||
} else if(part1 == "S_VOBSUB") {
|
||||
fmt.general = GeneralMediaFormat::VobSub;
|
||||
} else if(part1 == "S_KATE") {
|
||||
fmt.general = GeneralMediaFormat::OggKate;
|
||||
} else if(part1 == "B_VOBBTN") {
|
||||
fmt.general = GeneralMediaFormat::VobBtn;
|
||||
} else if(part1 == "V_MSWMV") {
|
||||
fmt.general = GeneralMediaFormat::Vc1;
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
||||
void MatroskaTrack::internalParseHeader()
|
||||
{
|
||||
const string context("parsing header of Matroska track");
|
||||
|
@ -61,13 +202,13 @@ void MatroskaTrack::internalParseHeader()
|
|||
case MatroskaIds::TrackType:
|
||||
switch(trackInfoElement->readUInteger()) {
|
||||
case MatroskaTrackType::Video:
|
||||
m_mediaType = MediaType::Visual;
|
||||
m_mediaType = MediaType::Video;
|
||||
break;
|
||||
case MatroskaTrackType::Audio:
|
||||
m_mediaType = MediaType::Acoustic;
|
||||
m_mediaType = MediaType::Audio;
|
||||
break;
|
||||
case MatroskaTrackType::Subtitle:
|
||||
m_mediaType = MediaType::Textual;
|
||||
m_mediaType = MediaType::Text;
|
||||
break;
|
||||
default:
|
||||
m_mediaType = MediaType::Unknown;
|
||||
|
@ -158,7 +299,10 @@ void MatroskaTrack::internalParseHeader()
|
|||
m_language = trackInfoElement->readString();
|
||||
break;
|
||||
case MatroskaIds::CodecID:
|
||||
m_formatId = trackInfoElement->readString();
|
||||
m_format = codecIdToMediaFormat(m_formatId = trackInfoElement->readString());
|
||||
if(m_formatName.empty()) {
|
||||
m_formatName = m_format ? string(m_format.name()) : m_formatId;
|
||||
}
|
||||
break;
|
||||
case MatroskaIds::CodecName:
|
||||
m_formatName = trackInfoElement->readString();
|
||||
|
@ -181,7 +325,7 @@ void MatroskaTrack::internalParseHeader()
|
|||
default: ;
|
||||
}
|
||||
switch(m_mediaType) {
|
||||
case MediaType::Visual:
|
||||
case MediaType::Video:
|
||||
if(m_fps == 0 && defaultDuration != 0) {
|
||||
m_fps = 1000000000.0 / static_cast<double>(defaultDuration);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ public:
|
|||
|
||||
TrackType type() const;
|
||||
|
||||
static MediaFormat codecIdToMediaFormat(const std::string &codecId);
|
||||
|
||||
protected:
|
||||
void internalParseHeader();
|
||||
|
||||
|
|
|
@ -537,18 +537,11 @@ const char *MediaFileInfo::containerFormatAbbreviation() const
|
|||
case ContainerFormat::Ogg:
|
||||
case ContainerFormat::Matroska:
|
||||
case ContainerFormat::Mp4:
|
||||
mediaType = hasTracksOfType(MediaType::Visual) ? MediaType::Visual : MediaType::Acoustic;
|
||||
mediaType = hasTracksOfType(MediaType::Video) ? MediaType::Video : MediaType::Audio;
|
||||
break;
|
||||
case ContainerFormat::MpegAudioFrames:
|
||||
if(m_mpegAudioFrameStream) {
|
||||
switch(m_mpegAudioFrameStream->format()) {
|
||||
case MediaFormat::MpegL1:
|
||||
version = 1;
|
||||
case MediaFormat::MpegL2:
|
||||
version = 2;
|
||||
default:
|
||||
version = 3;
|
||||
}
|
||||
version = m_mpegAudioFrameStream->format().sub;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -597,17 +590,17 @@ const char *MediaFileInfo::mimeType() const
|
|||
case ContainerFormat::MpegAudioFrames:
|
||||
return "audio/mpeg";
|
||||
case ContainerFormat::Mp4:
|
||||
if(hasTracksOfType(MediaType::Visual)) {
|
||||
if(hasTracksOfType(MediaType::Video)) {
|
||||
return "video/mp4";
|
||||
}
|
||||
return "audio/mp4";
|
||||
case ContainerFormat::Ogg:
|
||||
if(hasTracksOfType(MediaType::Visual)) {
|
||||
if(hasTracksOfType(MediaType::Video)) {
|
||||
return "video/ogg";
|
||||
}
|
||||
return "audio/ogg";
|
||||
case ContainerFormat::Matroska:
|
||||
if(hasTracksOfType(MediaType::Visual)) {
|
||||
if(hasTracksOfType(MediaType::Video)) {
|
||||
return "video/x-matroska";
|
||||
}
|
||||
return "audio/x-matroska";
|
||||
|
@ -699,7 +692,7 @@ bool MediaFileInfo::hasTracksOfType(MediaType type) const
|
|||
if(!areTracksParsed()) {
|
||||
return false;
|
||||
}
|
||||
if(type == MediaType::Acoustic && (m_waveAudioStream || m_mpegAudioFrameStream)) {
|
||||
if(type == MediaType::Audio && (m_waveAudioStream || m_mpegAudioFrameStream)) {
|
||||
return true;
|
||||
} else if(m_container) {
|
||||
for(size_t i = 0, count = m_container->trackCount(); i < count; ++i) {
|
||||
|
@ -907,6 +900,7 @@ bool MediaFileInfo::areChaptersSupported() const
|
|||
}
|
||||
switch(m_containerFormat) {
|
||||
case ContainerFormat::Matroska:
|
||||
case ContainerFormat::Webm:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -923,6 +917,7 @@ bool MediaFileInfo::areAttachmentsSupported() const
|
|||
}
|
||||
switch(m_containerFormat) {
|
||||
case ContainerFormat::Matroska:
|
||||
case ContainerFormat::Webm:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -943,6 +938,7 @@ bool MediaFileInfo::areTracksSupported() const
|
|||
case ContainerFormat::RiffWave:
|
||||
case ContainerFormat::Ogg:
|
||||
case ContainerFormat::Matroska:
|
||||
case ContainerFormat::Webm:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -962,6 +958,7 @@ bool MediaFileInfo::areTagsSupported() const
|
|||
case ContainerFormat::MpegAudioFrames:
|
||||
case ContainerFormat::Ogg:
|
||||
case ContainerFormat::Matroska:
|
||||
case ContainerFormat::Webm:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
334
mediaformat.cpp
334
mediaformat.cpp
|
@ -2,74 +2,282 @@
|
|||
|
||||
namespace Media {
|
||||
|
||||
using namespace SubFormats;
|
||||
|
||||
/*!
|
||||
* \brief Returns the name of the specified media format as C-style string.
|
||||
* \class Media::MediaFormat
|
||||
* \brief The MediaFormat class specifies the format of media data.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Returns the name of the media format as C-style string.
|
||||
*
|
||||
* Returns an empty string if no name is available.
|
||||
*/
|
||||
const char *mediaFormatName(MediaFormat mediaFormat)
|
||||
const char *MediaFormat::name() const
|
||||
{
|
||||
switch(mediaFormat) {
|
||||
case MediaFormat::Pcm:
|
||||
return "Puls-Code-Modulation";
|
||||
case MediaFormat::Mpeg1:
|
||||
return "MPEG-1";
|
||||
case MediaFormat::Mpeg2:
|
||||
return "MPEG-2";
|
||||
case MediaFormat::MpegL1:
|
||||
return "MPEG-1 Layer 1";
|
||||
case MediaFormat::MpegL2:
|
||||
return "MPEG-1 Layer 2";
|
||||
case MediaFormat::MpegL3:
|
||||
return "MPEG-1 Layer 3";
|
||||
case MediaFormat::Aac:
|
||||
return "Advanced Audio Coding";
|
||||
case MediaFormat::Vorbis:
|
||||
return "Vorbis";
|
||||
case MediaFormat::Png:
|
||||
return "Portable Network Graphics";
|
||||
case MediaFormat::Jpeg:
|
||||
return "JPEG File Interchange Format";
|
||||
case MediaFormat::Mpeg4Sp:
|
||||
return "H.264/MPEG-4 Simple profile";
|
||||
case MediaFormat::Mpeg4Avc:
|
||||
return "H.264/MPEG-4 Advanced Video Coding";
|
||||
case MediaFormat::Mpeg4Asp:
|
||||
return "H.263/MPEG-4 Advanced Simple Profile";
|
||||
case MediaFormat::Mpeg4:
|
||||
return "MPEG-4";
|
||||
case MediaFormat::Gif:
|
||||
return "Graphics Interchange Format";
|
||||
case MediaFormat::Tiff:
|
||||
return "Tagged Image File Format";
|
||||
case MediaFormat::UncompressedRgb:
|
||||
return "Uncompressed RGB";
|
||||
case MediaFormat::AdpcmAcm:
|
||||
return "Microsoft ADPCM-ACM code 2";
|
||||
case MediaFormat::ImaadpcmAcm:
|
||||
return "DVI/Intel IMAADPCM-ACM code 17";
|
||||
case MediaFormat::Ac3:
|
||||
return "Dolby Digital (AC-3)";
|
||||
case MediaFormat::Ac4:
|
||||
return "Dolby Digital (AC-4)";
|
||||
case MediaFormat::RealVideo:
|
||||
return "Real Video";
|
||||
case MediaFormat::RealAudio:
|
||||
return "Real Audio";
|
||||
case MediaFormat::QuicktimeVideo:
|
||||
return "Quicktime video";
|
||||
case MediaFormat::QuicktimeAudio:
|
||||
return "Quicktime audio";
|
||||
case MediaFormat::Dts:
|
||||
return "Digital Theatre System";
|
||||
case MediaFormat::Theora:
|
||||
return "Theora";
|
||||
case MediaFormat::ProRes:
|
||||
return "Apple ProRes";
|
||||
case MediaFormat::Alac:
|
||||
return "Apple lossless audio codec";
|
||||
default:
|
||||
return "";
|
||||
switch(general) {
|
||||
case GeneralMediaFormat::Aac:
|
||||
switch(sub) {
|
||||
case AacMpeg2MainProfile: return "Advanced Audio Coding Main Profile";
|
||||
case AacMpeg2LowComplexityProfile: return "Advanced Audio Coding Low Complexity Profile";
|
||||
case AacMpeg2SpectralBandReplicationProfile: return "Advanced Audio Coding Low Complexity with Spectral Band Replication Profile";
|
||||
case AacMpeg2ScalableSamplingRateProfile: return "Advanced Audio Coding Scalable Sampling Rate Profile";
|
||||
case AacMpeg4MainProfile: return "Advanced Audio Coding Main Profile";
|
||||
case AacMpeg4LowComplexityProfile: return "Advanced Audio Coding Low Complexity Profile";
|
||||
case AacMpeg4SpectralBandReplicationProfile: return "Advanced Audio Coding Low Complexity with Spectral Band Replication Profile";
|
||||
case AacMpeg4ScalableSamplingRateProfile: return "Advanced Audio Coding Scaleable Sampling Rate Profile";
|
||||
case AacMpeg4LongTermPredictionProfile: return "Advanced Audio Coding Scalable Sampling Rate Profile";
|
||||
default: return "Advanced Audio Coding";
|
||||
}
|
||||
case GeneralMediaFormat::Ac3: return "Dolby Digital";
|
||||
case GeneralMediaFormat::Ac4: return "AC-4";
|
||||
case GeneralMediaFormat::AdpcmAcm: return "ADPCM ACM";
|
||||
case GeneralMediaFormat::AfxStream: return "AFX Stream";
|
||||
case GeneralMediaFormat::Alac: return "Apple Lossless Audio Codec";
|
||||
case GeneralMediaFormat::Als: return "ALS";
|
||||
case GeneralMediaFormat::Bitmap: return "Windows Bitmap";
|
||||
case GeneralMediaFormat::Dirac: return "Dirac";
|
||||
case GeneralMediaFormat::Dts: return "DTS";
|
||||
switch(sub) {
|
||||
case DtsLossless: return "DTS Lossless";
|
||||
case DtsExpress: return "DTS Express";
|
||||
default: return "DTS";
|
||||
}
|
||||
case GeneralMediaFormat::DtsHd: return "DTS-HD";
|
||||
switch(sub) {
|
||||
case DtsHdHighResolution: return "DTS-HD High Resolution";
|
||||
case DtsHdMasterAudio: return "DTS-HD Master Audio";
|
||||
case DtsExpress: return "DTS-HD Express";
|
||||
default: return "DTS-HD";
|
||||
}
|
||||
case GeneralMediaFormat::EAc3: return "Dolby Digital Plus";
|
||||
case GeneralMediaFormat::Evrc: return "EVRC";
|
||||
case GeneralMediaFormat::Flac: return "Free Lossless Audio Codec";
|
||||
case GeneralMediaFormat::FontDataStream: return "Font Data Stream";
|
||||
case GeneralMediaFormat::Gif: return "GIF";
|
||||
case GeneralMediaFormat::Gpp2Cmf: return "3GPP2 Compact Multimedia Format (CMF)";
|
||||
case GeneralMediaFormat::ImaadpcmAcm: return "IMAADPCM ACM";
|
||||
case GeneralMediaFormat::ImageSubtitle:
|
||||
switch(sub) {
|
||||
case SubFormats::ImgSubBmp: return "Bitmap subtitle";
|
||||
default: return "Image subtitle";
|
||||
}
|
||||
case GeneralMediaFormat::InteractionStream: return "Interaction Stream";
|
||||
case GeneralMediaFormat::Jpeg: return "JPEG";
|
||||
case GeneralMediaFormat::OggKate: return "Karaoke And Text Encapsulation";
|
||||
case GeneralMediaFormat::MicrosoftAudioCodecManager: return "Microsoft Audio Codec Manager";
|
||||
case GeneralMediaFormat::MicrosoftVideoCodecManager: return "Microsoft Video Codec Manager";
|
||||
case GeneralMediaFormat::Mpeg1Audio:
|
||||
switch(sub) {
|
||||
case Mpeg1Layer1: return "MPEG-1 Layer 1";
|
||||
case Mpeg1Layer2: return "MPEG-1 Layer 2";
|
||||
case Mpeg1Layer3: return "MPEG-1 Layer 3";
|
||||
default: return "MPEG-1 Audio";
|
||||
}
|
||||
case GeneralMediaFormat::Mpeg1Video: return "MPEG-1 Video";
|
||||
case GeneralMediaFormat::Mpeg2Audio:
|
||||
switch(sub) {
|
||||
case Mpeg1Layer1: return "MPEG-2 Layer 1";
|
||||
case Mpeg1Layer2: return "MPEG-2 Layer 2";
|
||||
case Mpeg1Layer3: return "MPEG-2 Layer 3";
|
||||
default: return "MPEG-2 Audio";
|
||||
}
|
||||
case GeneralMediaFormat::Mpeg2Video:
|
||||
switch(sub) {
|
||||
case Mpeg2SimpleProfile: return "MPEG-2 Video Simple Profile";
|
||||
case Mpeg2MainProfile: return "MPEG-2 Video Main Profile";
|
||||
case Mpeg2SnrProfile: return "MPEG-2 Video SNR Profile";
|
||||
case Mpeg2SpatialProfile: return "MPEG-2 Video Spatial Profile";
|
||||
case Mpeg2HighProfile: return "MPEG-2 Video High Profile";
|
||||
case Mpeg2422Profile: return "MPEG-2 Video 422 Profile";
|
||||
default: return "MPEG-2 Video";
|
||||
}
|
||||
case GeneralMediaFormat::Mpeg4Video:
|
||||
switch(sub) {
|
||||
case Mpeg4Sp: return "MPEG-4 Simple Profile";
|
||||
case Mpeg4Asp: return "MPEG-4 Advanced Simple Profile";
|
||||
case Mpeg4Avc: return "MPEG-4 Advanced Video Coding";
|
||||
case Mpeg4AvcParams: return "Parameter for MPEG-4 Advanced Video Coding";
|
||||
case Mpeg4MsV3: return "MPEG-4 Microsoft V3";
|
||||
default: return "MPEG-4 Visual";
|
||||
}
|
||||
case GeneralMediaFormat::Mpc: return "Musepack SV8";
|
||||
case GeneralMediaFormat::Pcm:
|
||||
switch(sub) {
|
||||
case PcmIntBe: return "Pulse Code Modulation (integer, big endian)";
|
||||
case PcmIntLe: return "Pulse Code Modulation (integer, little endian)";
|
||||
case PcmFloatIeee: return "Pulse Code Modulation (float, IEEE)";
|
||||
default: return "Pulse Code Modulation";
|
||||
}
|
||||
case GeneralMediaFormat::Png: return "Portable Network Graphics";
|
||||
case GeneralMediaFormat::ProRes: return "ProRes";
|
||||
case GeneralMediaFormat::Qcelp: return "QCELP";
|
||||
case GeneralMediaFormat::QuicktimeAudio: return "Quicktime Audio";
|
||||
case GeneralMediaFormat::QuicktimeVideo: return "Quicktime Video";
|
||||
case GeneralMediaFormat::RealAudio: return "Real Audio";
|
||||
case GeneralMediaFormat::RealVideo: return "Real Video";
|
||||
case GeneralMediaFormat::Sa0c: return "SAOC";
|
||||
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::TextSubtitle:
|
||||
switch(sub) {
|
||||
case SubFormats::TextSubBasicUtf8: return "UTF-8 Plain Text subtitles";
|
||||
case SubFormats::TextSubSubtitlesFormat: return "Subtitles Format";
|
||||
case SubFormats::TextSubAdvancedSubtitlesFormat: return "Advanced Subtitles Format";
|
||||
case SubFormats::TextSubUniversalSubtitleFormat: return "Universal Subtitle Format";
|
||||
default: return "Text subtitle";
|
||||
}
|
||||
case GeneralMediaFormat::Theora: return "Theora";
|
||||
case GeneralMediaFormat::Tiff: return "Tagged Image File Format";
|
||||
case GeneralMediaFormat::Tta: return "The True Audio";
|
||||
case GeneralMediaFormat::UncompressedVideoFrames: return "uncompressed video frames";
|
||||
case GeneralMediaFormat::Vc1: return "Windows Media Video";
|
||||
case GeneralMediaFormat::VobBtn: return "VobBtn Buttons";
|
||||
case GeneralMediaFormat::VobSub: return "VobSub";
|
||||
case GeneralMediaFormat::Vorbis: return "Vorbis";
|
||||
case GeneralMediaFormat::WavPack: return "WavPack";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the abbreviation of the media format as C-style string.
|
||||
*
|
||||
* Returns an empty string if no abbreviation is available.
|
||||
*/
|
||||
const char *MediaFormat::abbreviation() const
|
||||
{
|
||||
switch(general) {
|
||||
case GeneralMediaFormat::Aac:
|
||||
switch(sub) {
|
||||
case AacMpeg2MainProfile: return "MPEG-2 AAC Main";
|
||||
case AacMpeg2LowComplexityProfile: return "MPEG-2 AAC-LC";
|
||||
case AacMpeg2SpectralBandReplicationProfile: return "MPEG-2-SBR";
|
||||
case AacMpeg2ScalableSamplingRateProfile: return "MPEG-2 AAC-SSR";
|
||||
case AacMpeg4MainProfile: return "MPEG-4 AAC Main";
|
||||
case AacMpeg4LowComplexityProfile: return "MPEG-4 AAC-LC";
|
||||
case AacMpeg4SpectralBandReplicationProfile: return "MPEG-4 AAC-SBR";
|
||||
case AacMpeg4ScalableSamplingRateProfile: return "MPEG-4 AAC-SSR";
|
||||
case AacMpeg4LongTermPredictionProfile: return "MPEG-4 AAC-LTP";
|
||||
default: return "AAC";
|
||||
}
|
||||
case GeneralMediaFormat::Ac3: return "AC-3";
|
||||
case GeneralMediaFormat::Ac4: return "AC-4";
|
||||
case GeneralMediaFormat::AdpcmAcm: return "ADPCM ACM";
|
||||
case GeneralMediaFormat::AfxStream: return "AFX";
|
||||
case GeneralMediaFormat::Alac: return "ALAC";
|
||||
case GeneralMediaFormat::Als: return "ALS";
|
||||
case GeneralMediaFormat::Bitmap: return "BMP";
|
||||
case GeneralMediaFormat::Dirac: return "Dirac";
|
||||
case GeneralMediaFormat::Dts: return "DTS";
|
||||
switch(sub) {
|
||||
case DtsLossless: return "DTS Lossless";
|
||||
case DtsExpress: return "DTS LBR";
|
||||
default: return "DTS";
|
||||
}
|
||||
case GeneralMediaFormat::DtsHd: return "DTS-HD";
|
||||
switch(sub) {
|
||||
case DtsHdHighResolution: return "DTS-HD High Resolution";
|
||||
case DtsHdMasterAudio: return "DTS-HD Master Audio";
|
||||
case DtsExpress: return "DTS-HD Express";
|
||||
default: return "DTS-HD";
|
||||
}
|
||||
case GeneralMediaFormat::EAc3: return "E-AC-3";
|
||||
case GeneralMediaFormat::Evrc: return "EVRC";
|
||||
case GeneralMediaFormat::Flac: return "FLAC";
|
||||
case GeneralMediaFormat::FontDataStream: return "FDS";
|
||||
case GeneralMediaFormat::Gif: return "GIF";
|
||||
case GeneralMediaFormat::Gpp2Cmf: return "3GPP2 CMF";
|
||||
case GeneralMediaFormat::ImaadpcmAcm: return "IMAADPCM ACM";
|
||||
case GeneralMediaFormat::ImageSubtitle:
|
||||
switch(sub) {
|
||||
case SubFormats::ImgSubBmp: return "BMP subtitle";
|
||||
default: return "Image subtitle";
|
||||
}
|
||||
case GeneralMediaFormat::InteractionStream: return "Interaction Stream";
|
||||
case GeneralMediaFormat::Jpeg: return "JPEG";
|
||||
case GeneralMediaFormat::OggKate: return "OggKate";
|
||||
case GeneralMediaFormat::MicrosoftAudioCodecManager: return "MS ACM";
|
||||
case GeneralMediaFormat::MicrosoftVideoCodecManager: return "MS VCM";
|
||||
case GeneralMediaFormat::Mpeg1Audio:
|
||||
switch(sub) {
|
||||
case Mpeg1Layer1: return "MP1";
|
||||
case Mpeg1Layer2: return "MP2";
|
||||
case Mpeg1Layer3: return "MP3";
|
||||
default: return "MPEG-1 Audio";
|
||||
}
|
||||
case GeneralMediaFormat::Mpeg1Video: return "MP1";
|
||||
case GeneralMediaFormat::Mpeg2Audio:
|
||||
switch(sub) {
|
||||
case Mpeg1Layer1: return "MP1";
|
||||
case Mpeg1Layer2: return "MP2";
|
||||
case Mpeg1Layer3: return "MP3";
|
||||
default: return "MPEG-2 Audio";
|
||||
}
|
||||
case GeneralMediaFormat::Mpeg2Video:
|
||||
switch(sub) {
|
||||
case Mpeg2SimpleProfile: return "MPEG-2 SP";
|
||||
case Mpeg2MainProfile: return "MPEG-2 Main";
|
||||
case Mpeg2SnrProfile: return "MPEG-2 SNR";
|
||||
case Mpeg2SpatialProfile: return "MPEG-2 Spatial";
|
||||
case Mpeg2HighProfile: return "MPEG-2 High";
|
||||
case Mpeg2422Profile: return "MPEG-2 422";
|
||||
default: return "MPEG-2 Video";
|
||||
}
|
||||
case GeneralMediaFormat::Mpeg4Video:
|
||||
switch(sub) {
|
||||
case Mpeg4Sp: return "MPEG-4 SP";
|
||||
case Mpeg4Asp: return "H.263";
|
||||
case Mpeg4Avc: return "H.264";
|
||||
case Mpeg4AvcParams: return "H.264 params";
|
||||
case Mpeg4MsV3: return "MPEG-4 MS V3";
|
||||
default: return "MPEG-4 Visual";
|
||||
}
|
||||
case GeneralMediaFormat::Mpc: return "MPC";
|
||||
case GeneralMediaFormat::Pcm:
|
||||
switch(sub) {
|
||||
case PcmIntBe: return "PCM (int, BE)";
|
||||
case PcmIntLe: return "PCM (int, LE)";
|
||||
case PcmFloatIeee: return "PCM IEEE";
|
||||
default: return "PCM";
|
||||
}
|
||||
case GeneralMediaFormat::Png: return "PNG";
|
||||
case GeneralMediaFormat::ProRes: return "ProRes";
|
||||
case GeneralMediaFormat::Qcelp: return "QCELP";
|
||||
case GeneralMediaFormat::QuicktimeAudio: return "Quicktime Audio";
|
||||
case GeneralMediaFormat::QuicktimeVideo: return "Quicktime Video";
|
||||
case GeneralMediaFormat::RealAudio: return "Real Audio";
|
||||
case GeneralMediaFormat::RealVideo: return "Real Video";
|
||||
case GeneralMediaFormat::Sa0c: return "SAOC";
|
||||
case GeneralMediaFormat::Smv: return "SMV";
|
||||
case GeneralMediaFormat::StreamingTextStream: return "Streaming Text Stream";
|
||||
case GeneralMediaFormat::SynthesizedTextureStream: return "Synthesized Texture Stream";
|
||||
case GeneralMediaFormat::Systems:
|
||||
switch(sub) {
|
||||
case 2: return "Systems v2";
|
||||
default: return "Systems";
|
||||
}
|
||||
case GeneralMediaFormat::TextSubtitle:
|
||||
switch(sub) {
|
||||
case SubFormats::TextSubBasicUtf8: return "UTF-8 Sub";
|
||||
case SubFormats::TextSubSubtitlesFormat: return "SSA";
|
||||
case SubFormats::TextSubAdvancedSubtitlesFormat: return "ASS";
|
||||
case SubFormats::TextSubUniversalSubtitleFormat: return "USF";
|
||||
default: return "Text subtitle";
|
||||
}
|
||||
case GeneralMediaFormat::Theora: return "Theora";
|
||||
case GeneralMediaFormat::Tiff: return "TIFF";
|
||||
case GeneralMediaFormat::Tta: return "TTA";
|
||||
case GeneralMediaFormat::UncompressedVideoFrames: return "uncompressed video frames";
|
||||
case GeneralMediaFormat::Vc1: return "VC-1";
|
||||
case GeneralMediaFormat::VobBtn: return "VobBtn";
|
||||
case GeneralMediaFormat::VobSub: return "VobSub";
|
||||
case GeneralMediaFormat::Vorbis: return "Vorbis";
|
||||
case GeneralMediaFormat::WavPack: return "WavPack";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
208
mediaformat.h
208
mediaformat.h
|
@ -1,61 +1,185 @@
|
|||
#ifndef MEDIAFORMAT_H
|
||||
#define MEDIAFORMAT_H
|
||||
|
||||
#include <c++utilities/application/global.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace Media {
|
||||
|
||||
/*!
|
||||
* \brief The MediaType enum specifies the type of media data (acoustic, visual, textual, ...).
|
||||
* \brief The MediaType enum specifies the type of media data (audio, video, text, ...).
|
||||
*/
|
||||
enum class MediaType
|
||||
{
|
||||
Acoustic,
|
||||
Visual,
|
||||
Textual,
|
||||
Hint,
|
||||
Unknown
|
||||
Unknown,
|
||||
Audio,
|
||||
Video,
|
||||
Text,
|
||||
Hint
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief The MediaFormat enum specifies the format of media data (PCM, MPEG-4, PNG, ...).
|
||||
* \brief The GeneralMediaFormat enum specifies the general format of media data (PCM, MPEG-4, PNG, ...).
|
||||
*/
|
||||
enum class MediaFormat
|
||||
enum class GeneralMediaFormat
|
||||
{
|
||||
Pcm,
|
||||
Mpeg1,
|
||||
Mpeg2,
|
||||
MpegL1,
|
||||
MpegL2,
|
||||
MpegL3,
|
||||
Aac,
|
||||
Alac,
|
||||
Vorbis,
|
||||
Png,
|
||||
Jpeg,
|
||||
Bitmap,
|
||||
Mpeg4Sp,
|
||||
Mpeg4Avc,
|
||||
Mpeg4Asp,
|
||||
Mpeg4,
|
||||
Gif,
|
||||
Tiff,
|
||||
UncompressedRgb,
|
||||
AdpcmAcm,
|
||||
ImaadpcmAcm,
|
||||
Ac3,
|
||||
Ac4,
|
||||
Dts,
|
||||
Flac,
|
||||
RealAudio,
|
||||
RealVideo,
|
||||
QuicktimeVideo,
|
||||
QuicktimeAudio,
|
||||
Theora,
|
||||
ProRes,
|
||||
VobSub,
|
||||
Unknown
|
||||
Unknown,
|
||||
Aac, /**< Advanced Video Coding */
|
||||
Ac3, /**< Dolby Digital */
|
||||
Ac4, /**< AC-4 */
|
||||
AdpcmAcm, /**< ADPCM ACM */
|
||||
AfxStream, /**< AFX Stream */
|
||||
Alac, /**< Apple Lossless Audio Codec */
|
||||
Als, /**< ALS */
|
||||
Bitmap, /**< Windows Bitmap */
|
||||
Dirac, /**< Dirac */
|
||||
Dts, /**< DTS */
|
||||
DtsHd, /**< DTS-HD */
|
||||
EAc3, /**< Dolby Digital Plus */
|
||||
Evrc, /**< EVRC */
|
||||
Flac, /**< FLAC */
|
||||
FontDataStream, /**< Font Data Stream */
|
||||
Gif, /**< GIF */
|
||||
Gpp2Cmf, /**< 3GPP2 Compact Multimedia Format (CMF) */
|
||||
ImaadpcmAcm, /**< IMAADPCM ACM */
|
||||
ImageSubtitle, /**< Image subtitle */
|
||||
InteractionStream, /**< Interaction Stream */
|
||||
Jpeg, /**< JPEG */
|
||||
OggKate, /**< Karaoke And Text Encapsulation */
|
||||
MicrosoftAudioCodecManager, /**< Microsoft Audio Codec Manager (ACM) */
|
||||
MicrosoftVideoCodecManager, /**< Microsoft Video Codec Manager (VCM) */
|
||||
Mpeg1Audio, /**< MPEG-1 Audio */
|
||||
Mpeg1Video, /**< MPEG-1 Vudio */
|
||||
Mpeg2Audio, /**< MPEG-2 Audio */
|
||||
Mpeg2Video, /**< MPEG-2 Vudio */
|
||||
Mpeg4Video, /**< MPEG-4 */
|
||||
Mpc, /**< Musepack */
|
||||
Pcm, /**< Pulse Code Modulation */
|
||||
Png, /**< PNG */
|
||||
ProRes, /**< ProRes */
|
||||
Qcelp, /**< QCELP */
|
||||
QuicktimeAudio, /**< Quicktime Audio */
|
||||
QuicktimeVideo, /**< Quicktime Video */
|
||||
RealAudio, /**< Real Audio */
|
||||
RealVideo, /**< Real Video */
|
||||
Sa0c, /**< SAOC */
|
||||
Smv, /**< SMV */
|
||||
StreamingTextStream, /**< Streaming Text Stream */
|
||||
SynthesizedTextureStream, /**< Synthesized Texture Stream */
|
||||
Systems, /**< Systems */
|
||||
TextSubtitle, /**< Text subtitle */
|
||||
Theora, /**< Theora */
|
||||
Tiff, /**< TIFF */
|
||||
Tta, /**< The True Audio lessles audio compressor */
|
||||
UncompressedVideoFrames, /**< uncompressed RGB */
|
||||
Vc1, /**< VC-1 */
|
||||
VobBtn, /**< VobBtn */
|
||||
VobSub, /**< VobSub */
|
||||
Vorbis, /**< Vorbis */
|
||||
WavPack /**< WavPack */
|
||||
};
|
||||
|
||||
const char *mediaFormatName(MediaFormat mediaFormat);
|
||||
/*!
|
||||
* \brief Encapsulates sub formats.
|
||||
*
|
||||
* For instance "Layer 3" is a sub format of MPEG-1 audio.
|
||||
*/
|
||||
namespace SubFormats {
|
||||
|
||||
enum : unsigned char {
|
||||
None
|
||||
};
|
||||
|
||||
enum Mpeg1AudioLayer : unsigned char {
|
||||
Mpeg1Layer1 = 1,
|
||||
Mpeg1Layer2,
|
||||
Mpeg1Layer3
|
||||
};
|
||||
|
||||
enum AacProfile : unsigned char {
|
||||
AacMpeg2MainProfile = 1,
|
||||
AacMpeg2LowComplexityProfile,
|
||||
AacMpeg2SpectralBandReplicationProfile,
|
||||
AacMpeg2ScalableSamplingRateProfile,
|
||||
AacMpeg4MainProfile,
|
||||
AacMpeg4LowComplexityProfile,
|
||||
AacMpeg4SpectralBandReplicationProfile,
|
||||
AacMpeg4ScalableSamplingRateProfile,
|
||||
AacMpeg4LongTermPredictionProfile
|
||||
};
|
||||
|
||||
enum Mpeg2VideoProfile : unsigned char {
|
||||
Mpeg2SimpleProfile = 1,
|
||||
Mpeg2MainProfile,
|
||||
Mpeg2SnrProfile,
|
||||
Mpeg2SpatialProfile,
|
||||
Mpeg2HighProfile,
|
||||
Mpeg2422Profile
|
||||
};
|
||||
|
||||
enum Mpeg4VideoProfile : unsigned char {
|
||||
Mpeg4Sp = 1,
|
||||
Mpeg4Asp,
|
||||
Mpeg4Avc,
|
||||
Mpeg4AvcParams,
|
||||
Mpeg4MsV3
|
||||
};
|
||||
|
||||
enum DtsSpecifier : unsigned char {
|
||||
DtsExpress = 1,
|
||||
DtsLossless,
|
||||
DtsHdHighResolution,
|
||||
DtsHdMasterAudio,
|
||||
};
|
||||
|
||||
enum PcmVersion : unsigned char {
|
||||
PcmIntBe = 1,
|
||||
PcmIntLe,
|
||||
PcmFloatIeee
|
||||
};
|
||||
|
||||
enum TextSubtitle : unsigned char {
|
||||
TextSubBasicUtf8 = 1,
|
||||
TextSubSubtitlesFormat,
|
||||
TextSubAdvancedSubtitlesFormat,
|
||||
TextSubUniversalSubtitleFormat
|
||||
};
|
||||
|
||||
enum ImageSubtitle : unsigned char {
|
||||
ImgSubBmp = 1
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class LIB_EXPORT MediaFormat
|
||||
{
|
||||
public:
|
||||
MediaFormat(GeneralMediaFormat general = GeneralMediaFormat::Unknown, unsigned char sub = 0);
|
||||
|
||||
const char *name() const;
|
||||
const char *abbreviation() const;
|
||||
operator bool() const;
|
||||
|
||||
GeneralMediaFormat general;
|
||||
unsigned char sub;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new media format.
|
||||
*/
|
||||
inline MediaFormat::MediaFormat(GeneralMediaFormat general, unsigned char sub) :
|
||||
general(general),
|
||||
sub(sub)
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \brief Returns whether the media format is known.
|
||||
*/
|
||||
inline MediaFormat::operator bool() const
|
||||
{
|
||||
return general != GeneralMediaFormat::Unknown;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,13 @@ Mp4Atom::Mp4Atom(GenericFileElement::containerType &container, uint64 startOffse
|
|||
GenericFileElement<Mp4Atom>(container, startOffset)
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new top level atom with the specified \a container at the specified \a startOffset.
|
||||
*/
|
||||
Mp4Atom::Mp4Atom(GenericFileElement::containerType &container, uint64 startOffset, uint64 maxSize) :
|
||||
GenericFileElement<Mp4Atom>(container, startOffset, maxSize)
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new sub level atom with the specified \a parent at the specified \a startOffset.
|
||||
*/
|
||||
|
@ -98,7 +105,7 @@ void Mp4Atom::internalParse()
|
|||
if(parent()) {
|
||||
sibling = new Mp4Atom(*(parent()), startOffset() + totalSize());
|
||||
} else {
|
||||
sibling = new Mp4Atom(container(), startOffset() + totalSize());
|
||||
sibling = new Mp4Atom(container(), startOffset() + totalSize(), maxTotalSize() - totalSize());
|
||||
}
|
||||
}
|
||||
m_nextSibling.reset(sibling);
|
||||
|
|
|
@ -35,6 +35,11 @@ public:
|
|||
*/
|
||||
typedef uint32 identifierType;
|
||||
|
||||
/*!
|
||||
* \brief The type used to store element sizes is an unsigned 64-bit integer.
|
||||
*/
|
||||
typedef uint64 dataSizeType;
|
||||
|
||||
/*!
|
||||
* \brief The implementation type is Mp4Atom.
|
||||
*/
|
||||
|
@ -56,6 +61,7 @@ public:
|
|||
static void seekBackAndWriteAtomSize(std::ostream &stream, const std::ostream::pos_type &startOffset, bool denote64BitSize = false);
|
||||
|
||||
protected:
|
||||
Mp4Atom(containerType& container, uint64 startOffset, uint64 maxSize);
|
||||
Mp4Atom(implementationType &parent, uint64 startOffset);
|
||||
|
||||
void internalParse();
|
||||
|
|
150
mp4/mp4ids.cpp
150
mp4/mp4ids.cpp
|
@ -1,5 +1,7 @@
|
|||
#include "mp4ids.h"
|
||||
|
||||
#include "../mediaformat.h"
|
||||
|
||||
namespace Media {
|
||||
|
||||
/*!
|
||||
|
@ -35,15 +37,157 @@ namespace Mp4MediaTypeIds {
|
|||
}
|
||||
|
||||
/*!
|
||||
* \brief Encapsulates all supported MP4 media format IDs.
|
||||
* \brief Encapsulates all supported MP4 media format IDs (aka "FOURCCs").
|
||||
* \sa http://wiki.multimedia.cx/?title=QuickTime_container
|
||||
*/
|
||||
namespace Mp4FormatIds {
|
||||
|
||||
MediaFormat fourccToMediaFormat(uint32 fourccId)
|
||||
{
|
||||
switch(fourccId) {
|
||||
case Mp4FormatIds::Mpeg4Video:
|
||||
return GeneralMediaFormat::Mpeg4Video;
|
||||
case Mp4FormatIds::Avc1:
|
||||
case Mp4FormatIds::Avc2:
|
||||
case Mp4FormatIds::Avc3:
|
||||
case Mp4FormatIds::Avc4:
|
||||
return MediaFormat(GeneralMediaFormat::Mpeg4Video, SubFormats::Mpeg4Avc);
|
||||
case Mp4FormatIds::H263:
|
||||
return MediaFormat(GeneralMediaFormat::Mpeg4Video, SubFormats::Mpeg4Asp);
|
||||
case Mp4FormatIds::Tiff:
|
||||
return GeneralMediaFormat::Tiff;
|
||||
case Mp4FormatIds::Raw:
|
||||
return GeneralMediaFormat::UncompressedVideoFrames;
|
||||
case Mp4FormatIds::Jpeg:
|
||||
return GeneralMediaFormat::Jpeg;
|
||||
case Mp4FormatIds::Gif:
|
||||
return GeneralMediaFormat::Gif;
|
||||
case Mp4FormatIds::AdpcmAcm:
|
||||
return GeneralMediaFormat::AdpcmAcm;
|
||||
case Mp4FormatIds::ImaadpcmAcm:
|
||||
return GeneralMediaFormat::ImaadpcmAcm;
|
||||
case Mp4FormatIds::Mp3CbrOnly:
|
||||
return MediaFormat(GeneralMediaFormat::Mpeg1Audio, SubFormats::Mpeg1Layer3);
|
||||
case Mp4FormatIds::Mpeg4Audio:
|
||||
return GeneralMediaFormat::Aac;
|
||||
case Mp4FormatIds::Alac:
|
||||
return GeneralMediaFormat::Alac;
|
||||
case Mp4FormatIds::Ac3:
|
||||
return GeneralMediaFormat::Ac3;
|
||||
case Mp4FormatIds::Ac4:
|
||||
return GeneralMediaFormat::Ac4;
|
||||
default:
|
||||
return GeneralMediaFormat::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Encapsulates all supported MP4 media format configuration box IDs.
|
||||
* \brief Encapsulates all supported MP4 media format description extensions.
|
||||
* \sa https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html
|
||||
*/
|
||||
namespace Mp4FormatConfigurationIds {
|
||||
namespace Mp4FormatExtensionIds {
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Encapsulates all supported MPEG-4 elementary stream object IDs.
|
||||
*/
|
||||
namespace Mpeg4ElementaryStreamObjectIds {
|
||||
|
||||
/*!
|
||||
* \brief Returns the Media::MediaFormat denoted by the specified MPEG-4 stream ID.
|
||||
*/
|
||||
MediaFormat streamObjectTypeFormat(byte streamObjectTypeId)
|
||||
{
|
||||
switch(streamObjectTypeId) {
|
||||
case SystemsIso144961: return GeneralMediaFormat::Systems;
|
||||
case SystemsIso144961v2: return MediaFormat(GeneralMediaFormat::Systems, 2);
|
||||
case InteractionStream: return GeneralMediaFormat::InteractionStream;
|
||||
case AfxStream: return GeneralMediaFormat::AfxStream;
|
||||
case FontDataStream: return GeneralMediaFormat::FontDataStream;
|
||||
case SynthesizedTextureStream: return GeneralMediaFormat::SynthesizedTextureStream;
|
||||
case StreamingTextStream: return GeneralMediaFormat::StreamingTextStream;
|
||||
case Mpeg4Visual: return GeneralMediaFormat::Mpeg4Video;
|
||||
case Avc: return MediaFormat(GeneralMediaFormat::Mpeg4Video, SubFormats::Mpeg4Avc);
|
||||
case ParameterSetsForAvc: return MediaFormat(GeneralMediaFormat::Mpeg4Video, SubFormats::Mpeg4AvcParams);
|
||||
case Als: return GeneralMediaFormat::Als;
|
||||
case Sa0c: return GeneralMediaFormat::Sa0c;
|
||||
case Aac: return GeneralMediaFormat::Aac;
|
||||
case Mpeg2VideoSimpleProfile: return MediaFormat(GeneralMediaFormat::Mpeg4Video, SubFormats::Mpeg2SimpleProfile);
|
||||
case Mpeg2VideoMainProfile: return MediaFormat(GeneralMediaFormat::Mpeg4Video, SubFormats::Mpeg2SnrProfile);
|
||||
case Mpeg2VideoSnrProfile: return MediaFormat(GeneralMediaFormat::Mpeg4Video, SubFormats::Mpeg2SpatialProfile);
|
||||
case Mpeg2VideoSpatialProfile: return MediaFormat(GeneralMediaFormat::Mpeg4Video, SubFormats::Mpeg2HighProfile);
|
||||
case Mpeg2VideoHighProfile: return MediaFormat(GeneralMediaFormat::Mpeg4Video, SubFormats::Mpeg2HighProfile);
|
||||
case Mpeg2Video422Profile: return MediaFormat(GeneralMediaFormat::Mpeg4Video, SubFormats::Mpeg2SimpleProfile);
|
||||
case AacMainProfile: return MediaFormat(GeneralMediaFormat::Aac, SubFormats::AacMpeg2MainProfile);
|
||||
case AacLowComplexityProfile: return MediaFormat(GeneralMediaFormat::Aac, SubFormats::AacMpeg2LowComplexityProfile);
|
||||
case AacScaleableSamplingRateProfile: return MediaFormat(GeneralMediaFormat::Aac, SubFormats::AacMpeg2ScalableSamplingRateProfile);
|
||||
case Mpeg2Audio: return GeneralMediaFormat::Mpeg2Audio;
|
||||
case Mpeg1Video: return GeneralMediaFormat::Mpeg1Video;
|
||||
case Mpeg1Audio: return GeneralMediaFormat::Mpeg1Audio;
|
||||
case Jpeg: return GeneralMediaFormat::Jpeg;
|
||||
case Png: return GeneralMediaFormat::Png;
|
||||
case Evrc: case PrivateEvrc: return GeneralMediaFormat::Evrc;
|
||||
case Smv: return GeneralMediaFormat::Smv;
|
||||
case Gpp2Cmf: return GeneralMediaFormat::Gpp2Cmf;
|
||||
case Vc1: return GeneralMediaFormat::Vc1;
|
||||
case Dirac: return GeneralMediaFormat::Dirac;
|
||||
case Ac3: case PrivateAc3: return GeneralMediaFormat::Ac3;
|
||||
case EAc3: return GeneralMediaFormat::EAc3;
|
||||
case Dts: case PrivateDts: return GeneralMediaFormat::Dts;
|
||||
case DtsHdHighResolution: return MediaFormat(GeneralMediaFormat::DtsHd, SubFormats::DtsHdHighResolution);
|
||||
case DtsHdMasterAudio: return MediaFormat(GeneralMediaFormat::DtsHd, SubFormats::DtsHdMasterAudio);
|
||||
case DtsHdExpress: return MediaFormat(GeneralMediaFormat::DtsHd, SubFormats::DtsExpress);
|
||||
case PrivateOgg: case PrivateOgg2: return GeneralMediaFormat::Vorbis;
|
||||
case PrivateQcelp: return GeneralMediaFormat::Qcelp;
|
||||
default: return MediaFormat();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Encapsulates all known MPEG-4 descriptor IDs.
|
||||
*/
|
||||
namespace Mpeg4DescriptorIds {
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the name of the stream type denoted by the specified MPEG-4 stream type ID.
|
||||
*/
|
||||
namespace Mpeg4ElementaryStreamTypeIds {
|
||||
|
||||
/*!
|
||||
* \brief Returns the name of the stream type denoted by the specified MPEG-4 stream type ID.
|
||||
*/
|
||||
const char *streamTypeName(byte streamTypeId)
|
||||
{
|
||||
switch(streamTypeId) {
|
||||
case ObjectDescriptor: return "object descriptor";
|
||||
case ClockReference: return "clock reference";
|
||||
case SceneDescriptor: return "scene descriptor";
|
||||
case Visual: return "visual";
|
||||
case Audio: return "audio";
|
||||
case Mpeg7: return "MPEG-7";
|
||||
case Ipmps: return "IMPS";
|
||||
case ObjectContentInfo: return "object content info";
|
||||
case MpegJava: return "MPEG Java";
|
||||
case Interaction: return "interaction";
|
||||
case Ipmp: return "IPMP";
|
||||
case FontData: return "font data";
|
||||
case StreamingText: return "streaming text";
|
||||
default: "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Encapsulates all supported MPEG-4 audio object format IDs.
|
||||
* \sa http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio
|
||||
*/
|
||||
namespace Mpeg4AudioObjectIds {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
245
mp4/mp4ids.h
245
mp4/mp4ids.h
|
@ -6,6 +6,8 @@
|
|||
namespace Media
|
||||
{
|
||||
|
||||
class MediaFormat;
|
||||
|
||||
namespace Mp4AtomIds {
|
||||
enum KnownValue : uint32 {
|
||||
AvcConfiguration = 0x61766343,
|
||||
|
@ -66,8 +68,8 @@ enum KnownValue : uint32 {
|
|||
TrackExtends = 0x74726578,
|
||||
TrackFragmentRun = 0x7472756E,
|
||||
UserData = 0x75647461,
|
||||
DataEntryUrl = 0x75726C20,
|
||||
DataEntryUrn = 0x75726E20,
|
||||
DataEntryUrl = 0x75726C20,
|
||||
DataEntryUrn = 0x75726E20,
|
||||
VideoMediaHeader = 0x766D6864,
|
||||
Wide = 0x77696465
|
||||
};
|
||||
|
@ -125,39 +127,228 @@ extern const char *cdec;
|
|||
|
||||
namespace Mp4MediaTypeIds {
|
||||
enum KnownValue : uint32 {
|
||||
Sound = 0x736f756e,
|
||||
Video = 0x76696465,
|
||||
Hint = 0x68696e74,
|
||||
Meta = 0x6d657461
|
||||
Sound = 0x736f756e, /**< Sound/Audio */
|
||||
Video = 0x76696465, /**< Video */
|
||||
Hint = 0x68696e74, /**< Hint */
|
||||
Meta = 0x6d657461 /**< Meta */
|
||||
};
|
||||
}
|
||||
|
||||
namespace Mp4FormatIds {
|
||||
enum KnownValue : uint32 {
|
||||
Mpeg4Visual = 0x6d703476,
|
||||
Avc1 = 0x61766331,
|
||||
Avc2 = 0x61766332,
|
||||
Avc3 = 0x61766333,
|
||||
Avc4 = 0x61766334,
|
||||
H263 = 0x68323633,
|
||||
Tiff = 0x74696666,
|
||||
Jpeg = 0x6a706567,
|
||||
Raw = 0x72617720,
|
||||
Gif = 0x67696620,
|
||||
Mp3 = 0x2e6d7033,
|
||||
Mpeg4Audio = 0x6d703461,
|
||||
Alac = 0x616C6163,
|
||||
Ac3 = 0x61632d33,
|
||||
Ac4 = 0x61632d34,
|
||||
AdpcmAcm = 0x6D730002,
|
||||
ImaadpcmAcm = 0x6D730011,
|
||||
Mp3CbrOnly = 0x6D730055
|
||||
Cinepak = 0x63766964, /**< Cinepak */
|
||||
Mpeg4Video = 0x6d703476, /**< MPEG-4 video */
|
||||
Graphics = 0x736D6320, /**< Graphics */
|
||||
Animation = 0x726C6520, /**< Animation */
|
||||
AppleVideo = 0x72707A61, /**< Apple video */
|
||||
Png = 0x706E6720, /**< Portable Network Graphics */
|
||||
Avc1 = 0x61766331, /**< H.264/MPEG-4 AVC video */
|
||||
Avc2 = 0x61766332, /**< H.264/MPEG-4 AVC video */
|
||||
Avc3 = 0x61766333, /**< H.264/MPEG-4 AVC video */
|
||||
Avc4 = 0x61766334, /**< H.264/MPEG-4 AVC video */
|
||||
H263 = 0x68323633, /**< H.263/MPEG-4 ASP video */
|
||||
Tiff = 0x74696666, /**< Tagged Image File Format */
|
||||
Jpeg = 0x6a706567, /**< JPEG */
|
||||
Raw = 0x72617720, /**< Uncompressed RGB */
|
||||
Gif = 0x67696620, /**< CompuServe Graphics Interchange Format */
|
||||
NtscDv25Video = 0x64766320, /**< NTSC DV-25 video */
|
||||
PalDv25Video = 0x64766370, /**< PAL DV-25 video */
|
||||
MotionJpegA = 0x6D6A7061, /**< Motion-JPEG (format A) */
|
||||
MotionJpegB = 0x6D6A7062, /**< Motion-JPEG (format B) */
|
||||
Mp3 = 0x2e6d7033, /**< MPEG-1 Layer 3 */
|
||||
Mpeg4Audio = 0x6d703461, /**< MPEG-4 audio */
|
||||
Mpeg4Stream = 0x6d703473, /**< MPEG-4 stream (other then video/audio) */
|
||||
Alac = 0x616C6163, /**< Apple Losless Audio Codec */
|
||||
Ac3 = 0x61632d33, /**< Dolby Digital */
|
||||
Ac4 = 0x61632d34, /**< ? */
|
||||
AdpcmAcm = 0x6D730002, /**< ? */
|
||||
ImaadpcmAcm = 0x6D730011, /**< ? */
|
||||
Mp3CbrOnly = 0x6D730055 /**< MPEG-1 Layer 3 (constant bitrate only) */
|
||||
};
|
||||
|
||||
MediaFormat fourccToMediaFormat(uint32 fourccId);
|
||||
|
||||
}
|
||||
|
||||
namespace Mp4FormatExtensionIds {
|
||||
enum KnownValue : uint32 {
|
||||
GammaLevel = 0x67616D61, /**< A 32-bit fixed-point number indicating the gamma level at which the image was captured. The decompressor can use this value to gamma-correct at display time. */
|
||||
FieldHandling = 0x6669656C, /**< Two 8-bit integers that define field handling. */
|
||||
DefaultQuantizationTable = 0x6D6A7174, /**< The default quantization table for a Motion-JPEG data stream. */
|
||||
DefaultHuffmanTable = 0x6D6A6874, /**< The default Huffman table for a Motion-JPEG data stream. */
|
||||
Mpeg4ElementaryStreamDescriptor = 0x65736473, /**< An MPEG-4 elementary stream descriptor atom. This extension is required for MPEG-4 video. */
|
||||
Mpeg4ElementaryStreamDescriptor2 = 0x6D346473, /**< Alternative if encoded to AVC stanard. */
|
||||
AvcConfiguration = 0x61766343, /**< An H.264 AVCConfigurationBox. This extension is required for H.264 video as defined in ISO/IEC 14496-15. */
|
||||
PixelAspectRatio = 0x70617370, /**< Pixel aspect ratio. This extension is mandatory for video formats that use non-square pixels. */
|
||||
ColorParameters = 0x636F6C72, /**< An image description extension required for all uncompressed Y´CbCr video types. */
|
||||
CleanAperature = 0x636C6170 /**< Spatial relationship of Y´CbCr components relative to a canonical image center. */
|
||||
};
|
||||
}
|
||||
|
||||
namespace Mp4FormatConfigurationIds {
|
||||
enum KnownValue : uint32 {
|
||||
AvcC = 0x61766343
|
||||
namespace Mpeg4ElementaryStreamObjectIds {
|
||||
enum KnownValue : byte {
|
||||
SystemsIso144961 = 0x01, /**< Systems */
|
||||
SystemsIso144961v2, /**< Systems (version 2) */
|
||||
InteractionStream, /**< Interaction Stream */
|
||||
AfxStream = 0x05, /**< AFX Stream */
|
||||
FontDataStream, /**< Font Data Stream */
|
||||
SynthesizedTextureStream, /**< Synthesized Texture Stream */
|
||||
StreamingTextStream, /**< Streaming Text Stream */
|
||||
Mpeg4Visual = 0x20, /**< MPEG-4 Visual */
|
||||
Avc, /**< Advanced Video Coding */
|
||||
ParameterSetsForAvc, /**< Parameter Sets for Advanced Video Coding */
|
||||
Als = 0x24, /**< ALS */
|
||||
Sa0c = 0x2B, /**< SAOC */
|
||||
Aac = 0x40, /**< Audio ISO/IEC 14496-3 (AAC) */
|
||||
Mpeg2VideoSimpleProfile = 0x60, /**< MPEG-2 Video Simple Profile */
|
||||
Mpeg2VideoMainProfile, /**< MPEG-2 Video Main Profile */
|
||||
Mpeg2VideoSnrProfile, /**< MPEG-2 Video SNR Profile */
|
||||
Mpeg2VideoSpatialProfile, /**< MPEG-2 Video Spatial Profile */
|
||||
Mpeg2VideoHighProfile, /**< MPEG-2 Video High Profile */
|
||||
Mpeg2Video422Profile, /**< MPEG-2 Video 422 Profile */
|
||||
AacMainProfile, /**< Advanced Audio Coding Main Profile */
|
||||
AacLowComplexityProfile, /**< Advanced Audio Coding Low Complexity Profile */
|
||||
AacScaleableSamplingRateProfile, /**< Advanced Audio Coding Scaleable Sampling Rate Profile */
|
||||
Mpeg2Audio, /**< MPEG-2 Audio */
|
||||
Mpeg1Video, /**< MPEG-1 Video */
|
||||
Mpeg1Audio, /**< MPEG-1 Audio */
|
||||
Jpeg, /**< JPEG */
|
||||
Png, /**< PNG */
|
||||
Evrc = 0xA0, /**< EVRC */
|
||||
Smv, /**< SMV */
|
||||
Gpp2Cmf, /**< 3GPP2 Compact Multimedia Format (CMF) */
|
||||
Vc1, /**< VC-1 */
|
||||
Dirac, /**< Dirac */
|
||||
Ac3, /**< AC-3 */
|
||||
EAc3, /**< E-AC-3 */
|
||||
Dts, /**< DTS */
|
||||
DtsHdHighResolution, /**< DTS-HD High Resolution */
|
||||
DtsHdMasterAudio, /**< DTS-HD Master Audio */
|
||||
DtsHdExpress, /**< DTS-HD Express */
|
||||
PrivateEvrc = 0xD1, /**< EVRC */
|
||||
PrivateAc3 = 0xD3, /**< AC-3 */
|
||||
PrivateDts, /**< DTS */
|
||||
PrivateOgg = 0xDD, /**< Ogg */
|
||||
PrivateOgg2, /**< Ogg */
|
||||
PrivateQcelp = 0xE1 /**< QCELP */
|
||||
};
|
||||
|
||||
MediaFormat streamObjectTypeFormat(byte streamObjectTypeId);
|
||||
|
||||
}
|
||||
|
||||
namespace Mpeg4ElementaryStreamTypeIds {
|
||||
enum KnownValue : byte {
|
||||
ObjectDescriptor = 0x01,
|
||||
ClockReference,
|
||||
SceneDescriptor,
|
||||
Visual,
|
||||
Audio,
|
||||
Mpeg7,
|
||||
Ipmps,
|
||||
ObjectContentInfo,
|
||||
MpegJava,
|
||||
Interaction,
|
||||
Ipmp,
|
||||
FontData,
|
||||
StreamingText
|
||||
};
|
||||
|
||||
const char *streamTypeName(byte streamTypeId);
|
||||
|
||||
}
|
||||
|
||||
namespace Mpeg4DescriptorIds {
|
||||
enum KnownValue : byte {
|
||||
ObjectDescr = 0x01,
|
||||
InitialObjectDescr,
|
||||
ElementaryStreamDescr,
|
||||
DecoderConfigDescr,
|
||||
DecoderSpecificInfo,
|
||||
SlConfigDescr,
|
||||
ContentIdentDescr,
|
||||
SupplContentIdentDescr,
|
||||
IpiDescPointer,
|
||||
IpmpDescPointer,
|
||||
IpmpDescr,
|
||||
QoSDescr,
|
||||
RegistrationDescr,
|
||||
EsIdInc,
|
||||
EsIdRef,
|
||||
Mp4I0d,
|
||||
Mp40d,
|
||||
IplDescrPointerRef,
|
||||
ExtendedProfileLevelDescr,
|
||||
ProfileLevelIndicationIndexDescr,
|
||||
ContentClassificationDescr = 0x40,
|
||||
KeyWordDescr,
|
||||
RatingDescr,
|
||||
LanguageDescr,
|
||||
ShortTextualDescr,
|
||||
ExpandedTextualDescr,
|
||||
ContentCreatorNameDescr,
|
||||
ContentCreationDateDescr,
|
||||
IcicCreatorDateDescr,
|
||||
SmpteCameraPositionDescr,
|
||||
SegmentDescr,
|
||||
MediaTimeDescr,
|
||||
IpmpToolsListDescr = 0x60,
|
||||
IpmpToolTag,
|
||||
FlexMuxTimingDescr,
|
||||
FlexMuxCodeTableDescr,
|
||||
ExtSlConfigDescr,
|
||||
FlexMuxIdentDescr,
|
||||
DependencyPointer,
|
||||
DependencyMaker,
|
||||
FlexMuxChannelDescr,
|
||||
UserPrivate = 0xC0
|
||||
};
|
||||
}
|
||||
|
||||
namespace Mpeg4AudioObjectIds {
|
||||
enum KnownValue : byte {
|
||||
Null = 0,
|
||||
AacMain,
|
||||
AacLc, /**< low complexity */
|
||||
AacSsr, /**< scalable sample rate */
|
||||
AacLtp, /**< long term prediction */
|
||||
Sbr, /**< spectral band replication */
|
||||
AacScalable,
|
||||
TwinVq,
|
||||
Celp, /**< code excited linear prediction */
|
||||
Hxvc, /**< harmonic vector excitation coding */
|
||||
Ttsi = 12, /**< text-to-speech interface */
|
||||
MainSynthesis,
|
||||
WavetableSynthesis,
|
||||
GeneralMidi,
|
||||
AlgorithmicSynthesisAudioEffects,
|
||||
ErAacLc, /**< error resillent AAC LC */
|
||||
ErAacLtp = 19,
|
||||
ErAacScalable,
|
||||
ErTwinVq,
|
||||
ErBsac,
|
||||
ErAacLd,
|
||||
ErCelp,
|
||||
ErHvxc,
|
||||
ErHiln,
|
||||
ErParametric,
|
||||
Ssc,
|
||||
Ps,
|
||||
MpegSurround,
|
||||
EscapeValue,
|
||||
Layer1,
|
||||
Layer2,
|
||||
Layer3,
|
||||
Dst,
|
||||
Als, /**< audio lossless */
|
||||
Sls, /**< scalable lossless */
|
||||
ErAacEld, /**< enhanced low delay */
|
||||
SmrSimple, /**< symbolic music representation */
|
||||
SmrMain,
|
||||
UsacNoSbr, /**< unified speech and audio coding */
|
||||
Saoc, /**< spatial audio object coding (no SBR) */
|
||||
LdMpegSurround,
|
||||
Usac /**< unified speech and audio coding */
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -213,22 +213,17 @@ void Mp4Tag::parse(Mp4Atom &metaAtom)
|
|||
addNotification(NotificationType::Critical, "Unable to parse child atoms of meta atom (stores hdlr and ilst atoms).", context);
|
||||
}
|
||||
if(subAtom) {
|
||||
Mp4Atom *child = subAtom->firstChild();
|
||||
Mp4TagField tagField;
|
||||
while(child) {
|
||||
for(Mp4Atom *child : *subAtom) {
|
||||
try {
|
||||
child->parse();
|
||||
tagField.invalidateNotifications();
|
||||
tagField.reparse(*child);
|
||||
fields().insert(pair<fieldType::identifierType, fieldType>(child->id(), tagField));
|
||||
addNotifications(context, *child);
|
||||
addNotifications(context, tagField);
|
||||
child = child->nextSibling();
|
||||
} catch(Failure &) {
|
||||
addNotifications(context, *child);
|
||||
addNotifications(context, tagField);
|
||||
break;
|
||||
}
|
||||
addNotifications(context, *child);
|
||||
addNotifications(context, tagField);
|
||||
}
|
||||
} else {
|
||||
addNotification(NotificationType::Warning, "No ilst atom found (stores attached meta information).", context);
|
||||
|
|
245
mp4/mp4track.cpp
245
mp4/mp4track.cpp
|
@ -2,6 +2,7 @@
|
|||
#include "mp4container.h"
|
||||
#include "mp4track.h"
|
||||
#include "mp4ids.h"
|
||||
#include "mpeg4descriptor.h"
|
||||
|
||||
#include "../exceptions.h"
|
||||
#include "../mediaformat.h"
|
||||
|
@ -21,6 +22,19 @@ namespace Media {
|
|||
|
||||
DateTime startDate = DateTime::fromDate(1904, 1, 1);
|
||||
|
||||
uint32 sampleRateTable[] = {
|
||||
96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000
|
||||
};
|
||||
|
||||
MediaFormat fmtTable[] = {
|
||||
GeneralMediaFormat::Unknown,
|
||||
MediaFormat(GeneralMediaFormat::Aac, SubFormats::AacMpeg4MainProfile),
|
||||
MediaFormat(GeneralMediaFormat::Aac, SubFormats::AacMpeg4LowComplexityProfile),
|
||||
MediaFormat(GeneralMediaFormat::Aac, SubFormats::AacMpeg4ScalableSamplingRateProfile),
|
||||
MediaFormat(GeneralMediaFormat::Aac, SubFormats::AacMpeg4LongTermPredictionProfile),
|
||||
MediaFormat(GeneralMediaFormat::Aac, SubFormats::AacMpeg4SpectralBandReplicationProfile)
|
||||
};
|
||||
|
||||
/*!
|
||||
* \class Media::Mp4Track
|
||||
* \brief Implementation of Media::AbstractTrack for the MP4 container.
|
||||
|
@ -46,6 +60,7 @@ Mp4Track::Mp4Track(Mp4Atom &trakAtom) :
|
|||
m_stcoAtom(nullptr),
|
||||
m_stszAtom(nullptr),
|
||||
m_codecConfigAtom(nullptr),
|
||||
m_esDescAtom(nullptr),
|
||||
m_framesPerSample(1),
|
||||
m_chunkOffsetSize(4),
|
||||
m_chunkCount(0),
|
||||
|
@ -394,37 +409,28 @@ vector<uint64> Mp4Track::readChunkSizes()
|
|||
|
||||
/*!
|
||||
* \brief Reads the AVC configuration for the track.
|
||||
* \remarks Ensure that the format is MediaFormat::Mpeg4Avc before calling.
|
||||
* \remarks
|
||||
* - Returns an empty configuration for non-AVC tracks.
|
||||
* - Notifications might be added.
|
||||
*/
|
||||
AvcConfiguration Mp4Track::readAvcConfiguration()
|
||||
AvcConfiguration Mp4Track::parseAvcConfiguration()
|
||||
{
|
||||
AvcConfiguration config;
|
||||
try {
|
||||
auto configSize = m_codecConfigAtom->dataSize();
|
||||
if(m_codecConfigAtom && configSize >= 5) {
|
||||
// skip first byte (is always 1)
|
||||
m_istream->seekg(m_codecConfigAtom->dataOffset() + 1);
|
||||
// read profile, IDC level, NALU size length
|
||||
config.profileIdc = m_reader.readByte();
|
||||
config.profileCompat = m_reader.readByte();
|
||||
config.levelIdc = m_reader.readByte();
|
||||
config.naluSizeLength = m_reader.readByte() & 0x03;
|
||||
// read SPS infos
|
||||
if((configSize -= 5) >= 3) {
|
||||
byte entryCount = m_reader.readByte() & 0x0f;
|
||||
uint16 entrySize;
|
||||
while(entryCount && configSize) {
|
||||
if((entrySize = m_reader.readUInt16BE()) <= configSize) {
|
||||
// TODO: read entry
|
||||
configSize -= entrySize;
|
||||
} else {
|
||||
throw TruncatedDataException();
|
||||
}
|
||||
--entryCount;
|
||||
}
|
||||
// read PPS infos
|
||||
if(m_codecConfigAtom) {
|
||||
try {
|
||||
auto configSize = m_codecConfigAtom->dataSize();
|
||||
if(m_codecConfigAtom && configSize >= 5) {
|
||||
// skip first byte (is always 1)
|
||||
m_istream->seekg(m_codecConfigAtom->dataOffset() + 1);
|
||||
// read profile, IDC level, NALU size length
|
||||
config.profileIdc = m_reader.readByte();
|
||||
config.profileCompat = m_reader.readByte();
|
||||
config.levelIdc = m_reader.readByte();
|
||||
config.naluSizeLength = m_reader.readByte() & 0x03;
|
||||
// read SPS infos
|
||||
if((configSize -= 5) >= 3) {
|
||||
entryCount = m_reader.readByte();
|
||||
byte entryCount = m_reader.readByte() & 0x0f;
|
||||
uint16 entrySize;
|
||||
while(entryCount && configSize) {
|
||||
if((entrySize = m_reader.readUInt16BE()) <= configSize) {
|
||||
// TODO: read entry
|
||||
|
@ -434,19 +440,107 @@ AvcConfiguration Mp4Track::readAvcConfiguration()
|
|||
}
|
||||
--entryCount;
|
||||
}
|
||||
// TODO: read trailer
|
||||
return config;
|
||||
// read PPS infos
|
||||
if((configSize -= 5) >= 3) {
|
||||
entryCount = m_reader.readByte();
|
||||
while(entryCount && configSize) {
|
||||
if((entrySize = m_reader.readUInt16BE()) <= configSize) {
|
||||
// TODO: read entry
|
||||
configSize -= entrySize;
|
||||
} else {
|
||||
throw TruncatedDataException();
|
||||
}
|
||||
--entryCount;
|
||||
}
|
||||
// TODO: read trailer
|
||||
return config;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw TruncatedDataException();
|
||||
} catch (TruncatedDataException &) {
|
||||
addNotification(NotificationType::Critical, "AVC configuration is truncated.", "parsing AVC configuration");
|
||||
}
|
||||
throw TruncatedDataException();
|
||||
} catch (TruncatedDataException &) {
|
||||
addNotification(NotificationType::Critical, "AVC configuration is truncated.", "parsing AVC configuration");
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Reads the MPEG-4 elementary stream descriptor for the track.
|
||||
* \remarks
|
||||
* - Notifications might be added.
|
||||
* \sa mpeg4ElementaryStreamInfo()
|
||||
*/
|
||||
void Mp4Track::parseMpeg4ElementaryStreamInfo()
|
||||
{
|
||||
static const string context("parsing MPEG-4 elementary stream descriptor");
|
||||
if(m_esDescAtom) {
|
||||
if(m_esDescAtom->dataSize() >= 12) {
|
||||
m_istream->seekg(m_esDescAtom->dataOffset());
|
||||
// read version/flags
|
||||
if(m_reader.readUInt32BE() != 0) {
|
||||
addNotification(NotificationType::Warning, "Unknown version/flags.", context);
|
||||
}
|
||||
// read extended descriptor
|
||||
Mpeg4Descriptor esDesc(m_esDescAtom->container(), m_istream->tellg(), m_esDescAtom->dataSize() - 4);
|
||||
try {
|
||||
esDesc.parse();
|
||||
// check ID
|
||||
if(esDesc.id() != Mpeg4DescriptorIds::ElementaryStreamDescr) {
|
||||
addNotification(NotificationType::Critical, "Invalid descriptor found.", context);
|
||||
throw Failure();
|
||||
}
|
||||
// read stream info
|
||||
m_istream->seekg(esDesc.dataOffset());
|
||||
m_esInfo = make_unique<Mpeg4ElementaryStreamInfo>();
|
||||
m_esInfo->id = m_reader.readUInt16BE();
|
||||
m_esInfo->esDescFlags = m_reader.readByte();
|
||||
if(m_esInfo->dependencyFlag()) {
|
||||
m_esInfo->dependsOnId = m_reader.readUInt16BE();
|
||||
}
|
||||
if(m_esInfo->urlFlag()) {
|
||||
m_esInfo->url = m_reader.readString(m_reader.readByte());
|
||||
}
|
||||
if(m_esInfo->ocrFlag()) {
|
||||
m_esInfo->ocrId = m_reader.readUInt16BE();
|
||||
}
|
||||
for(Mpeg4Descriptor *esDescChild = esDesc.denoteFirstChild(static_cast<uint64>(m_istream->tellg()) - esDesc.startOffset()); esDescChild; esDescChild = esDescChild->nextSibling()) {
|
||||
esDescChild->parse();
|
||||
switch(esDescChild->id()) {
|
||||
case Mpeg4DescriptorIds::DecoderConfigDescr:
|
||||
// read decoder config descriptor
|
||||
m_istream->seekg(esDescChild->dataOffset());
|
||||
m_esInfo->objectTypeId = m_reader.readByte();
|
||||
m_esInfo->decCfgDescFlags = m_reader.readByte();
|
||||
m_esInfo->bufferSize = m_reader.readUInt24BE();
|
||||
m_esInfo->maxBitrate = m_reader.readUInt32BE();
|
||||
m_esInfo->averageBitrate = m_reader.readUInt32BE();
|
||||
for(Mpeg4Descriptor *decCfgDescChild = esDescChild->denoteFirstChild(13); decCfgDescChild; decCfgDescChild = decCfgDescChild->nextSibling()) {
|
||||
decCfgDescChild->parse();
|
||||
switch(esDescChild->id()) {
|
||||
case Mpeg4DescriptorIds::DecoderSpecificInfo:
|
||||
// read decoder specific info
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Mpeg4DescriptorIds::SlConfigDescr:
|
||||
// uninteresting
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Failure &) {
|
||||
// notifications will be added in any case
|
||||
}
|
||||
addNotifications(esDesc);
|
||||
} else {
|
||||
addNotification(NotificationType::Warning, "Elementary stream descriptor atom (esds) is truncated.", context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the chunk offsets of the track. This is necessary when the mdat atom (which contains
|
||||
* the actual chunk data) is moved.
|
||||
* \param oldMdatOffsets Specifies a vector holding the old offsets of the "mdat"-atoms.
|
||||
|
@ -648,16 +742,16 @@ void Mp4Track::makeMedia()
|
|||
writer().writeUInt32BE(Mp4AtomIds::HandlerReference);
|
||||
writer().writeUInt64BE(0); // version, flags, pre defined
|
||||
switch(m_mediaType) {
|
||||
case MediaType::Visual:
|
||||
case MediaType::Video:
|
||||
outputStream().write("vide", 4);
|
||||
break;
|
||||
case MediaType::Acoustic:
|
||||
case MediaType::Audio:
|
||||
outputStream().write("soun", 4);
|
||||
break;
|
||||
case MediaType::Hint:
|
||||
outputStream().write("hint", 4);
|
||||
break;
|
||||
case MediaType::Textual:
|
||||
case MediaType::Text:
|
||||
outputStream().write("meta", 4);
|
||||
break;
|
||||
default:
|
||||
|
@ -730,6 +824,7 @@ void Mp4Track::makeMediaInfo()
|
|||
/*!
|
||||
* \brief Makes the sample table (stbl atom) for the track. The data is written to the assigned output stream
|
||||
* at the current position.
|
||||
* \remarks Not fully implemented yet.
|
||||
*/
|
||||
void Mp4Track::makeSampleTable()
|
||||
{
|
||||
|
@ -917,13 +1012,13 @@ void Mp4Track::internalParseHeader()
|
|||
m_istream->seekg(m_hdlrAtom->startOffset() + 16); // seek to beg, skip size, name, version, flags and reserved bytes
|
||||
string trackTypeStr = reader.readString(4);
|
||||
if(trackTypeStr == "soun") {
|
||||
m_mediaType = MediaType::Acoustic;
|
||||
m_mediaType = MediaType::Audio;
|
||||
} else if(trackTypeStr == "vide") {
|
||||
m_mediaType = MediaType::Visual;
|
||||
m_mediaType = MediaType::Video;
|
||||
} else if(trackTypeStr == "hint") {
|
||||
m_mediaType = MediaType::Hint;
|
||||
} else if(trackTypeStr == "meta") {
|
||||
m_mediaType = MediaType::Textual;
|
||||
m_mediaType = MediaType::Text;
|
||||
} else {
|
||||
m_mediaType = MediaType::Unknown;
|
||||
}
|
||||
|
@ -941,69 +1036,37 @@ void Mp4Track::internalParseHeader()
|
|||
if((codecConfigContainerAtom = m_stsdAtom->firstChild())) {
|
||||
try {
|
||||
codecConfigContainerAtom->parse();
|
||||
switch(codecConfigContainerAtom->id()) {
|
||||
case Mp4FormatIds::Mpeg4Visual:
|
||||
m_format = MediaFormat::Mpeg4;
|
||||
break;
|
||||
case Mp4FormatIds::Avc1:
|
||||
case Mp4FormatIds::Avc2:
|
||||
case Mp4FormatIds::Avc3:
|
||||
case Mp4FormatIds::Avc4:
|
||||
m_format = MediaFormat::Mpeg4Avc;
|
||||
m_codecConfigAtom = codecConfigContainerAtom->childById(Mp4AtomIds::AvcConfiguration);
|
||||
break;
|
||||
case Mp4FormatIds::H263:
|
||||
m_format = MediaFormat::Mpeg4Asp;
|
||||
break;
|
||||
case Mp4FormatIds::Tiff:
|
||||
m_format = MediaFormat::Tiff;
|
||||
break;
|
||||
case Mp4FormatIds::Raw:
|
||||
m_format = MediaFormat::UncompressedRgb;
|
||||
break;
|
||||
case Mp4FormatIds::Jpeg:
|
||||
m_format = MediaFormat::Jpeg;
|
||||
break;
|
||||
case Mp4FormatIds::Gif:
|
||||
m_format = MediaFormat::Gif;
|
||||
break;
|
||||
case Mp4FormatIds::AdpcmAcm:
|
||||
m_format = MediaFormat::AdpcmAcm;
|
||||
break;
|
||||
case Mp4FormatIds::ImaadpcmAcm:
|
||||
m_format = MediaFormat::ImaadpcmAcm;
|
||||
break;
|
||||
case Mp4FormatIds::Mp3CbrOnly:
|
||||
m_format = MediaFormat::MpegL3;
|
||||
break;
|
||||
case Mp4FormatIds::Mpeg4Audio:
|
||||
m_format = MediaFormat::Aac;
|
||||
break;
|
||||
case Mp4FormatIds::Alac:
|
||||
m_format = MediaFormat::Alac;
|
||||
break;
|
||||
case Mp4FormatIds::Ac3:
|
||||
m_format = MediaFormat::Ac3;
|
||||
break;
|
||||
case Mp4FormatIds::Ac4:
|
||||
m_format = MediaFormat::Ac4;
|
||||
break;
|
||||
default:
|
||||
// format id is unknown
|
||||
m_format = MediaFormat::Unknown;
|
||||
m_formatId = interpretIntegerAsString<uint32>(codecConfigContainerAtom->id());
|
||||
// parse FOURCC
|
||||
m_formatId = interpretIntegerAsString<uint32>(codecConfigContainerAtom->id());
|
||||
m_format = Mp4FormatIds::fourccToMediaFormat(codecConfigContainerAtom->id());
|
||||
// parse AVC configuration
|
||||
m_codecConfigAtom = codecConfigContainerAtom->childById(Mp4AtomIds::AvcConfiguration);
|
||||
// parse MPEG-4 elementary stream descriptor
|
||||
m_esDescAtom = codecConfigContainerAtom->childById(Mp4FormatExtensionIds::Mpeg4ElementaryStreamDescriptor);
|
||||
if(!m_esDescAtom) {
|
||||
m_esDescAtom = codecConfigContainerAtom->childById(Mp4FormatExtensionIds::Mpeg4ElementaryStreamDescriptor2);
|
||||
}
|
||||
try {
|
||||
parseMpeg4ElementaryStreamInfo();
|
||||
if(m_esInfo) {
|
||||
auto mediaFormat = Mpeg4ElementaryStreamObjectIds::streamObjectTypeFormat(m_esInfo->objectTypeId);
|
||||
if(mediaFormat) {
|
||||
m_format = mediaFormat;
|
||||
}
|
||||
}
|
||||
} catch(Failure &) {
|
||||
}
|
||||
// seek to start offset of additional atom and skip reserved bytes and data reference index
|
||||
m_istream->seekg(codecConfigContainerAtom->startOffset() + 8 + 6 + 2);
|
||||
switch(m_mediaType) {
|
||||
case MediaType::Acoustic:
|
||||
case MediaType::Audio:
|
||||
m_istream->seekg(8, ios_base::cur); // skip reserved bytes
|
||||
m_channelCount = reader.readUInt16BE();
|
||||
m_bitsPerSample = reader.readUInt16BE();
|
||||
m_istream->seekg(4, ios_base::cur); // skip reserved bytes
|
||||
m_samplesPerSecond = reader.readUInt32BE() >> 16;
|
||||
break;
|
||||
case MediaType::Visual:
|
||||
case MediaType::Video:
|
||||
m_istream->seekg(16, ios_base::cur); // skip reserved bytes
|
||||
m_pixelSize.setWidth(reader.readUInt16BE());
|
||||
m_pixelSize.setHeight(reader.readUInt16BE());
|
||||
|
|
|
@ -6,12 +6,79 @@
|
|||
#include "../abstracttrack.h"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace Media
|
||||
{
|
||||
|
||||
class Mp4Atom;
|
||||
|
||||
class LIB_EXPORT Mpeg4ElementaryStreamInfo
|
||||
{
|
||||
public:
|
||||
Mpeg4ElementaryStreamInfo();
|
||||
|
||||
uint16 id;
|
||||
byte esDescFlags;
|
||||
uint16 dependsOnId;
|
||||
std::string url;
|
||||
uint16 ocrId;
|
||||
byte objectTypeId;
|
||||
byte decCfgDescFlags;
|
||||
uint32 bufferSize;
|
||||
uint32 maxBitrate;
|
||||
uint32 averageBitrate;
|
||||
|
||||
bool dependencyFlag() const;
|
||||
bool urlFlag() const;
|
||||
bool ocrFlag() const;
|
||||
byte priority() const;
|
||||
byte streamTypeId() const;
|
||||
bool upstream() const;
|
||||
};
|
||||
|
||||
inline Mpeg4ElementaryStreamInfo::Mpeg4ElementaryStreamInfo() :
|
||||
id(0),
|
||||
esDescFlags(0),
|
||||
dependsOnId(0),
|
||||
ocrId(0),
|
||||
objectTypeId(0),
|
||||
decCfgDescFlags(0),
|
||||
bufferSize(0),
|
||||
maxBitrate(0),
|
||||
averageBitrate(0)
|
||||
{}
|
||||
|
||||
inline bool Mpeg4ElementaryStreamInfo::dependencyFlag() const
|
||||
{
|
||||
return esDescFlags & 0x80;
|
||||
}
|
||||
|
||||
inline bool Mpeg4ElementaryStreamInfo::urlFlag() const
|
||||
{
|
||||
return esDescFlags & 0x40;
|
||||
}
|
||||
|
||||
inline bool Mpeg4ElementaryStreamInfo::ocrFlag() const
|
||||
{
|
||||
return esDescFlags & 0x20;
|
||||
}
|
||||
|
||||
inline byte Mpeg4ElementaryStreamInfo::priority() const
|
||||
{
|
||||
return esDescFlags & 0x1F;
|
||||
}
|
||||
|
||||
inline byte Mpeg4ElementaryStreamInfo::streamTypeId() const
|
||||
{
|
||||
return decCfgDescFlags >> 2;
|
||||
}
|
||||
|
||||
inline bool Mpeg4ElementaryStreamInfo::upstream() const
|
||||
{
|
||||
return decCfgDescFlags & 0x02;
|
||||
}
|
||||
|
||||
class LIB_EXPORT Mp4Track : public AbstractTrack
|
||||
{
|
||||
public:
|
||||
|
@ -25,10 +92,13 @@ public:
|
|||
unsigned int chunkOffsetSize() const;
|
||||
uint32 chunkCount() const;
|
||||
uint32 sampleToChunkEntryCount() const;
|
||||
const Mpeg4ElementaryStreamInfo *mpeg4ElementaryStreamInfo() const;
|
||||
std::vector<uint64> readChunkOffsets();
|
||||
std::vector<std::tuple<uint32, uint32, uint32> > readSampleToChunkTable();
|
||||
std::vector<uint64> readChunkSizes();
|
||||
AvcConfiguration readAvcConfiguration();
|
||||
AvcConfiguration parseAvcConfiguration();
|
||||
bool hasMpeg4ElementaryStreamDesc() const;
|
||||
void parseMpeg4ElementaryStreamInfo();
|
||||
void updateChunkOffsets(const std::vector<int64> &oldMdatOffsets, const std::vector<int64> &newMdatOffsets);
|
||||
void updateChunkOffset(uint32 chunkIndex, uint64 offset);
|
||||
void makeTrack();
|
||||
|
@ -56,11 +126,13 @@ private:
|
|||
Mp4Atom *m_stcoAtom;
|
||||
Mp4Atom *m_stszAtom;
|
||||
Mp4Atom *m_codecConfigAtom;
|
||||
Mp4Atom *m_esDescAtom;
|
||||
uint16 m_framesPerSample;
|
||||
std::vector<uint32> m_sampleSizes;
|
||||
unsigned int m_chunkOffsetSize;
|
||||
uint32 m_chunkCount;
|
||||
uint32 m_sampleToChunkEntryCount;
|
||||
std::unique_ptr<Mpeg4ElementaryStreamInfo> m_esInfo;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -109,6 +181,31 @@ inline uint32 Mp4Track::sampleToChunkEntryCount() const
|
|||
return m_sampleToChunkEntryCount;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns information about the MPEG-4 elementary stream.
|
||||
* \remarks
|
||||
* - The Mp4Track::readMpeg4ElementaryStreamInfo() method must be called before
|
||||
* to parse the information. This is done when parsing the track.
|
||||
* - The information is only available, if the track has an MPEG-4 elementary stream
|
||||
* descriptor atom.
|
||||
* - The track keeps ownership over the returned object.
|
||||
* \sa
|
||||
* - readMpeg4ElementaryStreamInfo()
|
||||
* - hasMpeg4ElementaryStreamDesc()
|
||||
*/
|
||||
inline const Mpeg4ElementaryStreamInfo *Mp4Track::mpeg4ElementaryStreamInfo() const
|
||||
{
|
||||
return m_esInfo.get();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns whether the track has an MPEG-4 elementary stream descriptor atom.
|
||||
*/
|
||||
inline bool Mp4Track::hasMpeg4ElementaryStreamDesc() const
|
||||
{
|
||||
return m_esDescAtom != nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // MP4TRACK_H
|
||||
|
|
|
@ -1,7 +1,88 @@
|
|||
#include "mpeg4streamdescriptor.h"
|
||||
#include "mpeg4descriptor.h"
|
||||
#include "mp4container.h"
|
||||
|
||||
Mpeg4StreamDescriptor::Mpeg4StreamDescriptor()
|
||||
#include "mp4ids.h"
|
||||
|
||||
#include <c++utilities/io/binaryreader.h>
|
||||
#include <c++utilities/conversion/stringconversion.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace ConversionUtilities;
|
||||
|
||||
namespace Media {
|
||||
|
||||
/*!
|
||||
* \class Media::Mpeg4Descriptor
|
||||
* \brief The Mpeg4Descriptor class helps to parse MPEG-4 descriptors.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new top level descriptor with the specified \a container at the specified \a startOffset
|
||||
* and with the specified \a maxSize.
|
||||
*/
|
||||
Mpeg4Descriptor::Mpeg4Descriptor(containerType &container, uint64 startOffset, uint64 maxSize) :
|
||||
GenericFileElement<Mpeg4Descriptor>(container, startOffset, maxSize)
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new sub level descriptor with the specified \a parent at the specified \a startOffset.
|
||||
*/
|
||||
Mpeg4Descriptor::Mpeg4Descriptor(implementationType &parent, uint64 startOffset) :
|
||||
GenericFileElement<Mpeg4Descriptor>(parent, startOffset)
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \brief Returns the parsing context.
|
||||
*/
|
||||
string Mpeg4Descriptor::parsingContext() const
|
||||
{
|
||||
|
||||
return "parsing " + idToString() + " descriptor at " + numberToString(startOffset());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the specified atom \a ID to a printable string.
|
||||
*/
|
||||
std::string Mpeg4Descriptor::idToString() const
|
||||
{
|
||||
return "0x" + ConversionUtilities::numberToString(id(), 16);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Parses the MPEG-4 descriptor.
|
||||
* \remarks Does not detect the first child.
|
||||
*/
|
||||
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");
|
||||
throw TruncatedDataException();
|
||||
}
|
||||
stream().seekg(startOffset());
|
||||
// read ID
|
||||
m_idLength = m_sizeLength = 1;
|
||||
m_id = reader().readByte();
|
||||
// read data size
|
||||
byte tmp = reader().readByte() & 0x80;
|
||||
m_dataSize = tmp & 0x7F;
|
||||
while(tmp & 0x80) {
|
||||
m_dataSize = (m_dataSize << 7) | ((tmp = reader().readByte()) & 0x7F);
|
||||
++m_sizeLength;
|
||||
}
|
||||
// check whether the denoted data size exceeds the available data size
|
||||
if(maxTotalSize() < totalSize()) {
|
||||
addNotification(NotificationType::Warning, "The descriptor seems to be truncated; unable to parse siblings of that ", parsingContext());
|
||||
m_dataSize = maxTotalSize(); // using max size instead
|
||||
}
|
||||
m_firstChild.reset();
|
||||
implementationType *sibling = nullptr;
|
||||
if(totalSize() < maxTotalSize()) {
|
||||
if(parent()) {
|
||||
sibling = new implementationType(*(parent()), startOffset() + totalSize());
|
||||
} else {
|
||||
sibling = new implementationType(container(), startOffset() + totalSize(), maxTotalSize() - totalSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,103 @@
|
|||
#ifndef MPEG4STREAMDESCRIPTOR_H
|
||||
#define MPEG4STREAMDESCRIPTOR_H
|
||||
#ifndef MPEG4DESCRIPTOR_H
|
||||
#define MPEG4DESCRIPTOR_H
|
||||
|
||||
#include "../genericfileelement.h"
|
||||
|
||||
class Mpeg4StreamDescriptor
|
||||
#include <c++utilities/misc/memory.h>
|
||||
|
||||
namespace Media {
|
||||
|
||||
class Mp4Container;
|
||||
class Mpeg4Descriptor;
|
||||
|
||||
/*!
|
||||
* \brief Defines traits for the GenericFileElement implementation Mpeg4Descriptor.
|
||||
*/
|
||||
template <>
|
||||
class LIB_EXPORT FileElementTraits<Mpeg4Descriptor>
|
||||
{
|
||||
public:
|
||||
Mpeg4StreamDescriptor();
|
||||
/*!
|
||||
* \brief The container type used to store such elements is Mp4Container.
|
||||
*/
|
||||
typedef Mp4Container containerType;
|
||||
|
||||
/*!
|
||||
* \brief The type used to store atom IDs is an unsigned 32-bit integer.
|
||||
*/
|
||||
typedef byte identifierType;
|
||||
|
||||
/*!
|
||||
* \brief The type used to store element sizes is an unsigned 32-bit integer.
|
||||
*/
|
||||
typedef uint32 dataSizeType;
|
||||
|
||||
/*!
|
||||
* \brief The implementation type is Mp4Atom.
|
||||
*/
|
||||
typedef Mpeg4Descriptor implementationType;
|
||||
};
|
||||
|
||||
#endif // MPEG4STREAMDESCRIPTOR_H
|
||||
class LIB_EXPORT Mpeg4Descriptor : public GenericFileElement<Mpeg4Descriptor>
|
||||
{
|
||||
friend class GenericFileElement<Mpeg4Descriptor>;
|
||||
|
||||
public:
|
||||
Mpeg4Descriptor(containerType& container, uint64 startOffset, uint64 maxSize);
|
||||
|
||||
std::string idToString() const;
|
||||
bool isParent() const;
|
||||
bool isPadding() const;
|
||||
uint64 firstChildOffset() const;
|
||||
implementationType *denoteFirstChild(uint32 offset);
|
||||
|
||||
protected:
|
||||
Mpeg4Descriptor(implementationType &parent, uint64 startOffset);
|
||||
|
||||
void internalParse();
|
||||
|
||||
private:
|
||||
std::string parsingContext() const;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Returns an indication whether the descriptor contains sub descriptors.
|
||||
*
|
||||
* \remarks Returns true if a first child has been denoted (via denoteFirstChild()).
|
||||
*/
|
||||
inline bool Mpeg4Descriptor::isParent() const
|
||||
{
|
||||
return m_firstChild != nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns always false for MPEG-4 descriptors.
|
||||
*/
|
||||
inline bool Mpeg4Descriptor::isPadding() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the offset of the first child (relative to the start offset of this descriptor).
|
||||
*
|
||||
* \remarks The first child must be denoted (via denoteFirstChild()).
|
||||
*/
|
||||
inline uint64 Mpeg4Descriptor::firstChildOffset() const
|
||||
{
|
||||
return firstChild() ? firstChild()->startOffset() - startOffset() : 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Denotes the first child to start at the specified \a offset (relative to the start offset of this descriptor).
|
||||
* \remarks A new first child is constructed. A possibly existing subtree is invalidated.
|
||||
*/
|
||||
inline Mpeg4Descriptor::implementationType *Mpeg4Descriptor::denoteFirstChild(uint32 relativeFirstChildOffset)
|
||||
{
|
||||
m_firstChild.reset(new implementationType(static_cast<implementationType &>(*this), startOffset() + relativeFirstChildOffset));
|
||||
return m_firstChild.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // MPEG4DESCRIPTOR_H
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace Media {
|
|||
MpegAudioFrameStream::MpegAudioFrameStream(iostream &stream, uint64 startOffset) :
|
||||
AbstractTrack(stream, startOffset)
|
||||
{
|
||||
m_mediaType = MediaType::Acoustic;
|
||||
m_mediaType = MediaType::Audio;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -56,19 +56,7 @@ void MpegAudioFrameStream::internalParseHeader()
|
|||
MpegAudioFrame frame;
|
||||
frame.parseHeader(*m_istream);
|
||||
m_version = frame.mpegVersion();
|
||||
switch(frame.layer()) {
|
||||
case 1:
|
||||
m_format = MediaFormat::MpegL1;
|
||||
break;
|
||||
case 2:
|
||||
m_format = MediaFormat::MpegL2;
|
||||
break;
|
||||
case 3:
|
||||
m_format = MediaFormat::MpegL3;
|
||||
break;
|
||||
default:
|
||||
m_format = MediaFormat::Unknown;
|
||||
}
|
||||
m_format = MediaFormat(GeneralMediaFormat::Mpeg1Audio, frame.layer());
|
||||
m_channelCount = frame.channelMode() == MpegChannelMode::SingleChannel ? 1 : 2;
|
||||
m_samplesPerSecond = frame.samperate();
|
||||
if(frame.isXingBytesfieldPresent()) {
|
||||
|
|
|
@ -61,12 +61,12 @@ void OggStream::internalParseHeader()
|
|||
if((sig & 0x00ffffffffffff00u) == 0x00766F7262697300u) {
|
||||
// Vorbis header detected
|
||||
// set Vorbis as format
|
||||
switch(m_format) {
|
||||
case MediaFormat::Unknown:
|
||||
m_format = MediaFormat::Vorbis;
|
||||
m_mediaType = MediaType::Acoustic;
|
||||
switch(m_format.general) {
|
||||
case GeneralMediaFormat::Unknown:
|
||||
m_format = GeneralMediaFormat::Vorbis;
|
||||
m_mediaType = MediaType::Audio;
|
||||
break;
|
||||
case MediaFormat::Vorbis:
|
||||
case GeneralMediaFormat::Vorbis:
|
||||
break;
|
||||
default:
|
||||
addNotification(NotificationType::Warning, "Stream format is inconsistent.", context);
|
||||
|
|
|
@ -226,14 +226,14 @@ const char *containerFormatAbbreviation(ContainerFormat containerFormat, MediaTy
|
|||
case ContainerFormat::Lzw: return "lzw";
|
||||
case ContainerFormat::Mp4:
|
||||
switch(mediaType) {
|
||||
case MediaType::Acoustic:
|
||||
case MediaType::Audio:
|
||||
return "m4a";
|
||||
default:
|
||||
return "mp4";
|
||||
}
|
||||
case ContainerFormat::Ogg: return "ogg";
|
||||
switch(mediaType) {
|
||||
case MediaType::Visual:
|
||||
case MediaType::Video:
|
||||
return "ogv";
|
||||
default:
|
||||
return "ogg";
|
||||
|
@ -244,7 +244,7 @@ const char *containerFormatAbbreviation(ContainerFormat containerFormat, MediaTy
|
|||
case ContainerFormat::Rar: return "rar";
|
||||
case ContainerFormat::Matroska:
|
||||
switch(mediaType) {
|
||||
case MediaType::Acoustic:
|
||||
case MediaType::Audio:
|
||||
return "mka";
|
||||
default:
|
||||
return "mkv";
|
||||
|
@ -393,21 +393,21 @@ const char *containerMimeType(ContainerFormat containerFormat, MediaType mediaTy
|
|||
return "audio/mpeg";
|
||||
case ContainerFormat::Mp4:
|
||||
switch(mediaType) {
|
||||
case MediaType::Acoustic:
|
||||
case MediaType::Audio:
|
||||
return "audio/mp4";
|
||||
default:
|
||||
return "video/mp4";
|
||||
}
|
||||
case ContainerFormat::Ogg:
|
||||
switch(mediaType) {
|
||||
case MediaType::Acoustic:
|
||||
case MediaType::Audio:
|
||||
return "audio/ogg";
|
||||
default:
|
||||
return "video/ogg";
|
||||
}
|
||||
case ContainerFormat::Matroska:
|
||||
switch(mediaType) {
|
||||
case MediaType::Acoustic:
|
||||
case MediaType::Audio:
|
||||
return "audio/x-matroska";
|
||||
default:
|
||||
return "video/x-matroska";
|
||||
|
|
2
size.h
2
size.h
|
@ -94,7 +94,7 @@ inline constexpr bool Size::isNull() const
|
|||
inline std::string Size::toString() const
|
||||
{
|
||||
std::stringstream res;
|
||||
res << "width: " << m_width << "; height: " << m_height;
|
||||
res << "width: " << m_width << ", height: " << m_height;
|
||||
return std::string(res.str());
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,8 @@ SOURCES += \
|
|||
abstractattachment.cpp \
|
||||
matroska/matroskaattachment.cpp \
|
||||
mediaformat.cpp \
|
||||
avc/avcconfiguration.cpp
|
||||
avc/avcconfiguration.cpp \
|
||||
mp4/mpeg4descriptor.cpp
|
||||
|
||||
HEADERS += \
|
||||
abstractcontainer.h \
|
||||
|
@ -132,7 +133,8 @@ HEADERS += \
|
|||
matroska/matroskaattachment.h \
|
||||
mediaformat.h \
|
||||
avc/avcconfiguration.h \
|
||||
generictagfield.h
|
||||
generictagfield.h \
|
||||
mp4/mpeg4descriptor.h
|
||||
|
||||
LIBS += -lz
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Media {
|
|||
WaveAudioStream::WaveAudioStream(iostream &stream, uint64 startOffset) :
|
||||
AbstractTrack(stream, startOffset)
|
||||
{
|
||||
m_mediaType = MediaType::Acoustic;
|
||||
m_mediaType = MediaType::Audio;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -46,16 +46,16 @@ void WaveAudioStream::internalParseHeader()
|
|||
if(restHeaderLen >= 16u) {
|
||||
switch(m_reader.readUInt16LE()) {
|
||||
case 0x0001u:
|
||||
m_format = MediaFormat::Pcm;
|
||||
m_format = GeneralMediaFormat::Pcm;
|
||||
break;
|
||||
case 0x0050u:
|
||||
m_format = MediaFormat::MpegL2;
|
||||
m_format = MediaFormat(GeneralMediaFormat::Mpeg1Audio, SubFormats::Mpeg1Layer2);
|
||||
break;
|
||||
case 0x0055u:
|
||||
m_format = MediaFormat::MpegL3;
|
||||
m_format = MediaFormat(GeneralMediaFormat::Mpeg1Audio, SubFormats::Mpeg1Layer3);
|
||||
break;
|
||||
default:
|
||||
m_format = MediaFormat::Unknown;
|
||||
m_format = GeneralMediaFormat::Unknown;
|
||||
}
|
||||
m_channelCount = m_reader.readUInt16LE();
|
||||
m_samplesPerSecond = m_reader.readUInt32LE();
|
||||
|
@ -64,7 +64,7 @@ void WaveAudioStream::internalParseHeader()
|
|||
m_bitsPerSample = m_reader.readUInt16LE();
|
||||
m_bitrate = m_bitsPerSample * m_samplesPerSecond * m_channelCount;
|
||||
} else {
|
||||
m_format = MediaFormat::Unknown;
|
||||
m_format = GeneralMediaFormat::Unknown;
|
||||
}
|
||||
if(restHeaderLen > 16u) {
|
||||
m_istream->seekg(m_dataOffset, ios_base::beg);
|
||||
|
|
Loading…
Reference in New Issue