Bug 1513651 - Add gtest for MP4 metadata telemetry probes. r=chutten
authorBryce Van Dyk <bvandyk@mozilla.com>
Mon, 11 Feb 2019 20:15:22 +0000
changeset 459138 946f649535c1b323296e3ba2fc039db1fe4d0a63
parent 459137 c387900cf31b23ff830fc3f101303c8ac761b544
child 459139 fdf2d461ceb2f2d2f9e8a571c5a29641db351521
push id35556
push userdvarga@mozilla.com
push dateFri, 15 Feb 2019 01:38:24 +0000
treeherdermozilla-central@b29c87add05f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerschutten
bugs1513651
milestone67.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 1513651 - Add gtest for MP4 metadata telemetry probes. r=chutten Add a gtest to cover the new telemetry probes which collect info on sample description entries. Add a new init segment to those already in our gtests. This segment has data for one video track, and covers the case where multiple sample description entries are present for a single track. In this case, because separate sample description entries are used for unencrypted and encrypted samples. For reference, the test init segment was created from our existing bipbop using shaka-packager via the following command (non-init segments were discarded and the output was renamed): packager-win.exe in=bipbop.mp4,stream=video,init_segment=bipbop_cbcs_video_init.mp4,segment_template=bipbop_cbcs_video_$Number$.m4s --protection_scheme cbcs --enable_raw_key_encryption --keys label=:key_id=7e571d047e571d047e571d047e571d21:key=7e5744447e5744447e5744447e574421 --iv 11223344556677889900112233445566 --generate_static_mpd --mpd_output bipbop_cbcs.mpd Depends on D14426 Differential Revision: https://phabricator.services.mozilla.com/D19386
dom/media/gtest/mp4_demuxer/TestParser.cpp
dom/media/gtest/mp4_demuxer/moz.build
dom/media/gtest/mp4_demuxer/test_case_1513651-2-sample-description-entries.mp4
--- a/dom/media/gtest/mp4_demuxer/TestParser.cpp
+++ b/dom/media/gtest/mp4_demuxer/TestParser.cpp
@@ -2,19 +2,22 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gtest/gtest.h"
 #include "MediaData.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/Tuple.h"
 #include "BufferStream.h"
 #include "MP4Metadata.h"
 #include "MoofParser.h"
+#include "TelemetryFixture.h"
+#include "TelemetryTestHelpers.h"
 
 class TestStream;
 namespace mozilla {
 DDLoggedTypeNameAndBase(::TestStream, ByteStream);
 }  // namespace mozilla
 
 using namespace mozilla;
 
@@ -762,8 +765,215 @@ TEST(MP4Metadata, EmptyCTTS) {
   EXPECT_EQ(1u, metadata.GetNumberTracks(TrackInfo::kVideoTrack).Ref());
   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().Ref()->valid);
 }
