Home | History | Annotate | Download | only in media
      1 // Copyright (c) 2012 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/rtc_video_renderer.h"
      6 
      7 #include "base/debug/trace_event.h"
      8 #include "base/message_loop/message_loop_proxy.h"
      9 #include "media/base/bind_to_current_loop.h"
     10 #include "media/base/video_frame.h"
     11 #include "media/base/video_util.h"
     12 
     13 const int kMinFrameSize = 2;
     14 
     15 namespace content {
     16 
     17 RTCVideoRenderer::RTCVideoRenderer(
     18     const blink::WebMediaStreamTrack& video_track,
     19     const base::Closure& error_cb,
     20     const RepaintCB& repaint_cb)
     21     : error_cb_(error_cb),
     22       repaint_cb_(repaint_cb),
     23       message_loop_proxy_(base::MessageLoopProxy::current()),
     24       state_(STOPPED),
     25       frame_size_(kMinFrameSize, kMinFrameSize),
     26       video_track_(video_track),
     27       weak_factory_(this) {
     28 }
     29 
     30 RTCVideoRenderer::~RTCVideoRenderer() {
     31 }
     32 
     33 void RTCVideoRenderer::Start() {
     34   DCHECK(message_loop_proxy_->BelongsToCurrentThread());
     35   DCHECK_EQ(state_, STOPPED);
     36 
     37   AddToVideoTrack(
     38       this,
     39       media::BindToCurrentLoop(
     40           base::Bind(
     41               &RTCVideoRenderer::OnVideoFrame,
     42               weak_factory_.GetWeakPtr())),
     43       video_track_);
     44   state_ = STARTED;
     45 
     46   if (video_track_.source().readyState() ==
     47           blink::WebMediaStreamSource::ReadyStateEnded ||
     48       !video_track_.isEnabled()) {
     49     RenderSignalingFrame();
     50   }
     51 }
     52 
     53 void RTCVideoRenderer::Stop() {
     54   DCHECK(message_loop_proxy_->BelongsToCurrentThread());
     55   DCHECK(state_ == STARTED || state_ == PAUSED);
     56   RemoveFromVideoTrack(this, video_track_);
     57   weak_factory_.InvalidateWeakPtrs();
     58   state_ = STOPPED;
     59   frame_size_.set_width(kMinFrameSize);
     60   frame_size_.set_height(kMinFrameSize);
     61 }
     62 
     63 void RTCVideoRenderer::Play() {
     64   DCHECK(message_loop_proxy_->BelongsToCurrentThread());
     65   if (state_ == PAUSED) {
     66     state_ = STARTED;
     67   }
     68 }
     69 
     70 void RTCVideoRenderer::Pause() {
     71   DCHECK(message_loop_proxy_->BelongsToCurrentThread());
     72   if (state_ == STARTED) {
     73     state_ = PAUSED;
     74   }
     75 }
     76 
     77 void RTCVideoRenderer::OnReadyStateChanged(
     78     blink::WebMediaStreamSource::ReadyState state) {
     79   DCHECK(message_loop_proxy_->BelongsToCurrentThread());
     80   if (state == blink::WebMediaStreamSource::ReadyStateEnded)
     81     RenderSignalingFrame();
     82 }
     83 
     84 void RTCVideoRenderer::OnVideoFrame(
     85     const scoped_refptr<media::VideoFrame>& frame,
     86     const media::VideoCaptureFormat& format,
     87     const base::TimeTicks& estimated_capture_time) {
     88   DCHECK(message_loop_proxy_->BelongsToCurrentThread());
     89   if (state_ != STARTED) {
     90     return;
     91   }
     92 
     93   frame_size_ = frame->natural_size();
     94 
     95   TRACE_EVENT_INSTANT1("rtc_video_renderer",
     96                        "OnVideoFrame",
     97                        TRACE_EVENT_SCOPE_THREAD,
     98                        "timestamp",
     99                        frame->timestamp().InMilliseconds());
    100   repaint_cb_.Run(frame);
    101 }
    102 
    103 void RTCVideoRenderer::RenderSignalingFrame() {
    104   // This is necessary to make sure audio can play if the video tag src is
    105   // a MediaStream video track that has been rejected or ended.
    106   // It also ensure that the renderer don't hold a reference to a real video
    107   // frame if no more frames are provided. This is since there might be a
    108   // finite number of available buffers. E.g, video that
    109   // originates from a video camera.
    110   scoped_refptr<media::VideoFrame> video_frame =
    111       media::VideoFrame::CreateBlackFrame(frame_size_);
    112   OnVideoFrame(video_frame, media::VideoCaptureFormat(), base::TimeTicks());
    113 }
    114 
    115 }  // namespace content
    116