--- a/dom/media/MediaPrefs.h
+++ b/dom/media/MediaPrefs.h
@@ -181,25 +181,18 @@ private:
DECL_MEDIA_PREF("media.ogg.enabled", OggEnabled, bool, true);
// Flac
DECL_MEDIA_PREF("media.ogg.flac.enabled", FlacInOgg, bool, false);
DECL_MEDIA_PREF("media.flac.enabled", FlacEnabled, bool, true);
// Hls
DECL_MEDIA_PREF("media.hls.enabled", HLSEnabled, bool, false);
-#if !defined(RELEASE_OR_BETA)
DECL_MEDIA_PREF("media.rust.test_mode", RustTestMode, bool, false);
-#endif
-
-#if defined(MOZ_WIDGET_GTK)
DECL_MEDIA_PREF("media.rust.mp4parser", EnableRustMP4Parser, bool, true);
-#else
- DECL_MEDIA_PREF("media.rust.mp4parser", EnableRustMP4Parser, bool, false);
-#endif
DECL_MEDIA_PREF("media.mp4.enabled", MP4Enabled, bool, false);
// Error/warning handling, Decoder Doctor
DECL_MEDIA_PREF("media.playback.warnings-as-errors", MediaWarningsAsErrors, bool, false);
DECL_MEDIA_PREF("media.playback.warnings-as-errors.stagefright-vs-rust",
MediaWarningsAsErrorsStageFrightVsRust, bool, false);
--- a/media/libstagefright/binding/MP4Metadata.cpp
+++ b/media/libstagefright/binding/MP4Metadata.cpp
@@ -122,31 +122,33 @@ public:
private:
Stream* mSource;
CheckedInt<size_t> mOffset;
};
class MP4MetadataRust
{
public:
- explicit MP4MetadataRust(Stream* aSource);
+ explicit MP4MetadataRust(Stream* aSource, bool& aParseFailure);
~MP4MetadataRust();
static MP4Metadata::ResultAndByteBuffer Metadata(Stream* aSource);
MP4Metadata::ResultAndTrackCount
GetNumberTracks(mozilla::TrackInfo::TrackType aType) const;
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 ParseSuccess();
+
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;
@@ -230,23 +232,20 @@ IndiceWrapperRust::GetIndice(size_t aInd
aIndice.end_composition = indice->end_composition;
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())
+ , mRust(MakeUnique<MP4MetadataRust>(aSource, mDisableRust))
, mReportedAudioTrackTelemetry(false)
, mReportedVideoTrackTelemetry(false)
-#ifndef RELEASE_OR_BETA
, mRustTestMode(MediaPrefs::RustTestMode())
-#endif
{
}
MP4Metadata::~MP4Metadata()
{
}
/*static*/ MP4Metadata::ResultAndByteBuffer
@@ -269,130 +268,82 @@ 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 (mRustTestMode) {
+ // 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 (!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 (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 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.
+ 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()};
+ }
- // 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;
-}
+ // 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()};
+ }
-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;
- }
+ // 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()};
}
}
- 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,24 +389,19 @@ 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);
@@ -488,121 +434,98 @@ MP4Metadata::GetTrackInfo(mozilla::Track
// 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()) {
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())};
+ : 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 (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 || mRustTestMode) {
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 || mRustTestMode) {
MediaResult rvRust = mRust->ReadTrackIndice(&indiceRust, aTrackID);
if (NS_FAILED(rvRust)) {
return {Move(rvRust), nullptr};
}
}
-#ifndef RELEASE_OR_BETA
if (mRustTestMode) {
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,
@@ -882,33 +805,41 @@ read_source(uint8_t* buffer, uintptr_t s
bool rv = source->Read(buffer, size, &bytes_read);
if (!rv) {
MOZ_LOG(sLog, LogLevel::Warning, ("Error reading source data"));
return -1;
}
return bytes_read;
}
-MP4MetadataRust::MP4MetadataRust(Stream* aSource)
+MP4MetadataRust::MP4MetadataRust(Stream* aSource, bool& aParseFailure)
: mSource(aSource)
, mRustSource(aSource)
{
+ if (!MediaPrefs::EnableRustMP4Parser()) {
+ aParseFailure = true;
+ return;
+ }
+ aParseFailure = false;
+
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."));
+ aParseFailure = true;
MOZ_ASSERT(rv > 0);
Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_ERROR_CODE, rv);
}
UpdateCrypto();
}
MP4MetadataRust::~MP4MetadataRust()