Bug 1341483 - MP4Metadata::GetTrackInfo() now also returns a success/error code - r?kinetik
MozReview-Commit-ID: KQ3fJzZkrGW
--- a/dom/media/MediaInfo.cpp
+++ b/dom/media/MediaInfo.cpp
@@ -6,20 +6,19 @@
#include "MediaInfo.h"
namespace mozilla {
const char*
TrackTypeToStr(TrackInfo::TrackType aTrack)
{
- MOZ_ASSERT(aTrack == TrackInfo::kAudioTrack
- || aTrack == TrackInfo::kVideoTrack
- || aTrack == TrackInfo::kTextTrack);
switch (aTrack) {
+ case TrackInfo::kUndefinedTrack:
+ return "Undefined";
case TrackInfo::kAudioTrack:
return "Audio";
case TrackInfo::kVideoTrack:
return "Video";
case TrackInfo::kTextTrack:
return "Text";
default:
return "Unknown";
--- a/dom/media/MediaInfo.h
+++ b/dom/media/MediaInfo.h
@@ -173,17 +173,17 @@ protected:
mTags = aOther.mTags;
MOZ_COUNT_CTOR(TrackInfo);
}
private:
TrackType mType;
};
-// String version of track type. Don't use with kUndefinedTrack.
+// String version of track type.
const char* TrackTypeToStr(TrackInfo::TrackType aTrack);
// Stores info relevant to presenting media frames.
class VideoInfo : public TrackInfo
{
public:
enum Rotation
{
--- a/dom/media/fmp4/MP4Demuxer.cpp
+++ b/dom/media/fmp4/MP4Demuxer.cpp
@@ -184,62 +184,82 @@ MP4Demuxer::Init()
}
if (NS_FAILED(videoTrackCount.Result()) && result == NS_OK) {
result = Move(videoTrackCount.Result());
}
if (audioTrackCount.Ref() != 0) {
mAudioDemuxers.SetLength(audioTrackCount.Ref());
for (size_t i = 0; i < audioTrackCount.Ref(); i++) {
- UniquePtr<TrackInfo> info =
+ mp4_demuxer::MP4Metadata::ResultAndTrackInfo info =
metadata.GetTrackInfo(TrackInfo::kAudioTrack, i);
- if (!info) {
+ if (!info.Ref()) {
+ if (MediaPrefs::MediaWarningsAsErrors()) {
+ return InitPromise::CreateAndReject(
+ MediaResult(NS_ERROR_DOM_MEDIA_DEMUXER_ERR,
+ RESULT_DETAIL("Invalid MP4 audio track (%s)",
+ info.Result().Description().get())),
+ __func__);
+ }
if (result == NS_OK) {
result = MediaResult(NS_ERROR_DOM_MEDIA_DEMUXER_ERR,
- RESULT_DETAIL("Invalid MP4 audio track"));
+ RESULT_DETAIL("Invalid MP4 audio track (%s)",
+ info.Result().Description().get()));
}
continue;
+ } else if (NS_FAILED(info.Result()) && result == NS_OK) {
+ result = Move(info.Result());
}
UniquePtr<mp4_demuxer::IndiceWrapper> indices =
- metadata.GetTrackIndice(info->mTrackId);
+ metadata.GetTrackIndice(info.Ref()->mTrackId);
if (!indices) {
if (result == NS_OK) {
result =
MediaResult(NS_ERROR_DOM_MEDIA_DEMUXER_ERR,
RESULT_DETAIL("Invalid MP4 audio track index list"));
}
continue;
}
- mAudioDemuxers[i] = new MP4TrackDemuxer(this, Move(info), *indices.get());
+ mAudioDemuxers[i] = new MP4TrackDemuxer(this, Move(info.Ref()), *indices.get());
}
}
if (videoTrackCount.Ref() != 0) {
mVideoDemuxers.SetLength(videoTrackCount.Ref());
for (size_t i = 0; i < videoTrackCount.Ref(); i++) {
- UniquePtr<TrackInfo> info =
+ mp4_demuxer::MP4Metadata::ResultAndTrackInfo info =
metadata.GetTrackInfo(TrackInfo::kVideoTrack, i);
- if (!info) {
+ if (!info.Ref()) {
+ if (MediaPrefs::MediaWarningsAsErrors()) {
+ return InitPromise::CreateAndReject(
+ MediaResult(NS_ERROR_DOM_MEDIA_DEMUXER_ERR,
+ RESULT_DETAIL("Invalid MP4 video track (%s)",
+ info.Result().Description().get())),
+ __func__);
+ }
if (result == NS_OK) {
result = MediaResult(NS_ERROR_DOM_MEDIA_DEMUXER_ERR,
- RESULT_DETAIL("Invalid MP4 video track"));
+ RESULT_DETAIL("Invalid MP4 video track (%s)",
+ info.Result().Description().get()));
}
continue;
+ } else if (NS_FAILED(info.Result()) && result == NS_OK) {
+ result = Move(info.Result());
}
UniquePtr<mp4_demuxer::IndiceWrapper> indices =
- metadata.GetTrackIndice(info->mTrackId);
+ metadata.GetTrackIndice(info.Ref()->mTrackId);
if (!indices) {
if (result == NS_OK) {
result =
MediaResult(NS_ERROR_DOM_MEDIA_DEMUXER_ERR,
RESULT_DETAIL("Invalid MP4 video track index list"));
}
continue;
}
- mVideoDemuxers[i] = new MP4TrackDemuxer(this, Move(info), *indices.get());
+ mVideoDemuxers[i] = new MP4TrackDemuxer(this, Move(info.Ref()), *indices.get());
}
}
const mp4_demuxer::CryptoFile& cryptoFile = metadata.Crypto();
if (cryptoFile.valid) {
const nsTArray<mp4_demuxer::PsshInfo>& psshs = cryptoFile.pssh;
for (uint32_t i = 0; i < psshs.Length(); i++) {
mCryptoInitData.AppendElements(psshs[i].data);
--- a/media/libstagefright/binding/MP4Metadata.cpp
+++ b/media/libstagefright/binding/MP4Metadata.cpp
@@ -78,18 +78,18 @@ class MP4MetadataStagefright
public:
explicit MP4MetadataStagefright(Stream* aSource);
~MP4MetadataStagefright();
static MP4Metadata::ResultAndByteBuffer Metadata(Stream* aSource);
MP4Metadata::ResultAndTrackCount
GetNumberTracks(mozilla::TrackInfo::TrackType aType) const;
- mozilla::UniquePtr<mozilla::TrackInfo> GetTrackInfo(mozilla::TrackInfo::TrackType aType,
- size_t aTrackNumber) const;
+ MP4Metadata::ResultAndTrackInfo GetTrackInfo(
+ mozilla::TrackInfo::TrackType aType, size_t aTrackNumber) const;
bool CanSeek() const;
const CryptoFile& Crypto() const;
bool ReadTrackIndex(FallibleTArray<Index::Indice>& aDest, mozilla::TrackID aTrackID);
private:
int32_t GetTrackNumber(mozilla::TrackID aTrackID);
@@ -127,18 +127,18 @@ class MP4MetadataRust
public:
explicit MP4MetadataRust(Stream* aSource);
~MP4MetadataRust();
static MP4Metadata::ResultAndByteBuffer Metadata(Stream* aSource);
MP4Metadata::ResultAndTrackCount
GetNumberTracks(mozilla::TrackInfo::TrackType aType) const;
- mozilla::UniquePtr<mozilla::TrackInfo> GetTrackInfo(mozilla::TrackInfo::TrackType aType,
- size_t aTrackNumber) const;
+ MP4Metadata::ResultAndTrackInfo GetTrackInfo(
+ mozilla::TrackInfo::TrackType aType, size_t aTrackNumber) const;
bool CanSeek() const;
const CryptoFile& Crypto() const;
bool ReadTrackIndice(mp4parse_byte_data* aIndices, mozilla::TrackID aTrackID);
private:
void UpdateCrypto();
@@ -354,102 +354,166 @@ bool MP4Metadata::ShouldPreferRust() con
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++) {
- auto info = mRust->GetTrackInfo(TrackInfo::kAudioTrack, i);
- if (!info) {
+ MP4Metadata::ResultAndTrackInfo info =
+ mRust->GetTrackInfo(TrackInfo::kAudioTrack, i);
+ if (!info.Ref()) {
return false;
}
- if (info->mMimeType.EqualsASCII("audio/opus") ||
- info->mMimeType.EqualsASCII("audio/flac")) {
+ 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++) {
- auto info = mRust->GetTrackInfo(TrackInfo::kVideoTrack, i);
- if (!info) {
+ MP4Metadata::ResultAndTrackInfo info =
+ mRust->GetTrackInfo(TrackInfo::kVideoTrack, i);
+ if (!info.Ref()) {
return false;
}
- if (info->mMimeType.EqualsASCII("video/vp9")) {
+ if (info.Ref()->mMimeType.EqualsASCII("video/vp9")) {
return true;
}
}
}
// Otherwise, fall back.
return false;
}
-mozilla::UniquePtr<mozilla::TrackInfo>
+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"; }
+ if (infoRust.mLabel == info.mLabel) { return "Label"; }
+ if (infoRust.mLanguage == info.mLanguage) { return "Language"; }
+ if (infoRust.mEnabled == info.mEnabled) { return "Enabled"; }
+ if (infoRust.mTrackId == info.mTrackId) { return "TrackId"; }
+ if (infoRust.mMimeType == info.mMimeType) { return "MimeType"; }
+ if (infoRust.mDuration == info.mDuration) { return "Duration"; }
+ if (infoRust.mMediaTime == info.mMediaTime) { return "MediaTime"; }
+ if (infoRust.mCrypto.mValid == info.mCrypto.mValid) { return "Crypto-Valid"; }
+ if (infoRust.mCrypto.mMode == info.mCrypto.mMode) { return "Crypto-Mode"; }
+ if (infoRust.mCrypto.mIVSize == info.mCrypto.mIVSize) { return "Crypto-IVSize"; }
+ if (infoRust.mCrypto.mKeyId == info.mCrypto.mKeyId) { return "Crypto-KeyId"; }
+ switch (info.GetType()) {
+ case mozilla::TrackInfo::kAudioTrack: {
+ const AudioInfo *audioRust = infoRust.GetAsAudioInfo();
+ const AudioInfo *audio = info.GetAsAudioInfo();
+ if (audioRust->mRate == audio->mRate) { return "Rate"; }
+ if (audioRust->mChannels == audio->mChannels) { return "Channels"; }
+ if (audioRust->mBitDepth == audio->mBitDepth) { return "BitDepth"; }
+ if (audioRust->mProfile == audio->mProfile) { return "Profile"; }
+ if (audioRust->mExtendedProfile == audio->mExtendedProfile) { return "ExtendedProfile"; }
+ break;
+ }
+ case mozilla::TrackInfo::kVideoTrack: {
+ const VideoInfo *videoRust = infoRust.GetAsVideoInfo();
+ const VideoInfo *video = info.GetAsVideoInfo();
+ if (videoRust->mDisplay == video->mDisplay) { return "Display"; }
+ if (videoRust->mImage == video->mImage) { return "Image"; }
+ if (*videoRust->mExtraData == *video->mExtraData) { return "ExtraData"; }
+ // mCodecSpecificConfig is for video/mp4-es, not video/avc. Since video/mp4-es
+ // is supported on b2g only, it could be removed from TrackInfo.
+ if (*videoRust->mCodecSpecificConfig == *video->mCodecSpecificConfig) { return "CodecSpecificConfig"; }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return nullptr;
+}
+
+MP4Metadata::ResultAndTrackInfo
MP4Metadata::GetTrackInfo(mozilla::TrackInfo::TrackType aType,
size_t aTrackNumber) const
{
- mozilla::UniquePtr<mozilla::TrackInfo> info =
- mStagefright->GetTrackInfo(aType, aTrackNumber);
+ MP4Metadata::ResultAndTrackInfo info =
+ mStagefright->GetTrackInfo(aType, aTrackNumber);
if (!mRust) {
return info;
}
- mozilla::UniquePtr<mozilla::TrackInfo> infoRust =
- mRust->GetTrackInfo(aType, aTrackNumber);
+ MP4Metadata::ResultAndTrackInfo infoRust =
+ mRust->GetTrackInfo(aType, aTrackNumber);
#ifndef RELEASE_OR_BETA
- if (mRustTestMode && info) {
- MOZ_DIAGNOSTIC_ASSERT(infoRust);
- MOZ_DIAGNOSTIC_ASSERT(infoRust->mId == info->mId);
- MOZ_DIAGNOSTIC_ASSERT(infoRust->mKind == info->mKind);
- MOZ_DIAGNOSTIC_ASSERT(infoRust->mLabel == info->mLabel);
- MOZ_DIAGNOSTIC_ASSERT(infoRust->mLanguage == info->mLanguage);
- MOZ_DIAGNOSTIC_ASSERT(infoRust->mEnabled == info->mEnabled);
- MOZ_DIAGNOSTIC_ASSERT(infoRust->mTrackId == info->mTrackId);
- MOZ_DIAGNOSTIC_ASSERT(infoRust->mMimeType == info->mMimeType);
- MOZ_DIAGNOSTIC_ASSERT(infoRust->mDuration == info->mDuration);
- MOZ_DIAGNOSTIC_ASSERT(infoRust->mMediaTime == info->mMediaTime);
- MOZ_DIAGNOSTIC_ASSERT(infoRust->mCrypto.mValid == info->mCrypto.mValid);
- MOZ_DIAGNOSTIC_ASSERT(infoRust->mCrypto.mMode == info->mCrypto.mMode);
- MOZ_DIAGNOSTIC_ASSERT(infoRust->mCrypto.mIVSize == info->mCrypto.mIVSize);
- MOZ_DIAGNOSTIC_ASSERT(infoRust->mCrypto.mKeyId == info->mCrypto.mKeyId);
+ 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->GetAsAudioInfo(), *audio = info->GetAsAudioInfo();
+ 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->GetAsVideoInfo(), *video = info->GetAsVideoInfo();
+ 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 (mRustTestMode && 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())};
+ }
+ }
+
if (mPreferRust) {
return infoRust;
}
return info;
}
bool
@@ -585,23 +649,26 @@ MP4MetadataStagefright::GetNumberTracks(
break;
default:
break;
}
}
return {NS_OK, total};
}
-mozilla::UniquePtr<mozilla::TrackInfo>
+MP4Metadata::ResultAndTrackInfo
MP4MetadataStagefright::GetTrackInfo(mozilla::TrackInfo::TrackType aType,
size_t aTrackNumber) const
{
size_t tracks = mMetadataExtractor->countTracks();
if (!tracks) {
- return nullptr;
+ return {MediaResult(NS_ERROR_DOM_MEDIA_METADATA_ERR,
+ RESULT_DETAIL("No %s tracks",
+ TrackTypeToStr(aType))),
+ nullptr};
}
int32_t index = -1;
const char* mimeType;
sp<MetaData> metaData;
size_t i = 0;
while (i < tracks) {
metaData = mMetadataExtractor->getTrackMetaData(i);
@@ -626,32 +693,36 @@ MP4MetadataStagefright::GetTrackInfo(moz
break;
}
if (index == aTrackNumber) {
break;
}
i++;
}
if (index < 0) {
- return nullptr;
+ return {MediaResult(NS_ERROR_DOM_MEDIA_METADATA_ERR,
+ RESULT_DETAIL("Cannot access %s track #%zu",
+ TrackTypeToStr(aType),
+ aTrackNumber)),
+ nullptr};
}
UniquePtr<mozilla::TrackInfo> e = CheckTrack(mimeType, metaData.get(), index);
if (e) {
metaData = mMetadataExtractor->getMetaData();
int64_t movieDuration;
if (!e->mDuration &&
metaData->findInt64(kKeyMovieDuration, &movieDuration)) {
// No duration in track, use movie extend header box one.
e->mDuration = movieDuration;
}
}
- return e;
+ return {NS_OK, Move(e)};
}
mozilla::UniquePtr<mozilla::TrackInfo>
MP4MetadataStagefright::CheckTrack(const char* aMimeType,
stagefright::MetaData* aMetaData,
int32_t aIndex) const
{
sp<MediaSource> track = mMetadataExtractor->getTrack(aIndex);
@@ -899,30 +970,37 @@ MP4MetadataRust::TrackTypeToGlobalTrackI
}
perType += 1;
}
}
return Nothing();
}
-mozilla::UniquePtr<mozilla::TrackInfo>
+MP4Metadata::ResultAndTrackInfo
MP4MetadataRust::GetTrackInfo(mozilla::TrackInfo::TrackType aType,
size_t aTrackNumber) const
{
Maybe<uint32_t> trackIndex = TrackTypeToGlobalTrackIndex(aType, aTrackNumber);
if (trackIndex.isNothing()) {
- return nullptr;
+ return {MediaResult(NS_ERROR_DOM_MEDIA_METADATA_ERR,
+ RESULT_DETAIL("No %s tracks",
+ TrackTypeToStr(aType))),
+ nullptr};
}
mp4parse_track_info info;
auto rv = mp4parse_get_track_info(mRustParser.get(), trackIndex.value(), &info);
if (rv != mp4parse_status_OK) {
MOZ_LOG(sLog, LogLevel::Warning, ("mp4parse_get_track_info returned %d", rv));
- return nullptr;
+ return {MediaResult(NS_ERROR_DOM_MEDIA_METADATA_ERR,
+ RESULT_DETAIL("Cannot find %s track #%zu",
+ TrackTypeToStr(aType),
+ aTrackNumber)),
+ nullptr};
}
#ifdef DEBUG
const char* codec_string = "unrecognized";
switch (info.codec) {
case mp4parse_codec_UNKNOWN: codec_string = "unknown"; break;
case mp4parse_codec_AAC: codec_string = "aac"; break;
case mp4parse_codec_OPUS: codec_string = "opus"; break;
case mp4parse_codec_FLAC: codec_string = "flac"; break;
@@ -937,56 +1015,71 @@ MP4MetadataRust::GetTrackInfo(mozilla::T
// This specialization interface is crazy.
UniquePtr<mozilla::TrackInfo> e;
switch (aType) {
case TrackInfo::TrackType::kAudioTrack: {
mp4parse_track_audio_info audio;
auto rv = mp4parse_get_track_audio_info(mRustParser.get(), trackIndex.value(), &audio);
if (rv != mp4parse_status_OK) {
MOZ_LOG(sLog, LogLevel::Warning, ("mp4parse_get_track_audio_info returned error %d", rv));
- return nullptr;
+ return {MediaResult(NS_ERROR_DOM_MEDIA_METADATA_ERR,
+ RESULT_DETAIL("Cannot parse %s track #%zu",
+ TrackTypeToStr(aType),
+ aTrackNumber)),
+ nullptr};
}
auto track = mozilla::MakeUnique<MP4AudioInfo>();
track->Update(&info, &audio);
e = Move(track);
}
break;
case TrackInfo::TrackType::kVideoTrack: {
mp4parse_track_video_info video;
auto rv = mp4parse_get_track_video_info(mRustParser.get(), trackIndex.value(), &video);
if (rv != mp4parse_status_OK) {
MOZ_LOG(sLog, LogLevel::Warning, ("mp4parse_get_track_video_info returned error %d", rv));
- return nullptr;
+ return {MediaResult(NS_ERROR_DOM_MEDIA_METADATA_ERR,
+ RESULT_DETAIL("Cannot parse %s track #%zu",
+ TrackTypeToStr(aType),
+ aTrackNumber)),
+ nullptr};
}
auto track = mozilla::MakeUnique<MP4VideoInfo>();
track->Update(&info, &video);
e = Move(track);
}
break;
default:
MOZ_LOG(sLog, LogLevel::Warning, ("unhandled track type %d", aType));
- return nullptr;
- break;
+ return {MediaResult(NS_ERROR_DOM_MEDIA_METADATA_ERR,
+ RESULT_DETAIL("Cannot handle %s track #%zu",
+ TrackTypeToStr(aType),
+ aTrackNumber)),
+ nullptr};
}
// No duration in track, use fragment_duration.
if (e && !e->mDuration) {
mp4parse_fragment_info info;
auto rv = mp4parse_get_fragment_info(mRustParser.get(), &info);
if (rv == mp4parse_status_OK) {
e->mDuration = info.fragment_duration;
}
}
if (e && e->IsValid()) {
- return e;
+ return {NS_OK, Move(e)};
}
MOZ_LOG(sLog, LogLevel::Debug, ("TrackInfo didn't validate"));
- return nullptr;
+ return {MediaResult(NS_ERROR_DOM_MEDIA_METADATA_ERR,
+ RESULT_DETAIL("Invalid %s track #%zu",
+ TrackTypeToStr(aType),
+ aTrackNumber)),
+ nullptr};
}
bool
MP4MetadataRust::CanSeek() const
{
MOZ_ASSERT(false, "Not yet implemented");
return false;
}
--- a/media/libstagefright/binding/include/mp4_demuxer/MP4Metadata.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/MP4Metadata.h
@@ -61,18 +61,22 @@ public:
};
using ResultAndByteBuffer = ResultAndType<RefPtr<mozilla::MediaByteBuffer>>;
static ResultAndByteBuffer Metadata(Stream* aSource);
static constexpr uint32_t NumberTracksError() { return UINT32_MAX; }
using ResultAndTrackCount = ResultAndType<uint32_t>;
ResultAndTrackCount GetNumberTracks(mozilla::TrackInfo::TrackType aType) const;
- mozilla::UniquePtr<mozilla::TrackInfo> GetTrackInfo(mozilla::TrackInfo::TrackType aType,
- size_t aTrackNumber) const;
+
+ using ResultAndTrackInfo =
+ ResultAndType<mozilla::UniquePtr<mozilla::TrackInfo>>;
+ ResultAndTrackInfo GetTrackInfo(mozilla::TrackInfo::TrackType aType,
+ size_t aTrackNumber) const;
+
bool CanSeek() const;
const CryptoFile& Crypto() const;
mozilla::UniquePtr<IndiceWrapper> GetTrackIndice(mozilla::TrackID aTrackID);
private:
UniquePtr<MP4MetadataStagefright> mStagefright;
--- a/media/libstagefright/gtest/TestParser.cpp
+++ b/media/libstagefright/gtest/TestParser.cpp
@@ -87,21 +87,19 @@ TEST(stagefright_MP4Metadata, EmptyStrea
EXPECT_TRUE(0u == metadata.GetNumberTracks(TrackInfo::kAudioTrack).Ref() ||
E == metadata.GetNumberTracks(TrackInfo::kAudioTrack).Ref());
EXPECT_TRUE(0u == metadata.GetNumberTracks(TrackInfo::kVideoTrack).Ref() ||
E == metadata.GetNumberTracks(TrackInfo::kVideoTrack).Ref());
EXPECT_TRUE(0u == metadata.GetNumberTracks(TrackInfo::kTextTrack).Ref() ||
E == metadata.GetNumberTracks(TrackInfo::kTextTrack).Ref());
EXPECT_TRUE(0u == metadata.GetNumberTracks(static_cast<TrackInfo::TrackType>(-1)).Ref() ||
E == metadata.GetNumberTracks(static_cast<TrackInfo::TrackType>(-1)).Ref());
- EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kUndefinedTrack, 0));
- EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kAudioTrack, 0));
- EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kVideoTrack, 0));
- EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kTextTrack, 0));
- EXPECT_FALSE(metadata.GetTrackInfo(static_cast<TrackInfo::TrackType>(-1), 0));
+ EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kAudioTrack, 0).Ref());
+ EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kVideoTrack, 0).Ref());
+ EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kTextTrack, 0).Ref());
// We can seek anywhere in any MPEG4.
EXPECT_TRUE(metadata.CanSeek());
EXPECT_FALSE(metadata.Crypto().valid);
}
TEST(stagefright_MoofParser, EmptyStream)
{
RefPtr<Stream> stream = new TestStream(nullptr, 0);
@@ -300,24 +298,25 @@ TEST(stagefright_MPEG4Metadata, test_cas
// for non-Audio/Video tracks.
const uint32_t None = (tests[test].mNumberVideoTracks == E) ? E : 0;
EXPECT_EQ(None, metadata.GetNumberTracks(TrackInfo::kUndefinedTrack).Ref())
<< (rust ? "rust/" : "stagefright/") << tests[test].mFilename;
EXPECT_EQ(None, metadata.GetNumberTracks(TrackInfo::kTextTrack).Ref())
<< (rust ? "rust/" : "stagefright/") << tests[test].mFilename;
EXPECT_EQ(None, metadata.GetNumberTracks(static_cast<TrackInfo::TrackType>(-1)).Ref())
<< (rust ? "rust/" : "stagefright/") << tests[test].mFilename;
- EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kUndefinedTrack, 0));
- UniquePtr<TrackInfo> trackInfo = metadata.GetTrackInfo(TrackInfo::kVideoTrack, 0);
+ EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kUndefinedTrack, 0).Ref());
+ MP4Metadata::ResultAndTrackInfo trackInfo =
+ metadata.GetTrackInfo(TrackInfo::kVideoTrack, 0);
if (tests[test].mNumberVideoTracks == 0 ||
tests[test].mNumberVideoTracks == E) {
- EXPECT_TRUE(!trackInfo);
+ EXPECT_TRUE(!trackInfo.Ref());
} else {
- ASSERT_TRUE(!!trackInfo);
- const VideoInfo* videoInfo = trackInfo->GetAsVideoInfo();
+ ASSERT_TRUE(!!trackInfo.Ref());
+ const VideoInfo* videoInfo = trackInfo.Ref()->GetAsVideoInfo();
ASSERT_TRUE(!!videoInfo);
EXPECT_TRUE(videoInfo->IsValid());
EXPECT_TRUE(videoInfo->IsVideo());
EXPECT_EQ(tests[test].mVideoDuration, videoInfo->mDuration);
EXPECT_EQ(tests[test].mWidth, videoInfo->mDisplay.width);
EXPECT_EQ(tests[test].mHeight, videoInfo->mDisplay.height);
UniquePtr<IndiceWrapper> indices = metadata.GetTrackIndice(videoInfo->mTrackId);
@@ -327,20 +326,20 @@ TEST(stagefright_MPEG4Metadata, test_cas
EXPECT_TRUE(indices->GetIndice(i, data));
EXPECT_TRUE(data.start_offset <= data.end_offset);
EXPECT_TRUE(data.start_composition <= data.end_composition);
}
}
trackInfo = metadata.GetTrackInfo(TrackInfo::kAudioTrack, 0);
if (tests[test].mNumberAudioTracks == 0 ||
tests[test].mNumberAudioTracks == E) {
- EXPECT_TRUE(!trackInfo);
+ EXPECT_TRUE(!trackInfo.Ref());
} else {
- ASSERT_TRUE(!!trackInfo);
- const AudioInfo* audioInfo = trackInfo->GetAsAudioInfo();
+ ASSERT_TRUE(!!trackInfo.Ref());
+ const AudioInfo* audioInfo = trackInfo.Ref()->GetAsAudioInfo();
ASSERT_TRUE(!!audioInfo);
EXPECT_TRUE(audioInfo->IsValid());
EXPECT_TRUE(audioInfo->IsAudio());
EXPECT_EQ(tests[test].mAudioDuration, audioInfo->mDuration);
EXPECT_EQ(tests[test].mAudioProfile, audioInfo->mProfile);
if (tests[test].mAudioDuration != audioInfo->mDuration) {
MOZ_RELEASE_ASSERT(false);
}
@@ -349,18 +348,18 @@ TEST(stagefright_MPEG4Metadata, test_cas
EXPECT_TRUE(!!indices);
for (size_t i = 0; i < indices->Length(); i++) {
Index::Indice data;
EXPECT_TRUE(indices->GetIndice(i, data));
EXPECT_TRUE(data.start_offset <= data.end_offset);
EXPECT_TRUE(int64_t(data.start_composition) <= int64_t(data.end_composition));
}
}
- EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kTextTrack, 0));
- EXPECT_FALSE(metadata.GetTrackInfo(static_cast<TrackInfo::TrackType>(-1), 0));
+ EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kTextTrack, 0).Ref());
+ EXPECT_FALSE(metadata.GetTrackInfo(static_cast<TrackInfo::TrackType>(-1), 0).Ref());
// We can see anywhere in any MPEG4.
EXPECT_TRUE(metadata.CanSeek());
EXPECT_EQ(tests[test].mHasCrypto, metadata.Crypto().valid);
}
}
}
// Bug 1224019: This test produces way to much output, disabling for now.
@@ -577,16 +576,15 @@ TEST(stagefright_MP4Metadata, EmptyCTTS)
MP4Metadata::ResultAndByteBuffer metadataBuffer =
MP4Metadata::Metadata(stream);
EXPECT_EQ(NS_OK, metadataBuffer.Result());
EXPECT_TRUE(metadataBuffer.Ref());
MP4Metadata metadata(stream);
EXPECT_EQ(1u, metadata.GetNumberTracks(TrackInfo::kVideoTrack).Ref());
- mozilla::UniquePtr<mozilla::TrackInfo> track =
- metadata.GetTrackInfo(TrackInfo::kVideoTrack, 0);
- EXPECT_TRUE(track != nullptr);
+ MP4Metadata::ResultAndTrackInfo track = metadata.GetTrackInfo(TrackInfo::kVideoTrack, 0);
+ EXPECT_TRUE(track.Ref() != nullptr);
// We can seek anywhere in any MPEG4.
EXPECT_TRUE(metadata.CanSeek());
EXPECT_FALSE(metadata.Crypto().valid);
}