blob: 9aa89bf2602c9796a688aa2e2f6eaafd5729d673 [file] [log] [blame]
Peter Boström7252a2b2015-05-18 19:42:03 +02001/*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/video_decoder.h"
12
13#include "testing/gtest/include/gtest/gtest.h"
14#include "webrtc/modules/video_coding/codecs/interface/video_error_codes.h"
15
16namespace webrtc {
17
18class VideoDecoderSoftwareFallbackWrapperTest : public ::testing::Test {
19 protected:
20 VideoDecoderSoftwareFallbackWrapperTest()
21 : fallback_wrapper_(kVideoCodecVP8, &fake_decoder_) {}
22
23 class CountingFakeDecoder : public VideoDecoder {
24 public:
25 int32_t InitDecode(const VideoCodec* codec_settings,
26 int32_t number_of_cores) override {
27 ++init_decode_count_;
28 return WEBRTC_VIDEO_CODEC_OK;
29 }
30
31 int32_t Decode(const EncodedImage& input_image,
32 bool missing_frames,
33 const RTPFragmentationHeader* fragmentation,
34 const CodecSpecificInfo* codec_specific_info,
35 int64_t render_time_ms) override {
36 ++decode_count_;
37 return decode_return_code_;
38 }
39
40 int32_t RegisterDecodeCompleteCallback(
41 DecodedImageCallback* callback) override {
42 decode_complete_callback_ = callback;
43 return WEBRTC_VIDEO_CODEC_OK;
44 }
45
46 int32_t Release() override {
47 ++release_count_;
48 return WEBRTC_VIDEO_CODEC_OK;
49 }
50
51 int32_t Reset() override {
52 ++reset_count_;
53 return WEBRTC_VIDEO_CODEC_OK;
54 }
55 int init_decode_count_ = 0;
56 int decode_count_ = 0;
57 int32_t decode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
58 DecodedImageCallback* decode_complete_callback_ = nullptr;
59 int release_count_ = 0;
60 int reset_count_ = 0;
61 };
62 CountingFakeDecoder fake_decoder_;
63 VideoDecoderSoftwareFallbackWrapper fallback_wrapper_;
64};
65
66TEST_F(VideoDecoderSoftwareFallbackWrapperTest, InitializesDecoder) {
67 VideoCodec codec = {};
68 fallback_wrapper_.InitDecode(&codec, 2);
69 EXPECT_EQ(1, fake_decoder_.init_decode_count_);
70}
71
72TEST_F(VideoDecoderSoftwareFallbackWrapperTest,
73 CanRecoverFromSoftwareFallback) {
74 VideoCodec codec = {};
75 fallback_wrapper_.InitDecode(&codec, 2);
76 // Unfortunately faking a VP8 frame is hard. Rely on no Decode -> using SW
77 // decoder.
78 fake_decoder_.decode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
79 EncodedImage encoded_image;
80 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1);
81 EXPECT_EQ(1, fake_decoder_.decode_count_);
82
83 // Fail -> fake_decoder shouldn't be used anymore.
84 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1);
85 EXPECT_EQ(1, fake_decoder_.decode_count_)
86 << "Decoder used even though fallback should be active.";
87
88 // Should be able to recover on a keyframe.
89 encoded_image._frameType = kKeyFrame;
90 fake_decoder_.decode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
91 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1);
92 EXPECT_EQ(2, fake_decoder_.decode_count_)
93 << "Wrapper did not try to decode a keyframe using registered decoder.";
94
95 encoded_image._frameType = kDeltaFrame;
96 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1);
97 EXPECT_EQ(3, fake_decoder_.decode_count_)
98 << "Decoder not used on future delta frames.";
99}
100
101TEST_F(VideoDecoderSoftwareFallbackWrapperTest, DoesNotFallbackOnEveryError) {
102 VideoCodec codec = {};
103 fallback_wrapper_.InitDecode(&codec, 2);
104 fake_decoder_.decode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
105 EncodedImage encoded_image;
106 EXPECT_EQ(
107 fake_decoder_.decode_return_code_,
108 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1));
109 EXPECT_EQ(1, fake_decoder_.decode_count_);
110
111 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1);
112 EXPECT_EQ(2, fake_decoder_.decode_count_)
113 << "Decoder should be active even though previous decode failed.";
114}
115
116TEST_F(VideoDecoderSoftwareFallbackWrapperTest, ForwardsReleaseCall) {
117 VideoCodec codec = {};
118 fallback_wrapper_.InitDecode(&codec, 2);
119 fallback_wrapper_.Release();
120 EXPECT_EQ(1, fake_decoder_.release_count_);
121
122 fake_decoder_.decode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
123 EncodedImage encoded_image;
124 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1);
125 EXPECT_EQ(1, fake_decoder_.release_count_)
126 << "Decoder should not be released during fallback.";
127 fallback_wrapper_.Release();
128 EXPECT_EQ(2, fake_decoder_.release_count_);
129}
130
131TEST_F(VideoDecoderSoftwareFallbackWrapperTest, ForwardsResetCall) {
132 VideoCodec codec = {};
133 fallback_wrapper_.InitDecode(&codec, 2);
134 fallback_wrapper_.Reset();
135 EXPECT_EQ(1, fake_decoder_.reset_count_);
136
137 fake_decoder_.decode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
138 EncodedImage encoded_image;
139 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1);
140 fallback_wrapper_.Reset();
141 EXPECT_EQ(2, fake_decoder_.reset_count_)
142 << "Reset not forwarded during fallback.";
143}
144
145// TODO(pbos): Fake a VP8 frame well enough to actually receive a callback from
146// the software encoder.
147TEST_F(VideoDecoderSoftwareFallbackWrapperTest,
148 ForwardsRegisterDecodeCompleteCallback) {
149 class FakeDecodedImageCallback : public DecodedImageCallback {
150 int32_t Decoded(I420VideoFrame& decodedImage) override { return 0; }
151 } callback, callback2;
152
153 VideoCodec codec = {};
154 fallback_wrapper_.InitDecode(&codec, 2);
155 fallback_wrapper_.RegisterDecodeCompleteCallback(&callback);
156 EXPECT_EQ(&callback, fake_decoder_.decode_complete_callback_);
157
158 fake_decoder_.decode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
159 EncodedImage encoded_image;
160 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1);
161 fallback_wrapper_.RegisterDecodeCompleteCallback(&callback2);
162 EXPECT_EQ(&callback2, fake_decoder_.decode_complete_callback_);
163}
164
165} // namespace webrtc