Chromium Code Reviews| 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 "media/filters/gpu_video_decoder.h" | 5 #include "media/filters/gpu_video_decoder.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 | 29 |
| 30 GpuVideoDecoder::SHMBuffer::~SHMBuffer() {} | 30 GpuVideoDecoder::SHMBuffer::~SHMBuffer() {} |
| 31 | 31 |
| 32 GpuVideoDecoder::BufferPair::BufferPair( | 32 GpuVideoDecoder::BufferPair::BufferPair( |
| 33 SHMBuffer* s, const scoped_refptr<DecoderBuffer>& b) | 33 SHMBuffer* s, const scoped_refptr<DecoderBuffer>& b) |
| 34 : shm_buffer(s), buffer(b) { | 34 : shm_buffer(s), buffer(b) { |
| 35 } | 35 } |
| 36 | 36 |
| 37 GpuVideoDecoder::BufferPair::~BufferPair() {} | 37 GpuVideoDecoder::BufferPair::~BufferPair() {} |
| 38 | 38 |
| 39 GpuVideoDecoder::BufferTimeData::BufferTimeData( | |
| 40 int32 bbid, base::TimeDelta ts, base::TimeDelta dur) | |
| 41 : bitstream_buffer_id(bbid), timestamp(ts), duration(dur) { | |
| 42 } | |
| 43 | |
| 44 GpuVideoDecoder::BufferTimeData::~BufferTimeData() {} | |
| 45 | |
| 46 GpuVideoDecoder::GpuVideoDecoder( | 39 GpuVideoDecoder::GpuVideoDecoder( |
| 47 MessageLoop* message_loop, | 40 MessageLoop* message_loop, |
| 48 MessageLoop* vda_loop, | 41 MessageLoop* vda_loop, |
| 49 const scoped_refptr<Factories>& factories) | 42 const scoped_refptr<Factories>& factories) |
| 50 : gvd_loop_proxy_(message_loop->message_loop_proxy()), | 43 : gvd_loop_proxy_(message_loop->message_loop_proxy()), |
| 51 vda_loop_proxy_(vda_loop->message_loop_proxy()), | 44 vda_loop_proxy_(vda_loop->message_loop_proxy()), |
| 52 factories_(factories), | 45 factories_(factories), |
| 53 state_(kNormal), | 46 state_(kNormal), |
| 54 demuxer_read_in_progress_(false), | 47 demuxer_read_in_progress_(false), |
| 55 decoder_texture_target_(0), | 48 decoder_texture_target_(0), |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 156 return; | 149 return; |
| 157 } | 150 } |
| 158 | 151 |
| 159 demuxer_stream_ = stream; | 152 demuxer_stream_ = stream; |
| 160 statistics_cb_ = statistics_cb; | 153 statistics_cb_ = statistics_cb; |
| 161 | 154 |
| 162 if (config.codec() == kCodecH264) | 155 if (config.codec() == kCodecH264) |
| 163 demuxer_stream_->EnableBitstreamConverter(); | 156 demuxer_stream_->EnableBitstreamConverter(); |
| 164 | 157 |
| 165 natural_size_ = config.natural_size(); | 158 natural_size_ = config.natural_size(); |
| 166 config_frame_duration_ = GetFrameDuration(config); | |
| 167 | 159 |
| 168 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded."; | 160 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded."; |
| 169 vda_loop_proxy_->PostTaskAndReply( | 161 vda_loop_proxy_->PostTaskAndReply( |
| 170 FROM_HERE, | 162 FROM_HERE, |
| 171 base::Bind(&GpuVideoDecoder::SetVDA, this, vda), | 163 base::Bind(&GpuVideoDecoder::SetVDA, this, vda), |
| 172 base::Bind(status_cb, PIPELINE_OK)); | 164 base::Bind(status_cb, PIPELINE_OK)); |
| 173 } | 165 } |
| 174 | 166 |
| 175 void GpuVideoDecoder::SetVDA(VideoDecodeAccelerator* vda) { | 167 void GpuVideoDecoder::SetVDA(VideoDecodeAccelerator* vda) { |
| 176 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); | 168 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; | 259 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; |
| 268 DCHECK(inserted); | 260 DCHECK(inserted); |
| 269 RecordBufferTimeData(bitstream_buffer, *buffer); | 261 RecordBufferTimeData(bitstream_buffer, *buffer); |
| 270 | 262 |
| 271 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 263 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 272 &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer)); | 264 &VideoDecodeAccelerator::Decode, weak_vda_, bitstream_buffer)); |
| 273 } | 265 } |
| 274 | 266 |
| 275 void GpuVideoDecoder::RecordBufferTimeData( | 267 void GpuVideoDecoder::RecordBufferTimeData( |
| 276 const BitstreamBuffer& bitstream_buffer, const Buffer& buffer) { | 268 const BitstreamBuffer& bitstream_buffer, const Buffer& buffer) { |
| 277 base::TimeDelta duration = buffer.GetDuration(); | |
| 278 if (duration == base::TimeDelta()) | |
| 279 duration = config_frame_duration_; | |
| 280 input_buffer_time_data_.push_front(BufferTimeData( | 269 input_buffer_time_data_.push_front(BufferTimeData( |
| 281 bitstream_buffer.id(), buffer.GetTimestamp(), duration)); | 270 bitstream_buffer.id(), buffer.GetTimestamp())); |
| 282 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but | 271 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but |
| 283 // that's too small for some pathological B-frame test videos. The cost of | 272 // that's too small for some pathological B-frame test videos. The cost of |
| 284 // using too-high a value is low (192 bits per extra slot). | 273 // using too-high a value is low (192 bits per extra slot). |
| 285 static const size_t kMaxInputBufferTimeDataSize = 128; | 274 static const size_t kMaxInputBufferTimeDataSize = 128; |
| 286 // Pop from the back of the list, because that's the oldest and least likely | 275 // Pop from the back of the list, because that's the oldest and least likely |
| 287 // to be useful in the future data. | 276 // to be useful in the future data. |
| 288 if (input_buffer_time_data_.size() > kMaxInputBufferTimeDataSize) | 277 if (input_buffer_time_data_.size() > kMaxInputBufferTimeDataSize) |
| 289 input_buffer_time_data_.pop_back(); | 278 input_buffer_time_data_.pop_back(); |
| 290 } | 279 } |
| 291 | 280 |
| 292 void GpuVideoDecoder::GetBufferTimeData( | 281 base::TimeDelta GpuVideoDecoder::GetBufferTimeData(int32 id) { |
| 293 int32 id, base::TimeDelta* timestamp, base::TimeDelta* duration) { | |
| 294 // If all else fails later, at least we can set a default duration if there | |
| 295 // was one in the config. | |
| 296 *duration = config_frame_duration_; | |
| 297 for (std::list<BufferTimeData>::const_iterator it = | 282 for (std::list<BufferTimeData>::const_iterator it = |
| 298 input_buffer_time_data_.begin(); it != input_buffer_time_data_.end(); | 283 input_buffer_time_data_.begin(); it != input_buffer_time_data_.end(); |
| 299 ++it) { | 284 ++it) { |
| 300 if (it->bitstream_buffer_id != id) | 285 if (it->first != id) |
| 301 continue; | 286 continue; |
| 302 *timestamp = it->timestamp; | 287 return it->second; |
|
Ami GONE FROM CHROMIUM
2012/07/31 18:44:42
now that you're returning the value it'd be cleare
acolwell GONE FROM CHROMIUM
2012/07/31 19:23:44
Done.
| |
| 303 *duration = it->duration; | |
| 304 return; | |
| 305 } | 288 } |
| 306 NOTREACHED() << "Missing bitstreambuffer id: " << id; | 289 NOTREACHED() << "Missing bitstreambuffer id: " << id; |
| 290 return kNoTimestamp(); | |
| 307 } | 291 } |
| 308 | 292 |
| 309 const gfx::Size& GpuVideoDecoder::natural_size() { | 293 const gfx::Size& GpuVideoDecoder::natural_size() { |
| 310 return natural_size_; | 294 return natural_size_; |
| 311 } | 295 } |
| 312 | 296 |
| 313 bool GpuVideoDecoder::HasAlpha() const { | 297 bool GpuVideoDecoder::HasAlpha() const { |
| 314 return true; | 298 return true; |
| 315 } | 299 } |
| 316 | 300 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 386 std::map<int32, PictureBuffer>::iterator it = | 370 std::map<int32, PictureBuffer>::iterator it = |
| 387 picture_buffers_in_decoder_.find(picture.picture_buffer_id()); | 371 picture_buffers_in_decoder_.find(picture.picture_buffer_id()); |
| 388 if (it == picture_buffers_in_decoder_.end()) { | 372 if (it == picture_buffers_in_decoder_.end()) { |
| 389 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); | 373 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); |
| 390 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 374 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 391 return; | 375 return; |
| 392 } | 376 } |
| 393 const PictureBuffer& pb = it->second; | 377 const PictureBuffer& pb = it->second; |
| 394 | 378 |
| 395 // Update frame's timestamp. | 379 // Update frame's timestamp. |
| 396 base::TimeDelta timestamp; | 380 base::TimeDelta timestamp = GetBufferTimeData(picture.bitstream_buffer_id()); |
| 397 base::TimeDelta duration; | |
| 398 GetBufferTimeData(picture.bitstream_buffer_id(), ×tamp, &duration); | |
| 399 | |
| 400 DCHECK(decoder_texture_target_); | 381 DCHECK(decoder_texture_target_); |
| 401 scoped_refptr<VideoFrame> frame(VideoFrame::WrapNativeTexture( | 382 scoped_refptr<VideoFrame> frame(VideoFrame::WrapNativeTexture( |
| 402 pb.texture_id(), decoder_texture_target_, pb.size().width(), | 383 pb.texture_id(), decoder_texture_target_, pb.size().width(), |
| 403 pb.size().height(), timestamp, duration, | 384 pb.size().height(), timestamp, |
| 404 base::Bind(&GpuVideoDecoder::ReusePictureBuffer, this, | 385 base::Bind(&GpuVideoDecoder::ReusePictureBuffer, this, |
| 405 picture.picture_buffer_id()))); | 386 picture.picture_buffer_id()))); |
| 406 | 387 |
| 407 EnqueueFrameAndTriggerFrameDelivery(frame); | 388 EnqueueFrameAndTriggerFrameDelivery(frame); |
| 408 } | 389 } |
| 409 | 390 |
| 410 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( | 391 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( |
| 411 const scoped_refptr<VideoFrame>& frame) { | 392 const scoped_refptr<VideoFrame>& frame) { |
| 412 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 393 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
| 413 | 394 |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 567 | 548 |
| 568 error_occured_ = true; | 549 error_occured_ = true; |
| 569 | 550 |
| 570 if (!pending_read_cb_.is_null()) { | 551 if (!pending_read_cb_.is_null()) { |
| 571 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); | 552 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); |
| 572 return; | 553 return; |
| 573 } | 554 } |
| 574 } | 555 } |
| 575 | 556 |
| 576 } // namespace media | 557 } // namespace media |
| OLD | NEW |