• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libjingle
3  * Copyright 2004 Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "talk/media/webrtc/webrtcpassthroughrender.h"
29 
30 #include "webrtc/base/common.h"
31 #include "webrtc/base/logging.h"
32 
33 namespace cricket {
34 
35 #define LOG_FIND_STREAM_ERROR(func, id) LOG(LS_ERROR) \
36     << "" << func << " - Failed to find stream: " << id
37 
38 class PassthroughStream: public webrtc::VideoRenderCallback {
39  public:
PassthroughStream(const uint32_t stream_id)40   explicit PassthroughStream(const uint32_t stream_id)
41       : stream_id_(stream_id),
42         running_(false) {
43   }
~PassthroughStream()44   virtual ~PassthroughStream() {
45   }
RenderFrame(const uint32_t stream_id,webrtc::I420VideoFrame & videoFrame)46   virtual int32_t RenderFrame(const uint32_t stream_id,
47                               webrtc::I420VideoFrame& videoFrame) {
48     rtc::CritScope cs(&stream_critical_);
49     // Send frame for rendering directly
50     if (running_ && renderer_) {
51       renderer_->RenderFrame(stream_id, videoFrame);
52     }
53     return 0;
54   }
SetRenderer(VideoRenderCallback * renderer)55   int32_t SetRenderer(VideoRenderCallback* renderer) {
56     rtc::CritScope cs(&stream_critical_);
57     renderer_ = renderer;
58     return 0;
59   }
60 
StartRender()61   int32_t StartRender() {
62     rtc::CritScope cs(&stream_critical_);
63     running_ = true;
64     return 0;
65   }
66 
StopRender()67   int32_t StopRender() {
68     rtc::CritScope cs(&stream_critical_);
69     running_ = false;
70     return 0;
71   }
72 
73  private:
74   uint32_t stream_id_;
75   VideoRenderCallback* renderer_;
76   rtc::CriticalSection stream_critical_;
77   bool running_;
78 };
79 
WebRtcPassthroughRender()80 WebRtcPassthroughRender::WebRtcPassthroughRender()
81     : window_(NULL) {
82 }
83 
~WebRtcPassthroughRender()84 WebRtcPassthroughRender::~WebRtcPassthroughRender() {
85   while (!stream_render_map_.empty()) {
86     PassthroughStream* stream = stream_render_map_.begin()->second;
87     stream_render_map_.erase(stream_render_map_.begin());
88     delete stream;
89   }
90 }
91 
AddIncomingRenderStream(const uint32_t stream_id,const uint32_t zOrder,const float left,const float top,const float right,const float bottom)92 webrtc::VideoRenderCallback* WebRtcPassthroughRender::AddIncomingRenderStream(
93     const uint32_t stream_id,
94     const uint32_t zOrder,
95     const float left, const float top,
96     const float right, const float bottom) {
97   rtc::CritScope cs(&render_critical_);
98   // Stream already exist.
99   if (FindStream(stream_id) != NULL) {
100     LOG(LS_ERROR) << "AddIncomingRenderStream - Stream already exists: "
101                   << stream_id;
102     return NULL;
103   }
104 
105   PassthroughStream* stream = new PassthroughStream(stream_id);
106   // Store the stream
107   stream_render_map_[stream_id] = stream;
108   return stream;
109 }
110 
DeleteIncomingRenderStream(const uint32_t stream_id)111 int32_t WebRtcPassthroughRender::DeleteIncomingRenderStream(
112     const uint32_t stream_id) {
113   rtc::CritScope cs(&render_critical_);
114   PassthroughStream* stream = FindStream(stream_id);
115   if (stream == NULL) {
116     LOG_FIND_STREAM_ERROR("DeleteIncomingRenderStream", stream_id);
117     return -1;
118   }
119   delete stream;
120   stream_render_map_.erase(stream_id);
121   return 0;
122 }
123 
AddExternalRenderCallback(const uint32_t stream_id,webrtc::VideoRenderCallback * render_object)124 int32_t WebRtcPassthroughRender::AddExternalRenderCallback(
125     const uint32_t stream_id,
126     webrtc::VideoRenderCallback* render_object) {
127   rtc::CritScope cs(&render_critical_);
128   PassthroughStream* stream = FindStream(stream_id);
129   if (stream == NULL) {
130     LOG_FIND_STREAM_ERROR("AddExternalRenderCallback", stream_id);
131     return -1;
132   }
133   return stream->SetRenderer(render_object);
134 }
135 
HasIncomingRenderStream(const uint32_t stream_id) const136 bool WebRtcPassthroughRender::HasIncomingRenderStream(
137     const uint32_t stream_id) const {
138   return (FindStream(stream_id) != NULL);
139 }
140 
PreferredVideoType() const141 webrtc::RawVideoType WebRtcPassthroughRender::PreferredVideoType() const {
142   return webrtc::kVideoI420;
143 }
144 
StartRender(const uint32_t stream_id)145 int32_t WebRtcPassthroughRender::StartRender(const uint32_t stream_id) {
146   rtc::CritScope cs(&render_critical_);
147   PassthroughStream* stream = FindStream(stream_id);
148   if (stream == NULL) {
149     LOG_FIND_STREAM_ERROR("StartRender", stream_id);
150     return -1;
151   }
152   return stream->StartRender();
153 }
154 
StopRender(const uint32_t stream_id)155 int32_t WebRtcPassthroughRender::StopRender(const uint32_t stream_id) {
156   rtc::CritScope cs(&render_critical_);
157   PassthroughStream* stream = FindStream(stream_id);
158   if (stream == NULL) {
159     LOG_FIND_STREAM_ERROR("StopRender", stream_id);
160     return -1;
161   }
162   return stream->StopRender();
163 }
164 
165 // TODO(ronghuawu): Is it ok to return non-const pointer to PassthroughStream
166 // from this const function FindStream.
FindStream(const uint32_t stream_id) const167 PassthroughStream* WebRtcPassthroughRender::FindStream(
168     const uint32_t stream_id) const {
169   StreamMap::const_iterator it = stream_render_map_.find(stream_id);
170   if (it == stream_render_map_.end()) {
171     return NULL;
172   }
173   return it->second;
174 }
175 
176 }  // namespace cricket
177