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> | 7 #include <deque> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
48 FROM_HERE, | 48 FROM_HERE, |
49 base::Bind(&RTCVideoDecoder::Initialize, this, | 49 base::Bind(&RTCVideoDecoder::Initialize, this, |
50 make_scoped_refptr(demuxer_stream), | 50 make_scoped_refptr(demuxer_stream), |
51 filter_callback, stat_callback)); | 51 filter_callback, stat_callback)); |
52 return; | 52 return; |
53 } | 53 } |
54 | 54 |
55 DCHECK_EQ(MessageLoop::current(), message_loop_); | 55 DCHECK_EQ(MessageLoop::current(), message_loop_); |
56 | 56 |
57 lock_.Acquire(); | 57 lock_.Acquire(); |
58 frame_queue_available_.clear(); | 58 frame_ready_cb_.Reset(); // is this needed? |
acolwell GONE FROM CHROMIUM
2011/11/01 18:31:03
I don't think this is needed. As far as I know Ini
scherkus (not reviewing)
2011/11/03 04:55:59
Done.
| |
59 lock_.Release(); | 59 lock_.Release(); |
60 | 60 |
61 state_ = kNormal; | 61 state_ = kNormal; |
62 | 62 |
63 filter_callback.Run(); | 63 filter_callback.Run(); |
64 | 64 |
65 // TODO(acolwell): Implement stats. | 65 // TODO(acolwell): Implement stats. |
66 } | 66 } |
67 | 67 |
68 void RTCVideoDecoder::Play(const base::Closure& callback) { | 68 void RTCVideoDecoder::Play(const base::Closure& callback) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
110 | 110 |
111 void RTCVideoDecoder::Seek(base::TimeDelta time, const FilterStatusCB& cb) { | 111 void RTCVideoDecoder::Seek(base::TimeDelta time, const FilterStatusCB& cb) { |
112 if (MessageLoop::current() != message_loop_) { | 112 if (MessageLoop::current() != message_loop_) { |
113 message_loop_->PostTask(FROM_HERE, | 113 message_loop_->PostTask(FROM_HERE, |
114 base::Bind(&RTCVideoDecoder::Seek, this, | 114 base::Bind(&RTCVideoDecoder::Seek, this, |
115 time, cb)); | 115 time, cb)); |
116 return; | 116 return; |
117 } | 117 } |
118 | 118 |
119 DCHECK_EQ(MessageLoop::current(), message_loop_); | 119 DCHECK_EQ(MessageLoop::current(), message_loop_); |
120 | |
121 state_ = kSeeking; | |
122 // Create output buffer pool and pass the frames to renderer | |
123 // so that the renderer can complete the seeking. | |
124 for (size_t i = 0; i < Limits::kMaxVideoFrames; ++i) { | |
125 VideoFrameReady(VideoFrame::CreateBlackFrame( | |
126 visible_size_.width(), visible_size_.height())); | |
127 } | |
128 | |
129 state_ = kNormal; | 120 state_ = kNormal; |
130 | |
131 cb.Run(PIPELINE_OK); | 121 cb.Run(PIPELINE_OK); |
132 } | 122 } |
133 | 123 |
134 void RTCVideoDecoder::ProduceVideoFrame( | 124 void RTCVideoDecoder::Read(const FrameReadyCB& callback) { |
135 scoped_refptr<VideoFrame> video_frame) { | |
136 if (MessageLoop::current() != message_loop_) { | 125 if (MessageLoop::current() != message_loop_) { |
137 message_loop_->PostTask( | 126 message_loop_->PostTask( |
138 FROM_HERE, | 127 FROM_HERE, |
139 base::Bind(&RTCVideoDecoder::ProduceVideoFrame, this, video_frame)); | 128 base::Bind(&RTCVideoDecoder::Read, this, callback)); |
140 return; | 129 return; |
141 } | 130 } |
142 DCHECK_EQ(MessageLoop::current(), message_loop_); | 131 DCHECK_EQ(MessageLoop::current(), message_loop_); |
143 base::AutoLock auto_lock(lock_); | 132 base::AutoLock auto_lock(lock_); |
144 frame_queue_available_.push_back(video_frame); | 133 CHECK(frame_ready_cb_.is_null()); |
134 frame_ready_cb_ = callback; | |
145 } | 135 } |
146 | 136 |
147 gfx::Size RTCVideoDecoder::natural_size() { | 137 gfx::Size RTCVideoDecoder::natural_size() { |
148 // TODO(vrk): Return natural size when aspect ratio support is implemented. | 138 // TODO(vrk): Return natural size when aspect ratio support is implemented. |
149 return visible_size_; | 139 return visible_size_; |
150 } | 140 } |
151 | 141 |
152 bool RTCVideoDecoder::SetSize(int width, int height, int reserved) { | 142 bool RTCVideoDecoder::SetSize(int width, int height, int reserved) { |
153 visible_size_.SetSize(width, height); | 143 visible_size_.SetSize(width, height); |
154 | 144 |
155 // TODO(vrk): Provide natural size when aspect ratio support is implemented. | 145 // TODO(vrk): Provide natural size when aspect ratio support is implemented. |
156 host()->SetNaturalVideoSize(visible_size_); | 146 host()->SetNaturalVideoSize(visible_size_); |
157 return true; | 147 return true; |
158 } | 148 } |
159 | 149 |
160 bool RTCVideoDecoder::RenderFrame(const cricket::VideoFrame* frame) { | 150 bool RTCVideoDecoder::RenderFrame(const cricket::VideoFrame* frame) { |
151 // Called from libjingle thread. | |
161 DCHECK(frame); | 152 DCHECK(frame); |
162 | 153 |
163 if (state_ != kNormal) | 154 if (state_ != kNormal) |
164 return true; | 155 return true; |
165 | 156 |
166 // This is called from another thread. | 157 FrameReadyCB frame_ready_cb; |
167 scoped_refptr<VideoFrame> video_frame; | |
168 { | 158 { |
169 base::AutoLock auto_lock(lock_); | 159 base::AutoLock auto_lock(lock_); |
170 if (frame_queue_available_.size() == 0) { | 160 if (frame_ready_cb_.is_null()) { |
171 return true; | 161 return true; |
172 } | 162 } |
173 video_frame = frame_queue_available_.front(); | 163 std::swap(frame_ready_cb, frame_ready_cb_); |
174 frame_queue_available_.pop_front(); | |
175 } | 164 } |
176 | 165 |
177 // Check if there's a size change. | 166 // Always allocate a new frame. |
178 // TODO(vrk): Remove casts when media::VideoFrame is updated with gfx::Sizes | 167 // |
179 // for width/height. | 168 // TODO(scherkus): migrate this to proper buffer recycling. |
180 if (video_frame->width() != static_cast<size_t>(visible_size_.width()) || | 169 scoped_refptr<media::VideoFrame> video_frame = |
181 video_frame->height() != static_cast<size_t>(visible_size_.height())) { | 170 VideoFrame::CreateFrame(VideoFrame::YV12, |
182 // Allocate new buffer based on the new size. | 171 visible_size_.width(), |
183 video_frame = VideoFrame::CreateFrame(VideoFrame::YV12, | 172 visible_size_.height(), |
184 visible_size_.width(), | 173 host()->GetTime(), |
185 visible_size_.height(), | 174 base::TimeDelta::FromMilliseconds(30)); |
acolwell GONE FROM CHROMIUM
2011/11/01 18:31:03
Do we really want to hard code 30ms for the durati
scherkus (not reviewing)
2011/11/03 04:55:59
That's a question for wjia to answer (will cc him
| |
186 kNoTimestamp, | |
187 kNoTimestamp); | |
188 } | |
189 | 175 |
190 // Only YV12 frames are supported. | |
191 DCHECK(video_frame->format() == VideoFrame::YV12); | |
192 // Aspect ratio unsupported; DCHECK when there are non-square pixels. | 176 // Aspect ratio unsupported; DCHECK when there are non-square pixels. |
193 DCHECK(frame->GetPixelWidth() == 1); | 177 DCHECK_EQ(frame->GetPixelWidth(), 1u); |
194 DCHECK(frame->GetPixelHeight() == 1); | 178 DCHECK_EQ(frame->GetPixelHeight(), 1u); |
195 video_frame->SetTimestamp(host()->GetTime()); | |
196 video_frame->SetDuration(base::TimeDelta::FromMilliseconds(30)); | |
197 | 179 |
198 int y_rows = frame->GetHeight(); | 180 int y_rows = frame->GetHeight(); |
199 int uv_rows = frame->GetHeight() / 2; // YV12 format. | 181 int uv_rows = frame->GetHeight() / 2; // YV12 format. |
200 CopyYPlane(frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame); | 182 CopyYPlane(frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame); |
201 CopyUPlane(frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame); | 183 CopyUPlane(frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame); |
202 CopyVPlane(frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame); | 184 CopyVPlane(frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame); |
203 | 185 |
204 if (MessageLoop::current() != message_loop_) { | 186 frame_ready_cb.Run(video_frame); |
205 message_loop_->PostTask( | |
206 FROM_HERE, | |
207 base::Bind(&RTCVideoDecoder::VideoFrameReady, this, video_frame)); | |
208 } else { | |
209 VideoFrameReady(video_frame); | |
210 } | |
211 | |
212 return true; | 187 return true; |
213 } | 188 } |
OLD | NEW |