Chromium Code Reviews| Index: content/common/gpu/media/exynos_video_decode_accelerator.cc |
| diff --git a/content/common/gpu/media/exynos_video_decode_accelerator.cc b/content/common/gpu/media/exynos_video_decode_accelerator.cc |
| index 68d71293b681189c4abd10e25772774dc2d5e0b9..ae666c496e13f7a29f202a1dbc8c60b8970b32ed 100644 |
| --- a/content/common/gpu/media/exynos_video_decode_accelerator.cc |
| +++ b/content/common/gpu/media/exynos_video_decode_accelerator.cc |
| @@ -104,6 +104,13 @@ struct ExynosVideoDecodeAccelerator::EGLSyncKHRRef { |
| EGLSyncKHR egl_sync; |
| }; |
| +struct ExynosVideoDecodeAccelerator::PictureRecord { |
| + PictureRecord(bool cleared, const media::Picture& picture); |
| + ~PictureRecord(); |
| + bool cleared; // Whether the texture is cleared and safe to render from. |
| + media::Picture picture; // The decoded picture. |
| +}; |
| + |
| ExynosVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( |
| base::WeakPtr<Client>& client, |
| scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy, |
| @@ -195,12 +202,20 @@ ExynosVideoDecodeAccelerator::GscOutputRecord::GscOutputRecord() |
| fd(-1), |
| egl_image(EGL_NO_IMAGE_KHR), |
| egl_sync(EGL_NO_SYNC_KHR), |
| - picture_id(-1) { |
| -} |
| + picture_id(-1), |
| + cleared(false) {} |
| ExynosVideoDecodeAccelerator::GscOutputRecord::~GscOutputRecord() { |
| } |
| +ExynosVideoDecodeAccelerator::PictureRecord::PictureRecord( |
| + bool cleared, const media::Picture& picture) |
| + : cleared(cleared), picture(picture) { |
| +} |
| + |
| +ExynosVideoDecodeAccelerator::PictureRecord::~PictureRecord() { |
| +} |
| + |
| ExynosVideoDecodeAccelerator::ExynosVideoDecodeAccelerator( |
| EGLDisplay egl_display, |
| EGLContext egl_context, |
| @@ -236,6 +251,7 @@ ExynosVideoDecodeAccelerator::ExynosVideoDecodeAccelerator( |
| gsc_input_buffer_queued_count_(0), |
| gsc_output_streamon_(false), |
| gsc_output_buffer_queued_count_(0), |
| + picture_clearing_count_(0), |
| device_poll_thread_("ExynosDevicePollThread"), |
| device_poll_interrupt_fd_(-1), |
| make_context_current_(make_context_current), |
| @@ -1052,6 +1068,7 @@ void ExynosVideoDecodeAccelerator::AssignPictureBuffersTask( |
| DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); |
| DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
| DCHECK_EQ(output_record.picture_id, -1); |
| + DCHECK_EQ(output_record.cleared, false); |
| PictureBufferArrayRef::PictureBufferRef& buffer = |
| pic_buffers->picture_buffers[i]; |
| output_record.fd = buffer.egl_image_fd; |
| @@ -1415,9 +1432,11 @@ void ExynosVideoDecodeAccelerator::DequeueGsc() { |
| gsc_output_buffer_queued_count_--; |
| DVLOG(3) << "DequeueGsc(): returning input_id=" << dqbuf.timestamp.tv_sec |
| << " as picture_id=" << output_record.picture_id; |
| - io_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| - &Client::PictureReady, io_client_, media::Picture( |
| - output_record.picture_id, dqbuf.timestamp.tv_sec))); |
| + const media::Picture& picture = |
| + media::Picture(output_record.picture_id, dqbuf.timestamp.tv_sec); |
| + pending_picture_ready_.push(PictureRecord(output_record.cleared, picture)); |
| + SendPictureReady(); |
| + output_record.cleared = true; |
| decoder_frames_at_client_++; |
| } |
| @@ -2450,4 +2469,42 @@ void ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers() { |
| base::Unretained(this))); |
| } |
| +void ExynosVideoDecodeAccelerator::SendPictureReady() { |
| + DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| + while (pending_picture_ready_.size() > 0) { |
| + const media::Picture& picture = pending_picture_ready_.front().picture; |
| + if (!pending_picture_ready_.front().cleared) { |
| + // If the picture is not cleared, post it to the child thread because it |
| + // has to be cleared in the child thread. A picture only needs to be |
| + // cleared once. |
| + child_message_loop_proxy_->PostTaskAndReply( |
| + FROM_HERE, |
| + base::Bind(&Client::PictureReady, client_, picture), |
| + base::Bind(&ExynosVideoDecodeAccelerator::PictureCleared, |
| + weak_this_)); |
|
wuchengli
2013/10/01 13:54:50
Pawel. Thanks for the suggestion to test DASH. It
|
| + picture_clearing_count_++; |
| + pending_picture_ready_.pop(); |
| + } else if (picture_clearing_count_ == 0) { |
| + // This picture is cleared. Post it to IO thread to reduce latency. This |
| + // should be the case after all pictures are cleared at the beginning. |
| + io_message_loop_proxy_->PostTask( |
| + FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture)); |
| + pending_picture_ready_.pop(); |
| + } else { |
| + // This picture is cleared. But some pictures are about to be cleared on |
| + // the child thread. To preserve the order, do not send this until those |
| + // pictures are cleared. |
| + break; |
| + } |
| + } |
| +} |
| + |
| +void ExynosVideoDecodeAccelerator::PictureCleared() { |
| + DVLOG(3) << "PictureCleared()"; |
| + DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| + DCHECK_GT(picture_clearing_count_, 0); |
| + picture_clearing_count_--; |
| + SendPictureReady(); |
| +} |
| + |
| } // namespace content |