video_source_handler.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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.h" 11#include "content/renderer/media/media_stream_dependency_factory.h" 12#include "content/renderer/media/media_stream_registry_interface.h" 13#include "content/renderer/render_thread_impl.h" 14#include "third_party/WebKit/public/platform/WebMediaStream.h" 15#include "third_party/WebKit/public/web/WebMediaStreamRegistry.h" 16#include "third_party/libjingle/source/talk/media/base/videoframe.h" 17#include "third_party/libjingle/source/talk/media/base/videorenderer.h" 18 19using cricket::VideoFrame; 20using cricket::VideoRenderer; 21using webrtc::VideoSourceInterface; 22 23namespace content { 24 25// PpFrameReceiver implements cricket::VideoRenderer so that it can be attached 26// to native video track's video source to receive the captured frame. 27// It can be attached to a FrameReaderInterface to output the received frame. 28class PpFrameReceiver : public cricket::VideoRenderer { 29 public: 30 PpFrameReceiver() : reader_(NULL) {} 31 virtual ~PpFrameReceiver() {} 32 33 // Implements VideoRenderer. 34 virtual bool SetSize(int width, int height, int reserved) OVERRIDE { 35 return true; 36 } 37 virtual bool RenderFrame(const cricket::VideoFrame* frame) OVERRIDE { 38 base::AutoLock auto_lock(lock_); 39 if (reader_) { 40 // |frame| will be invalid after this function is returned. So keep a copy 41 // before return. 42 cricket::VideoFrame* copied_frame = frame->Copy(); 43 copied_frame->MakeExclusive(); 44 reader_->GotFrame(copied_frame); 45 } 46 return true; 47 } 48 49 void SetReader(FrameReaderInterface* reader) { 50 base::AutoLock auto_lock(lock_); 51 reader_ = reader; 52 } 53 54 private: 55 FrameReaderInterface* reader_; 56 base::Lock lock_; 57 58 DISALLOW_COPY_AND_ASSIGN(PpFrameReceiver); 59}; 60 61VideoSourceHandler::VideoSourceHandler( 62 MediaStreamRegistryInterface* registry) 63 : registry_(registry) { 64} 65 66VideoSourceHandler::~VideoSourceHandler() { 67 for (SourceInfoMap::iterator it = reader_to_receiver_.begin(); 68 it != reader_to_receiver_.end(); 69 ++it) { 70 delete it->second; 71 } 72} 73 74bool VideoSourceHandler::Open(const std::string& url, 75 FrameReaderInterface* reader) { 76 scoped_refptr<webrtc::VideoSourceInterface> source = GetFirstVideoSource(url); 77 if (!source.get()) { 78 return false; 79 } 80 reader_to_receiver_[reader] = new SourceInfo(source, reader); 81 return true; 82} 83 84bool VideoSourceHandler::Close(FrameReaderInterface* reader) { 85 SourceInfoMap::iterator it = reader_to_receiver_.find(reader); 86 if (it == reader_to_receiver_.end()) { 87 return false; 88 } 89 delete it->second; 90 reader_to_receiver_.erase(it); 91 return true; 92} 93 94scoped_refptr<VideoSourceInterface> VideoSourceHandler::GetFirstVideoSource( 95 const std::string& url) { 96 scoped_refptr<webrtc::VideoSourceInterface> source; 97 blink::WebMediaStream stream; 98 if (registry_) { 99 stream = registry_->GetMediaStream(url); 100 } else { 101 stream = 102 blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url)); 103 } 104 if (stream.isNull() || !stream.extraData()) { 105 LOG(ERROR) << "GetFirstVideoSource - invalid url: " << url; 106 return source; 107 } 108 109 // Get the first video track from the stream. 110 webrtc::MediaStreamInterface* native_stream = MediaStream::GetAdapter(stream); 111 webrtc::VideoTrackVector native_video_tracks = 112 native_stream->GetVideoTracks(); 113 if (native_video_tracks.empty()) { 114 LOG(ERROR) << "GetFirstVideoSource - stream has no video track."; 115 return source; 116 } 117 source = native_video_tracks[0]->GetSource(); 118 return source; 119} 120 121VideoRenderer* VideoSourceHandler::GetReceiver( 122 FrameReaderInterface* reader) { 123 SourceInfoMap::iterator it = reader_to_receiver_.find(reader); 124 if (it == reader_to_receiver_.end()) { 125 return NULL; 126 } 127 return it->second->receiver_.get(); 128} 129 130VideoSourceHandler::SourceInfo::SourceInfo( 131 scoped_refptr<webrtc::VideoSourceInterface> source, 132 FrameReaderInterface* reader) 133 : receiver_(new PpFrameReceiver()), 134 source_(source) { 135 source_->AddSink(receiver_.get()); 136 receiver_->SetReader(reader); 137} 138 139VideoSourceHandler::SourceInfo::~SourceInfo() { 140 source_->RemoveSink(receiver_.get()); 141 receiver_->SetReader(NULL); 142} 143 144} // namespace content 145 146