Fix a bug that break the vp8 fragment decoder.
(issue #882).
Change-Id: I2ca7f96d390c4eaec0473c50cb01b903d0bd3ee6
diff --git a/test/codec_factory.h b/test/codec_factory.h
index 7f9398c..3a0e3db 100644
--- a/test/codec_factory.h
+++ b/test/codec_factory.h
@@ -35,6 +35,11 @@
virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
unsigned long deadline) const = 0;
+ virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
+ const vpx_codec_flags_t flags,
+ unsigned long deadline) // NOLINT(runtime/int)
+ const = 0;
+
virtual Encoder* CreateEncoder(vpx_codec_enc_cfg_t cfg,
unsigned long deadline,
const unsigned long init_flags,
@@ -72,6 +77,10 @@
VP8Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
: Decoder(cfg, deadline) {}
+ VP8Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag,
+ unsigned long deadline) // NOLINT
+ : Decoder(cfg, flag, deadline) {}
+
protected:
virtual vpx_codec_iface_t* CodecInterface() const {
#if CONFIG_VP8_DECODER
@@ -104,8 +113,14 @@
virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
unsigned long deadline) const {
+ return CreateDecoder(cfg, 0, deadline);
+ }
+
+ virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
+ const vpx_codec_flags_t flags,
+ unsigned long deadline) const { // NOLINT
#if CONFIG_VP8_DECODER
- return new VP8Decoder(cfg, deadline);
+ return new VP8Decoder(cfg, flags, deadline);
#else
return NULL;
#endif
@@ -154,6 +169,10 @@
VP9Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
: Decoder(cfg, deadline) {}
+ VP9Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag,
+ unsigned long deadline) // NOLINT
+ : Decoder(cfg, flag, deadline) {}
+
protected:
virtual vpx_codec_iface_t* CodecInterface() const {
#if CONFIG_VP9_DECODER
@@ -186,8 +205,14 @@
virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
unsigned long deadline) const {
+ return CreateDecoder(cfg, 0, deadline);
+ }
+
+ virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
+ const vpx_codec_flags_t flags,
+ unsigned long deadline) const { // NOLINT
#if CONFIG_VP9_DECODER
- return new VP9Decoder(cfg, deadline);
+ return new VP9Decoder(cfg, flags, deadline);
#else
return NULL;
#endif
diff --git a/test/decode_test_driver.cc b/test/decode_test_driver.cc
index 0ef4f7b..852d90e 100644
--- a/test/decode_test_driver.cc
+++ b/test/decode_test_driver.cc
@@ -110,4 +110,12 @@
RunLoop(video, dec_cfg);
}
+void DecoderTest::set_cfg(const vpx_codec_dec_cfg_t &dec_cfg) {
+ memcpy(&cfg_, &dec_cfg, sizeof(cfg_));
+}
+
+void DecoderTest::set_flags(const vpx_codec_flags_t flags) {
+ flags_ = flags;
+}
+
} // namespace libvpx_test
diff --git a/test/decode_test_driver.h b/test/decode_test_driver.h
index 72a279f..f566c53 100644
--- a/test/decode_test_driver.h
+++ b/test/decode_test_driver.h
@@ -41,7 +41,13 @@
class Decoder {
public:
Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
- : cfg_(cfg), deadline_(deadline), init_done_(false) {
+ : cfg_(cfg), flags_(0), deadline_(deadline), init_done_(false) {
+ memset(&decoder_, 0, sizeof(decoder_));
+ }
+
+ Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag,
+ unsigned long deadline) // NOLINT
+ : cfg_(cfg), flags_(flag), deadline_(deadline), init_done_(false) {
memset(&decoder_, 0, sizeof(decoder_));
}
@@ -112,7 +118,7 @@
if (!init_done_) {
const vpx_codec_err_t res = vpx_codec_dec_init(&decoder_,
CodecInterface(),
- &cfg_, 0);
+ &cfg_, flags_);
ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError();
init_done_ = true;
}
@@ -120,6 +126,7 @@
vpx_codec_ctx_t decoder_;
vpx_codec_dec_cfg_t cfg_;
+ vpx_codec_flags_t flags_;
unsigned int deadline_;
bool init_done_;
};
@@ -132,6 +139,9 @@
virtual void RunLoop(CompressedVideoSource *video,
const vpx_codec_dec_cfg_t &dec_cfg);
+ virtual void set_cfg(const vpx_codec_dec_cfg_t &dec_cfg);
+ virtual void set_flags(const vpx_codec_flags_t flags);
+
// Hook to be called before decompressing every frame.
virtual void PreDecodeFrameHook(const CompressedVideoSource& /*video*/,
Decoder* /*decoder*/) {}
@@ -154,11 +164,16 @@
const vpx_codec_err_t res_peek);
protected:
- explicit DecoderTest(const CodecFactory *codec) : codec_(codec) {}
+ explicit DecoderTest(const CodecFactory *codec)
+ : codec_(codec),
+ cfg_(),
+ flags_(0) {}
virtual ~DecoderTest() {}
const CodecFactory *codec_;
+ vpx_codec_dec_cfg_t cfg_;
+ vpx_codec_flags_t flags_;
};
} // namespace libvpx_test
diff --git a/test/encode_test_driver.cc b/test/encode_test_driver.cc
index 5b6757c..b49e8cb 100644
--- a/test/encode_test_driver.cc
+++ b/test/encode_test_driver.cc
@@ -140,6 +140,8 @@
}
void EncoderTest::RunLoop(VideoSource *video) {
+ vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t();
+
stats_.Reset();
ASSERT_TRUE(passes_ == 1 || passes_ == 2);
@@ -157,7 +159,13 @@
Encoder* const encoder = codec_->CreateEncoder(cfg_, deadline_, init_flags_,
&stats_);
ASSERT_TRUE(encoder != NULL);
- Decoder* const decoder = codec_->CreateDecoder(dec_cfg_, 0);
+
+ unsigned long dec_init_flags = 0; // NOLINT
+ // Use fragment decoder if encoder outputs partitions.
+ // NOTE: fragment decoder and partition encoder are only supported by VP8.
+ if (init_flags_ & VPX_CODEC_USE_OUTPUT_PARTITION)
+ dec_init_flags |= VPX_CODEC_USE_INPUT_FRAGMENTS;
+ Decoder* const decoder = codec_->CreateDecoder(dec_cfg, dec_init_flags, 0);
bool again;
for (again = true, video->Begin(); again; video->Next()) {
again = (video->img() != NULL);
@@ -199,6 +207,13 @@
}
}
+ // Flush the decoder when there are no more fragments.
+ if ((init_flags_ & VPX_CODEC_USE_OUTPUT_PARTITION) && has_dxdata) {
+ const vpx_codec_err_t res_dec = decoder->DecodeFrame(NULL, 0);
+ if (!HandleDecodeResult(res_dec, *video, decoder))
+ break;
+ }
+
if (has_dxdata && has_cxdata) {
const vpx_image_t *img_enc = encoder->GetPreviewFrame();
DxDataIterator dec_iter = decoder->GetDxData();
diff --git a/test/encode_test_driver.h b/test/encode_test_driver.h
index 3bc7847..770ac7e 100644
--- a/test/encode_test_driver.h
+++ b/test/encode_test_driver.h
@@ -185,6 +185,11 @@
// Map the TestMode enum to the deadline_ and passes_ variables.
void SetMode(TestMode mode);
+ // Set encoder flag.
+ void set_init_flags(unsigned long flag) { // NOLINT(runtime/int)
+ init_flags_ = flag;
+ }
+
// Main loop
virtual void RunLoop(VideoSource *video);
diff --git a/test/test.mk b/test/test.mk
index f5c9c37..bd65759 100644
--- a/test/test.mk
+++ b/test/test.mk
@@ -95,6 +95,7 @@
# These tests require both the encoder and decoder to be built.
ifeq ($(CONFIG_VP8_ENCODER)$(CONFIG_VP8_DECODER),yesyes)
LIBVPX_TEST_SRCS-yes += vp8_boolcoder_test.cc
+LIBVPX_TEST_SRCS-yes += vp8_fragments_test.cc
endif
LIBVPX_TEST_SRCS-$(CONFIG_POSTPROC) += pp_filter_test.cc
diff --git a/test/vp8_fragments_test.cc b/test/vp8_fragments_test.cc
new file mode 100644
index 0000000..cb0d1a1
--- /dev/null
+++ b/test/vp8_fragments_test.cc
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/video_source.h"
+
+namespace {
+
+class VP8FramgmentsTest
+ : public ::libvpx_test::EncoderTest,
+ public ::testing::Test {
+ protected:
+ VP8FramgmentsTest() : EncoderTest(&::libvpx_test::kVP8) {}
+ virtual ~VP8FramgmentsTest() {}
+
+ virtual void SetUp() {
+ const unsigned long init_flags = // NOLINT(runtime/int)
+ VPX_CODEC_USE_OUTPUT_PARTITION;
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ set_init_flags(init_flags);
+ }
+};
+
+TEST_F(VP8FramgmentsTest, TestFragmentsEncodeDecode) {
+ ::libvpx_test::RandomVideoSource video;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+} // namespace
diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c
index 5aa274d..352ed7b 100644
--- a/vp8/vp8_dx_iface.c
+++ b/vp8/vp8_dx_iface.c
@@ -60,7 +60,6 @@
vpx_decrypt_cb decrypt_cb;
void *decrypt_state;
vpx_image_t img;
- int flushed;
int img_setup;
struct frame_buffers yv12_frame_buffers;
void *user_priv;
@@ -89,7 +88,6 @@
priv->si.sz = sizeof(priv->si);
priv->decrypt_cb = NULL;
priv->decrypt_state = NULL;
- priv->flushed = 0;
if (ctx->config.dec)
{
@@ -307,6 +305,11 @@
return 0;
}
+ if (!ctx->fragments.enabled && (data == NULL && data_sz == 0))
+ {
+ return 0;
+ }
+
if (!ctx->fragments.enabled)
{
ctx->fragments.ptrs[0] = data;
@@ -327,14 +330,11 @@
unsigned int resolution_change = 0;
unsigned int w, h;
- if (data == NULL && data_sz == 0) {
- ctx->flushed = 1;
- return VPX_CODEC_OK;
+ if (!ctx->fragments.enabled && (data == NULL && data_sz == 0))
+ {
+ return 0;
}
- /* Reset flushed when receiving a valid frame */
- ctx->flushed = 0;
-
/* Update the input fragment data */
if(update_fragments(ctx, data, data_sz, &res) <= 0)
return res;