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 "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"
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
{
29 PpFrameReceiver(blink::WebMediaStreamTrack track
)
35 virtual ~PpFrameReceiver() {}
37 void SetReader(FrameReaderInterface
* reader
) {
40 MediaStreamVideoSink::AddToVideoTrack(
42 media::BindToCurrentLoop(
44 &PpFrameReceiver::OnVideoFrame
,
45 weak_factory_
.GetWeakPtr())),
49 MediaStreamVideoSink::RemoveFromVideoTrack(this, track_
);
50 weak_factory_
.InvalidateWeakPtrs();
56 const scoped_refptr
<media::VideoFrame
>& frame
,
57 const media::VideoCaptureFormat
& format
,
58 const base::TimeTicks
& estimated_capture_time
) {
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
, media::VideoCaptureFormat(),
146 VideoSourceHandler::SourceInfo::SourceInfo(
147 const blink::WebMediaStreamTrack
& blink_track
,
148 FrameReaderInterface
* reader
)
149 : receiver_(new PpFrameReceiver(blink_track
)) {
150 receiver_
->SetReader(reader
);
153 VideoSourceHandler::SourceInfo::~SourceInfo() {
154 receiver_
->SetReader(NULL
);
157 } // namespace content