• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RTCVideoRenderer(const blink::WebMediaStreamTrack & video_track,const base::Closure & error_cb,const RepaintCB & repaint_cb)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 
~RTCVideoRenderer()30 RTCVideoRenderer::~RTCVideoRenderer() {
31 }
32 
Start()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 
Stop()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 
Play()63 void RTCVideoRenderer::Play() {
64   DCHECK(message_loop_proxy_->BelongsToCurrentThread());
65   if (state_ == PAUSED) {
66     state_ = STARTED;
67   }
68 }
69 
Pause()70 void RTCVideoRenderer::Pause() {
71   DCHECK(message_loop_proxy_->BelongsToCurrentThread());
72   if (state_ == STARTED) {
73     state_ = PAUSED;
74   }
75 }
76 
OnReadyStateChanged(blink::WebMediaStreamSource::ReadyState state)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 
OnVideoFrame(const scoped_refptr<media::VideoFrame> & frame,const media::VideoCaptureFormat & format,const base::TimeTicks & estimated_capture_time)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 
RenderSignalingFrame()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