diff --git a/dom/media/fmp4/MP4Reader.cpp b/dom/media/fmp4/MP4Reader.cpp index f1df00e8c218..48c15c048d7e 100644 --- a/dom/media/fmp4/MP4Reader.cpp +++ b/dom/media/fmp4/MP4Reader.cpp @@ -15,7 +15,10 @@ #include "Layers.h" #include "SharedThreadPool.h" #include "mozilla/Preferences.h" +#include "mozilla/Telemetry.h" #include "mozilla/dom/TimeRanges.h" +#include "mp4_demuxer/AnnexB.h" +#include "mp4_demuxer/H264.h" #include "SharedDecoderManager.h" #ifdef MOZ_EME @@ -64,6 +67,28 @@ TrackTypeToStr(TrackType aTrack) } #endif +bool +AccumulateSPSTelemetry(const ByteBuffer* aExtradata) +{ + SPSData spsdata; + if (H264::DecodeSPSFromExtraData(aExtradata, spsdata) && + spsdata.profile_idc && spsdata.level_idc) { + // 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); + + return true; + } + + return false; +} + // 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 @@ -114,6 +139,7 @@ MP4Reader::MP4Reader(AbstractMediaDecoder* aDecoder) , mLastReportedNumDecodedFrames(0) , mLayersBackendType(layers::LayersBackend::LAYERS_NONE) , mDemuxerInitialized(false) + , mFoundSPSForTelemetry(false) , mIsEncrypted(false) , mIndexReady(false) , mDemuxerMonitor("MP4 Demuxer") @@ -465,6 +491,11 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo, nsresult rv = mVideo.mDecoder->Init(); NS_ENSURE_SUCCESS(rv, rv); mInfo.mVideo.mIsHardwareAccelerated = mVideo.mDecoder->IsHardwareAccelerated(); + + // Collect telemetry from h264 AVCC SPS. + if (!mFoundSPSForTelemetry) { + mFoundSPSForTelemetry = AccumulateSPSTelemetry(video.extra_data); + } } // Get the duration, and report it to the decoder if we have it. @@ -682,6 +713,13 @@ MP4Reader::Update(TrackType aTrack) if (needInput) { MP4Sample* sample = PopSample(aTrack); + + // Collect telemetry from h264 Annex B SPS. + if (sample && !mFoundSPSForTelemetry && AnnexB::HasSPS(sample)) { + nsRefPtr extradata = AnnexB::ExtractExtraData(sample); + mFoundSPSForTelemetry = AccumulateSPSTelemetry(extradata); + } + if (sample) { decoder.mDecoder->Input(sample); if (aTrack == kVideo) { diff --git a/dom/media/fmp4/MP4Reader.h b/dom/media/fmp4/MP4Reader.h index 04a1afc28efc..0c894a626d71 100644 --- a/dom/media/fmp4/MP4Reader.h +++ b/dom/media/fmp4/MP4Reader.h @@ -260,6 +260,9 @@ private: // True if we've read the streams' metadata. bool mDemuxerInitialized; + // True if we've gathered telemetry from an SPS. + bool mFoundSPSForTelemetry; + // Synchronized by decoder monitor. bool mIsEncrypted; diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index b76b1a0b4f92..64c74c0a2d1e 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -5471,6 +5471,18 @@ "n_values": 244, "description": "The H.264 profile number (profile_idc) as extracted from the codecs parameter passed to HTMLMediaElement.canPlayType." }, + "VIDEO_DECODED_H264_SPS_LEVEL": { + "expires_in_version": "40", + "kind": "enumerated", + "n_values": 51, + "description": "The H.264 level (level_idc) as extracted from the decoded SPS, from levels 1 (10) to 5.2 (51), with the addition of 0 for unknown values." + }, + "VIDEO_DECODED_H264_SPS_PROFILE": { + "expires_in_version": "40", + "kind": "enumerated", + "n_values": 244, + "description": "The H.264 profile number (profile_idc) as extracted from the decoded SPS." + }, "WEBRTC_ICE_FINAL_CONNECTION_STATE": { "expires_in_version": "never", "kind": "enumerated",