Bug 1303247 - Fix track indexing and AudioInfo initialization in Rust metadata parser. r=rillian,a=gchang
authorMatthew Gregan <kinetik@flim.org>
Wed, 21 Sep 2016 14:30:04 +1200
changeset 358715 11f06ea89d23b457eef4759e6ea8eee2dc7b1515
parent 358714 a632178a4f48bc53360871435e97ea65abd05a71
child 358716 3ec059299a275c49adaee9c737cc94b7ce551231
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrillian, gchang
bugs1303247
milestone51.0a2
Bug 1303247 - Fix track indexing and AudioInfo initialization in Rust metadata parser. r=rillian,a=gchang MozReview-Commit-ID: d4ZccdQaMs
media/libstagefright/binding/MP4Metadata.cpp
--- a/media/libstagefright/binding/MP4Metadata.cpp
+++ b/media/libstagefright/binding/MP4Metadata.cpp
@@ -137,16 +137,18 @@ public:
                                                       size_t aTrackNumber) const;
   bool CanSeek() const;
 
   const CryptoFile& Crypto() const;
 
   bool ReadTrackIndex(FallibleTArray<Index::Indice>& aDest, mozilla::TrackID aTrackID);
 
 private:
+  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;
 };
 #endif
 
 MP4Metadata::MP4Metadata(Stream* aSource)
@@ -596,64 +598,102 @@ MP4MetadataRust::MP4MetadataRust(Stream*
     Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_ERROR_CODE, rv);
   }
 }
 
 MP4MetadataRust::~MP4MetadataRust()
 {
 }
 
