| OLD | NEW | 
|---|
|  | (Empty) | 
| 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/base/checks.h" |  | 
| 12 #include "webrtc/base/logging.h" |  | 
| 13 #include "webrtc/base/trace_event.h" |  | 
| 14 #include "webrtc/common_types.h" |  | 
| 15 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |  | 
| 16 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" |  | 
| 17 #include "webrtc/modules/video_coding/main/source/encoded_frame.h" |  | 
| 18 #include "webrtc/modules/video_coding/main/source/jitter_buffer.h" |  | 
| 19 #include "webrtc/modules/video_coding/main/source/packet.h" |  | 
| 20 #include "webrtc/modules/video_coding/main/source/video_coding_impl.h" |  | 
| 21 #include "webrtc/system_wrappers/include/clock.h" |  | 
| 22 |  | 
| 23 // #define DEBUG_DECODER_BIT_STREAM |  | 
| 24 |  | 
| 25 namespace webrtc { |  | 
| 26 namespace vcm { |  | 
| 27 |  | 
| 28 VideoReceiver::VideoReceiver(Clock* clock, EventFactory* event_factory) |  | 
| 29     : clock_(clock), |  | 
| 30       process_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), |  | 
| 31       _receiveCritSect(CriticalSectionWrapper::CreateCriticalSection()), |  | 
| 32       _timing(clock_), |  | 
| 33       _receiver(&_timing, clock_, event_factory), |  | 
| 34       _decodedFrameCallback(_timing, clock_), |  | 
| 35       _frameTypeCallback(NULL), |  | 
| 36       _receiveStatsCallback(NULL), |  | 
| 37       _decoderTimingCallback(NULL), |  | 
| 38       _packetRequestCallback(NULL), |  | 
| 39       render_buffer_callback_(NULL), |  | 
| 40       _decoder(NULL), |  | 
| 41 #ifdef DEBUG_DECODER_BIT_STREAM |  | 
| 42       _bitStreamBeforeDecoder(NULL), |  | 
| 43 #endif |  | 
| 44       _frameFromFile(), |  | 
| 45       _scheduleKeyRequest(false), |  | 
| 46       max_nack_list_size_(0), |  | 
| 47       pre_decode_image_callback_(NULL), |  | 
| 48       _codecDataBase(nullptr, nullptr), |  | 
| 49       _receiveStatsTimer(1000, clock_), |  | 
| 50       _retransmissionTimer(10, clock_), |  | 
| 51       _keyRequestTimer(500, clock_) { |  | 
| 52   assert(clock_); |  | 
| 53 #ifdef DEBUG_DECODER_BIT_STREAM |  | 
| 54   _bitStreamBeforeDecoder = fopen("decoderBitStream.bit", "wb"); |  | 
| 55 #endif |  | 
| 56 } |  | 
| 57 |  | 
| 58 VideoReceiver::~VideoReceiver() { |  | 
| 59   delete _receiveCritSect; |  | 
| 60 #ifdef DEBUG_DECODER_BIT_STREAM |  | 
| 61   fclose(_bitStreamBeforeDecoder); |  | 
| 62 #endif |  | 
| 63 } |  | 
| 64 |  | 
| 65 int32_t VideoReceiver::Process() { |  | 
| 66   int32_t returnValue = VCM_OK; |  | 
| 67 |  | 
| 68   // Receive-side statistics |  | 
| 69   if (_receiveStatsTimer.TimeUntilProcess() == 0) { |  | 
| 70     _receiveStatsTimer.Processed(); |  | 
| 71     CriticalSectionScoped cs(process_crit_sect_.get()); |  | 
| 72     if (_receiveStatsCallback != NULL) { |  | 
| 73       uint32_t bitRate; |  | 
| 74       uint32_t frameRate; |  | 
| 75       _receiver.ReceiveStatistics(&bitRate, &frameRate); |  | 
| 76       _receiveStatsCallback->OnReceiveRatesUpdated(bitRate, frameRate); |  | 
| 77     } |  | 
| 78 |  | 
| 79     if (_decoderTimingCallback != NULL) { |  | 
| 80       int decode_ms; |  | 
| 81       int max_decode_ms; |  | 
| 82       int current_delay_ms; |  | 
| 83       int target_delay_ms; |  | 
| 84       int jitter_buffer_ms; |  | 
| 85       int min_playout_delay_ms; |  | 
| 86       int render_delay_ms; |  | 
| 87       _timing.GetTimings(&decode_ms, |  | 
| 88                          &max_decode_ms, |  | 
| 89                          ¤t_delay_ms, |  | 
| 90                          &target_delay_ms, |  | 
| 91                          &jitter_buffer_ms, |  | 
| 92                          &min_playout_delay_ms, |  | 
| 93                          &render_delay_ms); |  | 
| 94       _decoderTimingCallback->OnDecoderTiming(decode_ms, |  | 
| 95                                               max_decode_ms, |  | 
| 96                                               current_delay_ms, |  | 
| 97                                               target_delay_ms, |  | 
| 98                                               jitter_buffer_ms, |  | 
| 99                                               min_playout_delay_ms, |  | 
| 100                                               render_delay_ms); |  | 
| 101     } |  | 
| 102 |  | 
| 103     // Size of render buffer. |  | 
| 104     if (render_buffer_callback_) { |  | 
| 105       int buffer_size_ms = _receiver.RenderBufferSizeMs(); |  | 
| 106       render_buffer_callback_->RenderBufferSizeMs(buffer_size_ms); |  | 
| 107     } |  | 
| 108   } |  | 
| 109 |  | 
| 110   // Key frame requests |  | 
| 111   if (_keyRequestTimer.TimeUntilProcess() == 0) { |  | 
| 112     _keyRequestTimer.Processed(); |  | 
| 113     bool request_key_frame = false; |  | 
| 114     { |  | 
| 115       CriticalSectionScoped cs(process_crit_sect_.get()); |  | 
| 116       request_key_frame = _scheduleKeyRequest && _frameTypeCallback != NULL; |  | 
| 117     } |  | 
| 118     if (request_key_frame) { |  | 
| 119       const int32_t ret = RequestKeyFrame(); |  | 
| 120       if (ret != VCM_OK && returnValue == VCM_OK) { |  | 
| 121         returnValue = ret; |  | 
| 122       } |  | 
| 123     } |  | 
| 124   } |  | 
| 125 |  | 
| 126   // Packet retransmission requests |  | 
| 127   // TODO(holmer): Add API for changing Process interval and make sure it's |  | 
| 128   // disabled when NACK is off. |  | 
| 129   if (_retransmissionTimer.TimeUntilProcess() == 0) { |  | 
| 130     _retransmissionTimer.Processed(); |  | 
| 131     bool callback_registered = false; |  | 
| 132     uint16_t length; |  | 
| 133     { |  | 
| 134       CriticalSectionScoped cs(process_crit_sect_.get()); |  | 
| 135       length = max_nack_list_size_; |  | 
| 136       callback_registered = _packetRequestCallback != NULL; |  | 
| 137     } |  | 
| 138     if (callback_registered && length > 0) { |  | 
| 139       // Collect sequence numbers from the default receiver. |  | 
| 140       bool request_key_frame = false; |  | 
| 141       std::vector<uint16_t> nackList = _receiver.NackList(&request_key_frame); |  | 
| 142       int32_t ret = VCM_OK; |  | 
| 143       if (request_key_frame) { |  | 
| 144         ret = RequestKeyFrame(); |  | 
| 145         if (ret != VCM_OK && returnValue == VCM_OK) { |  | 
| 146           returnValue = ret; |  | 
| 147         } |  | 
| 148       } |  | 
| 149       if (ret == VCM_OK && !nackList.empty()) { |  | 
| 150         CriticalSectionScoped cs(process_crit_sect_.get()); |  | 
| 151         if (_packetRequestCallback != NULL) { |  | 
| 152           _packetRequestCallback->ResendPackets(&nackList[0], nackList.size()); |  | 
| 153         } |  | 
| 154       } |  | 
| 155     } |  | 
| 156   } |  | 
| 157 |  | 
| 158   return returnValue; |  | 
| 159 } |  | 
| 160 |  | 
| 161 int64_t VideoReceiver::TimeUntilNextProcess() { |  | 
| 162   int64_t timeUntilNextProcess = _receiveStatsTimer.TimeUntilProcess(); |  | 
| 163   if (_receiver.NackMode() != kNoNack) { |  | 
| 164     // We need a Process call more often if we are relying on |  | 
| 165     // retransmissions |  | 
| 166     timeUntilNextProcess = |  | 
| 167         VCM_MIN(timeUntilNextProcess, _retransmissionTimer.TimeUntilProcess()); |  | 
| 168   } |  | 
| 169   timeUntilNextProcess = |  | 
| 170       VCM_MIN(timeUntilNextProcess, _keyRequestTimer.TimeUntilProcess()); |  | 
| 171 |  | 
| 172   return timeUntilNextProcess; |  | 
| 173 } |  | 
| 174 |  | 
| 175 int32_t VideoReceiver::SetReceiveChannelParameters(int64_t rtt) { |  | 
| 176   CriticalSectionScoped receiveCs(_receiveCritSect); |  | 
| 177   _receiver.UpdateRtt(rtt); |  | 
| 178   return 0; |  | 
| 179 } |  | 
| 180 |  | 
| 181 // Enable or disable a video protection method. |  | 
| 182 // Note: This API should be deprecated, as it does not offer a distinction |  | 
| 183 // between the protection method and decoding with or without errors. If such a |  | 
| 184 // behavior is desired, use the following API: SetReceiverRobustnessMode. |  | 
| 185 int32_t VideoReceiver::SetVideoProtection(VCMVideoProtection videoProtection, |  | 
| 186                                           bool enable) { |  | 
| 187   // By default, do not decode with errors. |  | 
| 188   _receiver.SetDecodeErrorMode(kNoErrors); |  | 
| 189   switch (videoProtection) { |  | 
| 190     case kProtectionNack: { |  | 
| 191       RTC_DCHECK(enable); |  | 
| 192       _receiver.SetNackMode(kNack, -1, -1); |  | 
| 193       break; |  | 
| 194     } |  | 
| 195 |  | 
| 196     case kProtectionNackFEC: { |  | 
| 197       CriticalSectionScoped cs(_receiveCritSect); |  | 
| 198       RTC_DCHECK(enable); |  | 
| 199       _receiver.SetNackMode(kNack, media_optimization::kLowRttNackMs, -1); |  | 
| 200       _receiver.SetDecodeErrorMode(kNoErrors); |  | 
| 201       break; |  | 
| 202     } |  | 
| 203     case kProtectionFEC: |  | 
| 204     case kProtectionNone: |  | 
| 205       // No receiver-side protection. |  | 
| 206       RTC_DCHECK(enable); |  | 
| 207       _receiver.SetNackMode(kNoNack, -1, -1); |  | 
| 208       _receiver.SetDecodeErrorMode(kWithErrors); |  | 
| 209       break; |  | 
| 210   } |  | 
| 211   return VCM_OK; |  | 
| 212 } |  | 
| 213 |  | 
| 214 // Register a receive callback. Will be called whenever there is a new frame |  | 
| 215 // ready for rendering. |  | 
| 216 int32_t VideoReceiver::RegisterReceiveCallback( |  | 
| 217     VCMReceiveCallback* receiveCallback) { |  | 
| 218   CriticalSectionScoped cs(_receiveCritSect); |  | 
| 219   _decodedFrameCallback.SetUserReceiveCallback(receiveCallback); |  | 
| 220   return VCM_OK; |  | 
| 221 } |  | 
| 222 |  | 
| 223 int32_t VideoReceiver::RegisterReceiveStatisticsCallback( |  | 
| 224     VCMReceiveStatisticsCallback* receiveStats) { |  | 
| 225   CriticalSectionScoped cs(process_crit_sect_.get()); |  | 
| 226   _receiver.RegisterStatsCallback(receiveStats); |  | 
| 227   _receiveStatsCallback = receiveStats; |  | 
| 228   return VCM_OK; |  | 
| 229 } |  | 
| 230 |  | 
| 231 int32_t VideoReceiver::RegisterDecoderTimingCallback( |  | 
| 232     VCMDecoderTimingCallback* decoderTiming) { |  | 
| 233   CriticalSectionScoped cs(process_crit_sect_.get()); |  | 
| 234   _decoderTimingCallback = decoderTiming; |  | 
| 235   return VCM_OK; |  | 
| 236 } |  | 
| 237 |  | 
| 238 // Register an externally defined decoder/render object. |  | 
| 239 // Can be a decoder only or a decoder coupled with a renderer. |  | 
| 240 int32_t VideoReceiver::RegisterExternalDecoder(VideoDecoder* externalDecoder, |  | 
| 241                                                uint8_t payloadType, |  | 
| 242                                                bool internalRenderTiming) { |  | 
| 243   CriticalSectionScoped cs(_receiveCritSect); |  | 
| 244   if (externalDecoder == NULL) { |  | 
| 245     // Make sure the VCM updates the decoder next time it decodes. |  | 
| 246     _decoder = NULL; |  | 
| 247     return _codecDataBase.DeregisterExternalDecoder(payloadType) ? 0 : -1; |  | 
| 248   } |  | 
| 249   return _codecDataBase.RegisterExternalDecoder( |  | 
| 250              externalDecoder, payloadType, internalRenderTiming) |  | 
| 251              ? 0 |  | 
| 252              : -1; |  | 
| 253 } |  | 
| 254 |  | 
| 255 // Register a frame type request callback. |  | 
| 256 int32_t VideoReceiver::RegisterFrameTypeCallback( |  | 
| 257     VCMFrameTypeCallback* frameTypeCallback) { |  | 
| 258   CriticalSectionScoped cs(process_crit_sect_.get()); |  | 
| 259   _frameTypeCallback = frameTypeCallback; |  | 
| 260   return VCM_OK; |  | 
| 261 } |  | 
| 262 |  | 
| 263 int32_t VideoReceiver::RegisterPacketRequestCallback( |  | 
| 264     VCMPacketRequestCallback* callback) { |  | 
| 265   CriticalSectionScoped cs(process_crit_sect_.get()); |  | 
| 266   _packetRequestCallback = callback; |  | 
| 267   return VCM_OK; |  | 
| 268 } |  | 
| 269 |  | 
| 270 int VideoReceiver::RegisterRenderBufferSizeCallback( |  | 
| 271     VCMRenderBufferSizeCallback* callback) { |  | 
| 272   CriticalSectionScoped cs(process_crit_sect_.get()); |  | 
| 273   render_buffer_callback_ = callback; |  | 
| 274   return VCM_OK; |  | 
| 275 } |  | 
| 276 |  | 
| 277 void VideoReceiver::TriggerDecoderShutdown() { |  | 
| 278   _receiver.TriggerDecoderShutdown(); |  | 
| 279 } |  | 
| 280 |  | 
| 281 // Decode next frame, blocking. |  | 
| 282 // Should be called as often as possible to get the most out of the decoder. |  | 
| 283 int32_t VideoReceiver::Decode(uint16_t maxWaitTimeMs) { |  | 
| 284   int64_t nextRenderTimeMs; |  | 
| 285   bool supports_render_scheduling; |  | 
| 286   { |  | 
| 287     CriticalSectionScoped cs(_receiveCritSect); |  | 
| 288     supports_render_scheduling = _codecDataBase.SupportsRenderScheduling(); |  | 
| 289   } |  | 
| 290 |  | 
| 291   VCMEncodedFrame* frame = _receiver.FrameForDecoding( |  | 
| 292       maxWaitTimeMs, nextRenderTimeMs, supports_render_scheduling); |  | 
| 293 |  | 
| 294   if (frame == NULL) { |  | 
| 295     return VCM_FRAME_NOT_READY; |  | 
| 296   } else { |  | 
| 297     CriticalSectionScoped cs(_receiveCritSect); |  | 
| 298 |  | 
| 299     // If this frame was too late, we should adjust the delay accordingly |  | 
| 300     _timing.UpdateCurrentDelay(frame->RenderTimeMs(), |  | 
| 301                                clock_->TimeInMilliseconds()); |  | 
| 302 |  | 
| 303     if (pre_decode_image_callback_) { |  | 
| 304       EncodedImage encoded_image(frame->EncodedImage()); |  | 
| 305       int qp = -1; |  | 
| 306       if (qp_parser_.GetQp(*frame, &qp)) { |  | 
| 307         encoded_image.qp_ = qp; |  | 
| 308       } |  | 
| 309       pre_decode_image_callback_->Encoded( |  | 
| 310           encoded_image, frame->CodecSpecific(), NULL); |  | 
| 311     } |  | 
| 312 |  | 
| 313 #ifdef DEBUG_DECODER_BIT_STREAM |  | 
| 314     if (_bitStreamBeforeDecoder != NULL) { |  | 
| 315       // Write bit stream to file for debugging purposes |  | 
| 316       if (fwrite( |  | 
| 317               frame->Buffer(), 1, frame->Length(), _bitStreamBeforeDecoder) != |  | 
| 318           frame->Length()) { |  | 
| 319         return -1; |  | 
| 320       } |  | 
| 321     } |  | 
| 322 #endif |  | 
| 323     const int32_t ret = Decode(*frame); |  | 
| 324     _receiver.ReleaseFrame(frame); |  | 
| 325     frame = NULL; |  | 
| 326     if (ret != VCM_OK) { |  | 
| 327       return ret; |  | 
| 328     } |  | 
| 329   } |  | 
| 330   return VCM_OK; |  | 
| 331 } |  | 
| 332 |  | 
| 333 int32_t VideoReceiver::RequestSliceLossIndication( |  | 
| 334     const uint64_t pictureID) const { |  | 
| 335   TRACE_EVENT1("webrtc", "RequestSLI", "picture_id", pictureID); |  | 
| 336   CriticalSectionScoped cs(process_crit_sect_.get()); |  | 
| 337   if (_frameTypeCallback != NULL) { |  | 
| 338     const int32_t ret = |  | 
| 339         _frameTypeCallback->SliceLossIndicationRequest(pictureID); |  | 
| 340     if (ret < 0) { |  | 
| 341       return ret; |  | 
| 342     } |  | 
| 343   } else { |  | 
| 344     return VCM_MISSING_CALLBACK; |  | 
| 345   } |  | 
| 346   return VCM_OK; |  | 
| 347 } |  | 
| 348 |  | 
| 349 int32_t VideoReceiver::RequestKeyFrame() { |  | 
| 350   TRACE_EVENT0("webrtc", "RequestKeyFrame"); |  | 
| 351   CriticalSectionScoped process_cs(process_crit_sect_.get()); |  | 
| 352   if (_frameTypeCallback != NULL) { |  | 
| 353     const int32_t ret = _frameTypeCallback->RequestKeyFrame(); |  | 
| 354     if (ret < 0) { |  | 
| 355       return ret; |  | 
| 356     } |  | 
| 357     _scheduleKeyRequest = false; |  | 
| 358   } else { |  | 
| 359     return VCM_MISSING_CALLBACK; |  | 
| 360   } |  | 
| 361   return VCM_OK; |  | 
| 362 } |  | 
| 363 |  | 
| 364 // Must be called from inside the receive side critical section. |  | 
| 365 int32_t VideoReceiver::Decode(const VCMEncodedFrame& frame) { |  | 
| 366   TRACE_EVENT_ASYNC_STEP1("webrtc", |  | 
| 367                           "Video", |  | 
| 368                           frame.TimeStamp(), |  | 
| 369                           "Decode", |  | 
| 370                           "type", |  | 
| 371                           frame.FrameType()); |  | 
| 372   // Change decoder if payload type has changed |  | 
| 373   const bool renderTimingBefore = _codecDataBase.SupportsRenderScheduling(); |  | 
| 374   _decoder = |  | 
| 375       _codecDataBase.GetDecoder(frame.PayloadType(), &_decodedFrameCallback); |  | 
| 376   if (renderTimingBefore != _codecDataBase.SupportsRenderScheduling()) { |  | 
| 377     // Make sure we reset the decode time estimate since it will |  | 
| 378     // be zero for codecs without render timing. |  | 
| 379     _timing.ResetDecodeTime(); |  | 
| 380   } |  | 
| 381   if (_decoder == NULL) { |  | 
| 382     return VCM_NO_CODEC_REGISTERED; |  | 
| 383   } |  | 
| 384   // Decode a frame |  | 
| 385   int32_t ret = _decoder->Decode(frame, clock_->TimeInMilliseconds()); |  | 
| 386 |  | 
| 387   // Check for failed decoding, run frame type request callback if needed. |  | 
| 388   bool request_key_frame = false; |  | 
| 389   if (ret < 0) { |  | 
| 390     if (ret == VCM_ERROR_REQUEST_SLI) { |  | 
| 391       return RequestSliceLossIndication( |  | 
| 392           _decodedFrameCallback.LastReceivedPictureID() + 1); |  | 
| 393     } else { |  | 
| 394       request_key_frame = true; |  | 
| 395     } |  | 
| 396   } else if (ret == VCM_REQUEST_SLI) { |  | 
| 397     ret = RequestSliceLossIndication( |  | 
| 398         _decodedFrameCallback.LastReceivedPictureID() + 1); |  | 
| 399   } |  | 
| 400   if (!frame.Complete() || frame.MissingFrame()) { |  | 
| 401     request_key_frame = true; |  | 
| 402     ret = VCM_OK; |  | 
| 403   } |  | 
| 404   if (request_key_frame) { |  | 
| 405     CriticalSectionScoped cs(process_crit_sect_.get()); |  | 
| 406     _scheduleKeyRequest = true; |  | 
| 407   } |  | 
| 408   TRACE_EVENT_ASYNC_END0("webrtc", "Video", frame.TimeStamp()); |  | 
| 409   return ret; |  | 
| 410 } |  | 
| 411 |  | 
| 412 // Reset the decoder state |  | 
| 413 int32_t VideoReceiver::ResetDecoder() { |  | 
| 414   bool reset_key_request = false; |  | 
| 415   { |  | 
| 416     CriticalSectionScoped cs(_receiveCritSect); |  | 
| 417     if (_decoder != NULL) { |  | 
| 418       _receiver.Reset(); |  | 
| 419       _timing.Reset(); |  | 
| 420       reset_key_request = true; |  | 
| 421       _decoder->Reset(); |  | 
| 422     } |  | 
| 423   } |  | 
| 424   if (reset_key_request) { |  | 
| 425     CriticalSectionScoped cs(process_crit_sect_.get()); |  | 
| 426     _scheduleKeyRequest = false; |  | 
| 427   } |  | 
| 428   return VCM_OK; |  | 
| 429 } |  | 
| 430 |  | 
| 431 // Register possible receive codecs, can be called multiple times |  | 
| 432 int32_t VideoReceiver::RegisterReceiveCodec(const VideoCodec* receiveCodec, |  | 
| 433                                             int32_t numberOfCores, |  | 
| 434                                             bool requireKeyFrame) { |  | 
| 435   CriticalSectionScoped cs(_receiveCritSect); |  | 
| 436   if (receiveCodec == NULL) { |  | 
| 437     return VCM_PARAMETER_ERROR; |  | 
| 438   } |  | 
| 439   if (!_codecDataBase.RegisterReceiveCodec( |  | 
| 440           receiveCodec, numberOfCores, requireKeyFrame)) { |  | 
| 441     return -1; |  | 
| 442   } |  | 
| 443   return 0; |  | 
| 444 } |  | 
| 445 |  | 
| 446 // Get current received codec |  | 
| 447 int32_t VideoReceiver::ReceiveCodec(VideoCodec* currentReceiveCodec) const { |  | 
| 448   CriticalSectionScoped cs(_receiveCritSect); |  | 
| 449   if (currentReceiveCodec == NULL) { |  | 
| 450     return VCM_PARAMETER_ERROR; |  | 
| 451   } |  | 
| 452   return _codecDataBase.ReceiveCodec(currentReceiveCodec) ? 0 : -1; |  | 
| 453 } |  | 
| 454 |  | 
| 455 // Get current received codec |  | 
| 456 VideoCodecType VideoReceiver::ReceiveCodec() const { |  | 
| 457   CriticalSectionScoped cs(_receiveCritSect); |  | 
| 458   return _codecDataBase.ReceiveCodec(); |  | 
| 459 } |  | 
| 460 |  | 
| 461 // Incoming packet from network parsed and ready for decode, non blocking. |  | 
| 462 int32_t VideoReceiver::IncomingPacket(const uint8_t* incomingPayload, |  | 
| 463                                       size_t payloadLength, |  | 
| 464                                       const WebRtcRTPHeader& rtpInfo) { |  | 
| 465   if (rtpInfo.frameType == kVideoFrameKey) { |  | 
| 466     TRACE_EVENT1("webrtc", |  | 
| 467                  "VCM::PacketKeyFrame", |  | 
| 468                  "seqnum", |  | 
| 469                  rtpInfo.header.sequenceNumber); |  | 
| 470   } |  | 
| 471   if (incomingPayload == NULL) { |  | 
| 472     // The jitter buffer doesn't handle non-zero payload lengths for packets |  | 
| 473     // without payload. |  | 
| 474     // TODO(holmer): We should fix this in the jitter buffer. |  | 
| 475     payloadLength = 0; |  | 
| 476   } |  | 
| 477   const VCMPacket packet(incomingPayload, payloadLength, rtpInfo); |  | 
| 478   int32_t ret = _receiver.InsertPacket(packet, rtpInfo.type.Video.width, |  | 
| 479                                        rtpInfo.type.Video.height); |  | 
| 480   // TODO(holmer): Investigate if this somehow should use the key frame |  | 
| 481   // request scheduling to throttle the requests. |  | 
| 482   if (ret == VCM_FLUSH_INDICATOR) { |  | 
| 483     RequestKeyFrame(); |  | 
| 484     ResetDecoder(); |  | 
| 485   } else if (ret < 0) { |  | 
| 486     return ret; |  | 
| 487   } |  | 
| 488   return VCM_OK; |  | 
| 489 } |  | 
| 490 |  | 
| 491 // Minimum playout delay (used for lip-sync). This is the minimum delay required |  | 
| 492 // to sync with audio. Not included in  VideoCodingModule::Delay() |  | 
| 493 // Defaults to 0 ms. |  | 
| 494 int32_t VideoReceiver::SetMinimumPlayoutDelay(uint32_t minPlayoutDelayMs) { |  | 
| 495   _timing.set_min_playout_delay(minPlayoutDelayMs); |  | 
| 496   return VCM_OK; |  | 
| 497 } |  | 
| 498 |  | 
| 499 // The estimated delay caused by rendering, defaults to |  | 
| 500 // kDefaultRenderDelayMs = 10 ms |  | 
| 501 int32_t VideoReceiver::SetRenderDelay(uint32_t timeMS) { |  | 
| 502   _timing.set_render_delay(timeMS); |  | 
| 503   return VCM_OK; |  | 
| 504 } |  | 
| 505 |  | 
| 506 // Current video delay |  | 
| 507 int32_t VideoReceiver::Delay() const { return _timing.TargetVideoDelay(); } |  | 
| 508 |  | 
| 509 uint32_t VideoReceiver::DiscardedPackets() const { |  | 
| 510   return _receiver.DiscardedPackets(); |  | 
| 511 } |  | 
| 512 |  | 
| 513 int VideoReceiver::SetReceiverRobustnessMode( |  | 
| 514     ReceiverRobustness robustnessMode, |  | 
| 515     VCMDecodeErrorMode decode_error_mode) { |  | 
| 516   CriticalSectionScoped cs(_receiveCritSect); |  | 
| 517   switch (robustnessMode) { |  | 
| 518     case VideoCodingModule::kNone: |  | 
| 519       _receiver.SetNackMode(kNoNack, -1, -1); |  | 
| 520       break; |  | 
| 521     case VideoCodingModule::kHardNack: |  | 
| 522       // Always wait for retransmissions (except when decoding with errors). |  | 
| 523       _receiver.SetNackMode(kNack, -1, -1); |  | 
| 524       break; |  | 
| 525     case VideoCodingModule::kSoftNack: |  | 
| 526 #if 1 |  | 
| 527       assert(false);  // TODO(hlundin): Not completed. |  | 
| 528       return VCM_NOT_IMPLEMENTED; |  | 
| 529 #else |  | 
| 530       // Enable hybrid NACK/FEC. Always wait for retransmissions and don't add |  | 
| 531       // extra delay when RTT is above kLowRttNackMs. |  | 
| 532       _receiver.SetNackMode(kNack, media_optimization::kLowRttNackMs, -1); |  | 
| 533       break; |  | 
| 534 #endif |  | 
| 535     case VideoCodingModule::kReferenceSelection: |  | 
| 536 #if 1 |  | 
| 537       assert(false);  // TODO(hlundin): Not completed. |  | 
| 538       return VCM_NOT_IMPLEMENTED; |  | 
| 539 #else |  | 
| 540       if (decode_error_mode == kNoErrors) { |  | 
| 541         return VCM_PARAMETER_ERROR; |  | 
| 542       } |  | 
| 543       _receiver.SetNackMode(kNoNack, -1, -1); |  | 
| 544       break; |  | 
| 545 #endif |  | 
| 546   } |  | 
| 547   _receiver.SetDecodeErrorMode(decode_error_mode); |  | 
| 548   return VCM_OK; |  | 
| 549 } |  | 
| 550 |  | 
| 551 void VideoReceiver::SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode) { |  | 
| 552   CriticalSectionScoped cs(_receiveCritSect); |  | 
| 553   _receiver.SetDecodeErrorMode(decode_error_mode); |  | 
| 554 } |  | 
| 555 |  | 
| 556 void VideoReceiver::SetNackSettings(size_t max_nack_list_size, |  | 
| 557                                     int max_packet_age_to_nack, |  | 
| 558                                     int max_incomplete_time_ms) { |  | 
| 559   if (max_nack_list_size != 0) { |  | 
| 560     CriticalSectionScoped process_cs(process_crit_sect_.get()); |  | 
| 561     max_nack_list_size_ = max_nack_list_size; |  | 
| 562   } |  | 
| 563   _receiver.SetNackSettings( |  | 
| 564       max_nack_list_size, max_packet_age_to_nack, max_incomplete_time_ms); |  | 
| 565 } |  | 
| 566 |  | 
| 567 int VideoReceiver::SetMinReceiverDelay(int desired_delay_ms) { |  | 
| 568   return _receiver.SetMinReceiverDelay(desired_delay_ms); |  | 
| 569 } |  | 
| 570 |  | 
| 571 void VideoReceiver::RegisterPreDecodeImageCallback( |  | 
| 572     EncodedImageCallback* observer) { |  | 
| 573   CriticalSectionScoped cs(_receiveCritSect); |  | 
| 574   pre_decode_image_callback_ = observer; |  | 
| 575 } |  | 
| 576 |  | 
| 577 }  // namespace vcm |  | 
| 578 }  // namespace webrtc |  | 
| OLD | NEW | 
|---|