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 <stddef.h>
12 
13 #include <cstdint>
14 #include <vector>
15 
16 #include "modules/video_coding/video_receiver2.h"
17 
18 #include "api/video_codecs/video_codec.h"
19 #include "api/video_codecs/video_decoder.h"
20 #include "modules/video_coding/decoder_database.h"
21 #include "modules/video_coding/encoded_frame.h"
22 #include "modules/video_coding/generic_decoder.h"
23 #include "modules/video_coding/include/video_coding_defines.h"
24 #include "modules/video_coding/timing.h"
25 #include "rtc_base/checks.h"
26 #include "rtc_base/trace_event.h"
27 #include "system_wrappers/include/clock.h"
28 
29 namespace webrtc {
30 
VideoReceiver2(Clock * clock,VCMTiming * timing)31 VideoReceiver2::VideoReceiver2(Clock* clock, VCMTiming* timing)
32     : clock_(clock),
33       timing_(timing),
34       decodedFrameCallback_(timing_, clock_),
35       codecDataBase_() {
36   decoder_thread_checker_.Detach();
37 }
38 
~VideoReceiver2()39 VideoReceiver2::~VideoReceiver2() {
40   RTC_DCHECK_RUN_ON(&construction_thread_checker_);
41 }
42 
43 // Register a receive callback. Will be called whenever there is a new frame
44 // ready for rendering.
RegisterReceiveCallback(VCMReceiveCallback * receiveCallback)45 int32_t VideoReceiver2::RegisterReceiveCallback(
46     VCMReceiveCallback* receiveCallback) {
47   RTC_DCHECK_RUN_ON(&construction_thread_checker_);
48   RTC_DCHECK(!IsDecoderThreadRunning());
49   // This value is set before the decoder thread starts and unset after
50   // the decoder thread has been stopped.
51   decodedFrameCallback_.SetUserReceiveCallback(receiveCallback);
52   return VCM_OK;
53 }
54 
55 // Register an externally defined decoder object.
RegisterExternalDecoder(VideoDecoder * externalDecoder,uint8_t payloadType)56 void VideoReceiver2::RegisterExternalDecoder(VideoDecoder* externalDecoder,
57                                              uint8_t payloadType) {
58   RTC_DCHECK_RUN_ON(&construction_thread_checker_);
59   RTC_DCHECK(!IsDecoderThreadRunning());
60   if (externalDecoder == nullptr) {
61     RTC_CHECK(codecDataBase_.DeregisterExternalDecoder(payloadType));
62     return;
63   }
64   codecDataBase_.RegisterExternalDecoder(externalDecoder, payloadType);
65 }
66 
DecoderThreadStarting()67 void VideoReceiver2::DecoderThreadStarting() {
68   RTC_DCHECK_RUN_ON(&construction_thread_checker_);
69   RTC_DCHECK(!IsDecoderThreadRunning());
70 #if RTC_DCHECK_IS_ON
71   decoder_thread_is_running_ = true;
72 #endif
73 }
74 
DecoderThreadStopped()75 void VideoReceiver2::DecoderThreadStopped() {
76   RTC_DCHECK_RUN_ON(&construction_thread_checker_);
77   RTC_DCHECK(IsDecoderThreadRunning());
78 #if RTC_DCHECK_IS_ON
79   decoder_thread_is_running_ = false;
80   decoder_thread_checker_.Detach();
81 #endif
82 }
83 
84 // Must be called from inside the receive side critical section.
Decode(const VCMEncodedFrame * frame)85 int32_t VideoReceiver2::Decode(const VCMEncodedFrame* frame) {
86   RTC_DCHECK_RUN_ON(&decoder_thread_checker_);
87   TRACE_EVENT0("webrtc", "VideoReceiver2::Decode");
88   // Change decoder if payload type has changed
89   VCMGenericDecoder* decoder =
90       codecDataBase_.GetDecoder(*frame, &decodedFrameCallback_);
91   if (decoder == nullptr) {
92     return VCM_NO_CODEC_REGISTERED;
93   }
94   return decoder->Decode(*frame, clock_->CurrentTime());
95 }
96 
97 // Register possible receive codecs, can be called multiple times
RegisterReceiveCodec(const VideoCodec * receiveCodec,int32_t numberOfCores,bool requireKeyFrame)98 int32_t VideoReceiver2::RegisterReceiveCodec(const VideoCodec* receiveCodec,
99                                              int32_t numberOfCores,
100                                              bool requireKeyFrame) {
101   RTC_DCHECK_RUN_ON(&construction_thread_checker_);
102   RTC_DCHECK(!IsDecoderThreadRunning());
103   if (receiveCodec == nullptr) {
104     return VCM_PARAMETER_ERROR;
105   }
106   if (!codecDataBase_.RegisterReceiveCodec(receiveCodec, numberOfCores,
107                                            requireKeyFrame)) {
108     return -1;
109   }
110   return 0;
111 }
112 
IsDecoderThreadRunning()113 bool VideoReceiver2::IsDecoderThreadRunning() {
114 #if RTC_DCHECK_IS_ON
115   return decoder_thread_is_running_;
116 #else
117   return true;
118 #endif
119 }
120 
121 }  // namespace webrtc
122