Bug 1169473: Re-add H264 telemetry. r=miketaylr
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 15 Jul 2015 17:18:23 +1000
changeset 253132 629be61818243fbbf1127efa140219292f762c2d
parent 253131 a5c54b9ebb83a09dc93472aecde1fc442ea66161
child 253133 80f9da7f0806760ee923f4adafe9631f13add38a
push id29061
push userryanvm@gmail.com
push dateThu, 16 Jul 2015 18:53:45 +0000
treeherdermozilla-central@a0f4a688433d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmiketaylr
bugs1169473
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1169473: Re-add H264 telemetry. r=miketaylr
dom/media/fmp4/MP4Demuxer.cpp
dom/media/fmp4/MP4Demuxer.h
dom/media/fmp4/MP4Reader.cpp
--- a/dom/media/fmp4/MP4Demuxer.cpp
+++ b/dom/media/fmp4/MP4Demuxer.cpp
@@ -10,18 +10,59 @@
 
 #include "MP4Demuxer.h"
 #include "mp4_demuxer/Index.h"
 #include "mp4_demuxer/MoofParser.h"
 #include "mp4_demuxer/MP4Metadata.h"
 #include "mp4_demuxer/ResourceStream.h"
 #include "mp4_demuxer/BufferStream.h"
 
+// Used for telemetry
+#include "mozilla/Telemetry.h"
+#include "mp4_demuxer/AnnexB.h"
+#include "mp4_demuxer/H264.h"
+
 namespace mozilla {
 
+// Returns true if no SPS was found and search for it should continue.
+bool
+AccumulateSPSTelemetry(const MediaByteBuffer* aExtradata)
+{
+  mp4_demuxer::SPSData spsdata;
+  if (mp4_demuxer::H264::DecodeSPSFromExtraData(aExtradata, spsdata)) {
+    uint8_t constraints = (spsdata.constraint_set0_flag ? (1 << 0) : 0) |
+                          (spsdata.constraint_set1_flag ? (1 << 1) : 0) |
+                          (spsdata.constraint_set2_flag ? (1 << 2) : 0) |
+                          (spsdata.constraint_set3_flag ? (1 << 3) : 0) |
+                          (spsdata.constraint_set4_flag ? (1 << 4) : 0) |
+                          (spsdata.constraint_set5_flag ? (1 << 5) : 0);
+    Telemetry::Accumulate(Telemetry::VIDEO_DECODED_H264_SPS_CONSTRAINT_SET_FLAG,
+                          constraints);
+
+    // Collect profile_idc values up to 244, otherwise 0 for unknown.
+    Telemetry::Accumulate(Telemetry::VIDEO_DECODED_H264_SPS_PROFILE,
+                          spsdata.profile_idc <= 244 ? spsdata.profile_idc : 0);
+
+    // Make sure level_idc represents a value between levels 1 and 5.2,
+    // otherwise collect 0 for unknown level.
+    Telemetry::Accumulate(Telemetry::VIDEO_DECODED_H264_SPS_LEVEL,
+                          (spsdata.level_idc >= 10 && spsdata.level_idc <= 52) ?
+                          spsdata.level_idc : 0);
+
+    // max_num_ref_frames should be between 0 and 16, anything larger will
+    // be treated as invalid.
+    Telemetry::Accumulate(Telemetry::VIDEO_H264_SPS_MAX_NUM_REF_FRAMES,
+                          std::min(spsdata.max_num_ref_frames, 17u));
+
+    return false;
+  }
+
+  return true;
+}
+
 MP4Demuxer::MP4Demuxer(MediaResource* aResource)
   : mResource(aResource)
   , mStream(new mp4_demuxer::ResourceStream(aResource))
   , mInitData(new MediaByteBuffer)
 {
 }
 
 nsRefPtr<MP4Demuxer::InitPromise>
@@ -164,16 +205,27 @@ MP4TrackDemuxer::MP4TrackDemuxer(MP4Demu
   }
   mIndex = new mp4_demuxer::Index(indices,
                                   mStream,
                                   mInfo->mTrackId,
                                   mInfo->IsAudio(),
                                   &mMonitor);
   mIterator = MakeUnique<mp4_demuxer::SampleIterator>(mIndex);
   EnsureUpToDateIndex(); // Force update of index
+
+  // Collect telemetry from h264 AVCC SPS.
+  if (mInfo->GetAsVideoInfo() &&
+      (mInfo->mMimeType.EqualsLiteral("video/mp4") ||
+       mInfo->mMimeType.EqualsLiteral("video/avc"))) {
+    mNeedSPSForTelemetry =
+      AccumulateSPSTelemetry(mInfo->GetAsVideoInfo()->mExtraData);
+  } else {
+    // No SPS to be found.
+    mNeedSPSForTelemetry = false;
+  }
 }
 
 UniquePtr<TrackInfo>
 MP4TrackDemuxer::GetInfo() const
 {
   return mInfo->Clone();
 }
 
