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