OLD | NEW |
---|---|
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(GetSourceState(video_track_)); | |
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 Register(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 UnRegister(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::OnSourceChangedState(ReadyState state) { |
57 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | |
58 MaybeRenderSignalingFrame(state); | |
74 } | 59 } |
75 | 60 |
76 void RTCVideoRenderer::RenderFrame(const cricket::VideoFrame* frame) { | 61 void RTCVideoRenderer::OnVideoFrame( |
77 base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds( | 62 const scoped_refptr<media::VideoFrame>& frame) { |
78 frame->GetTimeStamp() / talk_base::kNumNanosecsPerMillisec); | 63 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); |
79 | 64 if (state_ != kStarted) { |
80 TRACE_EVENT_INSTANT2("rtc_video_renderer", | 65 return; |
Alpha Left Google
2013/11/26 04:59:32
Please keep this event in some form.
Alpha Left Google
2013/11/26 10:00:47
Ignore this and just remove the events please.
| |
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 } | 66 } |
112 | 67 |
113 message_loop_proxy_->PostTask( | 68 // TODO(perkj): How does tracing work? |
114 FROM_HERE, base::Bind(&RTCVideoRenderer::DoRenderFrameOnMainThread, | 69 /* |
115 this, video_frame)); | 70 TRACE_EVENT_INSTANT1("rtc_video_renderer", |
71 "OnVideoFrame", | |
72 TRACE_EVENT_SCOPE_THREAD, | |
73 "timestamp", | |
74 frame->GetTimestamp());*/ | |
75 repaint_cb_.Run(frame); | |
Alpha Left Google
2013/11/26 04:59:32
Great! Love this!
| |
116 } | 76 } |
117 | 77 |
118 void RTCVideoRenderer::OnChanged() { | 78 void RTCVideoRenderer::MaybeRenderSignalingFrame(ReadyState state) { |
119 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); | |
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 == VideoTrackSink::kEnded) { |
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"); | |
Alpha Left Google
2013/11/26 04:59:32
Please keep this event. We depend on it to for som
perkj_chrome
2013/11/26 09:16:38
This does seem to make sense with this change. Can
Alpha Left Google
2013/11/26 10:00:47
Okay. Just remove the trace then, we'll handle tha
| |
145 repaint_cb_.Run(video_frame); | |
146 } | |
147 | |
148 } // namespace content | 91 } // namespace content |
OLD | NEW |