Commit 9353607a authored by hkuang's avatar hkuang

Fix a bug that break the vp8 fragment decoder.

(issue #882).

Change-Id: I2ca7f96d390c4eaec0473c50cb01b903d0bd3ee6
parent 089086bc
...@@ -35,6 +35,11 @@ class CodecFactory { ...@@ -35,6 +35,11 @@ class CodecFactory {
virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg, virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
unsigned long deadline) const = 0; 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, virtual Encoder* CreateEncoder(vpx_codec_enc_cfg_t cfg,
unsigned long deadline, unsigned long deadline,
const unsigned long init_flags, const unsigned long init_flags,
...@@ -72,6 +77,10 @@ class VP8Decoder : public Decoder { ...@@ -72,6 +77,10 @@ class VP8Decoder : public Decoder {
VP8Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline) VP8Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
: Decoder(cfg, 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: protected:
virtual vpx_codec_iface_t* CodecInterface() const { virtual vpx_codec_iface_t* CodecInterface() const {
#if CONFIG_VP8_DECODER #if CONFIG_VP8_DECODER
...@@ -104,8 +113,14 @@ class VP8CodecFactory : public CodecFactory { ...@@ -104,8 +113,14 @@ class VP8CodecFactory : public CodecFactory {
virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg, virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
unsigned long deadline) const { 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 #if CONFIG_VP8_DECODER
return new VP8Decoder(cfg, deadline); return new VP8Decoder(cfg, flags, deadline);
#else #else
return NULL; return NULL;
#endif #endif
...@@ -154,6 +169,10 @@ class VP9Decoder : public Decoder { ...@@ -154,6 +169,10 @@ class VP9Decoder : public Decoder {
VP9Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline) VP9Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
: Decoder(cfg, 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: protected:
virtual vpx_codec_iface_t* CodecInterface() const { virtual vpx_codec_iface_t* CodecInterface() const {
#if CONFIG_VP9_DECODER #if CONFIG_VP9_DECODER
...@@ -186,8 +205,14 @@ class VP9CodecFactory : public CodecFactory { ...@@ -186,8 +205,14 @@ class VP9CodecFactory : public CodecFactory {
virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg, virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
unsigned long deadline) const { 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 #if CONFIG_VP9_DECODER
return new VP9Decoder(cfg, deadline); return new VP9Decoder(cfg, flags, deadline);
#else #else
return NULL; return NULL;
#endif #endif
......
...@@ -110,4 +110,12 @@ void DecoderTest::RunLoop(CompressedVideoSource *video) { ...@@ -110,4 +110,12 @@ void DecoderTest::RunLoop(CompressedVideoSource *video) {
RunLoop(video, dec_cfg); 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 } // namespace libvpx_test
...@@ -41,7 +41,13 @@ class DxDataIterator { ...@@ -41,7 +41,13 @@ class DxDataIterator {
class Decoder { class Decoder {
public: public:
Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline) 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_)); memset(&decoder_, 0, sizeof(decoder_));
} }
...@@ -112,7 +118,7 @@ class Decoder { ...@@ -112,7 +118,7 @@ class Decoder {
if (!init_done_) { if (!init_done_) {
const vpx_codec_err_t res = vpx_codec_dec_init(&decoder_, const vpx_codec_err_t res = vpx_codec_dec_init(&decoder_,
CodecInterface(), CodecInterface(),
&cfg_, 0); &cfg_, flags_);
ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError(); ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError();
init_done_ = true; init_done_ = true;
} }
...@@ -120,6 +126,7 @@ class Decoder { ...@@ -120,6 +126,7 @@ class Decoder {
vpx_codec_ctx_t decoder_; vpx_codec_ctx_t decoder_;
vpx_codec_dec_cfg_t cfg_; vpx_codec_dec_cfg_t cfg_;
vpx_codec_flags_t flags_;
unsigned int deadline_; unsigned int deadline_;
bool init_done_; bool init_done_;
}; };
...@@ -132,6 +139,9 @@ class DecoderTest { ...@@ -132,6 +139,9 @@ class DecoderTest {
virtual void RunLoop(CompressedVideoSource *video, virtual void RunLoop(CompressedVideoSource *video,
const vpx_codec_dec_cfg_t &dec_cfg); 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. // Hook to be called before decompressing every frame.
virtual void PreDecodeFrameHook(const CompressedVideoSource& /*video*/, virtual void PreDecodeFrameHook(const CompressedVideoSource& /*video*/,
Decoder* /*decoder*/) {} Decoder* /*decoder*/) {}
...@@ -154,11 +164,16 @@ class DecoderTest { ...@@ -154,11 +164,16 @@ class DecoderTest {
const vpx_codec_err_t res_peek); const vpx_codec_err_t res_peek);
protected: protected:
explicit DecoderTest(const CodecFactory *codec) : codec_(codec) {} explicit DecoderTest(const CodecFactory *codec)
: codec_(codec),
cfg_(),
flags_(0) {}
virtual ~DecoderTest() {} virtual ~DecoderTest() {}
const CodecFactory *codec_; const CodecFactory *codec_;
vpx_codec_dec_cfg_t cfg_;
vpx_codec_flags_t flags_;
}; };
} // namespace libvpx_test } // namespace libvpx_test
......
...@@ -140,6 +140,8 @@ void EncoderTest::MismatchHook(const vpx_image_t* /*img1*/, ...@@ -140,6 +140,8 @@ void EncoderTest::MismatchHook(const vpx_image_t* /*img1*/,
} }
void EncoderTest::RunLoop(VideoSource *video) { void EncoderTest::RunLoop(VideoSource *video) {
vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t();
stats_.Reset(); stats_.Reset();
ASSERT_TRUE(passes_ == 1 || passes_ == 2); ASSERT_TRUE(passes_ == 1 || passes_ == 2);
...@@ -157,7 +159,13 @@ void EncoderTest::RunLoop(VideoSource *video) { ...@@ -157,7 +159,13 @@ void EncoderTest::RunLoop(VideoSource *video) {
Encoder* const encoder = codec_->CreateEncoder(cfg_, deadline_, init_flags_, Encoder* const encoder = codec_->CreateEncoder(cfg_, deadline_, init_flags_,
&stats_); &stats_);
ASSERT_TRUE(encoder != NULL); 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; bool again;
for (again = true, video->Begin(); again; video->Next()) { for (again = true, video->Begin(); again; video->Next()) {
again = (video->img() != NULL); again = (video->img() != NULL);
...@@ -199,6 +207,13 @@ void EncoderTest::RunLoop(VideoSource *video) { ...@@ -199,6 +207,13 @@ void EncoderTest::RunLoop(VideoSource *video) {
} }
} }
// 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) { if (has_dxdata && has_cxdata) {
const vpx_image_t *img_enc = encoder->GetPreviewFrame(); const vpx_image_t *img_enc = encoder->GetPreviewFrame();
DxDataIterator dec_iter = decoder->GetDxData(); DxDataIterator dec_iter = decoder->GetDxData();
......
...@@ -185,6 +185,11 @@ class EncoderTest { ...@@ -185,6 +185,11 @@ class EncoderTest {
// Map the TestMode enum to the deadline_ and passes_ variables. // Map the TestMode enum to the deadline_ and passes_ variables.
void SetMode(TestMode mode); void SetMode(TestMode mode);
// Set encoder flag.
void set_init_flags(unsigned long flag) { // NOLINT(runtime/int)
init_flags_ = flag;
}
// Main loop // Main loop
virtual void RunLoop(VideoSource *video); virtual void RunLoop(VideoSource *video);
......
...@@ -95,6 +95,7 @@ ifneq ($(CONFIG_VP8_ENCODER)$(CONFIG_VP8_DECODER),) ...@@ -95,6 +95,7 @@ ifneq ($(CONFIG_VP8_ENCODER)$(CONFIG_VP8_DECODER),)
# These tests require both the encoder and decoder to be built. # These tests require both the encoder and decoder to be built.
ifeq ($(CONFIG_VP8_ENCODER)$(CONFIG_VP8_DECODER),yesyes) ifeq ($(CONFIG_VP8_ENCODER)$(CONFIG_VP8_DECODER),yesyes)
LIBVPX_TEST_SRCS-yes += vp8_boolcoder_test.cc LIBVPX_TEST_SRCS-yes += vp8_boolcoder_test.cc
LIBVPX_TEST_SRCS-yes += vp8_fragments_test.cc
endif endif
LIBVPX_TEST_SRCS-$(CONFIG_POSTPROC) += pp_filter_test.cc LIBVPX_TEST_SRCS-$(CONFIG_POSTPROC) += pp_filter_test.cc
......
/*
* 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
...@@ -60,7 +60,6 @@ struct vpx_codec_alg_priv ...@@ -60,7 +60,6 @@ struct vpx_codec_alg_priv
vpx_decrypt_cb decrypt_cb; vpx_decrypt_cb decrypt_cb;
void *decrypt_state; void *decrypt_state;
vpx_image_t img; vpx_image_t img;
int flushed;
int img_setup; int img_setup;
struct frame_buffers yv12_frame_buffers; struct frame_buffers yv12_frame_buffers;
void *user_priv; void *user_priv;
...@@ -89,7 +88,6 @@ static void vp8_init_ctx(vpx_codec_ctx_t *ctx) ...@@ -89,7 +88,6 @@ static void vp8_init_ctx(vpx_codec_ctx_t *ctx)
priv->si.sz = sizeof(priv->si); priv->si.sz = sizeof(priv->si);
priv->decrypt_cb = NULL; priv->decrypt_cb = NULL;
priv->decrypt_state = NULL; priv->decrypt_state = NULL;
priv->flushed = 0;
if (ctx->config.dec) if (ctx->config.dec)
{ {
...@@ -307,6 +305,11 @@ update_fragments(vpx_codec_alg_priv_t *ctx, ...@@ -307,6 +305,11 @@ update_fragments(vpx_codec_alg_priv_t *ctx,
return 0; return 0;
} }
if (!ctx->fragments.enabled && (data == NULL && data_sz == 0))
{
return 0;
}
if (!ctx->fragments.enabled) if (!ctx->fragments.enabled)
{ {
ctx->fragments.ptrs[0] = data; ctx->fragments.ptrs[0] = data;
...@@ -327,14 +330,11 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, ...@@ -327,14 +330,11 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx,
unsigned int resolution_change = 0; unsigned int resolution_change = 0;
unsigned int w, h; unsigned int w, h;
if (data == NULL && data_sz == 0) { if (!ctx->fragments.enabled && (data == NULL && data_sz == 0))
ctx->flushed = 1; {
return VPX_CODEC_OK; return 0;
} }
/* Reset flushed when receiving a valid frame */
ctx->flushed = 0;
/* Update the input fragment data */ /* Update the input fragment data */
if(update_fragments(ctx, data, data_sz, &res) <= 0) if(update_fragments(ctx, data, data_sz, &res) <= 0)
return res; return res;
......
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