v4l2: Enable HEVC 10-bit decoding
This adds the HEVC Main 10 profiles to V4L2 and then also adds sending the EXT_CTRLS ioctl before CAPTURE format negotiation if it is a 10-bit HEVC format we are decoding. Doing that then enables the CAPTURE queue to return the proper 10-bit formats needed for output. BUG=b:326972730 TEST=HEVC 10-bit playback works on cherry w/ HEVC forcibly enabled Change-Id: If7ccfc0cff747016308fbec2971b1a25ebc8b98a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5322262 Reviewed-by: Steve Cho <stevecho@chromium.org> Commit-Queue: Jeffrey Kardatzke <jkardatzke@google.com> Cr-Commit-Position: refs/heads/main@{#1265527}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
aec1edfdc1
commit
90fa47c897
@ -185,7 +185,8 @@ static const std::map<v4l2_enum_type, std::vector<VideoCodecProfile>>
|
||||
H264PROFILE_HIGH,
|
||||
}},
|
||||
#if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
|
||||
{V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, {HEVCPROFILE_MAIN}},
|
||||
{V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
|
||||
{HEVCPROFILE_MAIN, HEVCPROFILE_MAIN10}},
|
||||
#endif // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
|
||||
{V4L2_CID_MPEG_VIDEO_VP8_PROFILE, {VP8PROFILE_ANY}},
|
||||
{V4L2_CID_MPEG_VIDEO_VP9_PROFILE, {VP9PROFILE_PROFILE0}},
|
||||
|
@ -344,7 +344,8 @@ static const std::map<v4l2_enum_type, std::vector<VideoCodecProfile>>
|
||||
H264PROFILE_HIGH,
|
||||
}},
|
||||
#if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
|
||||
{V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, {HEVCPROFILE_MAIN}},
|
||||
{V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
|
||||
{HEVCPROFILE_MAIN, HEVCPROFILE_MAIN10}},
|
||||
#endif // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
|
||||
{V4L2_CID_MPEG_VIDEO_VP8_PROFILE, {VP8PROFILE_ANY}},
|
||||
{V4L2_CID_MPEG_VIDEO_VP9_PROFILE, {VP9PROFILE_PROFILE0}},
|
||||
@ -363,6 +364,7 @@ static const std::map<VideoCodecProfile,
|
||||
{H264PROFILE_HIGH, MAKE_V4L2_CODEC_PAIR(V4L2_PIX_FMT_H264, SLICE)},
|
||||
#if BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
|
||||
{HEVCPROFILE_MAIN, MAKE_V4L2_CODEC_PAIR(V4L2_PIX_FMT_HEVC, SLICE)},
|
||||
{HEVCPROFILE_MAIN10, MAKE_V4L2_CODEC_PAIR(V4L2_PIX_FMT_HEVC, SLICE)},
|
||||
#endif // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
|
||||
{VP8PROFILE_ANY, MAKE_V4L2_CODEC_PAIR(V4L2_PIX_FMT_VP8, FRAME)},
|
||||
{VP9PROFILE_PROFILE0, MAKE_V4L2_CODEC_PAIR(V4L2_PIX_FMT_VP9, FRAME)},
|
||||
|
@ -648,6 +648,14 @@ CroStatus V4L2VideoDecoder::SetupOutputFormat(const gfx::Size& size,
|
||||
DVLOGF(3) << "size: " << size.ToString()
|
||||
<< ", visible_rect: " << visible_rect.ToString();
|
||||
|
||||
if (bit_depth == 10u) {
|
||||
VLOGF(1) << "10-bit format, need to set EXT_CTRLS first";
|
||||
CroStatus ext_status = SetExtCtrls10Bit(size);
|
||||
if (ext_status != CroStatus::Codes::kOk) {
|
||||
return ext_status;
|
||||
}
|
||||
}
|
||||
|
||||
const auto v4l2_pix_fmts = EnumerateSupportedPixFmts(
|
||||
base::BindRepeating(&V4L2Device::Ioctl, device_),
|
||||
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
||||
@ -666,8 +674,9 @@ CroStatus V4L2VideoDecoder::SetupOutputFormat(const gfx::Size& size,
|
||||
// P010 and NV12, and then down sample to NV12 if it is selected. This is
|
||||
// not desired, so drop the candidates that don't match the bit depth of the
|
||||
// stream.
|
||||
const size_t candidate_bit_depth =
|
||||
BitDepth(candidate->ToVideoPixelFormat());
|
||||
size_t candidate_bit_depth = (candidate == Fourcc(Fourcc::MT2T))
|
||||
? 10u
|
||||
: (candidate->ToVideoPixelFormat());
|
||||
if (candidate_bit_depth != bit_depth) {
|
||||
DVLOGF(1) << "Enumerated format " << candidate->ToString()
|
||||
<< " with a bit depth of " << candidate_bit_depth
|
||||
@ -761,6 +770,47 @@ CroStatus V4L2VideoDecoder::SetupOutputFormat(const gfx::Size& size,
|
||||
return CroStatus::Codes::kOk;
|
||||
}
|
||||
|
||||
CroStatus V4L2VideoDecoder::SetExtCtrls10Bit(const gfx::Size& size) {
|
||||
struct v4l2_ext_control ctrl;
|
||||
std::vector<struct v4l2_ext_control> ctrls;
|
||||
|
||||
if (input_format_fourcc_ == V4L2_PIX_FMT_HEVC_SLICE) {
|
||||
VLOGF(1) << "Setting EXT_CTRLS for 10-bit HEVC";
|
||||
// For 10-bit formats the CAPTURE queue will not report the proper formats
|
||||
// until the SPS data is sent in to indicate 10-bit content. We also set the
|
||||
// size and chroma format since that should be all the information needed in
|
||||
// order to know the format.
|
||||
struct v4l2_ctrl_hevc_sps v4l2_sps;
|
||||
memset(&v4l2_sps, 0, sizeof(v4l2_sps));
|
||||
v4l2_sps.pic_width_in_luma_samples = size.width();
|
||||
v4l2_sps.pic_height_in_luma_samples = size.height();
|
||||
v4l2_sps.bit_depth_luma_minus8 = 2;
|
||||
v4l2_sps.bit_depth_chroma_minus8 = 2;
|
||||
v4l2_sps.chroma_format_idc = 1; // 4:2:0
|
||||
memset(&ctrl, 0, sizeof(ctrl));
|
||||
ctrl.id = V4L2_CID_STATELESS_HEVC_SPS;
|
||||
ctrl.size = sizeof(v4l2_sps);
|
||||
ctrl.ptr = &v4l2_sps;
|
||||
ctrls.push_back(ctrl);
|
||||
} else {
|
||||
// TODO(b/): Add other 10-bit codecs
|
||||
return CroStatus::Codes::kNoDecoderOutputFormatCandidates;
|
||||
}
|
||||
|
||||
struct v4l2_ext_controls ext_ctrls;
|
||||
memset(&ext_ctrls, 0, sizeof(ext_ctrls));
|
||||
ext_ctrls.count = ctrls.size();
|
||||
ext_ctrls.controls = ctrls.data();
|
||||
ext_ctrls.which = V4L2_CTRL_WHICH_CUR_VAL;
|
||||
ext_ctrls.request_fd = -1;
|
||||
if (device_->Ioctl(VIDIOC_S_EXT_CTRLS, &ext_ctrls) != 0) {
|
||||
VPLOGF(1) << "ioctl() failed: VIDIOC_S_EXT_CTRLS";
|
||||
return CroStatus::Codes::kNoDecoderOutputFormatCandidates;
|
||||
}
|
||||
|
||||
return CroStatus::Codes::kOk;
|
||||
}
|
||||
|
||||
void V4L2VideoDecoder::Reset(base::OnceClosure closure) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
|
||||
DVLOGF(3);
|
||||
|
@ -135,6 +135,12 @@ class MEDIA_GPU_EXPORT V4L2VideoDecoder
|
||||
size_t num_codec_reference_frames,
|
||||
uint8_t bit_depth);
|
||||
|
||||
// Sends the EXT_CTRLS ioctl for 10-bit video at the specified |size|. This
|
||||
// will enable retrieving the proper format from the CAPTURE queue. |size| is
|
||||
// needed so that we are passing in all the information that might be needed
|
||||
// by the driver to know what the format is.
|
||||
CroStatus SetExtCtrls10Bit(const gfx::Size& size);
|
||||
|
||||
// Start streaming V4L2 input and (if |start_output_queue| is true) output
|
||||
// queues. Attempt to start |device_poll_thread_| after streaming starts.
|
||||
bool StartStreamV4L2Queue(bool start_output_queue);
|
||||
|
@ -405,7 +405,7 @@ bool V4L2StatelessVideoDecoderBackend::PumpDecodeTask() {
|
||||
while (true) {
|
||||
switch (decoder_->Decode()) {
|
||||
case AcceleratedVideoDecoder::kConfigChange:
|
||||
if (decoder_->GetBitDepth() != 8u) {
|
||||
if (decoder_->GetBitDepth() != 8u && decoder_->GetBitDepth() != 10u) {
|
||||
VLOGF(2) << "Unsupported bit depth: "
|
||||
<< base::strict_cast<int>(decoder_->GetBitDepth());
|
||||
return false;
|
||||
|
Reference in New Issue
Block a user