Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / renderer / media / media_stream_video_renderer_sink.cc
blob723b733df25d0502dfe8a5ae282f28beac1b8fe2
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/media_stream_video_renderer_sink.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;
15 namespace content {
17 MediaStreamVideoRendererSink::MediaStreamVideoRendererSink(
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()),
24 state_(STOPPED),
25 frame_size_(kMinFrameSize, kMinFrameSize),
26 video_track_(video_track),
27 weak_factory_(this) {
30 MediaStreamVideoRendererSink::~MediaStreamVideoRendererSink() {
33 void MediaStreamVideoRendererSink::Start() {
34 DCHECK(task_runner_->BelongsToCurrentThread());
35 DCHECK_EQ(state_, STOPPED);
37 AddToVideoTrack(
38 this,
39 media::BindToCurrentLoop(
40 base::Bind(
41 &MediaStreamVideoRendererSink::OnVideoFrame,
42 weak_factory_.GetWeakPtr())),
43 video_track_);
44 state_ = STARTED;
46 if (video_track_.source().readyState() ==
47 blink::WebMediaStreamSource::ReadyStateEnded ||
48 !video_track_.isEnabled()) {
49 RenderSignalingFrame();
53 void MediaStreamVideoRendererSink::Stop() {
54 DCHECK(task_runner_->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);
63 void MediaStreamVideoRendererSink::Play() {
64 DCHECK(task_runner_->BelongsToCurrentThread());
65 if (state_ == PAUSED)
66 state_ = STARTED;
69 void MediaStreamVideoRendererSink::Pause() {
70 DCHECK(task_runner_->BelongsToCurrentThread());
71 if (state_ == STARTED)
72 state_ = PAUSED;
75 void MediaStreamVideoRendererSink::OnReadyStateChanged(
76 blink::WebMediaStreamSource::ReadyState state) {
77 DCHECK(task_runner_->BelongsToCurrentThread());
78 if (state == blink::WebMediaStreamSource::ReadyStateEnded)
79 RenderSignalingFrame();
82 void MediaStreamVideoRendererSink::OnVideoFrame(
83 const scoped_refptr<media::VideoFrame>& frame,
84 base::TimeTicks estimated_capture_time) {
85 DCHECK(task_runner_->BelongsToCurrentThread());
86 if (state_ != STARTED)
87 return;
89 frame_size_ = frame->natural_size();
91 TRACE_EVENT_INSTANT1("media_stream_video_renderer_sink",
92 "OnVideoFrame",
93 TRACE_EVENT_SCOPE_THREAD,
94 "timestamp",
95 frame->timestamp().InMilliseconds());
96 repaint_cb_.Run(frame);
99 void MediaStreamVideoRendererSink::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