#ifndef TAG_PARSER_MP4TRACK_H #define TAG_PARSER_MP4TRACK_H #include "../abstracttrack.h" #include #include namespace TagParser { class Mp4Atom; class Mpeg4Descriptor; struct AvcConfiguration; struct Av1Configuration; struct TrackHeaderInfo; class TAG_PARSER_EXPORT Mpeg4AudioSpecificConfig { public: Mpeg4AudioSpecificConfig(); std::uint8_t audioObjectType; std::uint8_t sampleFrequencyIndex; std::uint32_t sampleFrequency; std::uint8_t channelConfiguration; std::uint8_t extensionAudioObjectType; bool sbrPresent; bool psPresent; std::uint8_t extensionSampleFrequencyIndex; std::uint32_t extensionSampleFrequency; std::uint8_t extensionChannelConfiguration; bool frameLengthFlag; bool dependsOnCoreCoder; 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; }; class TAG_PARSER_EXPORT Mpeg4VideoSpecificConfig { public: Mpeg4VideoSpecificConfig(); std::uint8_t profile; std::string userData; }; class TAG_PARSER_EXPORT Mpeg4ElementaryStreamInfo { public: Mpeg4ElementaryStreamInfo(); bool dependencyFlag() const; bool urlFlag() const; bool ocrFlag() const; std::uint8_t priority() const; std::uint8_t streamTypeId() const; bool upstream() const; std::uint16_t id; std::uint8_t esDescFlags; std::uint16_t dependsOnId; std::string url; std::uint16_t ocrId; std::uint8_t objectTypeId; std::uint8_t decCfgDescFlags; std::uint32_t bufferSize; std::uint32_t maxBitrate; std::uint32_t averageBitrate; std::unique_ptr audioSpecificConfig; std::unique_ptr videoSpecificConfig; }; 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 std::uint8_t Mpeg4ElementaryStreamInfo::priority() const { return esDescFlags & 0x1F; } inline std::uint8_t Mpeg4ElementaryStreamInfo::streamTypeId() const { return decCfgDescFlags >> 2; } inline bool Mpeg4ElementaryStreamInfo::upstream() const { return decCfgDescFlags & 0x02; } class TAG_PARSER_EXPORT Mp4Track : public AbstractTrack { public: Mp4Track(Mp4Atom &trakAtom); ~Mp4Track() override; TrackType type() const override; // getter methods specific for MP4 tracks Mp4Atom &trakAtom(); const std::vector &sampleSizes() const; unsigned int chunkOffsetSize() const; std::uint32_t chunkCount() const; std::uint32_t sampleToChunkEntryCount() const; const Mpeg4ElementaryStreamInfo *mpeg4ElementaryStreamInfo() const; const AvcConfiguration *avcConfiguration() const; const Av1Configuration *av1Configuration() const; // methods to parse configuration details from the track header static std::unique_ptr parseMpeg4ElementaryStreamInfo( CppUtilities::BinaryReader &reader, Mp4Atom *esDescAtom, Diagnostics &diag); static std::unique_ptr parseAudioSpecificConfig( std::istream &stream, std::uint64_t startOffset, std::uint64_t size, Diagnostics &diag); static std::unique_ptr parseVideoSpecificConfig( CppUtilities::BinaryReader &reader, std::uint64_t startOffset, std::uint64_t size, Diagnostics &diag); // methods to read the "index" (chunk offsets and sizes) std::vector readChunkOffsets(bool parseFragments, Diagnostics &diag); std::vector> readSampleToChunkTable(Diagnostics &diag); std::vector readChunkSizes(TagParser::Diagnostics &diag); // methods to make the track header void bufferTrackAtoms(Diagnostics &diag); std::uint64_t requiredSize(Diagnostics &diag) const; void makeTrack(Diagnostics &diag); void makeTrackHeader(Diagnostics &diag); void makeMedia(Diagnostics &diag); void makeMediaInfo(Diagnostics &diag); void makeSampleTable(Diagnostics &diag); // methods to update chunk offsets void updateChunkOffsets(const std::vector &oldMdatOffsets, const std::vector &newMdatOffsets); void updateChunkOffsets(const std::vector &chunkOffsets); void updateChunkOffset(std::uint32_t chunkIndex, std::uint64_t offset); static void addInfo(const AvcConfiguration &avcConfig, AbstractTrack &track); static void addInfo(const Av1Configuration &av1Config, AbstractTrack &track); protected: void internalParseHeader(Diagnostics &diag) override; private: // private helper methods std::uint64_t accumulateSampleSizes(size_t &sampleIndex, size_t count, Diagnostics &diag); void addChunkSizeEntries( std::vector &chunkSizeTable, size_t count, size_t &sampleIndex, std::uint32_t sampleCount, Diagnostics &diag); TrackHeaderInfo verifyPresentTrackHeader() const; 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; std::uint16_t m_framesPerSample; std::vector m_sampleSizes; unsigned int m_chunkOffsetSize; std::uint32_t m_chunkCount; std::uint32_t m_sampleToChunkEntryCount; std::unique_ptr m_esInfo; std::unique_ptr m_avcConfig; std::unique_ptr m_av1Config; }; /*! * \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() */ inline const std::vector &Mp4Track::sampleSizes() const { 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. */ inline std::uint32_t Mp4Track::chunkCount() const { return m_chunkCount; } /*! * \brief Returns the number of "sample to chunk" entries within the stsc atom. */ inline std::uint32_t Mp4Track::sampleToChunkEntryCount() const { return m_sampleToChunkEntryCount; } /*! * \brief Returns information about the MPEG-4 elementary stream. * \remarks * - 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. * - The track keeps ownership over the returned object. */ inline const Mpeg4ElementaryStreamInfo *Mp4Track::mpeg4ElementaryStreamInfo() const { return m_esInfo.get(); } /*! * \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(); } /*! * \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(); } } // namespace TagParser #endif // TAG_PARSER_MP4TRACK_H