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,
|
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 {
|
|||||||
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 {
|
|||||||
|
|
||||||
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 {
|
|||||||
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 {
|
|||||||
|
|
||||||
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) {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
|
|
||||||
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 {
|
|||||||
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 {
|
|||||||
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*/,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 {
|
|||||||
// 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),)
|
|||||||
# 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
|
||||||
|
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;
|
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user