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

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

Issue 22590009: EVDA: Add support for dynamic resolution change and MSE players. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 4 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 do { \ 43 do { \
44 if (HANDLE_EINTR(ioctl(fd, type, arg) != 0)) { \ 44 if (HANDLE_EINTR(ioctl(fd, type, arg) != 0)) { \
45 DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \ 45 DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
46 NOTIFY_ERROR(PLATFORM_FAILURE); \ 46 NOTIFY_ERROR(PLATFORM_FAILURE); \
47 return false; \ 47 return false; \
48 } \ 48 } \
49 } while (0) 49 } while (0)
50 50
51 namespace { 51 namespace {
52 52
53 // TODO(posciak): remove once we update linux-headers.
54 #ifndef V4L2_EVENT_RESOLUTION_CHANGE
55 #define V4L2_EVENT_RESOLUTION_CHANGE 5
56 #endif
57
53 const char kExynosMfcDevice[] = "/dev/mfc-dec"; 58 const char kExynosMfcDevice[] = "/dev/mfc-dec";
54 const char kExynosGscDevice[] = "/dev/gsc1"; 59 const char kExynosGscDevice[] = "/dev/gsc1";
55 const char kMaliDriver[] = "libmali.so"; 60 const char kMaliDriver[] = "libmali.so";
56 61
57 typedef EGLBoolean (*MaliEglImageGetBufferExtPhandleFunc)(EGLImageKHR, EGLint*, 62 typedef EGLBoolean (*MaliEglImageGetBufferExtPhandleFunc)(EGLImageKHR, EGLint*,
58 void*); 63 void*);
59 64
60 void* libmali_handle = NULL; 65 void* libmali_handle = NULL;
61 MaliEglImageGetBufferExtPhandleFunc 66 MaliEglImageGetBufferExtPhandleFunc
62 mali_egl_image_get_buffer_ext_phandle = NULL; 67 mali_egl_image_get_buffer_ext_phandle = NULL;
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 weak_this_(base::AsWeakPtr(this)), 210 weak_this_(base::AsWeakPtr(this)),
206 client_ptr_factory_(client), 211 client_ptr_factory_(client),
207 client_(client_ptr_factory_.GetWeakPtr()), 212 client_(client_ptr_factory_.GetWeakPtr()),
208 decoder_thread_("ExynosDecoderThread"), 213 decoder_thread_("ExynosDecoderThread"),
209 decoder_state_(kUninitialized), 214 decoder_state_(kUninitialized),
210 decoder_delay_bitstream_buffer_id_(-1), 215 decoder_delay_bitstream_buffer_id_(-1),
211 decoder_current_input_buffer_(-1), 216 decoder_current_input_buffer_(-1),
212 decoder_decode_buffer_tasks_scheduled_(0), 217 decoder_decode_buffer_tasks_scheduled_(0),
213 decoder_frames_at_client_(0), 218 decoder_frames_at_client_(0),
214 decoder_flushing_(false), 219 decoder_flushing_(false),
220 resolution_change_pending_(false),
221 reset_pending_(false),
215 decoder_partial_frame_pending_(false), 222 decoder_partial_frame_pending_(false),
216 mfc_fd_(-1), 223 mfc_fd_(-1),
217 mfc_input_streamon_(false), 224 mfc_input_streamon_(false),
218 mfc_input_buffer_queued_count_(0), 225 mfc_input_buffer_queued_count_(0),
219 mfc_output_streamon_(false), 226 mfc_output_streamon_(false),
220 mfc_output_buffer_queued_count_(0), 227 mfc_output_buffer_queued_count_(0),
221 mfc_output_buffer_pixelformat_(0), 228 mfc_output_buffer_pixelformat_(0),
222 mfc_output_dpb_size_(0), 229 mfc_output_dpb_size_(0),
223 gsc_fd_(-1), 230 gsc_fd_(-1),
224 gsc_input_streamon_(false), 231 gsc_input_streamon_(false),
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 if (!CreateMfcInputBuffers()) 379 if (!CreateMfcInputBuffers())
373 return false; 380 return false;
374 381
375 // MFC output format has to be setup before streaming starts. 382 // MFC output format has to be setup before streaming starts.
376 struct v4l2_format format; 383 struct v4l2_format format;
377 memset(&format, 0, sizeof(format)); 384 memset(&format, 0, sizeof(format));
378 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 385 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
379 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16; 386 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16;
380 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_S_FMT, &format); 387 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_S_FMT, &format);
381 388
389 // Subscribe for the resolution change event.
Ami GONE FROM CHROMIUM 2013/08/09 16:55:41 s/for/to/
Pawel Osciak 2013/08/11 12:40:13 Done.
390 struct v4l2_event_subscription sub;
391 memset(&sub, 0, sizeof(sub));
392 sub.type = V4L2_EVENT_RESOLUTION_CHANGE;
393 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_SUBSCRIBE_EVENT, &sub);
394
382 // Initialize format-specific bits. 395 // Initialize format-specific bits.
383 if (video_profile_ >= media::H264PROFILE_MIN && 396 if (video_profile_ >= media::H264PROFILE_MIN &&
384 video_profile_ <= media::H264PROFILE_MAX) { 397 video_profile_ <= media::H264PROFILE_MAX) {
385 decoder_h264_parser_.reset(new content::H264Parser()); 398 decoder_h264_parser_.reset(new content::H264Parser());
386 } 399 }
387 400
388 if (!decoder_thread_.Start()) { 401 if (!decoder_thread_.Start()) {
389 DLOG(ERROR) << "Initialize(): decoder thread failed to start"; 402 DLOG(ERROR) << "Initialize(): decoder thread failed to start";
390 NOTIFY_ERROR(PLATFORM_FAILURE); 403 NOTIFY_ERROR(PLATFORM_FAILURE);
391 return false; 404 return false;
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
630 TRACE_EVENT0("Video Decoder", "EVDA::DecodeBufferTask"); 643 TRACE_EVENT0("Video Decoder", "EVDA::DecodeBufferTask");
631 644
632 decoder_decode_buffer_tasks_scheduled_--; 645 decoder_decode_buffer_tasks_scheduled_--;
633 646
634 if (decoder_state_ == kResetting) { 647 if (decoder_state_ == kResetting) {
635 DVLOG(2) << "DecodeBufferTask(): early out: kResetting state"; 648 DVLOG(2) << "DecodeBufferTask(): early out: kResetting state";
636 return; 649 return;
637 } else if (decoder_state_ == kError) { 650 } else if (decoder_state_ == kError) {
638 DVLOG(2) << "DecodeBufferTask(): early out: kError state"; 651 DVLOG(2) << "DecodeBufferTask(): early out: kError state";
639 return; 652 return;
653 } else if (decoder_state_ == kChangingResolution) {
654 DVLOG(2) << "DecodeBufferTask(): early out: resolution change pending";
655 return;
640 } 656 }
641 657
642 if (decoder_current_bitstream_buffer_ == NULL) { 658 if (decoder_current_bitstream_buffer_ == NULL) {
643 if (decoder_input_queue_.empty()) { 659 if (decoder_input_queue_.empty()) {
644 // We're waiting for a new buffer -- exit without scheduling a new task. 660 // We're waiting for a new buffer -- exit without scheduling a new task.
645 return; 661 return;
646 } 662 }
647 linked_ptr<BitstreamBufferRef>& buffer_ref = decoder_input_queue_.front(); 663 linked_ptr<BitstreamBufferRef>& buffer_ref = decoder_input_queue_.front();
648 if (decoder_delay_bitstream_buffer_id_ == buffer_ref->input_id) { 664 if (decoder_delay_bitstream_buffer_id_ == buffer_ref->input_id) {
649 // We're asked to delay decoding on this and subsequent buffers. 665 // We're asked to delay decoding on this and subsequent buffers.
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
855 return true; 871 return true;
856 872
857 if (!FlushInputFrame()) 873 if (!FlushInputFrame())
858 return false; 874 return false;
859 875
860 // Recycle buffers. 876 // Recycle buffers.
861 DequeueMfc(); 877 DequeueMfc();
862 878
863 // Check and see if we have format info yet. 879 // Check and see if we have format info yet.
864 struct v4l2_format format; 880 struct v4l2_format format;
865 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 881 bool again = false;
866 if (ioctl(mfc_fd_, VIDIOC_G_FMT, &format) != 0) { 882 if (!GetFormatInfo(&format, &again))
867 if (errno == EINVAL) { 883 return false;
868 // We will get EINVAL if we haven't seen sufficient stream to decode the 884
869 // format. Return true and schedule the next buffer. 885 if (again) {
870 *endpos = size; 886 // Need more stream to decode format, return true and schedule next buffer.
871 return true; 887 *endpos = size;
872 } else { 888 return true;
873 DPLOG(ERROR) << "DecodeBufferInitial(): ioctl() failed: VIDIOC_G_FMT";
874 NOTIFY_ERROR(PLATFORM_FAILURE);
875 return false;
876 }
877 } 889 }
878 890
879 // Run this initialization only on first startup. 891 // Run this initialization only on first startup.
880 if (decoder_state_ == kInitialized) { 892 if (decoder_state_ == kInitialized) {
881 DVLOG(3) << "DecodeBufferInitial(): running one-time initialization"; 893 DVLOG(3) << "DecodeBufferInitial(): running initialization";
882 // Success! Setup our parameters. 894 // Success! Setup our parameters.
883 CHECK_EQ(format.fmt.pix_mp.num_planes, 2); 895 if (!CreateBuffersForFormat(format))
884 frame_buffer_size_.SetSize(
885 format.fmt.pix_mp.width, format.fmt.pix_mp.height);
886 mfc_output_buffer_size_[0] = format.fmt.pix_mp.plane_fmt[0].sizeimage;
887 mfc_output_buffer_size_[1] = format.fmt.pix_mp.plane_fmt[1].sizeimage;
888 mfc_output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat;
889 DCHECK_EQ(mfc_output_buffer_pixelformat_, V4L2_PIX_FMT_NV12MT_16X16);
890
891 // Create our other buffers.
892 if (!CreateMfcOutputBuffers() || !CreateGscInputBuffers() ||
893 !CreateGscOutputBuffers())
894 return false; 896 return false;
895 897
896 // MFC expects to process the initial buffer once during stream init to 898 // MFC expects to process the initial buffer once during stream init to
897 // configure stream parameters, but will not consume the steam data on that 899 // configure stream parameters, but will not consume the steam data on that
898 // iteration. Subsequent iterations (including after reset) do not require 900 // iteration. Subsequent iterations (including after reset) do not require
899 // the stream init step. 901 // the stream init step.
900 *endpos = 0; 902 *endpos = 0;
901 } else { 903 } else {
902 *endpos = size; 904 *endpos = size;
903 } 905 }
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
1057 1059
1058 // Take ownership of the EGLImage and fd. 1060 // Take ownership of the EGLImage and fd.
1059 buffer.egl_image = EGL_NO_IMAGE_KHR; 1061 buffer.egl_image = EGL_NO_IMAGE_KHR;
1060 buffer.egl_image_fd = -1; 1062 buffer.egl_image_fd = -1;
1061 // And add this buffer to the free list. 1063 // And add this buffer to the free list.
1062 gsc_free_output_buffers_.push_back(i); 1064 gsc_free_output_buffers_.push_back(i);
1063 } 1065 }
1064 1066
1065 // We got buffers! Kick the GSC. 1067 // We got buffers! Kick the GSC.
1066 EnqueueGsc(); 1068 EnqueueGsc();
1069
1070 if (decoder_state_ == kChangingResolution)
1071 ResumeAfterResolutionChangeTask();
1067 } 1072 }
1068 1073
1069 void ExynosVideoDecodeAccelerator::ServiceDeviceTask() { 1074 void ExynosVideoDecodeAccelerator::ServiceDeviceTask(bool event_pending) {
1070 DVLOG(3) << "ServiceDeviceTask()"; 1075 DVLOG(3) << "ServiceDeviceTask()";
1071 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1076 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1072 DCHECK_NE(decoder_state_, kUninitialized); 1077 DCHECK_NE(decoder_state_, kUninitialized);
1073 DCHECK_NE(decoder_state_, kInitialized); 1078 DCHECK_NE(decoder_state_, kInitialized);
1074 DCHECK_NE(decoder_state_, kAfterReset); 1079 DCHECK_NE(decoder_state_, kAfterReset);
1075 TRACE_EVENT0("Video Decoder", "EVDA::ServiceDeviceTask"); 1080 TRACE_EVENT0("Video Decoder", "EVDA::ServiceDeviceTask");
1076 1081
1077 if (decoder_state_ == kResetting) { 1082 if (decoder_state_ == kResetting) {
1078 DVLOG(2) << "ServiceDeviceTask(): early out: kResetting state"; 1083 DVLOG(2) << "ServiceDeviceTask(): early out: kResetting state";
1079 return; 1084 return;
1080 } else if (decoder_state_ == kError) { 1085 } else if (decoder_state_ == kError) {
1081 DVLOG(2) << "ServiceDeviceTask(): early out: kError state"; 1086 DVLOG(2) << "ServiceDeviceTask(): early out: kError state";
1082 return; 1087 return;
1088 } else if (decoder_state_ == kChangingResolution) {
1089 DVLOG(2) << "ServiceDeviceTask(): early out: kChangingResolution state";
1090 return;
1083 } 1091 }
1084 1092
1093 if (event_pending)
1094 DequeueEvents();
1085 DequeueMfc(); 1095 DequeueMfc();
1086 DequeueGsc(); 1096 DequeueGsc();
1087 EnqueueMfc(); 1097 EnqueueMfc();
1088 EnqueueGsc(); 1098 EnqueueGsc();
1089 1099
1090 // Clear the interrupt fd. 1100 // Clear the interrupt fd.
1091 if (!ClearDevicePollInterrupt()) 1101 if (!ClearDevicePollInterrupt())
1092 return; 1102 return;
1093 1103
1094 unsigned int poll_fds = 0; 1104 unsigned int poll_fds = 0;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1126 << mfc_output_gsc_input_queue_.size() << " => GSC[" 1136 << mfc_output_gsc_input_queue_.size() << " => GSC["
1127 << gsc_free_input_buffers_.size() << "+" 1137 << gsc_free_input_buffers_.size() << "+"
1128 << gsc_input_buffer_queued_count_ << "/" 1138 << gsc_input_buffer_queued_count_ << "/"
1129 << gsc_input_buffer_map_.size() << "->" 1139 << gsc_input_buffer_map_.size() << "->"
1130 << gsc_free_output_buffers_.size() << "+" 1140 << gsc_free_output_buffers_.size() << "+"
1131 << gsc_output_buffer_queued_count_ << "/" 1141 << gsc_output_buffer_queued_count_ << "/"
1132 << gsc_output_buffer_map_.size() << "] => VDA[" 1142 << gsc_output_buffer_map_.size() << "] => VDA["
1133 << decoder_frames_at_client_ << "]"; 1143 << decoder_frames_at_client_ << "]";
1134 1144
1135 ScheduleDecodeBufferTaskIfNeeded(); 1145 ScheduleDecodeBufferTaskIfNeeded();
1146 StartResolutionChangeIfNeeded();
1136 } 1147 }
1137 1148
1138 void ExynosVideoDecodeAccelerator::EnqueueMfc() { 1149 void ExynosVideoDecodeAccelerator::EnqueueMfc() {
1139 DVLOG(3) << "EnqueueMfc()"; 1150 DVLOG(3) << "EnqueueMfc()";
1140 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1151 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1141 DCHECK_NE(decoder_state_, kUninitialized); 1152 DCHECK_NE(decoder_state_, kUninitialized);
1142 TRACE_EVENT0("Video Decoder", "EVDA::EnqueueMfc"); 1153 TRACE_EVENT0("Video Decoder", "EVDA::EnqueueMfc");
1143 1154
1144 // Drain the pipe of completed decode buffers. 1155 // Drain the pipe of completed decode buffers.
1145 const int old_mfc_inputs_queued = mfc_input_buffer_queued_count_; 1156 const int old_mfc_inputs_queued = mfc_input_buffer_queued_count_;
(...skipping 27 matching lines...) Expand all
1173 return; 1184 return;
1174 // Start VIDIOC_STREAMON if we haven't yet. 1185 // Start VIDIOC_STREAMON if we haven't yet.
1175 if (!mfc_output_streamon_) { 1186 if (!mfc_output_streamon_) {
1176 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1187 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1177 IOCTL_OR_ERROR_RETURN(mfc_fd_, VIDIOC_STREAMON, &type); 1188 IOCTL_OR_ERROR_RETURN(mfc_fd_, VIDIOC_STREAMON, &type);
1178 mfc_output_streamon_ = true; 1189 mfc_output_streamon_ = true;
1179 } 1190 }
1180 } 1191 }
1181 } 1192 }
1182 1193
1194 void ExynosVideoDecodeAccelerator::DequeueEvents() {
1195 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1196 DCHECK_EQ(decoder_state_, kDecoding);
1197 DVLOG(3) << "DequeueEvents()";
1198
1199 struct v4l2_event ev;
1200 memset(&ev, 0, sizeof(ev));
1201
1202 while (ioctl(mfc_fd_, VIDIOC_DQEVENT, &ev) == 0) {
1203 if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) {
1204 DVLOG(3) << "DequeueEvents(): got resolution change event.";
1205 DCHECK(!resolution_change_pending_);
1206 resolution_change_pending_ = true;
1207 }
Ami GONE FROM CHROMIUM 2013/08/09 16:55:41 else DLOG(FATAL) since this is the only type we su
Pawel Osciak 2013/08/11 12:40:13 Done.
1208 }
1209 }
1210
1183 void ExynosVideoDecodeAccelerator::DequeueMfc() { 1211 void ExynosVideoDecodeAccelerator::DequeueMfc() {
1184 DVLOG(3) << "DequeueMfc()"; 1212 DVLOG(3) << "DequeueMfc()";
1185 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1213 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1186 DCHECK_NE(decoder_state_, kUninitialized); 1214 DCHECK_NE(decoder_state_, kUninitialized);
1187 TRACE_EVENT0("Video Decoder", "EVDA::DequeueMfc"); 1215 TRACE_EVENT0("Video Decoder", "EVDA::DequeueMfc");
1188 1216
1189 // Dequeue completed MFC input (VIDEO_OUTPUT) buffers, and recycle to the free 1217 // Dequeue completed MFC input (VIDEO_OUTPUT) buffers, and recycle to the free
1190 // list. 1218 // list.
1191 struct v4l2_buffer dqbuf; 1219 struct v4l2_buffer dqbuf;
1192 struct v4l2_plane planes[2]; 1220 struct v4l2_plane planes[2];
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
1531 << picture_buffer_id; 1559 << picture_buffer_id;
1532 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1560 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1533 TRACE_EVENT0("Video Decoder", "EVDA::ReusePictureBufferTask"); 1561 TRACE_EVENT0("Video Decoder", "EVDA::ReusePictureBufferTask");
1534 1562
1535 // We run ReusePictureBufferTask even if we're in kResetting. 1563 // We run ReusePictureBufferTask even if we're in kResetting.
1536 if (decoder_state_ == kError) { 1564 if (decoder_state_ == kError) {
1537 DVLOG(2) << "ReusePictureBufferTask(): early out: kError state"; 1565 DVLOG(2) << "ReusePictureBufferTask(): early out: kError state";
1538 return; 1566 return;
1539 } 1567 }
1540 1568
1569 if (decoder_state_ == kChangingResolution) {
1570 DVLOG(2) << "ReusePictureBufferTask(): early out: kChangingResolution";
1571 return;
1572 }
1573
1541 size_t index; 1574 size_t index;
1542 for (index = 0; index < gsc_output_buffer_map_.size(); ++index) 1575 for (index = 0; index < gsc_output_buffer_map_.size(); ++index)
1543 if (gsc_output_buffer_map_[index].picture_id == picture_buffer_id) 1576 if (gsc_output_buffer_map_[index].picture_id == picture_buffer_id)
1544 break; 1577 break;
1545 1578
1546 if (index >= gsc_output_buffer_map_.size()) { 1579 if (index >= gsc_output_buffer_map_.size()) {
1547 DLOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not found"; 1580 DLOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not found";
1548 NOTIFY_ERROR(INVALID_ARGUMENT); 1581 NOTIFY_ERROR(INVALID_ARGUMENT);
1549 return; 1582 return;
1550 } 1583 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1612 decoder_delay_bitstream_buffer_id_) 1645 decoder_delay_bitstream_buffer_id_)
1613 return; 1646 return;
1614 } 1647 }
1615 if (decoder_current_input_buffer_ != -1) 1648 if (decoder_current_input_buffer_ != -1)
1616 return; 1649 return;
1617 if ((mfc_input_ready_queue_.size() + 1650 if ((mfc_input_ready_queue_.size() +
1618 mfc_input_buffer_queued_count_ + mfc_output_gsc_input_queue_.size() + 1651 mfc_input_buffer_queued_count_ + mfc_output_gsc_input_queue_.size() +
1619 gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ ) != 0) 1652 gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ ) != 0)
1620 return; 1653 return;
1621 1654
1655 // TODO(posciak): crbug.com/270039. MFC requires a streamoff-streamon
1656 // sequence after flush to continue, even if we are not resetting. This would
1657 // make sense, because we don't really want to resume from a non-resume point
1658 // (e.g. not from an IDR) if we are flushed.
1659 // MSE player however triggers a Flush() on chunk end, but never Reset(). One
Ami GONE FROM CHROMIUM 2013/08/09 16:55:41 Can you substantiate this assertion: "MSE player h
Pawel Osciak 2013/08/10 05:40:29 I had time to look at this only briefly. EVDA was
1660 // could argue either way, or even say that Flush() is not needed/harmful when
1661 // transitioning to next chunk.
1662 // For now, do the streamoff-streamon cycle to satisfy MFC and not freeze when
1663 // doing MSE. This should be harmless otherwise.
1664 if (!StopDevicePoll(false))
1665 return;
1666
1667 if (!StartDevicePoll())
1668 return;
1669
1622 decoder_delay_bitstream_buffer_id_ = -1; 1670 decoder_delay_bitstream_buffer_id_ = -1;
1623 decoder_flushing_ = false; 1671 decoder_flushing_ = false;
1624 DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush"; 1672 DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush";
1625 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( 1673 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
1626 &Client::NotifyFlushDone, client_)); 1674 &Client::NotifyFlushDone, client_));
1627 1675
1628 // While we were flushing, we early-outed DecodeBufferTask()s. 1676 // While we were flushing, we early-outed DecodeBufferTask()s.
1629 ScheduleDecodeBufferTaskIfNeeded(); 1677 ScheduleDecodeBufferTaskIfNeeded();
1630 } 1678 }
1631 1679
1632 void ExynosVideoDecodeAccelerator::ResetTask() { 1680 void ExynosVideoDecodeAccelerator::ResetTask() {
1633 DVLOG(3) << "ResetTask()"; 1681 DVLOG(3) << "ResetTask()";
1634 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1682 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1635 TRACE_EVENT0("Video Decoder", "EVDA::ResetTask"); 1683 TRACE_EVENT0("Video Decoder", "EVDA::ResetTask");
1636 1684
1637 if (decoder_state_ == kError) { 1685 if (decoder_state_ == kError) {
1638 DVLOG(2) << "ResetTask(): early out: kError state"; 1686 DVLOG(2) << "ResetTask(): early out: kError state";
1639 return; 1687 return;
1640 } 1688 }
1641 1689
1642 // We stop streaming, but we _don't_ destroy our buffers. 1690 // If we are in the middle of switching resolutions, postpone reset until
1643 if (!StopDevicePoll()) 1691 // it's done. We don't have to worry about timing of this wrt to decoding,
1692 // before the MFC input pipe is already stopped if we are changing resolution.
Ami GONE FROM CHROMIUM 2013/08/09 16:55:41 s/before/because/ ?
Pawel Osciak 2013/08/11 12:40:13 Done.
1693 // We will come back here after we are done with the resolution change.
Ami GONE FROM CHROMIUM 2013/08/09 16:55:41 Did you mean to return; from the if block?
Pawel Osciak 2013/08/11 12:40:13 Yes, it was there, as braces prove, and I have no
1694 DCHECK(!reset_pending_);
1695 if (resolution_change_pending_ || decoder_state_ == kChangingResolution) {
1696 reset_pending_ = true;
1697 }
1698
1699 // We stop streaming and clear buffer tracking info (not preserving
1700 // MFC inputs).
1701 // StopDevicePoll() unconditionally does _not_ destroy buffers, however.
1702 if (!StopDevicePoll(false))
1644 return; 1703 return;
1645 1704
1705 DequeueEvents();
1706
1707 resolution_change_pending_ = false;
1646 decoder_current_bitstream_buffer_.reset(); 1708 decoder_current_bitstream_buffer_.reset();
1647 decoder_input_queue_.clear(); 1709 decoder_input_queue_.clear();
1648 1710
1649 decoder_current_input_buffer_ = -1; 1711 decoder_current_input_buffer_ = -1;
1650 1712
1651 // If we were flushing, we'll never return any more BitstreamBuffers or 1713 // If we were flushing, we'll never return any more BitstreamBuffers or
1652 // PictureBuffers; they have all been dropped and returned by now. 1714 // PictureBuffers; they have all been dropped and returned by now.
1653 NotifyFlushDoneIfNeeded(); 1715 NotifyFlushDoneIfNeeded();
1654 1716
1655 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening 1717 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1687 ScheduleDecodeBufferTaskIfNeeded(); 1749 ScheduleDecodeBufferTaskIfNeeded();
1688 } 1750 }
1689 1751
1690 void ExynosVideoDecodeAccelerator::DestroyTask() { 1752 void ExynosVideoDecodeAccelerator::DestroyTask() {
1691 DVLOG(3) << "DestroyTask()"; 1753 DVLOG(3) << "DestroyTask()";
1692 TRACE_EVENT0("Video Decoder", "EVDA::DestroyTask"); 1754 TRACE_EVENT0("Video Decoder", "EVDA::DestroyTask");
1693 1755
1694 // DestroyTask() should run regardless of decoder_state_. 1756 // DestroyTask() should run regardless of decoder_state_.
1695 1757
1696 // Stop streaming and the device_poll_thread_. 1758 // Stop streaming and the device_poll_thread_.
1697 StopDevicePoll(); 1759 StopDevicePoll(false);
1698 1760
1699 decoder_current_bitstream_buffer_.reset(); 1761 decoder_current_bitstream_buffer_.reset();
1700 decoder_current_input_buffer_ = -1; 1762 decoder_current_input_buffer_ = -1;
1701 decoder_decode_buffer_tasks_scheduled_ = 0; 1763 decoder_decode_buffer_tasks_scheduled_ = 0;
1702 decoder_frames_at_client_ = 0; 1764 decoder_frames_at_client_ = 0;
1703 decoder_input_queue_.clear(); 1765 decoder_input_queue_.clear();
1704 decoder_flushing_ = false; 1766 decoder_flushing_ = false;
1705 1767
1706 // Set our state to kError. Just in case. 1768 // Set our state to kError. Just in case.
1707 decoder_state_ = kError; 1769 decoder_state_ = kError;
(...skipping 11 matching lines...) Expand all
1719 return false; 1781 return false;
1720 } 1782 }
1721 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 1783 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
1722 &ExynosVideoDecodeAccelerator::DevicePollTask, 1784 &ExynosVideoDecodeAccelerator::DevicePollTask,
1723 base::Unretained(this), 1785 base::Unretained(this),
1724 0)); 1786 0));
1725 1787
1726 return true; 1788 return true;
1727 } 1789 }
1728 1790
1729 bool ExynosVideoDecodeAccelerator::StopDevicePoll() { 1791 bool ExynosVideoDecodeAccelerator::StopDevicePoll(bool keep_mfc_input) {
1730 DVLOG(3) << "StopDevicePoll()"; 1792 DVLOG(3) << "StopDevicePoll()";
1731 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1793 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1732 1794
1733 // Signal the DevicePollTask() to stop, and stop the device poll thread. 1795 // Signal the DevicePollTask() to stop, and stop the device poll thread.
1734 if (!SetDevicePollInterrupt()) 1796 if (!SetDevicePollInterrupt())
1735 return false; 1797 return false;
1736 device_poll_thread_.Stop(); 1798 device_poll_thread_.Stop();
1737 // Clear the interrupt now, to be sure. 1799 // Clear the interrupt now, to be sure.
1738 if (!ClearDevicePollInterrupt()) 1800 if (!ClearDevicePollInterrupt())
1739 return false; 1801 return false;
1740 1802
1741 // Stop streaming. 1803 // Stop streaming.
1742 if (mfc_input_streamon_) { 1804 if (!keep_mfc_input) {
1743 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1805 if (mfc_input_streamon_) {
1744 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type); 1806 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1807 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type);
1808 }
1809 mfc_input_streamon_ = false;
1745 } 1810 }
1746 mfc_input_streamon_ = false;
1747 if (mfc_output_streamon_) { 1811 if (mfc_output_streamon_) {
1748 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1812 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1749 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type); 1813 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type);
1750 } 1814 }
1751 mfc_output_streamon_ = false; 1815 mfc_output_streamon_ = false;
1752 if (gsc_input_streamon_) { 1816 if (gsc_input_streamon_) {
1753 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1817 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1754 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_STREAMOFF, &type); 1818 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_STREAMOFF, &type);
1755 } 1819 }
1756 gsc_input_streamon_ = false; 1820 gsc_input_streamon_ = false;
1757 if (gsc_output_streamon_) { 1821 if (gsc_output_streamon_) {
1758 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1822 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1759 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_STREAMOFF, &type); 1823 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_STREAMOFF, &type);
1760 } 1824 }
1761 gsc_output_streamon_ = false; 1825 gsc_output_streamon_ = false;
1762 1826
1763 // Reset all our accounting info. 1827 // Reset all our accounting info.
1764 mfc_input_ready_queue_.clear(); 1828 if (!keep_mfc_input) {
1765 mfc_free_input_buffers_.clear(); 1829 mfc_input_ready_queue_.clear();
1766 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) { 1830 mfc_free_input_buffers_.clear();
1767 mfc_free_input_buffers_.push_back(i); 1831 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) {
1768 mfc_input_buffer_map_[i].at_device = false; 1832 mfc_free_input_buffers_.push_back(i);
1769 mfc_input_buffer_map_[i].bytes_used = 0; 1833 mfc_input_buffer_map_[i].at_device = false;
1770 mfc_input_buffer_map_[i].input_id = -1; 1834 mfc_input_buffer_map_[i].bytes_used = 0;
1835 mfc_input_buffer_map_[i].input_id = -1;
1836 }
1837 mfc_input_buffer_queued_count_ = 0;
1771 } 1838 }
1772 mfc_input_buffer_queued_count_ = 0;
1773 mfc_free_output_buffers_.clear(); 1839 mfc_free_output_buffers_.clear();
1774 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) { 1840 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) {
1775 mfc_free_output_buffers_.push_back(i); 1841 mfc_free_output_buffers_.push_back(i);
1776 mfc_output_buffer_map_[i].at_device = false; 1842 mfc_output_buffer_map_[i].at_device = false;
1777 mfc_output_buffer_map_[i].input_id = -1; 1843 mfc_output_buffer_map_[i].input_id = -1;
1778 } 1844 }
1779 mfc_output_buffer_queued_count_ = 0; 1845 mfc_output_buffer_queued_count_ = 0;
1780 mfc_output_gsc_input_queue_.clear(); 1846 mfc_output_gsc_input_queue_.clear();
1781 gsc_free_input_buffers_.clear(); 1847 gsc_free_input_buffers_.clear();
1782 for (size_t i = 0; i < gsc_input_buffer_map_.size(); ++i) { 1848 for (size_t i = 0; i < gsc_input_buffer_map_.size(); ++i) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1823 return true; 1889 return true;
1824 } else { 1890 } else {
1825 DPLOG(ERROR) << "ClearDevicePollInterrupt(): read() failed"; 1891 DPLOG(ERROR) << "ClearDevicePollInterrupt(): read() failed";
1826 NOTIFY_ERROR(PLATFORM_FAILURE); 1892 NOTIFY_ERROR(PLATFORM_FAILURE);
1827 return false; 1893 return false;
1828 } 1894 }
1829 } 1895 }
1830 return true; 1896 return true;
1831 } 1897 }
1832 1898
1899 void ExynosVideoDecodeAccelerator::StartResolutionChangeIfNeeded() {
1900 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1901 DCHECK_EQ(decoder_state_, kDecoding);
1902
1903 if (!resolution_change_pending_)
1904 return;
1905
1906 if (!mfc_output_gsc_input_queue_.empty() ||
1907 gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ > 0) {
1908 DVLOG(3) << "StartResolutionChangeIfNeeded(): waiting for GSC to finish.";
1909 return;
1910 }
1911
1912 DVLOG(3) << "No more work for GSC, initiate resolution change";
1913
1914 // Keep MFC input queue.
1915 if (!StopDevicePoll(true))
1916 return;
1917
1918 decoder_state_ = kChangingResolution;
1919 DCHECK(resolution_change_pending_);
1920 resolution_change_pending_ = false;
1921
1922 // Post a task to clean up buffers on child thread. This will also ensure
1923 // that we won't accept ReusePictureBuffer() anymore after that.
1924 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
1925 &ExynosVideoDecodeAccelerator::ResChangeDestroyBuffersOnChildThread,
1926 weak_this_));
1927 }
1928
1929 void ExynosVideoDecodeAccelerator::ResChangeDestroyBuffersOnChildThread() {
1930 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
1931 DVLOG(3) << "ResolutionChangeDestroyBuffers()";
1932
1933 DestroyGscInputBuffers();
1934 DestroyGscOutputBuffers();
1935 DestroyMfcOutputBuffers();
1936
1937 // Finish resolution change on decoder thread.
1938 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
1939 &ExynosVideoDecodeAccelerator::FinishResolutionChangeTask,
1940 base::Unretained(this)));
1941 }
1942
1943 void ExynosVideoDecodeAccelerator::FinishResolutionChangeTask() {
1944 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1945 DVLOG(3) << "FinishResolutionChangeTask()";
1946
1947 if (decoder_state_ == kError) {
1948 DVLOG(2) << "FinishResolutionChangeTask(): early out: kError state";
1949 return;
1950 }
1951
1952 struct v4l2_format format;
1953 bool again;
1954 bool ret = GetFormatInfo(&format, &again);
1955 if (!ret || again) {
1956 DVLOG(3) << "Couldn't get format information after resolution change";
Ami GONE FROM CHROMIUM 2013/08/09 16:55:41 Isn't this a fatal error for the decoder? (what's
Pawel Osciak 2013/08/11 12:40:13 Yeah, good point, I should make it a platform erro
1957 return;
1958 }
1959
1960 if (!CreateBuffersForFormat(format))
1961 DVLOG(3) << "Couldn't reallocate buffers after resolution change";
Ami GONE FROM CHROMIUM 2013/08/09 16:55:41 ditto
Pawel Osciak 2013/08/11 12:40:13 Done.
1962
1963 // From here we stay in kChangingResolution and wait for
1964 // AssignPictureBuffers() before we can resume.
1965 }
1966
1967 void ExynosVideoDecodeAccelerator::ResumeAfterResolutionChangeTask() {
1968 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1969 DVLOG(3) << "ResumeAfterResolutionChangeTask()";
1970
1971 decoder_state_ = kDecoding;
1972
1973 if (reset_pending_) {
1974 reset_pending_ = false;
1975 ResetTask();
1976 return;
1977 }
1978
1979 if (!StartDevicePoll())
1980 return;
1981
1982 EnqueueMfc();
1983 // Gsc will get enqueued in AssignPictureBuffersTask().
1984 ScheduleDecodeBufferTaskIfNeeded();
1985 }
1986
1833 void ExynosVideoDecodeAccelerator::DevicePollTask(unsigned int poll_fds) { 1987 void ExynosVideoDecodeAccelerator::DevicePollTask(unsigned int poll_fds) {
1834 DVLOG(3) << "DevicePollTask()"; 1988 DVLOG(3) << "DevicePollTask()";
1835 DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current()); 1989 DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current());
1836 TRACE_EVENT0("Video Decoder", "EVDA::DevicePollTask"); 1990 TRACE_EVENT0("Video Decoder", "EVDA::DevicePollTask");
1837 1991
1838 // This routine just polls the set of device fds, and schedules a 1992 // This routine just polls the set of device fds, and schedules a
1839 // ServiceDeviceTask() on decoder_thread_ when processing needs to occur. 1993 // ServiceDeviceTask() on decoder_thread_ when processing needs to occur.
1840 // Other threads may notify this task to return early by writing to 1994 // Other threads may notify this task to return early by writing to
1841 // device_poll_interrupt_fd_. 1995 // device_poll_interrupt_fd_.
1842 struct pollfd pollfds[3]; 1996 struct pollfd pollfds[3];
1843 nfds_t nfds; 1997 nfds_t nfds;
1998 int mfc_pollfd = -1;
1844 1999
1845 // Add device_poll_interrupt_fd_; 2000 // Add device_poll_interrupt_fd_;
1846 pollfds[0].fd = device_poll_interrupt_fd_; 2001 pollfds[0].fd = device_poll_interrupt_fd_;
1847 pollfds[0].events = POLLIN | POLLERR; 2002 pollfds[0].events = POLLIN | POLLERR;
1848 nfds = 1; 2003 nfds = 1;
1849 2004
1850 if (poll_fds & kPollMfc) { 2005 if (poll_fds & kPollMfc) {
1851 DVLOG(3) << "DevicePollTask(): adding MFC to poll() set"; 2006 DVLOG(3) << "DevicePollTask(): adding MFC to poll() set";
1852 pollfds[nfds].fd = mfc_fd_; 2007 pollfds[nfds].fd = mfc_fd_;
1853 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR; 2008 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR | POLLPRI;
2009 mfc_pollfd = nfds;
1854 nfds++; 2010 nfds++;
1855 } 2011 }
1856 // Add GSC fd, if we should poll on it. 2012 // Add GSC fd, if we should poll on it.
1857 // GSC has to wait until both input and output buffers are queued. 2013 // GSC has to wait until both input and output buffers are queued.
1858 if (poll_fds & kPollGsc) { 2014 if (poll_fds & kPollGsc) {
1859 DVLOG(3) << "DevicePollTask(): adding GSC to poll() set"; 2015 DVLOG(3) << "DevicePollTask(): adding GSC to poll() set";
1860 pollfds[nfds].fd = gsc_fd_; 2016 pollfds[nfds].fd = gsc_fd_;
1861 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR; 2017 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR;
1862 nfds++; 2018 nfds++;
1863 } 2019 }
1864 2020
1865 // Poll it! 2021 // Poll it!
1866 if (HANDLE_EINTR(poll(pollfds, nfds, -1)) == -1) { 2022 if (HANDLE_EINTR(poll(pollfds, nfds, -1)) == -1) {
1867 DPLOG(ERROR) << "DevicePollTask(): poll() failed"; 2023 DPLOG(ERROR) << "DevicePollTask(): poll() failed";
1868 NOTIFY_ERROR(PLATFORM_FAILURE); 2024 NOTIFY_ERROR(PLATFORM_FAILURE);
1869 return; 2025 return;
1870 } 2026 }
1871 2027
2028 bool event_pending = (mfc_pollfd != -1 &&
Ami GONE FROM CHROMIUM 2013/08/09 16:55:41 Is it important to do this, vs. unconditionally al
Pawel Osciak 2013/08/10 05:40:29 Always better not to spam ioctls every frame, and
2029 pollfds[mfc_pollfd].revents & POLLPRI);
2030
1872 // All processing should happen on ServiceDeviceTask(), since we shouldn't 2031 // All processing should happen on ServiceDeviceTask(), since we shouldn't
1873 // touch decoder state from this thread. 2032 // touch decoder state from this thread.
1874 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 2033 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
1875 &ExynosVideoDecodeAccelerator::ServiceDeviceTask, 2034 &ExynosVideoDecodeAccelerator::ServiceDeviceTask,
1876 base::Unretained(this))); 2035 base::Unretained(this), event_pending));
1877 } 2036 }
1878 2037
1879 void ExynosVideoDecodeAccelerator::NotifyError(Error error) { 2038 void ExynosVideoDecodeAccelerator::NotifyError(Error error) {
1880 DVLOG(2) << "NotifyError()"; 2039 DVLOG(2) << "NotifyError()";
1881 2040
1882 if (!child_message_loop_proxy_->BelongsToCurrentThread()) { 2041 if (!child_message_loop_proxy_->BelongsToCurrentThread()) {
1883 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( 2042 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
1884 &ExynosVideoDecodeAccelerator::NotifyError, weak_this_, error)); 2043 &ExynosVideoDecodeAccelerator::NotifyError, weak_this_, error));
1885 return; 2044 return;
1886 } 2045 }
(...skipping 12 matching lines...) Expand all
1899 if (decoder_thread_.message_loop() != NULL && 2058 if (decoder_thread_.message_loop() != NULL &&
1900 decoder_thread_.message_loop() != base::MessageLoop::current()) { 2059 decoder_thread_.message_loop() != base::MessageLoop::current()) {
1901 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( 2060 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
1902 &ExynosVideoDecodeAccelerator::SetDecoderState, 2061 &ExynosVideoDecodeAccelerator::SetDecoderState,
1903 base::Unretained(this), state)); 2062 base::Unretained(this), state));
1904 } else { 2063 } else {
1905 decoder_state_ = state; 2064 decoder_state_ = state;
1906 } 2065 }
1907 } 2066 }
1908 2067
2068 bool ExynosVideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format,
2069 bool* again) {
2070 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
2071
2072 *again = false;
2073 memset(format, 0, sizeof(*format));
2074 format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2075 if (HANDLE_EINTR(ioctl(mfc_fd_, VIDIOC_G_FMT, format)) != 0) {
2076 if (errno == EINVAL) {
2077 // EINVAL means we haven't seen sufficient stream to decode the format.
2078 *again = true;
2079 return true;
2080 } else {
2081 DPLOG(ERROR) << "DecodeBufferInitial(): ioctl() failed: VIDIOC_G_FMT";
2082 NOTIFY_ERROR(PLATFORM_FAILURE);
2083 return false;
2084 }
2085 }
2086
2087 return true;
2088 }
2089
2090 bool ExynosVideoDecodeAccelerator::CreateBuffersForFormat(
2091 const struct v4l2_format& format) {
2092 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
2093 CHECK_EQ(format.fmt.pix_mp.num_planes, 2);
2094 frame_buffer_size_.SetSize(
2095 format.fmt.pix_mp.width, format.fmt.pix_mp.height);
2096 mfc_output_buffer_size_[0] = format.fmt.pix_mp.plane_fmt[0].sizeimage;
2097 mfc_output_buffer_size_[1] = format.fmt.pix_mp.plane_fmt[1].sizeimage;
2098 mfc_output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat;
2099 DCHECK_EQ(mfc_output_buffer_pixelformat_, V4L2_PIX_FMT_NV12MT_16X16);
2100 DVLOG(3) << "CreateBuffersForFormat(): new resolution: "
2101 << frame_buffer_size_.ToString();
2102
2103 if (!CreateMfcOutputBuffers() || !CreateGscInputBuffers() ||
2104 !CreateGscOutputBuffers())
2105 return false;
2106
2107 return true;
2108 }
2109
1909 bool ExynosVideoDecodeAccelerator::CreateMfcInputBuffers() { 2110 bool ExynosVideoDecodeAccelerator::CreateMfcInputBuffers() {
1910 DVLOG(3) << "CreateMfcInputBuffers()"; 2111 DVLOG(3) << "CreateMfcInputBuffers()";
1911 // We always run this as we prepare to initialize. 2112 // We always run this as we prepare to initialize.
1912 DCHECK_EQ(decoder_state_, kUninitialized); 2113 DCHECK_EQ(decoder_state_, kUninitialized);
1913 DCHECK(!mfc_input_streamon_); 2114 DCHECK(!mfc_input_streamon_);
1914 DCHECK(mfc_input_buffer_map_.empty()); 2115 DCHECK(mfc_input_buffer_map_.empty());
1915 2116
1916 __u32 pixelformat = 0; 2117 __u32 pixelformat = 0;
1917 if (video_profile_ >= media::H264PROFILE_MIN && 2118 if (video_profile_ >= media::H264PROFILE_MIN &&
1918 video_profile_ <= media::H264PROFILE_MAX) { 2119 video_profile_ <= media::H264PROFILE_MAX) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1962 } 2163 }
1963 mfc_input_buffer_map_[i].address = address; 2164 mfc_input_buffer_map_[i].address = address;
1964 mfc_input_buffer_map_[i].length = buffer.m.planes[0].length; 2165 mfc_input_buffer_map_[i].length = buffer.m.planes[0].length;
1965 } 2166 }
1966 2167
1967 return true; 2168 return true;
1968 } 2169 }
1969 2170
1970 bool ExynosVideoDecodeAccelerator::CreateMfcOutputBuffers() { 2171 bool ExynosVideoDecodeAccelerator::CreateMfcOutputBuffers() {
1971 DVLOG(3) << "CreateMfcOutputBuffers()"; 2172 DVLOG(3) << "CreateMfcOutputBuffers()";
1972 DCHECK_EQ(decoder_state_, kInitialized); 2173 DCHECK(decoder_state_ == kInitialized ||
2174 decoder_state_ == kChangingResolution);
1973 DCHECK(!mfc_output_streamon_); 2175 DCHECK(!mfc_output_streamon_);
1974 DCHECK(mfc_output_buffer_map_.empty()); 2176 DCHECK(mfc_output_buffer_map_.empty());
1975 2177
1976 // Number of MFC output buffers we need. 2178 // Number of MFC output buffers we need.
1977 struct v4l2_control ctrl; 2179 struct v4l2_control ctrl;
1978 memset(&ctrl, 0, sizeof(ctrl)); 2180 memset(&ctrl, 0, sizeof(ctrl));
1979 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; 2181 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
1980 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_G_CTRL, &ctrl); 2182 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_G_CTRL, &ctrl);
1981 mfc_output_dpb_size_ = ctrl.value; 2183 mfc_output_dpb_size_ = ctrl.value;
1982 2184
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2019 mfc_output_buffer_map_[i].address[j] = address; 2221 mfc_output_buffer_map_[i].address[j] = address;
2020 mfc_output_buffer_map_[i].length[j] = buffer.m.planes[j].length; 2222 mfc_output_buffer_map_[i].length[j] = buffer.m.planes[j].length;
2021 } 2223 }
2022 } 2224 }
2023 2225
2024 return true; 2226 return true;
2025 } 2227 }
2026 2228
2027 bool ExynosVideoDecodeAccelerator::CreateGscInputBuffers() { 2229 bool ExynosVideoDecodeAccelerator::CreateGscInputBuffers() {
2028 DVLOG(3) << "CreateGscInputBuffers()"; 2230 DVLOG(3) << "CreateGscInputBuffers()";
2029 DCHECK_EQ(decoder_state_, kInitialized); 2231 DCHECK(decoder_state_ == kInitialized ||
2232 decoder_state_ == kChangingResolution);
2030 DCHECK(!gsc_input_streamon_); 2233 DCHECK(!gsc_input_streamon_);
2031 DCHECK(gsc_input_buffer_map_.empty()); 2234 DCHECK(gsc_input_buffer_map_.empty());
2032 2235
2033 struct v4l2_format format; 2236 struct v4l2_format format;
2034 memset(&format, 0, sizeof(format)); 2237 memset(&format, 0, sizeof(format));
2035 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 2238 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2036 format.fmt.pix_mp.width = frame_buffer_size_.width(); 2239 format.fmt.pix_mp.width = frame_buffer_size_.width();
2037 format.fmt.pix_mp.height = frame_buffer_size_.height(); 2240 format.fmt.pix_mp.height = frame_buffer_size_.height();
2038 format.fmt.pix_mp.pixelformat = mfc_output_buffer_pixelformat_; 2241 format.fmt.pix_mp.pixelformat = mfc_output_buffer_pixelformat_;
2039 format.fmt.pix_mp.plane_fmt[0].sizeimage = mfc_output_buffer_size_[0]; 2242 format.fmt.pix_mp.plane_fmt[0].sizeimage = mfc_output_buffer_size_[0];
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2082 for (size_t i = 0; i < gsc_input_buffer_map_.size(); ++i) { 2285 for (size_t i = 0; i < gsc_input_buffer_map_.size(); ++i) {
2083 gsc_free_input_buffers_.push_back(i); 2286 gsc_free_input_buffers_.push_back(i);
2084 gsc_input_buffer_map_[i].mfc_output = -1; 2287 gsc_input_buffer_map_[i].mfc_output = -1;
2085 } 2288 }
2086 2289
2087 return true; 2290 return true;
2088 } 2291 }
2089 2292
2090 bool ExynosVideoDecodeAccelerator::CreateGscOutputBuffers() { 2293 bool ExynosVideoDecodeAccelerator::CreateGscOutputBuffers() {
2091 DVLOG(3) << "CreateGscOutputBuffers()"; 2294 DVLOG(3) << "CreateGscOutputBuffers()";
2092 DCHECK_EQ(decoder_state_, kInitialized); 2295 DCHECK(decoder_state_ == kInitialized ||
2296 decoder_state_ == kChangingResolution);
2093 DCHECK(!gsc_output_streamon_); 2297 DCHECK(!gsc_output_streamon_);
2094 DCHECK(gsc_output_buffer_map_.empty()); 2298 DCHECK(gsc_output_buffer_map_.empty());
2095 2299
2096 // GSC outputs into the EGLImages we create from the textures we are 2300 // GSC outputs into the EGLImages we create from the textures we are
2097 // assigned. Assume RGBA8888 format. 2301 // assigned. Assume RGBA8888 format.
2098 struct v4l2_format format; 2302 struct v4l2_format format;
2099 memset(&format, 0, sizeof(format)); 2303 memset(&format, 0, sizeof(format));
2100 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 2304 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2101 format.fmt.pix_mp.width = frame_buffer_size_.width(); 2305 format.fmt.pix_mp.width = frame_buffer_size_.width();
2102 format.fmt.pix_mp.height = frame_buffer_size_.height(); 2306 format.fmt.pix_mp.height = frame_buffer_size_.height();
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
2209 2413
2210 size_t i = 0; 2414 size_t i = 0;
2211 do { 2415 do {
2212 GscOutputRecord& output_record = gsc_output_buffer_map_[i]; 2416 GscOutputRecord& output_record = gsc_output_buffer_map_[i];
2213 if (output_record.fd != -1) 2417 if (output_record.fd != -1)
2214 HANDLE_EINTR(close(output_record.fd)); 2418 HANDLE_EINTR(close(output_record.fd));
2215 if (output_record.egl_image != EGL_NO_IMAGE_KHR) 2419 if (output_record.egl_image != EGL_NO_IMAGE_KHR)
2216 eglDestroyImageKHR(egl_display_, output_record.egl_image); 2420 eglDestroyImageKHR(egl_display_, output_record.egl_image);
2217 if (output_record.egl_sync != EGL_NO_SYNC_KHR) 2421 if (output_record.egl_sync != EGL_NO_SYNC_KHR)
2218 eglDestroySyncKHR(egl_display_, output_record.egl_sync); 2422 eglDestroySyncKHR(egl_display_, output_record.egl_sync);
2219 if (client_) 2423 if (client_) {
2424 DVLOG(1) << "DestroyGscOutputBuffers(): "
2425 << "dismissing PictureBuffer id=" << output_record.picture_id;
2220 client_->DismissPictureBuffer(output_record.picture_id); 2426 client_->DismissPictureBuffer(output_record.picture_id);
2427 }
2221 ++i; 2428 ++i;
2222 } while (i < gsc_output_buffer_map_.size()); 2429 } while (i < gsc_output_buffer_map_.size());
2223 } 2430 }
2224 2431
2225 struct v4l2_requestbuffers reqbufs; 2432 struct v4l2_requestbuffers reqbufs;
2226 memset(&reqbufs, 0, sizeof(reqbufs)); 2433 memset(&reqbufs, 0, sizeof(reqbufs));
2227 reqbufs.count = 0; 2434 reqbufs.count = 0;
2228 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 2435 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2229 reqbufs.memory = V4L2_MEMORY_DMABUF; 2436 reqbufs.memory = V4L2_MEMORY_DMABUF;
2230 if (ioctl(gsc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0) 2437 if (ioctl(gsc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0)
2231 DPLOG(ERROR) << "DestroyGscOutputBuffers(): ioctl() failed: VIDIOC_REQBUFS"; 2438 DPLOG(ERROR) << "DestroyGscOutputBuffers(): ioctl() failed: VIDIOC_REQBUFS";
2232 2439
2233 gsc_output_buffer_map_.clear(); 2440 gsc_output_buffer_map_.clear();
2234 gsc_free_output_buffers_.clear(); 2441 gsc_free_output_buffers_.clear();
2235 } 2442 }
2236 2443
2237 } // namespace content 2444 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698