Add QP for libvpx VP8 decoder.

BUG=webrtc:6541, webrtc:7065
TBR=hta@webrtc.org

Review-Url: https://codereview.webrtc.org/2656603002
Cr-Commit-Position: refs/heads/master@{#16722}
This commit is contained in:
sakal
2017-02-20 06:43:58 -08:00
committed by Commit bot
parent 4228784609
commit 5fec128de9
5 changed files with 50 additions and 24 deletions

View File

@ -148,7 +148,7 @@ class Vp8TestDecodedImageCallback : public DecodedImageCallback {
void Decoded(VideoFrame& decoded_image,
rtc::Optional<int32_t> decode_time_ms,
rtc::Optional<uint8_t> qp) override {
RTC_NOTREACHED();
Decoded(decoded_image);
}
int DecodedFrames() { return decoded_frames_; }

View File

@ -76,6 +76,7 @@ Vp8UnitTestEncodeCompleteCallback::OnEncodedImage(
encoded_frame_->_timeStamp = encoded_frame._timeStamp;
encoded_frame_->_frameType = encoded_frame._frameType;
encoded_frame_->_completeFrame = encoded_frame._completeFrame;
encoded_frame_->qp_ = encoded_frame.qp_;
encode_complete_ = true;
return Result(Result::OK, 0);
}
@ -90,22 +91,25 @@ bool Vp8UnitTestEncodeCompleteCallback::EncodeComplete() {
class Vp8UnitTestDecodeCompleteCallback : public webrtc::DecodedImageCallback {
public:
explicit Vp8UnitTestDecodeCompleteCallback(rtc::Optional<VideoFrame>* frame)
: decoded_frame_(frame), decode_complete(false) {}
int32_t Decoded(VideoFrame& frame) override;
explicit Vp8UnitTestDecodeCompleteCallback(rtc::Optional<VideoFrame>* frame,
rtc::Optional<uint8_t>* qp)
: decoded_frame_(frame), decoded_qp_(qp), decode_complete(false) {}
int32_t Decoded(VideoFrame& frame) override {
RTC_NOTREACHED();
return -1;
}
int32_t Decoded(VideoFrame& frame, int64_t decode_time_ms) override {
RTC_NOTREACHED();
return -1;
}
void Decoded(VideoFrame& frame,
rtc::Optional<int32_t> decode_time_ms,
rtc::Optional<uint8_t> qp) override {
RTC_NOTREACHED();
}
rtc::Optional<uint8_t> qp) override;
bool DecodeComplete();
private:
rtc::Optional<VideoFrame>* decoded_frame_;
rtc::Optional<uint8_t>* decoded_qp_;
bool decode_complete;
};
@ -117,10 +121,13 @@ bool Vp8UnitTestDecodeCompleteCallback::DecodeComplete() {
return false;
}
int Vp8UnitTestDecodeCompleteCallback::Decoded(VideoFrame& image) {
*decoded_frame_ = rtc::Optional<VideoFrame>(image);
void Vp8UnitTestDecodeCompleteCallback::Decoded(
VideoFrame& frame,
rtc::Optional<int32_t> decode_time_ms,
rtc::Optional<uint8_t> qp) {
*decoded_frame_ = rtc::Optional<VideoFrame>(frame);
*decoded_qp_ = qp;
decode_complete = true;
return 0;
}
class TestVp8Impl : public ::testing::Test {
@ -132,7 +139,7 @@ class TestVp8Impl : public ::testing::Test {
encode_complete_callback_.reset(
new Vp8UnitTestEncodeCompleteCallback(&encoded_frame_, 0, NULL));
decode_complete_callback_.reset(
new Vp8UnitTestDecodeCompleteCallback(&decoded_frame_));
new Vp8UnitTestDecodeCompleteCallback(&decoded_frame_, &decoded_qp_));
encoder_->RegisterEncodeCompleteCallback(encode_complete_callback_.get());
decoder_->RegisterDecodeCompleteCallback(decode_complete_callback_.get());
// Using a QCIF image (aligned stride (u,v planes) > width).
@ -210,6 +217,7 @@ class TestVp8Impl : public ::testing::Test {
std::unique_ptr<VideoDecoder> decoder_;
EncodedImage encoded_frame_;
rtc::Optional<VideoFrame> decoded_frame_;
rtc::Optional<uint8_t> decoded_qp_;
VideoCodec codec_inst_;
TemporalLayersFactory tl_factory_;
};
@ -244,6 +252,21 @@ TEST_F(TestVp8Impl, EncoderParameterTest) {
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->InitDecode(&codec_inst_, 1));
}
TEST_F(TestVp8Impl, DecodedQpEqualsEncodedQp) {
SetUpEncodeDecode();
encoder_->Encode(*input_frame_, nullptr, nullptr);
EXPECT_GT(WaitForEncodedFrame(), 0u);
// First frame should be a key frame.
encoded_frame_._frameType = kVideoFrameKey;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
decoder_->Decode(encoded_frame_, false, nullptr));
EXPECT_GT(WaitForDecodedFrame(), 0u);
ASSERT_TRUE(decoded_frame_);
EXPECT_GT(I420PSNR(input_frame_.get(), &*decoded_frame_), 36);
ASSERT_TRUE(decoded_qp_);
EXPECT_EQ(encoded_frame_.qp_, *decoded_qp_);
}
#if defined(WEBRTC_ANDROID)
#define MAYBE_AlignedStrideEncodeDecode DISABLED_AlignedStrideEncodeDecode
#else

View File

@ -1145,7 +1145,11 @@ int VP8DecoderImpl::Decode(const EncodedImage& input_image,
}
img = vpx_codec_get_frame(decoder_, &iter);
ret = ReturnFrame(img, input_image._timeStamp, input_image.ntp_time_ms_);
int qp;
vpx_codec_err_t vpx_ret =
vpx_codec_control(decoder_, VPXD_GET_LAST_QUANTIZER, &qp);
RTC_DCHECK_EQ(vpx_ret, VPX_CODEC_OK);
ret = ReturnFrame(img, input_image._timeStamp, input_image.ntp_time_ms_, qp);
if (ret != 0) {
// Reset to avoid requesting key frames too often.
if (ret < 0 && propagation_cnt_ > 0)
@ -1205,7 +1209,8 @@ int VP8DecoderImpl::Decode(const EncodedImage& input_image,
int VP8DecoderImpl::ReturnFrame(const vpx_image_t* img,
uint32_t timestamp,
int64_t ntp_time_ms) {
int64_t ntp_time_ms,
int qp) {
if (img == NULL) {
// Decoder OK and NULL image => No show frame
return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
@ -1232,9 +1237,8 @@ int VP8DecoderImpl::ReturnFrame(const vpx_image_t* img,
VideoFrame decoded_image(buffer, timestamp, 0, kVideoRotation_0);
decoded_image.set_ntp_time_ms(ntp_time_ms);
int ret = decode_complete_callback_->Decoded(decoded_image);
if (ret != 0)
return ret;
decode_complete_callback_->Decoded(decoded_image, rtc::Optional<int32_t>(),
rtc::Optional<uint8_t>(qp));
// Remember image format for later
image_format_ = img->fmt;

View File

@ -149,7 +149,8 @@ class VP8DecoderImpl : public VP8Decoder {
int ReturnFrame(const vpx_image_t* img,
uint32_t timeStamp,
int64_t ntp_time_ms);
int64_t ntp_time_ms,
int qp);
I420BufferPool buffer_pool_;
DecodedImageCallback* decode_complete_callback_;