video_source_handler.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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 "content/renderer/media/media_stream_dependency_factory.h"
11#include "content/renderer/media/media_stream_registry_interface.h"
12#include "content/renderer/render_thread_impl.h"
13#include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStream.h"
14#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStreamRegistry.h"
15#include "third_party/libjingle/source/talk/media/base/videoframe.h"
16#include "third_party/libjingle/source/talk/media/base/videorenderer.h"
17
18using cricket::VideoFrame;
19using cricket::VideoRenderer;
20using webrtc::VideoSourceInterface;
21
22namespace content {
23
24// PpFrameReceiver implements cricket::VideoRenderer so that it can be attached
25// to native video track's video source to receive the captured frame.
26// It can be attached to a FrameReaderInterface to output the received frame.
27class PpFrameReceiver : public cricket::VideoRenderer {
28 public:
29  PpFrameReceiver() : reader_(NULL) {}
30  virtual ~PpFrameReceiver() {}
31
32  // Implements VideoRenderer.
33  virtual bool SetSize(int width, int height, int reserved) OVERRIDE {
34    return true;
35  }
36  virtual bool RenderFrame(const cricket::VideoFrame* frame) OVERRIDE {
37    base::AutoLock auto_lock(lock_);
38    if (reader_) {
39      // Make a shallow copy of the frame as the |reader_| may need to queue it.
40      // Both frames will share a single reference-counted frame buffer.
41      reader_->GotFrame(frame->Copy());
42    }
43    return true;
44  }
45
46  void SetReader(FrameReaderInterface* reader) {
47    base::AutoLock auto_lock(lock_);
48    reader_ = reader;
49  }
50
51 private:
52  FrameReaderInterface* reader_;
53  base::Lock lock_;
54
55  DISALLOW_COPY_AND_ASSIGN(PpFrameReceiver);
56};
57
58VideoSourceHandler::VideoSourceHandler(
59    MediaStreamRegistryInterface* registry)
60    : registry_(registry) {
61}
62
63VideoSourceHandler::~VideoSourceHandler() {}
64
65bool VideoSourceHandler::Open(const std::string& url,
66                              FrameReaderInterface* reader) {
67  scoped_refptr<webrtc::VideoSourceInterface> source = GetFirstVideoSource(url);
68  if (!source.get()) {
69    return false;
70  }
71  PpFrameReceiver* receiver = new PpFrameReceiver();
72  receiver->SetReader(reader);
73  source->AddSink(receiver);
74  reader_to_receiver_[reader] = receiver;
75  return true;
76}
77
78bool VideoSourceHandler::Close(const std::string& url,
79                               FrameReaderInterface* reader) {
80  scoped_refptr<webrtc::VideoSourceInterface> source = GetFirstVideoSource(url);
81  if (!source.get()) {
82    LOG(ERROR) << "VideoSourceHandler::Close - Failed to get the video source "
83               << "from MediaStream with url: " << url;
84    return false;
85  }
86  PpFrameReceiver* receiver =
87      static_cast<PpFrameReceiver*>(GetReceiver(reader));
88  receiver->SetReader(NULL);
89  source->RemoveSink(receiver);
90  reader_to_receiver_.erase(reader);
91  return true;
92}
93
94scoped_refptr<VideoSourceInterface> VideoSourceHandler::GetFirstVideoSource(
95    const std::string& url) {
96  scoped_refptr<webrtc::VideoSourceInterface> source;
97  WebKit::WebMediaStream stream;
98  if (registry_) {
99    stream = registry_->GetMediaStream(url);
100  } else {
101    stream =
102        WebKit::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url));
103  }
104  if (stream.isNull() || !stream.extraData()) {
105    LOG(ERROR) << "GetFirstVideoSource - invalid url: " << url;
106    return source;
107  }
108
109  // Get the first video track from the stream.
110  MediaStreamExtraData* extra_data =
111      static_cast<MediaStreamExtraData*>(stream.extraData());
112  if (!extra_data) {
113    LOG(ERROR) << "GetFirstVideoSource - MediaStreamExtraData is NULL.";
114    return source;
115  }
116  webrtc::MediaStreamInterface* native_stream = extra_data->stream();
117  if (!native_stream) {
118    LOG(ERROR) << "GetFirstVideoSource - native stream is NULL.";
119    return source;
120  }
121  webrtc::VideoTrackVector native_video_tracks =
122      native_stream->GetVideoTracks();
123  if (native_video_tracks.empty()) {
124    LOG(ERROR) << "GetFirstVideoSource - stream has no video track.";
125    return source;
126  }
127  source = native_video_tracks[0]->GetSource();
128  return source;
129}
130
131VideoRenderer* VideoSourceHandler::GetReceiver(
132    FrameReaderInterface* reader) {
133  std::map<FrameReaderInterface*, VideoRenderer*>::iterator it;
134  it = reader_to_receiver_.find(reader);
135  if (it == reader_to_receiver_.end()) {
136    return NULL;
137  }
138  return it->second;
139}
140
141}  // namespace content
142
143