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 "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"
     20 #include "url/gurl.h"
     21 
     22 namespace content {
     23 
     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 {
     28  public:
     29   PpFrameReceiver(blink::WebMediaStreamTrack track)
     30     : track_(track),
     31       reader_(NULL),
     32       weak_factory_(this) {
     33   }
     34 
     35   virtual ~PpFrameReceiver() {}
     36 
     37   void SetReader(FrameReaderInterface* reader) {
     38     if (reader) {
     39       DCHECK(!reader_);
     40       MediaStreamVideoSink::AddToVideoTrack(
     41           this,
     42           media::BindToCurrentLoop(
     43               base::Bind(
     44                   &PpFrameReceiver::OnVideoFrame,
     45                   weak_factory_.GetWeakPtr())),
     46           track_);
     47     } else {
     48       DCHECK(reader_);
     49       MediaStreamVideoSink::RemoveFromVideoTrack(this, track_);
     50       weak_factory_.InvalidateWeakPtrs();
     51     }
     52     reader_ = reader;
     53   }
     54 
     55   void OnVideoFrame(
     56       const scoped_refptr<media::VideoFrame>& frame,
     57       const media::VideoCaptureFormat& format,
     58       const base::TimeTicks& estimated_capture_time) {
     59     if (reader_) {
     60       reader_->GotFrame(frame);
     61     }
     62   }
     63 
     64  private:
     65   blink::WebMediaStreamTrack track_;
     66   FrameReaderInterface* reader_;
     67   base::WeakPtrFactory<PpFrameReceiver> weak_factory_;
     68 
     69   DISALLOW_COPY_AND_ASSIGN(PpFrameReceiver);
     70 };
     71 
     72 VideoSourceHandler::VideoSourceHandler(
     73     MediaStreamRegistryInterface* registry)
     74     : registry_(registry) {
     75 }
     76 
     77 VideoSourceHandler::~VideoSourceHandler() {
     78   for (SourceInfoMap::iterator it = reader_to_receiver_.begin();
     79        it != reader_to_receiver_.end();
     80        ++it) {
     81     delete it->second;
     82   }
     83 }
     84 
     85 bool VideoSourceHandler::Open(const std::string& url,
     86                               FrameReaderInterface* reader) {
     87   DCHECK(thread_checker_.CalledOnValidThread());
     88   const blink::WebMediaStreamTrack& track = GetFirstVideoTrack(url);
     89   if (track.isNull()) {
     90     return false;
     91   }
     92   reader_to_receiver_[reader] = new SourceInfo(track, reader);
     93   return true;
     94 }
     95 
     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()) {
    100     return false;
    101   }
    102   delete it->second;
    103   reader_to_receiver_.erase(it);
    104   return true;
    105 }
    106 
    107 blink::WebMediaStreamTrack VideoSourceHandler::GetFirstVideoTrack(
    108     const std::string& url) {
    109   blink::WebMediaStream stream;
    110   if (registry_) {
    111     stream = registry_->GetMediaStream(url);
    112   } else {
    113     stream =
    114         blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url));
    115   }
    116 
    117   if (stream.isNull()) {
    118     LOG(ERROR) << "GetFirstVideoSource - invalid url: " << url;
    119     return blink::WebMediaStreamTrack();
    120   }
    121 
    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."
    127                << " url: " << url;
    128     return blink::WebMediaStreamTrack();
    129   }
    130 
    131   return video_tracks[0];
    132 }
    133 
    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()) {
    139     return;
    140   }
    141   PpFrameReceiver* receiver = it->second->receiver_.get();
    142   receiver->OnVideoFrame(frame, media::VideoCaptureFormat(),
    143                          base::TimeTicks());
    144 }
    145 
    146 VideoSourceHandler::SourceInfo::SourceInfo(
    147     const blink::WebMediaStreamTrack& blink_track,
    148     FrameReaderInterface* reader)
    149     : receiver_(new PpFrameReceiver(blink_track)) {
    150   receiver_->SetReader(reader);
    151 }
    152 
    153 VideoSourceHandler::SourceInfo::~SourceInfo() {
    154   receiver_->SetReader(NULL);
    155 }
    156 
    157 }  // namespace content
    158