Commit da77e32f authored by Hirokazu Honda's avatar Hirokazu Honda Committed by Commit Bot

media/gpu/V4L2Device: Query supported H264 profiles

Chromium should query a driver its supported H264 profiles. Thanks to this CL,
Chromium can know the truly supported profiles in advance.

Bug: 970152
Test: Check h264 profiles queried with driver patches
Change-Id: Ib387fdd9d5e606fa58d3a0f67734b6e42aac12a9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1903240Reviewed-by: default avatarChih-Yu Huang <akahuang@chromium.org>
Commit-Queue: Hirokazu Honda <hiroh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#714417}
parent 31ae2517
...@@ -1177,85 +1177,125 @@ uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile, ...@@ -1177,85 +1177,125 @@ uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
} }
// static // static
VideoCodecProfile V4L2Device::V4L2VP9ProfileToVideoCodecProfile( VideoCodecProfile V4L2Device::V4L2ProfileToVideoCodecProfile(VideoCodec codec,
uint32_t profile) { uint32_t profile) {
switch (profile) { switch (codec) {
case V4L2_MPEG_VIDEO_VP9_PROFILE_0: case kCodecH264:
return VP9PROFILE_PROFILE0; switch (profile) {
case V4L2_MPEG_VIDEO_VP9_PROFILE_1: case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
return VP9PROFILE_PROFILE1; case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
case V4L2_MPEG_VIDEO_VP9_PROFILE_2: return H264PROFILE_BASELINE;
return VP9PROFILE_PROFILE2; case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
case V4L2_MPEG_VIDEO_VP9_PROFILE_3: return H264PROFILE_MAIN;
return VP9PROFILE_PROFILE3; case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
return H264PROFILE_EXTENDED;
case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
return H264PROFILE_HIGH;
}
break;
case kCodecVP8:
switch (profile) {
case V4L2_MPEG_VIDEO_VP8_PROFILE_0:
case V4L2_MPEG_VIDEO_VP8_PROFILE_1:
case V4L2_MPEG_VIDEO_VP8_PROFILE_2:
case V4L2_MPEG_VIDEO_VP8_PROFILE_3:
return VP8PROFILE_ANY;
}
break;
case kCodecVP9:
switch (profile) {
case V4L2_MPEG_VIDEO_VP9_PROFILE_0:
return VP9PROFILE_PROFILE0;
case V4L2_MPEG_VIDEO_VP9_PROFILE_1:
return VP9PROFILE_PROFILE1;
case V4L2_MPEG_VIDEO_VP9_PROFILE_2:
return VP9PROFILE_PROFILE2;
case V4L2_MPEG_VIDEO_VP9_PROFILE_3:
return VP9PROFILE_PROFILE3;
}
break;
default: default:
VLOGF(2) << "Not a VP9 profile: " << profile; VLOGF(2) << "Unknown codec: " << codec;
return VIDEO_CODEC_PROFILE_UNKNOWN;
} }
VLOGF(2) << "Unknown profile: " << profile;
return VIDEO_CODEC_PROFILE_UNKNOWN;
} }
// static
std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles( std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles(
uint32_t pix_fmt, uint32_t pix_fmt,
bool is_encoder) { bool is_encoder) {
VideoCodecProfile min_profile, max_profile; auto get_supported_profiles = [this](
std::vector<VideoCodecProfile> profiles; VideoCodec codec,
std::vector<VideoCodecProfile>* profiles) {
uint32_t query_id = 0;
switch (codec) {
case kCodecH264:
query_id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
break;
case kCodecVP8:
query_id = V4L2_CID_MPEG_VIDEO_VP8_PROFILE;
break;
case kCodecVP9:
query_id = V4L2_CID_MPEG_VIDEO_VP9_PROFILE;
break;
default:
return false;
}
v4l2_queryctrl query_ctrl = {};
query_ctrl.id = query_id;
if (Ioctl(VIDIOC_QUERYCTRL, &query_ctrl) != 0) {
return false;
}
v4l2_querymenu query_menu = {};
query_menu.id = query_ctrl.id;
for (query_menu.index = query_ctrl.minimum;
static_cast<int>(query_menu.index) <= query_ctrl.maximum;
query_menu.index++) {
if (Ioctl(VIDIOC_QUERYMENU, &query_menu) == 0) {
const VideoCodecProfile profile =
V4L2Device::V4L2ProfileToVideoCodecProfile(codec, query_menu.index);
if (profile != VIDEO_CODEC_PROFILE_UNKNOWN)
profiles->push_back(profile);
}
}
return true;
};
std::vector<VideoCodecProfile> profiles;
switch (pix_fmt) { switch (pix_fmt) {
case V4L2_PIX_FMT_H264: case V4L2_PIX_FMT_H264:
case V4L2_PIX_FMT_H264_SLICE: case V4L2_PIX_FMT_H264_SLICE:
if (is_encoder) { if (!get_supported_profiles(kCodecH264, &profiles)) {
// TODO(posciak): need to query the device for supported H.264 profiles, DLOG(WARNING) << "Driver doesn't support QUERY H264 profiles, "
// for now choose Main as a sensible default. << "use default values, Base, Main, High";
min_profile = H264PROFILE_MAIN; profiles = {
max_profile = H264PROFILE_MAIN; H264PROFILE_BASELINE,
} else { H264PROFILE_MAIN,
min_profile = H264PROFILE_MIN; H264PROFILE_HIGH,
max_profile = H264PROFILE_MAX; };
} }
break; break;
case V4L2_PIX_FMT_VP8: case V4L2_PIX_FMT_VP8:
case V4L2_PIX_FMT_VP8_FRAME: case V4L2_PIX_FMT_VP8_FRAME:
min_profile = VP8PROFILE_MIN; profiles = {VP8PROFILE_ANY};
max_profile = VP8PROFILE_MAX;
break; break;
case V4L2_PIX_FMT_VP9: case V4L2_PIX_FMT_VP9:
case V4L2_PIX_FMT_VP9_FRAME: { case V4L2_PIX_FMT_VP9_FRAME:
v4l2_queryctrl query_ctrl = {}; if (!get_supported_profiles(kCodecVP9, &profiles)) {
query_ctrl.id = V4L2_CID_MPEG_VIDEO_VP9_PROFILE; DLOG(WARNING) << "Driver doesn't support QUERY VP9 profiles, "
if (Ioctl(VIDIOC_QUERYCTRL, &query_ctrl) == 0) { << "use default values, Profile0";
v4l2_querymenu query_menu = {}; profiles = {VP9PROFILE_PROFILE0};
query_menu.id = query_ctrl.id;
for (query_menu.index = query_ctrl.minimum;
static_cast<int>(query_menu.index) <= query_ctrl.maximum;
query_menu.index++) {
if (Ioctl(VIDIOC_QUERYMENU, &query_menu) == 0) {
const VideoCodecProfile profile =
V4L2VP9ProfileToVideoCodecProfile(query_menu.index);
if (profile != VIDEO_CODEC_PROFILE_UNKNOWN)
profiles.push_back(profile);
}
}
return profiles;
} else {
// TODO(keiichiw): need a fallback here?
VLOGF(2) << "V4L2_CID_MPEG_VIDEO_VP9_PROFILE is not supported.";
min_profile = VP9PROFILE_PROFILE0;
max_profile = VP9PROFILE_PROFILE0;
} }
break; break;
}
default: default:
VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt); VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt);
return profiles; return {};
} }
for (int profile = min_profile; profile <= max_profile; ++profile) // Erase duplicated profiles.
profiles.push_back(static_cast<VideoCodecProfile>(profile)); std::sort(profiles.begin(), profiles.end());
profiles.erase(std::unique(profiles.begin(), profiles.end()), profiles.end());
return profiles; return profiles;
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "media/base/video_codecs.h"
#include "media/base/video_decoder_config.h" #include "media/base/video_decoder_config.h"
#include "media/base/video_frame.h" #include "media/base/video_frame.h"
#include "media/base/video_frame_layout.h" #include "media/base/video_frame_layout.h"
...@@ -384,7 +385,8 @@ class MEDIA_GPU_EXPORT V4L2Device ...@@ -384,7 +385,8 @@ class MEDIA_GPU_EXPORT V4L2Device
// If there is no corresponding single- or multi-planar format, returns 0. // If there is no corresponding single- or multi-planar format, returns 0.
static uint32_t VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile, static uint32_t VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
bool slice_based); bool slice_based);
static VideoCodecProfile V4L2VP9ProfileToVideoCodecProfile(uint32_t profile); static VideoCodecProfile V4L2ProfileToVideoCodecProfile(VideoCodec codec,
uint32_t profile);
std::vector<VideoCodecProfile> V4L2PixFmtToVideoCodecProfiles( std::vector<VideoCodecProfile> V4L2PixFmtToVideoCodecProfiles(
uint32_t pix_fmt, uint32_t pix_fmt,
bool is_encoder); bool is_encoder);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment