Fix a bug that break the vp8 fragment decoder.
(issue #882). Change-Id: I2ca7f96d390c4eaec0473c50cb01b903d0bd3ee6
This commit is contained in:
parent
089086bc25
commit
9353607ac8
@ -35,6 +35,11 @@ class CodecFactory {
|
||||
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 @@ class VP8Decoder : public Decoder {
|
||||
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 @@ class VP8CodecFactory : public CodecFactory {
|
||||
|
||||
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 @@ class VP9Decoder : public Decoder {
|
||||
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 @@ class VP9CodecFactory : public CodecFactory {
|
||||
|
||||
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
|
||||
|
@ -110,4 +110,12 @@ void DecoderTest::RunLoop(CompressedVideoSource *video) {
|
||||
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
|
||||
|
@ -41,7 +41,13 @@ class DxDataIterator {
|
||||
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 @@ class Decoder {
|
||||
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 @@ class Decoder {
|
||||
|
||||
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 @@ class DecoderTest {
|
||||
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 @@ class DecoderTest {
|
||||
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
|
||||
|
@ -140,6 +140,8 @@ void EncoderTest::MismatchHook(const vpx_image_t* /*img1*/,
|
||||
}
|
||||
|
||||
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 @@ void EncoderTest::RunLoop(VideoSource *video) {
|
||||
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 @@ 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) {
|
||||
const vpx_image_t *img_enc = encoder->GetPreviewFrame();
|
||||
DxDataIterator dec_iter = decoder->GetDxData();
|
||||
|
@ -185,6 +185,11 @@ class EncoderTest {
|
||||
// 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);
|
||||
|
||||
|
@ -95,6 +95,7 @@ ifneq ($(CONFIG_VP8_ENCODER)$(CONFIG_VP8_DECODER),)
|
||||
# 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
|
||||
|
37
test/vp8_fragments_test.cc
Normal file
37
test/vp8_fragments_test.cc
Normal file
@ -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
|
@ -60,7 +60,6 @@ struct vpx_codec_alg_priv
|
||||
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 @@ static void vp8_init_ctx(vpx_codec_ctx_t *ctx)
|
||||
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 @@ update_fragments(vpx_codec_alg_priv_t *ctx,
|
||||
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 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx,
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user