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/thread_task_runner_handle.h"
8 #include "base/trace_event/trace_event.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 task_runner_(base::ThreadTaskRunnerHandle::Get()),
25 frame_size_(kMinFrameSize
, kMinFrameSize
),
26 video_track_(video_track
),
30 RTCVideoRenderer::~RTCVideoRenderer() {
33 void RTCVideoRenderer::Start() {
34 DCHECK(task_runner_
->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(task_runner_
->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(task_runner_
->BelongsToCurrentThread());
69 void RTCVideoRenderer::Pause() {
70 DCHECK(task_runner_
->BelongsToCurrentThread());
71 if (state_
== STARTED
)
75 void RTCVideoRenderer::OnReadyStateChanged(
76 blink::WebMediaStreamSource::ReadyState state
) {
77 DCHECK(task_runner_
->BelongsToCurrentThread());
78 if (state
== blink::WebMediaStreamSource::ReadyStateEnded
)
79 RenderSignalingFrame();
82 void RTCVideoRenderer::OnVideoFrame(
83 const scoped_refptr
<media::VideoFrame
>& frame
,
84 const base::TimeTicks
& estimated_capture_time
) {
85 DCHECK(task_runner_
->BelongsToCurrentThread());
86 if (state_
!= STARTED
)
89 frame_size_
= frame
->natural_size();
91 TRACE_EVENT_INSTANT1("rtc_video_renderer",
93 TRACE_EVENT_SCOPE_THREAD
,
95 frame
->timestamp().InMilliseconds());
96 repaint_cb_
.Run(frame
);
99 void RTCVideoRenderer::RenderSignalingFrame() {
100 // This is necessary to make sure audio can play if the video tag src is
101 // a MediaStream video track that has been rejected or ended.
102 // It also ensure that the renderer don't hold a reference to a real video
103 // frame if no more frames are provided. This is since there might be a
104 // finite number of available buffers. E.g, video that
105 // originates from a video camera.
106 scoped_refptr
<media::VideoFrame
> video_frame
=
107 media::VideoFrame::CreateBlackFrame(frame_size_
);
108 OnVideoFrame(video_frame
, base::TimeTicks());
111 } // namespace content