media/webrtc/signaling/test/mediaconduit_unittests.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     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/. */
     5 #include <iostream>
     6 #include <string>
     7 #include <fstream>
     8 #include <unistd.h>
     9 #include <vector>
    10 #include <math.h>
    12 using namespace std;
    14 #include "mozilla/Scoped.h"
    15 #include <MediaConduitInterface.h>
    16 #include "nsIEventTarget.h"
    17 #include "FakeMediaStreamsImpl.h"
    19 #define GTEST_HAS_RTTI 0
    20 #include "gtest/gtest.h"
    21 #include "gtest_utils.h"
    23 #include "mtransport_test_utils.h"
    24 MtransportTestUtils *test_utils;
    26 //Video Frame Color
    27 const int COLOR = 0x80; //Gray
    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 }
    39 /**
    40   * Global structure to store video test results.
    41   */
    42 struct VideoTestStats
    43 {
    44  int numRawFramesInserted;
    45  int numFramesRenderedSuccessfully;
    46  int numFramesRenderedWrongly;
    47 };
    49 VideoTestStats vidStatsGlobal={0,0,0};
    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  */
    58 class VideoSendAndReceive
    59 {
    60 public:
    61   VideoSendAndReceive():width(640),
    62                         height(480)
    63   {
    64   }
    66   ~VideoSendAndReceive()
    67   {
    68   }
    70   void Init(mozilla::RefPtr<mozilla::VideoSessionConduit> aSession)
    71   {
    72         mSession = aSession;
    73   }
    74   void GenerateAndReadSamples()
    75   {
    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);
    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   }
    97 private:
    98 mozilla::RefPtr<mozilla::VideoSessionConduit> mSession;
    99 int width, height;
   100 };
   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
   118   AudioSendAndReceive()
   119   {
   120   }
   122   ~AudioSendAndReceive()
   123   {
   124   }
   126  void Init(mozilla::RefPtr<mozilla::AudioSessionConduit> aSession,
   127            mozilla::RefPtr<mozilla::AudioSessionConduit> aOtherSession,
   128            std::string fileIn, std::string fileOut)
   129   {
   131     mSession = aSession;
   132     mOtherSession = aOtherSession;
   133     iFile = fileIn;
   134     oFile = fileOut;
   135  }
   137   //Kick start the test
   138   void GenerateAndReadSamples();
   140 private:
   142   mozilla::RefPtr<mozilla::AudioSessionConduit> mSession;
   143   mozilla::RefPtr<mozilla::AudioSessionConduit> mOtherSession;
   144   std::string iFile;
   145   std::string oFile;
   147   int WriteWaveHeader(int rate, int channels, FILE* outFile);
   148   int FinishWaveHeader(FILE* outFile);
   149   void GenerateMusic(int16_t* buf, int len);
   150 };
   152 const unsigned int AudioSendAndReceive::PLAYOUT_SAMPLE_FREQUENCY = 16000;
   153 const unsigned int AudioSendAndReceive::PLAYOUT_SAMPLE_LENGTH  = 160000;
   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   };
   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 );
   184   // set dynamic header fields
   185   set_uint16le(header + 22, channels);
   186   set_uint32le(header + 24, rate);
   187   set_uint16le(header + 32, channels*2);
   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   }
   195   return 0;
   196 }
   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   }
   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   }
   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   }
   229   return 0;
   230 }
   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 }
   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);
   283    FILE* inFile = fopen( iFile.c_str(), "wb+");
   284    if(!inFile) {
   285      cerr << "Input File Creation Failed " << endl;
   286      return;
   287    }
   289    FILE* outFile = fopen( oFile.c_str(), "wb+");
   290    if(!outFile) {
   291      cerr << "Output File Creation Failed " << endl;
   292      return;
   293    }
   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);
   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     }
   311     numSamplesReadFromInput += PLAYOUT_SAMPLE_LENGTH;
   312     inbuf += PLAYOUT_SAMPLE_LENGTH;
   314     mSession->SendAudioFrame(audioInput,
   315                              PLAYOUT_SAMPLE_LENGTH,
   316                              PLAYOUT_SAMPLE_FREQUENCY,10);
   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     }
   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);
   334    FinishWaveHeader(outFile);
   335    fclose(outFile);
   336 }
   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   }
   351   virtual ~DummyVideoTarget()
   352   {
   353   }
   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  }
   372  void FrameSizeChange(unsigned int, unsigned int, unsigned int)
   373  {
   374     //do nothing
   375  }
   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  }
   396 };
   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   }
   414   ~FakeMediaTransport()
   415   {
   416   }
   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   }
   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   }
   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   }
   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   }
   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 };
   473 namespace {
   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   }
   485   ~TransportConduitTest()
   486   {
   487   }
   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);
   498     mAudioSession2 = mozilla::AudioSessionConduit::Create(nullptr);
   499     if( !mAudioSession2 )
   500       ASSERT_NE(mAudioSession2, (void*)nullptr);
   502     FakeMediaTransport* xport = new FakeMediaTransport();
   503     ASSERT_NE(xport, (void*)nullptr);
   504     xport->SetAudioSession(mAudioSession, mAudioSession2);
   505     mAudioTransport = xport;
   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);
   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);
   519     std::vector<mozilla::AudioCodecConfig*> rcvCodecList;
   520     rcvCodecList.push_back(&cinst1);
   521     rcvCodecList.push_back(&cinst2);
   523     err = mAudioSession->ConfigureSendMediaCodec(&cinst1);
   524     ASSERT_EQ(mozilla::kMediaConduitNoError, err);
   525     err = mAudioSession->ConfigureRecvMediaCodecs(rcvCodecList);
   526     ASSERT_EQ(mozilla::kMediaConduitNoError, err);
   528     err = mAudioSession2->ConfigureSendMediaCodec(&cinst1);
   529     ASSERT_EQ(mozilla::kMediaConduitNoError, err);
   530     err = mAudioSession2->ConfigureRecvMediaCodecs(rcvCodecList);
   531     ASSERT_EQ(mozilla::kMediaConduitNoError, err);
   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   }
   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);
   556    // This session is for other one
   557     mVideoSession2 = mozilla::VideoSessionConduit::Create(nullptr);
   558     if( !mVideoSession2 )
   559       ASSERT_NE(mVideoSession2,(void*)nullptr);
   561     mVideoRenderer = new DummyVideoTarget();
   562     ASSERT_NE(mVideoRenderer, (void*)nullptr);
   564     FakeMediaTransport* xport = new FakeMediaTransport();
   565     ASSERT_NE(xport, (void*)nullptr);
   566     xport->SetVideoSession(mVideoSession,mVideoSession2);
   567     mVideoTransport = xport;
   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);
   577     //configure send and recv codecs on theconduit
   578     mozilla::VideoCodecConfig cinst1(120, "VP8", 0);
   579     mozilla::VideoCodecConfig cinst2(124, "I420", 0);
   582     std::vector<mozilla::VideoCodecConfig* > rcvCodecList;
   583     rcvCodecList.push_back(&cinst1);
   584     rcvCodecList.push_back(&cinst2);
   586     err = mVideoSession->ConfigureSendMediaCodec(&cinst1);
   587     ASSERT_EQ(mozilla::kMediaConduitNoError, err);
   589     err = mVideoSession2->ConfigureRecvMediaCodecs(rcvCodecList);
   590     ASSERT_EQ(mozilla::kMediaConduitNoError, err);
   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;
   610     cerr << "    Done With The Testing  " << endl;
   612     cerr << "   **************************************************" << endl;
   613     ASSERT_EQ(0, vidStatsGlobal.numFramesRenderedWrongly);
   614     ASSERT_EQ(vidStatsGlobal.numRawFramesInserted,
   615         vidStatsGlobal.numFramesRenderedSuccessfully);
   616   }
   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);
   627     //Test Configure Recv Codec APIS
   628     cerr << "   *************************************************" << endl;
   629     cerr << "    Test Receive Codec Configuration API Now " << endl;
   630     cerr << "   *************************************************" << endl;
   632     std::vector<mozilla::VideoCodecConfig* > rcvCodecList;
   634     //Same APIs
   635     cerr << "   *************************************************" << endl;
   636     cerr << "    1. Same Codec (VP8) Repeated Twice " << endl;
   637     cerr << "   *************************************************" << endl;
   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();
   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;
   656     mozilla::VideoCodecConfig cinst3(124, "I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676", 0);
   657     mozilla::VideoCodecConfig cinst4(124, "", 0);
   659     rcvCodecList.push_back(&cinst3);
   660     rcvCodecList.push_back(&cinst4);
   662     err = mVideoSession->ConfigureRecvMediaCodecs(rcvCodecList);
   663     EXPECT_TRUE(err != mozilla::kMediaConduitNoError);
   664     rcvCodecList.pop_back();
   665     rcvCodecList.pop_back();
   668     PR_Sleep(PR_SecondsToInterval(2));
   669     cerr << "   *************************************************" << endl;
   670     cerr << "    3. Null Codec Parameter  " << endl;
   671     cerr << "   *************************************************" << endl;
   673     rcvCodecList.push_back(0);
   675     err = mVideoSession->ConfigureRecvMediaCodecs(rcvCodecList);
   676     EXPECT_TRUE(err != mozilla::kMediaConduitNoError);
   677     rcvCodecList.pop_back();
   679     cerr << "   *************************************************" << endl;
   680     cerr << "    Test Send Codec Configuration API Now " << endl;
   681     cerr << "   *************************************************" << endl;
   683     cerr << "   *************************************************" << endl;
   684     cerr << "    1. Same Codec (VP8) Repeated Twice " << endl;
   685     cerr << "   *************************************************" << endl;
   688     err = mVideoSession->ConfigureSendMediaCodec(&cinst1);
   689     EXPECT_EQ(mozilla::kMediaConduitNoError, err);
   690     err = mVideoSession->ConfigureSendMediaCodec(&cinst1);
   691     EXPECT_EQ(mozilla::kMediaConduitCodecInUse, err);
   694     cerr << "   *************************************************" << endl;
   695     cerr << "    2. Codec With Invalid Payload Names " << endl;
   696     cerr << "   *************************************************" << endl;
   697     cerr << "   Setting payload with name: I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676" << endl;
   699     err = mVideoSession->ConfigureSendMediaCodec(&cinst3);
   700     EXPECT_TRUE(err != mozilla::kMediaConduitNoError);
   702     cerr << "   *************************************************" << endl;
   703     cerr << "    3. Null Codec Parameter  " << endl;
   704     cerr << "   *************************************************" << endl;
   706     err = mVideoSession->ConfigureSendMediaCodec(nullptr);
   707     EXPECT_TRUE(err != mozilla::kMediaConduitNoError);
   709   }
   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   }
   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;
   726     // Get pointer to VideoSessionConduit.
   727     mVideoSession = mozilla::VideoSessionConduit::Create(nullptr);
   728     if( !mVideoSession )
   729       ASSERT_NE(mVideoSession, (void*)nullptr);
   731     // Configure send codecs on the conduit.
   732     mozilla::VideoCodecConfig cinst1(120, "VP8", 0, max_fs, 0);
   734     err = mVideoSession->ConfigureSendMediaCodec(&cinst1);
   735     ASSERT_EQ(mozilla::kMediaConduitNoError, err);
   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);
   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);
   752     // Get the new resolution as adjusted by the max-fs constraint.
   753     *new_width = mVideoSession->SendingWidth();
   754     *new_height = mVideoSession->SendingHeight();
   755   }
   757   void TestVideoConduitMaxFs()
   758   {
   759     int orig_width, orig_height, width, height, max_fs;
   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);
   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);
   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);
   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);
   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);
   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);
   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);
   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);
   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;
   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  }
   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;
   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;
   878   std::string fileToPlay;
   879   std::string fileToRecord;
   880   std::string iAudiofilename;
   881   std::string oAudiofilename;
   882 };
   885 // Test 1: Test Dummy External Xport
   886 TEST_F(TransportConduitTest, TestDummyAudioWithTransport) {
   887   TestDummyAudioAndTransport();
   888 }
   890 // Test 2: Test Dummy External Xport
   891 TEST_F(TransportConduitTest, TestDummyVideoWithTransport) {
   892   TestDummyVideoAndTransport();
   893  }
   895 TEST_F(TransportConduitTest, TestVideoConduitCodecAPI) {
   896   TestVideoConduitCodecAPI();
   897  }
   899 TEST_F(TransportConduitTest, TestVideoConduitMaxFs) {
   900   TestVideoConduitMaxFs();
   901  }
   903 }  // end namespace
   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")
   910   test_utils = new MtransportTestUtils();
   911   ::testing::InitGoogleTest(&argc, argv);
   912   int rv = RUN_ALL_TESTS();
   913   delete test_utils;
   914   return rv;
   915 }

mercurial