Skip to content

Commit

Permalink
Add UMA for camera pixel formats and resolutions
Browse files Browse the repository at this point in the history
These are measured the first time the capture process enumerates
devices. This can give insights into which pixel formats would be good
options for optimizations.

Tested with the unit tests, and compiling Chromium and checking
chrome://histograms

Bug: 1156144
Change-Id: Idb72a74822ac2e9206fadb37fe365fd85cb16a5a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2579510
Commit-Queue: Evan Shrubsole <eshr@google.com>
Reviewed-by: Markus Handell <handellm@google.com>
Reviewed-by: Weilun Shi <sweilun@chromium.org>
Reviewed-by: Ilya Sherman <isherman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836606}
  • Loading branch information
eshrubs authored and Chromium LUCI CQ committed Dec 14, 2020
1 parent 76de3fb commit e901a90
Show file tree
Hide file tree
Showing 7 changed files with 338 additions and 0 deletions.
3 changes: 3 additions & 0 deletions media/capture/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ component("capture_lib") {
"video/video_capture_buffer_tracker_factory_impl.h",
"video/video_capture_device_client.cc",
"video/video_capture_device_client.h",
"video/video_capture_metrics.cc",
"video/video_capture_metrics.h",
"video/video_capture_system.h",
"video/video_capture_system_impl.cc",
"video/video_capture_system_impl.h",
Expand Down Expand Up @@ -423,6 +425,7 @@ test("capture_unittests") {
"video/file_video_capture_device_unittest.cc",
"video/video_capture_device_client_unittest.cc",
"video/video_capture_device_unittest.cc",
"video/video_capture_metrics_unittest.cc",
"video_capture_types_unittest.cc",
]

Expand Down
180 changes: 180 additions & 0 deletions media/capture/video/video_capture_metrics.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/capture/video/video_capture_metrics.h"

#include "base/containers/fixed_flat_map.h"
#include "base/containers/flat_set.h"
#include "base/containers/span.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "ui/gfx/geometry/size.h"

namespace {

// These resolutions are ones supported on a test webcam. Names given
// where possible, from https://en.wikipedia.org/wiki/List_of_common_resolutions
enum class VideoResolutionDesignation {
kUnknown = 0, // Catch-all for resolutions not understood.
// Video Graphics Array resolutions
kQQVGA = 1, // 160x120
kHQVGA = 2, // 240x160
kQVGA = 3, // 320x240
kWQVGA = 4, // 432x240
kHVGA = 5, // 480x320
kVGA = 6, // 640x480
kWVGA = 7, // 720x480
kWSVGA = 8, // 1024x576
kSVGA = 9, // 800x600

// Extended Graphics Array resolutions
kSXGA_MINUS = 10, // 1280x960
kUXGA = 11, // 1600x1200
kQXGA = 12, // 2048x1536

// Common Intermediate Format resolutions
kQCIF = 13, // 176x144
kCIF = 14, // 352x288

// High-definition resolutions.
kNHD = 15, // 640x360
kQHD = 16, // 960x540
kHD_FULLSCREEN = 17, // 960x720
kHD = 18, // 1280x720
kHD_PLUS = 19, // 1600x900
kFHD = 20, // 1920x1080
kWQHD = 21, // 2560x1440
kQHD_PLUS = 22, // 3200x1800
k4K_UHD = 23, // 3840x2160
kDCI_4K = 24, // 4096x2160
k5K = 25, // 5120x2880
k8K_UHD = 26, // 7680x4320

// Odd resolutions with no name
k160x90 = 27,
k320x176 = 28,
k320x180 = 29,
k480x270 = 30,
k544x288 = 31,
k752x416 = 32,
k864x480 = 33,
k800x448 = 34,
k960x544 = 35,
k1184x656 = 36,
k1392x768 = 37,
k1504x832 = 38,
k1600x896 = 39,
k1712x960 = 40,
k1792x1008 = 41,
k2592x1944 = 42,

kMaxValue = k2592x1944,
};

struct FrameSizeCompare {
// Return true iff lhs < rhs.
constexpr bool operator()(const gfx::Size& lhs, const gfx::Size& rhs) const {
return (lhs.height() < rhs.height() ||
(lhs.height() == rhs.height() && lhs.width() < rhs.width()));
}
};

constexpr auto kResolutions =
base::MakeFixedFlatMap<gfx::Size, VideoResolutionDesignation>(
{
{{160, 120}, VideoResolutionDesignation::kQQVGA},
{{240, 160}, VideoResolutionDesignation::kHQVGA},
{{320, 240}, VideoResolutionDesignation::kQVGA},
{{432, 240}, VideoResolutionDesignation::kWQVGA},
{{480, 320}, VideoResolutionDesignation::kHVGA},
{{640, 480}, VideoResolutionDesignation::kVGA},
{{720, 480}, VideoResolutionDesignation::kWVGA},
{{1024, 576}, VideoResolutionDesignation::kWSVGA},
{{800, 600}, VideoResolutionDesignation::kSVGA},
{{1280, 960}, VideoResolutionDesignation::kSXGA_MINUS},
{{1600, 1200}, VideoResolutionDesignation::kUXGA},
{{2048, 1536}, VideoResolutionDesignation::kQXGA},
{{176, 144}, VideoResolutionDesignation::kQCIF},
{{352, 288}, VideoResolutionDesignation::kCIF},
{{640, 360}, VideoResolutionDesignation::kNHD},
{{960, 540}, VideoResolutionDesignation::kQHD},
{{960, 720}, VideoResolutionDesignation::kHD_FULLSCREEN},
{{1280, 720}, VideoResolutionDesignation::kHD},
{{1600, 900}, VideoResolutionDesignation::kHD_PLUS},
{{1920, 1080}, VideoResolutionDesignation::kFHD},
{{2560, 1440}, VideoResolutionDesignation::kWQHD},
{{3200, 1800}, VideoResolutionDesignation::kQHD_PLUS},
{{3840, 2160}, VideoResolutionDesignation::k4K_UHD},
{{4096, 2160}, VideoResolutionDesignation::kDCI_4K},
{{5120, 2880}, VideoResolutionDesignation::k5K},
{{7680, 4320}, VideoResolutionDesignation::k8K_UHD},
{{160, 90}, VideoResolutionDesignation::k160x90},
{{320, 176}, VideoResolutionDesignation::k320x176},
{{320, 180}, VideoResolutionDesignation::k320x180},
{{480, 270}, VideoResolutionDesignation::k480x270},
{{544, 288}, VideoResolutionDesignation::k544x288},
{{752, 416}, VideoResolutionDesignation::k752x416},
{{864, 480}, VideoResolutionDesignation::k864x480},
{{800, 448}, VideoResolutionDesignation::k800x448},
{{960, 544}, VideoResolutionDesignation::k960x544},
{{1184, 656}, VideoResolutionDesignation::k1184x656},
{{1392, 768}, VideoResolutionDesignation::k1392x768},
{{1504, 832}, VideoResolutionDesignation::k1504x832},
{{1600, 896}, VideoResolutionDesignation::k1600x896},
{{1712, 960}, VideoResolutionDesignation::k1712x960},
{{1792, 1008}, VideoResolutionDesignation::k1792x1008},
{{2592, 1944}, VideoResolutionDesignation::k2592x1944},
},
FrameSizeCompare());

static_assert(kResolutions.size() ==
static_cast<size_t>(VideoResolutionDesignation::kMaxValue),
"Each resolution must have one entry in kResolutions.");

VideoResolutionDesignation ResolutionNameFromSize(gfx::Size frame_size) {
// Rotate such that we are always in landscape.
if (frame_size.width() < frame_size.height()) {
int tmp = frame_size.width();
frame_size.set_width(frame_size.height());
frame_size.set_width(tmp);
}
auto* it = kResolutions.find(frame_size);
return it != kResolutions.end() ? it->second
: VideoResolutionDesignation::kUnknown;
}

} // namespace

namespace media {

void LogCaptureDeviceMetrics(
base::span<const media::VideoCaptureDeviceInfo> devices_info) {
for (const auto& device : devices_info) {
base::flat_set<media::VideoPixelFormat> supported_pixel_formats;
base::flat_set<gfx::Size, FrameSizeCompare> resolutions;
for (const auto& format : device.supported_formats) {
VLOG(2) << "Device supports "
<< media::VideoPixelFormatToString(format.pixel_format) << " at "
<< format.frame_size.ToString() << " ("
<< static_cast<int>(ResolutionNameFromSize(format.frame_size))
<< ")";
media::VideoPixelFormat pixel_format = format.pixel_format;
bool inserted = supported_pixel_formats.insert(pixel_format).second;
if (inserted) {
base::UmaHistogramEnumeration(
"Media.VideoCapture.Device.SupportedPixelFormat", pixel_format,
media::VideoPixelFormat::PIXEL_FORMAT_MAX);
}
if (!resolutions.contains(format.frame_size)) {
resolutions.insert(format.frame_size);
base::UmaHistogramEnumeration(
"Media.VideoCapture.Device.SupportedResolution",
ResolutionNameFromSize(format.frame_size));
}
}
}
}

} // namespace media
19 changes: 19 additions & 0 deletions media/capture/video/video_capture_metrics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_CAPTURE_VIDEO_VIDEO_CAPTURE_METRICS_H_
#define MEDIA_CAPTURE_VIDEO_VIDEO_CAPTURE_METRICS_H_

#include "base/containers/span.h"
#include "media/capture/video/video_capture_device_info.h"

namespace media {

CAPTURE_EXPORT
void LogCaptureDeviceMetrics(
base::span<const media::VideoCaptureDeviceInfo> devices_info);

} // namespace media

#endif // MEDIA_CAPTURE_VIDEO_VIDEO_CAPTURE_METRICS_H_
59 changes: 59 additions & 0 deletions media/capture/video/video_capture_metrics_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/capture/video/video_capture_metrics.h"

#include "base/test/metrics/histogram_tester.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace media {
namespace test {

TEST(VideoCaptureMetricsTest, TestLogCaptureDeviceMetrics) {
base::HistogramTester histogram_tester;
std::vector<media::VideoCaptureDeviceInfo> devices_info;
// First device
VideoCaptureDeviceInfo first_device;
first_device.supported_formats = {
// NV12 QQVGA at 30fps, 15fps
{{160, 120}, 30.0, media::PIXEL_FORMAT_NV12},
{{160, 120}, 15.0, media::PIXEL_FORMAT_NV12},
// NV12 VGA
{{640, 480}, 30.0, media::PIXEL_FORMAT_NV12},
// UYVY VGA
{{640, 480}, 30.0, media::PIXEL_FORMAT_UYVY},
// MJPEG 4K
{{3840, 2160}, 30.0, media::PIXEL_FORMAT_MJPEG},
// Odd resolution
{{844, 400}, 30.0, media::PIXEL_FORMAT_NV12},
// HD at unknown pixel format
{{1280, 720}, 30.0, media::PIXEL_FORMAT_UNKNOWN}};
devices_info.push_back(first_device);
VideoCaptureDeviceInfo second_device;
second_device.supported_formats = {
// UYVY VGA to test that we get 2 UYVY and 2 VGA in metrics.
{{640, 480}, 30.0, media::PIXEL_FORMAT_UYVY}};
devices_info.push_back(second_device);

LogCaptureDeviceMetrics(devices_info);

EXPECT_THAT(histogram_tester.GetAllSamples(
"Media.VideoCapture.Device.SupportedPixelFormat"),
testing::UnorderedElementsAre(
base::Bucket(media::PIXEL_FORMAT_NV12, 1),
base::Bucket(media::PIXEL_FORMAT_UYVY, 2),
base::Bucket(media::PIXEL_FORMAT_MJPEG, 1),
base::Bucket(media::PIXEL_FORMAT_UNKNOWN, 1)));

EXPECT_THAT(histogram_tester.GetAllSamples(
"Media.VideoCapture.Device.SupportedResolution"),
testing::UnorderedElementsAre(
base::Bucket(0 /*other*/, 1), base::Bucket(1 /*qqvga*/, 1),
base::Bucket(6 /*vga*/, 2), base::Bucket(23 /*4k_UHD*/, 1),
base::Bucket(18 /*hd*/, 1)));
}

} // namespace test
} // namespace media
6 changes: 6 additions & 0 deletions media/capture/video/video_capture_system_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "base/callback_helpers.h"
#include "build/build_config.h"
#include "media/base/bind_to_current_loop.h"
#include "media/capture/video/video_capture_metrics.h"

