Chromium Code Reviews| 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 |