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 <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 Loading... | |
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 Loading... | |
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 resolution_change_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 Loading... | |
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 to the resolution change event. | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 ResumeAfterResolutionChange(); | |
1067 } | 1072 } |
1068 | 1073 |
1069 void ExynosVideoDecodeAccelerator::ServiceDeviceTask() { | 1074 void ExynosVideoDecodeAccelerator::ServiceDeviceTask(bool mfc_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 (mfc_event_pending) | |
1094 DequeueMfcEvents(); | |
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 Loading... | |
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 Loading... | |
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::DequeueMfcEvents() { | |
1195 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | |
1196 DCHECK_EQ(decoder_state_, kDecoding); | |
1197 DVLOG(3) << "DequeueMfcEvents()"; | |
Ami GONE FROM CHROMIUM
2013/08/12 03:46:19
Is there some reason you (and your kind, who enjoy
Pawel Osciak
2013/08/12 04:07:45
I do enjoy those traces and they help a lot when d
sheu
2013/08/12 04:49:20
My fault. I just started doing it this way, and h
| |
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) << "DequeueMfcEvents(): got resolution change event."; | |
1205 DCHECK(!resolution_change_pending_); | |
1206 resolution_change_pending_ = true; | |
1207 } else { | |
1208 DLOG(FATAL) << "DequeueMfcEvents(): got an event (" << ev.type | |
1209 << ") we haven't subscribed to."; | |
1210 } | |
1211 } | |
1212 } | |
1213 | |
1183 void ExynosVideoDecodeAccelerator::DequeueMfc() { | 1214 void ExynosVideoDecodeAccelerator::DequeueMfc() { |
1184 DVLOG(3) << "DequeueMfc()"; | 1215 DVLOG(3) << "DequeueMfc()"; |
1185 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1216 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1186 DCHECK_NE(decoder_state_, kUninitialized); | 1217 DCHECK_NE(decoder_state_, kUninitialized); |
1187 TRACE_EVENT0("Video Decoder", "EVDA::DequeueMfc"); | 1218 TRACE_EVENT0("Video Decoder", "EVDA::DequeueMfc"); |
1188 | 1219 |
1189 // Dequeue completed MFC input (VIDEO_OUTPUT) buffers, and recycle to the free | 1220 // Dequeue completed MFC input (VIDEO_OUTPUT) buffers, and recycle to the free |
1190 // list. | 1221 // list. |
1191 struct v4l2_buffer dqbuf; | 1222 struct v4l2_buffer dqbuf; |
1192 struct v4l2_plane planes[2]; | 1223 struct v4l2_plane planes[2]; |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1531 << picture_buffer_id; | 1562 << picture_buffer_id; |
1532 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1563 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1533 TRACE_EVENT0("Video Decoder", "EVDA::ReusePictureBufferTask"); | 1564 TRACE_EVENT0("Video Decoder", "EVDA::ReusePictureBufferTask"); |
1534 | 1565 |
1535 // We run ReusePictureBufferTask even if we're in kResetting. | 1566 // We run ReusePictureBufferTask even if we're in kResetting. |
1536 if (decoder_state_ == kError) { | 1567 if (decoder_state_ == kError) { |
1537 DVLOG(2) << "ReusePictureBufferTask(): early out: kError state"; | 1568 DVLOG(2) << "ReusePictureBufferTask(): early out: kError state"; |
1538 return; | 1569 return; |
1539 } | 1570 } |
1540 | 1571 |
1572 if (decoder_state_ == kChangingResolution) { | |
1573 DVLOG(2) << "ReusePictureBufferTask(): early out: kChangingResolution"; | |
1574 return; | |
1575 } | |
1576 | |
1541 size_t index; | 1577 size_t index; |
1542 for (index = 0; index < gsc_output_buffer_map_.size(); ++index) | 1578 for (index = 0; index < gsc_output_buffer_map_.size(); ++index) |
1543 if (gsc_output_buffer_map_[index].picture_id == picture_buffer_id) | 1579 if (gsc_output_buffer_map_[index].picture_id == picture_buffer_id) |
1544 break; | 1580 break; |
1545 | 1581 |
1546 if (index >= gsc_output_buffer_map_.size()) { | 1582 if (index >= gsc_output_buffer_map_.size()) { |
1547 DLOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not found"; | 1583 DLOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not found"; |
1548 NOTIFY_ERROR(INVALID_ARGUMENT); | 1584 NOTIFY_ERROR(INVALID_ARGUMENT); |
1549 return; | 1585 return; |
1550 } | 1586 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1612 decoder_delay_bitstream_buffer_id_) | 1648 decoder_delay_bitstream_buffer_id_) |
1613 return; | 1649 return; |
1614 } | 1650 } |
1615 if (decoder_current_input_buffer_ != -1) | 1651 if (decoder_current_input_buffer_ != -1) |
1616 return; | 1652 return; |
1617 if ((mfc_input_ready_queue_.size() + | 1653 if ((mfc_input_ready_queue_.size() + |
1618 mfc_input_buffer_queued_count_ + mfc_output_gsc_input_queue_.size() + | 1654 mfc_input_buffer_queued_count_ + mfc_output_gsc_input_queue_.size() + |
1619 gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ ) != 0) | 1655 gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ ) != 0) |
1620 return; | 1656 return; |
1621 | 1657 |
1658 // TODO(posciak): crbug.com/270039. MFC requires a streamoff-streamon | |
1659 // sequence after flush to continue, even if we are not resetting. This would | |
1660 // make sense, because we don't really want to resume from a non-resume point | |
1661 // (e.g. not from an IDR) if we are flushed. | |
1662 // MSE player however triggers a Flush() on chunk end, but never Reset(). One | |
1663 // could argue either way, or even say that Flush() is not needed/harmful when | |
1664 // transitioning to next chunk. | |
1665 // For now, do the streamoff-streamon cycle to satisfy MFC and not freeze when | |
1666 // doing MSE. This should be harmless otherwise. | |
1667 if (!StopDevicePoll(false)) | |
1668 return; | |
1669 | |
1670 if (!StartDevicePoll()) | |
1671 return; | |
1672 | |
1622 decoder_delay_bitstream_buffer_id_ = -1; | 1673 decoder_delay_bitstream_buffer_id_ = -1; |
1623 decoder_flushing_ = false; | 1674 decoder_flushing_ = false; |
1624 DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush"; | 1675 DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush"; |
1625 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 1676 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
1626 &Client::NotifyFlushDone, client_)); | 1677 &Client::NotifyFlushDone, client_)); |
1627 | 1678 |
1628 // While we were flushing, we early-outed DecodeBufferTask()s. | 1679 // While we were flushing, we early-outed DecodeBufferTask()s. |
1629 ScheduleDecodeBufferTaskIfNeeded(); | 1680 ScheduleDecodeBufferTaskIfNeeded(); |
1630 } | 1681 } |
1631 | 1682 |
1632 void ExynosVideoDecodeAccelerator::ResetTask() { | 1683 void ExynosVideoDecodeAccelerator::ResetTask() { |
1633 DVLOG(3) << "ResetTask()"; | 1684 DVLOG(3) << "ResetTask()"; |
1634 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1685 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1635 TRACE_EVENT0("Video Decoder", "EVDA::ResetTask"); | 1686 TRACE_EVENT0("Video Decoder", "EVDA::ResetTask"); |
1636 | 1687 |
1637 if (decoder_state_ == kError) { | 1688 if (decoder_state_ == kError) { |
1638 DVLOG(2) << "ResetTask(): early out: kError state"; | 1689 DVLOG(2) << "ResetTask(): early out: kError state"; |
1639 return; | 1690 return; |
1640 } | 1691 } |
1641 | 1692 |
1642 // We stop streaming, but we _don't_ destroy our buffers. | 1693 // If we are in the middle of switching resolutions, postpone reset until |
1643 if (!StopDevicePoll()) | 1694 // it's done. We don't have to worry about timing of this wrt to decoding, |
1695 // because MFC input pipe is already stopped if we are changing resolution. | |
1696 // We will come back here after we are done with the resolution change. | |
1697 DCHECK(!resolution_change_reset_pending_); | |
1698 if (resolution_change_pending_ || decoder_state_ == kChangingResolution) { | |
1699 resolution_change_reset_pending_ = true; | |
1700 return; | |
1701 } | |
1702 | |
1703 // We stop streaming and clear buffer tracking info (not preserving | |
1704 // MFC inputs). | |
1705 // StopDevicePoll() unconditionally does _not_ destroy buffers, however. | |
1706 if (!StopDevicePoll(false)) | |
1644 return; | 1707 return; |
1645 | 1708 |
1709 DequeueMfcEvents(); | |
1710 | |
1711 resolution_change_pending_ = false; | |
1646 decoder_current_bitstream_buffer_.reset(); | 1712 decoder_current_bitstream_buffer_.reset(); |
1647 decoder_input_queue_.clear(); | 1713 decoder_input_queue_.clear(); |
1648 | 1714 |
1649 decoder_current_input_buffer_ = -1; | 1715 decoder_current_input_buffer_ = -1; |
1650 | 1716 |
1651 // If we were flushing, we'll never return any more BitstreamBuffers or | 1717 // If we were flushing, we'll never return any more BitstreamBuffers or |
1652 // PictureBuffers; they have all been dropped and returned by now. | 1718 // PictureBuffers; they have all been dropped and returned by now. |
1653 NotifyFlushDoneIfNeeded(); | 1719 NotifyFlushDoneIfNeeded(); |
1654 | 1720 |
1655 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening | 1721 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1687 ScheduleDecodeBufferTaskIfNeeded(); | 1753 ScheduleDecodeBufferTaskIfNeeded(); |
1688 } | 1754 } |
1689 | 1755 |
1690 void ExynosVideoDecodeAccelerator::DestroyTask() { | 1756 void ExynosVideoDecodeAccelerator::DestroyTask() { |
1691 DVLOG(3) << "DestroyTask()"; | 1757 DVLOG(3) << "DestroyTask()"; |
1692 TRACE_EVENT0("Video Decoder", "EVDA::DestroyTask"); | 1758 TRACE_EVENT0("Video Decoder", "EVDA::DestroyTask"); |
1693 | 1759 |
1694 // DestroyTask() should run regardless of decoder_state_. | 1760 // DestroyTask() should run regardless of decoder_state_. |
1695 | 1761 |
1696 // Stop streaming and the device_poll_thread_. | 1762 // Stop streaming and the device_poll_thread_. |
1697 StopDevicePoll(); | 1763 StopDevicePoll(false); |
1698 | 1764 |
1699 decoder_current_bitstream_buffer_.reset(); | 1765 decoder_current_bitstream_buffer_.reset(); |
1700 decoder_current_input_buffer_ = -1; | 1766 decoder_current_input_buffer_ = -1; |
1701 decoder_decode_buffer_tasks_scheduled_ = 0; | 1767 decoder_decode_buffer_tasks_scheduled_ = 0; |
1702 decoder_frames_at_client_ = 0; | 1768 decoder_frames_at_client_ = 0; |
1703 decoder_input_queue_.clear(); | 1769 decoder_input_queue_.clear(); |
1704 decoder_flushing_ = false; | 1770 decoder_flushing_ = false; |
1705 | 1771 |
1706 // Set our state to kError. Just in case. | 1772 // Set our state to kError. Just in case. |
1707 decoder_state_ = kError; | 1773 decoder_state_ = kError; |
(...skipping 11 matching lines...) Expand all Loading... | |
1719 return false; | 1785 return false; |
1720 } | 1786 } |
1721 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1787 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
1722 &ExynosVideoDecodeAccelerator::DevicePollTask, | 1788 &ExynosVideoDecodeAccelerator::DevicePollTask, |
1723 base::Unretained(this), | 1789 base::Unretained(this), |
1724 0)); | 1790 0)); |
1725 | 1791 |
1726 return true; | 1792 return true; |
1727 } | 1793 } |
1728 | 1794 |
1729 bool ExynosVideoDecodeAccelerator::StopDevicePoll() { | 1795 bool ExynosVideoDecodeAccelerator::StopDevicePoll(bool keep_mfc_input_state) { |
1730 DVLOG(3) << "StopDevicePoll()"; | 1796 DVLOG(3) << "StopDevicePoll()"; |
1731 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1797 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1732 | 1798 |
1733 // Signal the DevicePollTask() to stop, and stop the device poll thread. | 1799 // Signal the DevicePollTask() to stop, and stop the device poll thread. |
1734 if (!SetDevicePollInterrupt()) | 1800 if (!SetDevicePollInterrupt()) |
1735 return false; | 1801 return false; |
1736 device_poll_thread_.Stop(); | 1802 device_poll_thread_.Stop(); |
1737 // Clear the interrupt now, to be sure. | 1803 // Clear the interrupt now, to be sure. |
1738 if (!ClearDevicePollInterrupt()) | 1804 if (!ClearDevicePollInterrupt()) |
1739 return false; | 1805 return false; |
1740 | 1806 |
1741 // Stop streaming. | 1807 // Stop streaming. |
1742 if (mfc_input_streamon_) { | 1808 if (!keep_mfc_input_state) { |
1743 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1809 if (mfc_input_streamon_) { |
1744 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type); | 1810 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
1811 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type); | |
1812 } | |
1813 mfc_input_streamon_ = false; | |
1745 } | 1814 } |
1746 mfc_input_streamon_ = false; | |
1747 if (mfc_output_streamon_) { | 1815 if (mfc_output_streamon_) { |
1748 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1816 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
1749 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type); | 1817 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type); |
1750 } | 1818 } |
1751 mfc_output_streamon_ = false; | 1819 mfc_output_streamon_ = false; |
1752 if (gsc_input_streamon_) { | 1820 if (gsc_input_streamon_) { |
1753 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1821 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
1754 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_STREAMOFF, &type); | 1822 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_STREAMOFF, &type); |
1755 } | 1823 } |
1756 gsc_input_streamon_ = false; | 1824 gsc_input_streamon_ = false; |
1757 if (gsc_output_streamon_) { | 1825 if (gsc_output_streamon_) { |
1758 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1826 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
1759 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_STREAMOFF, &type); | 1827 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_STREAMOFF, &type); |
1760 } | 1828 } |
1761 gsc_output_streamon_ = false; | 1829 gsc_output_streamon_ = false; |
1762 | 1830 |
1763 // Reset all our accounting info. | 1831 // Reset all our accounting info. |
1764 mfc_input_ready_queue_.clear(); | 1832 if (!keep_mfc_input_state) { |
1765 mfc_free_input_buffers_.clear(); | 1833 mfc_input_ready_queue_.clear(); |
1766 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) { | 1834 mfc_free_input_buffers_.clear(); |
1767 mfc_free_input_buffers_.push_back(i); | 1835 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) { |
1768 mfc_input_buffer_map_[i].at_device = false; | 1836 mfc_free_input_buffers_.push_back(i); |
1769 mfc_input_buffer_map_[i].bytes_used = 0; | 1837 mfc_input_buffer_map_[i].at_device = false; |
1770 mfc_input_buffer_map_[i].input_id = -1; | 1838 mfc_input_buffer_map_[i].bytes_used = 0; |
1839 mfc_input_buffer_map_[i].input_id = -1; | |
1840 } | |
1841 mfc_input_buffer_queued_count_ = 0; | |
1771 } | 1842 } |
1772 mfc_input_buffer_queued_count_ = 0; | |
1773 mfc_free_output_buffers_.clear(); | 1843 mfc_free_output_buffers_.clear(); |
1774 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) { | 1844 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) { |
1775 mfc_free_output_buffers_.push_back(i); | 1845 mfc_free_output_buffers_.push_back(i); |
1776 mfc_output_buffer_map_[i].at_device = false; | 1846 mfc_output_buffer_map_[i].at_device = false; |
1777 mfc_output_buffer_map_[i].input_id = -1; | 1847 mfc_output_buffer_map_[i].input_id = -1; |
1778 } | 1848 } |
1779 mfc_output_buffer_queued_count_ = 0; | 1849 mfc_output_buffer_queued_count_ = 0; |
1780 mfc_output_gsc_input_queue_.clear(); | 1850 mfc_output_gsc_input_queue_.clear(); |
1781 gsc_free_input_buffers_.clear(); | 1851 gsc_free_input_buffers_.clear(); |
1782 for (size_t i = 0; i < gsc_input_buffer_map_.size(); ++i) { | 1852 for (size_t i = 0; i < gsc_input_buffer_map_.size(); ++i) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1823 return true; | 1893 return true; |
1824 } else { | 1894 } else { |
1825 DPLOG(ERROR) << "ClearDevicePollInterrupt(): read() failed"; | 1895 DPLOG(ERROR) << "ClearDevicePollInterrupt(): read() failed"; |
1826 NOTIFY_ERROR(PLATFORM_FAILURE); | 1896 NOTIFY_ERROR(PLATFORM_FAILURE); |
1827 return false; | 1897 return false; |
1828 } | 1898 } |
1829 } | 1899 } |
1830 return true; | 1900 return true; |
1831 } | 1901 } |
1832 | 1902 |
1903 void ExynosVideoDecodeAccelerator::StartResolutionChangeIfNeeded() { | |
1904 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | |
1905 DCHECK_EQ(decoder_state_, kDecoding); | |
1906 | |
1907 if (!resolution_change_pending_) | |
1908 return; | |
1909 | |
1910 if (!mfc_output_gsc_input_queue_.empty() || | |
1911 gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ > 0) { | |
1912 DVLOG(3) << "StartResolutionChangeIfNeeded(): waiting for GSC to finish."; | |
1913 return; | |
1914 } | |
1915 | |
1916 DVLOG(3) << "No more work for GSC, initiate resolution change"; | |
1917 | |
1918 // Keep MFC input queue. | |
1919 if (!StopDevicePoll(true)) | |
1920 return; | |
1921 | |
1922 decoder_state_ = kChangingResolution; | |
1923 DCHECK(resolution_change_pending_); | |
1924 resolution_change_pending_ = false; | |
1925 | |
1926 // Post a task to clean up buffers on child thread. This will also ensure | |
1927 // that we won't accept ReusePictureBuffer() anymore after that. | |
1928 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | |
1929 &ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers, | |
1930 weak_this_)); | |
1931 } | |
1932 | |
1933 void ExynosVideoDecodeAccelerator::FinishResolutionChange() { | |
1934 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | |
1935 DVLOG(3) << "FinishResolutionChange()"; | |
1936 | |
1937 if (decoder_state_ == kError) { | |
1938 DVLOG(2) << "FinishResolutionChange(): early out: kError state"; | |
1939 return; | |
1940 } | |
1941 | |
1942 struct v4l2_format format; | |
1943 bool again; | |
1944 bool ret = GetFormatInfo(&format, &again); | |
1945 if (!ret || again) { | |
1946 DVLOG(3) << "Couldn't get format information after resolution change"; | |
1947 NOTIFY_ERROR(PLATFORM_FAILURE); | |
1948 return; | |
1949 } | |
1950 | |
1951 if (!CreateBuffersForFormat(format)) { | |
1952 DVLOG(3) << "Couldn't reallocate buffers after resolution change"; | |
1953 NOTIFY_ERROR(PLATFORM_FAILURE); | |
1954 return; | |
1955 } | |
1956 | |
1957 // From here we stay in kChangingResolution and wait for | |
1958 // AssignPictureBuffers() before we can resume. | |
1959 } | |
1960 | |
1961 void ExynosVideoDecodeAccelerator::ResumeAfterResolutionChange() { | |
1962 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | |
1963 DVLOG(3) << "ResumeAfterResolutionChange()"; | |
1964 | |
1965 decoder_state_ = kDecoding; | |
1966 | |
1967 if (resolution_change_reset_pending_) { | |
1968 resolution_change_reset_pending_ = false; | |
1969 ResetTask(); | |
1970 return; | |
1971 } | |
1972 | |
1973 if (!StartDevicePoll()) | |
1974 return; | |
1975 | |
1976 EnqueueMfc(); | |
1977 // Gsc will get enqueued in AssignPictureBuffersTask(). | |
1978 ScheduleDecodeBufferTaskIfNeeded(); | |
1979 } | |
1980 | |
1833 void ExynosVideoDecodeAccelerator::DevicePollTask(unsigned int poll_fds) { | 1981 void ExynosVideoDecodeAccelerator::DevicePollTask(unsigned int poll_fds) { |
1834 DVLOG(3) << "DevicePollTask()"; | 1982 DVLOG(3) << "DevicePollTask()"; |
1835 DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current()); | 1983 DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current()); |
1836 TRACE_EVENT0("Video Decoder", "EVDA::DevicePollTask"); | 1984 TRACE_EVENT0("Video Decoder", "EVDA::DevicePollTask"); |
1837 | 1985 |
1838 // This routine just polls the set of device fds, and schedules a | 1986 // This routine just polls the set of device fds, and schedules a |
1839 // ServiceDeviceTask() on decoder_thread_ when processing needs to occur. | 1987 // ServiceDeviceTask() on decoder_thread_ when processing needs to occur. |
1840 // Other threads may notify this task to return early by writing to | 1988 // Other threads may notify this task to return early by writing to |
1841 // device_poll_interrupt_fd_. | 1989 // device_poll_interrupt_fd_. |
1842 struct pollfd pollfds[3]; | 1990 struct pollfd pollfds[3]; |
1843 nfds_t nfds; | 1991 nfds_t nfds; |
1992 int mfc_pollfd = -1; | |
1844 | 1993 |
1845 // Add device_poll_interrupt_fd_; | 1994 // Add device_poll_interrupt_fd_; |
1846 pollfds[0].fd = device_poll_interrupt_fd_; | 1995 pollfds[0].fd = device_poll_interrupt_fd_; |
1847 pollfds[0].events = POLLIN | POLLERR; | 1996 pollfds[0].events = POLLIN | POLLERR; |
1848 nfds = 1; | 1997 nfds = 1; |
1849 | 1998 |
1850 if (poll_fds & kPollMfc) { | 1999 if (poll_fds & kPollMfc) { |
1851 DVLOG(3) << "DevicePollTask(): adding MFC to poll() set"; | 2000 DVLOG(3) << "DevicePollTask(): adding MFC to poll() set"; |
1852 pollfds[nfds].fd = mfc_fd_; | 2001 pollfds[nfds].fd = mfc_fd_; |
1853 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR; | 2002 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR | POLLPRI; |
2003 mfc_pollfd = nfds; | |
1854 nfds++; | 2004 nfds++; |
1855 } | 2005 } |
1856 // Add GSC fd, if we should poll on it. | 2006 // Add GSC fd, if we should poll on it. |
1857 // GSC has to wait until both input and output buffers are queued. | 2007 // GSC has to wait until both input and output buffers are queued. |
1858 if (poll_fds & kPollGsc) { | 2008 if (poll_fds & kPollGsc) { |
1859 DVLOG(3) << "DevicePollTask(): adding GSC to poll() set"; | 2009 DVLOG(3) << "DevicePollTask(): adding GSC to poll() set"; |
1860 pollfds[nfds].fd = gsc_fd_; | 2010 pollfds[nfds].fd = gsc_fd_; |
1861 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR; | 2011 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR; |
1862 nfds++; | 2012 nfds++; |
1863 } | 2013 } |
1864 | 2014 |
1865 // Poll it! | 2015 // Poll it! |
1866 if (HANDLE_EINTR(poll(pollfds, nfds, -1)) == -1) { | 2016 if (HANDLE_EINTR(poll(pollfds, nfds, -1)) == -1) { |
1867 DPLOG(ERROR) << "DevicePollTask(): poll() failed"; | 2017 DPLOG(ERROR) << "DevicePollTask(): poll() failed"; |
1868 NOTIFY_ERROR(PLATFORM_FAILURE); | 2018 NOTIFY_ERROR(PLATFORM_FAILURE); |
1869 return; | 2019 return; |
1870 } | 2020 } |
1871 | 2021 |
2022 bool mfc_event_pending = (mfc_pollfd != -1 && | |
2023 pollfds[mfc_pollfd].revents & POLLPRI); | |
2024 | |
1872 // All processing should happen on ServiceDeviceTask(), since we shouldn't | 2025 // All processing should happen on ServiceDeviceTask(), since we shouldn't |
1873 // touch decoder state from this thread. | 2026 // touch decoder state from this thread. |
1874 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 2027 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
1875 &ExynosVideoDecodeAccelerator::ServiceDeviceTask, | 2028 &ExynosVideoDecodeAccelerator::ServiceDeviceTask, |
1876 base::Unretained(this))); | 2029 base::Unretained(this), mfc_event_pending)); |
1877 } | 2030 } |
1878 | 2031 |
1879 void ExynosVideoDecodeAccelerator::NotifyError(Error error) { | 2032 void ExynosVideoDecodeAccelerator::NotifyError(Error error) { |
1880 DVLOG(2) << "NotifyError()"; | 2033 DVLOG(2) << "NotifyError()"; |
1881 | 2034 |
1882 if (!child_message_loop_proxy_->BelongsToCurrentThread()) { | 2035 if (!child_message_loop_proxy_->BelongsToCurrentThread()) { |
1883 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 2036 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
1884 &ExynosVideoDecodeAccelerator::NotifyError, weak_this_, error)); | 2037 &ExynosVideoDecodeAccelerator::NotifyError, weak_this_, error)); |
1885 return; | 2038 return; |
1886 } | 2039 } |
(...skipping 12 matching lines...) Expand all Loading... | |
1899 if (decoder_thread_.message_loop() != NULL && | 2052 if (decoder_thread_.message_loop() != NULL && |
1900 decoder_thread_.message_loop() != base::MessageLoop::current()) { | 2053 decoder_thread_.message_loop() != base::MessageLoop::current()) { |
1901 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 2054 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
1902 &ExynosVideoDecodeAccelerator::SetDecoderState, | 2055 &ExynosVideoDecodeAccelerator::SetDecoderState, |
1903 base::Unretained(this), state)); | 2056 base::Unretained(this), state)); |
1904 } else { | 2057 } else { |
1905 decoder_state_ = state; | 2058 decoder_state_ = state; |
1906 } | 2059 } |
1907 } | 2060 } |
1908 | 2061 |
2062 bool ExynosVideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format, | |
2063 bool* again) { | |
2064 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | |
2065 | |
2066 *again = false; | |
2067 memset(format, 0, sizeof(*format)); | |
2068 format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | |
2069 if (HANDLE_EINTR(ioctl(mfc_fd_, VIDIOC_G_FMT, format)) != 0) { | |
2070 if (errno == EINVAL) { | |
2071 // EINVAL means we haven't seen sufficient stream to decode the format. | |
2072 *again = true; | |
2073 return true; | |
2074 } else { | |
2075 DPLOG(ERROR) << "DecodeBufferInitial(): ioctl() failed: VIDIOC_G_FMT"; | |
2076 NOTIFY_ERROR(PLATFORM_FAILURE); | |
2077 return false; | |
2078 } | |
2079 } | |
2080 | |
2081 return true; | |
2082 } | |
2083 | |
2084 bool ExynosVideoDecodeAccelerator::CreateBuffersForFormat( | |
2085 const struct v4l2_format& format) { | |
2086 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | |
2087 CHECK_EQ(format.fmt.pix_mp.num_planes, 2); | |
2088 frame_buffer_size_.SetSize( | |
2089 format.fmt.pix_mp.width, format.fmt.pix_mp.height); | |
2090 mfc_output_buffer_size_[0] = format.fmt.pix_mp.plane_fmt[0].sizeimage; | |
2091 mfc_output_buffer_size_[1] = format.fmt.pix_mp.plane_fmt[1].sizeimage; | |
2092 mfc_output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat; | |
2093 DCHECK_EQ(mfc_output_buffer_pixelformat_, V4L2_PIX_FMT_NV12MT_16X16); | |
2094 DVLOG(3) << "CreateBuffersForFormat(): new resolution: " | |
2095 << frame_buffer_size_.ToString(); | |
2096 | |
2097 if (!CreateMfcOutputBuffers() || !CreateGscInputBuffers() || | |
2098 !CreateGscOutputBuffers()) | |
2099 return false; | |
2100 | |
2101 return true; | |
2102 } | |
2103 | |
1909 bool ExynosVideoDecodeAccelerator::CreateMfcInputBuffers() { | 2104 bool ExynosVideoDecodeAccelerator::CreateMfcInputBuffers() { |
1910 DVLOG(3) << "CreateMfcInputBuffers()"; | 2105 DVLOG(3) << "CreateMfcInputBuffers()"; |
1911 // We always run this as we prepare to initialize. | 2106 // We always run this as we prepare to initialize. |
1912 DCHECK_EQ(decoder_state_, kUninitialized); | 2107 DCHECK_EQ(decoder_state_, kUninitialized); |
1913 DCHECK(!mfc_input_streamon_); | 2108 DCHECK(!mfc_input_streamon_); |
1914 DCHECK(mfc_input_buffer_map_.empty()); | 2109 DCHECK(mfc_input_buffer_map_.empty()); |
1915 | 2110 |
1916 __u32 pixelformat = 0; | 2111 __u32 pixelformat = 0; |
1917 if (video_profile_ >= media::H264PROFILE_MIN && | 2112 if (video_profile_ >= media::H264PROFILE_MIN && |
1918 video_profile_ <= media::H264PROFILE_MAX) { | 2113 video_profile_ <= media::H264PROFILE_MAX) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1962 } | 2157 } |
1963 mfc_input_buffer_map_[i].address = address; | 2158 mfc_input_buffer_map_[i].address = address; |
1964 mfc_input_buffer_map_[i].length = buffer.m.planes[0].length; | 2159 mfc_input_buffer_map_[i].length = buffer.m.planes[0].length; |
1965 } | 2160 } |
1966 | 2161 |
1967 return true; | 2162 return true; |
1968 } | 2163 } |
1969 | 2164 |
1970 bool ExynosVideoDecodeAccelerator::CreateMfcOutputBuffers() { | 2165 bool ExynosVideoDecodeAccelerator::CreateMfcOutputBuffers() { |
1971 DVLOG(3) << "CreateMfcOutputBuffers()"; | 2166 DVLOG(3) << "CreateMfcOutputBuffers()"; |
1972 DCHECK_EQ(decoder_state_, kInitialized); | 2167 DCHECK(decoder_state_ == kInitialized || |
2168 decoder_state_ == kChangingResolution); | |
1973 DCHECK(!mfc_output_streamon_); | 2169 DCHECK(!mfc_output_streamon_); |
1974 DCHECK(mfc_output_buffer_map_.empty()); | 2170 DCHECK(mfc_output_buffer_map_.empty()); |
1975 | 2171 |
1976 // Number of MFC output buffers we need. | 2172 // Number of MFC output buffers we need. |
1977 struct v4l2_control ctrl; | 2173 struct v4l2_control ctrl; |
1978 memset(&ctrl, 0, sizeof(ctrl)); | 2174 memset(&ctrl, 0, sizeof(ctrl)); |
1979 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; | 2175 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; |
1980 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_G_CTRL, &ctrl); | 2176 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_G_CTRL, &ctrl); |
1981 mfc_output_dpb_size_ = ctrl.value; | 2177 mfc_output_dpb_size_ = ctrl.value; |
1982 | 2178 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2019 mfc_output_buffer_map_[i].address[j] = address; | 2215 mfc_output_buffer_map_[i].address[j] = address; |
2020 mfc_output_buffer_map_[i].length[j] = buffer.m.planes[j].length; | 2216 mfc_output_buffer_map_[i].length[j] = buffer.m.planes[j].length; |
2021 } | 2217 } |
2022 } | 2218 } |
2023 | 2219 |
2024 return true; | 2220 return true; |
2025 } | 2221 } |
2026 | 2222 |
2027 bool ExynosVideoDecodeAccelerator::CreateGscInputBuffers() { | 2223 bool ExynosVideoDecodeAccelerator::CreateGscInputBuffers() { |
2028 DVLOG(3) << "CreateGscInputBuffers()"; | 2224 DVLOG(3) << "CreateGscInputBuffers()"; |
2029 DCHECK_EQ(decoder_state_, kInitialized); | 2225 DCHECK(decoder_state_ == kInitialized || |
2226 decoder_state_ == kChangingResolution); | |
2030 DCHECK(!gsc_input_streamon_); | 2227 DCHECK(!gsc_input_streamon_); |
2031 DCHECK(gsc_input_buffer_map_.empty()); | 2228 DCHECK(gsc_input_buffer_map_.empty()); |
2032 | 2229 |
2033 struct v4l2_format format; | 2230 struct v4l2_format format; |
2034 memset(&format, 0, sizeof(format)); | 2231 memset(&format, 0, sizeof(format)); |
2035 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 2232 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
2036 format.fmt.pix_mp.width = frame_buffer_size_.width(); | 2233 format.fmt.pix_mp.width = frame_buffer_size_.width(); |
2037 format.fmt.pix_mp.height = frame_buffer_size_.height(); | 2234 format.fmt.pix_mp.height = frame_buffer_size_.height(); |
2038 format.fmt.pix_mp.pixelformat = mfc_output_buffer_pixelformat_; | 2235 format.fmt.pix_mp.pixelformat = mfc_output_buffer_pixelformat_; |
2039 format.fmt.pix_mp.plane_fmt[0].sizeimage = mfc_output_buffer_size_[0]; | 2236 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 Loading... | |
2082 for (size_t i = 0; i < gsc_input_buffer_map_.size(); ++i) { | 2279 for (size_t i = 0; i < gsc_input_buffer_map_.size(); ++i) { |
2083 gsc_free_input_buffers_.push_back(i); | 2280 gsc_free_input_buffers_.push_back(i); |
2084 gsc_input_buffer_map_[i].mfc_output = -1; | 2281 gsc_input_buffer_map_[i].mfc_output = -1; |
2085 } | 2282 } |
2086 | 2283 |
2087 return true; | 2284 return true; |
2088 } | 2285 } |
2089 | 2286 |
2090 bool ExynosVideoDecodeAccelerator::CreateGscOutputBuffers() { | 2287 bool ExynosVideoDecodeAccelerator::CreateGscOutputBuffers() { |
2091 DVLOG(3) << "CreateGscOutputBuffers()"; | 2288 DVLOG(3) << "CreateGscOutputBuffers()"; |
2092 DCHECK_EQ(decoder_state_, kInitialized); | 2289 DCHECK(decoder_state_ == kInitialized || |
2290 decoder_state_ == kChangingResolution); | |
2093 DCHECK(!gsc_output_streamon_); | 2291 DCHECK(!gsc_output_streamon_); |
2094 DCHECK(gsc_output_buffer_map_.empty()); | 2292 DCHECK(gsc_output_buffer_map_.empty()); |
2095 | 2293 |
2096 // GSC outputs into the EGLImages we create from the textures we are | 2294 // GSC outputs into the EGLImages we create from the textures we are |
2097 // assigned. Assume RGBA8888 format. | 2295 // assigned. Assume RGBA8888 format. |
2098 struct v4l2_format format; | 2296 struct v4l2_format format; |
2099 memset(&format, 0, sizeof(format)); | 2297 memset(&format, 0, sizeof(format)); |
2100 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 2298 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
2101 format.fmt.pix_mp.width = frame_buffer_size_.width(); | 2299 format.fmt.pix_mp.width = frame_buffer_size_.width(); |
2102 format.fmt.pix_mp.height = frame_buffer_size_.height(); | 2300 format.fmt.pix_mp.height = frame_buffer_size_.height(); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2209 | 2407 |
2210 size_t i = 0; | 2408 size_t i = 0; |
2211 do { | 2409 do { |
2212 GscOutputRecord& output_record = gsc_output_buffer_map_[i]; | 2410 GscOutputRecord& output_record = gsc_output_buffer_map_[i]; |
2213 if (output_record.fd != -1) | 2411 if (output_record.fd != -1) |
2214 HANDLE_EINTR(close(output_record.fd)); | 2412 HANDLE_EINTR(close(output_record.fd)); |
2215 if (output_record.egl_image != EGL_NO_IMAGE_KHR) | 2413 if (output_record.egl_image != EGL_NO_IMAGE_KHR) |
2216 eglDestroyImageKHR(egl_display_, output_record.egl_image); | 2414 eglDestroyImageKHR(egl_display_, output_record.egl_image); |
2217 if (output_record.egl_sync != EGL_NO_SYNC_KHR) | 2415 if (output_record.egl_sync != EGL_NO_SYNC_KHR) |
2218 eglDestroySyncKHR(egl_display_, output_record.egl_sync); | 2416 eglDestroySyncKHR(egl_display_, output_record.egl_sync); |
2219 if (client_) | 2417 if (client_) { |
2418 DVLOG(1) << "DestroyGscOutputBuffers(): " | |
2419 << "dismissing PictureBuffer id=" << output_record.picture_id; | |
2220 client_->DismissPictureBuffer(output_record.picture_id); | 2420 client_->DismissPictureBuffer(output_record.picture_id); |
2421 } | |
2221 ++i; | 2422 ++i; |
2222 } while (i < gsc_output_buffer_map_.size()); | 2423 } while (i < gsc_output_buffer_map_.size()); |
2223 } | 2424 } |
2224 | 2425 |
2225 struct v4l2_requestbuffers reqbufs; | 2426 struct v4l2_requestbuffers reqbufs; |
2226 memset(&reqbufs, 0, sizeof(reqbufs)); | 2427 memset(&reqbufs, 0, sizeof(reqbufs)); |
2227 reqbufs.count = 0; | 2428 reqbufs.count = 0; |
2228 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 2429 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
2229 reqbufs.memory = V4L2_MEMORY_DMABUF; | 2430 reqbufs.memory = V4L2_MEMORY_DMABUF; |
2230 if (ioctl(gsc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0) | 2431 if (ioctl(gsc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0) |
2231 DPLOG(ERROR) << "DestroyGscOutputBuffers(): ioctl() failed: VIDIOC_REQBUFS"; | 2432 DPLOG(ERROR) << "DestroyGscOutputBuffers(): ioctl() failed: VIDIOC_REQBUFS"; |
2232 | 2433 |
2233 gsc_output_buffer_map_.clear(); | 2434 gsc_output_buffer_map_.clear(); |
2234 gsc_free_output_buffers_.clear(); | 2435 gsc_free_output_buffers_.clear(); |
2235 } | 2436 } |
2236 | 2437 |
2438 void ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers() { | |
2439 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | |
2440 DVLOG(3) << "ResolutionChangeDestroyBuffers()"; | |
2441 | |
2442 DestroyGscInputBuffers(); | |
2443 DestroyGscOutputBuffers(); | |
2444 DestroyMfcOutputBuffers(); | |
2445 | |
2446 // Finish resolution change on decoder thread. | |
2447 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | |
2448 &ExynosVideoDecodeAccelerator::FinishResolutionChange, | |
2449 base::Unretained(this))); | |
2450 } | |
2451 | |
2237 } // namespace content | 2452 } // namespace content |
OLD | NEW |