+bool
+TrackTypeEqual(TrackInfo::TrackType aLHS, mp4parse_track_type aRHS)
+{
+  switch (aLHS) {
+  case TrackInfo::kAudioTrack:
+    return aRHS == MP4PARSE_TRACK_TYPE_AUDIO;
+  case TrackInfo::kVideoTrack:
+    return aRHS == MP4PARSE_TRACK_TYPE_VIDEO;
+  default:
+    return false;
+  }
+}
+
 uint32_t
 MP4MetadataRust::GetNumberTracks(mozilla::TrackInfo::TrackType aType) const
 {
   static LazyLogModule sLog("MP4Metadata");
 
   uint32_t tracks;
-  mp4parse_error rv = mp4parse_get_track_count(mRustParser.get(), &tracks);
+  auto rv = mp4parse_get_track_count(mRustParser.get(), &tracks);
   if (rv != MP4PARSE_OK) {
     MOZ_LOG(sLog, LogLevel::Warning,
         ("rust parser error %d counting tracks", rv));
     return 0;
   }
   MOZ_LOG(sLog, LogLevel::Info, ("rust parser found %u tracks", tracks));
 
   uint32_t total = 0;
   for (uint32_t i = 0; i < tracks; ++i) {
     mp4parse_track_info track_info;
-    int32_t rv = mp4parse_get_track_info(mRustParser.get(), i, &track_info);
+    rv = mp4parse_get_track_info(mRustParser.get(), i, &track_info);
     if (rv != MP4PARSE_OK) {
       continue;
     }
-    switch (aType) {
-    case mozilla::TrackInfo::kAudioTrack:
-      if (track_info.track_type == MP4PARSE_TRACK_TYPE_AUDIO) {
+    if (TrackTypeEqual(aType, track_info.track_type)) {
         total += 1;
-      }
-      break;
-    case mozilla::TrackInfo::kVideoTrack:
-      if (track_info.track_type == MP4PARSE_TRACK_TYPE_VIDEO) {
-        total += 1;
-      }
-      break;
-    default:
-      break;
     }
   }
 
   return total;
 }
 
+Maybe<uint32_t>
+MP4MetadataRust::TrackTypeToGlobalTrackIndex(mozilla::TrackInfo::TrackType aType, size_t aTrackNumber) const
+{
+  uint32_t tracks;
+  auto rv = mp4parse_get_track_count(mRustParser.get(), &tracks);
+  if (rv != MP4PARSE_OK) {
+    return Nothing();
+  }
+
+  /* The MP4Metadata API uses a per-TrackType index of tracks, but mp4parse
+     (and libstagefright) use a global track index.  Convert the index by
+     counting the tracks of the requested type and returning the global
+     track index when a match is found. */
+  uint32_t perType = 0;
+  for (uint32_t i = 0; i < tracks; ++i) {
+    mp4parse_track_info track_info;
+    rv = mp4parse_get_track_info(mRustParser.get(), i, &track_info);
+    if (rv != MP4PARSE_OK) {
+      continue;
+    }
+    if (TrackTypeEqual(aType, track_info.track_type)) {
+      if (perType == aTrackNumber) {
+        return Some(i);
+      }
+      perType += 1;
+    }
+  }
+
+  return Nothing();
+}
+
 mozilla::UniquePtr<mozilla::TrackInfo>
 MP4MetadataRust::GetTrackInfo(mozilla::TrackInfo::TrackType aType,
                               size_t aTrackNumber) const
 {
   static LazyLogModule sLog("MP4Metadata");
 
+  Maybe<uint32_t> trackIndex = TrackTypeToGlobalTrackIndex(aType, aTrackNumber);
+  if (trackIndex.isNothing()) {
+    return nullptr;
+  }
+
   mp4parse_track_info info;
-  auto rv = mp4parse_get_track_info(mRustParser.get(), aTrackNumber, &info);
+  auto rv = mp4parse_get_track_info(mRustParser.get(), trackIndex.value(), &info);
   if (rv != MP4PARSE_OK) {
     MOZ_LOG(sLog, LogLevel::Warning, ("mp4parse_get_track_info returned %d", rv));
     return nullptr;
   }
 #ifdef DEBUG
   const char* codec_string = "unrecognized";
   switch (info.codec) {
     case MP4PARSE_CODEC_UNKNOWN: codec_string = "unknown"; break;
@@ -667,17 +707,17 @@ MP4MetadataRust::GetTrackInfo(mozilla::T
         codec_string, info.codec));
 #endif
 
   // 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(), aTrackNumber, &audio);
+      auto rv = mp4parse_get_track_audio_info(mRustParser.get(), trackIndex.value(), &audio);
       if (rv != MP4PARSE_OK) {
         MOZ_LOG(sLog, LogLevel::Warning, ("mp4parse_get_track_audio_info returned error %d", rv));
         return nullptr;
       }
       auto track = mozilla::MakeUnique<mozilla::AudioInfo>();
       if (info.codec == MP4PARSE_CODEC_OPUS) {
         track->mMimeType = NS_LITERAL_CSTRING("audio/opus");
         // The Opus decoder expects the container's codec delay or
@@ -699,22 +739,23 @@ MP4MetadataRust::GetTrackInfo(mozilla::T
       track->mCodecSpecificConfig->AppendElements(
           audio.codec_specific_config.data,
           audio.codec_specific_config.length);
       track->mRate = audio.sample_rate;
       track->mChannels = audio.channels;
       track->mBitDepth = audio.bit_depth;
       track->mDuration = info.duration;
       track->mMediaTime = info.media_time;
+      track->mTrackId = info.track_id;
       e = Move(track);
     }
     break;
     case TrackInfo::TrackType::kVideoTrack: {
       mp4parse_track_video_info video;
-      auto rv = mp4parse_get_track_video_info(mRustParser.get(), aTrackNumber, &video);
+      auto rv = mp4parse_get_track_video_info(mRustParser.get(), trackIndex.value(), &video);
       if (rv != MP4PARSE_OK) {
         MOZ_LOG(sLog, LogLevel::Warning, ("mp4parse_get_track_video_info returned error %d", rv));
         return nullptr;
       }
       auto track = mozilla::MakeUnique<MP4VideoInfo>();
       track->Update(&info, &video);
       e = Move(track);
     }
@@ -746,17 +787,17 @@ MP4MetadataRust::Crypto() const
   MOZ_ASSERT(false, "Not yet implemented");
   return mCrypto;
 }
 
 bool
 MP4MetadataRust::ReadTrackIndex(FallibleTArray<Index::Indice>& aDest, mozilla::TrackID aTrackID)
 {
   uint8_t fragmented = false;
-  int32_t rv = mp4parse_is_fragmented(mRustParser.get(), aTrackID, &fragmented);
+  auto rv = mp4parse_is_fragmented(mRustParser.get(), aTrackID, &fragmented);
   if (rv != MP4PARSE_OK) {
     return false;
   }
 
   if (fragmented) {
     return true;
   }