summaryrefslogtreecommitdiffstats
path: root/dom/media/ADTSDemuxer.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:27 +0000
commit40a355a42d4a9444dc753c04c6608dade2f06a23 (patch)
tree871fc667d2de662f171103ce5ec067014ef85e61 /dom/media/ADTSDemuxer.cpp
parentAdding upstream version 124.0.1. (diff)
downloadfirefox-40a355a42d4a9444dc753c04c6608dade2f06a23.tar.xz
firefox-40a355a42d4a9444dc753c04c6608dade2f06a23.zip
Adding upstream version 125.0.1.upstream/125.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/media/ADTSDemuxer.cpp')
-rw-r--r--dom/media/ADTSDemuxer.cpp247
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