namespace {

Expand Down Expand Up @@ -111,6 +112,11 @@ void VideoCaptureSystemImpl::DevicesInfoReady(
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!device_enum_request_queue_.empty());

// Only save metrics the first time device infos are populated.
if (devices_info_cache_.empty()) {
LogCaptureDeviceMetrics(devices_info);
}

for (auto& device_info : devices_info) {
ConsolidateCaptureFormats(&device_info.supported_formats);
}
Expand Down
46 changes: 46 additions & 0 deletions tools/metrics/histograms/enums.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76097,6 +76097,52 @@ Full version information for the fingerprint enum values:
<int value="1" label="Play on cast device"/>
</enum>

<enum name="VideoResolutionDesignation">
<int value="0" label="Unknown"/>
<int value="1" label="QQVGA (160x120)"/>
<int value="2" label="HQVGA (240x160)"/>
<int value="3" label="QVGA (320x240)"/>
<int value="4" label="WQVGA (432x240)"/>
<int value="5" label="HVGA (480x320)"/>
<int value="6" label="VGA (640x480)"/>
<int value="7" label="WVGA (720x480)"/>
<int value="8" label="WSVGA (1024x576)"/>
<int value="9" label="SVGA (800x600)"/>
<int value="10" label="SXGA- (1280x960)"/>
<int value="11" label="UXGA (1600x1200)"/>
<int value="12" label="QXGA (2048x1536)"/>
<int value="13" label="QCIF (176x144)"/>
<int value="14" label="CIF (352x288)"/>
<int value="15" label="NHD (640x360)"/>
<int value="16" label="QHD (960x540)"/>
<int value="17" label="HD Fullscreen (960x720)"/>
<int value="18" label="HD (1280x720)"/>
<int value="19" label="HD_PLUS (1600x900)"/>
<int value="20" label="FHD (1920x1080)"/>
<int value="21" label="WQHD (2560x1440)"/>
<int value="22" label="QHD+ (3200x1800)"/>
<int value="23" label="4K UHD (3840x2160)"/>
<int value="24" label="DCI 4K (4096x2160)"/>
<int value="25" label="5K (5120x2880)"/>
<int value="26" label="8K UHD (7680x4320)"/>
<int value="27" label="160x90"/>
<int value="28" label="320x176"/>
<int value="29" label="320x180"/>
<int value="30" label="480x270"/>
<int value="31" label="544x288"/>
<int value="32" label="752x416"/>
<int value="33" label="864x480"/>
<int value="34" label="800x448"/>
<int value="35" label="960x544"/>
<int value="36" label="1184x656"/>
<int value="37" label="1392x768"/>
<int value="38" label="1504x832"/>
<int value="39" label="1600x896"/>
<int value="40" label="1712x960"/>
<int value="41" label="1792x1008"/>
<int value="42" label="2592x1944"/>
</enum>

<enum name="VideoRotation">
<int value="0" label="VIDEO_ROTATION_0"/>
<int value="1" label="VIDEO_ROTATION_90"/>
Expand Down
25 changes: 25 additions & 0 deletions tools/metrics/histograms/histograms_xml/media/histograms.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3732,6 +3732,31 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</summary>
</histogram>

<histogram name="Media.VideoCapture.Device.SupportedPixelFormat"
enum="VideoPixelFormatUnion" expires_after="M92">
<owner>eshr@google.com</owner>
<owner>handellm@google.com</owner>
<summary>
Counts each pixel format an enumerated video capture device supports. This
is recorded during the first device enumeration per Capture process launch.
(This is usually once per launch of Chrome unless the Capture process
crashes.)
</summary>
</histogram>

<histogram name="Media.VideoCapture.Device.SupportedResolution"
enum="VideoResolutionDesignation" expires_after="M92">
<owner>eshr@google.com</owner>
<owner>handellm@google.com</owner>
<summary>
Counts each resolution supported by an enumerated video capture device.
These are categorized by designation (eg. QVGA, HD, 4KUHD, etc) instead of
pixel count. This is recorded during the first device enumeration per
Capture process launch. (This is usually once per launch of Chrome unless
the Capture process crashes.)
</summary>
</histogram>

<histogram name="Media.VideoCapture.Error" enum="VideoCaptureError"
expires_after="2021-05-02">
<owner>mcasas@chromium.org</owner>
Expand Down

0 comments on commit e901a90

Please sign in to comment.