Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / video_coding / main / test / generic_codec_test.cc
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/modules/video_coding/main/test/generic_codec_test.h"
12
13 #include <math.h>
14 #include <stdio.h>
15
16 #include "webrtc/common_video/interface/i420_video_frame.h"
17 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
18 #include "webrtc/modules/video_coding/main/interface/video_coding.h"
19 #include "webrtc/modules/video_coding/main/test/test_macros.h"
20 #include "webrtc/system_wrappers/interface/clock.h"
21 #include "webrtc/test/testsupport/fileutils.h"
22
23 using namespace webrtc;
24
25 enum { kMaxWaitEncTimeMs = 100 };
26
27 int GenericCodecTest::RunTest(CmdArgs& args)
28 {
29     SimulatedClock clock(0);
30     NullEventFactory event_factory;
31     VideoCodingModule* vcm = VideoCodingModule::Create(&clock, &event_factory);
32     GenericCodecTest* get = new GenericCodecTest(vcm, &clock);
33     Trace::CreateTrace();
34     Trace::SetTraceFile(
35         (test::OutputPath() + "genericCodecTestTrace.txt").c_str());
36     Trace::set_level_filter(webrtc::kTraceAll);
37     get->Perform(args);
38     Trace::ReturnTrace();
39     delete get;
40     VideoCodingModule::Destroy(vcm);
41     return 0;
42 }
43
44 GenericCodecTest::GenericCodecTest(VideoCodingModule* vcm,
45                                    SimulatedClock* clock):
46 _clock(clock),
47 _vcm(vcm),
48 _width(0),
49 _height(0),
50 _frameRate(0),
51 _lengthSourceFrame(0),
52 _timeStamp(0)
53 {
54 }
55
56 GenericCodecTest::~GenericCodecTest()
57 {
58 }
59
60 void
61 GenericCodecTest::Setup(CmdArgs& args)
62 {
63     _timeStamp = 0;
64
65     /* Test Sequence parameters */
66
67     _inname= args.inputFile;
68     if (args.outputFile.compare(""))
69         _outname = test::OutputPath() + "GCTest_decoded.yuv";
70     else
71         _outname = args.outputFile;
72     _encodedName = test::OutputPath() + "GCTest_encoded.vp8";
73     _width = args.width;
74     _height = args.height;
75     _frameRate = args.frameRate;
76     _lengthSourceFrame  = 3*_width*_height/2;
77
78     /* File settings */
79
80     if ((_sourceFile = fopen(_inname.c_str(), "rb")) == NULL)
81     {
82         printf("Cannot read file %s.\n", _inname.c_str());
83         exit(1);
84     }
85     if ((_encodedFile = fopen(_encodedName.c_str(), "wb")) == NULL)
86     {
87         printf("Cannot write encoded file.\n");
88         exit(1);
89     }
90     if ((_decodedFile = fopen(_outname.c_str(),  "wb")) == NULL)
91     {
92         printf("Cannot write file %s.\n", _outname.c_str());
93         exit(1);
94     }
95
96     return;
97 }
98 int32_t
99 GenericCodecTest::Perform(CmdArgs& args)
100 {
101     int32_t ret;
102     Setup(args);
103     /*
104     1. sanity checks
105     2. encode/decoder individuality
106     3. API testing
107     4. Target bitrate (within a specific timespan)
108     5. Pipeline Delay
109     */
110
111     /*******************************/
112     /* sanity checks on inputs    */
113     /*****************************/
114     VideoCodec sendCodec, receiveCodec;
115     sendCodec.maxBitrate = 8000;
116     TEST(_vcm->NumberOfCodecs() > 0); // This works since we now initialize the list in the constructor
117     TEST(_vcm->Codec(0, &sendCodec)  == VCM_OK);
118     _vcm->InitializeSender();
119     _vcm->InitializeReceiver();
120     int32_t NumberOfCodecs = _vcm->NumberOfCodecs();
121     // registration of first codec in the list
122     int i = 0;
123     _vcm->Codec(0, &_sendCodec);
124     TEST(_vcm->RegisterSendCodec(&_sendCodec, 4, 1440) == VCM_OK);
125     // sanity on encoder registration
126     I420VideoFrame sourceFrame;
127     _vcm->InitializeSender();
128     TEST(_vcm->Codec(kVideoCodecVP8, &sendCodec) == 0);
129     sendCodec.maxBitrate = 8000;
130     _vcm->RegisterSendCodec(&sendCodec, 1, 1440);
131     _vcm->InitializeSender();
132     _vcm->Codec(kVideoCodecVP8, &sendCodec);
133     sendCodec.height = 0;
134     TEST(_vcm->RegisterSendCodec(&sendCodec, 1, 1440) < 0); // bad height
135     _vcm->Codec(kVideoCodecVP8, &sendCodec);
136     _vcm->Codec(kVideoCodecVP8, &sendCodec);
137     _vcm->InitializeSender();
138     // Setting rate when encoder uninitialized.
139     TEST(_vcm->SetChannelParameters(100000, 0, 0) < 0);
140     // register all availbale decoders -- need to have more for this test
141     for (i=0; i< NumberOfCodecs; i++)
142     {
143         _vcm->Codec(i, &receiveCodec);
144         _vcm->RegisterReceiveCodec(&receiveCodec, 1);
145     }
146     uint8_t* tmpBuffer = new uint8_t[_lengthSourceFrame];
147     TEST(fread(tmpBuffer, 1, _lengthSourceFrame, _sourceFile) > 0);
148     int half_width = (_width + 1) / 2;
149     int half_height = (_height + 1) / 2;
150     int size_y = _width * _height;
151     int size_uv = half_width * half_height;
152     sourceFrame.CreateFrame(size_y, tmpBuffer,
153                             size_uv, tmpBuffer + size_y,
154                             size_uv, tmpBuffer + size_y + size_uv,
155                             _width, _height,
156                             _width, half_width, half_width);
157     sourceFrame.set_timestamp(_timeStamp++);
158     TEST(_vcm->AddVideoFrame(sourceFrame) < 0 ); // encoder uninitialized
159     _vcm->InitializeReceiver();
160     // Setting rtt when receiver uninitialized.
161     TEST(_vcm->SetChannelParameters(100000, 0, 0) < 0);
162
163       /**************************************/
164      /* encoder/decoder individuality test */
165     /**************************************/
166     //Register both encoder and decoder, reset decoder - encode, set up decoder, reset encoder - decode.
167     rewind(_sourceFile);
168     _vcm->InitializeReceiver();
169     _vcm->InitializeSender();
170     NumberOfCodecs = _vcm->NumberOfCodecs();
171     // Register VP8
172     _vcm->Codec(kVideoCodecVP8, &_sendCodec);
173     _vcm->RegisterSendCodec(&_sendCodec, 4, 1440);
174     _vcm->SendCodec(&sendCodec);
175     sendCodec.startBitrate = 2000;
176
177     // Set target frame rate to half of the incoming frame rate
178     // to test the frame rate control in the VCM
179     sendCodec.maxFramerate = (uint8_t)(_frameRate / 2);
180     sendCodec.width = _width;
181     sendCodec.height = _height;
182     TEST(strncmp(_sendCodec.plName, "VP8", 3) == 0); // was VP8
183
184     _decodeCallback = new VCMDecodeCompleteCallback(_decodedFile);
185     _encodeCompleteCallback = new VCMEncodeCompleteCallback(_encodedFile);
186     _vcm->RegisterReceiveCallback(_decodeCallback);
187     _vcm->RegisterTransportCallback(_encodeCompleteCallback);
188     _encodeCompleteCallback->RegisterReceiverVCM(_vcm);
189
190     _vcm->RegisterSendCodec(&sendCodec, 4, 1440);
191     _encodeCompleteCallback->SetCodecType(ConvertCodecType(sendCodec.plName));
192
193     _vcm->InitializeReceiver();
194     _vcm->Process();
195
196     //encoding 1 second of video
197     for (i = 0; i < _frameRate; i++)
198     {
199         TEST(fread(tmpBuffer, 1, _lengthSourceFrame, _sourceFile) > 0);
200         sourceFrame.CreateFrame(size_y, tmpBuffer,
201                                 size_uv, tmpBuffer + size_y,
202                                 size_uv, tmpBuffer + size_y + size_uv,
203                                 _width, _height,
204                                 _width, half_width, half_width);
205         _timeStamp += (uint32_t)(9e4 / static_cast<float>(_frameRate));
206         sourceFrame.set_timestamp(_timeStamp);
207         TEST(_vcm->AddVideoFrame(sourceFrame) == VCM_OK);
208         IncrementDebugClock(_frameRate);
209         _vcm->Process();
210     }
211     sendCodec.maxFramerate = (uint8_t)_frameRate;
212     _vcm->InitializeSender();
213     TEST(_vcm->RegisterReceiveCodec(&sendCodec, 1) == VCM_OK); // same codec for encode and decode
214     ret = 0;
215     i = 0;
216     while ((i < 25) && (ret == 0) )
217     {
218         ret = _vcm->Decode();
219         TEST(ret == VCM_OK);
220         if (ret < 0)
221         {
222             printf("error in frame # %d \n", i);
223         }
224         IncrementDebugClock(_frameRate);
225         i++;
226     }
227     //TEST((ret == 0) && (i = 50));
228     if (ret == 0)
229     {
230         printf("Encoder/Decoder individuality test complete - View output files \n");
231     }
232     // last frame - not decoded
233     _vcm->InitializeReceiver();
234     TEST(_vcm->Decode() < 0); // frame to be encoded exists, decoder uninitialized
235
236
237     // Test key frame request on packet loss mode.
238     // This a frame as a key frame and fooling the receiver
239     // that the last packet was lost. The decoding will succeed,
240     // but the VCM will see a packet loss and request a new key frame.
241     VCMEncComplete_KeyReqTest keyReqTest_EncCompleteCallback(*_vcm);
242     KeyFrameReqTest frameTypeCallback;
243     _vcm->RegisterTransportCallback(&keyReqTest_EncCompleteCallback);
244     _encodeCompleteCallback->RegisterReceiverVCM(_vcm);
245     _vcm->RegisterSendCodec(&sendCodec, 4, 1440);
246     _encodeCompleteCallback->SetCodecType(ConvertCodecType(sendCodec.plName));
247     TEST(_vcm->SetVideoProtection(kProtectionKeyOnKeyLoss, true) == VCM_OK);
248     TEST(_vcm->RegisterFrameTypeCallback(&frameTypeCallback) == VCM_OK);
249     TEST(_vcm->RegisterReceiveCodec(&sendCodec, 1) == VCM_OK);
250     TEST(_vcm->AddVideoFrame(sourceFrame) == VCM_OK);
251     _timeStamp += (uint32_t)(9e4 / static_cast<float>(_frameRate));
252     sourceFrame.set_timestamp(_timeStamp);
253     // First packet of a subsequent frame required before the jitter buffer
254     // will allow decoding an incomplete frame.
255     TEST(_vcm->AddVideoFrame(sourceFrame) == VCM_OK);
256     TEST(_vcm->Decode() == VCM_OK);
257
258     printf("API tests complete \n");
259
260      /*******************/
261     /* Bit Rate Tests */
262     /*****************/
263     /* Requirements:
264     * 1. OneSecReq = 15 % above/below target over a time period of 1s (_frameRate number of frames)
265     * 3. FullReq  = 10% for total seq. (for 300 frames/seq. coincides with #1)
266     * 4. Test will go over all registered codecs
267     //NOTE: time requirements are not part of the release tests
268     */
269     double FullReq   =  0.1;
270     //double OneSecReq = 0.15;
271     printf("\n RATE CONTROL TEST\n");
272     // initializing....
273     _vcm->InitializeSender();
274     _vcm->InitializeReceiver();
275     rewind(_sourceFile);
276     sourceFrame.CreateEmptyFrame(_width, _height, _width,
277                                  (_width + 1) / 2, (_width + 1) / 2);
278     const float bitRate[] = {100, 400, 600, 1000, 2000};
279     const float nBitrates = sizeof(bitRate)/sizeof(*bitRate);
280     float _bitRate = 0;
281     int _frameCnt = 0;
282     float totalBytesOneSec = 0;//, totalBytesTenSec;
283     float totalBytes, actualBitrate;
284     VCMFrameCount frameCount; // testing frame type counters
285     // start test
286     NumberOfCodecs = _vcm->NumberOfCodecs();
287     // going over all available codecs
288     _encodeCompleteCallback->SetFrameDimensions(_width, _height);
289     SendStatsTest sendStats;
290     for (int k = 0; k < NumberOfCodecs; k++)
291     //for (int k = NumberOfCodecs - 1; k >=0; k--)
292     {// static list starts from 0
293         //just checking
294         _vcm->InitializeSender();
295         _sendCodec.maxBitrate = 8000;
296         TEST(_vcm->Codec(k, &_sendCodec)== VCM_OK);
297         _vcm->RegisterSendCodec(&_sendCodec, 1, 1440);
298         _vcm->RegisterTransportCallback(_encodeCompleteCallback);
299         _encodeCompleteCallback->SetCodecType(ConvertCodecType(_sendCodec.plName));
300         printf (" \n\n Codec type = %s \n\n",_sendCodec.plName);
301         for (i = 0; i < nBitrates; i++)
302         {
303              _bitRate = static_cast<float>(bitRate[i]);
304             // just testing
305             _vcm->InitializeSender();
306             _sendCodec.startBitrate = (int)_bitRate;
307             _sendCodec.maxBitrate = 8000;
308             _sendCodec.maxFramerate = _frameRate;
309             _vcm->RegisterSendCodec(&_sendCodec, 1, 1440);
310             _vcm->RegisterTransportCallback(_encodeCompleteCallback);
311             // up to here
312             _vcm->SetChannelParameters(static_cast<uint32_t>(1000 * _bitRate),
313                                        0, 20);
314             _frameCnt = 0;
315             totalBytes = 0;
316             _encodeCompleteCallback->Initialize();
317             sendStats.set_framerate(static_cast<uint32_t>(_frameRate));
318             sendStats.set_bitrate(1000 * _bitRate);
319             _vcm->RegisterSendStatisticsCallback(&sendStats);
320             while (fread(tmpBuffer, 1, _lengthSourceFrame, _sourceFile) ==
321                 _lengthSourceFrame)
322             {
323                 _frameCnt++;
324                 sourceFrame.CreateFrame(size_y, tmpBuffer,
325                                         size_uv, tmpBuffer + size_y,
326                                         size_uv, tmpBuffer + size_y + size_uv,
327                                         _width, _height,
328                                         _width, (_width + 1) / 2,
329                                         (_width + 1) / 2);
330                 _timeStamp += (uint32_t)(9e4 / static_cast<float>(_frameRate));
331                 sourceFrame.set_timestamp(_timeStamp);
332
333                 ret = _vcm->AddVideoFrame(sourceFrame);
334                 IncrementDebugClock(_frameRate);
335                 // The following should be uncommneted for timing tests. Release tests only include
336                 // compliance with full sequence bit rate.
337                 if (_frameCnt == _frameRate)// @ 1sec
338                 {
339                     totalBytesOneSec =  _encodeCompleteCallback->EncodedBytes();//totalBytes;
340                 }
341                 TEST(_vcm->TimeUntilNextProcess() >= 0);
342             }  // video seq. encode done
343             TEST(_vcm->TimeUntilNextProcess() == 0);
344             _vcm->Process(); // Let the module calculate its send bit rate estimate
345             // estimating rates
346             // complete sequence
347             // bit rate assumes input frame rate is as specified
348             totalBytes = _encodeCompleteCallback->EncodedBytes();
349             actualBitrate = (float)(8.0/1000)*(totalBytes / (_frameCnt / _frameRate));
350
351             printf("Complete Seq.: target bitrate: %.0f kbps, actual bitrate: %.1f kbps\n", _bitRate, actualBitrate);
352             TEST((fabs(actualBitrate - _bitRate) < FullReq * _bitRate) ||
353                  (strncmp(_sendCodec.plName, "I420", 4) == 0));
354
355             // 1 Sec.
356             actualBitrate = (float)(8.0/1000)*(totalBytesOneSec);
357             //actualBitrate = (float)(8.0*totalBytesOneSec)/(oneSecTime - startTime);
358             //printf("First 1Sec: target bitrate: %.0f kbps, actual bitrate: %.1f kbps\n", _bitRate, actualBitrate);
359             //TEST(fabs(actualBitrate - _bitRate) < OneSecReq * _bitRate);
360             rewind(_sourceFile);
361
362             //checking key/delta frame count
363             _vcm->SentFrameCount(frameCount);
364             printf("frame count: %d delta, %d key\n", frameCount.numDeltaFrames, frameCount.numKeyFrames);
365         }// end per codec
366
367     }  // end rate control test
368     /********************************/
369     /* Encoder Pipeline Delay Test */
370     /******************************/
371     _vcm->InitializeSender();
372     NumberOfCodecs = _vcm->NumberOfCodecs();
373     bool encodeComplete = false;
374     // going over all available codecs
375     for (int k = 0; k < NumberOfCodecs; k++)
376     {
377         _vcm->Codec(k, &_sendCodec);
378         _vcm->InitializeSender();
379         _sendCodec.maxBitrate = 8000;
380         _vcm->RegisterSendCodec(&_sendCodec, 4, 1440);
381         _vcm->RegisterTransportCallback(_encodeCompleteCallback);
382
383         _frameCnt = 0;
384         encodeComplete = false;
385         while (encodeComplete == false)
386         {
387             TEST(fread(tmpBuffer, 1, _lengthSourceFrame, _sourceFile) > 0);
388             _frameCnt++;
389             sourceFrame.CreateFrame(size_y, tmpBuffer,
390                                     size_uv, tmpBuffer + size_y,
391                                     size_uv, tmpBuffer + size_y + size_uv,
392                                     _width, _height,
393                                     _width, half_width, half_width);
394             _timeStamp += (uint32_t)(9e4 / static_cast<float>(_frameRate));
395             sourceFrame.set_timestamp(_timeStamp);
396             _vcm->AddVideoFrame(sourceFrame);
397             encodeComplete = _encodeCompleteCallback->EncodeComplete();
398         }  // first frame encoded
399         printf ("\n Codec type = %s \n", _sendCodec.plName);
400         printf(" Encoder pipeline delay = %d frames\n", _frameCnt - 1);
401     }  // end for all codecs
402
403     /********************************/
404     /* Encoder Packet Size Test     */
405     /********************************/
406     RTPSendCallback_SizeTest sendCallback;
407
408     RtpRtcp::Configuration configuration;
409     configuration.id = 1;
410     configuration.audio = false;
411     configuration.outgoing_transport = &sendCallback;
412
413     RtpRtcp& rtpModule = *RtpRtcp::CreateRtpRtcp(configuration);
414
415     VCMRTPEncodeCompleteCallback encCompleteCallback(&rtpModule);
416     _vcm->InitializeSender();
417
418     // Test temporal decimation settings
419     for (int k = 0; k < NumberOfCodecs; k++)
420     {
421         _vcm->Codec(k, &_sendCodec);
422         if (strncmp(_sendCodec.plName, "I420", 4) == 0)
423         {
424             // Only test with I420
425             break;
426         }
427     }
428     TEST(strncmp(_sendCodec.plName, "I420", 4) == 0);
429     _vcm->InitializeSender();
430     _sendCodec.maxFramerate = static_cast<uint8_t>(_frameRate / 2.0 + 0.5f);
431     _vcm->RegisterSendCodec(&_sendCodec, 4, 1440);
432     _vcm->SetChannelParameters(2000000, 0, 0);
433     _vcm->RegisterTransportCallback(_encodeCompleteCallback);
434     // up to here
435     _vcm->SetChannelParameters(static_cast<uint32_t>(1000 * _bitRate), 0, 20);
436     _encodeCompleteCallback->Initialize();
437     sendStats.set_framerate(static_cast<uint32_t>(_frameRate));
438     sendStats.set_bitrate(1000 * _bitRate);
439     _vcm->RegisterSendStatisticsCallback(&sendStats);
440     rewind(_sourceFile);
441     while (fread(tmpBuffer, 1, _lengthSourceFrame, _sourceFile) ==
442         _lengthSourceFrame) {
443         sourceFrame.CreateFrame(size_y, tmpBuffer,
444                                 size_uv, tmpBuffer + size_y,
445                                 size_uv, tmpBuffer + size_y + size_uv,
446                                 _width, _height,
447                                 _width, half_width, half_width);
448         _timeStamp += (uint32_t)(9e4 / static_cast<float>(_frameRate));
449         sourceFrame.set_timestamp(_timeStamp);
450         ret = _vcm->AddVideoFrame(sourceFrame);
451         if (_vcm->TimeUntilNextProcess() <= 0)
452         {
453             _vcm->Process();
454         }
455         IncrementDebugClock(_frameRate);
456     }  // first frame encoded
457
458     delete &rtpModule;
459     Print();
460     delete tmpBuffer;
461     delete _decodeCallback;
462     delete _encodeCompleteCallback;
463     return 0;
464 }
465
466
467 void
468 GenericCodecTest::Print()
469 {
470     printf(" \n\n VCM Generic Encoder Test: \n\n%i tests completed\n", vcmMacrosTests);
471     if (vcmMacrosErrors > 0)
472     {
473         printf("%i FAILED\n\n", vcmMacrosErrors);
474     }
475     else
476     {
477         printf("ALL PASSED\n\n");
478     }
479 }
480
481 float
482 GenericCodecTest::WaitForEncodedFrame() const
483 {
484     int64_t startTime = _clock->TimeInMilliseconds();
485     while (_clock->TimeInMilliseconds() - startTime < kMaxWaitEncTimeMs*10)
486     {
487         if (_encodeCompleteCallback->EncodeComplete())
488         {
489             return _encodeCompleteCallback->EncodedBytes();
490         }
491     }
492     return 0;
493 }
494
495 void
496 GenericCodecTest::IncrementDebugClock(float frameRate)
497 {
498     _clock->AdvanceTimeMilliseconds(1000/frameRate);
499 }
500
501 int
502 RTPSendCallback_SizeTest::SendPacket(int channel, const void *data, int len)
503 {
504     _nPackets++;
505     _payloadSizeSum += len;
506     // Make sure no payloads (len - header size) are larger than maxPayloadSize
507     TEST(len > 0 && static_cast<uint32_t>(len - 12) <= _maxPayloadSize);
508     return 0;
509 }
510
511 void
512 RTPSendCallback_SizeTest::SetMaxPayloadSize(uint32_t maxPayloadSize)
513 {
514     _maxPayloadSize = maxPayloadSize;
515 }
516
517 void
518 RTPSendCallback_SizeTest::Reset()
519 {
520     _nPackets = 0;
521     _payloadSizeSum = 0;
522 }
523
524 float
525 RTPSendCallback_SizeTest::AveragePayloadSize() const
526 {
527     if (_nPackets > 0)
528     {
529         return _payloadSizeSum / static_cast<float>(_nPackets);
530     }
531     return 0;
532 }
533
534 int32_t
535 VCMEncComplete_KeyReqTest::SendData(
536         const FrameType frameType,
537         const uint8_t payloadType,
538         const uint32_t timeStamp,
539         int64_t capture_time_ms,
540         const uint8_t* payloadData,
541         const uint32_t payloadSize,
542         const RTPFragmentationHeader& /*fragmentationHeader*/,
543         const webrtc::RTPVideoHeader* /*videoHdr*/)
544 {
545     WebRtcRTPHeader rtpInfo;
546     rtpInfo.header.markerBit = true; // end of frame
547     rtpInfo.type.Video.codecHeader.VP8.InitRTPVideoHeaderVP8();
548     rtpInfo.type.Video.codec = kRtpVideoVp8;
549     rtpInfo.header.payloadType = payloadType;
550     rtpInfo.header.sequenceNumber = _seqNo;
551     _seqNo += 2;
552     rtpInfo.header.ssrc = 0;
553     rtpInfo.header.timestamp = _timeStamp;
554     _timeStamp += 3000;
555     rtpInfo.type.Video.isFirstPacket = false;
556     rtpInfo.frameType = kVideoFrameKey;
557     return _vcm.IncomingPacket(payloadData, payloadSize, rtpInfo);
558 }