OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_decoder.h" | 5 #include "content/renderer/media/rtc_video_decoder.h" |
6 | 6 |
7 #include <deque> | |
8 | |
9 #include "base/bind.h" | 7 #include "base/bind.h" |
10 #include "base/callback.h" | 8 #include "base/callback.h" |
11 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
12 #include "base/task.h" | 10 #include "base/task.h" |
13 #include "media/base/demuxer.h" | 11 #include "media/base/demuxer.h" |
14 #include "media/base/filter_host.h" | 12 #include "media/base/filter_host.h" |
15 #include "media/base/filters.h" | 13 #include "media/base/filters.h" |
16 #include "media/base/limits.h" | 14 #include "media/base/limits.h" |
17 #include "media/base/video_frame.h" | 15 #include "media/base/video_frame.h" |
18 #include "media/base/video_util.h" | 16 #include "media/base/video_util.h" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 return; | 78 return; |
81 } | 79 } |
82 | 80 |
83 DCHECK_EQ(MessageLoop::current(), message_loop_); | 81 DCHECK_EQ(MessageLoop::current(), message_loop_); |
84 | 82 |
85 state_ = kPaused; | 83 state_ = kPaused; |
86 | 84 |
87 VideoDecoder::Pause(callback); | 85 VideoDecoder::Pause(callback); |
88 } | 86 } |
89 | 87 |
| 88 void RTCVideoDecoder::Flush(const base::Closure& callback) { |
| 89 if (MessageLoop::current() != message_loop_) { |
| 90 message_loop_->PostTask(FROM_HERE, |
| 91 base::Bind(&RTCVideoDecoder::Flush, |
| 92 this, callback)); |
| 93 return; |
| 94 } |
| 95 |
| 96 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 97 |
| 98 { |
| 99 base::AutoLock auto_lock(lock_); |
| 100 while (!read_cbs_.empty()) { |
| 101 DeliverBlackFrame(read_cbs_.front()); |
| 102 read_cbs_.pop(); |
| 103 } |
| 104 } |
| 105 |
| 106 VideoDecoder::Flush(callback); |
| 107 } |
| 108 |
90 void RTCVideoDecoder::Stop(const base::Closure& callback) { | 109 void RTCVideoDecoder::Stop(const base::Closure& callback) { |
91 if (MessageLoop::current() != message_loop_) { | 110 if (MessageLoop::current() != message_loop_) { |
92 message_loop_->PostTask(FROM_HERE, | 111 message_loop_->PostTask(FROM_HERE, |
93 base::Bind(&RTCVideoDecoder::Stop, | 112 base::Bind(&RTCVideoDecoder::Stop, |
94 this, callback)); | 113 this, callback)); |
95 return; | 114 return; |
96 } | 115 } |
97 | 116 |
98 DCHECK_EQ(MessageLoop::current(), message_loop_); | 117 DCHECK_EQ(MessageLoop::current(), message_loop_); |
99 | 118 |
(...skipping 16 matching lines...) Expand all Loading... |
116 } | 135 } |
117 | 136 |
118 void RTCVideoDecoder::Read(const ReadCB& callback) { | 137 void RTCVideoDecoder::Read(const ReadCB& callback) { |
119 if (MessageLoop::current() != message_loop_) { | 138 if (MessageLoop::current() != message_loop_) { |
120 message_loop_->PostTask( | 139 message_loop_->PostTask( |
121 FROM_HERE, | 140 FROM_HERE, |
122 base::Bind(&RTCVideoDecoder::Read, this, callback)); | 141 base::Bind(&RTCVideoDecoder::Read, this, callback)); |
123 return; | 142 return; |
124 } | 143 } |
125 DCHECK_EQ(MessageLoop::current(), message_loop_); | 144 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 145 CHECK(!callback.is_null()); |
| 146 if (state_ != kNormal) { |
| 147 DeliverBlackFrame(callback); |
| 148 return; |
| 149 } |
126 base::AutoLock auto_lock(lock_); | 150 base::AutoLock auto_lock(lock_); |
127 CHECK(read_cb_.is_null()); | 151 read_cbs_.push(callback); |
128 read_cb_ = callback; | |
129 } | 152 } |
130 | 153 |
131 const gfx::Size& RTCVideoDecoder::natural_size() { | 154 const gfx::Size& RTCVideoDecoder::natural_size() { |
132 // TODO(vrk): Return natural size when aspect ratio support is implemented. | 155 // TODO(vrk): Return natural size when aspect ratio support is implemented. |
133 return visible_size_; | 156 return visible_size_; |
134 } | 157 } |
135 | 158 |
136 bool RTCVideoDecoder::SetSize(int width, int height, int reserved) { | 159 bool RTCVideoDecoder::SetSize(int width, int height, int reserved) { |
137 visible_size_.SetSize(width, height); | 160 visible_size_.SetSize(width, height); |
138 | 161 |
139 // TODO(vrk): Provide natural size when aspect ratio support is implemented. | 162 // TODO(vrk): Provide natural size when aspect ratio support is implemented. |
140 host()->SetNaturalVideoSize(visible_size_); | 163 host()->SetNaturalVideoSize(visible_size_); |
141 return true; | 164 return true; |
142 } | 165 } |
143 | 166 |
| 167 // TODO(wjia): this function can be split into two parts so that the |lock_| |
| 168 // can be removed. |
| 169 // First creates media::VideoFrame, then post a task onto |message_loop_| |
| 170 // to deliver that frame. |
144 bool RTCVideoDecoder::RenderFrame(const cricket::VideoFrame* frame) { | 171 bool RTCVideoDecoder::RenderFrame(const cricket::VideoFrame* frame) { |
145 // Called from libjingle thread. | 172 // Called from libjingle thread. |
146 DCHECK(frame); | 173 DCHECK(frame); |
147 | 174 |
148 if (state_ != kNormal) | 175 if (state_ != kNormal) |
149 return true; | 176 return true; |
150 | 177 |
151 ReadCB read_cb; | 178 ReadCB read_cb; |
152 { | 179 { |
153 base::AutoLock auto_lock(lock_); | 180 base::AutoLock auto_lock(lock_); |
154 if (read_cb_.is_null()) { | 181 if (read_cbs_.empty()) { |
155 return true; | 182 return true; |
156 } | 183 } |
157 std::swap(read_cb, read_cb_); | 184 read_cb = read_cbs_.front(); |
| 185 read_cbs_.pop(); |
158 } | 186 } |
159 | 187 |
160 // Always allocate a new frame. | 188 // Always allocate a new frame. |
161 // | 189 // |
162 // TODO(scherkus): migrate this to proper buffer recycling. | 190 // TODO(scherkus): migrate this to proper buffer recycling. |
163 scoped_refptr<media::VideoFrame> video_frame = | 191 scoped_refptr<media::VideoFrame> video_frame = |
164 VideoFrame::CreateFrame(VideoFrame::YV12, | 192 VideoFrame::CreateFrame(VideoFrame::YV12, |
165 visible_size_.width(), | 193 visible_size_.width(), |
166 visible_size_.height(), | 194 visible_size_.height(), |
167 host()->GetTime(), | 195 host()->GetTime(), |
168 base::TimeDelta::FromMilliseconds(30)); | 196 base::TimeDelta::FromMilliseconds(30)); |
169 | 197 |
170 // Aspect ratio unsupported; DCHECK when there are non-square pixels. | 198 // Aspect ratio unsupported; DCHECK when there are non-square pixels. |
171 DCHECK_EQ(frame->GetPixelWidth(), 1u); | 199 DCHECK_EQ(frame->GetPixelWidth(), 1u); |
172 DCHECK_EQ(frame->GetPixelHeight(), 1u); | 200 DCHECK_EQ(frame->GetPixelHeight(), 1u); |
173 | 201 |
174 int y_rows = frame->GetHeight(); | 202 int y_rows = frame->GetHeight(); |
175 int uv_rows = frame->GetHeight() / 2; // YV12 format. | 203 int uv_rows = frame->GetHeight() / 2; // YV12 format. |
176 CopyYPlane(frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame); | 204 CopyYPlane(frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame); |
177 CopyUPlane(frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame); | 205 CopyUPlane(frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame); |
178 CopyVPlane(frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame); | 206 CopyVPlane(frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame); |
179 | 207 |
180 read_cb.Run(video_frame); | 208 read_cb.Run(video_frame); |
181 return true; | 209 return true; |
182 } | 210 } |
| 211 |
| 212 void RTCVideoDecoder::DeliverBlackFrame( |
| 213 const ReadCB& read_cb) { |
| 214 CHECK(!read_cb.is_null()); |
| 215 scoped_refptr<media::VideoFrame> video_frame = |
| 216 media::VideoFrame::CreateBlackFrame(visible_size_.width(), |
| 217 visible_size_.height()); |
| 218 read_cb.Run(video_frame); |
| 219 } |
OLD | NEW |