@@ -263,16 +315,22 @@ MP4TrackDemuxer::Reset()
   SetNextKeyFrameTime();
 }
 
 void
 MP4TrackDemuxer::UpdateSamples(nsTArray<nsRefPtr<MediaRawData>>& aSamples)
 {
   for (size_t i = 0; i < aSamples.Length(); i++) {
     MediaRawData* sample = aSamples[i];
+    // Collect telemetry from h264 Annex B SPS.
+    if (mNeedSPSForTelemetry && mp4_demuxer::AnnexB::HasSPS(sample)) {
+      nsRefPtr<MediaByteBuffer> extradata =
+        mp4_demuxer::AnnexB::ExtractExtraData(sample);
+      mNeedSPSForTelemetry = AccumulateSPSTelemetry(extradata);
+    }
     if (sample->mCrypto.mValid) {
       nsAutoPtr<MediaRawDataWriter> writer(sample->CreateWriter());
       writer->mCrypto.mMode = mInfo->mCrypto.mMode;
       writer->mCrypto.mIVSize = mInfo->mCrypto.mIVSize;
       writer->mCrypto.mKeyId.AppendElements(mInfo->mCrypto.mKeyId);
     }
     if (mInfo->GetAsVideoInfo()) {
       sample->mExtraData = mInfo->GetAsVideoInfo()->mExtraData;
--- a/dom/media/fmp4/MP4Demuxer.h
+++ b/dom/media/fmp4/MP4Demuxer.h
@@ -91,16 +91,17 @@ private:
   nsRefPtr<mp4_demuxer::Index> mIndex;
   UniquePtr<mp4_demuxer::SampleIterator> mIterator;
   UniquePtr<TrackInfo> mInfo;
   nsRefPtr<mp4_demuxer::ResourceStream> mStream;
   Maybe<media::TimeUnit> mNextKeyframeTime;
   // Queued samples extracted by the demuxer, but not yet returned.
   nsRefPtr<MediaRawData> mQueuedSample;
   bool mNeedReIndex;
+  bool mNeedSPSForTelemetry;
 
   // We do not actually need a monitor, however MoofParser will assert
   // if a monitor isn't held.
   Monitor mMonitor;
 };
 
 } // namespace mozilla
 
--- a/dom/media/fmp4/MP4Reader.cpp
+++ b/dom/media/fmp4/MP4Reader.cpp
@@ -61,50 +61,17 @@ TrackTypeToStr(TrackInfo::TrackType aTra
     return "Audio";
   case TrackInfo::kVideoTrack:
     return "Video";
   default:
     return "Unknown";
   }
 }
 
-bool
-AccumulateSPSTelemetry(const MediaByteBuffer* aExtradata)
-{
-  SPSData spsdata;
-  if (H264::DecodeSPSFromExtraData(aExtradata, spsdata)) {
-   uint8_t constraints = (spsdata.constraint_set0_flag ? (1 << 0) : 0) |
-                         (spsdata.constraint_set1_flag ? (1 << 1) : 0) |
-                         (spsdata.constraint_set2_flag ? (1 << 2) : 0) |
-                         (spsdata.constraint_set3_flag ? (1 << 3) : 0) |
-                         (spsdata.constraint_set4_flag ? (1 << 4) : 0) |
-                         (spsdata.constraint_set5_flag ? (1 << 5) : 0);
-    Telemetry::Accumulate(Telemetry::VIDEO_DECODED_H264_SPS_CONSTRAINT_SET_FLAG,
-                          constraints);
-
-    // Collect profile_idc values up to 244, otherwise 0 for unknown.
-    Telemetry::Accumulate(Telemetry::VIDEO_DECODED_H264_SPS_PROFILE,
-                          spsdata.profile_idc <= 244 ? spsdata.profile_idc : 0);
-
-    // Make sure level_idc represents a value between levels 1 and 5.2,
-    // otherwise collect 0 for unknown level.
-    Telemetry::Accumulate(Telemetry::VIDEO_DECODED_H264_SPS_LEVEL,
-                          (spsdata.level_idc >= 10 && spsdata.level_idc <= 52) ?
-                          spsdata.level_idc : 0);
-
-    // max_num_ref_frames should be between 0 and 16, anything larger will
-    // be treated as invalid.
-    Telemetry::Accumulate(Telemetry::VIDEO_H264_SPS_MAX_NUM_REF_FRAMES,
-                          std::min(spsdata.max_num_ref_frames, 17u));
-
-    return true;
-  }
-
-  return false;
-}
+extern bool AccumulateSPSTelemetry(const MediaByteBuffer* aExtradata);
 
 // MP4Demuxer wants to do various blocking reads, which cause deadlocks while
 // mDemuxerMonitor is held. This stuff should really be redesigned, but we don't
 // have time for that right now. So in order to get proper synchronization while
 // keeping behavior as similar as possible, we do the following nasty hack:
 //
 // The demuxer has a Stream object with APIs to do both blocking and non-blocking
 // reads. When it does a blocking read, MP4Stream actually redirects it to a non-