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"
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"
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
{
30 PpFrameReceiver(blink::WebMediaStreamTrack track
)
36 ~PpFrameReceiver() override
{}
38 void SetReader(FrameReaderInterface
* reader
) {
41 MediaStreamVideoSink::AddToVideoTrack(
43 media::BindToCurrentLoop(
45 &PpFrameReceiver::OnVideoFrame
,
46 weak_factory_
.GetWeakPtr())),
50 MediaStreamVideoSink::RemoveFromVideoTrack(this, track_
);
51 weak_factory_
.InvalidateWeakPtrs();
56 void OnVideoFrame(const scoped_refptr
<media::VideoFrame
>& frame
,
57 const base::TimeTicks
& estimated_capture_time
) {
58 TRACE_EVENT0("video", "PpFrameReceiver::OnVideoFrame");
60 reader_
->GotFrame(frame
);
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();
85 bool VideoSourceHandler::Open(const std::string
& url
,
86 FrameReaderInterface
* reader
) {
87 DCHECK(thread_checker_
.CalledOnValidThread());
88 const blink::WebMediaStreamTrack
& track
= GetFirstVideoTrack(url
);
92 reader_to_receiver_
[reader
] = new SourceInfo(track
, 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()) {
103 reader_to_receiver_
.erase(it
);
107 blink::WebMediaStreamTrack
VideoSourceHandler::GetFirstVideoTrack(
108 const std::string
& url
) {
109 blink::WebMediaStream stream
;
111 stream
= registry_
->GetMediaStream(url
);
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."
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()) {
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