video_source_handler.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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/Source/WebKit/chromium/public/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 18using cricket::VideoFrame; 19using cricket::VideoRenderer; 20using webrtc::VideoSourceInterface; 21 22namespace 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. 27class 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 58VideoSourceHandler::VideoSourceHandler( 59 MediaStreamRegistryInterface* registry) 60 : registry_(registry) { 61} 62 63VideoSourceHandler::~VideoSourceHandler() { 64 // All the opened readers should have been closed by now. 65 DCHECK(reader_to_receiver_.empty()); 66} 67 68bool 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 81bool 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 103scoped_refptr<VideoSourceInterface> VideoSourceHandler::GetFirstVideoSource( 104 const std::string& url) { 105 scoped_refptr<webrtc::VideoSourceInterface> source; 106 WebKit::WebMediaStream stream; 107 if (registry_) { 108 stream = registry_->GetMediaStream(url); 109 } else { 110 stream = 111 WebKit::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 140VideoRenderer* 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