2018-03-06 23:09:15 +01:00
|
|
|
#ifndef TAG_PARSER_MP4TRACK_H
|
|
|
|
#define TAG_PARSER_MP4TRACK_H
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2015-09-06 19:57:33 +02:00
|
|
|
#include "../abstracttrack.h"
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2015-06-07 00:18:28 +02:00
|
|
|
#include <memory>
|
2018-03-07 01:17:50 +01:00
|
|
|
#include <vector>
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2018-03-07 01:17:50 +01:00
|
|
|
namespace TagParser {
|
2015-04-22 19:22:01 +02:00
|
|
|
|
|
|
|
class Mp4Atom;
|
2015-06-10 01:28:22 +02:00
|
|
|
class Mpeg4Descriptor;
|
2017-06-10 21:46:25 +02:00
|
|
|
struct AvcConfiguration;
|
2018-08-23 23:18:57 +02:00
|
|
|
struct Av1Configuration;
|
2017-09-14 01:37:15 +02:00
|
|
|
struct TrackHeaderInfo;
|
2015-06-10 01:28:22 +02:00
|
|
|
|
2018-03-07 01:17:50 +01:00
|
|
|
class TAG_PARSER_EXPORT Mpeg4AudioSpecificConfig {
|
2015-06-10 01:28:22 +02:00
|
|
|
public:
|
|
|
|
Mpeg4AudioSpecificConfig();
|
|
|
|
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint8_t audioObjectType;
|
|
|
|
std::uint8_t sampleFrequencyIndex;
|
|
|
|
std::uint32_t sampleFrequency;
|
|
|
|
std::uint8_t channelConfiguration;
|
|
|
|
std::uint8_t extensionAudioObjectType;
|
2015-06-10 01:28:22 +02:00
|
|
|
bool sbrPresent;
|
|
|
|
bool psPresent;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint8_t extensionSampleFrequencyIndex;
|
|
|
|
std::uint32_t extensionSampleFrequency;
|
|
|
|
std::uint8_t extensionChannelConfiguration;
|
2015-06-10 01:28:22 +02:00
|
|
|
bool frameLengthFlag;
|
|
|
|
bool dependsOnCoreCoder;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint16_t coreCoderDelay;
|
|
|
|
std::uint8_t extensionFlag;
|
|
|
|
std::uint8_t layerNr;
|
|
|
|
std::uint8_t numOfSubFrame;
|
|
|
|
std::uint16_t layerLength;
|
|
|
|
std::uint8_t resilienceFlags;
|
|
|
|
std::uint8_t epConfig;
|
2015-06-10 01:28:22 +02:00
|
|
|
};
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2018-03-07 01:17:50 +01:00
|
|
|
class TAG_PARSER_EXPORT Mpeg4VideoSpecificConfig {
|
2015-07-07 03:01:48 +02:00
|
|
|
public:
|
|
|
|
Mpeg4VideoSpecificConfig();
|
|
|
|
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint8_t profile;
|
2015-07-07 03:01:48 +02:00
|
|
|
std::string userData;
|
|
|
|
};
|
|
|
|
|
2018-03-07 01:17:50 +01:00
|
|
|
class TAG_PARSER_EXPORT Mpeg4ElementaryStreamInfo {
|
2015-06-07 00:18:28 +02:00
|
|
|
public:
|
|
|
|
Mpeg4ElementaryStreamInfo();
|
|
|
|
|
2015-06-10 01:28:22 +02:00
|
|
|
bool dependencyFlag() const;
|
|
|
|
bool urlFlag() const;
|
|
|
|
bool ocrFlag() const;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint8_t priority() const;
|
|
|
|
std::uint8_t streamTypeId() const;
|
2015-06-10 01:28:22 +02:00
|
|
|
bool upstream() const;
|
|
|
|
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint16_t id;
|
|
|
|
std::uint8_t esDescFlags;
|
|
|
|
std::uint16_t dependsOnId;
|
2015-06-07 00:18:28 +02:00
|
|
|
std::string url;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint16_t ocrId;
|
|
|
|
std::uint8_t objectTypeId;
|
|
|
|
std::uint8_t decCfgDescFlags;
|
|
|
|
std::uint32_t bufferSize;
|
|
|
|
std::uint32_t maxBitrate;
|
|
|
|
std::uint32_t averageBitrate;
|
2015-06-10 01:28:22 +02:00
|
|
|
std::unique_ptr<Mpeg4AudioSpecificConfig> audioSpecificConfig;
|
2015-07-07 03:01:48 +02:00
|
|
|
std::unique_ptr<Mpeg4VideoSpecificConfig> videoSpecificConfig;
|
2015-06-07 00:18:28 +02:00
|
|
|
};
|
|
|
|
|
2018-03-07 01:17:50 +01:00
|
|
|
inline Mpeg4ElementaryStreamInfo::Mpeg4ElementaryStreamInfo()
|
|
|
|
: id(0)
|
|
|
|
, esDescFlags(0)
|
|
|
|
, dependsOnId(0)
|
|
|
|
, ocrId(0)
|
|
|
|
, objectTypeId(0)
|
|
|
|
, decCfgDescFlags(0)
|
|
|
|
, bufferSize(0)
|
|
|
|
, maxBitrate(0)
|
|
|
|
, averageBitrate(0)
|
|
|
|
{
|
|
|
|
}
|
2015-06-07 00:18:28 +02:00
|
|
|
|
|
|
|
inline bool Mpeg4ElementaryStreamInfo::dependencyFlag() const
|
|
|
|
{
|
|
|
|
return esDescFlags & 0x80;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool Mpeg4ElementaryStreamInfo::urlFlag() const
|
|
|
|
{
|
|
|
|
return esDescFlags & 0x40;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool Mpeg4ElementaryStreamInfo::ocrFlag() const
|
|
|
|
{
|
|
|
|
return esDescFlags & 0x20;
|
|
|
|
}
|
|
|
|
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint8_t Mpeg4ElementaryStreamInfo::priority() const
|
2015-06-07 00:18:28 +02:00
|
|
|
{
|
|
|
|
return esDescFlags & 0x1F;
|
|
|
|
}
|
|
|
|
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint8_t Mpeg4ElementaryStreamInfo::streamTypeId() const
|
2015-06-07 00:18:28 +02:00
|
|
|
{
|
|
|
|
return decCfgDescFlags >> 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool Mpeg4ElementaryStreamInfo::upstream() const
|
|
|
|
{
|
|
|
|
return decCfgDescFlags & 0x02;
|
|
|
|
}
|
|
|
|
|
2020-12-18 21:13:52 +01:00
|
|
|
class TAG_PARSER_EXPORT Mp4Track final : public AbstractTrack {
|
2015-04-22 19:22:01 +02:00
|
|
|
public:
|
|
|
|
Mp4Track(Mp4Atom &trakAtom);
|
2018-03-07 01:11:42 +01:00
|
|
|
~Mp4Track() override;
|
|
|
|
TrackType type() const override;
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2015-06-10 01:28:22 +02:00
|
|
|
// getter methods specific for MP4 tracks
|
|
|
|
Mp4Atom &trakAtom();
|
2019-03-13 19:06:42 +01:00
|
|
|
const std::vector<std::uint32_t> &sampleSizes() const;
|
2015-04-22 19:22:01 +02:00
|
|
|
unsigned int chunkOffsetSize() const;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint32_t chunkCount() const;
|
|
|
|
std::uint32_t sampleToChunkEntryCount() const;
|
2015-06-07 00:18:28 +02:00
|
|
|
const Mpeg4ElementaryStreamInfo *mpeg4ElementaryStreamInfo() const;
|
2016-02-17 20:19:05 +01:00
|
|
|
const AvcConfiguration *avcConfiguration() const;
|
2018-08-23 23:18:57 +02:00
|
|
|
const Av1Configuration *av1Configuration() const;
|
2015-06-10 01:28:22 +02:00
|
|
|
|
|
|
|
// methods to parse configuration details from the track header
|
2018-03-07 01:17:50 +01:00
|
|
|
static std::unique_ptr<Mpeg4ElementaryStreamInfo> parseMpeg4ElementaryStreamInfo(
|
2019-06-10 22:49:11 +02:00
|
|
|
CppUtilities::BinaryReader &reader, Mp4Atom *esDescAtom, Diagnostics &diag);
|
2018-03-07 01:17:50 +01:00
|
|
|
static std::unique_ptr<Mpeg4AudioSpecificConfig> parseAudioSpecificConfig(
|
2019-03-13 19:06:42 +01:00
|
|
|
std::istream &stream, std::uint64_t startOffset, std::uint64_t size, Diagnostics &diag);
|
2018-03-07 01:17:50 +01:00
|
|
|
static std::unique_ptr<Mpeg4VideoSpecificConfig> parseVideoSpecificConfig(
|
2019-06-10 22:49:11 +02:00
|
|
|
CppUtilities::BinaryReader &reader, std::uint64_t startOffset, std::uint64_t size, Diagnostics &diag);
|
2015-06-10 01:28:22 +02:00
|
|
|
|
|
|
|
// methods to read the "index" (chunk offsets and sizes)
|
2019-03-13 19:06:42 +01:00
|
|
|
std::vector<std::uint64_t> readChunkOffsets(bool parseFragments, Diagnostics &diag);
|
|
|
|
std::vector<std::tuple<std::uint32_t, std::uint32_t, std::uint32_t>> readSampleToChunkTable(Diagnostics &diag);
|
|
|
|
std::vector<std::uint64_t> readChunkSizes(TagParser::Diagnostics &diag);
|
2015-06-10 01:28:22 +02:00
|
|
|
|
|
|
|
// methods to make the track header
|
2018-03-05 17:49:29 +01:00
|
|
|
void bufferTrackAtoms(Diagnostics &diag);
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint64_t requiredSize(Diagnostics &diag) const;
|
2018-03-05 17:49:29 +01:00
|
|
|
void makeTrack(Diagnostics &diag);
|
|
|
|
void makeTrackHeader(Diagnostics &diag);
|
|
|
|
void makeMedia(Diagnostics &diag);
|
|
|
|
void makeMediaInfo(Diagnostics &diag);
|
|
|
|
void makeSampleTable(Diagnostics &diag);
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2015-06-10 01:28:22 +02:00
|
|
|
// methods to update chunk offsets
|
2019-03-13 19:06:42 +01:00
|
|
|
void updateChunkOffsets(const std::vector<std::int64_t> &oldMdatOffsets, const std::vector<std::int64_t> &newMdatOffsets);
|
|
|
|
void updateChunkOffsets(const std::vector<std::uint64_t> &chunkOffsets);
|
|
|
|
void updateChunkOffset(std::uint32_t chunkIndex, std::uint64_t offset);
|
2015-06-10 01:28:22 +02:00
|
|
|
|
2016-02-17 20:19:05 +01:00
|
|
|
static void addInfo(const AvcConfiguration &avcConfig, AbstractTrack &track);
|
2018-08-23 23:18:57 +02:00
|
|
|
static void addInfo(const Av1Configuration &av1Config, AbstractTrack &track);
|
2016-02-17 20:19:05 +01:00
|
|
|
|
2015-04-22 19:22:01 +02:00
|
|
|
protected:
|
2018-03-07 01:11:42 +01:00
|
|
|
void internalParseHeader(Diagnostics &diag) override;
|
2015-04-22 19:22:01 +02:00
|
|
|
|
|
|
|
private:
|
2015-06-10 01:28:22 +02:00
|
|
|
// private helper methods
|
2020-11-25 17:54:30 +01:00
|
|
|
std::uint64_t accumulateSampleSizes(std::size_t &sampleIndex, std::size_t count, Diagnostics &diag);
|
2019-03-13 19:06:42 +01:00
|
|
|
void addChunkSizeEntries(
|
2020-11-25 17:54:30 +01:00
|
|
|
std::vector<std::uint64_t> &chunkSizeTable, std::size_t count, std::size_t &sampleIndex, std::uint32_t sampleCount, Diagnostics &diag);
|
2017-09-14 01:37:15 +02:00
|
|
|
TrackHeaderInfo verifyPresentTrackHeader() const;
|
2015-04-22 19:22:01 +02:00
|
|
|
|
|
|
|
Mp4Atom *m_trakAtom;
|
|
|
|
Mp4Atom *m_tkhdAtom;
|
|
|
|
Mp4Atom *m_mdiaAtom;
|
|
|
|
Mp4Atom *m_mdhdAtom;
|
|
|
|
Mp4Atom *m_hdlrAtom;
|
|
|
|
Mp4Atom *m_minfAtom;
|
|
|
|
Mp4Atom *m_stblAtom;
|
|
|
|
Mp4Atom *m_stsdAtom;
|
|
|
|
Mp4Atom *m_stscAtom;
|
|
|
|
Mp4Atom *m_stcoAtom;
|
|
|
|
Mp4Atom *m_stszAtom;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint16_t m_framesPerSample;
|
|
|
|
std::vector<std::uint32_t> m_sampleSizes;
|
2015-04-22 19:22:01 +02:00
|
|
|
unsigned int m_chunkOffsetSize;
|
2019-03-13 19:06:42 +01:00
|
|
|
std::uint32_t m_chunkCount;
|
|
|
|
std::uint32_t m_sampleToChunkEntryCount;
|
2015-06-07 00:18:28 +02:00
|
|
|
std::unique_ptr<Mpeg4ElementaryStreamInfo> m_esInfo;
|
2016-02-17 20:19:05 +01:00
|
|
|
std::unique_ptr<AvcConfiguration> m_avcConfig;
|
2018-08-23 23:18:57 +02:00
|
|
|
std::unique_ptr<Av1Configuration> m_av1Config;
|
2015-04-22 19:22:01 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the trak atom for the current instance.
|
|
|
|
*/
|
|
|
|
inline Mp4Atom &Mp4Track::trakAtom()
|
|
|
|
{
|
|
|
|
return *m_trakAtom;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the sample size table for the track.
|
|
|
|
* \remarks If the table contains only one size this is the constant
|
|
|
|
* sample size.
|
|
|
|
* \remarks The table is empty if the track denotes 64-bit sample sizes.
|
|
|
|
* \sa sampleSizes64()
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline const std::vector<std::uint32_t> &Mp4Track::sampleSizes() const
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
return m_sampleSizes;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the size of a single chunk offset denotation within the stco atom.
|
|
|
|
*
|
|
|
|
* Valid values are 4 and 8 bytes.
|
|
|
|
*/
|
|
|
|
inline unsigned int Mp4Track::chunkOffsetSize() const
|
|
|
|
{
|
|
|
|
return m_chunkOffsetSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the number of chunks denoted by the stco atom.
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint32_t Mp4Track::chunkCount() const
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
return m_chunkCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns the number of "sample to chunk" entries within the stsc atom.
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
inline std::uint32_t Mp4Track::sampleToChunkEntryCount() const
|
2015-04-22 19:22:01 +02:00
|
|
|
{
|
|
|
|
return m_sampleToChunkEntryCount;
|
|
|
|
}
|
|
|
|
|
2015-06-07 00:18:28 +02:00
|
|
|
/*!
|
|
|
|
* \brief Returns information about the MPEG-4 elementary stream.
|
|
|
|
* \remarks
|
2016-02-17 20:19:05 +01:00
|
|
|
* - The track must be parsed before this information becomes available.
|
|
|
|
* - The information is only available, if the track has an MPEG-4 elementary stream descriptor atom.
|
2015-06-07 00:18:28 +02:00
|
|
|
* - The track keeps ownership over the returned object.
|
|
|
|
*/
|
|
|
|
inline const Mpeg4ElementaryStreamInfo *Mp4Track::mpeg4ElementaryStreamInfo() const
|
|
|
|
{
|
|
|
|
return m_esInfo.get();
|
|
|
|
}
|
|
|
|
|
2016-02-17 20:19:05 +01:00
|
|
|
/*!
|
|
|
|
* \brief Returns the AVC configuration.
|
|
|
|
* \remarks
|
|
|
|
* - The track must be parsed before this information becomes available.
|
|
|
|
* - The track keeps ownership over the returned object.
|
|
|
|
*/
|
|
|
|
inline const AvcConfiguration *Mp4Track::avcConfiguration() const
|
|
|
|
{
|
|
|
|
return m_avcConfig.get();
|
|
|
|
}
|
|
|
|
|
2018-08-23 23:18:57 +02:00
|
|
|
/*!
|
|
|
|
* \brief Returns the AV1 configuration.
|
|
|
|
* \remarks
|
|
|
|
* - The track must be parsed before this information becomes available.
|
|
|
|
* - The track keeps ownership over the returned object.
|
|
|
|
*/
|
|
|
|
inline const Av1Configuration *Mp4Track::av1Configuration() const
|
|
|
|
{
|
|
|
|
return m_av1Config.get();
|
|
|
|
}
|
|
|
|
|
2018-03-07 01:17:50 +01:00
|
|
|
} // namespace TagParser
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2018-03-06 23:09:15 +01:00
|
|
|
#endif // TAG_PARSER_MP4TRACK_H
|