OLD | NEW |
| (Empty) |
1 /* | |
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 "webrtc/base/checks.h" | |
14 #include "webrtc/modules/video_coding/include/video_error_codes.h" | |
15 #include "webrtc/test/gtest.h" | |
16 | |
17 namespace webrtc { | |
18 | |
19 class VideoDecoderSoftwareFallbackWrapperTest : public ::testing::Test { | |
20 protected: | |
21 VideoDecoderSoftwareFallbackWrapperTest() | |
22 : fallback_wrapper_(kVideoCodecVP8, &fake_decoder_) {} | |
23 | |
24 class CountingFakeDecoder : public VideoDecoder { | |
25 public: | |
26 int32_t InitDecode(const VideoCodec* codec_settings, | |
27 int32_t number_of_cores) override { | |
28 ++init_decode_count_; | |
29 return WEBRTC_VIDEO_CODEC_OK; | |
30 } | |
31 | |
32 int32_t Decode(const EncodedImage& input_image, | |
33 bool missing_frames, | |
34 const RTPFragmentationHeader* fragmentation, | |
35 const CodecSpecificInfo* codec_specific_info, | |
36 int64_t render_time_ms) override { | |
37 ++decode_count_; | |
38 return decode_return_code_; | |
39 } | |
40 | |
41 int32_t RegisterDecodeCompleteCallback( | |
42 DecodedImageCallback* callback) override { | |
43 decode_complete_callback_ = callback; | |
44 return WEBRTC_VIDEO_CODEC_OK; | |
45 } | |
46 | |
47 int32_t Release() override { | |
48 ++release_count_; | |
49 return WEBRTC_VIDEO_CODEC_OK; | |
50 } | |
51 | |
52 const char* ImplementationName() const override { | |
53 return "fake-decoder"; | |
54 } | |
55 | |
56 int init_decode_count_ = 0; | |
57 int decode_count_ = 0; | |
58 int32_t decode_return_code_ = WEBRTC_VIDEO_CODEC_OK; | |
59 DecodedImageCallback* decode_complete_callback_ = nullptr; | |
60 int release_count_ = 0; | |
61 int reset_count_ = 0; | |
62 }; | |
63 CountingFakeDecoder fake_decoder_; | |
64 VideoDecoderSoftwareFallbackWrapper fallback_wrapper_; | |
65 }; | |
66 | |
67 TEST_F(VideoDecoderSoftwareFallbackWrapperTest, InitializesDecoder) { | |
68 VideoCodec codec = {}; | |
69 fallback_wrapper_.InitDecode(&codec, 2); | |
70 EXPECT_EQ(1, fake_decoder_.init_decode_count_); | |
71 } | |
72 | |
73 TEST_F(VideoDecoderSoftwareFallbackWrapperTest, | |
74 CanRecoverFromSoftwareFallback) { | |
75 VideoCodec codec = {}; | |
76 fallback_wrapper_.InitDecode(&codec, 2); | |
77 // Unfortunately faking a VP8 frame is hard. Rely on no Decode -> using SW | |
78 // decoder. | |
79 fake_decoder_.decode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; | |
80 EncodedImage encoded_image; | |
81 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1); | |
82 EXPECT_EQ(1, fake_decoder_.decode_count_); | |
83 | |
84 // Fail -> fake_decoder shouldn't be used anymore. | |
85 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1); | |
86 EXPECT_EQ(1, fake_decoder_.decode_count_) | |
87 << "Decoder used even though fallback should be active."; | |
88 | |
89 // Should be able to recover on a keyframe. | |
90 encoded_image._frameType = kVideoFrameKey; | |
91 fake_decoder_.decode_return_code_ = WEBRTC_VIDEO_CODEC_OK; | |
92 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1); | |
93 EXPECT_EQ(2, fake_decoder_.decode_count_) | |
94 << "Wrapper did not try to decode a keyframe using registered decoder."; | |
95 | |
96 encoded_image._frameType = kVideoFrameDelta; | |
97 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1); | |
98 EXPECT_EQ(3, fake_decoder_.decode_count_) | |
99 << "Decoder not used on future delta frames."; | |
100 } | |
101 | |
102 TEST_F(VideoDecoderSoftwareFallbackWrapperTest, DoesNotFallbackOnEveryError) { | |
103 VideoCodec codec = {}; | |
104 fallback_wrapper_.InitDecode(&codec, 2); | |
105 fake_decoder_.decode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR; | |
106 EncodedImage encoded_image; | |
107 EXPECT_EQ( | |
108 fake_decoder_.decode_return_code_, | |
109 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1)); | |
110 EXPECT_EQ(1, fake_decoder_.decode_count_); | |
111 | |
112 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1); | |
113 EXPECT_EQ(2, fake_decoder_.decode_count_) | |
114 << "Decoder should be active even though previous decode failed."; | |
115 } | |
116 | |
117 TEST_F(VideoDecoderSoftwareFallbackWrapperTest, ForwardsReleaseCall) { | |
118 VideoCodec codec = {}; | |
119 fallback_wrapper_.InitDecode(&codec, 2); | |
120 fallback_wrapper_.Release(); | |
121 EXPECT_EQ(1, fake_decoder_.release_count_); | |
122 | |
123 fake_decoder_.decode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; | |
124 EncodedImage encoded_image; | |
125 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1); | |
126 EXPECT_EQ(1, fake_decoder_.release_count_) | |
127 << "Decoder should not be released during fallback."; | |
128 fallback_wrapper_.Release(); | |
129 EXPECT_EQ(2, fake_decoder_.release_count_); | |
130 } | |
131 | |
132 // TODO(pbos): Fake a VP8 frame well enough to actually receive a callback from | |
133 // the software decoder. | |
134 TEST_F(VideoDecoderSoftwareFallbackWrapperTest, | |
135 ForwardsRegisterDecodeCompleteCallback) { | |
136 class FakeDecodedImageCallback : public DecodedImageCallback { | |
137 int32_t Decoded(VideoFrame& decodedImage) override { return 0; } | |
138 int32_t Decoded( | |
139 webrtc::VideoFrame& decodedImage, int64_t decode_time_ms) override { | |
140 RTC_NOTREACHED(); | |
141 return -1; | |
142 } | |
143 } callback, callback2; | |
144 | |
145 VideoCodec codec = {}; | |
146 fallback_wrapper_.InitDecode(&codec, 2); | |
147 fallback_wrapper_.RegisterDecodeCompleteCallback(&callback); | |
148 EXPECT_EQ(&callback, fake_decoder_.decode_complete_callback_); | |
149 | |
150 fake_decoder_.decode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; | |
151 EncodedImage encoded_image; | |
152 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1); | |
153 fallback_wrapper_.RegisterDecodeCompleteCallback(&callback2); | |
154 EXPECT_EQ(&callback2, fake_decoder_.decode_complete_callback_); | |
155 } | |
156 | |
157 TEST_F(VideoDecoderSoftwareFallbackWrapperTest, | |
158 ReportsFallbackImplementationName) { | |
159 VideoCodec codec = {}; | |
160 fallback_wrapper_.InitDecode(&codec, 2); | |
161 | |
162 fake_decoder_.decode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; | |
163 EncodedImage encoded_image; | |
164 fallback_wrapper_.Decode(encoded_image, false, nullptr, nullptr, -1); | |
165 // Hard coded expected value since libvpx is the software implementation name | |
166 // for VP8. Change accordingly if the underlying implementation does. | |
167 EXPECT_STREQ("libvpx (fallback from: fake-decoder)", | |
168 fallback_wrapper_.ImplementationName()); | |
169 fallback_wrapper_.Release(); | |
170 } | |
171 | |
172 } // namespace webrtc | |
OLD | NEW |