Commit 4553b3c8 authored by Hirokazu Honda's avatar Hirokazu Honda Committed by Chromium LUCI CQ

media/gpu/AV1Decoder: Deny av1 film grain streams on ChromeOS

The hardware video decoder outputs color artifacts with av1 film
grain streams. We deny av1 film grain streams so that software
decoders are instead used for them.

Bug: b:176927551
Test: No artifacts with film grain streams (i.e. software decoders are used) on volteer
Change-Id: I85eceb0a82ee6e021943194d2429c1c6be87fe4b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2615723
Auto-Submit: Hirokazu Honda <hiroh@chromium.org>
Commit-Queue: Andres Calderon Jaramillo <andrescj@chromium.org>
Reviewed-by: default avatarAndres Calderon Jaramillo <andrescj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843393}
parent 84957eeb
...@@ -541,7 +541,10 @@ source_set("unit_tests") { ...@@ -541,7 +541,10 @@ source_set("unit_tests") {
if ((is_chromeos_ash && use_vaapi) || is_win) { if ((is_chromeos_ash && use_vaapi) || is_win) {
sources += [ "av1_decoder_unittest.cc" ] sources += [ "av1_decoder_unittest.cc" ]
deps += [ "//third_party/ffmpeg" ] deps += [
"//build:chromeos_buildflags",
"//third_party/ffmpeg",
]
} }
if (is_win && enable_library_cdms) { if (is_win && enable_library_cdms) {
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "build/chromeos_buildflags.h"
#include "media/base/limits.h" #include "media/base/limits.h"
#include "media/gpu/av1_picture.h" #include "media/gpu/av1_picture.h"
#include "third_party/libgav1/src/src/decoder_state.h" #include "third_party/libgav1/src/src/decoder_state.h"
...@@ -219,12 +220,6 @@ AcceleratedVideoDecoder::DecodeResult AV1Decoder::DecodeInternal() { ...@@ -219,12 +220,6 @@ AcceleratedVideoDecoder::DecodeResult AV1Decoder::DecodeInternal() {
return kDecodeError; return kDecodeError;
} }
const gfx::Size new_frame_size(
base::strict_cast<int>(current_sequence_header_->max_frame_width),
base::strict_cast<int>(current_sequence_header_->max_frame_height));
gfx::Rect new_visible_rect(
base::strict_cast<int>(current_frame_header_->render_width),
base::strict_cast<int>(current_frame_header_->render_height));
const VideoCodecProfile new_profile = const VideoCodecProfile new_profile =
AV1ProfileToVideoCodecProfile(current_sequence_header_->profile); AV1ProfileToVideoCodecProfile(current_sequence_header_->profile);
const uint8_t new_bit_depth = base::checked_cast<uint8_t>( const uint8_t new_bit_depth = base::checked_cast<uint8_t>(
...@@ -235,7 +230,21 @@ AcceleratedVideoDecoder::DecodeResult AV1Decoder::DecodeInternal() { ...@@ -235,7 +230,21 @@ AcceleratedVideoDecoder::DecodeResult AV1Decoder::DecodeInternal() {
<< ", profile=" << GetProfileName(new_profile); << ", profile=" << GetProfileName(new_profile);
return kDecodeError; return kDecodeError;
} }
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
if (current_sequence_header_->film_grain_params_present) {
// TODO(b/176927551): Decode film grain streams on ChromeOS once the
// issue is fixed.
DVLOG(1) << "Film grain streams are not supported";
return kDecodeError;
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
const gfx::Size new_frame_size(
base::strict_cast<int>(current_sequence_header_->max_frame_width),
base::strict_cast<int>(current_sequence_header_->max_frame_height));
gfx::Rect new_visible_rect(
base::strict_cast<int>(current_frame_header_->render_width),
base::strict_cast<int>(current_frame_header_->render_height));
DCHECK(!new_frame_size.IsEmpty()); DCHECK(!new_frame_size.IsEmpty());
if (!gfx::Rect(new_frame_size).Contains(new_visible_rect)) { if (!gfx::Rect(new_frame_size).Contains(new_visible_rect)) {
DVLOG(1) << "Render size exceeds picture size. render size: " DVLOG(1) << "Render size exceeds picture size. render size: "
...@@ -338,6 +347,8 @@ AcceleratedVideoDecoder::DecodeResult AV1Decoder::DecodeInternal() { ...@@ -338,6 +347,8 @@ AcceleratedVideoDecoder::DecodeResult AV1Decoder::DecodeInternal() {
return kDecodeError; return kDecodeError;
} }
DCHECK(current_sequence_header_->film_grain_params_present ||
!frame_header.film_grain_params.apply_grain);
auto pic = accelerator_->CreateAV1Picture( auto pic = accelerator_->CreateAV1Picture(
frame_header.film_grain_params.apply_grain); frame_header.film_grain_params.apply_grain);
if (!pic) { if (!pic) {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/numerics/safe_conversions.h" #include "base/numerics/safe_conversions.h"
#include "build/chromeos_buildflags.h"
#include "media/base/decoder_buffer.h" #include "media/base/decoder_buffer.h"
#include "media/base/test_data_util.h" #include "media/base/test_data_util.h"
#include "media/ffmpeg/ffmpeg_common.h" #include "media/ffmpeg/ffmpeg_common.h"
...@@ -416,6 +417,54 @@ TEST_F(AV1DecoderTest, DenyDecodeNonYUV420) { ...@@ -416,6 +417,54 @@ TEST_F(AV1DecoderTest, DenyDecodeNonYUV420) {
// until Reset(). // until Reset().
EXPECT_EQ(Decode(buffers[0]), expected); EXPECT_EQ(Decode(buffers[0]), expected);
} }
TEST_F(AV1DecoderTest, DecodeFilmGrain) {
// Note: This video also contains show_existing_frame.
const std::string kFilmGrainStream("av1-film_grain.ivf");
std::vector<scoped_refptr<DecoderBuffer>> buffers = ReadIVF(kFilmGrainStream);
ASSERT_FALSE(buffers.empty());
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
std::vector<DecodeResult> expected = {DecodeResult::kDecodeError};
EXPECT_EQ(Decode(buffers[0]), expected);
// Once AV1Decoder gets into an error state, Decode() returns kDecodeError
// until Reset().
EXPECT_EQ(Decode(buffers[0]), expected);
#else
constexpr size_t kDecodedFrames = 11;
constexpr size_t kOutputFrames = 10;
constexpr gfx::Size kFrameSize(352, 288);
constexpr gfx::Size kRenderSize(352, 288);
constexpr auto kProfile = libgav1::BitstreamProfile::kProfile0;
std::vector<DecodeResult> expected = {DecodeResult::kConfigChange};
std::vector<DecodeResult> results;
// TODO(hiroh): test that CreateAV1Picture is called with the right parameter
// which depends on the frame
EXPECT_CALL(*mock_accelerator_, CreateAV1Picture(_))
.Times(kDecodedFrames)
.WillRepeatedly(Return(base::MakeRefCounted<FakeAV1Picture>()));
EXPECT_CALL(
*mock_accelerator_,
SubmitDecode(
MatchesFrameSizeAndRenderSize(kFrameSize, kRenderSize),
MatchesYUV420SequenceHeader(kProfile, /*bitdepth=*/8, kFrameSize,
/*film_grain_params_present=*/true),
_, NonEmptyTileBuffers(), _))
.Times(kDecodedFrames)
.WillRepeatedly(Return(true));
EXPECT_CALL(*mock_accelerator_, OutputPicture(_))
.Times(kOutputFrames)
.WillRepeatedly(Return(true));
for (auto buffer : buffers) {
for (DecodeResult r : Decode(buffer))
results.push_back(r);
expected.push_back(DecodeResult::kRanOutOfStreamData);
}
EXPECT_EQ(results, expected);
#endif
}
// TODO(hiroh): Add more tests, Reset() flow, mid-stream configuration change, // TODO(hiroh): Add more tests, Reset() flow, mid-stream configuration change,
// and reference frame tracking. // and reference frame tracking.
} // namespace } // namespace
......
...@@ -190,6 +190,11 @@ https://people.xiph.org/~tterribe/av1/samples-all/ ...@@ -190,6 +190,11 @@ https://people.xiph.org/~tterribe/av1/samples-all/
The first frame of blackwhite\_yuv444p.mp4 coded in AV1 by the following command. The first frame of blackwhite\_yuv444p.mp4 coded in AV1 by the following command.
`ffmpeg -i blackwhite_yuv444p.mp4 -strict -2 -vcodec av1 -vframes 1 blackwhite_yuv444p-frame.av1.ivf` `ffmpeg -i blackwhite_yuv444p.mp4 -strict -2 -vcodec av1 -vframes 1 blackwhite_yuv444p-frame.av1.ivf`
#### av1-film\_grain.ivf
AV1 data where film grain feature is used.
This is the same as av1-1-b8-23-film\_grain-50.ivf in
[libaom test vectors]:https://aomedia.googlesource.com/aom/+/master/test/test_vectors.cc
### Alpha Channel ### Alpha Channel
#### bear-vp8a.webm #### bear-vp8a.webm
......
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