+
+// Fixture so we test telemetry probes.
+class MP4MetadataTelemetryFixture : public TelemetryTestFixture {};
+
+TEST_F(MP4MetadataTelemetryFixture, Telemetry) {
+  // Helper to fetch the metadata from a file and send telemetry in the process.
+  auto UpdateMetadataAndHistograms = [](const char* testFileName) {
+    nsTArray<uint8_t> buffer = ReadTestFile(testFileName);
+    ASSERT_FALSE(buffer.IsEmpty());
+    RefPtr<ByteStream> stream =
+        new TestStream(buffer.Elements(), buffer.Length());
+
+    MP4Metadata::ResultAndByteBuffer metadataBuffer =
+        MP4Metadata::Metadata(stream);
+    EXPECT_EQ(NS_OK, metadataBuffer.Result());
+    EXPECT_TRUE(metadataBuffer.Ref());
+
+    MP4Metadata metadata(stream);
+    nsresult res = metadata.Parse();
+    EXPECT_TRUE(NS_SUCCEEDED(res));
+    auto audioTrackCount = metadata.GetNumberTracks(TrackInfo::kAudioTrack);
+    ASSERT_NE(audioTrackCount.Ref(), MP4Metadata::NumberTracksError());
+    auto videoTrackCount = metadata.GetNumberTracks(TrackInfo::kVideoTrack);
+    ASSERT_NE(videoTrackCount.Ref(), MP4Metadata::NumberTracksError());
+
+    // Need to read the track data to get telemetry to fire.
+    for (uint32_t i = 0; i < audioTrackCount.Ref(); i++) {
+      metadata.GetTrackInfo(TrackInfo::kAudioTrack, i);
+    }
+    for (uint32_t i = 0; i < videoTrackCount.Ref(); i++) {
+      metadata.GetTrackInfo(TrackInfo::kVideoTrack, i);
+    }
+  };
+
+  AutoJSContextWithGlobal cx(mCleanGlobal);
+
+  // Checks the current state of the histograms relating to sample description
+  // entries and verifies they're in an expected state.
+  // aExpectedMultipleCodecCounts is a tuple where the first value represents
+  // the number of expected 'false' count, and the second the expected 'true'
+  // count for the sample description entries have multiple codecs histogram.
+  // aExpectedMultipleCryptoCounts is the same, but for the sample description
+  // entires have multiple crypto histogram.
+  // aExpectedSampleDescriptionEntryCounts is a tuple with 6 values, each is
+  // the expected number of sample description seen. I.e, the first value in the
+  // tuple is the number of tracks we've seen with 0 sample descriptions, the
+  // second value with 1 sample description, and so on up to 5 sample
+  // descriptions. aFileName is the name of the most recent file we've parsed,
+  // and is used to log if our telem counts are not in an expected state.
+  auto CheckHistograms =
+      [this, &cx](
+          const Tuple<uint32_t, uint32_t>& aExpectedMultipleCodecCounts,
+          const Tuple<uint32_t, uint32_t>& aExpectedMultipleCryptoCounts,
+          const Tuple<uint32_t, uint32_t, uint32_t, uint32_t, uint32_t,
+                      uint32_t>& aExpectedSampleDescriptionEntryCounts,
+          const char* aFileName) {
+        // Get a snapshot of the current histograms
+        JS::RootedValue snapshot(cx.GetJSContext());
+        TelemetryTestHelpers::GetSnapshots(cx.GetJSContext(), mTelemetry,
+                                           "" /* this string is unused */,
+                                           &snapshot, false /* is_keyed */);
+
+        // We'll use these to pull values out of the histograms.
+        JS::RootedValue values(cx.GetJSContext());
+        JS::RootedValue value(cx.GetJSContext());
+
+        // Verify our multiple codecs count histogram.
+        JS::RootedValue multipleCodecsHistogram(cx.GetJSContext());
+        TelemetryTestHelpers::GetProperty(
+            cx.GetJSContext(),
+            "MEDIA_MP4_PARSE_SAMPLE_DESCRIPTION_ENTRIES_HAVE_MULTIPLE_CODECS",
+            snapshot, &multipleCodecsHistogram);
+        ASSERT_TRUE(multipleCodecsHistogram.isObject())
+            << "Multiple codecs histogram should exist!";
+
+        TelemetryTestHelpers::GetProperty(cx.GetJSContext(), "values",
+                                          multipleCodecsHistogram, &values);
+        // False count.
+        TelemetryTestHelpers::GetElement(cx.GetJSContext(), 0, values, &value);
+        uint32_t uValue = 0;
+        JS::ToUint32(cx.GetJSContext(), value, &uValue);
+        EXPECT_EQ(Get<0>(aExpectedMultipleCodecCounts), uValue)
+            << "Unexpected number of false multiple codecs after parsing "
+            << aFileName;
+        // True count.
+        TelemetryTestHelpers::GetElement(cx.GetJSContext(), 1, values, &value);
+        JS::ToUint32(cx.GetJSContext(), value, &uValue);
+        EXPECT_EQ(Get<1>(aExpectedMultipleCodecCounts), uValue)
+            << "Unexpected number of true multiple codecs after parsing "
+            << aFileName;
+
+        // Verify our multiple crypto count histogram.
+        JS::RootedValue multipleCryptoHistogram(cx.GetJSContext());
+        TelemetryTestHelpers::GetProperty(
+            cx.GetJSContext(),
+            "MEDIA_MP4_PARSE_SAMPLE_DESCRIPTION_ENTRIES_HAVE_MULTIPLE_CRYPTO",
+            snapshot, &multipleCryptoHistogram);
+        ASSERT_TRUE(multipleCryptoHistogram.isObject())
+            << "Multiple crypto histogram should exist!";
+
+        TelemetryTestHelpers::GetProperty(cx.GetJSContext(), "values",
+                                          multipleCryptoHistogram, &values);
+        // False count.
+        TelemetryTestHelpers::GetElement(cx.GetJSContext(), 0, values, &value);
+        JS::ToUint32(cx.GetJSContext(), value, &uValue);
+        EXPECT_EQ(Get<0>(aExpectedMultipleCryptoCounts), uValue)
+            << "Unexpected number of false multiple cryptos after parsing "
+            << aFileName;
+        // True count.
+        TelemetryTestHelpers::GetElement(cx.GetJSContext(), 1, values, &value);
+        JS::ToUint32(cx.GetJSContext(), value, &uValue);
+        EXPECT_EQ(Get<1>(aExpectedMultipleCryptoCounts), uValue)
+            << "Unexpected number of true multiple cryptos after parsing "
+            << aFileName;
+
+        // Verify our sample description entry count histogram.
+        JS::RootedValue numSamplesHistogram(cx.GetJSContext());
+        TelemetryTestHelpers::GetProperty(
+            cx.GetJSContext(), "MEDIA_MP4_PARSE_NUM_SAMPLE_DESCRIPTION_ENTRIES",
+            snapshot, &numSamplesHistogram);
+        ASSERT_TRUE(numSamplesHistogram.isObject())
+            << "Num sample description entries histogram should exist!";
+
+        TelemetryTestHelpers::GetProperty(cx.GetJSContext(), "values",
+                                          numSamplesHistogram, &values);
+
+        TelemetryTestHelpers::GetElement(cx.GetJSContext(), 0, values, &value);
+        JS::ToUint32(cx.GetJSContext(), value, &uValue);
+        EXPECT_EQ(Get<0>(aExpectedSampleDescriptionEntryCounts), uValue)
+            << "Unexpected number of 0 sample entry descriptions after parsing "
+            << aFileName;
+        TelemetryTestHelpers::GetElement(cx.GetJSContext(), 1, values, &value);
+        JS::ToUint32(cx.GetJSContext(), value, &uValue);
+        EXPECT_EQ(Get<1>(aExpectedSampleDescriptionEntryCounts), uValue)
+            << "Unexpected number of 1 sample entry descriptions after parsing "
+            << aFileName;
+        TelemetryTestHelpers::GetElement(cx.GetJSContext(), 2, values, &value);
+        JS::ToUint32(cx.GetJSContext(), value, &uValue);
+        EXPECT_EQ(Get<2>(aExpectedSampleDescriptionEntryCounts), uValue)
+            << "Unexpected number of 2 sample entry descriptions after parsing "
+            << aFileName;
+        TelemetryTestHelpers::GetElement(cx.GetJSContext(), 3, values, &value);
+        JS::ToUint32(cx.GetJSContext(), value, &uValue);
+        EXPECT_EQ(Get<3>(aExpectedSampleDescriptionEntryCounts), uValue)
+            << "Unexpected number of 3 sample entry descriptions after parsing "
+            << aFileName;
+        TelemetryTestHelpers::GetElement(cx.GetJSContext(), 4, values, &value);
+        JS::ToUint32(cx.GetJSContext(), value, &uValue);
+        EXPECT_EQ(Get<4>(aExpectedSampleDescriptionEntryCounts), uValue)
+            << "Unexpected number of 4 sample entry descriptions after parsing "
+            << aFileName;
+        TelemetryTestHelpers::GetElement(cx.GetJSContext(), 5, values, &value);
+        JS::ToUint32(cx.GetJSContext(), value, &uValue);
+        EXPECT_EQ(Get<5>(aExpectedSampleDescriptionEntryCounts), uValue)
+            << "Unexpected number of 5 sample entry descriptions after parsing "
+            << aFileName;
+      };
+
+  // Clear histograms
+  TelemetryTestHelpers::GetAndClearHistogram(
+      cx.GetJSContext(), mTelemetry,
+      NS_LITERAL_CSTRING(
+          "MEDIA_MP4_PARSE_SAMPLE_DESCRIPTION_ENTRIES_HAVE_MULTIPLE_CODECS"),
+      false /* is_keyed */);
+
+  TelemetryTestHelpers::GetAndClearHistogram(
+      cx.GetJSContext(), mTelemetry,
+      NS_LITERAL_CSTRING(
+          "MEDIA_MP4_PARSE_SAMPLE_DESCRIPTION_ENTRIES_HAVE_MULTIPLE_CRYPTO"),
+      false /* is_keyed */);
+
+  TelemetryTestHelpers::GetAndClearHistogram(
+      cx.GetJSContext(), mTelemetry,
+      NS_LITERAL_CSTRING("MEDIA_MP4_PARSE_NUM_SAMPLE_DESCRIPTION_ENTRIES"),
+      false /* is_keyed */);
+
+  // The snapshot won't have any data in it until we populate our histograms, so
+  // we don't check for a baseline here. Just read out first MP4 metadata.
+
+  // Grab one of the test cases we know should parse and parse it, this should
+  // trigger telemetry gathering.
+
+  // This file contains 2 moovs, each with a video and audio track with one
+  // sample description entry. So we should see 4 tracks, each with a single
+  // codec, no crypto, and a single sample description entry.
+  UpdateMetadataAndHistograms("test_case_1185230.mp4");
+
+  // Verify our histograms are updated.
+  CheckHistograms(
+      MakeTuple<uint32_t, uint32_t>(4, 0), MakeTuple<uint32_t, uint32_t>(4, 0),
+      MakeTuple<uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t>(
+          0, 4, 0, 0, 0, 0),
+      "test_case_1185230.mp4");
+
+  // Parse another test case. This one has a single moov with a single video
+  // track. However, the track has two sample description entries, and our
+  // updated telemetry should reflect that.
+  UpdateMetadataAndHistograms(
+      "test_case_1513651-2-sample-description-entries.mp4");
+
+  // Verify our histograms are updated.
+  CheckHistograms(
+      MakeTuple<uint32_t, uint32_t>(5, 0), MakeTuple<uint32_t, uint32_t>(5, 0),
+      MakeTuple<uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t>(
+          0, 4, 1, 0, 0, 0),
+      "test_case_1513651-2-sample-description-entries.mp4");
+}
--- a/dom/media/gtest/mp4_demuxer/moz.build
+++ b/dom/media/gtest/mp4_demuxer/moz.build
@@ -37,22 +37,24 @@ TEST_HARNESS_FILES.gtest += [
     'test_case_1329061.mov',
     'test_case_1351094.mp4',
     'test_case_1380468.mp4',
     'test_case_1388991.mp4',
     'test_case_1389299.mp4',
     'test_case_1389527.mp4',
     'test_case_1395244.mp4',
     'test_case_1410565.mp4',
+    'test_case_1513651-2-sample-description-entries.mp4',
     'test_case_1519617-cenc-init-with-track_id-0.mp4',
     'test_case_1519617-track2-trafs-removed.mp4',
     'test_case_1519617-video-has-track_id-0.mp4',
 ]
 
 UNIFIED_SOURCES += ['TestMP4.cpp',]
 TEST_HARNESS_FILES.gtest += [
     '../../test/street.mp4',
 ]
 LOCAL_INCLUDES += [
     '../../mp4',
+    '/toolkit/components/telemetry/tests/gtest',
 ]
 
 FINAL_LIBRARY = 'xul-gtest'
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2f8f235a9b4b826547a387fdb4ffc801d317a9b3
GIT binary patch
literal 1100
zc$~#j&1(}u6rU*p(Y6pVg$i0$DJW<XlPx8Y9vag_iWa2UcoAeWGy6eyvdhkN>j#K}
zhhBtU{SyQW;;A=12>uCP#E*IvJa`m|Z*~(M(^}}sVc)!u`OTa6d;1VVvyQqO`7#s;
z7U-IY<|>Rxk0i80g+md_ofl!4z;PfFk7?Yy_ttkU2;bh)KEmnuXZ_{u^%v2BYYb#d
za76~b<*^_h9xgB0)e$@!#-`qal}lsSuCFe)L0>`0Q!0{|%VpPB-g>7*Ls53a&<%JQ
zSawM<BD70f9;2jMs+KMl>%3mGZBFLxV$1_hB!`lAR7|>%@0RMOJvj2a2YcBbst*`C
zh%ctJZwTgV&X!>N_j&D2daY>oBk>tGbGE?`TcpPVt}(bT{GJ2GEX(vM7IViaXJS1L
ztjxx*r0N8qrBsp`KVz5oXz~wAKmf{bfzcWUjy2j%s~N(B?*46=?)PE803+7KD~nV8
z&!}(?^t0*eiJzY)8xI@XFShT0#27~J!_iHE5}6f0;lzUI$ppI~sh3VI?NB)=s}3<A
zbVWhMY3L+I4{n~$8FD6n{H(pS=4@;}MVSS#M}wsQjbUCYC5;5&OKSK9@b8U00vH;a
zm_(#=V-l!|gx}Fv!Lyk{laHUkZmBqp4+(>e?-=*yA}Kw6kl*<B_4Uh@vFBeFW>$B9
MT-Dgoj_M1)0E-F2S^xk5