Commit 1fc7d07f authored by Steve Cho's avatar Steve Cho Committed by Chromium LUCI CQ

video: fix vp9 uncompressed header parser issue, add unittest for

SetupPastIndependence

This CL fixes a bug reported about ref_frame_sign_bias issue in
Vp9UncompressedHeaderParser::SetupPastIndependence. Also, unittest
is added for SetupPastIndependence function.

There are two bugs:
 1. SetupPastIndependence() is not invoked in some cases.
 2. ref_frame_sign_bias is not reset in SetupPastIndependence().
Their triggering conditions are identical, that is
 !show_existing_frame && frame_type!=KEYFRAME && !intra_only
&& error_resilient_mode

According to VP9 Bitstream & Decoding Process Specification,
section 7.2 (page 64), ref_frame_sign_bias should be reset in
setup_past_independence.

Change-Id: I4928e8363406ae7ee0e3f7c59ea4926483c68bf8
Bug: b:176566296
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2629652
Commit-Queue: Steve Cho <stevecho@chromium.org>
Reviewed-by: default avatarKuang-che Wu <kcwu@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarHirokazu Honda <hiroh@chromium.org>
Reviewed-by: default avatarMiguel Casas <mcasas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#845245}
parent 0b9c0182
...@@ -300,6 +300,7 @@ source_set("unit_tests") { ...@@ -300,6 +300,7 @@ source_set("unit_tests") {
"video_renderer_algorithm_unittest.cc", "video_renderer_algorithm_unittest.cc",
"vp9_parser_unittest.cc", "vp9_parser_unittest.cc",
"vp9_raw_bits_reader_unittest.cc", "vp9_raw_bits_reader_unittest.cc",
"vp9_uncompressed_header_parser_unittest.cc",
] ]
deps = [ deps = [
......
...@@ -300,7 +300,7 @@ class MEDIA_EXPORT Vp9Parser { ...@@ -300,7 +300,7 @@ class MEDIA_EXPORT Vp9Parser {
// The parsing context that persists across frames. // The parsing context that persists across frames.
class Context { class Context {
public: public:
class Vp9FrameContextManager { class MEDIA_EXPORT Vp9FrameContextManager {
public: public:
Vp9FrameContextManager(); Vp9FrameContextManager();
~Vp9FrameContextManager(); ~Vp9FrameContextManager();
......
...@@ -622,6 +622,11 @@ Vp9UncompressedHeaderParser::Vp9UncompressedHeaderParser( ...@@ -622,6 +622,11 @@ Vp9UncompressedHeaderParser::Vp9UncompressedHeaderParser(
Vp9Parser::Context* context) Vp9Parser::Context* context)
: context_(context) {} : context_(context) {}
const Vp9FrameContext&
Vp9UncompressedHeaderParser::GetVp9DefaultFrameContextForTesting() const {
return kVp9DefaultFrameContext;
}
uint8_t Vp9UncompressedHeaderParser::ReadProfile() { uint8_t Vp9UncompressedHeaderParser::ReadProfile() {
uint8_t profile = 0; uint8_t profile = 0;
...@@ -765,6 +770,8 @@ Vp9InterpolationFilter Vp9UncompressedHeaderParser::ReadInterpolationFilter() { ...@@ -765,6 +770,8 @@ Vp9InterpolationFilter Vp9UncompressedHeaderParser::ReadInterpolationFilter() {
void Vp9UncompressedHeaderParser::SetupPastIndependence(Vp9FrameHeader* fhdr) { void Vp9UncompressedHeaderParser::SetupPastIndependence(Vp9FrameHeader* fhdr) {
memset(&context_->segmentation_, 0, sizeof(context_->segmentation_)); memset(&context_->segmentation_, 0, sizeof(context_->segmentation_));
memset(fhdr->ref_frame_sign_bias, 0, sizeof(fhdr->ref_frame_sign_bias));
ResetLoopfilter(); ResetLoopfilter();
fhdr->frame_context = kVp9DefaultFrameContext; fhdr->frame_context = kVp9DefaultFrameContext;
DCHECK(fhdr->frame_context.IsValid()); DCHECK(fhdr->frame_context.IsValid());
...@@ -1069,7 +1076,7 @@ bool Vp9UncompressedHeaderParser::Parse(const uint8_t* stream, ...@@ -1069,7 +1076,7 @@ bool Vp9UncompressedHeaderParser::Parse(const uint8_t* stream,
fhdr->frame_context_idx_to_save_probs = fhdr->frame_context_idx = fhdr->frame_context_idx_to_save_probs = fhdr->frame_context_idx =
reader_.ReadLiteral(kVp9NumFrameContextsLog2); reader_.ReadLiteral(kVp9NumFrameContextsLog2);
if (fhdr->IsIntra()) { if (fhdr->IsIntra() || fhdr->error_resilient_mode) {
SetupPastIndependence(fhdr); SetupPastIndependence(fhdr);
if (fhdr->IsKeyframe() || fhdr->error_resilient_mode || if (fhdr->IsKeyframe() || fhdr->error_resilient_mode ||
fhdr->reset_frame_context == 3) { fhdr->reset_frame_context == 3) {
......
...@@ -8,9 +8,11 @@ ...@@ -8,9 +8,11 @@
#include "media/filters/vp9_parser.h" #include "media/filters/vp9_parser.h"
#include "media/filters/vp9_raw_bits_reader.h" #include "media/filters/vp9_raw_bits_reader.h"
#include "media/base/media_export.h"
namespace media { namespace media {
class Vp9UncompressedHeaderParser { class MEDIA_EXPORT Vp9UncompressedHeaderParser {
public: public:
Vp9UncompressedHeaderParser(Vp9Parser::Context* context); Vp9UncompressedHeaderParser(Vp9Parser::Context* context);
...@@ -18,7 +20,11 @@ class Vp9UncompressedHeaderParser { ...@@ -18,7 +20,11 @@ class Vp9UncompressedHeaderParser {
// Returns true if no error. // Returns true if no error.
bool Parse(const uint8_t* stream, off_t frame_size, Vp9FrameHeader* fhdr); bool Parse(const uint8_t* stream, off_t frame_size, Vp9FrameHeader* fhdr);
const Vp9FrameContext& GetVp9DefaultFrameContextForTesting() const;
private: private:
friend class Vp9UncompressedHeaderParserTest;
uint8_t ReadProfile(); uint8_t ReadProfile();
bool VerifySyncCode(); bool VerifySyncCode();
bool ReadColorConfig(Vp9FrameHeader* fhdr); bool ReadColorConfig(Vp9FrameHeader* fhdr);
......
// Copyright 2021 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/filters/vp9_uncompressed_header_parser.h"
#include "media/filters/vp9_parser.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
class Vp9UncompressedHeaderParserTest : public testing::Test {
public:
void SetupPastIndependence(Vp9FrameHeader* fhdr) {
vp9_uncompressed_header_parser_.SetupPastIndependence(fhdr);
}
const Vp9FrameContext& GetVp9DefaultFrameContextForTesting() const {
return vp9_uncompressed_header_parser_
.GetVp9DefaultFrameContextForTesting();
}
Vp9UncompressedHeaderParserTest()
: vp9_uncompressed_header_parser_((&vp9_parser_context_)) {}
protected:
const Vp9LoopFilterParams& GetLoopFilter() const {
return vp9_parser_context_.loop_filter();
}
Vp9Parser::Context vp9_parser_context_;
Vp9UncompressedHeaderParser vp9_uncompressed_header_parser_;
};
TEST_F(Vp9UncompressedHeaderParserTest, SetupPastIndependence) {
Vp9FrameHeader frame_header = {};
SetupPastIndependence(&frame_header);
EXPECT_EQ(0, frame_header.ref_frame_sign_bias[VP9_FRAME_INTRA]);
EXPECT_EQ(0, frame_header.ref_frame_sign_bias[VP9_FRAME_LAST]);
EXPECT_EQ(0, frame_header.ref_frame_sign_bias[VP9_FRAME_GOLDEN]);
EXPECT_EQ(0, frame_header.ref_frame_sign_bias[VP9_FRAME_ALTREF]);
// Verify ResetLoopfilter() result
const Vp9LoopFilterParams& lf = GetLoopFilter();
EXPECT_TRUE(lf.delta_enabled);
EXPECT_TRUE(lf.delta_update);
EXPECT_EQ(1, lf.ref_deltas[VP9_FRAME_INTRA]);
EXPECT_EQ(0, lf.ref_deltas[VP9_FRAME_LAST]);
EXPECT_EQ(-1, lf.ref_deltas[VP9_FRAME_GOLDEN]);
EXPECT_EQ(-1, lf.ref_deltas[VP9_FRAME_ALTREF]);
EXPECT_EQ(0, lf.mode_deltas[0]);
EXPECT_EQ(0, lf.mode_deltas[1]);
EXPECT_TRUE(frame_header.frame_context.IsValid());
static_assert(std::is_pod<Vp9FrameContext>::value,
"Vp9FrameContext is not POD, rewrite the next EXPECT_TRUE");
EXPECT_TRUE(std::memcmp(&frame_header.frame_context,
&GetVp9DefaultFrameContextForTesting(),
sizeof(GetVp9DefaultFrameContextForTesting())) == 0);
}
} // namespace media
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