Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / video_coding / main / source / video_receiver.cc
1 /*
2  *  Copyright (c) 2013 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/common_video/libyuv/include/webrtc_libyuv.h"
13 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
14 #include "webrtc/modules/video_coding/main/source/encoded_frame.h"
15 #include "webrtc/modules/video_coding/main/source/jitter_buffer.h"
16 #include "webrtc/modules/video_coding/main/source/packet.h"
17 #include "webrtc/modules/video_coding/main/source/video_coding_impl.h"
18 #include "webrtc/system_wrappers/interface/clock.h"
19 #include "webrtc/system_wrappers/interface/trace.h"
20 #include "webrtc/system_wrappers/interface/trace_event.h"
21
22 // #define DEBUG_DECODER_BIT_STREAM
23
24 namespace webrtc {
25 namespace vcm {
26
27 VideoReceiver::VideoReceiver(const int32_t id,
28                              Clock* clock,
29                              EventFactory* event_factory)
30     : _id(id),
31       clock_(clock),
32       process_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
33       _receiveCritSect(CriticalSectionWrapper::CreateCriticalSection()),
34       _receiverInited(false),
35       _timing(clock_, id, 1),
36       _dualTiming(clock_, id, 2, &_timing),
37       _receiver(&_timing, clock_, event_factory, id, 1, true),
38       _dualReceiver(&_dualTiming, clock_, event_factory, id, 2, false),
39       _decodedFrameCallback(_timing, clock_),
40       _dualDecodedFrameCallback(_dualTiming, clock_),
41       _frameTypeCallback(NULL),
42       _receiveStatsCallback(NULL),
43       _decoderTimingCallback(NULL),
44       _packetRequestCallback(NULL),
45       render_buffer_callback_(NULL),
46       _decoder(NULL),
47       _dualDecoder(NULL),
48 #ifdef DEBUG_DECODER_BIT_STREAM
49       _bitStreamBeforeDecoder(NULL),
50 #endif
51       _frameFromFile(),
52       _keyRequestMode(kKeyOnError),
53       _scheduleKeyRequest(false),
54       max_nack_list_size_(0),
55       pre_decode_image_callback_(NULL),
56       _codecDataBase(id),
57       _receiveStatsTimer(1000, clock_),
58       _retransmissionTimer(10, clock_),
59       _keyRequestTimer(500, clock_) {
60   assert(clock_);
61 #ifdef DEBUG_DECODER_BIT_STREAM
62   _bitStreamBeforeDecoder = fopen("decoderBitStream.bit", "wb");
63 #endif
64 }
65
66 VideoReceiver::~VideoReceiver() {
67   if (_dualDecoder != NULL) {
68     _codecDataBase.ReleaseDecoder(_dualDecoder);
69   }
70   delete _receiveCritSect;
71 #ifdef DEBUG_DECODER_BIT_STREAM
72   fclose(_bitStreamBeforeDecoder);
73 #endif
74 }
75
76 int32_t VideoReceiver::Process() {
77   int32_t returnValue = VCM_OK;
78
79   // Receive-side statistics
80   if (_receiveStatsTimer.TimeUntilProcess() == 0) {
81     _receiveStatsTimer.Processed();
82     CriticalSectionScoped cs(process_crit_sect_.get());
83     if (_receiveStatsCallback != NULL) {
84       uint32_t bitRate;
85       uint32_t frameRate;
86       _receiver.ReceiveStatistics(&bitRate, &frameRate);
87       _receiveStatsCallback->OnReceiveStatisticsUpdate(bitRate, frameRate);
88     }
89
90     if (_decoderTimingCallback != NULL) {
91       int decode_ms;
92       int max_decode_ms;
93       int current_delay_ms;
94       int target_delay_ms;
95       int jitter_buffer_ms;
96       int min_playout_delay_ms;
97       int render_delay_ms;
98       _timing.GetTimings(&decode_ms,
99                          &max_decode_ms,
100                          &current_delay_ms,
101                          &target_delay_ms,
102                          &jitter_buffer_ms,
103                          &min_playout_delay_ms,
104                          &render_delay_ms);
105       _decoderTimingCallback->OnDecoderTiming(decode_ms,
106                                               max_decode_ms,
107                                               current_delay_ms,
108                                               target_delay_ms,
109                                               jitter_buffer_ms,
110                                               min_playout_delay_ms,
111                                               render_delay_ms);
112     }
113
114     // Size of render buffer.
115     if (render_buffer_callback_) {
116       int buffer_size_ms = _receiver.RenderBufferSizeMs();
117       render_buffer_callback_->RenderBufferSizeMs(buffer_size_ms);
118     }
119   }
120
121   // Key frame requests
122   if (_keyRequestTimer.TimeUntilProcess() == 0) {
123     _keyRequestTimer.Processed();
124     bool request_key_frame = false;
125     {
126       CriticalSectionScoped cs(process_crit_sect_.get());
127       request_key_frame = _scheduleKeyRequest && _frameTypeCallback != NULL;
128     }
129     if (request_key_frame) {
130       const int32_t ret = RequestKeyFrame();
131       if (ret != VCM_OK && returnValue == VCM_OK) {
132         returnValue = ret;
133       }
134     }
135   }
136
137   // Packet retransmission requests
138   // TODO(holmer): Add API for changing Process interval and make sure it's
139   // disabled when NACK is off.
140   if (_retransmissionTimer.TimeUntilProcess() == 0) {
141     _retransmissionTimer.Processed();
142     bool callback_registered = false;
143     uint16_t length;
144     {
145       CriticalSectionScoped cs(process_crit_sect_.get());
146       length = max_nack_list_size_;
147       callback_registered = _packetRequestCallback != NULL;
148     }
149     if (callback_registered && length > 0) {
150       std::vector<uint16_t> nackList(length);
151       const int32_t ret = NackList(&nackList[0], &length);
152       if (ret != VCM_OK && returnValue == VCM_OK) {
153         returnValue = ret;
154       }
155       if (ret == VCM_OK && length > 0) {
156         CriticalSectionScoped cs(process_crit_sect_.get());
157         if (_packetRequestCallback != NULL) {
158           _packetRequestCallback->ResendPackets(&nackList[0], length);
159         }
160       }
161     }
162   }
163
164   return returnValue;
165 }
166
167 int32_t VideoReceiver::TimeUntilNextProcess() {
168   uint32_t timeUntilNextProcess = _receiveStatsTimer.TimeUntilProcess();
169   if ((_receiver.NackMode() != kNoNack) ||
170       (_dualReceiver.State() != kPassive)) {
171     // We need a Process call more often if we are relying on
172     // retransmissions
173     timeUntilNextProcess =
174         VCM_MIN(timeUntilNextProcess, _retransmissionTimer.TimeUntilProcess());
175   }
176   timeUntilNextProcess =
177       VCM_MIN(timeUntilNextProcess, _keyRequestTimer.TimeUntilProcess());
178
179   return timeUntilNextProcess;
180 }
181
182 int32_t VideoReceiver::SetReceiveChannelParameters(uint32_t rtt) {
183   CriticalSectionScoped receiveCs(_receiveCritSect);
184   _receiver.UpdateRtt(rtt);
185   return 0;
186 }
187
188 // Enable or disable a video protection method.
189 // Note: This API should be deprecated, as it does not offer a distinction
190 // between the protection method and decoding with or without errors. If such a
191 // behavior is desired, use the following API: SetReceiverRobustnessMode.
192 int32_t VideoReceiver::SetVideoProtection(VCMVideoProtection videoProtection,
193                                           bool enable) {
194   // By default, do not decode with errors.
195   _receiver.SetDecodeErrorMode(kNoErrors);
196   // The dual decoder should always be error free.
197   _dualReceiver.SetDecodeErrorMode(kNoErrors);
198   switch (videoProtection) {
199     case kProtectionNack:
200     case kProtectionNackReceiver: {
201       CriticalSectionScoped cs(_receiveCritSect);
202       if (enable) {
203         // Enable NACK and always wait for retransmits.
204         _receiver.SetNackMode(kNack, -1, -1);
205       } else {
206         _receiver.SetNackMode(kNoNack, -1, -1);
207       }
208       break;
209     }
210
211     case kProtectionDualDecoder: {
212       CriticalSectionScoped cs(_receiveCritSect);
213       if (enable) {
214         // Enable NACK but don't wait for retransmissions and don't
215         // add any extra delay.
216         _receiver.SetNackMode(kNack, 0, 0);
217         // Enable NACK and always wait for retransmissions and
218         // compensate with extra delay.
219         _dualReceiver.SetNackMode(kNack, -1, -1);
220         _receiver.SetDecodeErrorMode(kWithErrors);
221       } else {
222         _dualReceiver.SetNackMode(kNoNack, -1, -1);
223       }
224       break;
225     }
226
227     case kProtectionKeyOnLoss: {
228       CriticalSectionScoped cs(_receiveCritSect);
229       if (enable) {
230         _keyRequestMode = kKeyOnLoss;
231         _receiver.SetDecodeErrorMode(kWithErrors);
232       } else if (_keyRequestMode == kKeyOnLoss) {
233         _keyRequestMode = kKeyOnError;  // default mode
234       } else {
235         return VCM_PARAMETER_ERROR;
236       }
237       break;
238     }
239
240     case kProtectionKeyOnKeyLoss: {
241       CriticalSectionScoped cs(_receiveCritSect);
242       if (enable) {
243         _keyRequestMode = kKeyOnKeyLoss;
244       } else if (_keyRequestMode == kKeyOnKeyLoss) {
245         _keyRequestMode = kKeyOnError;  // default mode
246       } else {
247         return VCM_PARAMETER_ERROR;
248       }
249       break;
250     }
251
252     case kProtectionNackFEC: {
253       CriticalSectionScoped cs(_receiveCritSect);
254       if (enable) {
255         // Enable hybrid NACK/FEC. Always wait for retransmissions
256         // and don't add extra delay when RTT is above
257         // kLowRttNackMs.
258         _receiver.SetNackMode(kNack, media_optimization::kLowRttNackMs, -1);
259         _receiver.SetDecodeErrorMode(kNoErrors);
260         _receiver.SetDecodeErrorMode(kNoErrors);
261       } else {
262         _receiver.SetNackMode(kNoNack, -1, -1);
263       }
264       break;
265     }
266     case kProtectionNackSender:
267     case kProtectionFEC:
268     case kProtectionPeriodicKeyFrames:
269       // Ignore encoder modes.
270       return VCM_OK;
271   }
272   return VCM_OK;
273 }
274
275 // Initialize receiver, resets codec database etc
276 int32_t VideoReceiver::InitializeReceiver() {
277   CriticalSectionScoped receive_cs(_receiveCritSect);
278   CriticalSectionScoped process_cs(process_crit_sect_.get());
279   int32_t ret = _receiver.Initialize();
280   if (ret < 0) {
281     return ret;
282   }
283
284   ret = _dualReceiver.Initialize();
285   if (ret < 0) {
286     return ret;
287   }
288   _codecDataBase.ResetReceiver();
289   _timing.Reset();
290
291   _decoder = NULL;
292   _decodedFrameCallback.SetUserReceiveCallback(NULL);
293   _receiverInited = true;
294   _frameTypeCallback = NULL;
295   _receiveStatsCallback = NULL;
296   _decoderTimingCallback = NULL;
297   _packetRequestCallback = NULL;
298   _keyRequestMode = kKeyOnError;
299   _scheduleKeyRequest = false;
300
301   return VCM_OK;
302 }
303
304 // Register a receive callback. Will be called whenever there is a new frame
305 // ready for rendering.
306 int32_t VideoReceiver::RegisterReceiveCallback(
307     VCMReceiveCallback* receiveCallback) {
308   CriticalSectionScoped cs(_receiveCritSect);
309   _decodedFrameCallback.SetUserReceiveCallback(receiveCallback);
310   return VCM_OK;
311 }
312
313 int32_t VideoReceiver::RegisterReceiveStatisticsCallback(
314     VCMReceiveStatisticsCallback* receiveStats) {
315   CriticalSectionScoped cs(process_crit_sect_.get());
316   _receiveStatsCallback = receiveStats;
317   return VCM_OK;
318 }
319
320 int32_t VideoReceiver::RegisterDecoderTimingCallback(
321     VCMDecoderTimingCallback* decoderTiming) {
322   CriticalSectionScoped cs(process_crit_sect_.get());
323   _decoderTimingCallback = decoderTiming;
324   return VCM_OK;
325 }
326
327 // Register an externally defined decoder/render object.
328 // Can be a decoder only or a decoder coupled with a renderer.
329 int32_t VideoReceiver::RegisterExternalDecoder(VideoDecoder* externalDecoder,
330                                                uint8_t payloadType,
331                                                bool internalRenderTiming) {
332   CriticalSectionScoped cs(_receiveCritSect);
333   if (externalDecoder == NULL) {
334     // Make sure the VCM updates the decoder next time it decodes.
335     _decoder = NULL;
336     return _codecDataBase.DeregisterExternalDecoder(payloadType) ? 0 : -1;
337   }
338   return _codecDataBase.RegisterExternalDecoder(
339              externalDecoder, payloadType, internalRenderTiming)
340              ? 0
341              : -1;
342 }
343
344 // Register a frame type request callback.
345 int32_t VideoReceiver::RegisterFrameTypeCallback(
346     VCMFrameTypeCallback* frameTypeCallback) {
347   CriticalSectionScoped cs(process_crit_sect_.get());
348   _frameTypeCallback = frameTypeCallback;
349   return VCM_OK;
350 }
351
352 int32_t VideoReceiver::RegisterPacketRequestCallback(
353     VCMPacketRequestCallback* callback) {
354   CriticalSectionScoped cs(process_crit_sect_.get());
355   _packetRequestCallback = callback;
356   return VCM_OK;
357 }
358
359 int VideoReceiver::RegisterRenderBufferSizeCallback(
360     VCMRenderBufferSizeCallback* callback) {
361   CriticalSectionScoped cs(process_crit_sect_.get());
362   render_buffer_callback_ = callback;
363   return VCM_OK;
364 }
365
366 // Decode next frame, blocking.
367 // Should be called as often as possible to get the most out of the decoder.
368 int32_t VideoReceiver::Decode(uint16_t maxWaitTimeMs) {
369   int64_t nextRenderTimeMs;
370   {
371     CriticalSectionScoped cs(_receiveCritSect);
372     if (!_receiverInited) {
373       return VCM_UNINITIALIZED;
374     }
375     if (!_codecDataBase.DecoderRegistered()) {
376       return VCM_NO_CODEC_REGISTERED;
377     }
378   }
379
380   const bool dualReceiverEnabledNotReceiving = (
381       _dualReceiver.State() != kReceiving && _dualReceiver.NackMode() == kNack);
382
383   VCMEncodedFrame* frame =
384       _receiver.FrameForDecoding(maxWaitTimeMs,
385                                  nextRenderTimeMs,
386                                  _codecDataBase.SupportsRenderScheduling(),
387                                  &_dualReceiver);
388
389   if (dualReceiverEnabledNotReceiving && _dualReceiver.State() == kReceiving) {
390     // Dual receiver is enabled (kNACK enabled), but was not receiving
391     // before the call to FrameForDecoding(). After the call the state
392     // changed to receiving, and therefore we must copy the primary decoder
393     // state to the dual decoder to make it possible for the dual decoder to
394     // start decoding retransmitted frames and recover.
395     CriticalSectionScoped cs(_receiveCritSect);
396     if (_dualDecoder != NULL) {
397       _codecDataBase.ReleaseDecoder(_dualDecoder);
398     }
399     _dualDecoder = _codecDataBase.CreateDecoderCopy();
400     if (_dualDecoder != NULL) {
401       _dualDecoder->RegisterDecodeCompleteCallback(&_dualDecodedFrameCallback);
402     } else {
403       _dualReceiver.Reset();
404     }
405   }
406
407   if (frame == NULL) {
408     return VCM_FRAME_NOT_READY;
409   } else {
410     CriticalSectionScoped cs(_receiveCritSect);
411
412     // If this frame was too late, we should adjust the delay accordingly
413     _timing.UpdateCurrentDelay(frame->RenderTimeMs(),
414                                clock_->TimeInMilliseconds());
415
416     if (pre_decode_image_callback_) {
417       EncodedImage encoded_image(frame->EncodedImage());
418       pre_decode_image_callback_->Encoded(encoded_image);
419     }
420
421 #ifdef DEBUG_DECODER_BIT_STREAM
422     if (_bitStreamBeforeDecoder != NULL) {
423       // Write bit stream to file for debugging purposes
424       if (fwrite(
425               frame->Buffer(), 1, frame->Length(), _bitStreamBeforeDecoder) !=
426           frame->Length()) {
427         return -1;
428       }
429     }
430 #endif
431     const int32_t ret = Decode(*frame);
432     _receiver.ReleaseFrame(frame);
433     frame = NULL;
434     if (ret != VCM_OK) {
435       return ret;
436     }
437   }
438   return VCM_OK;
439 }
440
441 int32_t VideoReceiver::RequestSliceLossIndication(
442     const uint64_t pictureID) const {
443   TRACE_EVENT1("webrtc", "RequestSLI", "picture_id", pictureID);
444   CriticalSectionScoped cs(process_crit_sect_.get());
445   if (_frameTypeCallback != NULL) {
446     const int32_t ret =
447         _frameTypeCallback->SliceLossIndicationRequest(pictureID);
448     if (ret < 0) {
449       WEBRTC_TRACE(webrtc::kTraceError,
450                    webrtc::kTraceVideoCoding,
451                    VCMId(_id),
452                    "Failed to request key frame");
453       return ret;
454     }
455   } else {
456     WEBRTC_TRACE(webrtc::kTraceWarning,
457                  webrtc::kTraceVideoCoding,
458                  VCMId(_id),
459                  "No frame type request callback registered");
460     return VCM_MISSING_CALLBACK;
461   }
462   return VCM_OK;
463 }
464
465 int32_t VideoReceiver::RequestKeyFrame() {
466   TRACE_EVENT0("webrtc", "RequestKeyFrame");
467   CriticalSectionScoped process_cs(process_crit_sect_.get());
468   if (_frameTypeCallback != NULL) {
469     const int32_t ret = _frameTypeCallback->RequestKeyFrame();
470     if (ret < 0) {
471       WEBRTC_TRACE(webrtc::kTraceError,
472                    webrtc::kTraceVideoCoding,
473                    VCMId(_id),
474                    "Failed to request key frame");
475       return ret;
476     }
477     _scheduleKeyRequest = false;
478   } else {
479     WEBRTC_TRACE(webrtc::kTraceWarning,
480                  webrtc::kTraceVideoCoding,
481                  VCMId(_id),
482                  "No frame type request callback registered");
483     return VCM_MISSING_CALLBACK;
484   }
485   return VCM_OK;
486 }
487
488 int32_t VideoReceiver::DecodeDualFrame(uint16_t maxWaitTimeMs) {
489   CriticalSectionScoped cs(_receiveCritSect);
490   if (_dualReceiver.State() != kReceiving ||
491       _dualReceiver.NackMode() != kNack) {
492     // The dual receiver is currently not receiving or
493     // dual decoder mode is disabled.
494     return VCM_OK;
495   }
496   int64_t dummyRenderTime;
497   int32_t decodeCount = 0;
498   // The dual decoder's state is copied from the main decoder, which may
499   // decode with errors. Make sure that the dual decoder does not introduce
500   // error.
501   _dualReceiver.SetDecodeErrorMode(kNoErrors);
502   VCMEncodedFrame* dualFrame =
503       _dualReceiver.FrameForDecoding(maxWaitTimeMs, dummyRenderTime);
504   if (dualFrame != NULL && _dualDecoder != NULL) {
505     WEBRTC_TRACE(webrtc::kTraceStream,
506                  webrtc::kTraceVideoCoding,
507                  VCMId(_id),
508                  "Decoding frame %u with dual decoder",
509                  dualFrame->TimeStamp());
510     // Decode dualFrame and try to catch up
511     int32_t ret =
512         _dualDecoder->Decode(*dualFrame, clock_->TimeInMilliseconds());
513     if (ret != WEBRTC_VIDEO_CODEC_OK) {
514       WEBRTC_TRACE(webrtc::kTraceWarning,
515                    webrtc::kTraceVideoCoding,
516                    VCMId(_id),
517                    "Failed to decode frame with dual decoder");
518       _dualReceiver.ReleaseFrame(dualFrame);
519       return VCM_CODEC_ERROR;
520     }
521     if (_receiver.DualDecoderCaughtUp(dualFrame, _dualReceiver)) {
522       // Copy the complete decoder state of the dual decoder
523       // to the primary decoder.
524       WEBRTC_TRACE(webrtc::kTraceStream,
525                    webrtc::kTraceVideoCoding,
526                    VCMId(_id),
527                    "Dual decoder caught up");
528       _codecDataBase.CopyDecoder(*_dualDecoder);
529       _codecDataBase.ReleaseDecoder(_dualDecoder);
530       _dualDecoder = NULL;
531     }
532     decodeCount++;
533   }
534   _dualReceiver.ReleaseFrame(dualFrame);
535   return decodeCount;
536 }
537
538 // Must be called from inside the receive side critical section.
539 int32_t VideoReceiver::Decode(const VCMEncodedFrame& frame) {
540   TRACE_EVENT_ASYNC_STEP1("webrtc",
541                           "Video",
542                           frame.TimeStamp(),
543                           "Decode",
544                           "type",
545                           frame.FrameType());
546   // Change decoder if payload type has changed
547   const bool renderTimingBefore = _codecDataBase.SupportsRenderScheduling();
548   _decoder =
549       _codecDataBase.GetDecoder(frame.PayloadType(), &_decodedFrameCallback);
550   if (renderTimingBefore != _codecDataBase.SupportsRenderScheduling()) {
551     // Make sure we reset the decode time estimate since it will
552     // be zero for codecs without render timing.
553     _timing.ResetDecodeTime();
554   }
555   if (_decoder == NULL) {
556     return VCM_NO_CODEC_REGISTERED;
557   }
558   // Decode a frame
559   int32_t ret = _decoder->Decode(frame, clock_->TimeInMilliseconds());
560
561   // Check for failed decoding, run frame type request callback if needed.
562   bool request_key_frame = false;
563   if (ret < 0) {
564     if (ret == VCM_ERROR_REQUEST_SLI) {
565       return RequestSliceLossIndication(
566           _decodedFrameCallback.LastReceivedPictureID() + 1);
567     } else {
568       WEBRTC_TRACE(webrtc::kTraceError,
569                    webrtc::kTraceVideoCoding,
570                    VCMId(_id),
571                    "Failed to decode frame %u, requesting key frame",
572                    frame.TimeStamp());
573       request_key_frame = true;
574     }
575   } else if (ret == VCM_REQUEST_SLI) {
576     ret = RequestSliceLossIndication(
577         _decodedFrameCallback.LastReceivedPictureID() + 1);
578   }
579   if (!frame.Complete() || frame.MissingFrame()) {
580     switch (_keyRequestMode) {
581       case kKeyOnKeyLoss: {
582         if (frame.FrameType() == kVideoFrameKey) {
583           request_key_frame = true;
584           ret = VCM_OK;
585         }
586         break;
587       }
588       case kKeyOnLoss: {
589         request_key_frame = true;
590         ret = VCM_OK;
591       }
592       default:
593         break;
594     }
595   }
596   if (request_key_frame) {
597     CriticalSectionScoped cs(process_crit_sect_.get());
598     _scheduleKeyRequest = true;
599   }
600   TRACE_EVENT_ASYNC_END0("webrtc", "Video", frame.TimeStamp());
601   return ret;
602 }
603
604 // Reset the decoder state
605 int32_t VideoReceiver::ResetDecoder() {
606   bool reset_key_request = false;
607   {
608     CriticalSectionScoped cs(_receiveCritSect);
609     if (_decoder != NULL) {
610       _receiver.Initialize();
611       _timing.Reset();
612       reset_key_request = true;
613       _decoder->Reset();
614     }
615     if (_dualReceiver.State() != kPassive) {
616       _dualReceiver.Initialize();
617     }
618     if (_dualDecoder != NULL) {
619       _codecDataBase.ReleaseDecoder(_dualDecoder);
620       _dualDecoder = NULL;
621     }
622   }
623   if (reset_key_request) {
624     CriticalSectionScoped cs(process_crit_sect_.get());
625     _scheduleKeyRequest = false;
626   }
627   return VCM_OK;
628 }
629
630 // Register possible receive codecs, can be called multiple times
631 int32_t VideoReceiver::RegisterReceiveCodec(const VideoCodec* receiveCodec,
632                                             int32_t numberOfCores,
633                                             bool requireKeyFrame) {
634   CriticalSectionScoped cs(_receiveCritSect);
635   if (receiveCodec == NULL) {
636     return VCM_PARAMETER_ERROR;
637   }
638   if (!_codecDataBase.RegisterReceiveCodec(
639           receiveCodec, numberOfCores, requireKeyFrame)) {
640     return -1;
641   }
642   return 0;
643 }
644
645 // Get current received codec
646 int32_t VideoReceiver::ReceiveCodec(VideoCodec* currentReceiveCodec) const {
647   CriticalSectionScoped cs(_receiveCritSect);
648   if (currentReceiveCodec == NULL) {
649     return VCM_PARAMETER_ERROR;
650   }
651   return _codecDataBase.ReceiveCodec(currentReceiveCodec) ? 0 : -1;
652 }
653
654 // Get current received codec
655 VideoCodecType VideoReceiver::ReceiveCodec() const {
656   CriticalSectionScoped cs(_receiveCritSect);
657   return _codecDataBase.ReceiveCodec();
658 }
659
660 // Incoming packet from network parsed and ready for decode, non blocking.
661 int32_t VideoReceiver::IncomingPacket(const uint8_t* incomingPayload,
662                                       uint32_t payloadLength,
663                                       const WebRtcRTPHeader& rtpInfo) {
664   if (rtpInfo.frameType == kVideoFrameKey) {
665     TRACE_EVENT1("webrtc",
666                  "VCM::PacketKeyFrame",
667                  "seqnum",
668                  rtpInfo.header.sequenceNumber);
669   }
670   if (incomingPayload == NULL) {
671     // The jitter buffer doesn't handle non-zero payload lengths for packets
672     // without payload.
673     // TODO(holmer): We should fix this in the jitter buffer.
674     payloadLength = 0;
675   }
676   const VCMPacket packet(incomingPayload, payloadLength, rtpInfo);
677   int32_t ret;
678   if (_dualReceiver.State() != kPassive) {
679     ret = _dualReceiver.InsertPacket(
680         packet, rtpInfo.type.Video.width, rtpInfo.type.Video.height);
681     if (ret == VCM_FLUSH_INDICATOR) {
682       RequestKeyFrame();
683       ResetDecoder();
684     } else if (ret < 0) {
685       return ret;
686     }
687   }
688   ret = _receiver.InsertPacket(
689       packet, rtpInfo.type.Video.width, rtpInfo.type.Video.height);
690   // TODO(holmer): Investigate if this somehow should use the key frame
691   // request scheduling to throttle the requests.
692   if (ret == VCM_FLUSH_INDICATOR) {
693     RequestKeyFrame();
694     ResetDecoder();
695   } else if (ret < 0) {
696     return ret;
697   }
698   return VCM_OK;
699 }
700
701 // Minimum playout delay (used for lip-sync). This is the minimum delay required
702 // to sync with audio. Not included in  VideoCodingModule::Delay()
703 // Defaults to 0 ms.
704 int32_t VideoReceiver::SetMinimumPlayoutDelay(uint32_t minPlayoutDelayMs) {
705   _timing.set_min_playout_delay(minPlayoutDelayMs);
706   return VCM_OK;
707 }
708
709 // The estimated delay caused by rendering, defaults to
710 // kDefaultRenderDelayMs = 10 ms
711 int32_t VideoReceiver::SetRenderDelay(uint32_t timeMS) {
712   _timing.set_render_delay(timeMS);
713   return VCM_OK;
714 }
715
716 // Current video delay
717 int32_t VideoReceiver::Delay() const { return _timing.TargetVideoDelay(); }
718
719 // Nack list
720 int32_t VideoReceiver::NackList(uint16_t* nackList, uint16_t* size) {
721   VCMNackStatus nackStatus = kNackOk;
722   uint16_t nack_list_length = 0;
723   // Collect sequence numbers from the default receiver
724   // if in normal nack mode. Otherwise collect them from
725   // the dual receiver if the dual receiver is receiving.
726   if (_receiver.NackMode() != kNoNack) {
727     nackStatus = _receiver.NackList(nackList, *size, &nack_list_length);
728   }
729   if (nack_list_length == 0 && _dualReceiver.State() != kPassive) {
730     nackStatus = _dualReceiver.NackList(nackList, *size, &nack_list_length);
731   }
732   *size = nack_list_length;
733
734   switch (nackStatus) {
735     case kNackNeedMoreMemory: {
736       WEBRTC_TRACE(webrtc::kTraceError,
737                    webrtc::kTraceVideoCoding,
738                    VCMId(_id),
739                    "Out of memory");
740       return VCM_MEMORY;
741     }
742     case kNackKeyFrameRequest: {
743       WEBRTC_TRACE(webrtc::kTraceWarning,
744                    webrtc::kTraceVideoCoding,
745                    VCMId(_id),
746                    "Failed to get NACK list, requesting key frame");
747       return RequestKeyFrame();
748     }
749     default:
750       break;
751   }
752   return VCM_OK;
753 }
754
755 int32_t VideoReceiver::ReceivedFrameCount(VCMFrameCount* frameCount) const {
756   _receiver.ReceivedFrameCount(frameCount);
757   return VCM_OK;
758 }
759
760 uint32_t VideoReceiver::DiscardedPackets() const {
761   return _receiver.DiscardedPackets();
762 }
763
764 int VideoReceiver::SetReceiverRobustnessMode(
765     ReceiverRobustness robustnessMode,
766     VCMDecodeErrorMode decode_error_mode) {
767   CriticalSectionScoped cs(_receiveCritSect);
768   switch (robustnessMode) {
769     case VideoCodingModule::kNone:
770       _receiver.SetNackMode(kNoNack, -1, -1);
771       _dualReceiver.SetNackMode(kNoNack, -1, -1);
772       if (decode_error_mode == kNoErrors) {
773         _keyRequestMode = kKeyOnLoss;
774       } else {
775         _keyRequestMode = kKeyOnError;
776       }
777       break;
778     case VideoCodingModule::kHardNack:
779       // Always wait for retransmissions (except when decoding with errors).
780       _receiver.SetNackMode(kNack, -1, -1);
781       _dualReceiver.SetNackMode(kNoNack, -1, -1);
782       _keyRequestMode = kKeyOnError;  // TODO(hlundin): On long NACK list?
783       break;
784     case VideoCodingModule::kSoftNack:
785       assert(false);  // TODO(hlundin): Not completed.
786       return VCM_NOT_IMPLEMENTED;
787       // Enable hybrid NACK/FEC. Always wait for retransmissions and don't add
788       // extra delay when RTT is above kLowRttNackMs.
789       _receiver.SetNackMode(kNack, media_optimization::kLowRttNackMs, -1);
790       _dualReceiver.SetNackMode(kNoNack, -1, -1);
791       _keyRequestMode = kKeyOnError;
792       break;
793     case VideoCodingModule::kDualDecoder:
794       if (decode_error_mode == kNoErrors) {
795         return VCM_PARAMETER_ERROR;
796       }
797       // Enable NACK but don't wait for retransmissions and don't add any extra
798       // delay.
799       _receiver.SetNackMode(kNack, 0, 0);
800       // Enable NACK, compensate with extra delay and wait for retransmissions.
801       _dualReceiver.SetNackMode(kNack, -1, -1);
802       _keyRequestMode = kKeyOnError;
803       break;
804     case VideoCodingModule::kReferenceSelection:
805       assert(false);  // TODO(hlundin): Not completed.
806       return VCM_NOT_IMPLEMENTED;
807       if (decode_error_mode == kNoErrors) {
808         return VCM_PARAMETER_ERROR;
809       }
810       _receiver.SetNackMode(kNoNack, -1, -1);
811       _dualReceiver.SetNackMode(kNoNack, -1, -1);
812       break;
813   }
814   _receiver.SetDecodeErrorMode(decode_error_mode);
815   // The dual decoder should never decode with errors.
816   _dualReceiver.SetDecodeErrorMode(kNoErrors);
817   return VCM_OK;
818 }
819
820 void VideoReceiver::SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode) {
821   CriticalSectionScoped cs(_receiveCritSect);
822   _receiver.SetDecodeErrorMode(decode_error_mode);
823 }
824
825 void VideoReceiver::SetNackSettings(size_t max_nack_list_size,
826                                     int max_packet_age_to_nack,
827                                     int max_incomplete_time_ms) {
828   if (max_nack_list_size != 0) {
829     CriticalSectionScoped receive_cs(_receiveCritSect);
830     CriticalSectionScoped process_cs(process_crit_sect_.get());
831     max_nack_list_size_ = max_nack_list_size;
832   }
833   _receiver.SetNackSettings(
834       max_nack_list_size, max_packet_age_to_nack, max_incomplete_time_ms);
835   _dualReceiver.SetNackSettings(
836       max_nack_list_size, max_packet_age_to_nack, max_incomplete_time_ms);
837 }
838
839 int VideoReceiver::SetMinReceiverDelay(int desired_delay_ms) {
840   return _receiver.SetMinReceiverDelay(desired_delay_ms);
841 }
842
843 void VideoReceiver::RegisterPreDecodeImageCallback(
844     EncodedImageCallback* observer) {
845   CriticalSectionScoped cs(_receiveCritSect);
846   pre_decode_image_callback_ = observer;
847 }
848
849 }  // namespace vcm
850 }  // namespace webrtc