Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Side by Side Diff: content/common/gpu/media/exynos_video_decode_accelerator.cc

Issue 24762003: Set the texture to cleared in VideoDecodeAccelerator::PictureReady. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: refactor SendPictureReady by kcwu's suggestion Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <dlfcn.h> 5 #include <dlfcn.h>
6 #include <errno.h> 6 #include <errno.h>
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <linux/videodev2.h> 8 #include <linux/videodev2.h>
9 #include <poll.h> 9 #include <poll.h>
10 #include <sys/eventfd.h> 10 #include <sys/eventfd.h>
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 std::vector<PictureBufferRef> picture_buffers; 97 std::vector<PictureBufferRef> picture_buffers;
98 }; 98 };
99 99
100 struct ExynosVideoDecodeAccelerator::EGLSyncKHRRef { 100 struct ExynosVideoDecodeAccelerator::EGLSyncKHRRef {
101 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); 101 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync);
102 ~EGLSyncKHRRef(); 102 ~EGLSyncKHRRef();
103 EGLDisplay const egl_display; 103 EGLDisplay const egl_display;
104 EGLSyncKHR egl_sync; 104 EGLSyncKHR egl_sync;
105 }; 105 };
106 106
107 struct ExynosVideoDecodeAccelerator::PictureRecord {
108 PictureRecord(bool cleared, const media::Picture& picture);
109 ~PictureRecord();
110 bool cleared; // Whether the texture is cleared and safe to render from.
111 media::Picture picture; // The decoded picture.
112 };
113
107 ExynosVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( 114 ExynosVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef(
108 base::WeakPtr<Client>& client, 115 base::WeakPtr<Client>& client,
109 scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy, 116 scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy,
110 base::SharedMemory* shm, size_t size, int32 input_id) 117 base::SharedMemory* shm, size_t size, int32 input_id)
111 : client(client), 118 : client(client),
112 client_message_loop_proxy(client_message_loop_proxy), 119 client_message_loop_proxy(client_message_loop_proxy),
113 shm(shm), 120 shm(shm),
114 size(size), 121 size(size),
115 bytes_used(0), 122 bytes_used(0),
116 input_id(input_id) { 123 input_id(input_id) {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 195
189 ExynosVideoDecodeAccelerator::GscInputRecord::~GscInputRecord() { 196 ExynosVideoDecodeAccelerator::GscInputRecord::~GscInputRecord() {
190 } 197 }
191 198
192 ExynosVideoDecodeAccelerator::GscOutputRecord::GscOutputRecord() 199 ExynosVideoDecodeAccelerator::GscOutputRecord::GscOutputRecord()
193 : at_device(false), 200 : at_device(false),
194 at_client(false), 201 at_client(false),
195 fd(-1), 202 fd(-1),
196 egl_image(EGL_NO_IMAGE_KHR), 203 egl_image(EGL_NO_IMAGE_KHR),
197 egl_sync(EGL_NO_SYNC_KHR), 204 egl_sync(EGL_NO_SYNC_KHR),
198 picture_id(-1) { 205 picture_id(-1),
199 } 206 cleared(false) {}
200 207
201 ExynosVideoDecodeAccelerator::GscOutputRecord::~GscOutputRecord() { 208 ExynosVideoDecodeAccelerator::GscOutputRecord::~GscOutputRecord() {
202 } 209 }
203 210
211 ExynosVideoDecodeAccelerator::PictureRecord::PictureRecord(
212 bool cleared,
213 const media::Picture& picture)
214 : cleared(cleared), picture(picture) {}
215
216 ExynosVideoDecodeAccelerator::PictureRecord::~PictureRecord() {}
217
204 ExynosVideoDecodeAccelerator::ExynosVideoDecodeAccelerator( 218 ExynosVideoDecodeAccelerator::ExynosVideoDecodeAccelerator(
205 EGLDisplay egl_display, 219 EGLDisplay egl_display,
206 EGLContext egl_context, 220 EGLContext egl_context,
207 Client* client, 221 Client* client,
208 const base::WeakPtr<Client>& io_client, 222 const base::WeakPtr<Client>& io_client,
209 const base::Callback<bool(void)>& make_context_current, 223 const base::Callback<bool(void)>& make_context_current,
210 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy) 224 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy)
211 : child_message_loop_proxy_(base::MessageLoopProxy::current()), 225 : child_message_loop_proxy_(base::MessageLoopProxy::current()),
212 io_message_loop_proxy_(io_message_loop_proxy), 226 io_message_loop_proxy_(io_message_loop_proxy),
213 weak_this_(base::AsWeakPtr(this)), 227 weak_this_(base::AsWeakPtr(this)),
(...skipping 15 matching lines...) Expand all
229 mfc_input_buffer_queued_count_(0), 243 mfc_input_buffer_queued_count_(0),
230 mfc_output_streamon_(false), 244 mfc_output_streamon_(false),
231 mfc_output_buffer_queued_count_(0), 245 mfc_output_buffer_queued_count_(0),
232 mfc_output_buffer_pixelformat_(0), 246 mfc_output_buffer_pixelformat_(0),
233 mfc_output_dpb_size_(0), 247 mfc_output_dpb_size_(0),
234 gsc_fd_(-1), 248 gsc_fd_(-1),
235 gsc_input_streamon_(false), 249 gsc_input_streamon_(false),
236 gsc_input_buffer_queued_count_(0), 250 gsc_input_buffer_queued_count_(0),
237 gsc_output_streamon_(false), 251 gsc_output_streamon_(false),
238 gsc_output_buffer_queued_count_(0), 252 gsc_output_buffer_queued_count_(0),
253 picture_clearing_count_(0),
239 device_poll_thread_("ExynosDevicePollThread"), 254 device_poll_thread_("ExynosDevicePollThread"),
240 device_poll_interrupt_fd_(-1), 255 device_poll_interrupt_fd_(-1),
241 make_context_current_(make_context_current), 256 make_context_current_(make_context_current),
242 egl_display_(egl_display), 257 egl_display_(egl_display),
243 egl_context_(egl_context), 258 egl_context_(egl_context),
244 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN) {} 259 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN) {}
245 260
246 ExynosVideoDecodeAccelerator::~ExynosVideoDecodeAccelerator() { 261 ExynosVideoDecodeAccelerator::~ExynosVideoDecodeAccelerator() {
247 DCHECK(!decoder_thread_.IsRunning()); 262 DCHECK(!decoder_thread_.IsRunning());
248 DCHECK(!device_poll_thread_.IsRunning()); 263 DCHECK(!device_poll_thread_.IsRunning());
(...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after
1045 } 1060 }
1046 1061
1047 DCHECK_EQ(pic_buffers->picture_buffers.size(), gsc_output_buffer_map_.size()); 1062 DCHECK_EQ(pic_buffers->picture_buffers.size(), gsc_output_buffer_map_.size());
1048 for (size_t i = 0; i < gsc_output_buffer_map_.size(); ++i) { 1063 for (size_t i = 0; i < gsc_output_buffer_map_.size(); ++i) {
1049 // We should be blank right now. 1064 // We should be blank right now.
1050 GscOutputRecord& output_record = gsc_output_buffer_map_[i]; 1065 GscOutputRecord& output_record = gsc_output_buffer_map_[i];
1051 DCHECK_EQ(output_record.fd, -1); 1066 DCHECK_EQ(output_record.fd, -1);
1052 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); 1067 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR);
1053 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); 1068 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
1054 DCHECK_EQ(output_record.picture_id, -1); 1069 DCHECK_EQ(output_record.picture_id, -1);
1070 DCHECK_EQ(output_record.cleared, false);
1055 PictureBufferArrayRef::PictureBufferRef& buffer = 1071 PictureBufferArrayRef::PictureBufferRef& buffer =
1056 pic_buffers->picture_buffers[i]; 1072 pic_buffers->picture_buffers[i];
1057 output_record.fd = buffer.egl_image_fd; 1073 output_record.fd = buffer.egl_image_fd;
1058 output_record.egl_image = buffer.egl_image; 1074 output_record.egl_image = buffer.egl_image;
1059 output_record.picture_id = buffer.client_id; 1075 output_record.picture_id = buffer.client_id;
1060 1076
1061 // Take ownership of the EGLImage and fd. 1077 // Take ownership of the EGLImage and fd.
1062 buffer.egl_image = EGL_NO_IMAGE_KHR; 1078 buffer.egl_image = EGL_NO_IMAGE_KHR;
1063 buffer.egl_image_fd = -1; 1079 buffer.egl_image_fd = -1;
1064 // And add this buffer to the free list. 1080 // And add this buffer to the free list.
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
1408 } 1424 }
1409 GscOutputRecord& output_record = gsc_output_buffer_map_[dqbuf.index]; 1425 GscOutputRecord& output_record = gsc_output_buffer_map_[dqbuf.index];
1410 DCHECK(output_record.at_device); 1426 DCHECK(output_record.at_device);
1411 DCHECK(!output_record.at_client); 1427 DCHECK(!output_record.at_client);
1412 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); 1428 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
1413 output_record.at_device = false; 1429 output_record.at_device = false;
1414 output_record.at_client = true; 1430 output_record.at_client = true;
1415 gsc_output_buffer_queued_count_--; 1431 gsc_output_buffer_queued_count_--;
1416 DVLOG(3) << "DequeueGsc(): returning input_id=" << dqbuf.timestamp.tv_sec 1432 DVLOG(3) << "DequeueGsc(): returning input_id=" << dqbuf.timestamp.tv_sec
1417 << " as picture_id=" << output_record.picture_id; 1433 << " as picture_id=" << output_record.picture_id;
1418 io_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( 1434 const media::Picture& picture =
1419 &Client::PictureReady, io_client_, media::Picture( 1435 media::Picture(output_record.picture_id, dqbuf.timestamp.tv_sec);
1420 output_record.picture_id, dqbuf.timestamp.tv_sec))); 1436 pending_picture_ready_.push(PictureRecord(output_record.cleared, picture));
1437 SendPictureReady();
1438 output_record.cleared = true;
1421 decoder_frames_at_client_++; 1439 decoder_frames_at_client_++;
1422 } 1440 }
1423 1441
1424 NotifyFlushDoneIfNeeded(); 1442 NotifyFlushDoneIfNeeded();
1425 } 1443 }
1426 1444
1427 bool ExynosVideoDecodeAccelerator::EnqueueMfcInputRecord() { 1445 bool ExynosVideoDecodeAccelerator::EnqueueMfcInputRecord() {
1428 DVLOG(3) << "EnqueueMfcInputRecord()"; 1446 DVLOG(3) << "EnqueueMfcInputRecord()";
1429 DCHECK(!mfc_input_ready_queue_.empty()); 1447 DCHECK(!mfc_input_ready_queue_.empty());
1430 1448
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
1622 } 1640 }
1623 1641
1624 // We don't support stacked flushing. 1642 // We don't support stacked flushing.
1625 DCHECK(!decoder_flushing_); 1643 DCHECK(!decoder_flushing_);
1626 1644
1627 // Queue up an empty buffer -- this triggers the flush. 1645 // Queue up an empty buffer -- this triggers the flush.
1628 decoder_input_queue_.push_back(linked_ptr<BitstreamBufferRef>( 1646 decoder_input_queue_.push_back(linked_ptr<BitstreamBufferRef>(
1629 new BitstreamBufferRef(io_client_, io_message_loop_proxy_, NULL, 0, 1647 new BitstreamBufferRef(io_client_, io_message_loop_proxy_, NULL, 0,
1630 kFlushBufferId))); 1648 kFlushBufferId)));
1631 decoder_flushing_ = true; 1649 decoder_flushing_ = true;
1650 SendPictureReady(); // Send all pending PictureReady.
1632 1651
1633 ScheduleDecodeBufferTaskIfNeeded(); 1652 ScheduleDecodeBufferTaskIfNeeded();
1634 } 1653 }
1635 1654
1636 void ExynosVideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { 1655 void ExynosVideoDecodeAccelerator::NotifyFlushDoneIfNeeded() {
1637 if (!decoder_flushing_) 1656 if (!decoder_flushing_)
1638 return; 1657 return;
1639 1658
1640 // Pipeline is empty when: 1659 // Pipeline is empty when:
1641 // * Decoder input queue is empty of non-delayed buffers. 1660 // * Decoder input queue is empty of non-delayed buffers.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1715 1734
1716 decoder_current_input_buffer_ = -1; 1735 decoder_current_input_buffer_ = -1;
1717 1736
1718 // If we were flushing, we'll never return any more BitstreamBuffers or 1737 // If we were flushing, we'll never return any more BitstreamBuffers or
1719 // PictureBuffers; they have all been dropped and returned by now. 1738 // PictureBuffers; they have all been dropped and returned by now.
1720 NotifyFlushDoneIfNeeded(); 1739 NotifyFlushDoneIfNeeded();
1721 1740
1722 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening 1741 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening
1723 // jobs will early-out in the kResetting state. 1742 // jobs will early-out in the kResetting state.
1724 decoder_state_ = kResetting; 1743 decoder_state_ = kResetting;
1744 SendPictureReady(); // Send all pending PictureReady.
1725 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 1745 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
1726 &ExynosVideoDecodeAccelerator::ResetDoneTask, base::Unretained(this))); 1746 &ExynosVideoDecodeAccelerator::ResetDoneTask, base::Unretained(this)));
1727 } 1747 }
1728 1748
1729 void ExynosVideoDecodeAccelerator::ResetDoneTask() { 1749 void ExynosVideoDecodeAccelerator::ResetDoneTask() {
1730 DVLOG(3) << "ResetDoneTask()"; 1750 DVLOG(3) << "ResetDoneTask()";
1731 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1751 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1732 TRACE_EVENT0("Video Decoder", "EVDA::ResetDoneTask"); 1752 TRACE_EVENT0("Video Decoder", "EVDA::ResetDoneTask");
1733 1753
1734 if (decoder_state_ == kError) { 1754 if (decoder_state_ == kError) {
(...skipping 708 matching lines...) Expand 10 before | Expand all | Expand 10 after
2443 DestroyGscInputBuffers(); 2463 DestroyGscInputBuffers();
2444 DestroyGscOutputBuffers(); 2464 DestroyGscOutputBuffers();
2445 DestroyMfcOutputBuffers(); 2465 DestroyMfcOutputBuffers();
2446 2466
2447 // Finish resolution change on decoder thread. 2467 // Finish resolution change on decoder thread.
2448 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 2468 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
2449 &ExynosVideoDecodeAccelerator::FinishResolutionChange, 2469 &ExynosVideoDecodeAccelerator::FinishResolutionChange,
2450 base::Unretained(this))); 2470 base::Unretained(this)));
2451 } 2471 }
2452 2472
2473 void ExynosVideoDecodeAccelerator::SendPictureReady() {
2474 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
2475 bool resetting_or_flushing =
2476 (decoder_state_ == kResetting || decoder_flushing_);
2477 while (pending_picture_ready_.size() > 0) {
2478 bool cleared = pending_picture_ready_.front().cleared;
2479 const media::Picture& picture = pending_picture_ready_.front().picture;
2480 if (cleared && picture_clearing_count_ == 0) {
2481 // This picture is cleared. Post it to IO thread to reduce latency. This
2482 // should be the case after all pictures are cleared at the beginning.
2483 io_message_loop_proxy_->PostTask(
2484 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture));
2485 pending_picture_ready_.pop();
2486 } else if (!cleared || resetting_or_flushing) {
2487 DVLOG(3) << "SendPictureReady()"
2488 << ". cleared=" << pending_picture_ready_.front().cleared
2489 << ", decoder_state_=" << decoder_state_
2490 << ", decoder_flushing_=" << decoder_flushing_
2491 << ", picture_clearing_count_=" << picture_clearing_count_;
2492 // If the picture is not cleared, post it to the child thread because it
2493 // has to be cleared in the child thread. A picture only needs to be
2494 // cleared once. If the decoder is resetting or flushing, send all
2495 // pictures to ensure PictureReady arrive before reset or flush done.
2496 child_message_loop_proxy_->PostTaskAndReply(
2497 FROM_HERE,
2498 base::Bind(&Client::PictureReady, client_, picture),
2499 // Unretained is safe. If Client::PictureReady gets to run, |this| is
2500 // alive. Destroy() will wait the decode thread to finish.
2501 base::Bind(&ExynosVideoDecodeAccelerator::PictureCleared,
2502 base::Unretained(this)));
2503 picture_clearing_count_++;
2504 pending_picture_ready_.pop();
2505 } else {
2506 // This picture is cleared. But some pictures are about to be cleared on
2507 // the child thread. To preserve the order, do not send this until those
2508 // pictures are cleared.
2509 break;
2510 }
2511 }
2512 }
2513
2514 void ExynosVideoDecodeAccelerator::PictureCleared() {
2515 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_;
2516 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
2517 DCHECK_GT(picture_clearing_count_, 0);
2518 picture_clearing_count_--;
2519 SendPictureReady();
2520 }
2521
2453 } // namespace content 2522 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/exynos_video_decode_accelerator.h ('k') | content/common/gpu/media/gpu_video_decode_accelerator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698