Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / renderer / media / video_source_handler.cc
blob13af886fe9b96bed850dc924f0712e7825ffc19b
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.
5 #include "content/renderer/media/video_source_handler.h"
7 #include <string>
9 #include "base/logging.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/synchronization/lock.h"
12 #include "base/trace_event/trace_event.h"
13 #include "content/public/renderer/media_stream_video_sink.h"
14 #include "content/renderer/media/media_stream.h"
15 #include "content/renderer/media/media_stream_registry_interface.h"
16 #include "media/base/bind_to_current_loop.h"
17 #include "media/base/video_capture_types.h"
18 #include "third_party/WebKit/public/platform/WebMediaStream.h"
19 #include "third_party/WebKit/public/platform/WebURL.h"
20 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
21 #include "url/gurl.h"
23 namespace content {
25 // PpFrameReceiver implements MediaStreamVideoSink so that it can be attached
26 // to video track to receive the captured frame.
27 // It can be attached to a FrameReaderInterface to output the received frame.
28 class PpFrameReceiver : public MediaStreamVideoSink {
29 public:
30 PpFrameReceiver(blink::WebMediaStreamTrack track)
31 : track_(track),
32 reader_(NULL),
33 weak_factory_(this) {
36 ~PpFrameReceiver() override {}
38 void SetReader(FrameReaderInterface* reader) {
39 if (reader) {
40 DCHECK(!reader_);
41 MediaStreamVideoSink::AddToVideoTrack(
42 this,
43 media::BindToCurrentLoop(
44 base::Bind(
45 &PpFrameReceiver::OnVideoFrame,
46 weak_factory_.GetWeakPtr())),
47 track_);
48 } else {
49 DCHECK(reader_);
50 MediaStreamVideoSink::RemoveFromVideoTrack(this, track_);
51 weak_factory_.InvalidateWeakPtrs();
53 reader_ = reader;
56 void OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame,
57 const base::TimeTicks& estimated_capture_time) {
58 TRACE_EVENT0("video", "PpFrameReceiver::OnVideoFrame");
59 if (reader_) {
60 reader_->GotFrame(frame);
64 private:
65 blink::WebMediaStreamTrack track_;
66 FrameReaderInterface* reader_;
67 base::WeakPtrFactory<PpFrameReceiver> weak_factory_;
69 DISALLOW_COPY_AND_ASSIGN(PpFrameReceiver);
72 VideoSourceHandler::VideoSourceHandler(
73 MediaStreamRegistryInterface* registry)
74 : registry_(registry) {
77 VideoSourceHandler::~VideoSourceHandler() {
78 for (SourceInfoMap::iterator it = reader_to_receiver_.begin();
79 it != reader_to_receiver_.end();
80 ++it) {
81 delete it->second;
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;
92 reader_to_receiver_[reader] = new SourceInfo(track, reader);
93 return true;
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;
102 delete it->second;
103 reader_to_receiver_.erase(it);
104 return true;
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));
117 if (stream.isNull()) {
118 LOG(ERROR) << "GetFirstVideoSource - invalid url: " << url;
119 return blink::WebMediaStreamTrack();
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();
131 return video_tracks[0];
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;
141 PpFrameReceiver* receiver = it->second->receiver_.get();
142 receiver->OnVideoFrame(frame, base::TimeTicks());
145 VideoSourceHandler::SourceInfo::SourceInfo(
146 const blink::WebMediaStreamTrack& blink_track,
147 FrameReaderInterface* reader)
148 : receiver_(new PpFrameReceiver(blink_track)) {
149 receiver_->SetReader(reader);
152 VideoSourceHandler::SourceInfo::~SourceInfo() {
153 receiver_->SetReader(NULL);
156 } // namespace content