blob: a4cc5b0ded0d9124341702f17a7a1727b3b87da9 [file] [log] [blame]
/*
* Copyright (c) 2016 The WebRTC 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 "modules/video_coding/generic_decoder.h"
#include <vector>
#include "absl/types/optional.h"
#include "api/task_queue/default_task_queue_factory.h"
#include "common_video/test/utilities.h"
#include "modules/video_coding/timing.h"
#include "rtc_base/event.h"
#include "rtc_base/synchronization/mutex.h"
#include "system_wrappers/include/clock.h"
#include "test/fake_decoder.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
namespace video_coding {
class ReceiveCallback : public VCMReceiveCallback {
public:
int32_t FrameToRender(VideoFrame& videoFrame, // NOLINT
absl::optional<uint8_t> qp,
int32_t decode_time_ms,
VideoContentType content_type) override {
{
MutexLock lock(&lock_);
last_frame_ = videoFrame;
}
received_frame_event_.Set();
return 0;
}
absl::optional<VideoFrame> GetLastFrame() {
MutexLock lock(&lock_);
return last_frame_;
}
absl::optional<VideoFrame> WaitForFrame(int64_t wait_ms) {
if (received_frame_event_.Wait(wait_ms)) {
MutexLock lock(&lock_);
return last_frame_;
} else {
return absl::nullopt;
}
}
private:
Mutex lock_;
rtc::Event received_frame_event_;
absl::optional<VideoFrame> last_frame_ RTC_GUARDED_BY(lock_);
};
class GenericDecoderTest : public ::testing::Test {
protected:
GenericDecoderTest()
: clock_(0),
timing_(&clock_),
task_queue_factory_(CreateDefaultTaskQueueFactory()),
decoder_(task_queue_factory_.get()),
vcm_callback_(&timing_, &clock_),
generic_decoder_(&decoder_, /*isExternal=*/true) {}
void SetUp() override {
generic_decoder_.RegisterDecodeCompleteCallback(&vcm_callback_);
vcm_callback_.SetUserReceiveCallback(&user_callback_);
VideoCodec settings;
settings.codecType = kVideoCodecVP8;
settings.width = 10;
settings.height = 10;
generic_decoder_.InitDecode(&settings, /*numberOfCores=*/4);
}
SimulatedClock clock_;
VCMTiming timing_;
std::unique_ptr<TaskQueueFactory> task_queue_factory_;
webrtc::test::FakeDecoder decoder_;
VCMDecodedFrameCallback vcm_callback_;
VCMGenericDecoder generic_decoder_;
ReceiveCallback user_callback_;
};
TEST_F(GenericDecoderTest, PassesPacketInfos) {
RtpPacketInfos packet_infos = CreatePacketInfos(3);
VCMEncodedFrame encoded_frame;
encoded_frame.SetPacketInfos(packet_infos);
generic_decoder_.Decode(encoded_frame, clock_.CurrentTime());
absl::optional<VideoFrame> decoded_frame = user_callback_.WaitForFrame(10);
ASSERT_TRUE(decoded_frame.has_value());
EXPECT_EQ(decoded_frame->packet_infos().size(), 3U);
}
TEST_F(GenericDecoderTest, PassesPacketInfosForDelayedDecoders) {
RtpPacketInfos packet_infos = CreatePacketInfos(3);
decoder_.SetDelayedDecoding(100);
{
// Ensure the original frame is destroyed before the decoding is completed.
VCMEncodedFrame encoded_frame;
encoded_frame.SetPacketInfos(packet_infos);
generic_decoder_.Decode(encoded_frame, clock_.CurrentTime());
}
absl::optional<VideoFrame> decoded_frame = user_callback_.WaitForFrame(200);
ASSERT_TRUE(decoded_frame.has_value());
EXPECT_EQ(decoded_frame->packet_infos().size(), 3U);
}
TEST_F(GenericDecoderTest, MaxCompositionDelayNotSetByDefault) {
VCMEncodedFrame encoded_frame;
generic_decoder_.Decode(encoded_frame, clock_.CurrentTime());
absl::optional<VideoFrame> decoded_frame = user_callback_.WaitForFrame(10);
ASSERT_TRUE(decoded_frame.has_value());
EXPECT_FALSE(decoded_frame->max_composition_delay_in_frames());
}
TEST_F(GenericDecoderTest, MaxCompositionDelayActivatedByPlayoutDelay) {
VCMEncodedFrame encoded_frame;
// VideoReceiveStream2 would set MaxCompositionDelayInFrames if playout delay
// is specified as X,Y, where X=0, Y>0.
const VideoPlayoutDelay kPlayoutDelay = {0, 50};
constexpr int kMaxCompositionDelayInFrames = 3; // ~50 ms at 60 fps.
encoded_frame.SetPlayoutDelay(kPlayoutDelay);
timing_.SetMaxCompositionDelayInFrames(
absl::make_optional(kMaxCompositionDelayInFrames));
generic_decoder_.Decode(encoded_frame, clock_.CurrentTime());
absl::optional<VideoFrame> decoded_frame = user_callback_.WaitForFrame(10);
ASSERT_TRUE(decoded_frame.has_value());
EXPECT_EQ(kMaxCompositionDelayInFrames,
decoded_frame->max_composition_delay_in_frames());
}
} // namespace video_coding
} // namespace webrtc