media/webrtc/signaling/test/mediaconduit_unittests.cpp

branch
TOR_BUG_9701
changeset 10
ac0c01689b40
equal deleted inserted replaced
-1:000000000000 0:e603d309d007
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include <iostream>
6 #include <string>
7 #include <fstream>
8 #include <unistd.h>
9 #include <vector>
10 #include <math.h>
11
12 using namespace std;
13
14 #include "mozilla/Scoped.h"
15 #include <MediaConduitInterface.h>
16 #include "nsIEventTarget.h"
17 #include "FakeMediaStreamsImpl.h"
18
19 #define GTEST_HAS_RTTI 0
20 #include "gtest/gtest.h"
21 #include "gtest_utils.h"
22
23 #include "mtransport_test_utils.h"
24 MtransportTestUtils *test_utils;
25
26 //Video Frame Color
27 const int COLOR = 0x80; //Gray
28
29 //MWC RNG of George Marsaglia
30 //taken from xiph.org
31 static int32_t Rz, Rw;
32 static inline int32_t fast_rand(void)
33 {
34 Rz=36969*(Rz&65535)+(Rz>>16);
35 Rw=18000*(Rw&65535)+(Rw>>16);
36 return (Rz<<16)+Rw;
37 }
38
39 /**
40 * Global structure to store video test results.
41 */
42 struct VideoTestStats
43 {
44 int numRawFramesInserted;
45 int numFramesRenderedSuccessfully;
46 int numFramesRenderedWrongly;
47 };
48
49 VideoTestStats vidStatsGlobal={0,0,0};
50
51
52 /**
53 * A Dummy Video Conduit Tester.
54 * The test-case inserts a 640*480 grey imagerevery 33 milliseconds
55 * to the video-conduit for encoding and transporting.
56 */
57
58 class VideoSendAndReceive
59 {
60 public:
61 VideoSendAndReceive():width(640),
62 height(480)
63 {
64 }
65
66 ~VideoSendAndReceive()
67 {
68 }
69
70 void Init(mozilla::RefPtr<mozilla::VideoSessionConduit> aSession)
71 {
72 mSession = aSession;
73 }
74 void GenerateAndReadSamples()
75 {
76
77 int len = ((width * height) * 3 / 2);
78 uint8_t* frame = (uint8_t*) PR_MALLOC(len);
79 int numFrames = 121;
80 memset(frame, COLOR, len);
81
82 do
83 {
84 mSession->SendVideoFrame((unsigned char*)frame,
85 len,
86 width,
87 height,
88 mozilla::kVideoI420,
89 0);
90 PR_Sleep(PR_MillisecondsToInterval(33));
91 vidStatsGlobal.numRawFramesInserted++;
92 numFrames--;
93 } while(numFrames >= 0);
94 PR_Free(frame);
95 }
96
97 private:
98 mozilla::RefPtr<mozilla::VideoSessionConduit> mSession;
99 int width, height;
100 };
101
102
103
104 /**
105 * A Dummy AudioConduit Tester
106 * The test reads PCM samples of a standard test file and
107 * passws to audio-conduit for encoding, RTPfication and
108 * decoding ebery 10 milliseconds.
109 * This decoded samples are read-off the conduit for writing
110 * into output audio file in PCM format.
111 */
112 class AudioSendAndReceive
113 {
114 public:
115 static const unsigned int PLAYOUT_SAMPLE_FREQUENCY; //default is 16000
116 static const unsigned int PLAYOUT_SAMPLE_LENGTH; //default is 160000
117
118 AudioSendAndReceive()
119 {
120 }
121
122 ~AudioSendAndReceive()
123 {
124 }
125
126 void Init(mozilla::RefPtr<mozilla::AudioSessionConduit> aSession,
127 mozilla::RefPtr<mozilla::AudioSessionConduit> aOtherSession,
128 std::string fileIn, std::string fileOut)
129 {
130
131 mSession = aSession;
132 mOtherSession = aOtherSession;
133 iFile = fileIn;
134 oFile = fileOut;
135 }
136
137 //Kick start the test
138 void GenerateAndReadSamples();
139
140 private:
141
142 mozilla::RefPtr<mozilla::AudioSessionConduit> mSession;
143 mozilla::RefPtr<mozilla::AudioSessionConduit> mOtherSession;
144 std::string iFile;
145 std::string oFile;
146
147 int WriteWaveHeader(int rate, int channels, FILE* outFile);
148 int FinishWaveHeader(FILE* outFile);
149 void GenerateMusic(int16_t* buf, int len);
150 };
151
152 const unsigned int AudioSendAndReceive::PLAYOUT_SAMPLE_FREQUENCY = 16000;
153 const unsigned int AudioSendAndReceive::PLAYOUT_SAMPLE_LENGTH = 160000;
154
155 int AudioSendAndReceive::WriteWaveHeader(int rate, int channels, FILE* outFile)
156 {
157 //Hardcoded for 16 bit samples
158 unsigned char header[] = {
159 // File header
160 0x52, 0x49, 0x46, 0x46, // 'RIFF'
161 0x00, 0x00, 0x00, 0x00, // chunk size
162 0x57, 0x41, 0x56, 0x45, // 'WAVE'
163 // fmt chunk. We always write 16-bit samples.
164 0x66, 0x6d, 0x74, 0x20, // 'fmt '
165 0x10, 0x00, 0x00, 0x00, // chunk size
166 0x01, 0x00, // WAVE_FORMAT_PCM
167 0xFF, 0xFF, // channels
168 0xFF, 0xFF, 0xFF, 0xFF, // sample rate
169 0x00, 0x00, 0x00, 0x00, // data rate
170 0xFF, 0xFF, // frame size in bytes
171 0x10, 0x00, // bits per sample
172 // data chunk
173 0x64, 0x61, 0x74, 0x61, // 'data'
174 0xFE, 0xFF, 0xFF, 0x7F // chunk size
175 };
176
177 #define set_uint16le(buffer, value) \
178 (buffer)[0] = (value) & 0xff; \
179 (buffer)[1] = (value) >> 8;
180 #define set_uint32le(buffer, value) \
181 set_uint16le( (buffer), (value) & 0xffff ); \
182 set_uint16le( (buffer) + 2, (value) >> 16 );
183
184 // set dynamic header fields
185 set_uint16le(header + 22, channels);
186 set_uint32le(header + 24, rate);
187 set_uint16le(header + 32, channels*2);
188
189 size_t written = fwrite(header, 1, sizeof(header), outFile);
190 if (written != sizeof(header)) {
191 cerr << "Writing WAV header failed" << endl;
192 return -1;
193 }
194
195 return 0;
196 }
197
198 // Update the WAVE file header with the written length
199 int AudioSendAndReceive::FinishWaveHeader(FILE* outFile)
200 {
201 // Measure how much data we've written
202 long end = ftell(outFile);
203 if (end < 16) {
204 cerr << "Couldn't get output file length" << endl;
205 return (end < 0) ? end : -1;
206 }
207
208 // Update the header
209 unsigned char size[4];
210 int err = fseek(outFile, 40, SEEK_SET);
211 if (err < 0) {
212 cerr << "Couldn't seek to WAV file header." << endl;
213 return err;
214 }
215 set_uint32le(size, (end - 44) & 0xffffffff);
216 size_t written = fwrite(size, 1, sizeof(size), outFile);
217 if (written != sizeof(size)) {
218 cerr << "Couldn't write data size to WAV header" << endl;
219 return -1;
220 }
221
222 // Return to the end
223 err = fseek(outFile, 0, SEEK_END);
224 if (err < 0) {
225 cerr << "Couldn't seek to WAV file end." << endl;
226 return err;
227 }
228
229 return 0;
230 }
231
232 //Code from xiph.org to generate music of predefined length
233 void AudioSendAndReceive::GenerateMusic(short* buf, int len)
234 {
235 cerr <<" Generating Input Music " << endl;
236 int32_t a1,a2,b1,b2;
237 int32_t c1,c2,d1,d2;
238 int32_t i,j;
239 a1=b1=a2=b2=0;
240 c1=c2=d1=d2=0;
241 j=0;
242 /*60ms silence */
243 for(i=0;i<2880;i++)
244 {
245 buf[i*2]=buf[(i*2)+1]=0;
246 }
247 for(i=2880;i<len-1;i+=2)
248 {
249 int32_t r;
250 int32_t v1,v2;
251 v1=v2=(((j*((j>>12)^((j>>10|j>>12)&26&j>>7)))&128)+128)<<15;
252 r=fast_rand();v1+=r&65535;v1-=r>>16;
253 r=fast_rand();v2+=r&65535;v2-=r>>16;
254 b1=v1-a1+((b1*61+32)>>6);a1=v1;
255 b2=v2-a2+((b2*61+32)>>6);a2=v2;
256 c1=(30*(c1+b1+d1)+32)>>6;d1=b1;
257 c2=(30*(c2+b2+d2)+32)>>6;d2=b2;
258 v1=(c1+128)>>8;
259 v2=(c2+128)>>8;
260 buf[i]=v1>32767?32767:(v1<-32768?-32768:v1);
261 buf[i+1]=v2>32767?32767:(v2<-32768?-32768:v2);
262 if(i%6==0)j++;
263 }
264 cerr << "Generating Input Music Done " << endl;
265 }
266
267 //Hardcoded for 16 bit samples for now
268 void AudioSendAndReceive::GenerateAndReadSamples()
269 {
270 int16_t audioInput[PLAYOUT_SAMPLE_LENGTH];
271 int16_t audioOutput[PLAYOUT_SAMPLE_LENGTH];
272 short* inbuf;
273 int sampleLengthDecoded = 0;
274 unsigned int SAMPLES = (PLAYOUT_SAMPLE_FREQUENCY * 10); //10 seconds
275 int CHANNELS = 1; //mono audio
276 int sampleLengthInBytes = sizeof(audioInput);
277 //generated audio buffer
278 inbuf = (short *)moz_xmalloc(sizeof(short)*SAMPLES*CHANNELS);
279 memset(audioInput,0,sampleLengthInBytes);
280 memset(audioOutput,0,sampleLengthInBytes);
281 MOZ_ASSERT(SAMPLES <= PLAYOUT_SAMPLE_LENGTH);
282
283 FILE* inFile = fopen( iFile.c_str(), "wb+");
284 if(!inFile) {
285 cerr << "Input File Creation Failed " << endl;
286 return;
287 }
288
289 FILE* outFile = fopen( oFile.c_str(), "wb+");
290 if(!outFile) {
291 cerr << "Output File Creation Failed " << endl;
292 return;
293 }
294
295 //Create input file with the music
296 WriteWaveHeader(PLAYOUT_SAMPLE_FREQUENCY, 1, inFile);
297 GenerateMusic(inbuf, SAMPLES);
298 fwrite(inbuf,1,SAMPLES*sizeof(inbuf[0])*CHANNELS,inFile);
299 FinishWaveHeader(inFile);
300 fclose(inFile);
301
302 WriteWaveHeader(PLAYOUT_SAMPLE_FREQUENCY, 1, outFile);
303 unsigned int numSamplesReadFromInput = 0;
304 do
305 {
306 if(!memcpy(audioInput, inbuf, sampleLengthInBytes))
307 {
308 return;
309 }
310
311 numSamplesReadFromInput += PLAYOUT_SAMPLE_LENGTH;
312 inbuf += PLAYOUT_SAMPLE_LENGTH;
313
314 mSession->SendAudioFrame(audioInput,
315 PLAYOUT_SAMPLE_LENGTH,
316 PLAYOUT_SAMPLE_FREQUENCY,10);
317
318 PR_Sleep(PR_MillisecondsToInterval(10));
319 mOtherSession->GetAudioFrame(audioOutput, PLAYOUT_SAMPLE_FREQUENCY,
320 10, sampleLengthDecoded);
321 if(sampleLengthDecoded == 0)
322 {
323 cerr << " Zero length Sample " << endl;
324 }
325
326 int wrote_ = fwrite (audioOutput, 1 , sampleLengthInBytes, outFile);
327 if(wrote_ != sampleLengthInBytes)
328 {
329 cerr << "Couldn't Write " << sampleLengthInBytes << "bytes" << endl;
330 break;
331 }
332 }while(numSamplesReadFromInput < SAMPLES);
333
334 FinishWaveHeader(outFile);
335 fclose(outFile);
336 }
337
338 /**
339 * Dummy Video Target for the conduit
340 * This class acts as renderer attached to the video conuit
341 * As of today we just verify if the frames rendered are exactly
342 * the same as frame inserted at the first place
343 */
344 class DummyVideoTarget: public mozilla::VideoRenderer
345 {
346 public:
347 DummyVideoTarget()
348 {
349 }
350
351 virtual ~DummyVideoTarget()
352 {
353 }
354
355
356 void RenderVideoFrame(const unsigned char* buffer,
357 unsigned int buffer_size,
358 uint32_t time_stamp,
359 int64_t render_time,
360 const mozilla::ImageHandle& handle)
361 {
362 //write the frame to the file
363 if(VerifyFrame(buffer, buffer_size) == 0)
364 {
365 vidStatsGlobal.numFramesRenderedSuccessfully++;
366 } else
367 {
368 vidStatsGlobal.numFramesRenderedWrongly++;
369 }
370 }
371
372 void FrameSizeChange(unsigned int, unsigned int, unsigned int)
373 {
374 //do nothing
375 }
376
377 //This is hardcoded to check if the contents of frame is COLOR
378 // as we set while sending.
379 int VerifyFrame(const unsigned char* buffer, unsigned int buffer_size)
380 {
381 int good = 0;
382 for(int i=0; i < (int) buffer_size; i++)
383 {
384 if(buffer[i] == COLOR)
385 {
386 ++good;
387 }
388 else
389 {
390 --good;
391 }
392 }
393 return 0;
394 }
395
396 };
397
398 /**
399 * Fake Audio and Video External Transport Class
400 * The functions in this class will be invoked by the conduit
401 * when it has RTP/RTCP frame to transmit.
402 * For everty RTP/RTCP frame we receive, we pass it back
403 * to the conduit for eventual decoding and rendering.
404 */
405 class FakeMediaTransport : public mozilla::TransportInterface
406 {
407 public:
408 FakeMediaTransport():numPkts(0),
409 mAudio(false),
410 mVideo(false)
411 {
412 }
413
414 ~FakeMediaTransport()
415 {
416 }
417
418 virtual nsresult SendRtpPacket(const void* data, int len)
419 {
420 ++numPkts;
421 if(mAudio)
422 {
423 mOtherAudioSession->ReceivedRTPPacket(data,len);
424 } else
425 {
426 mOtherVideoSession->ReceivedRTPPacket(data,len);
427 }
428 return NS_OK;
429 }
430
431 virtual nsresult SendRtcpPacket(const void* data, int len)
432 {
433 if(mAudio)
434 {
435 mOtherAudioSession->ReceivedRTCPPacket(data,len);
436 } else
437 {
438 mOtherVideoSession->ReceivedRTCPPacket(data,len);
439 }
440 return NS_OK;
441 }
442
443 //Treat this object as Audio Transport
444 void SetAudioSession(mozilla::RefPtr<mozilla::AudioSessionConduit> aSession,
445 mozilla::RefPtr<mozilla::AudioSessionConduit>
446 aOtherSession)
447 {
448 mAudioSession = aSession;
449 mOtherAudioSession = aOtherSession;
450 mAudio = true;
451 }
452
453 // Treat this object as Video Transport
454 void SetVideoSession(mozilla::RefPtr<mozilla::VideoSessionConduit> aSession,
455 mozilla::RefPtr<mozilla::VideoSessionConduit>
456 aOtherSession)
457 {
458 mVideoSession = aSession;
459 mOtherVideoSession = aOtherSession;
460 mVideo = true;
461 }
462
463 private:
464 mozilla::RefPtr<mozilla::AudioSessionConduit> mAudioSession;
465 mozilla::RefPtr<mozilla::VideoSessionConduit> mVideoSession;
466 mozilla::RefPtr<mozilla::VideoSessionConduit> mOtherVideoSession;
467 mozilla::RefPtr<mozilla::AudioSessionConduit> mOtherAudioSession;
468 int numPkts;
469 bool mAudio, mVideo;
470 };
471
472
473 namespace {
474
475 class TransportConduitTest : public ::testing::Test
476 {
477 public:
478 TransportConduitTest()
479 {
480 //input and output file names
481 iAudiofilename = "input.wav";
482 oAudiofilename = "recorded.wav";
483 }
484
485 ~TransportConduitTest()
486 {
487 }
488
489 //1. Dump audio samples to dummy external transport
490 void TestDummyAudioAndTransport()
491 {
492 //get pointer to AudioSessionConduit
493 int err=0;
494 mAudioSession = mozilla::AudioSessionConduit::Create(nullptr);
495 if( !mAudioSession )
496 ASSERT_NE(mAudioSession, (void*)nullptr);
497
498 mAudioSession2 = mozilla::AudioSessionConduit::Create(nullptr);
499 if( !mAudioSession2 )
500 ASSERT_NE(mAudioSession2, (void*)nullptr);
501
502 FakeMediaTransport* xport = new FakeMediaTransport();
503 ASSERT_NE(xport, (void*)nullptr);
504 xport->SetAudioSession(mAudioSession, mAudioSession2);
505 mAudioTransport = xport;
506
507 // attach the transport to audio-conduit
508 err = mAudioSession->AttachTransport(mAudioTransport);
509 ASSERT_EQ(mozilla::kMediaConduitNoError, err);
510 err = mAudioSession2->AttachTransport(mAudioTransport);
511 ASSERT_EQ(mozilla::kMediaConduitNoError, err);
512
513 //configure send and recv codecs on the audio-conduit
514 //mozilla::AudioCodecConfig cinst1(124,"PCMU",8000,80,1,64000);
515 mozilla::AudioCodecConfig cinst1(124,"opus",48000,960,1,64000);
516 mozilla::AudioCodecConfig cinst2(125,"L16",16000,320,1,256000);
517
518
519 std::vector<mozilla::AudioCodecConfig*> rcvCodecList;
520 rcvCodecList.push_back(&cinst1);
521 rcvCodecList.push_back(&cinst2);
522
523 err = mAudioSession->ConfigureSendMediaCodec(&cinst1);
524 ASSERT_EQ(mozilla::kMediaConduitNoError, err);
525 err = mAudioSession->ConfigureRecvMediaCodecs(rcvCodecList);
526 ASSERT_EQ(mozilla::kMediaConduitNoError, err);
527
528 err = mAudioSession2->ConfigureSendMediaCodec(&cinst1);
529 ASSERT_EQ(mozilla::kMediaConduitNoError, err);
530 err = mAudioSession2->ConfigureRecvMediaCodecs(rcvCodecList);
531 ASSERT_EQ(mozilla::kMediaConduitNoError, err);
532
533 //start generating samples
534 audioTester.Init(mAudioSession,mAudioSession2, iAudiofilename,oAudiofilename);
535 cerr << " ******************************************************** " << endl;
536 cerr << " Generating Audio Samples " << endl;
537 cerr << " ******************************************************** " << endl;
538 PR_Sleep(PR_SecondsToInterval(2));
539 audioTester.GenerateAndReadSamples();
540 PR_Sleep(PR_SecondsToInterval(2));
541 cerr << " ******************************************************** " << endl;
542 cerr << " Input Audio File " << iAudiofilename << endl;
543 cerr << " Output Audio File " << oAudiofilename << endl;
544 cerr << " ******************************************************** " << endl;
545 }
546
547 //2. Dump audio samples to dummy external transport
548 void TestDummyVideoAndTransport()
549 {
550 int err = 0;
551 //get pointer to VideoSessionConduit
552 mVideoSession = mozilla::VideoSessionConduit::Create(nullptr);
553 if( !mVideoSession )
554 ASSERT_NE(mVideoSession, (void*)nullptr);
555
556 // This session is for other one
557 mVideoSession2 = mozilla::VideoSessionConduit::Create(nullptr);
558 if( !mVideoSession2 )
559 ASSERT_NE(mVideoSession2,(void*)nullptr);
560
561 mVideoRenderer = new DummyVideoTarget();
562 ASSERT_NE(mVideoRenderer, (void*)nullptr);
563
564 FakeMediaTransport* xport = new FakeMediaTransport();
565 ASSERT_NE(xport, (void*)nullptr);
566 xport->SetVideoSession(mVideoSession,mVideoSession2);
567 mVideoTransport = xport;
568
569 // attach the transport and renderer to video-conduit
570 err = mVideoSession2->AttachRenderer(mVideoRenderer);
571 ASSERT_EQ(mozilla::kMediaConduitNoError, err);
572 err = mVideoSession->AttachTransport(mVideoTransport);
573 ASSERT_EQ(mozilla::kMediaConduitNoError, err);
574 err = mVideoSession2->AttachTransport(mVideoTransport);
575 ASSERT_EQ(mozilla::kMediaConduitNoError, err);
576
577 //configure send and recv codecs on theconduit
578 mozilla::VideoCodecConfig cinst1(120, "VP8", 0);
579 mozilla::VideoCodecConfig cinst2(124, "I420", 0);
580
581
582 std::vector<mozilla::VideoCodecConfig* > rcvCodecList;
583 rcvCodecList.push_back(&cinst1);
584 rcvCodecList.push_back(&cinst2);
585
586 err = mVideoSession->ConfigureSendMediaCodec(&cinst1);
587 ASSERT_EQ(mozilla::kMediaConduitNoError, err);
588
589 err = mVideoSession2->ConfigureRecvMediaCodecs(rcvCodecList);
590 ASSERT_EQ(mozilla::kMediaConduitNoError, err);
591
592 //start generating samples
593 cerr << " *************************************************" << endl;
594 cerr << " Starting the Video Sample Generation " << endl;
595 cerr << " *************************************************" << endl;
596 PR_Sleep(PR_SecondsToInterval(2));
597 videoTester.Init(mVideoSession);
598 videoTester.GenerateAndReadSamples();
599 PR_Sleep(PR_SecondsToInterval(2));
600 cerr << " **************************************************" << endl;
601 cerr << " Done With The Testing " << endl;
602 cerr << " VIDEO TEST STATS " << endl;
603 cerr << " Num Raw Frames Inserted: "<<
604 vidStatsGlobal.numRawFramesInserted << endl;
605 cerr << " Num Frames Successfully Rendered: "<<
606 vidStatsGlobal.numFramesRenderedSuccessfully << endl;
607 cerr << " Num Frames Wrongly Rendered: "<<
608 vidStatsGlobal.numFramesRenderedWrongly << endl;
609
610 cerr << " Done With The Testing " << endl;
611
612 cerr << " **************************************************" << endl;
613 ASSERT_EQ(0, vidStatsGlobal.numFramesRenderedWrongly);
614 ASSERT_EQ(vidStatsGlobal.numRawFramesInserted,
615 vidStatsGlobal.numFramesRenderedSuccessfully);
616 }
617
618 void TestVideoConduitCodecAPI()
619 {
620 int err = 0;
621 mozilla::RefPtr<mozilla::VideoSessionConduit> mVideoSession;
622 //get pointer to VideoSessionConduit
623 mVideoSession = mozilla::VideoSessionConduit::Create(nullptr);
624 if( !mVideoSession )
625 ASSERT_NE(mVideoSession, (void*)nullptr);
626
627 //Test Configure Recv Codec APIS
628 cerr << " *************************************************" << endl;
629 cerr << " Test Receive Codec Configuration API Now " << endl;
630 cerr << " *************************************************" << endl;
631
632 std::vector<mozilla::VideoCodecConfig* > rcvCodecList;
633
634 //Same APIs
635 cerr << " *************************************************" << endl;
636 cerr << " 1. Same Codec (VP8) Repeated Twice " << endl;
637 cerr << " *************************************************" << endl;
638
639 mozilla::VideoCodecConfig cinst1(120, "VP8", 0);
640 mozilla::VideoCodecConfig cinst2(120, "VP8", 0);
641 rcvCodecList.push_back(&cinst1);
642 rcvCodecList.push_back(&cinst2);
643 err = mVideoSession->ConfigureRecvMediaCodecs(rcvCodecList);
644 EXPECT_NE(err,mozilla::kMediaConduitNoError);
645 rcvCodecList.pop_back();
646 rcvCodecList.pop_back();
647
648
649 PR_Sleep(PR_SecondsToInterval(2));
650 cerr << " *************************************************" << endl;
651 cerr << " 2. Codec With Invalid Payload Names " << endl;
652 cerr << " *************************************************" << endl;
653 cerr << " Setting payload 1 with name: I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676" << endl;
654 cerr << " Setting payload 2 with name of zero length" << endl;
655
656 mozilla::VideoCodecConfig cinst3(124, "I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676", 0);
657 mozilla::VideoCodecConfig cinst4(124, "", 0);
658
659 rcvCodecList.push_back(&cinst3);
660 rcvCodecList.push_back(&cinst4);
661
662 err = mVideoSession->ConfigureRecvMediaCodecs(rcvCodecList);
663 EXPECT_TRUE(err != mozilla::kMediaConduitNoError);
664 rcvCodecList.pop_back();
665 rcvCodecList.pop_back();
666
667
668 PR_Sleep(PR_SecondsToInterval(2));
669 cerr << " *************************************************" << endl;
670 cerr << " 3. Null Codec Parameter " << endl;
671 cerr << " *************************************************" << endl;
672
673 rcvCodecList.push_back(0);
674
675 err = mVideoSession->ConfigureRecvMediaCodecs(rcvCodecList);
676 EXPECT_TRUE(err != mozilla::kMediaConduitNoError);
677 rcvCodecList.pop_back();
678
679 cerr << " *************************************************" << endl;
680 cerr << " Test Send Codec Configuration API Now " << endl;
681 cerr << " *************************************************" << endl;
682
683 cerr << " *************************************************" << endl;
684 cerr << " 1. Same Codec (VP8) Repeated Twice " << endl;
685 cerr << " *************************************************" << endl;
686
687
688 err = mVideoSession->ConfigureSendMediaCodec(&cinst1);
689 EXPECT_EQ(mozilla::kMediaConduitNoError, err);
690 err = mVideoSession->ConfigureSendMediaCodec(&cinst1);
691 EXPECT_EQ(mozilla::kMediaConduitCodecInUse, err);
692
693
694 cerr << " *************************************************" << endl;
695 cerr << " 2. Codec With Invalid Payload Names " << endl;
696 cerr << " *************************************************" << endl;
697 cerr << " Setting payload with name: I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676" << endl;
698
699 err = mVideoSession->ConfigureSendMediaCodec(&cinst3);
700 EXPECT_TRUE(err != mozilla::kMediaConduitNoError);
701
702 cerr << " *************************************************" << endl;
703 cerr << " 3. Null Codec Parameter " << endl;
704 cerr << " *************************************************" << endl;
705
706 err = mVideoSession->ConfigureSendMediaCodec(nullptr);
707 EXPECT_TRUE(err != mozilla::kMediaConduitNoError);
708
709 }
710
711 void DumpMaxFs(int orig_width, int orig_height, int max_fs,
712 int new_width, int new_height)
713 {
714 cerr << "Applying max_fs=" << max_fs << " to input resolution " <<
715 orig_width << "x" << orig_height << endl;
716 cerr << "New resolution: " << new_width << "x" << new_height << endl;
717 cerr << endl;
718 }
719
720 // Calculate new resolution for sending video by applying max-fs constraint.
721 void GetVideoResolutionWithMaxFs(int orig_width, int orig_height, int max_fs,
722 int *new_width, int *new_height)
723 {
724 int err = 0;
725
726 // Get pointer to VideoSessionConduit.
727 mVideoSession = mozilla::VideoSessionConduit::Create(nullptr);
728 if( !mVideoSession )
729 ASSERT_NE(mVideoSession, (void*)nullptr);
730
731 // Configure send codecs on the conduit.
732 mozilla::VideoCodecConfig cinst1(120, "VP8", 0, max_fs, 0);
733
734 err = mVideoSession->ConfigureSendMediaCodec(&cinst1);
735 ASSERT_EQ(mozilla::kMediaConduitNoError, err);
736
737 // Send one frame.
738 MOZ_ASSERT(!(orig_width & 1));
739 MOZ_ASSERT(!(orig_height & 1));
740 int len = ((orig_width * orig_height) * 3 / 2);
741 uint8_t* frame = (uint8_t*) PR_MALLOC(len);
742
743 memset(frame, COLOR, len);
744 mVideoSession->SendVideoFrame((unsigned char*)frame,
745 len,
746 orig_width,
747 orig_height,
748 mozilla::kVideoI420,
749 0);
750 PR_Free(frame);
751
752 // Get the new resolution as adjusted by the max-fs constraint.
753 *new_width = mVideoSession->SendingWidth();
754 *new_height = mVideoSession->SendingHeight();
755 }
756
757 void TestVideoConduitMaxFs()
758 {
759 int orig_width, orig_height, width, height, max_fs;
760
761 // No limitation.
762 cerr << "Test no max-fs limition" << endl;
763 orig_width = 640;
764 orig_height = 480;
765 max_fs = 0;
766 GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, &width, &height);
767 DumpMaxFs(orig_width, orig_height, max_fs, width, height);
768 ASSERT_EQ(width, 640);
769 ASSERT_EQ(height, 480);
770
771 // VGA to QVGA.
772 cerr << "Test resizing from VGA to QVGA" << endl;
773 orig_width = 640;
774 orig_height = 480;
775 max_fs = 300;
776 GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, &width, &height);
777 DumpMaxFs(orig_width, orig_height, max_fs, width, height);
778 ASSERT_EQ(width, 320);
779 ASSERT_EQ(height, 240);
780
781 // Extreme input resolution.
782 cerr << "Test extreme input resolution" << endl;
783 orig_width = 3072;
784 orig_height = 100;
785 max_fs = 300;
786 GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, &width, &height);
787 DumpMaxFs(orig_width, orig_height, max_fs, width, height);
788 ASSERT_EQ(width, 768);
789 ASSERT_EQ(height, 26);
790
791 // Small max-fs.
792 cerr << "Test small max-fs (case 1)" << endl;
793 orig_width = 8;
794 orig_height = 32;
795 max_fs = 1;
796 GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, &width, &height);
797 DumpMaxFs(orig_width, orig_height, max_fs, width, height);
798 ASSERT_EQ(width, 4);
799 ASSERT_EQ(height, 16);
800
801 // Small max-fs.
802 cerr << "Test small max-fs (case 2)" << endl;
803 orig_width = 4;
804 orig_height = 50;
805 max_fs = 1;
806 GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, &width, &height);
807 DumpMaxFs(orig_width, orig_height, max_fs, width, height);
808 ASSERT_EQ(width, 2);
809 ASSERT_EQ(height, 16);
810
811 // Small max-fs.
812 cerr << "Test small max-fs (case 3)" << endl;
813 orig_width = 872;
814 orig_height = 136;
815 max_fs = 3;
816 GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, &width, &height);
817 DumpMaxFs(orig_width, orig_height, max_fs, width, height);
818 ASSERT_EQ(width, 48);
819 ASSERT_EQ(height, 8);
820
821 // Small max-fs.
822 cerr << "Test small max-fs (case 4)" << endl;
823 orig_width = 160;
824 orig_height = 8;
825 max_fs = 5;
826 GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, &width, &height);
827 DumpMaxFs(orig_width, orig_height, max_fs, width, height);
828 ASSERT_EQ(width, 80);
829 ASSERT_EQ(height, 4);
830
831 // Extremely small width and height(see bug 919979).
832 cerr << "Test with extremely small width and height" << endl;
833 orig_width = 2;
834 orig_height = 2;
835 max_fs = 5;
836 GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, &width, &height);
837 DumpMaxFs(orig_width, orig_height, max_fs, width, height);
838 ASSERT_EQ(width, 2);
839 ASSERT_EQ(height, 2);
840
841 // Random values.
842 cerr << "Test with random values" << endl;
843 for (int i = 0; i < 30; i++) {
844 cerr << ".";
845 max_fs = rand() % 1000;
846 orig_width = ((rand() % 2000) & ~1) + 2;
847 orig_height = ((rand() % 2000) & ~1) + 2;
848
849 GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs,
850 &width, &height);
851 if (max_fs > 0 &&
852 ceil(width / 16.) * ceil(height / 16.) > max_fs) {
853 DumpMaxFs(orig_width, orig_height, max_fs, width, height);
854 ADD_FAILURE();
855 }
856 if ((width & 1) || (height & 1)) {
857 DumpMaxFs(orig_width, orig_height, max_fs, width, height);
858 ADD_FAILURE();
859 }
860 }
861 cerr << endl;
862 }
863
864 private:
865 //Audio Conduit Test Objects
866 mozilla::RefPtr<mozilla::AudioSessionConduit> mAudioSession;
867 mozilla::RefPtr<mozilla::AudioSessionConduit> mAudioSession2;
868 mozilla::RefPtr<mozilla::TransportInterface> mAudioTransport;
869 AudioSendAndReceive audioTester;
870
871 //Video Conduit Test Objects
872 mozilla::RefPtr<mozilla::VideoSessionConduit> mVideoSession;
873 mozilla::RefPtr<mozilla::VideoSessionConduit> mVideoSession2;
874 mozilla::RefPtr<mozilla::VideoRenderer> mVideoRenderer;
875 mozilla::RefPtr<mozilla::TransportInterface> mVideoTransport;
876 VideoSendAndReceive videoTester;
877
878 std::string fileToPlay;
879 std::string fileToRecord;
880 std::string iAudiofilename;
881 std::string oAudiofilename;
882 };
883
884
885 // Test 1: Test Dummy External Xport
886 TEST_F(TransportConduitTest, TestDummyAudioWithTransport) {
887 TestDummyAudioAndTransport();
888 }
889
890 // Test 2: Test Dummy External Xport
891 TEST_F(TransportConduitTest, TestDummyVideoWithTransport) {
892 TestDummyVideoAndTransport();
893 }
894
895 TEST_F(TransportConduitTest, TestVideoConduitCodecAPI) {
896 TestVideoConduitCodecAPI();
897 }
898
899 TEST_F(TransportConduitTest, TestVideoConduitMaxFs) {
900 TestVideoConduitMaxFs();
901 }
902
903 } // end namespace
904
905 int main(int argc, char **argv)
906 {
907 // This test can cause intermittent oranges on the builders
908 CHECK_ENVIRONMENT_FLAG("MOZ_WEBRTC_MEDIACONDUIT_TESTS")
909
910 test_utils = new MtransportTestUtils();
911 ::testing::InitGoogleTest(&argc, argv);
912 int rv = RUN_ALL_TESTS();
913 delete test_utils;
914 return rv;
915 }
916
917

mercurial