• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
PpFrameReceiver(blink::WebMediaStreamTrack track)29   PpFrameReceiver(blink::WebMediaStreamTrack track)
30     : track_(track),
31       reader_(NULL),
32       weak_factory_(this) {
33   }
34 
~PpFrameReceiver()35   virtual ~PpFrameReceiver() {}
36 
SetReader(FrameReaderInterface * reader)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 
OnVideoFrame(const scoped_refptr<media::VideoFrame> & frame,const media::VideoCaptureFormat & format,const base::TimeTicks & estimated_capture_time)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 
VideoSourceHandler(MediaStreamRegistryInterface * registry)72 VideoSourceHandler::VideoSourceHandler(
73     MediaStreamRegistryInterface* registry)
74     : registry_(registry) {
75 }
76 
~VideoSourceHandler()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 
Open(const std::string & url,FrameReaderInterface * reader)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 
Close(FrameReaderInterface * reader)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 
GetFirstVideoTrack(const std::string & url)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 
DeliverFrameForTesting(FrameReaderInterface * reader,const scoped_refptr<media::VideoFrame> & frame)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 
SourceInfo(const blink::WebMediaStreamTrack & blink_track,FrameReaderInterface * reader)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 
~SourceInfo()153 VideoSourceHandler::SourceInfo::~SourceInfo() {
154   receiver_->SetReader(NULL);
155 }
156 
157 }  // namespace content
158