diff options
Diffstat (limited to 'dom/media/ADTSDemuxer.cpp')
-rw-r--r-- | dom/media/ADTSDemuxer.cpp | 247 |
1 files changed, 14 insertions, 233 deletions
diff --git a/dom/media/ADTSDemuxer.cpp b/dom/media/ADTSDemuxer.cpp index 29ea270461..49135efc52 100644 --- a/dom/media/ADTSDemuxer.cpp +++ b/dom/media/ADTSDemuxer.cpp @@ -10,6 +10,7 @@ #include "VideoUtils.h" #include "mozilla/Logging.h" #include "mozilla/UniquePtr.h" +#include "Adts.h" #include <inttypes.h> extern mozilla::LazyLogModule gMediaDemuxerLog; @@ -21,227 +22,6 @@ extern mozilla::LazyLogModule gMediaDemuxerLog; DDMOZ_LOG(gMediaDemuxerLog, LogLevel::Verbose, msg, ##__VA_ARGS__) namespace mozilla { -namespace adts { - -// adts::FrameHeader - Holds the ADTS frame header and its parsing -// state. -// -// ADTS Frame Structure -// -// 11111111 1111BCCD EEFFFFGH HHIJKLMM MMMMMMMM MMMOOOOO OOOOOOPP(QQQQQQQQ -// QQQQQQQQ) -// -// Header consists of 7 or 9 bytes(without or with CRC). -// Letter Length(bits) Description -// { sync } 12 syncword 0xFFF, all bits must be 1 -// B 1 MPEG Version: 0 for MPEG-4, 1 for MPEG-2 -// C 2 Layer: always 0 -// D 1 protection absent, Warning, set to 1 if there is no -// CRC and 0 if there is CRC -// E 2 profile, the MPEG-4 Audio Object Type minus 1 -// F 4 MPEG-4 Sampling Frequency Index (15 is forbidden) -// H 3 MPEG-4 Channel Configuration (in the case of 0, the -// channel configuration is sent via an in-band PCE) -// M 13 frame length, this value must include 7 or 9 bytes of -// header length: FrameLength = -// (ProtectionAbsent == 1 ? 7 : 9) + size(AACFrame) -// O 11 Buffer fullness -// P 2 Number of AAC frames(RDBs) in ADTS frame minus 1, for -// maximum compatibility always use 1 AAC frame per ADTS -// frame -// Q 16 CRC if protection absent is 0 -class FrameHeader { - public: - uint32_t mFrameLength{}; - uint32_t mSampleRate{}; - uint32_t mSamples{}; - uint32_t mChannels{}; - uint8_t mObjectType{}; - uint8_t mSamplingIndex{}; - uint8_t mChannelConfig{}; - uint8_t mNumAACFrames{}; - bool mHaveCrc{}; - - // Returns whether aPtr matches a valid ADTS header sync marker - static bool MatchesSync(const uint8_t* aPtr) { - return aPtr[0] == 0xFF && (aPtr[1] & 0xF6) == 0xF0; - } - - FrameHeader() { Reset(); } - - // Header size - uint64_t HeaderSize() const { return (mHaveCrc) ? 9 : 7; } - - bool IsValid() const { return mFrameLength > 0; } - - // Resets the state to allow for a new parsing session. - void Reset() { PodZero(this); } - - // Returns whether the byte creates a valid sequence up to this point. - bool Parse(const uint8_t* aPtr) { - const uint8_t* p = aPtr; - - if (!MatchesSync(p)) { - return false; - } - - // AAC has 1024 samples per frame per channel. - mSamples = 1024; - - mHaveCrc = !(p[1] & 0x01); - mObjectType = ((p[2] & 0xC0) >> 6) + 1; - mSamplingIndex = (p[2] & 0x3C) >> 2; - mChannelConfig = (p[2] & 0x01) << 2 | (p[3] & 0xC0) >> 6; - mFrameLength = static_cast<uint32_t>( - (p[3] & 0x03) << 11 | (p[4] & 0xFF) << 3 | (p[5] & 0xE0) >> 5); - mNumAACFrames = (p[6] & 0x03) + 1; - - static const uint32_t SAMPLE_RATES[] = {96000, 88200, 64000, 48000, 44100, - 32000, 24000, 22050, 16000, 12000, - 11025, 8000, 7350}; - if (mSamplingIndex >= ArrayLength(SAMPLE_RATES)) { - LOG(("ADTS: Init() failure: invalid sample-rate index value: %" PRIu32 - ".", - mSamplingIndex)); - return false; - } - mSampleRate = SAMPLE_RATES[mSamplingIndex]; - - MOZ_ASSERT(mChannelConfig < 8); - mChannels = (mChannelConfig == 7) ? 8 : mChannelConfig; - - return true; - } -}; - -// adts::Frame - Frame meta container used to parse and hold a frame -// header and side info. -class Frame { - public: - Frame() : mOffset(0) {} - - uint64_t Offset() const { return mOffset; } - size_t Length() const { - // TODO: If fields are zero'd when invalid, this check wouldn't be - // necessary. - if (!mHeader.IsValid()) { - return 0; - } - - return mHeader.mFrameLength; - } - - // Returns the offset to the start of frame's raw data. - uint64_t PayloadOffset() const { return mOffset + mHeader.HeaderSize(); } - - // Returns the length of the frame's raw data (excluding the header) in bytes. - size_t PayloadLength() const { - // TODO: If fields are zero'd when invalid, this check wouldn't be - // necessary. - if (!mHeader.IsValid()) { - return 0; - } - - return mHeader.mFrameLength - mHeader.HeaderSize(); - } - - // Returns the parsed frame header. - const FrameHeader& Header() const { return mHeader; } - - bool IsValid() const { return mHeader.IsValid(); } - - // Resets the frame header and data. - void Reset() { - mHeader.Reset(); - mOffset = 0; - } - - // Returns whether the valid - bool Parse(uint64_t aOffset, const uint8_t* aStart, const uint8_t* aEnd) { - MOZ_ASSERT(aStart && aEnd); - - bool found = false; - const uint8_t* ptr = aStart; - // Require at least 7 bytes of data at the end of the buffer for the minimum - // ADTS frame header. - while (ptr < aEnd - 7 && !found) { - found = mHeader.Parse(ptr); - ptr++; - } - - mOffset = aOffset + (static_cast<size_t>(ptr - aStart)) - 1u; - - return found; - } - - private: - // The offset to the start of the header. - uint64_t mOffset; - - // The currently parsed frame header. - FrameHeader mHeader; -}; - -class FrameParser { - public: - // Returns the currently parsed frame. Reset via Reset or EndFrameSession. - const Frame& CurrentFrame() const { return mFrame; } - - // Returns the first parsed frame. Reset via Reset. - const Frame& FirstFrame() const { return mFirstFrame; } - - // Resets the parser. Don't use between frames as first frame data is reset. - void Reset() { - EndFrameSession(); - mFirstFrame.Reset(); - } - - // Clear the last parsed frame to allow for next frame parsing, i.e.: - // - sets PrevFrame to CurrentFrame - // - resets the CurrentFrame - // - resets ID3Header if no valid header was parsed yet - void EndFrameSession() { mFrame.Reset(); } - - // Parses contents of given ByteReader for a valid frame header and returns - // true if one was found. After returning, the variable passed to - // 'aBytesToSkip' holds the amount of bytes to be skipped (if any) in order to - // jump across a large ID3v2 tag spanning multiple buffers. - bool Parse(uint64_t aOffset, const uint8_t* aStart, const uint8_t* aEnd) { - const bool found = mFrame.Parse(aOffset, aStart, aEnd); - - if (mFrame.Length() && !mFirstFrame.Length()) { - mFirstFrame = mFrame; - } - - return found; - } - - private: - // We keep the first parsed frame around for static info access, the - // previously parsed frame for debugging and the currently parsed frame. - Frame mFirstFrame; - Frame mFrame; -}; - -// Initialize the AAC AudioSpecificConfig. -// Only handles two-byte version for AAC-LC. -static void InitAudioSpecificConfig(const Frame& frame, - MediaByteBuffer* aBuffer) { - const FrameHeader& header = frame.Header(); - MOZ_ASSERT(header.IsValid()); - - int audioObjectType = header.mObjectType; - int samplingFrequencyIndex = header.mSamplingIndex; - int channelConfig = header.mChannelConfig; - - uint8_t asc[2]; - asc[0] = (audioObjectType & 0x1F) << 3 | (samplingFrequencyIndex & 0x0E) >> 1; - asc[1] = (samplingFrequencyIndex & 0x01) << 7 | (channelConfig & 0x0F) << 3; - - aBuffer->AppendElements(asc, 2); -} - -} // namespace adts using media::TimeUnit; @@ -292,7 +72,7 @@ bool ADTSDemuxer::IsSeekable() const { // ADTSTrackDemuxer ADTSTrackDemuxer::ADTSTrackDemuxer(MediaResource* aSource) : mSource(aSource), - mParser(new adts::FrameParser()), + mParser(new ADTS::FrameParser()), mOffset(0), mNumParsedFrames(0), mFrameIndex(0), @@ -535,7 +315,7 @@ TimeUnit ADTSTrackDemuxer::Duration(int64_t aNumFrames) const { return TimeUnit(aNumFrames * mSamplesPerFrame, mSamplesPerSecond); } -const adts::Frame& ADTSTrackDemuxer::FindNextFrame( +const ADTS::Frame& ADTSTrackDemuxer::FindNextFrame( bool findFirstFrame /*= false*/) { static const int BUFFER_SIZE = 4096; static const int MAX_SKIPPED_BYTES = 10 * BUFFER_SIZE; @@ -568,7 +348,7 @@ const adts::Frame& ADTSTrackDemuxer::FindNextFrame( break; } - const adts::Frame& currentFrame = mParser->CurrentFrame(); + const ADTS::Frame& currentFrame = mParser->CurrentFrame(); foundFrame = mParser->Parse(frameHeaderOffset, buffer, buffer + read); if (findFirstFrame && foundFrame) { // Check for sync marker after the found frame, since it's @@ -579,7 +359,7 @@ const adts::Frame& ADTSTrackDemuxer::FindNextFrame( currentFrame.Offset() + currentFrame.Length(); uint32_t read = Read(buffer, AssertedCast<int64_t>(nextFrameHeaderOffset), 2); - if (read != 2 || !adts::FrameHeader::MatchesSync(buffer)) { + if (read != 2 || !ADTS::FrameHeader::MatchesSync(buffer)) { frameHeaderOffset = currentFrame.Offset() + 1; mParser->Reset(); foundFrame = false; @@ -621,7 +401,7 @@ const adts::Frame& ADTSTrackDemuxer::FindNextFrame( return mParser->CurrentFrame(); } -bool ADTSTrackDemuxer::SkipNextFrame(const adts::Frame& aFrame) { +bool ADTSTrackDemuxer::SkipNextFrame(const ADTS::Frame& aFrame) { if (!mNumParsedFrames || !aFrame.Length()) { RefPtr<MediaRawData> frame(GetNextFrame(aFrame)); return frame; @@ -639,7 +419,7 @@ bool ADTSTrackDemuxer::SkipNextFrame(const adts::Frame& aFrame) { } already_AddRefed<MediaRawData> ADTSTrackDemuxer::GetNextFrame( - const adts::Frame& aFrame) { + const ADTS::Frame& aFrame) { ADTSLOG("GetNext() Begin({mOffset=%" PRIu64 " HeaderSize()=%" PRIu64 " Length()=%zu})", aFrame.Offset(), aFrame.Header().HeaderSize(), @@ -735,7 +515,7 @@ int64_t ADTSTrackDemuxer::FrameIndexFromTime(const TimeUnit& aTime) const { return std::max<int64_t>(0, frameIndex); } -void ADTSTrackDemuxer::UpdateState(const adts::Frame& aFrame) { +void ADTSTrackDemuxer::UpdateState(const ADTS::Frame& aFrame) { uint32_t frameLength = aFrame.Length(); // Prevent overflow. if (mTotalFrameLen + frameLength < mTotalFrameLen) { @@ -750,7 +530,7 @@ void ADTSTrackDemuxer::UpdateState(const adts::Frame& aFrame) { mTotalFrameLen += frameLength; if (!mSamplesPerFrame) { - const adts::FrameHeader& header = aFrame.Header(); + const ADTS::FrameHeader& header = aFrame.Header(); mSamplesPerFrame = header.mSamples; mSamplesPerSecond = header.mSampleRate; mChannels = header.mChannels; @@ -795,15 +575,15 @@ bool ADTSDemuxer::ADTSSniffer(const uint8_t* aData, const uint32_t aLength) { if (aLength < 7) { return false; } - if (!adts::FrameHeader::MatchesSync(aData)) { + if (!ADTS::FrameHeader::MatchesSync(Span(aData, aLength))) { return false; } - auto parser = MakeUnique<adts::FrameParser>(); + auto parser = MakeUnique<ADTS::FrameParser>(); if (!parser->Parse(0, aData, aData + aLength)) { return false; } - const adts::Frame& currentFrame = parser->CurrentFrame(); + const ADTS::Frame& currentFrame = parser->CurrentFrame(); // Check for sync marker after the found frame, since it's // possible to find sync marker in AAC data. If sync marker // exists after the current frame then we've found a frame @@ -812,7 +592,8 @@ bool ADTSDemuxer::ADTSSniffer(const uint8_t* aData, const uint32_t aLength) { currentFrame.Offset() + currentFrame.Length(); return aLength > nextFrameHeaderOffset && aLength - nextFrameHeaderOffset >= 2 && - adts::FrameHeader::MatchesSync(aData + nextFrameHeaderOffset); + ADTS::FrameHeader::MatchesSync(Span(aData + nextFrameHeaderOffset, + aLength - nextFrameHeaderOffset)); } } // namespace mozilla |