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.
5 #include "content/renderer/media/rtc_video_renderer.h"
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"
13 const int kMinFrameSize
= 2;
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()),
25 frame_size_(kMinFrameSize
, kMinFrameSize
),
26 video_track_(video_track
),
30 RTCVideoRenderer::~RTCVideoRenderer() {
33 void RTCVideoRenderer::Start() {
34 DCHECK(message_loop_proxy_
->BelongsToCurrentThread());
35 DCHECK_EQ(state_
, STOPPED
);
39 media::BindToCurrentLoop(
41 &RTCVideoRenderer::OnVideoFrame
,
42 weak_factory_
.GetWeakPtr())),
46 if (video_track_
.source().readyState() ==
47 blink::WebMediaStreamSource::ReadyStateEnded
||
48 !video_track_
.isEnabled()) {
49 RenderSignalingFrame();
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();
59 frame_size_
.set_width(kMinFrameSize
);
60 frame_size_
.set_height(kMinFrameSize
);
63 void RTCVideoRenderer::Play() {
64 DCHECK(message_loop_proxy_
->BelongsToCurrentThread());
65 if (state_
== PAUSED
) {
70 void RTCVideoRenderer::Pause() {
71 DCHECK(message_loop_proxy_
->BelongsToCurrentThread());
72 if (state_
== STARTED
) {
77 void RTCVideoRenderer::OnReadyStateChanged(
78 blink::WebMediaStreamSource::ReadyState state
) {
79 DCHECK(message_loop_proxy_
->BelongsToCurrentThread());
80 if (state
== blink::WebMediaStreamSource::ReadyStateEnded
)
81 RenderSignalingFrame();
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
) {
93 frame_size_
= frame
->natural_size();
95 TRACE_EVENT_INSTANT1("rtc_video_renderer",
97 TRACE_EVENT_SCOPE_THREAD
,
99 frame
->timestamp().InMilliseconds());
100 repaint_cb_
.Run(frame
);
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());
115 } // namespace content