Commit 937900aa authored by Hirokazu Honda's avatar Hirokazu Honda Committed by Chromium LUCI CQ

media/gpu/vaapi: Enable VaapiVideoDecoder to decode av1 10bit streams

This adds av1 10 bit streams decoding support to VaapiVideoDecoder.

Bug: b:172223934, b:172217032
Test: video_decode_accelerator_tests --use_vd bear-320x180-10bit.av1.ivf
Change-Id: I1c50516dba300fbe5e4b1056e931fb7da7264ef6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2563183
Commit-Queue: Hirokazu Honda <hiroh@chromium.org>
Reviewed-by: default avatarAndres Calderon Jaramillo <andrescj@chromium.org>
Reviewed-by: default avatarJeffrey Kardatzke <jkardatzke@google.com>
Reviewed-by: default avatarDavid Staessens <dstaessens@chromium.org>
Auto-Submit: Hirokazu Honda <hiroh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#834524}
parent f64c223e
......@@ -131,6 +131,7 @@ std::unique_ptr<Video> Video::ConvertToNV12() const {
new_video->thumbnail_checksums_ = thumbnail_checksums_;
new_video->profile_ = profile_;
new_video->codec_ = codec_;
new_video->bit_depth_ = bit_depth_;
new_video->frame_rate_ = frame_rate_;
new_video->num_frames_ = num_frames_;
new_video->num_fragments_ = num_fragments_;
......@@ -239,6 +240,10 @@ bool Video::Decode() {
LOG(ERROR) << "Decoding is currently only supported for VP9 videos";
return false;
}
if (bit_depth_ != 8u) {
LOG(ERROR) << "Decoding is currently only supported for 8bpp videos";
return false;
}
// The VpxVideoDecoder requires running on a SequencedTaskRunner, so we can't
// decode the video on the main test thread.
......@@ -294,6 +299,10 @@ VideoCodecProfile Video::Profile() const {
return profile_;
}
uint8_t Video::BitDepth() const {
return bit_depth_;
}
VideoPixelFormat Video::PixelFormat() const {
return pixel_format_;
}
......@@ -389,6 +398,21 @@ bool Video::LoadMetadata() {
codec_ = converted_codec.value();
}
// Find the video's bit depth. This is optional and only required for encoded
// video streams.
const base::Value* bit_depth =
metadata->FindKeyOfType("bit_depth", base::Value::Type::INTEGER);
if (bit_depth) {
bit_depth_ = base::checked_cast<uint8_t>(bit_depth->GetInt());
} else {
if (profile_ == VP9PROFILE_PROFILE2) {
LOG(ERROR) << "Bit depth is unspecified for VP9 profile 2";
return false;
}
constexpr uint8_t kDefaultBitDepth = 8u;
bit_depth_ = kDefaultBitDepth;
}
// Find the video's pixel format, only required for raw video streams.
pixel_format_ = VideoPixelFormat::PIXEL_FORMAT_UNKNOWN;
const base::Value* pixel_format =
......
......@@ -64,6 +64,8 @@ class Video {
VideoCodec Codec() const;
// Get the video's codec profile.
VideoCodecProfile Profile() const;
// Get the video's color bit depth.
uint8_t BitDepth() const;
// Get the video's pixel format.
VideoPixelFormat PixelFormat() const;
// Get the video frame rate.
......@@ -143,9 +145,11 @@ class Video {
// List of thumbnail checksums.
std::vector<std::string> thumbnail_checksums_;
// Video codec and profile for encoded videos.
// Video codec, profile and bit depth for encoded videos.
VideoCodecProfile profile_ = VIDEO_CODEC_PROFILE_UNKNOWN;
VideoCodec codec_ = kUnknownVideoCodec;
uint8_t bit_depth_ = 0u;
// Pixel format for raw videos.
VideoPixelFormat pixel_format_ = VideoPixelFormat::PIXEL_FORMAT_UNKNOWN;
......
......@@ -10,8 +10,10 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/containers/fixed_flat_map.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
#include "gpu/config/gpu_switches.h"
#include "media/base/bind_to_current_loop.h"
......@@ -46,23 +48,22 @@ namespace {
// Size of the timestamp cache, needs to be large enough for frame-reordering.
constexpr size_t kTimestampCacheSize = 128;
// Returns the preferred VA_RT_FORMAT for the given |profile|.
unsigned int GetVaFormatForVideoCodecProfile(VideoCodecProfile profile) {
if (profile == VP9PROFILE_PROFILE2 || profile == VP9PROFILE_PROFILE3)
return VA_RT_FORMAT_YUV420_10BPP;
return VA_RT_FORMAT_YUV420;
}
gfx::BufferFormat GetBufferFormat(VideoCodecProfile profile) {
base::Optional<VideoPixelFormat> GetPixelFormatForBitDepth(uint8_t bit_depth) {
constexpr auto kSupportedBitDepthAndGfxFormats = base::MakeFixedFlatMap<
uint8_t, gfx::BufferFormat>({
#if defined(USE_OZONE)
if (profile == VP9PROFILE_PROFILE2 || profile == VP9PROFILE_PROFILE3)
return gfx::BufferFormat::P010;
return gfx::BufferFormat::YUV_420_BIPLANAR;
{8u, gfx::BufferFormat::YUV_420_BIPLANAR}, {10u, gfx::BufferFormat::P010},
#else
return gfx::BufferFormat::RGBX_8888;
#endif
{8u, gfx::BufferFormat::RGBX_8888},
#endif // defined(USE_OZONE)
});
if (!base::Contains(kSupportedBitDepthAndGfxFormats, bit_depth)) {
VLOGF(1) << "Unsupported bit depth: " << base::strict_cast<int>(bit_depth);
return base::nullopt;
}
return GfxBufferFormatToVideoPixelFormat(
kSupportedBitDepthAndGfxFormats.at(bit_depth));
}
} // namespace
VaapiVideoDecoder::DecodeTask::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
......@@ -452,8 +453,7 @@ scoped_refptr<VASurface> VaapiVideoDecoder::CreateSurface() {
base::BindOnce(&VaapiVideoDecoder::ReleaseVideoFrame, weak_this_);
return new VASurface(surface_id, frame->layout().coded_size(),
GetVaFormatForVideoCodecProfile(profile_),
std::move(release_frame_cb));
va_surface->format(), std::move(release_frame_cb));
}
void VaapiVideoDecoder::SurfaceReady(scoped_refptr<VASurface> va_surface,
......@@ -512,14 +512,17 @@ void VaapiVideoDecoder::ApplyResolutionChange() {
DCHECK(output_frames_.empty());
VLOGF(2);
const uint8_t bit_depth = decoder_->GetBitDepth();
const base::Optional<VideoPixelFormat> format =
GetPixelFormatForBitDepth(bit_depth);
if (!format) {
SetState(State::kError);
return;
}
const gfx::Rect visible_rect = decoder_->GetVisibleRect();
const gfx::Size natural_size =
GetNaturalSize(visible_rect, pixel_aspect_ratio_);
const gfx::Size pic_size = decoder_->GetPicSize();
const base::Optional<VideoPixelFormat> format =
GfxBufferFormatToVideoPixelFormat(
GetBufferFormat(decoder_->GetProfile()));
CHECK(format);
auto format_fourcc = Fourcc::FromVideoPixelFormat(*format);
CHECK(format_fourcc);
if (!frame_pool_->Initialize(
......
......@@ -6,6 +6,7 @@
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "media/base/test_data_util.h"
#include "media/gpu/test/video.h"
......@@ -103,14 +104,15 @@ class VideoDecoderTest : public ::testing::Test {
output_folder, g_env->GetFrameOutputFormat(),
g_env->GetFrameOutputLimit());
}
// VP9 profile 2 supports 10 and 12 bit color depths, but we currently
// assume a profile 2 stream contains 10 bit color depth only.
// TODO(hiroh): Add bit depth info to Video class and follow it here.
if (g_env->Video()->BitDepth() != 8u &&
g_env->Video()->BitDepth() != 10u) {
LOG(ERROR) << "Unsupported bit depth: "
<< base::strict_cast<int>(g_env->Video()->BitDepth());
return nullptr;
}
const VideoPixelFormat validation_format =
g_env->Video()->Profile() == VP9PROFILE_PROFILE2
? PIXEL_FORMAT_YUV420P10
: PIXEL_FORMAT_I420;
g_env->Video()->BitDepth() == 10 ? PIXEL_FORMAT_YUV420P10
: PIXEL_FORMAT_I420;
frame_processors.push_back(media::test::MD5VideoFrameValidator::Create(
video->FrameChecksums(), validation_format, std::move(frame_writer)));
}
......
{
"profile": "VP9PROFILE_PROFILE2",
"bit_depth": 10,
"width": 320,
"height": 240,
"frame_rate": 25,
......
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