Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(144)

Side by Side Diff: content/renderer/media/rtc_video_renderer.cc

Issue 83023005: Add VideoTrackSink interface to content/public (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed Tommis comments. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/media/rtc_video_renderer.h" 5 #include "content/renderer/media/rtc_video_renderer.h"
6 6
7 #include "base/bind.h"
8 #include "base/debug/trace_event.h" 7 #include "base/debug/trace_event.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop_proxy.h" 8 #include "base/message_loop/message_loop_proxy.h"
12 #include "content/renderer/media/native_handle_impl.h"
13 #include "media/base/video_frame.h" 9 #include "media/base/video_frame.h"
14 #include "media/base/video_util.h" 10 #include "media/base/video_util.h"
15 #include "third_party/libjingle/source/talk/media/base/videoframe.h"
16
17 using media::CopyYPlane;
18 using media::CopyUPlane;
19 using media::CopyVPlane;
20 11
21 namespace content { 12 namespace content {
22 13
23 RTCVideoRenderer::RTCVideoRenderer( 14 RTCVideoRenderer::RTCVideoRenderer(
24 webrtc::VideoTrackInterface* video_track, 15 const blink::WebMediaStreamTrack& video_track,
25 const base::Closure& error_cb, 16 const base::Closure& error_cb,
26 const RepaintCB& repaint_cb) 17 const RepaintCB& repaint_cb)
27 : error_cb_(error_cb), 18 : error_cb_(error_cb),
28 repaint_cb_(repaint_cb), 19 repaint_cb_(repaint_cb),
29 message_loop_proxy_(base::MessageLoopProxy::current()), 20 message_loop_proxy_(base::MessageLoopProxy::current()),
30 state_(kStopped), 21 state_(kStopped),
31 video_track_(video_track) { 22 video_track_(video_track) {
23 MaybeRenderSignalingFrame(video_track_.source().readyState());
32 } 24 }
33 25
34 RTCVideoRenderer::~RTCVideoRenderer() { 26 RTCVideoRenderer::~RTCVideoRenderer() {
35 } 27 }
36 28
37 void RTCVideoRenderer::Start() { 29 void RTCVideoRenderer::Start() {
38 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 30 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
39 DCHECK_EQ(state_, kStopped); 31 DCHECK_EQ(state_, kStopped);
40 32
41 if (video_track_.get()) { 33 AddToVideoTrack(this, video_track_);
42 video_track_->AddRenderer(this);
43 video_track_->RegisterObserver(this);
44 }
45 state_ = kStarted; 34 state_ = kStarted;
46 MaybeRenderSignalingFrame();
47 } 35 }
48 36
49 void RTCVideoRenderer::Stop() { 37 void RTCVideoRenderer::Stop() {
50 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 38 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
51 if (video_track_.get()) { 39 RemoveFromVideoTrack(this, video_track_);
52 state_ = kStopped;
53 video_track_->RemoveRenderer(this);
54 video_track_->UnregisterObserver(this);
55 video_track_ = NULL;
56 }
57 } 40 }
58 41
59 void RTCVideoRenderer::Play() { 42 void RTCVideoRenderer::Play() {
60 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 43 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
61 if (video_track_.get() && state_ == kPaused) { 44 if (state_ == kPaused) {
62 state_ = kStarted; 45 state_ = kStarted;
63 } 46 }
64 } 47 }
65 48
66 void RTCVideoRenderer::Pause() { 49 void RTCVideoRenderer::Pause() {
67 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 50 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
68 if (video_track_.get() && state_ == kStarted) { 51 if (state_ == kStarted) {
69 state_ = kPaused; 52 state_ = kPaused;
70 } 53 }
71 } 54 }
72 55
73 void RTCVideoRenderer::SetSize(int width, int height) { 56 void RTCVideoRenderer::OnReadyStateChanged(
57 blink::WebMediaStreamSource::ReadyState state) {
58 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
59 MaybeRenderSignalingFrame(state);
74 } 60 }
75 61
76 void RTCVideoRenderer::RenderFrame(const cricket::VideoFrame* frame) { 62 void RTCVideoRenderer::OnVideoFrame(
77 base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds( 63 const scoped_refptr<media::VideoFrame>& frame) {
78 frame->GetTimeStamp() / talk_base::kNumNanosecsPerMillisec); 64 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
79 65 if (state_ != kStarted) {
80 TRACE_EVENT_INSTANT2("rtc_video_renderer", 66 return;
81 "RenderFrame",
82 TRACE_EVENT_SCOPE_THREAD,
83 "elapsed time",
84 frame->GetElapsedTime(),
85 "timestamp_ms",
86 timestamp.InMilliseconds());
87
88 scoped_refptr<media::VideoFrame> video_frame;
89 if (frame->GetNativeHandle() != NULL) {
90 NativeHandleImpl* handle =
91 static_cast<NativeHandleImpl*>(frame->GetNativeHandle());
92 video_frame = static_cast<media::VideoFrame*>(handle->GetHandle());
93 video_frame->SetTimestamp(timestamp);
94 } else {
95 gfx::Size size(frame->GetWidth(), frame->GetHeight());
96 video_frame = media::VideoFrame::CreateFrame(
97 media::VideoFrame::YV12, size, gfx::Rect(size), size, timestamp);
98
99 // Aspect ratio unsupported; DCHECK when there are non-square pixels.
100 DCHECK_EQ(frame->GetPixelWidth(), 1u);
101 DCHECK_EQ(frame->GetPixelHeight(), 1u);
102
103 int y_rows = frame->GetHeight();
104 int uv_rows = frame->GetHeight() / 2; // YV12 format.
105 CopyYPlane(
106 frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame.get());
107 CopyUPlane(
108 frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame.get());
109 CopyVPlane(
110 frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame.get());
111 } 67 }
112 68
113 message_loop_proxy_->PostTask( 69 TRACE_EVENT_INSTANT1("rtc_video_renderer",
114 FROM_HERE, base::Bind(&RTCVideoRenderer::DoRenderFrameOnMainThread, 70 "OnVideoFrame",
115 this, video_frame)); 71 TRACE_EVENT_SCOPE_THREAD,
72 "timestamp",
73 frame->GetTimestamp().InMilliseconds());
74 repaint_cb_.Run(frame);
116 } 75 }
117 76
118 void RTCVideoRenderer::OnChanged() { 77 void RTCVideoRenderer::MaybeRenderSignalingFrame(
119 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 78 blink::WebMediaStreamSource::ReadyState state) {
120 MaybeRenderSignalingFrame();
121 }
122
123 void RTCVideoRenderer::MaybeRenderSignalingFrame() {
124 // Render a small black frame if the track transition to ended. 79 // Render a small black frame if the track transition to ended.
125 // This is necessary to make sure audio can play if the video tag src is 80 // This is necessary to make sure audio can play if the video tag src is
126 // a MediaStream video track that has been rejected or ended. 81 // a MediaStream video track that has been rejected or ended.
127 if (video_track_->state() == webrtc::MediaStreamTrackInterface::kEnded) { 82 if (state == blink::WebMediaStreamSource::ReadyStateEnded) {
128 const int kMinFrameSize = 2; 83 const int kMinFrameSize = 2;
129 const gfx::Size size(kMinFrameSize, kMinFrameSize); 84 const gfx::Size size(kMinFrameSize, kMinFrameSize);
130 scoped_refptr<media::VideoFrame> video_frame = 85 scoped_refptr<media::VideoFrame> video_frame =
131 media::VideoFrame::CreateBlackFrame(size); 86 media::VideoFrame::CreateBlackFrame(size);
132 DoRenderFrameOnMainThread(video_frame); 87 OnVideoFrame(video_frame);
133 } 88 }
134 } 89 }
135 90
136 void RTCVideoRenderer::DoRenderFrameOnMainThread(
137 scoped_refptr<media::VideoFrame> video_frame) {
138 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
139
140 if (state_ != kStarted) {
141 return;
142 }
143
144 TRACE_EVENT0("video", "DoRenderFrameOnMainThread");
145 repaint_cb_.Run(video_frame);
146 }
147
148 } // namespace content 91 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698