| 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 if (MessageLoop::current() != message_loop_) { | 46 if (MessageLoop::current() != message_loop_) { |
| 47 message_loop_->PostTask( | 47 message_loop_->PostTask( |
| 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 | |
| 57 lock_.Acquire(); | |
| 58 frame_queue_available_.clear(); | |
| 59 lock_.Release(); | |
| 60 | |
| 61 state_ = kNormal; | 56 state_ = kNormal; |
| 62 | |
| 63 filter_callback.Run(); | 57 filter_callback.Run(); |
| 64 | 58 |
| 65 // TODO(acolwell): Implement stats. | 59 // TODO(acolwell): Implement stats. |
| 66 } | 60 } |
| 67 | 61 |
| 68 void RTCVideoDecoder::Play(const base::Closure& callback) { | 62 void RTCVideoDecoder::Play(const base::Closure& callback) { |
| 69 if (MessageLoop::current() != message_loop_) { | 63 if (MessageLoop::current() != message_loop_) { |
| 70 message_loop_->PostTask(FROM_HERE, | 64 message_loop_->PostTask(FROM_HERE, |
| 71 base::Bind(&RTCVideoDecoder::Play, | 65 base::Bind(&RTCVideoDecoder::Play, |
| 72 this, callback)); | 66 this, callback)); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 | 104 |
| 111 void RTCVideoDecoder::Seek(base::TimeDelta time, const FilterStatusCB& cb) { | 105 void RTCVideoDecoder::Seek(base::TimeDelta time, const FilterStatusCB& cb) { |
| 112 if (MessageLoop::current() != message_loop_) { | 106 if (MessageLoop::current() != message_loop_) { |
| 113 message_loop_->PostTask(FROM_HERE, | 107 message_loop_->PostTask(FROM_HERE, |
| 114 base::Bind(&RTCVideoDecoder::Seek, this, | 108 base::Bind(&RTCVideoDecoder::Seek, this, |
| 115 time, cb)); | 109 time, cb)); |
| 116 return; | 110 return; |
| 117 } | 111 } |
| 118 | 112 |
| 119 DCHECK_EQ(MessageLoop::current(), message_loop_); | 113 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; | 114 state_ = kNormal; |
| 130 | |
| 131 cb.Run(PIPELINE_OK); | 115 cb.Run(PIPELINE_OK); |
| 132 } | 116 } |
| 133 | 117 |
| 134 void RTCVideoDecoder::ProduceVideoFrame( | 118 void RTCVideoDecoder::Read(const ReadCB& callback) { |
| 135 scoped_refptr<VideoFrame> video_frame) { | |
| 136 if (MessageLoop::current() != message_loop_) { | 119 if (MessageLoop::current() != message_loop_) { |
| 137 message_loop_->PostTask( | 120 message_loop_->PostTask( |
| 138 FROM_HERE, | 121 FROM_HERE, |
| 139 base::Bind(&RTCVideoDecoder::ProduceVideoFrame, this, video_frame)); | 122 base::Bind(&RTCVideoDecoder::Read, this, callback)); |
| 140 return; | 123 return; |
| 141 } | 124 } |
| 142 DCHECK_EQ(MessageLoop::current(), message_loop_); | 125 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 143 base::AutoLock auto_lock(lock_); | 126 base::AutoLock auto_lock(lock_); |
| 144 frame_queue_available_.push_back(video_frame); | 127 CHECK(read_cb_.is_null()); |
| 128 read_cb_ = callback; |
| 145 } | 129 } |
| 146 | 130 |
| 147 gfx::Size RTCVideoDecoder::natural_size() { | 131 const gfx::Size& RTCVideoDecoder::natural_size() { |
| 148 // TODO(vrk): Return natural size when aspect ratio support is implemented. | 132 // TODO(vrk): Return natural size when aspect ratio support is implemented. |
| 149 return visible_size_; | 133 return visible_size_; |
| 150 } | 134 } |
| 151 | 135 |
| 152 bool RTCVideoDecoder::SetSize(int width, int height, int reserved) { | 136 bool RTCVideoDecoder::SetSize(int width, int height, int reserved) { |
| 153 visible_size_.SetSize(width, height); | 137 visible_size_.SetSize(width, height); |
| 154 | 138 |
| 155 // TODO(vrk): Provide natural size when aspect ratio support is implemented. | 139 // TODO(vrk): Provide natural size when aspect ratio support is implemented. |
| 156 host()->SetNaturalVideoSize(visible_size_); | 140 host()->SetNaturalVideoSize(visible_size_); |
| 157 return true; | 141 return true; |
| 158 } | 142 } |
| 159 | 143 |
| 160 bool RTCVideoDecoder::RenderFrame(const cricket::VideoFrame* frame) { | 144 bool RTCVideoDecoder::RenderFrame(const cricket::VideoFrame* frame) { |
| 145 // Called from libjingle thread. |
| 161 DCHECK(frame); | 146 DCHECK(frame); |
| 162 | 147 |
| 163 if (state_ != kNormal) | 148 if (state_ != kNormal) |
| 164 return true; | 149 return true; |
| 165 | 150 |
| 166 // This is called from another thread. | 151 ReadCB read_cb; |
| 167 scoped_refptr<VideoFrame> video_frame; | |
| 168 { | 152 { |
| 169 base::AutoLock auto_lock(lock_); | 153 base::AutoLock auto_lock(lock_); |
| 170 if (frame_queue_available_.size() == 0) { | 154 if (read_cb_.is_null()) { |
| 171 return true; | 155 return true; |
| 172 } | 156 } |
| 173 video_frame = frame_queue_available_.front(); | 157 std::swap(read_cb, read_cb_); |
| 174 frame_queue_available_.pop_front(); | |
| 175 } | 158 } |
| 176 | 159 |
| 177 // Check if there's a size change. | 160 // Always allocate a new frame. |
| 178 // TODO(vrk): Remove casts when media::VideoFrame is updated with gfx::Sizes | 161 // |
| 179 // for width/height. | 162 // TODO(scherkus): migrate this to proper buffer recycling. |
| 180 if (video_frame->width() != static_cast<size_t>(visible_size_.width()) || | 163 scoped_refptr<media::VideoFrame> video_frame = |
| 181 video_frame->height() != static_cast<size_t>(visible_size_.height())) { | 164 VideoFrame::CreateFrame(VideoFrame::YV12, |
| 182 // Allocate new buffer based on the new size. | 165 visible_size_.width(), |
| 183 video_frame = VideoFrame::CreateFrame(VideoFrame::YV12, | 166 visible_size_.height(), |
| 184 visible_size_.width(), | 167 host()->GetTime(), |
| 185 visible_size_.height(), | 168 base::TimeDelta::FromMilliseconds(30)); |
| 186 kNoTimestamp, | |
| 187 kNoTimestamp); | |
| 188 } | |
| 189 | 169 |
| 190 // Only YV12 frames are supported. | |
| 191 DCHECK(video_frame->format() == VideoFrame::YV12); | |
| 192 // Aspect ratio unsupported; DCHECK when there are non-square pixels. | 170 // Aspect ratio unsupported; DCHECK when there are non-square pixels. |
| 193 DCHECK(frame->GetPixelWidth() == 1); | 171 DCHECK_EQ(frame->GetPixelWidth(), 1u); |
| 194 DCHECK(frame->GetPixelHeight() == 1); | 172 DCHECK_EQ(frame->GetPixelHeight(), 1u); |
| 195 video_frame->SetTimestamp(host()->GetTime()); | |
| 196 video_frame->SetDuration(base::TimeDelta::FromMilliseconds(30)); | |
| 197 | 173 |
| 198 int y_rows = frame->GetHeight(); | 174 int y_rows = frame->GetHeight(); |
| 199 int uv_rows = frame->GetHeight() / 2; // YV12 format. | 175 int uv_rows = frame->GetHeight() / 2; // YV12 format. |
| 200 CopyYPlane(frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame); | 176 CopyYPlane(frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame); |
| 201 CopyUPlane(frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame); | 177 CopyUPlane(frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame); |
| 202 CopyVPlane(frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame); | 178 CopyVPlane(frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame); |
| 203 | 179 |
| 204 if (MessageLoop::current() != message_loop_) { | 180 read_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; | 181 return true; |
| 213 } | 182 } |
| OLD | NEW |