Home | History | Annotate | Download | only in media
      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/public/platform/WebMediaStream.h"
     14 #include "third_party/WebKit/public/web/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 
     18 using cricket::VideoFrame;
     19 using cricket::VideoRenderer;
     20 using webrtc::VideoSourceInterface;
     21 
     22 namespace 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.
     27 class 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 
     58 VideoSourceHandler::VideoSourceHandler(
     59     MediaStreamRegistryInterface* registry)
     60     : registry_(registry) {
     61 }
     62 
     63 VideoSourceHandler::~VideoSourceHandler() {
     64   // All the opened readers should have been closed by now.
     65   DCHECK(reader_to_receiver_.empty());
     66 }
     67 
     68 bool VideoSourceHandler::Open(const std::string& url,
     69                               FrameReaderInterface* reader) {
     70   scoped_refptr<webrtc::VideoSourceInterface> source = GetFirstVideoSource(url);
     71   if (!source.get()) {
     72     return false;
     73   }
     74   PpFrameReceiver* receiver = new PpFrameReceiver();
     75   receiver->SetReader(reader);
     76   source->AddSink(receiver);
     77   reader_to_receiver_[reader] = receiver;
     78   return true;
     79 }
     80 
     81 bool VideoSourceHandler::Close(const std::string& url,
     82                                FrameReaderInterface* reader) {
     83   scoped_refptr<webrtc::VideoSourceInterface> source = GetFirstVideoSource(url);
     84   if (!source.get()) {
     85     LOG(ERROR) << "VideoSourceHandler::Close - Failed to get the video source "
     86                << "from MediaStream with url: " << url;
     87     return false;
     88   }
     89   PpFrameReceiver* receiver =
     90       static_cast<PpFrameReceiver*>(GetReceiver(reader));
     91   if (!receiver) {
     92     LOG(ERROR) << "VideoSourceHandler::Close - Failed to find receiver that "
     93                << "is associated with the given reader.";
     94     return false;
     95   }
     96   receiver->SetReader(NULL);
     97   source->RemoveSink(receiver);
     98   reader_to_receiver_.erase(reader);
     99   delete receiver;
    100   return true;
    101 }
    102 
    103 scoped_refptr<VideoSourceInterface> VideoSourceHandler::GetFirstVideoSource(
    104     const std::string& url) {
    105   scoped_refptr<webrtc::VideoSourceInterface> source;
    106   WebKit::WebMediaStream stream;
    107   if (registry_) {
    108     stream = registry_->GetMediaStream(url);
    109   } else {
    110     stream =
    111         WebKit::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url));
    112   }
    113   if (stream.isNull() || !stream.extraData()) {
    114     LOG(ERROR) << "GetFirstVideoSource - invalid url: " << url;
    115     return source;
    116   }
    117 
    118   // Get the first video track from the stream.
    119   MediaStreamExtraData* extra_data =
    120       static_cast<MediaStreamExtraData*>(stream.extraData());
    121   if (!extra_data) {
    122     LOG(ERROR) << "GetFirstVideoSource - MediaStreamExtraData is NULL.";
    123     return source;
    124   }
    125   webrtc::MediaStreamInterface* native_stream = extra_data->stream().get();
    126   if (!native_stream) {
    127     LOG(ERROR) << "GetFirstVideoSource - native stream is NULL.";
    128     return source;
    129   }
    130   webrtc::VideoTrackVector native_video_tracks =
    131       native_stream->GetVideoTracks();
    132   if (native_video_tracks.empty()) {
    133     LOG(ERROR) << "GetFirstVideoSource - stream has no video track.";
    134     return source;
    135   }
    136   source = native_video_tracks[0]->GetSource();
    137   return source;
    138 }
    139 
    140 VideoRenderer* VideoSourceHandler::GetReceiver(
    141     FrameReaderInterface* reader) {
    142   std::map<FrameReaderInterface*, VideoRenderer*>::iterator it;
    143   it = reader_to_receiver_.find(reader);
    144   if (it == reader_to_receiver_.end()) {
    145     return NULL;
    146   }
    147   return it->second;
    148 }
    149 
    150 }  // namespace content
    151 
    152