| /* |
| * libjingle |
| * Copyright 2011, Google Inc. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "talk/app/webrtc/mediastreamtrackproxy.h" |
| |
| #include "talk/session/phone/videocapturer.h" |
| |
| namespace { |
| |
| enum { |
| MSG_REGISTER_OBSERVER = 1, |
| MSG_UNREGISTER_OBSERVER, |
| MSG_LABEL, |
| MSG_ENABLED, |
| MSG_SET_ENABLED, |
| MSG_STATE, |
| MSG_GET_AUDIODEVICE, |
| MSG_GET_VIDEODEVICE, |
| MSG_GET_VIDEORENDERER, |
| MSG_SET_VIDEORENDERER, |
| }; |
| |
| typedef talk_base::TypedMessageData<std::string*> LabelMessageData; |
| typedef talk_base::TypedMessageData<webrtc::ObserverInterface*> |
| ObserverMessageData; |
| typedef talk_base::TypedMessageData |
| <webrtc::MediaStreamTrackInterface::TrackState> TrackStateMessageData; |
| typedef talk_base::TypedMessageData<bool> EnableMessageData; |
| |
| |
| class AudioDeviceMessageData : public talk_base::MessageData { |
| public: |
| talk_base::scoped_refptr<webrtc::AudioDeviceModule> audio_device_; |
| }; |
| |
| class VideoDeviceMessageData : public talk_base::MessageData { |
| public: |
| cricket::VideoCapturer* video_device_; |
| }; |
| |
| class VideoRendererMessageData : public talk_base::MessageData { |
| public: |
| talk_base::scoped_refptr<webrtc::VideoRendererWrapperInterface> |
| video_renderer_; |
| }; |
| |
| } // namespace anonymous |
| |
| namespace webrtc { |
| |
| template <class T> |
| MediaStreamTrackProxy<T>::MediaStreamTrackProxy( |
| talk_base::Thread* signaling_thread) |
| : signaling_thread_(signaling_thread) { |
| } |
| |
| template <class T> |
| void MediaStreamTrackProxy<T>::Init(MediaStreamTrackInterface* track) { |
| track_ = track; |
| } |
| |
| template <class T> |
| std::string MediaStreamTrackProxy<T>::kind() const { |
| return track_->kind(); |
| } |
| |
| template <class T> |
| std::string MediaStreamTrackProxy<T>::label() const { |
| if (!signaling_thread_->IsCurrent()) { |
| std::string label; |
| LabelMessageData msg(&label); |
| Send(MSG_LABEL, &msg); |
| return label; |
| } |
| return track_->label(); |
| } |
| |
| template <class T> |
| MediaStreamTrackInterface::TrackState MediaStreamTrackProxy<T>::state() const { |
| if (!signaling_thread_->IsCurrent()) { |
| TrackStateMessageData msg(MediaStreamTrackInterface::kInitializing); |
| Send(MSG_STATE, &msg); |
| return msg.data(); |
| } |
| return track_->state(); |
| } |
| |
| template <class T> |
| bool MediaStreamTrackProxy<T>::enabled() const { |
| if (!signaling_thread_->IsCurrent()) { |
| EnableMessageData msg(false); |
| Send(MSG_ENABLED, &msg); |
| return msg.data(); |
| } |
| return track_->enabled(); |
| } |
| |
| template <class T> |
| bool MediaStreamTrackProxy<T>::set_enabled(bool enable) { |
| if (!signaling_thread_->IsCurrent()) { |
| EnableMessageData msg(enable); |
| Send(MSG_SET_ENABLED, &msg); |
| return msg.data(); |
| } |
| return track_->set_enabled(enable); |
| } |
| |
| template <class T> |
| bool MediaStreamTrackProxy<T>::set_state( |
| MediaStreamTrackInterface::TrackState new_state) { |
| if (!signaling_thread_->IsCurrent()) { |
| // State should only be allowed to be changed from the signaling thread. |
| ASSERT(!"Not Allowed!"); |
| return false; |
| } |
| return track_->set_state(new_state); |
| } |
| |
| template <class T> |
| void MediaStreamTrackProxy<T>::RegisterObserver(ObserverInterface* observer) { |
| if (!signaling_thread_->IsCurrent()) { |
| ObserverMessageData msg(observer); |
| Send(MSG_REGISTER_OBSERVER, &msg); |
| return; |
| } |
| track_->RegisterObserver(observer); |
| } |
| |
| template <class T> |
| void MediaStreamTrackProxy<T>::UnregisterObserver(ObserverInterface* observer) { |
| if (!signaling_thread_->IsCurrent()) { |
| ObserverMessageData msg(observer); |
| Send(MSG_UNREGISTER_OBSERVER, &msg); |
| return; |
| } |
| track_->UnregisterObserver(observer); |
| } |
| |
| template <class T> |
| void MediaStreamTrackProxy<T>::Send(uint32 id, |
| talk_base::MessageData* data) const { |
| signaling_thread_->Send(const_cast<MediaStreamTrackProxy<T>*>(this), id, |
| data); |
| } |
| |
| template <class T> |
| bool MediaStreamTrackProxy<T>::HandleMessage(talk_base::Message* msg) { |
| talk_base::MessageData* data = msg->pdata; |
| switch (msg->message_id) { |
| case MSG_REGISTER_OBSERVER: { |
| ObserverMessageData* observer = static_cast<ObserverMessageData*>(data); |
| track_->RegisterObserver(observer->data()); |
| return true; |
| break; |
| } |
| case MSG_UNREGISTER_OBSERVER: { |
| ObserverMessageData* observer = static_cast<ObserverMessageData*>(data); |
| track_->UnregisterObserver(observer->data()); |
| return true; |
| break; |
| } |
| case MSG_LABEL: { |
| LabelMessageData* label = static_cast<LabelMessageData*>(data); |
| *(label->data()) = track_->label(); |
| return true; |
| } |
| case MSG_SET_ENABLED: { |
| EnableMessageData* enabled = static_cast<EnableMessageData*>(data); |
| enabled->data() = track_->set_enabled(enabled->data()); |
| return true; |
| break; |
| } |
| case MSG_ENABLED: { |
| EnableMessageData* enabled = static_cast<EnableMessageData*>(data); |
| enabled->data() = track_->enabled(); |
| return true; |
| break; |
| } |
| case MSG_STATE: { |
| TrackStateMessageData* state = static_cast<TrackStateMessageData*>(data); |
| state->data() = track_->state(); |
| return true; |
| break; |
| } |
| default: |
| return false; |
| } |
| } |
| |
| AudioTrackProxy::AudioTrackProxy(const std::string& label, |
| talk_base::Thread* signaling_thread) |
| : MediaStreamTrackProxy<LocalAudioTrackInterface>(signaling_thread), |
| audio_track_(AudioTrack::CreateRemote(label)) { |
| Init(audio_track_); |
| } |
| |
| AudioTrackProxy::AudioTrackProxy(const std::string& label, |
| AudioDeviceModule* audio_device, |
| talk_base::Thread* signaling_thread) |
| : MediaStreamTrackProxy<LocalAudioTrackInterface>(signaling_thread), |
| audio_track_(AudioTrack::CreateLocal(label, audio_device)) { |
| Init(audio_track_); |
| } |
| |
| AudioTrackProxy::AudioTrackProxy(LocalAudioTrackInterface* implementation, |
| talk_base::Thread* signaling_thread) |
| : MediaStreamTrackProxy<LocalAudioTrackInterface>(signaling_thread), |
| audio_track_(implementation) { |
| Init(audio_track_); |
| } |
| |
| talk_base::scoped_refptr<AudioTrackInterface> AudioTrackProxy::CreateRemote( |
| const std::string& label, |
| talk_base::Thread* signaling_thread) { |
| ASSERT(signaling_thread != NULL); |
| talk_base::RefCountedObject<AudioTrackProxy>* track = |
| new talk_base::RefCountedObject<AudioTrackProxy>(label, signaling_thread); |
| return track; |
| } |
| |
| talk_base::scoped_refptr<LocalAudioTrackInterface> AudioTrackProxy::CreateLocal( |
| const std::string& label, |
| AudioDeviceModule* audio_device, |
| talk_base::Thread* signaling_thread) { |
| ASSERT(signaling_thread != NULL); |
| talk_base::RefCountedObject<AudioTrackProxy>* track = |
| new talk_base::RefCountedObject<AudioTrackProxy>(label, |
| audio_device, |
| signaling_thread); |
| return track; |
| } |
| |
| talk_base::scoped_refptr<LocalAudioTrackInterface> AudioTrackProxy::CreateLocal( |
| LocalAudioTrackInterface* implementation, |
| talk_base::Thread* signaling_thread) { |
| ASSERT(signaling_thread != NULL); |
| talk_base::RefCountedObject<AudioTrackProxy>* track = |
| new talk_base::RefCountedObject<AudioTrackProxy>(implementation, |
| signaling_thread); |
| return track; |
| } |
| |
| AudioDeviceModule* AudioTrackProxy::GetAudioDevice() { |
| if (!signaling_thread_->IsCurrent()) { |
| AudioDeviceMessageData msg; |
| Send(MSG_GET_AUDIODEVICE, &msg); |
| return msg.audio_device_; |
| } |
| return audio_track_->GetAudioDevice(); |
| } |
| |
| void AudioTrackProxy::OnMessage(talk_base::Message* msg) { |
| if (!MediaStreamTrackProxy<LocalAudioTrackInterface>::HandleMessage(msg)) { |
| if (msg->message_id == MSG_GET_AUDIODEVICE) { |
| AudioDeviceMessageData* audio_device = |
| static_cast<AudioDeviceMessageData*>(msg->pdata); |
| audio_device->audio_device_ = audio_track_->GetAudioDevice(); |
| } else { |
| ASSERT(!"Not Implemented!"); |
| } |
| } |
| } |
| |
| VideoTrackProxy::VideoTrackProxy(const std::string& label, |
| talk_base::Thread* signaling_thread) |
| : MediaStreamTrackProxy<LocalVideoTrackInterface>(signaling_thread), |
| video_track_(VideoTrack::CreateRemote(label)) { |
| Init(video_track_); |
| } |
| |
| VideoTrackProxy::VideoTrackProxy(const std::string& label, |
| cricket::VideoCapturer* video_device, |
| talk_base::Thread* signaling_thread) |
| : MediaStreamTrackProxy<LocalVideoTrackInterface>(signaling_thread), |
| video_track_(VideoTrack::CreateLocal(label, video_device)) { |
| Init(video_track_); |
| } |
| |
| VideoTrackProxy::VideoTrackProxy(LocalVideoTrackInterface* implementation, |
| talk_base::Thread* signaling_thread) |
| : MediaStreamTrackProxy<LocalVideoTrackInterface>(signaling_thread), |
| video_track_(implementation) { |
| Init(video_track_); |
| } |
| |
| talk_base::scoped_refptr<VideoTrackInterface> VideoTrackProxy::CreateRemote( |
| const std::string& label, |
| talk_base::Thread* signaling_thread) { |
| ASSERT(signaling_thread != NULL); |
| talk_base::RefCountedObject<VideoTrackProxy>* track = |
| new talk_base::RefCountedObject<VideoTrackProxy>(label, signaling_thread); |
| return track; |
| } |
| |
| talk_base::scoped_refptr<LocalVideoTrackInterface> VideoTrackProxy::CreateLocal( |
| const std::string& label, |
| cricket::VideoCapturer* video_device, |
| talk_base::Thread* signaling_thread) { |
| ASSERT(signaling_thread != NULL); |
| talk_base::RefCountedObject<VideoTrackProxy>* track = |
| new talk_base::RefCountedObject<VideoTrackProxy>(label, video_device, |
| signaling_thread); |
| return track; |
| } |
| |
| talk_base::scoped_refptr<LocalVideoTrackInterface> VideoTrackProxy::CreateLocal( |
| LocalVideoTrackInterface* implementation, |
| talk_base::Thread* signaling_thread) { |
| ASSERT(signaling_thread != NULL); |
| talk_base::RefCountedObject<VideoTrackProxy>* track = |
| new talk_base::RefCountedObject<VideoTrackProxy>(implementation, |
| signaling_thread); |
| return track; |
| } |
| |
| cricket::VideoCapturer* VideoTrackProxy::GetVideoCapture() { |
| if (!signaling_thread_->IsCurrent()) { |
| VideoDeviceMessageData msg; |
| Send(MSG_GET_VIDEODEVICE, &msg); |
| return msg.video_device_; |
| } |
| return video_track_->GetVideoCapture(); |
| } |
| |
| void VideoTrackProxy::SetRenderer(VideoRendererWrapperInterface* renderer) { |
| if (!signaling_thread_->IsCurrent()) { |
| VideoRendererMessageData msg; |
| msg.video_renderer_ = renderer; |
| Send(MSG_SET_VIDEORENDERER, &msg); |
| return; |
| } |
| return video_track_->SetRenderer(renderer); |
| } |
| |
| VideoRendererWrapperInterface* VideoTrackProxy::GetRenderer() { |
| if (!signaling_thread_->IsCurrent()) { |
| VideoRendererMessageData msg; |
| Send(MSG_GET_VIDEORENDERER, &msg); |
| return msg.video_renderer_; |
| } |
| return video_track_->GetRenderer(); |
| } |
| |
| void VideoTrackProxy::OnMessage(talk_base::Message* msg) { |
| if (!MediaStreamTrackProxy<LocalVideoTrackInterface>::HandleMessage(msg)) { |
| switch (msg->message_id) { |
| case MSG_GET_VIDEODEVICE: { |
| VideoDeviceMessageData* video_device = |
| static_cast<VideoDeviceMessageData*>(msg->pdata); |
| video_device->video_device_ = video_track_->GetVideoCapture(); |
| break; |
| } |
| case MSG_GET_VIDEORENDERER: { |
| VideoRendererMessageData* video_renderer = |
| static_cast<VideoRendererMessageData*>(msg->pdata); |
| video_renderer->video_renderer_ = video_track_->GetRenderer(); |
| break; |
| } |
| case MSG_SET_VIDEORENDERER: { |
| VideoRendererMessageData* video_renderer = |
| static_cast<VideoRendererMessageData*>(msg->pdata); |
| video_track_->SetRenderer(video_renderer->video_renderer_.get()); |
| break; |
| } |
| default: |
| ASSERT(!"Not Implemented!"); |
| break; |
| } |
| } |
| } |
| |
| } // namespace webrtc |