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 "base/memory/weak_ptr.h" 11 #include "base/synchronization/lock.h" 12 #include "content/public/renderer/media_stream_video_sink.h" 13 #include "content/renderer/media/media_stream.h" 14 #include "content/renderer/media/media_stream_registry_interface.h" 15 #include "media/base/bind_to_current_loop.h" 16 #include "media/video/capture/video_capture_types.h" 17 #include "third_party/WebKit/public/platform/WebMediaStream.h" 18 #include "third_party/WebKit/public/platform/WebURL.h" 19 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h" 20 #include "url/gurl.h" 21 22 namespace content { 23 24 // PpFrameReceiver implements MediaStreamVideoSink so that it can be attached 25 // to video track to receive the captured frame. 26 // It can be attached to a FrameReaderInterface to output the received frame. 27 class PpFrameReceiver : public MediaStreamVideoSink { 28 public: 29 PpFrameReceiver(blink::WebMediaStreamTrack track) 30 : track_(track), 31 reader_(NULL), 32 weak_factory_(this) { 33 } 34 35 virtual ~PpFrameReceiver() {} 36 37 void SetReader(FrameReaderInterface* reader) { 38 if (reader) { 39 DCHECK(!reader_); 40 MediaStreamVideoSink::AddToVideoTrack( 41 this, 42 media::BindToCurrentLoop( 43 base::Bind( 44 &PpFrameReceiver::OnVideoFrame, 45 weak_factory_.GetWeakPtr())), 46 track_); 47 } else { 48 DCHECK(reader_); 49 MediaStreamVideoSink::RemoveFromVideoTrack(this, track_); 50 weak_factory_.InvalidateWeakPtrs(); 51 } 52 reader_ = reader; 53 } 54 55 void OnVideoFrame( 56 const scoped_refptr<media::VideoFrame>& frame, 57 const media::VideoCaptureFormat& format, 58 const base::TimeTicks& estimated_capture_time) { 59 if (reader_) { 60 reader_->GotFrame(frame); 61 } 62 } 63 64 private: 65 blink::WebMediaStreamTrack track_; 66 FrameReaderInterface* reader_; 67 base::WeakPtrFactory<PpFrameReceiver> weak_factory_; 68 69 DISALLOW_COPY_AND_ASSIGN(PpFrameReceiver); 70 }; 71 72 VideoSourceHandler::VideoSourceHandler( 73 MediaStreamRegistryInterface* registry) 74 : registry_(registry) { 75 } 76 77 VideoSourceHandler::~VideoSourceHandler() { 78 for (SourceInfoMap::iterator it = reader_to_receiver_.begin(); 79 it != reader_to_receiver_.end(); 80 ++it) { 81 delete it->second; 82 } 83 } 84 85 bool VideoSourceHandler::Open(const std::string& url, 86 FrameReaderInterface* reader) { 87 DCHECK(thread_checker_.CalledOnValidThread()); 88 const blink::WebMediaStreamTrack& track = GetFirstVideoTrack(url); 89 if (track.isNull()) { 90 return false; 91 } 92 reader_to_receiver_[reader] = new SourceInfo(track, reader); 93 return true; 94 } 95 96 bool VideoSourceHandler::Close(FrameReaderInterface* reader) { 97 DCHECK(thread_checker_. CalledOnValidThread()); 98 SourceInfoMap::iterator it = reader_to_receiver_.find(reader); 99 if (it == reader_to_receiver_.end()) { 100 return false; 101 } 102 delete it->second; 103 reader_to_receiver_.erase(it); 104 return true; 105 } 106 107 blink::WebMediaStreamTrack VideoSourceHandler::GetFirstVideoTrack( 108 const std::string& url) { 109 blink::WebMediaStream stream; 110 if (registry_) { 111 stream = registry_->GetMediaStream(url); 112 } else { 113 stream = 114 blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url)); 115 } 116 117 if (stream.isNull()) { 118 LOG(ERROR) << "GetFirstVideoSource - invalid url: " << url; 119 return blink::WebMediaStreamTrack(); 120 } 121 122 // Get the first video track from the stream. 123 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; 124 stream.videoTracks(video_tracks); 125 if (video_tracks.isEmpty()) { 126 LOG(ERROR) << "GetFirstVideoSource - non video tracks available." 127 << " url: " << url; 128 return blink::WebMediaStreamTrack(); 129 } 130 131 return video_tracks[0]; 132 } 133 134 void VideoSourceHandler::DeliverFrameForTesting( 135 FrameReaderInterface* reader, 136 const scoped_refptr<media::VideoFrame>& frame) { 137 SourceInfoMap::iterator it = reader_to_receiver_.find(reader); 138 if (it == reader_to_receiver_.end()) { 139 return; 140 } 141 PpFrameReceiver* receiver = it->second->receiver_.get(); 142 receiver->OnVideoFrame(frame, media::VideoCaptureFormat(), 143 base::TimeTicks()); 144 } 145 146 VideoSourceHandler::SourceInfo::SourceInfo( 147 const blink::WebMediaStreamTrack& blink_track, 148 FrameReaderInterface* reader) 149 : receiver_(new PpFrameReceiver(blink_track)) { 150 receiver_->SetReader(reader); 151 } 152 153 VideoSourceHandler::SourceInfo::~SourceInfo() { 154 receiver_->SetReader(NULL); 155 } 156 157 } // namespace content 158