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..a261035154014281eca4a8c1b16b4e85972176ae 100644 |
--- a/content/common/gpu/media/exynos_video_decode_accelerator.cc |
+++ b/content/common/gpu/media/exynos_video_decode_accelerator.cc |
@@ -195,8 +195,8 @@ 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() { |
} |
@@ -236,6 +236,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 +1053,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 +1417,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(std::make_pair(output_record.cleared, picture)); |
+ SendPictureReady(); |
+ output_record.cleared = true; |
decoder_frames_at_client_++; |
} |
@@ -2450,4 +2454,41 @@ void ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers() { |
base::Unretained(this))); |
} |
+void ExynosVideoDecodeAccelerator::SendPictureReady() { |
+ DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
+ while (pending_picture_ready_.size() > 0) { |
+ bool cleared = pending_picture_ready_.front().first; |
+ const media::Picture& picture = pending_picture_ready_.front().second; |
+ if (!cleared) { |
+ // If the picture is not cleared, post it to the child thread because it |
+ // has to be cleared in the child thread. |
+ child_message_loop_proxy_->PostTaskAndReply( |
+ FROM_HERE, |
+ base::Bind(&Client::PictureReady, client_, picture), |
+ base::Bind(&ExynosVideoDecodeAccelerator::PictureCleared, |
+ weak_this_)); |
+ 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. |
+ 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(picture_clearing_count_ > 0); |
piman
2013/09/30 21:49:13
nit: DCHECK_GT
wuchengli
2013/10/01 03:49:43
Done.
|
+ picture_clearing_count_--; |
+ SendPictureReady(); |
+} |
+ |
} // namespace content |