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