• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2012 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/common_types.h"
12 #include "webrtc/engine_configurations.h"
13 #include "webrtc/modules/video_coding/codecs/i420/main/interface/i420.h"
14 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
15 #include "webrtc/test/channel_transport/include/channel_transport.h"
16 #include "webrtc/video_engine/include/vie_base.h"
17 #include "webrtc/video_engine/include/vie_capture.h"
18 #include "webrtc/video_engine/include/vie_codec.h"
19 #include "webrtc/video_engine/include/vie_external_codec.h"
20 #include "webrtc/video_engine/include/vie_network.h"
21 #include "webrtc/video_engine/include/vie_render.h"
22 #include "webrtc/video_engine/include/vie_rtp_rtcp.h"
23 #include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h"
24 #include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h"
25 #include "webrtc/video_engine/test/libvietest/include/tb_I420_codec.h"
26 #include "webrtc/video_engine/test/libvietest/include/tb_capture_device.h"
27 #include "webrtc/video_engine/test/libvietest/include/tb_interfaces.h"
28 #include "webrtc/video_engine/test/libvietest/include/tb_video_channel.h"
29 #include "webrtc/voice_engine/include/voe_base.h"
30 
31 class TestCodecObserver : public webrtc::ViEEncoderObserver,
32                           public webrtc::ViEDecoderObserver {
33  public:
34   int incoming_codec_called_;
35   int incoming_rate_called_;
36   int decoder_timing_called_;
37   int outgoing_rate_called_;
38 
39   unsigned char last_payload_type_;
40   uint16_t last_width_;
41   uint16_t last_height_;
42 
43   unsigned int last_outgoing_framerate_;
44   unsigned int last_outgoing_bitrate_;
45   unsigned int last_incoming_framerate_;
46   unsigned int last_incoming_bitrate_;
47   unsigned int suspend_change_called_;
48 
49   webrtc::VideoCodec incoming_codec_;
50 
TestCodecObserver()51   TestCodecObserver()
52       : incoming_codec_called_(0),
53         incoming_rate_called_(0),
54         decoder_timing_called_(0),
55         outgoing_rate_called_(0),
56         last_payload_type_(0),
57         last_width_(0),
58         last_height_(0),
59         last_outgoing_framerate_(0),
60         last_outgoing_bitrate_(0),
61         last_incoming_framerate_(0),
62         last_incoming_bitrate_(0),
63         suspend_change_called_(0) {
64     memset(&incoming_codec_, 0, sizeof(incoming_codec_));
65   }
IncomingCodecChanged(const int video_channel,const webrtc::VideoCodec & video_codec)66   virtual void IncomingCodecChanged(const int video_channel,
67                                     const webrtc::VideoCodec& video_codec) {
68     incoming_codec_called_++;
69     last_payload_type_ = video_codec.plType;
70     last_width_ = video_codec.width;
71     last_height_ = video_codec.height;
72 
73     memcpy(&incoming_codec_, &video_codec, sizeof(video_codec));
74   }
75 
IncomingRate(const int video_channel,const unsigned int framerate,const unsigned int bitrate)76   virtual void IncomingRate(const int video_channel,
77                             const unsigned int framerate,
78                             const unsigned int bitrate) {
79     incoming_rate_called_++;
80     last_incoming_framerate_ += framerate;
81     last_incoming_bitrate_ += bitrate;
82   }
83 
DecoderTiming(int decode_ms,int max_decode_ms,int current_delay_ms,int target_delay_ms,int jitter_buffer_ms,int min_playout_delay_ms,int render_delay_ms)84   virtual void DecoderTiming(int decode_ms,
85                              int max_decode_ms,
86                              int current_delay_ms,
87                              int target_delay_ms,
88                              int jitter_buffer_ms,
89                              int min_playout_delay_ms,
90                              int render_delay_ms) {
91     ++decoder_timing_called_;
92     // TODO(fischman): anything useful to be done with the data here?
93   }
94 
OutgoingRate(const int video_channel,const unsigned int framerate,const unsigned int bitrate)95   virtual void OutgoingRate(const int video_channel,
96                             const unsigned int framerate,
97                             const unsigned int bitrate) {
98     outgoing_rate_called_++;
99     last_outgoing_framerate_ += framerate;
100     last_outgoing_bitrate_ += bitrate;
101   }
102 
SuspendChange(int video_channel,bool is_suspended)103   virtual void SuspendChange(int video_channel, bool is_suspended) OVERRIDE {
104     suspend_change_called_++;
105   }
106 
RequestNewKeyFrame(const int video_channel)107   virtual void RequestNewKeyFrame(const int video_channel) {
108   }
109 };
110 
111 class RenderFilter : public webrtc::ViEEffectFilter {
112  public:
113   int num_frames_;
114   unsigned int last_render_width_;
115   unsigned int last_render_height_;
116 
RenderFilter()117   RenderFilter()
118       : num_frames_(0),
119         last_render_width_(0),
120         last_render_height_(0) {
121   }
122 
~RenderFilter()123   virtual ~RenderFilter() {
124   }
Transform(int size,unsigned char * frame_buffer,int64_t ntp_time_ms,unsigned int timestamp,unsigned int width,unsigned int height)125   virtual int Transform(int size,
126                         unsigned char* frame_buffer,
127                         int64_t ntp_time_ms,
128                         unsigned int timestamp,
129                         unsigned int width,
130                         unsigned int height)  {
131     num_frames_++;
132     last_render_width_ = width;
133     last_render_height_ = height;
134     return 0;
135   }
136 };
137 
ViECodecStandardTest()138 void ViEAutoTest::ViECodecStandardTest() {
139   TbInterfaces interfaces("ViECodecStandardTest");
140 
141   TbCaptureDevice capture_device = TbCaptureDevice(interfaces);
142   int capture_id = capture_device.captureId;
143 
144   webrtc::VideoEngine* video_engine = interfaces.video_engine;
145   webrtc::ViEBase* base = interfaces.base;
146   webrtc::ViECapture* capture = interfaces.capture;
147   webrtc::ViERender* render = interfaces.render;
148   webrtc::ViECodec* codec = interfaces.codec;
149   webrtc::ViERTP_RTCP* rtp_rtcp = interfaces.rtp_rtcp;
150   webrtc::ViENetwork* network = interfaces.network;
151 
152   int video_channel = -1;
153   EXPECT_EQ(0, base->CreateChannel(video_channel));
154   EXPECT_EQ(0, capture->ConnectCaptureDevice(capture_id, video_channel));
155   EXPECT_EQ(0, rtp_rtcp->SetRTCPStatus(
156       video_channel, webrtc::kRtcpCompound_RFC4585));
157 
158   EXPECT_EQ(0, rtp_rtcp->SetKeyFrameRequestMethod(
159       video_channel, webrtc::kViEKeyFrameRequestPliRtcp));
160   EXPECT_EQ(0, rtp_rtcp->SetTMMBRStatus(video_channel, true));
161   EXPECT_EQ(0, render->AddRenderer(capture_id, _window1, 0, 0.0, 0.0, 1.0,
162                                    1.0));
163   EXPECT_EQ(0, render->AddRenderer(video_channel, _window2, 1, 0.0, 0.0, 1.0,
164                                    1.0));
165   EXPECT_EQ(0, render->StartRender(capture_id));
166   EXPECT_EQ(0, render->StartRender(video_channel));
167 
168   webrtc::VideoCodec video_codec;
169   memset(&video_codec, 0, sizeof(webrtc::VideoCodec));
170   for (int idx = 0; idx < codec->NumberOfCodecs(); idx++) {
171     EXPECT_EQ(0, codec->GetCodec(idx, video_codec));
172     if (video_codec.codecType != webrtc::kVideoCodecI420) {
173       video_codec.width = 640;
174       video_codec.height = 480;
175     }
176     if (video_codec.codecType == webrtc::kVideoCodecI420) {
177       video_codec.width = 176;
178       video_codec.height = 144;
179     }
180     EXPECT_EQ(0, codec->SetReceiveCodec(video_channel, video_codec));
181   }
182 
183   for (int idx = 0; idx < codec->NumberOfCodecs(); idx++) {
184     EXPECT_EQ(0, codec->GetCodec(idx, video_codec));
185     if (video_codec.codecType == webrtc::kVideoCodecVP8) {
186       EXPECT_EQ(0, codec->SetSendCodec(video_channel, video_codec));
187       break;
188     }
189   }
190   const char* ip_address = "127.0.0.1";
191   const uint16_t rtp_port = 6000;
192 
193   webrtc::scoped_ptr<webrtc::test::VideoChannelTransport>
194       video_channel_transport(
195           new webrtc::test::VideoChannelTransport(network, video_channel));
196 
197   ASSERT_EQ(0, video_channel_transport->SetSendDestination(ip_address,
198                                                            rtp_port));
199   ASSERT_EQ(0, video_channel_transport->SetLocalReceiver(rtp_port));
200 
201   EXPECT_EQ(0, base->StartReceive(video_channel));
202   EXPECT_EQ(0, base->StartSend(video_channel));
203 
204   // Make sure all codecs runs
205   {
206     webrtc::ViEImageProcess* image_process =
207         webrtc::ViEImageProcess::GetInterface(video_engine);
208     TestCodecObserver codec_observer;
209     EXPECT_EQ(0, codec->RegisterDecoderObserver(video_channel, codec_observer));
210     ViETest::Log("Loop through all codecs for %d seconds",
211                  kAutoTestSleepTimeMs / 1000);
212 
213     for (int i = 0; i < codec->NumberOfCodecs() - 2; i++) {
214       EXPECT_EQ(0, codec->GetCodec(i, video_codec));
215       if (video_codec.codecType == webrtc::kVideoCodecI420) {
216         // Lower resolution to sockets keep up.
217         video_codec.width = 176;
218         video_codec.height = 144;
219         video_codec.maxFramerate = 15;
220       }
221       EXPECT_EQ(0, codec->SetSendCodec(video_channel, video_codec));
222       ViETest::Log("\t %d. %s", i, video_codec.plName);
223 
224       RenderFilter frame_counter;
225       EXPECT_EQ(0, image_process->RegisterRenderEffectFilter(video_channel,
226                                                              frame_counter));
227       AutoTestSleep(kAutoTestSleepTimeMs);
228 
229       // Verify we've received and decoded correct payload.
230       EXPECT_EQ(video_codec.codecType,
231                 codec_observer.incoming_codec_.codecType);
232 
233       // This requirement is quite relaxed, but it's hard to say what's an
234       // acceptable number of received frames when we take into account the
235       // wide variety of devices (and that we run under valgrind).
236       EXPECT_GT(frame_counter.num_frames_, 0);
237 
238       EXPECT_EQ(0, image_process->DeregisterRenderEffectFilter(
239           video_channel));
240     }
241     image_process->Release();
242     EXPECT_EQ(0, codec->DeregisterDecoderObserver(video_channel));
243     ViETest::Log("Done!");
244   }
245 
246   // Test Callbacks
247   TestCodecObserver codec_observer;
248   EXPECT_EQ(0, codec->RegisterEncoderObserver(video_channel, codec_observer));
249   EXPECT_EQ(0, codec->RegisterDecoderObserver(video_channel, codec_observer));
250 
251   ViETest::Log("\nTesting codec callbacks...");
252 
253   for (int idx = 0; idx < codec->NumberOfCodecs(); idx++) {
254     EXPECT_EQ(0, codec->GetCodec(idx, video_codec));
255     if (video_codec.codecType == webrtc::kVideoCodecVP8) {
256       EXPECT_EQ(0, codec->SetSendCodec(video_channel, video_codec));
257       break;
258     }
259   }
260   AutoTestSleep(kAutoTestSleepTimeMs);
261 
262   // Verify the delay estimates are larger than 0.
263   int avg_send_delay = 0;
264   int max_send_delay = 0;
265   EXPECT_TRUE(codec->GetSendSideDelay(video_channel, &avg_send_delay,
266                                       &max_send_delay));
267   EXPECT_GT(avg_send_delay, 0);
268   EXPECT_GE(max_send_delay, avg_send_delay);
269   int receive_delay_ms = 0;
270   EXPECT_EQ(0, codec->GetReceiveSideDelay(video_channel, &receive_delay_ms));
271   EXPECT_GT(receive_delay_ms, 0);
272 
273   EXPECT_EQ(0, base->StopSend(video_channel));
274   EXPECT_EQ(0, codec->DeregisterEncoderObserver(video_channel));
275   EXPECT_EQ(0, codec->DeregisterDecoderObserver(video_channel));
276 
277   EXPECT_GT(codec_observer.incoming_codec_called_, 0);
278   EXPECT_GT(codec_observer.incoming_rate_called_, 0);
279   EXPECT_GT(codec_observer.decoder_timing_called_, 0);
280   EXPECT_GT(codec_observer.outgoing_rate_called_, 0);
281 
282   EXPECT_EQ(0, base->StopReceive(video_channel));
283   EXPECT_EQ(0, render->StopRender(video_channel));
284   EXPECT_EQ(0, render->RemoveRenderer(capture_id));
285   EXPECT_EQ(0, render->RemoveRenderer(video_channel));
286   EXPECT_EQ(0, capture->DisconnectCaptureDevice(video_channel));
287   EXPECT_EQ(0, base->DeleteChannel(video_channel));
288 }
289 
ViECodecExtendedTest()290 void ViEAutoTest::ViECodecExtendedTest() {
291   {
292     ViETest::Log(" ");
293     ViETest::Log("========================================");
294     ViETest::Log(" ViECodec Extended Test\n");
295 
296     ViECodecExternalCodecTest();
297 
298     TbInterfaces interfaces("ViECodecExtendedTest");
299     webrtc::ViEBase* base = interfaces.base;
300     webrtc::ViECapture* capture = interfaces.capture;
301     webrtc::ViERender* render = interfaces.render;
302     webrtc::ViECodec* codec = interfaces.codec;
303     webrtc::ViERTP_RTCP* rtp_rtcp = interfaces.rtp_rtcp;
304     webrtc::ViENetwork* network = interfaces.network;
305 
306     TbCaptureDevice capture_device = TbCaptureDevice(interfaces);
307     int capture_id = capture_device.captureId;
308 
309     int video_channel = -1;
310     EXPECT_EQ(0, base->CreateChannel(video_channel));
311     EXPECT_EQ(0, capture->ConnectCaptureDevice(capture_id, video_channel));
312     EXPECT_EQ(0, rtp_rtcp->SetRTCPStatus(
313                 video_channel, webrtc::kRtcpCompound_RFC4585));
314     EXPECT_EQ(0, rtp_rtcp->SetKeyFrameRequestMethod(
315                 video_channel, webrtc::kViEKeyFrameRequestPliRtcp));
316     EXPECT_EQ(0, rtp_rtcp->SetTMMBRStatus(video_channel, true));
317     EXPECT_EQ(0, render->AddRenderer(capture_id, _window1, 0, 0.0, 0.0, 1.0,
318                                      1.0));
319 
320     EXPECT_EQ(0, render->AddRenderer(video_channel, _window2, 1, 0.0, 0.0, 1.0,
321                                      1.0));
322     EXPECT_EQ(0, render->StartRender(capture_id));
323     EXPECT_EQ(0, render->StartRender(video_channel));
324 
325     webrtc::VideoCodec video_codec;
326     memset(&video_codec, 0, sizeof(webrtc::VideoCodec));
327     for (int idx = 0; idx < codec->NumberOfCodecs(); idx++) {
328       EXPECT_EQ(0, codec->GetCodec(idx, video_codec));
329       if (video_codec.codecType != webrtc::kVideoCodecI420) {
330         video_codec.width = 640;
331         video_codec.height = 480;
332       }
333       EXPECT_EQ(0, codec->SetReceiveCodec(video_channel, video_codec));
334     }
335 
336     const char* ip_address = "127.0.0.1";
337     const uint16_t rtp_port = 6000;
338 
339     webrtc::scoped_ptr<webrtc::test::VideoChannelTransport>
340         video_channel_transport(
341             new webrtc::test::VideoChannelTransport(network, video_channel));
342 
343     ASSERT_EQ(0, video_channel_transport->SetSendDestination(ip_address,
344                                                              rtp_port));
345     ASSERT_EQ(0, video_channel_transport->SetLocalReceiver(rtp_port));
346 
347     EXPECT_EQ(0, base->StartSend(video_channel));
348     EXPECT_EQ(0, base->StartReceive(video_channel));
349 
350     // Codec specific tests
351     memset(&video_codec, 0, sizeof(webrtc::VideoCodec));
352     EXPECT_EQ(0, base->StopSend(video_channel));
353 
354     TestCodecObserver codec_observer;
355     EXPECT_EQ(0, codec->RegisterEncoderObserver(video_channel, codec_observer));
356     EXPECT_EQ(0, codec->RegisterDecoderObserver(video_channel, codec_observer));
357     EXPECT_EQ(0, base->StopReceive(video_channel));
358 
359     EXPECT_EQ(0, render->StopRender(video_channel));
360     EXPECT_EQ(0, render->RemoveRenderer(capture_id));
361     EXPECT_EQ(0, render->RemoveRenderer(video_channel));
362     EXPECT_EQ(0, capture->DisconnectCaptureDevice(video_channel));
363     EXPECT_EQ(0, base->DeleteChannel(video_channel));
364   }
365 
366   // Multiple send channels.
367   {
368     // Create two channels, where the second channel is created from the
369     // first channel. Send different resolutions on the channels and verify
370     // the received streams.
371     TbInterfaces video_engine("ViECodecExtendedTest2");
372     TbCaptureDevice tb_capture(video_engine);
373     webrtc::ViENetwork* network = video_engine.network;
374 
375     // Create channel 1.
376     int video_channel_1 = -1;
377     EXPECT_EQ(0, video_engine.base->CreateChannel(video_channel_1));
378 
379     // Create channel 2 based on the first channel.
380     int video_channel_2 = -1;
381     EXPECT_EQ(0, video_engine.base->CreateChannel(
382         video_channel_2, video_channel_1));
383     EXPECT_NE(video_channel_1, video_channel_2)
384         << "Channel 2 should be unique.";
385 
386     const char* ip_address = "127.0.0.1";
387     uint16_t rtp_port_1 = 12000;
388     uint16_t rtp_port_2 = 13000;
389 
390     webrtc::scoped_ptr<webrtc::test::VideoChannelTransport>
391         video_channel_transport_1(
392             new webrtc::test::VideoChannelTransport(network, video_channel_1));
393 
394     ASSERT_EQ(0, video_channel_transport_1->SetSendDestination(ip_address,
395                                                                rtp_port_1));
396     ASSERT_EQ(0, video_channel_transport_1->SetLocalReceiver(rtp_port_1));
397 
398     webrtc::scoped_ptr<webrtc::test::VideoChannelTransport>
399         video_channel_transport_2(
400             new webrtc::test::VideoChannelTransport(network, video_channel_2));
401 
402     ASSERT_EQ(0, video_channel_transport_2->SetSendDestination(ip_address,
403                                                                rtp_port_2));
404     ASSERT_EQ(0, video_channel_transport_2->SetLocalReceiver(rtp_port_2));
405 
406     EXPECT_EQ(0, video_engine.rtp_rtcp->SetLocalSSRC(video_channel_1, 1));
407     EXPECT_EQ(0, video_engine.rtp_rtcp->SetLocalSSRC(video_channel_2, 2));
408     tb_capture.ConnectTo(video_channel_1);
409     tb_capture.ConnectTo(video_channel_2);
410     EXPECT_EQ(0, video_engine.rtp_rtcp->SetKeyFrameRequestMethod(
411         video_channel_1, webrtc::kViEKeyFrameRequestPliRtcp));
412     EXPECT_EQ(0, video_engine.rtp_rtcp->SetKeyFrameRequestMethod(
413         video_channel_2, webrtc::kViEKeyFrameRequestPliRtcp));
414     EXPECT_EQ(0, video_engine.render->AddRenderer(video_channel_1, _window1, 0,
415                                                   0.0, 0.0, 1.0, 1.0));
416     EXPECT_EQ(0, video_engine.render->StartRender(video_channel_1));
417     EXPECT_EQ(0, video_engine.render->AddRenderer(video_channel_2, _window2, 0,
418                                                   0.0, 0.0, 1.0, 1.0));
419     EXPECT_EQ(0, video_engine.render->StartRender(video_channel_2));
420 
421     // Set Send codec.
422     uint16_t codec_width = 320;
423     uint16_t codec_height = 240;
424     bool codec_set = false;
425     webrtc::VideoCodec video_codec;
426     webrtc::VideoCodec send_codec1;
427     webrtc::VideoCodec send_codec2;
428     for (int idx = 0; idx < video_engine.codec->NumberOfCodecs(); idx++) {
429       EXPECT_EQ(0, video_engine.codec->GetCodec(idx, video_codec));
430       EXPECT_EQ(0, video_engine.codec->SetReceiveCodec(video_channel_1,
431                                                        video_codec));
432       if (video_codec.codecType == webrtc::kVideoCodecVP8) {
433         memcpy(&send_codec1, &video_codec, sizeof(video_codec));
434         send_codec1.width = codec_width;
435         send_codec1.height = codec_height;
436         EXPECT_EQ(0, video_engine.codec->SetSendCodec(
437                     video_channel_1, send_codec1));
438         memcpy(&send_codec2, &video_codec, sizeof(video_codec));
439         send_codec2.width = 2 * codec_width;
440         send_codec2.height = 2 * codec_height;
441         EXPECT_EQ(0, video_engine.codec->SetSendCodec(
442                     video_channel_2, send_codec2));
443         codec_set = true;
444         break;
445       }
446     }
447     EXPECT_TRUE(codec_set);
448 
449     // We need to verify using render effect filter since we won't trigger
450     // a decode reset in loopback (due to using the same SSRC).
451     RenderFilter filter1;
452     RenderFilter filter2;
453     EXPECT_EQ(0, video_engine.image_process->RegisterRenderEffectFilter(
454         video_channel_1, filter1));
455     EXPECT_EQ(0, video_engine.image_process->RegisterRenderEffectFilter(
456         video_channel_2, filter2));
457 
458     EXPECT_EQ(0, video_engine.base->StartReceive(video_channel_1));
459     EXPECT_EQ(0, video_engine.base->StartSend(video_channel_1));
460     EXPECT_EQ(0, video_engine.base->StartReceive(video_channel_2));
461     EXPECT_EQ(0, video_engine.base->StartSend(video_channel_2));
462 
463     AutoTestSleep(kAutoTestSleepTimeMs);
464 
465     EXPECT_EQ(0, video_engine.base->StopReceive(video_channel_1));
466     EXPECT_EQ(0, video_engine.base->StopSend(video_channel_1));
467     EXPECT_EQ(0, video_engine.base->StopReceive(video_channel_2));
468     EXPECT_EQ(0, video_engine.base->StopSend(video_channel_2));
469 
470     EXPECT_EQ(0, video_engine.image_process->DeregisterRenderEffectFilter(
471         video_channel_1));
472     EXPECT_EQ(0, video_engine.image_process->DeregisterRenderEffectFilter(
473         video_channel_2));
474     EXPECT_EQ(send_codec1.width, filter1.last_render_width_);
475     EXPECT_EQ(send_codec1.height, filter1.last_render_height_);
476     EXPECT_EQ(send_codec2.width, filter2.last_render_width_);
477     EXPECT_EQ(send_codec2.height, filter2.last_render_height_);
478 
479     EXPECT_EQ(0, video_engine.base->DeleteChannel(video_channel_1));
480     EXPECT_EQ(0, video_engine.base->DeleteChannel(video_channel_2));
481   }
482 }
483 
ViECodecAPITest()484 void ViEAutoTest::ViECodecAPITest() {
485   webrtc::VideoEngine* video_engine = NULL;
486   video_engine = webrtc::VideoEngine::Create();
487   EXPECT_TRUE(video_engine != NULL);
488 
489   webrtc::ViEBase* base = webrtc::ViEBase::GetInterface(video_engine);
490   EXPECT_EQ(0, base->Init());
491 
492   int video_channel = -1;
493   EXPECT_EQ(0, base->CreateChannel(video_channel));
494 
495   webrtc::ViECodec* codec = webrtc::ViECodec::GetInterface(video_engine);
496   EXPECT_TRUE(codec != NULL);
497 
498   webrtc::VideoCodec video_codec;
499   memset(&video_codec, 0, sizeof(webrtc::VideoCodec));
500 
501   const int number_of_codecs = codec->NumberOfCodecs();
502 
503   for (int i = 0; i < number_of_codecs; i++) {
504     EXPECT_EQ(0, codec->GetCodec(i, video_codec));
505     if (video_codec.codecType == webrtc::kVideoCodecVP8) {
506       video_codec.codecSpecific.VP8.automaticResizeOn = true;
507       video_codec.codecSpecific.VP8.frameDroppingOn = true;
508       video_codec.codecSpecific.VP8.keyFrameInterval = 300;
509       EXPECT_EQ(0, codec->SetSendCodec(video_channel, video_codec));
510       break;
511     }
512   }
513   const unsigned int kMinBitrate = 123;
514   video_codec.minBitrate = kMinBitrate;
515   video_codec.startBitrate = 50;
516   EXPECT_EQ(0, codec->SetSendCodec(video_channel, video_codec));
517   EXPECT_EQ(0, codec->GetSendCodec(video_channel, video_codec));
518   EXPECT_EQ(kMinBitrate, video_codec.startBitrate);
519 
520   memset(&video_codec, 0, sizeof(video_codec));
521   EXPECT_EQ(0, codec->GetSendCodec(video_channel, video_codec));
522   EXPECT_EQ(webrtc::kVideoCodecVP8, video_codec.codecType);
523   EXPECT_TRUE(video_codec.codecSpecific.VP8.automaticResizeOn);
524   EXPECT_TRUE(video_codec.codecSpecific.VP8.frameDroppingOn);
525   EXPECT_EQ(300, video_codec.codecSpecific.VP8.keyFrameInterval);
526 
527   for (int i = 0; i < number_of_codecs; i++) {
528     EXPECT_EQ(0, codec->GetCodec(i, video_codec));
529     if (video_codec.codecType == webrtc::kVideoCodecI420) {
530       EXPECT_EQ(0, codec->SetSendCodec(video_channel, video_codec));
531       break;
532     }
533   }
534 
535   memset(&video_codec, 0, sizeof(video_codec));
536   EXPECT_EQ(0, codec->GetSendCodec(video_channel, video_codec));
537   EXPECT_EQ(webrtc::kVideoCodecI420, video_codec.codecType);
538 
539   // Register a generic codec
540   memset(&video_codec, 0, sizeof(video_codec));
541   video_codec.codecType = webrtc::kVideoCodecGeneric;
542   strcpy(video_codec.plName, "generic-codec");
543   uint8_t payload_type = 127;
544   video_codec.plType = payload_type;
545   video_codec.minBitrate = 100;
546   video_codec.startBitrate = 500;
547   video_codec.maxBitrate = 10000;
548   video_codec.width = 1920;
549   video_codec.height = 1080;
550   video_codec.maxFramerate = 30;
551   video_codec.qpMax = 50;
552 
553   webrtc::ViEExternalCodec* external_codec =
554       webrtc::ViEExternalCodec::GetInterface(video_engine);
555   EXPECT_TRUE(external_codec != NULL);
556 
557   // Any encoder will do.
558   webrtc::I420Encoder encoder;
559   EXPECT_EQ(0, external_codec->RegisterExternalSendCodec(video_channel,
560                                                          payload_type, &encoder,
561                                                          false));
562   EXPECT_EQ(0, codec->SetSendCodec(video_channel, video_codec));
563 
564   memset(&video_codec, 0, sizeof(video_codec));
565   EXPECT_EQ(0, codec->GetSendCodec(video_channel, video_codec));
566   EXPECT_EQ(webrtc::kVideoCodecGeneric, video_codec.codecType);
567 
568   EXPECT_EQ(0, base->DeleteChannel(video_channel));
569 
570   EXPECT_EQ(0, external_codec->Release());
571   EXPECT_EQ(0, codec->Release());
572   EXPECT_EQ(0, base->Release());
573   EXPECT_TRUE(webrtc::VideoEngine::Delete(video_engine));
574 }
575 
ViECodecExternalCodecTest()576 void ViEAutoTest::ViECodecExternalCodecTest() {
577   ViETest::Log(" ");
578   ViETest::Log("========================================");
579   ViETest::Log(" ViEExternalCodec Test\n");
580 
581   /// **************************************************************
582   //  Begin create/initialize WebRTC Video Engine for testing
583   /// **************************************************************
584 
585   /// **************************************************************
586   //  Engine ready. Begin testing class
587   /// **************************************************************
588 
589 #ifdef WEBRTC_VIDEO_ENGINE_EXTERNAL_CODEC_API
590   int number_of_errors = 0;
591   {
592     int error = 0;
593     TbInterfaces ViE("ViEExternalCodec");
594     TbCaptureDevice capture_device(ViE);
595     TbVideoChannel channel(ViE, webrtc::kVideoCodecI420, 352, 288, 30,
596                            (352 * 288 * 3 * 8 * 30) / (2 * 1000));
597     capture_device.ConnectTo(channel.videoChannel);
598 
599     error = ViE.render->AddRenderer(channel.videoChannel, _window1, 0, 0.0, 0.0,
600                                     1.0, 1.0);
601     number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
602                                            __FUNCTION__, __LINE__);
603     error = ViE.render->StartRender(channel.videoChannel);
604     number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
605                                            __FUNCTION__, __LINE__);
606 
607     channel.StartReceive();
608     channel.StartSend();
609 
610     ViETest::Log("Using internal I420 codec");
611     AutoTestSleep(kAutoTestSleepTimeMs / 2);
612 
613     webrtc::ViEExternalCodec* vie_external_codec =
614         webrtc::ViEExternalCodec::GetInterface(ViE.video_engine);
615     number_of_errors += ViETest::TestError(vie_external_codec != NULL,
616                                            "ERROR: %s at line %d",
617                                            __FUNCTION__, __LINE__);
618     webrtc::VideoCodec codec;
619     error = ViE.codec->GetSendCodec(channel.videoChannel, codec);
620     number_of_errors += ViETest::TestError(vie_external_codec != NULL,
621                                            "ERROR: %s at line %d",
622                                            __FUNCTION__, __LINE__);
623 
624     // Use external encoder instead.
625     {
626       TbI420Encoder ext_encoder;
627 
628       // Test to register on wrong channel.
629       error = vie_external_codec->RegisterExternalSendCodec(
630           channel.videoChannel + 5, codec.plType, &ext_encoder, false);
631       number_of_errors += ViETest::TestError(error == -1,
632                                              "ERROR: %s at line %d",
633                                              __FUNCTION__, __LINE__);
634       number_of_errors += ViETest::TestError(
635           ViE.LastError() == kViECodecInvalidArgument,
636           "ERROR: %s at line %d", __FUNCTION__, __LINE__);
637 
638       error = vie_external_codec->RegisterExternalSendCodec(
639                 channel.videoChannel, codec.plType, &ext_encoder, false);
640       number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
641                                              __FUNCTION__, __LINE__);
642 
643       // Use new external encoder
644       error = ViE.codec->SetSendCodec(channel.videoChannel, codec);
645       number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
646                                              __FUNCTION__, __LINE__);
647 
648       TbI420Decoder ext_decoder;
649       error = vie_external_codec->RegisterExternalReceiveCodec(
650           channel.videoChannel, codec.plType, &ext_decoder);
651       number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
652                                              __FUNCTION__, __LINE__);
653 
654       error = ViE.codec->SetReceiveCodec(channel.videoChannel, codec);
655       number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
656                                              __FUNCTION__, __LINE__);
657 
658       ViETest::Log("Using external I420 codec");
659       AutoTestSleep(kAutoTestSleepTimeMs);
660 
661       // Test to deregister on wrong channel
662       error = vie_external_codec->DeRegisterExternalSendCodec(
663           channel.videoChannel + 5, codec.plType);
664       number_of_errors += ViETest::TestError(error == -1,
665                                              "ERROR: %s at line %d",
666                                              __FUNCTION__, __LINE__);
667       number_of_errors += ViETest::TestError(
668           ViE.LastError() == kViECodecInvalidArgument, "ERROR: %s at line %d",
669           __FUNCTION__, __LINE__);
670 
671       // Test to deregister wrong payload type.
672       error = vie_external_codec->DeRegisterExternalSendCodec(
673           channel.videoChannel, codec.plType - 1);
674       number_of_errors += ViETest::TestError(error == -1,
675                                              "ERROR: %s at line %d",
676                                              __FUNCTION__, __LINE__);
677 
678       // Deregister external send codec
679       error = vie_external_codec->DeRegisterExternalSendCodec(
680           channel.videoChannel, codec.plType);
681       number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
682                                              __FUNCTION__, __LINE__);
683 
684       error = vie_external_codec->DeRegisterExternalReceiveCodec(
685           channel.videoChannel, codec.plType);
686       number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
687                                              __FUNCTION__, __LINE__);
688 
689       // Verify that the encoder and decoder has been used
690       TbI420Encoder::FunctionCalls encode_calls =
691           ext_encoder.GetFunctionCalls();
692       number_of_errors += ViETest::TestError(encode_calls.InitEncode == 1,
693                                              "ERROR: %s at line %d",
694                                              __FUNCTION__, __LINE__);
695       number_of_errors += ViETest::TestError(encode_calls.Release == 1,
696                                              "ERROR: %s at line %d",
697                                              __FUNCTION__, __LINE__);
698       number_of_errors += ViETest::TestError(encode_calls.Encode > 30,
699                                              "ERROR: %s at line %d",
700                                              __FUNCTION__, __LINE__);
701       number_of_errors += ViETest::TestError(
702           encode_calls.RegisterEncodeCompleteCallback == 1,
703           "ERROR: %s at line %d", __FUNCTION__, __LINE__);
704       number_of_errors += ViETest::TestError(
705           encode_calls.SetChannelParameters > 1, "ERROR: %s at line %d",
706           __FUNCTION__, __LINE__);
707       number_of_errors += ViETest::TestError(encode_calls.SetRates > 1,
708                                              "ERROR: %s at line %d",
709                                              __FUNCTION__, __LINE__);
710 
711       TbI420Decoder::FunctionCalls decode_calls =
712           ext_decoder.GetFunctionCalls();
713       number_of_errors += ViETest::TestError(decode_calls.InitDecode == 1,
714                                              "ERROR: %s at line %d",
715                                              __FUNCTION__, __LINE__);
716       number_of_errors += ViETest::TestError(decode_calls.Release == 1,
717                                              "ERROR: %s at line %d",
718                                              __FUNCTION__, __LINE__);
719       number_of_errors += ViETest::TestError(decode_calls.Decode > 30,
720                                              "ERROR: %s at line %d",
721                                              __FUNCTION__, __LINE__);
722       number_of_errors += ViETest::TestError(
723           decode_calls.RegisterDecodeCompleteCallback == 1,
724           "ERROR: %s at line %d", __FUNCTION__, __LINE__);
725 
726       ViETest::Log("Changing payload type Using external I420 codec");
727 
728       codec.plType = codec.plType - 1;
729       error = vie_external_codec->RegisterExternalReceiveCodec(
730           channel.videoChannel, codec.plType, &ext_decoder);
731       number_of_errors += ViETest::TestError(error == 0,
732                                              "ERROR: %s at line %d",
733                                              __FUNCTION__, __LINE__);
734 
735       error = ViE.codec->SetReceiveCodec(channel.videoChannel,
736                                          codec);
737       number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
738                                              __FUNCTION__, __LINE__);
739 
740       error = vie_external_codec->RegisterExternalSendCodec(
741                 channel.videoChannel, codec.plType, &ext_encoder, false);
742       number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
743                                              __FUNCTION__, __LINE__);
744 
745       // Use new external encoder
746       error = ViE.codec->SetSendCodec(channel.videoChannel,
747                                       codec);
748       number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
749                                              __FUNCTION__, __LINE__);
750 
751       AutoTestSleep(kAutoTestSleepTimeMs / 2);
752 
753       /// **************************************************************
754       //  Testing finished. Tear down Video Engine
755       /// **************************************************************
756 
757       error = vie_external_codec->DeRegisterExternalSendCodec(
758                 channel.videoChannel, codec.plType);
759       number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
760                                              __FUNCTION__, __LINE__);
761       error = vie_external_codec->DeRegisterExternalReceiveCodec(
762                 channel.videoChannel, codec.plType);
763       number_of_errors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
764                                              __FUNCTION__, __LINE__);
765 
766       // Verify that the encoder and decoder has been used
767       encode_calls = ext_encoder.GetFunctionCalls();
768       number_of_errors += ViETest::TestError(encode_calls.InitEncode == 2,
769                                              "ERROR: %s at line %d",
770                                              __FUNCTION__, __LINE__);
771       number_of_errors += ViETest::TestError(encode_calls.Release == 2,
772                                              "ERROR: %s at line %d",
773                                              __FUNCTION__, __LINE__);
774       number_of_errors += ViETest::TestError(encode_calls.Encode > 30,
775                                              "ERROR: %s at line %d",
776                                              __FUNCTION__, __LINE__);
777       number_of_errors += ViETest::TestError(
778           encode_calls.RegisterEncodeCompleteCallback == 2,
779           "ERROR: %s at line %d", __FUNCTION__, __LINE__);
780       number_of_errors += ViETest::TestError(
781           encode_calls.SetChannelParameters > 1, "ERROR: %s at line %d",
782           __FUNCTION__, __LINE__);
783       number_of_errors += ViETest::TestError(encode_calls.SetRates > 1,
784                                              "ERROR: %s at line %d",
785                                              __FUNCTION__, __LINE__);
786       decode_calls = ext_decoder.GetFunctionCalls();
787       number_of_errors += ViETest::TestError(decode_calls.InitDecode == 2,
788                                              "ERROR: %s at line %d",
789                                              __FUNCTION__, __LINE__);
790       number_of_errors += ViETest::TestError(decode_calls.Release == 2,
791                                              "ERROR: %s at line %d",
792                                              __FUNCTION__, __LINE__);
793       number_of_errors += ViETest::TestError(decode_calls.Decode > 30,
794                                              "ERROR: %s at line %d",
795                                              __FUNCTION__, __LINE__);
796       number_of_errors += ViETest::TestError(
797           decode_calls.RegisterDecodeCompleteCallback == 2,
798           "ERROR: %s at line %d", __FUNCTION__, __LINE__);
799 
800       int remaining_interfaces = vie_external_codec->Release();
801       number_of_errors += ViETest::TestError(remaining_interfaces == 0,
802                                              "ERROR: %s at line %d",
803                                              __FUNCTION__, __LINE__);
804     }  // tbI420Encoder and ext_decoder goes out of scope.
805 
806     ViETest::Log("Using internal I420 codec");
807     AutoTestSleep(kAutoTestSleepTimeMs / 2);
808   }
809   if (number_of_errors > 0) {
810     // Test failed
811     ViETest::Log(" ");
812     ViETest::Log(" ERROR ViEExternalCodec Test FAILED!");
813     ViETest::Log(" Number of errors: %d", number_of_errors);
814     ViETest::Log("========================================");
815     ViETest::Log(" ");
816     return;
817   }
818 
819   ViETest::Log(" ");
820   ViETest::Log(" ViEExternalCodec Test PASSED!");
821   ViETest::Log("========================================");
822   ViETest::Log(" ");
823   return;
824 
825 #else
826   ViETest::Log(" ViEExternalCodec not enabled\n");
827   return;
828 #endif
829 }
830