1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/renderer/media/video_source_handler.h" 6 7 #include <string> 8 9 #include "base/logging.h" 10 #include "content/renderer/media/media_stream_dependency_factory.h" 11 #include "content/renderer/media/media_stream_registry_interface.h" 12 #include "content/renderer/render_thread_impl.h" 13 #include "third_party/WebKit/public/platform/WebMediaStream.h" 14 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h" 15 #include "third_party/libjingle/source/talk/media/base/videoframe.h" 16 #include "third_party/libjingle/source/talk/media/base/videorenderer.h" 17 18 using cricket::VideoFrame; 19 using cricket::VideoRenderer; 20 using webrtc::VideoSourceInterface; 21 22 namespace content { 23 24 // PpFrameReceiver implements cricket::VideoRenderer so that it can be attached 25 // to native video track's video source to receive the captured frame. 26 // It can be attached to a FrameReaderInterface to output the received frame. 27 class PpFrameReceiver : public cricket::VideoRenderer { 28 public: 29 PpFrameReceiver() : reader_(NULL) {} 30 virtual ~PpFrameReceiver() {} 31 32 // Implements VideoRenderer. 33 virtual bool SetSize(int width, int height, int reserved) OVERRIDE { 34 return true; 35 } 36 virtual bool RenderFrame(const cricket::VideoFrame* frame) OVERRIDE { 37 base::AutoLock auto_lock(lock_); 38 if (reader_) { 39 // Make a shallow copy of the frame as the |reader_| may need to queue it. 40 // Both frames will share a single reference-counted frame buffer. 41 reader_->GotFrame(frame->Copy()); 42 } 43 return true; 44 } 45 46 void SetReader(FrameReaderInterface* reader) { 47 base::AutoLock auto_lock(lock_); 48 reader_ = reader; 49 } 50 51 private: 52 FrameReaderInterface* reader_; 53 base::Lock lock_; 54 55 DISALLOW_COPY_AND_ASSIGN(PpFrameReceiver); 56 }; 57 58 VideoSourceHandler::VideoSourceHandler( 59 MediaStreamRegistryInterface* registry) 60 : registry_(registry) { 61 } 62 63 VideoSourceHandler::~VideoSourceHandler() { 64 // All the opened readers should have been closed by now. 65 DCHECK(reader_to_receiver_.empty()); 66 } 67 68 bool VideoSourceHandler::Open(const std::string& url, 69 FrameReaderInterface* reader) { 70 scoped_refptr<webrtc::VideoSourceInterface> source = GetFirstVideoSource(url); 71 if (!source.get()) { 72 return false; 73 } 74 PpFrameReceiver* receiver = new PpFrameReceiver(); 75 receiver->SetReader(reader); 76 source->AddSink(receiver); 77 reader_to_receiver_[reader] = receiver; 78 return true; 79 } 80 81 bool VideoSourceHandler::Close(const std::string& url, 82 FrameReaderInterface* reader) { 83 scoped_refptr<webrtc::VideoSourceInterface> source = GetFirstVideoSource(url); 84 if (!source.get()) { 85 LOG(ERROR) << "VideoSourceHandler::Close - Failed to get the video source " 86 << "from MediaStream with url: " << url; 87 return false; 88 } 89 PpFrameReceiver* receiver = 90 static_cast<PpFrameReceiver*>(GetReceiver(reader)); 91 if (!receiver) { 92 LOG(ERROR) << "VideoSourceHandler::Close - Failed to find receiver that " 93 << "is associated with the given reader."; 94 return false; 95 } 96 receiver->SetReader(NULL); 97 source->RemoveSink(receiver); 98 reader_to_receiver_.erase(reader); 99 delete receiver; 100 return true; 101 } 102 103 scoped_refptr<VideoSourceInterface> VideoSourceHandler::GetFirstVideoSource( 104 const std::string& url) { 105 scoped_refptr<webrtc::VideoSourceInterface> source; 106 blink::WebMediaStream stream; 107 if (registry_) { 108 stream = registry_->GetMediaStream(url); 109 } else { 110 stream = 111 blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url)); 112 } 113 if (stream.isNull() || !stream.extraData()) { 114 LOG(ERROR) << "GetFirstVideoSource - invalid url: " << url; 115 return source; 116 } 117 118 // Get the first video track from the stream. 119 MediaStreamExtraData* extra_data = 120 static_cast<MediaStreamExtraData*>(stream.extraData()); 121 if (!extra_data) { 122 LOG(ERROR) << "GetFirstVideoSource - MediaStreamExtraData is NULL."; 123 return source; 124 } 125 webrtc::MediaStreamInterface* native_stream = extra_data->stream().get(); 126 if (!native_stream) { 127 LOG(ERROR) << "GetFirstVideoSource - native stream is NULL."; 128 return source; 129 } 130 webrtc::VideoTrackVector native_video_tracks = 131 native_stream->GetVideoTracks(); 132 if (native_video_tracks.empty()) { 133 LOG(ERROR) << "GetFirstVideoSource - stream has no video track."; 134 return source; 135 } 136 source = native_video_tracks[0]->GetSource(); 137 return source; 138 } 139 140 VideoRenderer* VideoSourceHandler::GetReceiver( 141 FrameReaderInterface* reader) { 142 std::map<FrameReaderInterface*, VideoRenderer*>::iterator it; 143 it = reader_to_receiver_.find(reader); 144 if (it == reader_to_receiver_.end()) { 145 return NULL; 146 } 147 return it->second; 148 } 149 150 } // namespace content 151 152