--- a/media/libstagefright/binding/MP4Metadata.cpp
+++ b/media/libstagefright/binding/MP4Metadata.cpp
@@ -137,16 +137,18 @@ public:
MP4Metadata::ResultAndTrackInfo GetTrackInfo(
mozilla::TrackInfo::TrackType aType, size_t aTrackNumber) const;
bool CanSeek() const;
MP4Metadata::ResultAndCryptoFile Crypto() const;
MediaResult ReadTrackIndice(mp4parse_byte_data* aIndices, mozilla::TrackID aTrackID);
+ bool Init();
+
private:
void UpdateCrypto();
Maybe<uint32_t> TrackTypeToGlobalTrackIndex(mozilla::TrackInfo::TrackType aType, size_t aTrackNumber) const;
CryptoFile mCrypto;
RefPtr<Stream> mSource;
RustStreamAdaptor mRustSource;
mozilla::UniquePtr<mp4parse_parser, FreeMP4Parser> mRustParser;
@@ -231,23 +233,25 @@ IndiceWrapperRust::GetIndice(size_t aInd
aIndice.start_decode = indice->start_decode;
aIndice.sync = indice->sync;
return true;
}
MP4Metadata::MP4Metadata(Stream* aSource)
: mStagefright(MakeUnique<MP4MetadataStagefright>(aSource))
, mRust(MakeUnique<MP4MetadataRust>(aSource))
- , mPreferRust(MediaPrefs::EnableRustMP4Parser())
, mReportedAudioTrackTelemetry(false)
, mReportedVideoTrackTelemetry(false)
-#ifndef RELEASE_OR_BETA
- , mRustTestMode(MediaPrefs::RustTestMode())
-#endif
{
+ mDisableRust = !MediaPrefs::EnableRustMP4Parser() && !MediaPrefs::RustTestMode();
+ if (mDisableRust) {
+ return;
+ }
+ // Fallback to stagefright if it fails.
+ mDisableRust = !mRust->Init();
}
MP4Metadata::~MP4Metadata()
{
}
/*static*/ MP4Metadata::ResultAndByteBuffer
MP4Metadata::Metadata(Stream* aSource)
@@ -269,130 +273,54 @@ TrackTypeToString(mozilla::TrackInfo::Tr
}
MP4Metadata::ResultAndTrackCount
MP4Metadata::GetNumberTracks(mozilla::TrackInfo::TrackType aType) const
{
MP4Metadata::ResultAndTrackCount numTracks =
mStagefright->GetNumberTracks(aType);
- if (!mRust) {
- return numTracks;
- }
-
MP4Metadata::ResultAndTrackCount numTracksRust =
mRust->GetNumberTracks(aType);
MOZ_LOG(sLog, LogLevel::Info, ("%s tracks found: stagefright=(%s)%u rust=(%s)%u",
TrackTypeToString(aType),
numTracks.Result().Description().get(),
numTracks.Ref(),
numTracksRust.Result().Description().get(),
numTracksRust.Ref()));
+
// Consider '0' and 'error' the same for comparison purposes.
// (Mostly because Stagefright never returns errors, but Rust may.)
bool numTracksMatch =
(numTracks.Ref() != NumberTracksError() ? numTracks.Ref() : 0) ==
(numTracksRust.Ref() != NumberTracksError() ? numTracksRust.Ref() : 0);
if (aType == mozilla::TrackInfo::kAudioTrack && !mReportedAudioTrackTelemetry) {
Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_TRACK_MATCH_AUDIO,
numTracksMatch);
mReportedAudioTrackTelemetry = true;
} else if (aType == mozilla::TrackInfo::kVideoTrack && !mReportedVideoTrackTelemetry) {
Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_TRACK_MATCH_VIDEO,
numTracksMatch);
mReportedVideoTrackTelemetry = true;
}
- if (!numTracksMatch &&
- MediaPrefs::MediaWarningsAsErrorsStageFrightVsRust()) {
+ if (!numTracksMatch && MediaPrefs::MediaWarningsAsErrorsStageFrightVsRust()) {
return {MediaResult(NS_ERROR_DOM_MEDIA_METADATA_ERR,
RESULT_DETAIL("Different numbers of tracks: "
"Stagefright=%u (%s) Rust=%u (%s)",
numTracks.Ref(),
numTracks.Result().Description().get(),
numTracksRust.Ref(),
numTracksRust.Result().Description().get())),
NumberTracksError()};
}
- // If we prefer Rust, just return it.
- if (mPreferRust || ShouldPreferRust()) {
- MOZ_LOG(sLog, LogLevel::Info, ("Preferring rust demuxer"));
- mPreferRust = true;
- return numTracksRust;
- }
-
- // If numbers are different, return the stagefright number with a warning.
- if (!numTracksMatch) {
- return {MediaResult(NS_ERROR_DOM_MEDIA_METADATA_ERR,
- RESULT_DETAIL("Different numbers of tracks: "
- "Stagefright=%u (%s) Rust=%u (%s)",
- numTracks.Ref(),
- numTracks.Result().Description().get(),
- numTracksRust.Ref(),
- numTracksRust.Result().Description().get())),
- numTracks.Ref()};
- }
-
- // Numbers are effectively the same.
-
- // Error(s) -> Combine both messages to get more details out.
- if (numTracks.Ref() == NumberTracksError() ||
- numTracksRust.Ref() == NumberTracksError()) {
- return {MediaResult(NS_ERROR_DOM_MEDIA_METADATA_ERR,
- RESULT_DETAIL("Errors: "
- "Stagefright=(%s) Rust=(%s)",
- numTracks.Result().Description().get(),
- numTracksRust.Result().Description().get())),
- numTracks.Ref()};
- }
-
- // Same non-error numbers, just return any.
- // (Choosing Rust here, in case it carries a warning, we'd want to know that.)
- return numTracksRust;
-}
-
-bool MP4Metadata::ShouldPreferRust() const {
- if (!mRust) {
- return false;
- }
- // See if there's an Opus track.
- MP4Metadata::ResultAndTrackCount numTracks =
- mRust->GetNumberTracks(TrackInfo::kAudioTrack);
- if (numTracks.Ref() != NumberTracksError()) {
- for (auto i = 0; i < numTracks.Ref(); i++) {
- MP4Metadata::ResultAndTrackInfo info =
- mRust->GetTrackInfo(TrackInfo::kAudioTrack, i);
- if (!info.Ref()) {
- return false;
- }
- if (info.Ref()->mMimeType.EqualsASCII("audio/opus") ||
- info.Ref()->mMimeType.EqualsASCII("audio/flac")) {
- return true;
- }
- }
- }
-
- numTracks = mRust->GetNumberTracks(TrackInfo::kVideoTrack);
- if (numTracks.Ref() != NumberTracksError()) {
- for (auto i = 0; i < numTracks.Ref(); i++) {
- MP4Metadata::ResultAndTrackInfo info =
- mRust->GetTrackInfo(TrackInfo::kVideoTrack, i);
- if (!info.Ref()) {
- return false;
- }
- if (info.Ref()->mMimeType.EqualsASCII("video/vp9")) {
- return true;
- }
- }
- }
- // Otherwise, fall back.
- return false;
+ return mDisableRust ? numTracks : numTracksRust;
}
static const char*
GetDifferentField(const mozilla::TrackInfo& info,
const mozilla::TrackInfo& infoRust)
{
if (infoRust.mId != info.mId) { return "Id"; }
if (infoRust.mKind != info.mKind) { return "Kind"; }
@@ -438,171 +366,99 @@ GetDifferentField(const mozilla::TrackIn
MP4Metadata::ResultAndTrackInfo
MP4Metadata::GetTrackInfo(mozilla::TrackInfo::TrackType aType,
size_t aTrackNumber) const
{
MP4Metadata::ResultAndTrackInfo info =
mStagefright->GetTrackInfo(aType, aTrackNumber);
- if (!mRust) {
- return info;
- }
-
MP4Metadata::ResultAndTrackInfo infoRust =
mRust->GetTrackInfo(aType, aTrackNumber);
-#ifndef RELEASE_OR_BETA
- if (mRustTestMode && info.Ref() && infoRust.Ref()) {
- MOZ_DIAGNOSTIC_ASSERT(infoRust.Ref()->mId == info.Ref()->mId);
- MOZ_DIAGNOSTIC_ASSERT(infoRust.Ref()->mKind == info.Ref()->mKind);
- MOZ_DIAGNOSTIC_ASSERT(infoRust.Ref()->mLabel == info.Ref()->mLabel);
- MOZ_DIAGNOSTIC_ASSERT(infoRust.Ref()->mLanguage == info.Ref()->mLanguage);
- MOZ_DIAGNOSTIC_ASSERT(infoRust.Ref()->mEnabled == info.Ref()->mEnabled);
- MOZ_DIAGNOSTIC_ASSERT(infoRust.Ref()->mTrackId == info.Ref()->mTrackId);
- MOZ_DIAGNOSTIC_ASSERT(infoRust.Ref()->mMimeType == info.Ref()->mMimeType);
- MOZ_DIAGNOSTIC_ASSERT(infoRust.Ref()->mDuration == info.Ref()->mDuration);
- MOZ_DIAGNOSTIC_ASSERT(infoRust.Ref()->mMediaTime == info.Ref()->mMediaTime);
- MOZ_DIAGNOSTIC_ASSERT(infoRust.Ref()->mCrypto.mValid == info.Ref()->mCrypto.mValid);
- MOZ_DIAGNOSTIC_ASSERT(infoRust.Ref()->mCrypto.mMode == info.Ref()->mCrypto.mMode);
- MOZ_DIAGNOSTIC_ASSERT(infoRust.Ref()->mCrypto.mIVSize == info.Ref()->mCrypto.mIVSize);
- MOZ_DIAGNOSTIC_ASSERT(infoRust.Ref()->mCrypto.mKeyId == info.Ref()->mCrypto.mKeyId);
- switch (aType) {
- case mozilla::TrackInfo::kAudioTrack: {
- AudioInfo *audioRust = infoRust.Ref()->GetAsAudioInfo();
- AudioInfo *audio = info.Ref()->GetAsAudioInfo();
- MOZ_DIAGNOSTIC_ASSERT(audioRust->mRate == audio->mRate);
- MOZ_DIAGNOSTIC_ASSERT(audioRust->mChannels == audio->mChannels);
- MOZ_DIAGNOSTIC_ASSERT(audioRust->mBitDepth == audio->mBitDepth);
- MOZ_DIAGNOSTIC_ASSERT(audioRust->mProfile == audio->mProfile);
- MOZ_DIAGNOSTIC_ASSERT(audioRust->mExtendedProfile == audio->mExtendedProfile);
- MOZ_DIAGNOSTIC_ASSERT(*audioRust->mExtraData == *audio->mExtraData);
- MOZ_DIAGNOSTIC_ASSERT(*audioRust->mCodecSpecificConfig == *audio->mCodecSpecificConfig);
- break;
- }
- case mozilla::TrackInfo::kVideoTrack: {
- VideoInfo *videoRust = infoRust.Ref()->GetAsVideoInfo();
- VideoInfo *video = info.Ref()->GetAsVideoInfo();
- MOZ_DIAGNOSTIC_ASSERT(videoRust->mDisplay == video->mDisplay);
- MOZ_DIAGNOSTIC_ASSERT(videoRust->mImage == video->mImage);
- MOZ_DIAGNOSTIC_ASSERT(videoRust->mRotation == video->mRotation);
- MOZ_DIAGNOSTIC_ASSERT(*videoRust->mExtraData == *video->mExtraData);
- // mCodecSpecificConfig is for video/mp4-es, not video/avc. Since video/mp4-es
- // is supported on b2g only, it could be removed from TrackInfo.
- MOZ_DIAGNOSTIC_ASSERT(*videoRust->mCodecSpecificConfig == *video->mCodecSpecificConfig);
- break;
- }
- default:
- break;
- }
- }
-#endif
-
- if (info.Ref() && infoRust.Ref()) {
+ if (info.Ref() && infoRust.Ref() && MediaPrefs::MediaWarningsAsErrorsStageFrightVsRust()) {
const char* diff = GetDifferentField(*info.Ref(), *infoRust.Ref());
if (diff) {
return {MediaResult(NS_ERROR_DOM_MEDIA_METADATA_ERR,
RESULT_DETAIL("Different field '%s' between "
"Stagefright (%s) and Rust (%s)",
diff,
info.Result().Description().get(),
infoRust.Result().Description().get())),
MediaPrefs::MediaWarningsAsErrorsStageFrightVsRust()
- ? mozilla::UniquePtr<mozilla::TrackInfo>(nullptr)
- : mPreferRust ? Move(infoRust.Ref()) : Move(info.Ref())};
+ ? mozilla::UniquePtr<mozilla::TrackInfo>(nullptr)
+ : mDisableRust ? Move(info.Ref()) : Move(infoRust.Ref())};
}
}
- if (mPreferRust) {
- return infoRust;
- }
-
- return info;
+ return mDisableRust ? Move(info) : Move(infoRust);
}
bool
MP4Metadata::CanSeek() const
{
return mStagefright->CanSeek();
}
MP4Metadata::ResultAndCryptoFile
MP4Metadata::Crypto() const
{
MP4Metadata::ResultAndCryptoFile crypto = mStagefright->Crypto();
MP4Metadata::ResultAndCryptoFile rustCrypto = mRust->Crypto();
-#ifndef RELEASE_OR_BETA
- if (mRustTestMode) {
- MOZ_DIAGNOSTIC_ASSERT(rustCrypto.Ref()->pssh == crypto.Ref()->pssh);
- }
-#endif
-
- if (rustCrypto.Ref()->pssh != crypto.Ref()->pssh) {
- return {MediaResult(
- NS_ERROR_DOM_MEDIA_METADATA_ERR,
- RESULT_DETAIL("Mismatch between Stagefright (%s) and Rust (%s) crypto file",
- crypto.Result().Description().get(),
- rustCrypto.Result().Description().get())),
- mPreferRust ? rustCrypto.Ref() : crypto.Ref()};
+ if (MediaPrefs::MediaWarningsAsErrorsStageFrightVsRust()) {
+ if (rustCrypto.Ref()->pssh != crypto.Ref()->pssh) {
+ return {MediaResult(
+ NS_ERROR_DOM_MEDIA_METADATA_ERR,
+ RESULT_DETAIL("Mismatch between Stagefright (%s) and Rust (%s) crypto file",
+ crypto.Result().Description().get(),
+ rustCrypto.Result().Description().get())),
+ mDisableRust ? crypto.Ref() : rustCrypto.Ref()};
+ }
}
- if (mPreferRust) {
- return rustCrypto;
- }
-
- return crypto;
+ return mDisableRust ? crypto : rustCrypto;
}
MP4Metadata::ResultAndIndice
MP4Metadata::GetTrackIndice(mozilla::TrackID aTrackID)
{
FallibleTArray<Index::Indice> indiceSF;
- if (!mPreferRust
-#ifndef RELEASE_OR_BETA
- || mRustTestMode
-#endif
- ) {
+ if (mDisableRust || MediaPrefs::MediaWarningsAsErrorsStageFrightVsRust()) {
MediaResult rv = mStagefright->ReadTrackIndex(indiceSF, aTrackID);
if (NS_FAILED(rv)) {
return {Move(rv), nullptr};
}
}
mp4parse_byte_data indiceRust = {};
- if (mPreferRust
-#ifndef RELEASE_OR_BETA
- || mRustTestMode
-#endif
- ) {
+ if (!mDisableRust || MediaPrefs::MediaWarningsAsErrorsStageFrightVsRust()) {
MediaResult rvRust = mRust->ReadTrackIndice(&indiceRust, aTrackID);
if (NS_FAILED(rvRust)) {
return {Move(rvRust), nullptr};
}
}
-#ifndef RELEASE_OR_BETA
- if (mRustTestMode) {
+ if (MediaPrefs::MediaWarningsAsErrorsStageFrightVsRust()) {
MOZ_DIAGNOSTIC_ASSERT(indiceRust.length == indiceSF.Length());
for (uint32_t i = 0; i < indiceRust.length; i++) {
MOZ_DIAGNOSTIC_ASSERT(indiceRust.indices[i].start_offset == indiceSF[i].start_offset);
MOZ_DIAGNOSTIC_ASSERT(indiceRust.indices[i].end_offset == indiceSF[i].end_offset);
MOZ_DIAGNOSTIC_ASSERT(llabs(indiceRust.indices[i].start_composition - int64_t(indiceSF[i].start_composition)) <= 1);
MOZ_DIAGNOSTIC_ASSERT(llabs(indiceRust.indices[i].end_composition - int64_t(indiceSF[i].end_composition)) <= 1);
MOZ_DIAGNOSTIC_ASSERT(llabs(indiceRust.indices[i].start_decode - int64_t(indiceSF[i].start_decode)) <= 1);
MOZ_DIAGNOSTIC_ASSERT(indiceRust.indices[i].sync == indiceSF[i].sync);
}
}
-#endif
UniquePtr<IndiceWrapper> indice;
- if (mPreferRust) {
+ if (mDisableRust) {
+ indice = mozilla::MakeUnique<IndiceWrapperStagefright>(indiceSF);
+ } else {
indice = mozilla::MakeUnique<IndiceWrapperRust>(indiceRust);
- } else {
- indice = mozilla::MakeUnique<IndiceWrapperStagefright>(indiceSF);
}
return {NS_OK, Move(indice)};
}
static inline MediaResult
ConvertIndex(FallibleTArray<Index::Indice>& aDest,
const nsTArray<stagefright::MediaSource::Indice>& aIndex,
@@ -886,38 +742,47 @@ read_source(uint8_t* buffer, uintptr_t s
}
return bytes_read;
}
MP4MetadataRust::MP4MetadataRust(Stream* aSource)
: mSource(aSource)
, mRustSource(aSource)
{
+}
+
+MP4MetadataRust::~MP4MetadataRust()
+{
+}
+
+bool
+MP4MetadataRust::Init()
+{
mp4parse_io io = { read_source, &mRustSource };
mRustParser.reset(mp4parse_new(&io));
MOZ_ASSERT(mRustParser);
if (MOZ_LOG_TEST(sLog, LogLevel::Debug)) {
mp4parse_log(true);
}
mp4parse_status rv = mp4parse_read(mRustParser.get());
MOZ_LOG(sLog, LogLevel::Debug, ("rust parser returned %d\n", rv));
Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_SUCCESS,
rv == mp4parse_status_OK);
if (rv != mp4parse_status_OK) {
+ MOZ_LOG(sLog, LogLevel::Info, ("Rust mp4 parser fails to parse this stream."));
MOZ_ASSERT(rv > 0);
Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_ERROR_CODE, rv);
+ return false;
}
UpdateCrypto();
-}
-MP4MetadataRust::~MP4MetadataRust()
-{
+ return true;
}
void
MP4MetadataRust::UpdateCrypto()
{
mp4parse_pssh_info info = {};
if (mp4parse_get_pssh_info(mRustParser.get(), &info) != mp4parse_status_OK) {
return;
--- a/media/libstagefright/gtest/TestParser.cpp
+++ b/media/libstagefright/gtest/TestParser.cpp
@@ -212,33 +212,33 @@ static const TestFileData testFiles[] =
{ "test_case_1301065-u64max.mp4", 0, -1, 0, 0, 1, 0, false, 0, false, false, 2 },
{ "test_case_1329061.mov", 0, -1, 0, 0, 1, 234567981,
false, 0, false, false, 2 },
{ "test_case_1351094.mp4", 0, -1, 0, 0, 0, -1, false, 0, true, true, 0 },
};
static const TestFileData rustTestFiles[] = {
// filename #V dur w h #A dur crypt off moof headr audio_profile
- { "test_case_1156505.mp4", E, -1, 0, 0, E, -1, false, 152, false, false, 0 },
+ { "test_case_1156505.mp4", 0, -1, 0, 0, 0, -1, false, 152, false, false, 0 },
{ "test_case_1181213.mp4", 1, 416666,
320, 240, 1, 477460,
true, 0, false, false, 2 },
{ "test_case_1181215.mp4", 1, 4966666, 190, 240, 0, -1, false, 0, false, false, 0 },
- { "test_case_1181220.mp4", E, -1, 0, 0, E, -1, false, 0, false, false, 0 },
- { "test_case_1181223.mp4", 1, 416666,
+ { "test_case_1181220.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 },
+ { "test_case_1181223.mp4", 0, 416666,
320, 240, 0, -1, false, 0, false, false, 0 },
- { "test_case_1181719.mp4", E, -1, 0, 0, E, -1, false, 0, false, false, 0 },
+ { "test_case_1181719.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 },
{ "test_case_1185230.mp4", 2, 416666,
320, 240, 2, 5, false, 0, false, false, 2 },
{ "test_case_1187067.mp4", 1, 80000,
160, 90, 0, -1, false, 0, false, false, 0 },
{ "test_case_1200326.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 },
{ "test_case_1204580.mp4", 1, 502500,
320, 180, 0, -1, false, 0, false, false, 0 },
- { "test_case_1216748.mp4", E, -1, 0, 0, E, -1, false, 152, false, false, 0 },
+ { "test_case_1216748.mp4", 0, -1, 0, 0, 0, -1, false, 152, false, false, 0 },
{ "test_case_1296473.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 },
{ "test_case_1296532.mp4", 1, 5589333,
560, 320, 1, 5589333,
true, 0, true, true, 2 },
{ "test_case_1301065.mp4", 0, -1, 0, 0, 1, 100079991719000000,
false, 0, false, false, 2 },
{ "test_case_1301065-u32max.mp4", 0, -1, 0, 0, 1, 97391548639,
false, 0, false, false, 2 },