| 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 <libdrm/drm_fourcc.h> | |
| 9 #include <linux/videodev2.h> | 8 #include <linux/videodev2.h> |
| 10 #include <poll.h> | 9 #include <poll.h> |
| 11 #include <sys/eventfd.h> | 10 #include <sys/eventfd.h> |
| 12 #include <sys/ioctl.h> | 11 #include <sys/ioctl.h> |
| 13 #include <sys/mman.h> | 12 #include <sys/mman.h> |
| 14 | 13 |
| 15 #include "base/bind.h" | 14 #include "base/bind.h" |
| 16 #include "base/debug/trace_event.h" | 15 #include "base/debug/trace_event.h" |
| 17 #include "base/memory/shared_memory.h" | 16 #include "base/memory/shared_memory.h" |
| 18 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 } while (0) | 49 } while (0) |
| 51 | 50 |
| 52 namespace { | 51 namespace { |
| 53 | 52 |
| 54 // TODO(posciak): remove once we update linux-headers. | 53 // TODO(posciak): remove once we update linux-headers. |
| 55 #ifndef V4L2_EVENT_RESOLUTION_CHANGE | 54 #ifndef V4L2_EVENT_RESOLUTION_CHANGE |
| 56 #define V4L2_EVENT_RESOLUTION_CHANGE 5 | 55 #define V4L2_EVENT_RESOLUTION_CHANGE 5 |
| 57 #endif | 56 #endif |
| 58 | 57 |
| 59 const char kExynosMfcDevice[] = "/dev/mfc-dec"; | 58 const char kExynosMfcDevice[] = "/dev/mfc-dec"; |
| 59 const char kExynosGscDevice[] = "/dev/gsc1"; |
| 60 const char kMaliDriver[] = "libmali.so"; |
| 60 | 61 |
| 62 typedef EGLBoolean (*MaliEglImageGetBufferExtPhandleFunc)(EGLImageKHR, EGLint*, |
| 63 void*); |
| 64 |
| 65 void* libmali_handle = NULL; |
| 66 MaliEglImageGetBufferExtPhandleFunc |
| 67 mali_egl_image_get_buffer_ext_phandle = NULL; |
| 61 } // anonymous namespace | 68 } // anonymous namespace |
| 62 | 69 |
| 63 struct ExynosVideoDecodeAccelerator::BitstreamBufferRef { | 70 struct ExynosVideoDecodeAccelerator::BitstreamBufferRef { |
| 64 BitstreamBufferRef( | 71 BitstreamBufferRef( |
| 65 base::WeakPtr<Client>& client, | 72 base::WeakPtr<Client>& client, |
| 66 scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy, | 73 scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy, |
| 67 base::SharedMemory* shm, | 74 base::SharedMemory* shm, |
| 68 size_t size, | 75 size_t size, |
| 69 int32 input_id); | 76 int32 input_id); |
| 70 ~BitstreamBufferRef(); | 77 ~BitstreamBufferRef(); |
| 71 const base::WeakPtr<Client> client; | 78 const base::WeakPtr<Client> client; |
| 72 const scoped_refptr<base::MessageLoopProxy> client_message_loop_proxy; | 79 const scoped_refptr<base::MessageLoopProxy> client_message_loop_proxy; |
| 73 const scoped_ptr<base::SharedMemory> shm; | 80 const scoped_ptr<base::SharedMemory> shm; |
| 74 const size_t size; | 81 const size_t size; |
| 75 off_t bytes_used; | 82 off_t bytes_used; |
| 76 const int32 input_id; | 83 const int32 input_id; |
| 77 }; | 84 }; |
| 78 | 85 |
| 79 struct ExynosVideoDecodeAccelerator::PictureBufferArrayRef { | 86 struct ExynosVideoDecodeAccelerator::PictureBufferArrayRef { |
| 80 PictureBufferArrayRef(EGLDisplay egl_display); | 87 PictureBufferArrayRef(EGLDisplay egl_display, size_t count); |
| 81 ~PictureBufferArrayRef(); | 88 ~PictureBufferArrayRef(); |
| 82 | 89 |
| 83 struct PictureBufferRef { | 90 struct PictureBufferRef { |
| 84 PictureBufferRef(EGLImageKHR egl_image, int32 picture_id) | |
| 85 : egl_image(egl_image), picture_id(picture_id) {} | |
| 86 EGLImageKHR egl_image; | 91 EGLImageKHR egl_image; |
| 87 int32 picture_id; | 92 int egl_image_fd; |
| 93 int32 client_id; |
| 88 }; | 94 }; |
| 89 | 95 |
| 90 EGLDisplay const egl_display; | 96 EGLDisplay const egl_display; |
| 91 std::vector<PictureBufferRef> picture_buffers; | 97 std::vector<PictureBufferRef> picture_buffers; |
| 92 }; | 98 }; |
| 93 | 99 |
| 94 struct ExynosVideoDecodeAccelerator::EGLSyncKHRRef { | 100 struct ExynosVideoDecodeAccelerator::EGLSyncKHRRef { |
| 95 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); | 101 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); |
| 96 ~EGLSyncKHRRef(); | 102 ~EGLSyncKHRRef(); |
| 97 EGLDisplay const egl_display; | 103 EGLDisplay const egl_display; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 118 } | 124 } |
| 119 | 125 |
| 120 ExynosVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { | 126 ExynosVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { |
| 121 if (input_id >= 0) { | 127 if (input_id >= 0) { |
| 122 client_message_loop_proxy->PostTask(FROM_HERE, base::Bind( | 128 client_message_loop_proxy->PostTask(FROM_HERE, base::Bind( |
| 123 &Client::NotifyEndOfBitstreamBuffer, client, input_id)); | 129 &Client::NotifyEndOfBitstreamBuffer, client, input_id)); |
| 124 } | 130 } |
| 125 } | 131 } |
| 126 | 132 |
| 127 ExynosVideoDecodeAccelerator::PictureBufferArrayRef::PictureBufferArrayRef( | 133 ExynosVideoDecodeAccelerator::PictureBufferArrayRef::PictureBufferArrayRef( |
| 128 EGLDisplay egl_display) | 134 EGLDisplay egl_display, size_t count) |
| 129 : egl_display(egl_display) {} | 135 : egl_display(egl_display), |
| 136 picture_buffers(count) { |
| 137 for (size_t i = 0; i < picture_buffers.size(); ++i) { |
| 138 PictureBufferRef& buffer = picture_buffers[i]; |
| 139 buffer.egl_image = EGL_NO_IMAGE_KHR; |
| 140 buffer.egl_image_fd = -1; |
| 141 buffer.client_id = -1; |
| 142 } |
| 143 } |
| 130 | 144 |
| 131 ExynosVideoDecodeAccelerator::PictureBufferArrayRef::~PictureBufferArrayRef() { | 145 ExynosVideoDecodeAccelerator::PictureBufferArrayRef::~PictureBufferArrayRef() { |
| 132 for (size_t i = 0; i < picture_buffers.size(); ++i) { | 146 for (size_t i = 0; i < picture_buffers.size(); ++i) { |
| 133 EGLImageKHR egl_image = picture_buffers[i].egl_image; | 147 PictureBufferRef& buffer = picture_buffers[i]; |
| 134 if (egl_image != EGL_NO_IMAGE_KHR) | 148 if (buffer.egl_image != EGL_NO_IMAGE_KHR) |
| 135 eglDestroyImageKHR(egl_display, egl_image); | 149 eglDestroyImageKHR(egl_display, buffer.egl_image); |
| 150 if (buffer.egl_image_fd != -1) |
| 151 HANDLE_EINTR(close(buffer.egl_image_fd)); |
| 136 } | 152 } |
| 137 } | 153 } |
| 138 | 154 |
| 139 ExynosVideoDecodeAccelerator::EGLSyncKHRRef::EGLSyncKHRRef( | 155 ExynosVideoDecodeAccelerator::EGLSyncKHRRef::EGLSyncKHRRef( |
| 140 EGLDisplay egl_display, EGLSyncKHR egl_sync) | 156 EGLDisplay egl_display, EGLSyncKHR egl_sync) |
| 141 : egl_display(egl_display), | 157 : egl_display(egl_display), |
| 142 egl_sync(egl_sync) { | 158 egl_sync(egl_sync) { |
| 143 } | 159 } |
| 144 | 160 |
| 145 ExynosVideoDecodeAccelerator::EGLSyncKHRRef::~EGLSyncKHRRef() { | 161 ExynosVideoDecodeAccelerator::EGLSyncKHRRef::~EGLSyncKHRRef() { |
| 146 if (egl_sync != EGL_NO_SYNC_KHR) | 162 if (egl_sync != EGL_NO_SYNC_KHR) |
| 147 eglDestroySyncKHR(egl_display, egl_sync); | 163 eglDestroySyncKHR(egl_display, egl_sync); |
| 148 } | 164 } |
| 149 | 165 |
| 150 ExynosVideoDecodeAccelerator::MfcInputRecord::MfcInputRecord() | 166 ExynosVideoDecodeAccelerator::MfcInputRecord::MfcInputRecord() |
| 151 : at_device(false), | 167 : at_device(false), |
| 152 address(NULL), | 168 address(NULL), |
| 153 length(0), | 169 length(0), |
| 154 bytes_used(0), | 170 bytes_used(0), |
| 155 input_id(-1) { | 171 input_id(-1) { |
| 156 } | 172 } |
| 157 | 173 |
| 158 ExynosVideoDecodeAccelerator::MfcInputRecord::~MfcInputRecord() { | 174 ExynosVideoDecodeAccelerator::MfcInputRecord::~MfcInputRecord() { |
| 159 } | 175 } |
| 160 | 176 |
| 161 ExynosVideoDecodeAccelerator::MfcOutputRecord::MfcOutputRecord() | 177 ExynosVideoDecodeAccelerator::MfcOutputRecord::MfcOutputRecord() |
| 162 : at_device(false), | 178 : at_device(false), |
| 179 input_id(-1) { |
| 180 bytes_used[0] = 0; |
| 181 bytes_used[1] = 0; |
| 182 address[0] = NULL; |
| 183 address[1] = NULL; |
| 184 length[0] = 0; |
| 185 length[1] = 0; |
| 186 } |
| 187 |
| 188 ExynosVideoDecodeAccelerator::MfcOutputRecord::~MfcOutputRecord() { |
| 189 } |
| 190 |
| 191 ExynosVideoDecodeAccelerator::GscInputRecord::GscInputRecord() |
| 192 : at_device(false), |
| 193 mfc_output(-1) { |
| 194 } |
| 195 |
| 196 ExynosVideoDecodeAccelerator::GscInputRecord::~GscInputRecord() { |
| 197 } |
| 198 |
| 199 ExynosVideoDecodeAccelerator::GscOutputRecord::GscOutputRecord() |
| 200 : at_device(false), |
| 163 at_client(false), | 201 at_client(false), |
| 202 fd(-1), |
| 164 egl_image(EGL_NO_IMAGE_KHR), | 203 egl_image(EGL_NO_IMAGE_KHR), |
| 165 egl_sync(EGL_NO_SYNC_KHR), | 204 egl_sync(EGL_NO_SYNC_KHR), |
| 166 picture_id(-1), | 205 picture_id(-1), |
| 167 cleared(false) { | 206 cleared(false) {} |
| 168 for (size_t i = 0; i < arraysize(fds); ++i) | 207 |
| 169 fds[i] = -1; | 208 ExynosVideoDecodeAccelerator::GscOutputRecord::~GscOutputRecord() { |
| 170 } | 209 } |
| 171 | 210 |
| 172 ExynosVideoDecodeAccelerator::MfcOutputRecord::~MfcOutputRecord() {} | |
| 173 | |
| 174 ExynosVideoDecodeAccelerator::PictureRecord::PictureRecord( | 211 ExynosVideoDecodeAccelerator::PictureRecord::PictureRecord( |
| 175 bool cleared, | 212 bool cleared, |
| 176 const media::Picture& picture) | 213 const media::Picture& picture) |
| 177 : cleared(cleared), picture(picture) {} | 214 : cleared(cleared), picture(picture) {} |
| 178 | 215 |
| 179 ExynosVideoDecodeAccelerator::PictureRecord::~PictureRecord() {} | 216 ExynosVideoDecodeAccelerator::PictureRecord::~PictureRecord() {} |
| 180 | 217 |
| 181 ExynosVideoDecodeAccelerator::ExynosVideoDecodeAccelerator( | 218 ExynosVideoDecodeAccelerator::ExynosVideoDecodeAccelerator( |
| 182 EGLDisplay egl_display, | 219 EGLDisplay egl_display, |
| 183 EGLContext egl_context, | 220 EGLContext egl_context, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 201 resolution_change_pending_(false), | 238 resolution_change_pending_(false), |
| 202 resolution_change_reset_pending_(false), | 239 resolution_change_reset_pending_(false), |
| 203 decoder_partial_frame_pending_(false), | 240 decoder_partial_frame_pending_(false), |
| 204 mfc_fd_(-1), | 241 mfc_fd_(-1), |
| 205 mfc_input_streamon_(false), | 242 mfc_input_streamon_(false), |
| 206 mfc_input_buffer_queued_count_(0), | 243 mfc_input_buffer_queued_count_(0), |
| 207 mfc_output_streamon_(false), | 244 mfc_output_streamon_(false), |
| 208 mfc_output_buffer_queued_count_(0), | 245 mfc_output_buffer_queued_count_(0), |
| 209 mfc_output_buffer_pixelformat_(0), | 246 mfc_output_buffer_pixelformat_(0), |
| 210 mfc_output_dpb_size_(0), | 247 mfc_output_dpb_size_(0), |
| 248 gsc_fd_(-1), |
| 249 gsc_input_streamon_(false), |
| 250 gsc_input_buffer_queued_count_(0), |
| 251 gsc_output_streamon_(false), |
| 252 gsc_output_buffer_queued_count_(0), |
| 211 picture_clearing_count_(0), | 253 picture_clearing_count_(0), |
| 212 device_poll_thread_("ExynosDevicePollThread"), | 254 device_poll_thread_("ExynosDevicePollThread"), |
| 213 device_poll_interrupt_fd_(-1), | 255 device_poll_interrupt_fd_(-1), |
| 214 make_context_current_(make_context_current), | 256 make_context_current_(make_context_current), |
| 215 egl_display_(egl_display), | 257 egl_display_(egl_display), |
| 216 egl_context_(egl_context), | 258 egl_context_(egl_context), |
| 217 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN) {} | 259 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN) {} |
| 218 | 260 |
| 219 ExynosVideoDecodeAccelerator::~ExynosVideoDecodeAccelerator() { | 261 ExynosVideoDecodeAccelerator::~ExynosVideoDecodeAccelerator() { |
| 220 DCHECK(!decoder_thread_.IsRunning()); | 262 DCHECK(!decoder_thread_.IsRunning()); |
| 221 DCHECK(!device_poll_thread_.IsRunning()); | 263 DCHECK(!device_poll_thread_.IsRunning()); |
| 222 | 264 |
| 223 if (device_poll_interrupt_fd_ != -1) { | 265 if (device_poll_interrupt_fd_ != -1) { |
| 224 HANDLE_EINTR(close(device_poll_interrupt_fd_)); | 266 HANDLE_EINTR(close(device_poll_interrupt_fd_)); |
| 225 device_poll_interrupt_fd_ = -1; | 267 device_poll_interrupt_fd_ = -1; |
| 226 } | 268 } |
| 269 if (gsc_fd_ != -1) { |
| 270 DestroyGscInputBuffers(); |
| 271 DestroyGscOutputBuffers(); |
| 272 HANDLE_EINTR(close(gsc_fd_)); |
| 273 gsc_fd_ = -1; |
| 274 } |
| 227 if (mfc_fd_ != -1) { | 275 if (mfc_fd_ != -1) { |
| 228 DestroyMfcInputBuffers(); | 276 DestroyMfcInputBuffers(); |
| 229 DestroyMfcOutputBuffers(); | 277 DestroyMfcOutputBuffers(); |
| 230 HANDLE_EINTR(close(mfc_fd_)); | 278 HANDLE_EINTR(close(mfc_fd_)); |
| 231 mfc_fd_ = -1; | 279 mfc_fd_ = -1; |
| 232 } | 280 } |
| 233 | 281 |
| 234 // These maps have members that should be manually destroyed, e.g. file | 282 // These maps have members that should be manually destroyed, e.g. file |
| 235 // descriptors, mmap() segments, etc. | 283 // descriptors, mmap() segments, etc. |
| 236 DCHECK(mfc_input_buffer_map_.empty()); | 284 DCHECK(mfc_input_buffer_map_.empty()); |
| 237 DCHECK(mfc_output_buffer_map_.empty()); | 285 DCHECK(mfc_output_buffer_map_.empty()); |
| 286 DCHECK(gsc_input_buffer_map_.empty()); |
| 287 DCHECK(gsc_output_buffer_map_.empty()); |
| 238 } | 288 } |
| 239 | 289 |
| 240 bool ExynosVideoDecodeAccelerator::Initialize( | 290 bool ExynosVideoDecodeAccelerator::Initialize( |
| 241 media::VideoCodecProfile profile) { | 291 media::VideoCodecProfile profile) { |
| 242 DVLOG(3) << "Initialize()"; | 292 DVLOG(3) << "Initialize()"; |
| 243 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 293 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 244 DCHECK_EQ(decoder_state_, kUninitialized); | 294 DCHECK_EQ(decoder_state_, kUninitialized); |
| 245 | 295 |
| 246 switch (profile) { | 296 switch (profile) { |
| 247 case media::H264PROFILE_BASELINE: | 297 case media::H264PROFILE_BASELINE: |
| 248 DVLOG(2) << "Initialize(): profile H264PROFILE_BASELINE"; | 298 DVLOG(2) << "Initialize(): profile H264PROFILE_BASELINE"; |
| 249 break; | 299 break; |
| 250 case media::H264PROFILE_MAIN: | 300 case media::H264PROFILE_MAIN: |
| 251 DVLOG(2) << "Initialize(): profile H264PROFILE_MAIN"; | 301 DVLOG(2) << "Initialize(): profile H264PROFILE_MAIN"; |
| 252 break; | 302 break; |
| 253 case media::H264PROFILE_HIGH: | 303 case media::H264PROFILE_HIGH: |
| 254 DVLOG(2) << "Initialize(): profile H264PROFILE_HIGH"; | 304 DVLOG(2) << "Initialize(): profile H264PROFILE_HIGH"; |
| 255 break; | 305 break; |
| 256 case media::VP8PROFILE_MAIN: | 306 case media::VP8PROFILE_MAIN: |
| 257 DVLOG(2) << "Initialize(): profile VP8PROFILE_MAIN"; | 307 DVLOG(2) << "Initialize(): profile VP8PROFILE_MAIN"; |
| 258 break; | 308 break; |
| 259 default: | 309 default: |
| 260 DLOG(ERROR) << "Initialize(): unsupported profile=" << profile; | 310 DLOG(ERROR) << "Initialize(): unsupported profile=" << profile; |
| 261 return false; | 311 return false; |
| 262 }; | 312 }; |
| 263 video_profile_ = profile; | 313 video_profile_ = profile; |
| 264 | 314 |
| 315 static bool sandbox_initialized = PostSandboxInitialization(); |
| 316 if (!sandbox_initialized) { |
| 317 DLOG(ERROR) << "Initialize(): PostSandboxInitialization() failed"; |
| 318 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 319 return false; |
| 320 } |
| 321 |
| 265 if (egl_display_ == EGL_NO_DISPLAY) { | 322 if (egl_display_ == EGL_NO_DISPLAY) { |
| 266 DLOG(ERROR) << "Initialize(): could not get EGLDisplay"; | 323 DLOG(ERROR) << "Initialize(): could not get EGLDisplay"; |
| 267 NOTIFY_ERROR(PLATFORM_FAILURE); | 324 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 268 return false; | 325 return false; |
| 269 } | 326 } |
| 270 | 327 |
| 271 if (egl_context_ == EGL_NO_CONTEXT) { | 328 if (egl_context_ == EGL_NO_CONTEXT) { |
| 272 DLOG(ERROR) << "Initialize(): could not get EGLContext"; | 329 DLOG(ERROR) << "Initialize(): could not get EGLContext"; |
| 273 NOTIFY_ERROR(PLATFORM_FAILURE); | 330 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 274 return false; | 331 return false; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 290 // Open the video devices. | 347 // Open the video devices. |
| 291 DVLOG(2) << "Initialize(): opening MFC device: " << kExynosMfcDevice; | 348 DVLOG(2) << "Initialize(): opening MFC device: " << kExynosMfcDevice; |
| 292 mfc_fd_ = HANDLE_EINTR(open(kExynosMfcDevice, | 349 mfc_fd_ = HANDLE_EINTR(open(kExynosMfcDevice, |
| 293 O_RDWR | O_NONBLOCK | O_CLOEXEC)); | 350 O_RDWR | O_NONBLOCK | O_CLOEXEC)); |
| 294 if (mfc_fd_ == -1) { | 351 if (mfc_fd_ == -1) { |
| 295 DPLOG(ERROR) << "Initialize(): could not open MFC device: " | 352 DPLOG(ERROR) << "Initialize(): could not open MFC device: " |
| 296 << kExynosMfcDevice; | 353 << kExynosMfcDevice; |
| 297 NOTIFY_ERROR(PLATFORM_FAILURE); | 354 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 298 return false; | 355 return false; |
| 299 } | 356 } |
| 357 DVLOG(2) << "Initialize(): opening GSC device: " << kExynosGscDevice; |
| 358 gsc_fd_ = HANDLE_EINTR(open(kExynosGscDevice, |
| 359 O_RDWR | O_NONBLOCK | O_CLOEXEC)); |
| 360 if (gsc_fd_ == -1) { |
| 361 DPLOG(ERROR) << "Initialize(): could not open GSC device: " |
| 362 << kExynosGscDevice; |
| 363 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 364 return false; |
| 365 } |
| 300 | 366 |
| 301 // Create the interrupt fd. | 367 // Create the interrupt fd. |
| 302 DCHECK_EQ(device_poll_interrupt_fd_, -1); | 368 DCHECK_EQ(device_poll_interrupt_fd_, -1); |
| 303 device_poll_interrupt_fd_ = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); | 369 device_poll_interrupt_fd_ = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); |
| 304 if (device_poll_interrupt_fd_ == -1) { | 370 if (device_poll_interrupt_fd_ == -1) { |
| 305 DPLOG(ERROR) << "Initialize(): eventfd() failed"; | 371 DPLOG(ERROR) << "Initialize(): eventfd() failed"; |
| 306 NOTIFY_ERROR(PLATFORM_FAILURE); | 372 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 307 return false; | 373 return false; |
| 308 } | 374 } |
| 309 | 375 |
| 310 // Capabilities check. | 376 // Capabilities check. |
| 311 struct v4l2_capability caps; | 377 struct v4l2_capability caps; |
| 312 const __u32 kCapsRequired = | 378 const __u32 kCapsRequired = |
| 313 V4L2_CAP_VIDEO_CAPTURE_MPLANE | | 379 V4L2_CAP_VIDEO_CAPTURE_MPLANE | |
| 314 V4L2_CAP_VIDEO_OUTPUT_MPLANE | | 380 V4L2_CAP_VIDEO_OUTPUT_MPLANE | |
| 315 V4L2_CAP_STREAMING; | 381 V4L2_CAP_STREAMING; |
| 316 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QUERYCAP, &caps); | 382 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QUERYCAP, &caps); |
| 317 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { | 383 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { |
| 318 DLOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP" | 384 DLOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP" |
| 319 ", caps check failed: 0x" << std::hex << caps.capabilities; | 385 ", caps check failed: 0x" << std::hex << caps.capabilities; |
| 320 NOTIFY_ERROR(PLATFORM_FAILURE); | 386 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 321 return false; | 387 return false; |
| 322 } | 388 } |
| 389 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_QUERYCAP, &caps); |
| 390 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { |
| 391 DLOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP" |
| 392 ", caps check failed: 0x" << std::hex << caps.capabilities; |
| 393 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 394 return false; |
| 395 } |
| 323 | 396 |
| 324 if (!CreateMfcInputBuffers()) | 397 if (!CreateMfcInputBuffers()) |
| 325 return false; | 398 return false; |
| 326 | 399 |
| 327 // MFC output format has to be setup before streaming starts. | 400 // MFC output format has to be setup before streaming starts. |
| 328 struct v4l2_format format; | 401 struct v4l2_format format; |
| 329 memset(&format, 0, sizeof(format)); | 402 memset(&format, 0, sizeof(format)); |
| 330 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 403 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 331 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; | 404 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16; |
| 332 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_S_FMT, &format); | 405 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_S_FMT, &format); |
| 333 | 406 |
| 334 // Subscribe to the resolution change event. | 407 // Subscribe to the resolution change event. |
| 335 struct v4l2_event_subscription sub; | 408 struct v4l2_event_subscription sub; |
| 336 memset(&sub, 0, sizeof(sub)); | 409 memset(&sub, 0, sizeof(sub)); |
| 337 sub.type = V4L2_EVENT_RESOLUTION_CHANGE; | 410 sub.type = V4L2_EVENT_RESOLUTION_CHANGE; |
| 338 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_SUBSCRIBE_EVENT, &sub); | 411 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_SUBSCRIBE_EVENT, &sub); |
| 339 | 412 |
| 340 // Initialize format-specific bits. | 413 // Initialize format-specific bits. |
| 341 if (video_profile_ >= media::H264PROFILE_MIN && | 414 if (video_profile_ >= media::H264PROFILE_MIN && |
| (...skipping 24 matching lines...) Expand all Loading... |
| 366 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 439 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 367 &ExynosVideoDecodeAccelerator::DecodeTask, base::Unretained(this), | 440 &ExynosVideoDecodeAccelerator::DecodeTask, base::Unretained(this), |
| 368 bitstream_buffer)); | 441 bitstream_buffer)); |
| 369 } | 442 } |
| 370 | 443 |
| 371 void ExynosVideoDecodeAccelerator::AssignPictureBuffers( | 444 void ExynosVideoDecodeAccelerator::AssignPictureBuffers( |
| 372 const std::vector<media::PictureBuffer>& buffers) { | 445 const std::vector<media::PictureBuffer>& buffers) { |
| 373 DVLOG(3) << "AssignPictureBuffers(): buffer_count=" << buffers.size(); | 446 DVLOG(3) << "AssignPictureBuffers(): buffer_count=" << buffers.size(); |
| 374 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 447 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 375 | 448 |
| 376 if (buffers.size() != mfc_output_buffer_map_.size()) { | 449 if (buffers.size() != gsc_output_buffer_map_.size()) { |
| 377 DLOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" | 450 DLOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" |
| 378 " buffers. (Got " << buffers.size() | 451 " buffers. (Got " << buffers.size() << ", requested " << |
| 379 << ", requested " << mfc_output_buffer_map_.size() << ")"; | 452 gsc_output_buffer_map_.size() << ")"; |
| 380 NOTIFY_ERROR(INVALID_ARGUMENT); | 453 NOTIFY_ERROR(INVALID_ARGUMENT); |
| 381 return; | 454 return; |
| 382 } | 455 } |
| 383 | 456 |
| 384 if (!make_context_current_.Run()) { | 457 if (!make_context_current_.Run()) { |
| 385 DLOG(ERROR) << "AssignPictureBuffers(): could not make context current"; | 458 DLOG(ERROR) << "AssignPictureBuffers(): could not make context current"; |
| 386 NOTIFY_ERROR(PLATFORM_FAILURE); | 459 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 387 return; | 460 return; |
| 388 } | 461 } |
| 389 | 462 |
| 390 scoped_ptr<PictureBufferArrayRef> picture_buffers_ref( | 463 scoped_ptr<PictureBufferArrayRef> pic_buffers_ref( |
| 391 new PictureBufferArrayRef(egl_display_)); | 464 new PictureBufferArrayRef(egl_display_, buffers.size())); |
| 392 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); | 465 |
| 393 EGLint attrs[] = { | 466 const static EGLint kImageAttrs[] = { |
| 394 EGL_WIDTH, 0, EGL_HEIGHT, 0, | 467 EGL_IMAGE_PRESERVED_KHR, 0, |
| 395 EGL_LINUX_DRM_FOURCC_EXT, 0, EGL_DMA_BUF_PLANE0_FD_EXT, 0, | 468 EGL_NONE, |
| 396 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, EGL_DMA_BUF_PLANE0_PITCH_EXT, 0, | 469 }; |
| 397 EGL_DMA_BUF_PLANE1_FD_EXT, 0, EGL_DMA_BUF_PLANE1_OFFSET_EXT, 0, | 470 Display* x_display = base::MessagePumpForUI::GetDefaultXDisplay(); |
| 398 EGL_DMA_BUF_PLANE1_PITCH_EXT, 0, EGL_NONE, }; | 471 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_2D, 0); |
| 399 attrs[1] = frame_buffer_size_.width(); | 472 for (size_t i = 0; i < pic_buffers_ref->picture_buffers.size(); ++i) { |
| 400 attrs[3] = frame_buffer_size_.height(); | |
| 401 attrs[5] = DRM_FORMAT_NV12; | |
| 402 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) { | |
| 403 DCHECK(buffers[i].size() == frame_buffer_size_); | 473 DCHECK(buffers[i].size() == frame_buffer_size_); |
| 404 MfcOutputRecord& output_record = mfc_output_buffer_map_[i]; | 474 PictureBufferArrayRef::PictureBufferRef& buffer = |
| 405 attrs[7] = output_record.fds[0]; | 475 pic_buffers_ref->picture_buffers[i]; |
| 406 attrs[9] = 0; | 476 // Create the X pixmap and then create an EGLImageKHR from it, so we can |
| 407 attrs[11] = frame_buffer_size_.width(); | 477 // get dma_buf backing. |
| 408 attrs[13] = output_record.fds[1]; | 478 Pixmap pixmap = XCreatePixmap(x_display, |
| 409 attrs[15] = 0; | 479 RootWindow(x_display, 0), |
| 410 attrs[17] = frame_buffer_size_.width(); | 480 frame_buffer_size_.width(), |
| 481 frame_buffer_size_.height(), |
| 482 32); |
| 483 if (!pixmap) { |
| 484 DLOG(ERROR) << "AssignPictureBuffers(): could not create X pixmap"; |
| 485 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 486 return; |
| 487 } |
| 488 glBindTexture(GL_TEXTURE_2D, buffers[i].texture_id()); |
| 411 EGLImageKHR egl_image = eglCreateImageKHR( | 489 EGLImageKHR egl_image = eglCreateImageKHR( |
| 412 egl_display_, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attrs); | 490 egl_display_, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, |
| 491 (EGLClientBuffer)pixmap, kImageAttrs); |
| 492 // We can free the X pixmap immediately -- according to the |
| 493 // EGL_KHR_image_base spec, the backing storage does not go away until the |
| 494 // last referencing EGLImage is destroyed. |
| 495 XFreePixmap(x_display, pixmap); |
| 413 if (egl_image == EGL_NO_IMAGE_KHR) { | 496 if (egl_image == EGL_NO_IMAGE_KHR) { |
| 414 DLOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; | 497 DLOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; |
| 415 NOTIFY_ERROR(PLATFORM_FAILURE); | 498 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 416 return; | 499 return; |
| 417 } | 500 } |
| 418 | 501 buffer.egl_image = egl_image; |
| 419 glBindTexture(GL_TEXTURE_EXTERNAL_OES, buffers[i].texture_id()); | 502 int fd; |
| 420 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image); | 503 if (!mali_egl_image_get_buffer_ext_phandle(buffer.egl_image, NULL, &fd)) { |
| 421 picture_buffers_ref->picture_buffers.push_back( | 504 DLOG(ERROR) << "AssignPictureBuffers(): " |
| 422 PictureBufferArrayRef::PictureBufferRef(egl_image, buffers[i].id())); | 505 << "could not get EGLImageKHR dmabuf fd"; |
| 506 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 507 return; |
| 508 } |
| 509 buffer.egl_image_fd = fd; |
| 510 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image); |
| 511 buffer.client_id = buffers[i].id(); |
| 423 } | 512 } |
| 424 decoder_thread_.message_loop()->PostTask( | 513 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 425 FROM_HERE, | 514 &ExynosVideoDecodeAccelerator::AssignPictureBuffersTask, |
| 426 base::Bind(&ExynosVideoDecodeAccelerator::AssignPictureBuffersTask, | 515 base::Unretained(this), base::Passed(&pic_buffers_ref))); |
| 427 base::Unretained(this), | |
| 428 base::Passed(&picture_buffers_ref))); | |
| 429 } | 516 } |
| 430 | 517 |
| 431 void ExynosVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { | 518 void ExynosVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { |
| 432 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; | 519 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; |
| 433 // Must be run on child thread, as we'll insert a sync in the EGL context. | 520 // Must be run on child thread, as we'll insert a sync in the EGL context. |
| 434 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 521 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 435 | 522 |
| 436 if (!make_context_current_.Run()) { | 523 if (!make_context_current_.Run()) { |
| 437 DLOG(ERROR) << "ReusePictureBuffer(): could not make context current"; | 524 DLOG(ERROR) << "ReusePictureBuffer(): could not make context current"; |
| 438 NOTIFY_ERROR(PLATFORM_FAILURE); | 525 NOTIFY_ERROR(PLATFORM_FAILURE); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 } | 574 } |
| 488 | 575 |
| 489 // Set to kError state just in case. | 576 // Set to kError state just in case. |
| 490 SetDecoderState(kError); | 577 SetDecoderState(kError); |
| 491 | 578 |
| 492 delete this; | 579 delete this; |
| 493 } | 580 } |
| 494 | 581 |
| 495 bool ExynosVideoDecodeAccelerator::CanDecodeOnIOThread() { return true; } | 582 bool ExynosVideoDecodeAccelerator::CanDecodeOnIOThread() { return true; } |
| 496 | 583 |
| 584 // static |
| 585 void ExynosVideoDecodeAccelerator::PreSandboxInitialization() { |
| 586 DVLOG(3) << "PreSandboxInitialization()"; |
| 587 dlerror(); |
| 588 |
| 589 libmali_handle = dlopen(kMaliDriver, RTLD_LAZY | RTLD_LOCAL); |
| 590 if (libmali_handle == NULL) { |
| 591 DPLOG(ERROR) << "failed to dlopen() " << kMaliDriver << ": " << dlerror(); |
| 592 } |
| 593 } |
| 594 |
| 595 // static |
| 596 bool ExynosVideoDecodeAccelerator::PostSandboxInitialization() { |
| 597 DVLOG(3) << "PostSandboxInitialization()"; |
| 598 if (libmali_handle == NULL) { |
| 599 DLOG(ERROR) << "PostSandboxInitialization(): no " << kMaliDriver |
| 600 << " driver handle"; |
| 601 return false; |
| 602 } |
| 603 |
| 604 dlerror(); |
| 605 mali_egl_image_get_buffer_ext_phandle = |
| 606 reinterpret_cast<MaliEglImageGetBufferExtPhandleFunc>( |
| 607 dlsym(libmali_handle, "mali_egl_image_get_buffer_ext_phandle")); |
| 608 if (mali_egl_image_get_buffer_ext_phandle == NULL) { |
| 609 DPLOG(ERROR) << "PostSandboxInitialization(): failed to dlsym() " |
| 610 << "mali_egl_image_get_buffer_ext_phandle: " << dlerror(); |
| 611 return false; |
| 612 } |
| 613 |
| 614 return true; |
| 615 } |
| 616 |
| 497 void ExynosVideoDecodeAccelerator::DecodeTask( | 617 void ExynosVideoDecodeAccelerator::DecodeTask( |
| 498 const media::BitstreamBuffer& bitstream_buffer) { | 618 const media::BitstreamBuffer& bitstream_buffer) { |
| 499 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); | 619 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); |
| 500 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 620 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 501 DCHECK_NE(decoder_state_, kUninitialized); | 621 DCHECK_NE(decoder_state_, kUninitialized); |
| 502 TRACE_EVENT1("Video Decoder", "EVDA::DecodeTask", "input_id", | 622 TRACE_EVENT1("Video Decoder", "EVDA::DecodeTask", "input_id", |
| 503 bitstream_buffer.id()); | 623 bitstream_buffer.id()); |
| 504 | 624 |
| 505 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( | 625 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( |
| 506 io_client_, io_message_loop_proxy_, | 626 io_client_, io_message_loop_proxy_, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 519 // we're here, we know that this DecodeTask() was scheduled by a Decode() | 639 // we're here, we know that this DecodeTask() was scheduled by a Decode() |
| 520 // call that came after (in the client thread) the Reset() or Flush() call; | 640 // call that came after (in the client thread) the Reset() or Flush() call; |
| 521 // thus set up the delay if necessary. | 641 // thus set up the delay if necessary. |
| 522 if (decoder_delay_bitstream_buffer_id_ == -1) | 642 if (decoder_delay_bitstream_buffer_id_ == -1) |
| 523 decoder_delay_bitstream_buffer_id_ = bitstream_record->input_id; | 643 decoder_delay_bitstream_buffer_id_ = bitstream_record->input_id; |
| 524 } else if (decoder_state_ == kError) { | 644 } else if (decoder_state_ == kError) { |
| 525 DVLOG(2) << "DecodeTask(): early out: kError state"; | 645 DVLOG(2) << "DecodeTask(): early out: kError state"; |
| 526 return; | 646 return; |
| 527 } | 647 } |
| 528 | 648 |
| 529 decoder_input_queue_.push( | 649 decoder_input_queue_.push_back( |
| 530 linked_ptr<BitstreamBufferRef>(bitstream_record.release())); | 650 linked_ptr<BitstreamBufferRef>(bitstream_record.release())); |
| 531 decoder_decode_buffer_tasks_scheduled_++; | 651 decoder_decode_buffer_tasks_scheduled_++; |
| 532 DecodeBufferTask(); | 652 DecodeBufferTask(); |
| 533 } | 653 } |
| 534 | 654 |
| 535 void ExynosVideoDecodeAccelerator::DecodeBufferTask() { | 655 void ExynosVideoDecodeAccelerator::DecodeBufferTask() { |
| 536 DVLOG(3) << "DecodeBufferTask()"; | 656 DVLOG(3) << "DecodeBufferTask()"; |
| 537 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 657 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 538 DCHECK_NE(decoder_state_, kUninitialized); | 658 DCHECK_NE(decoder_state_, kUninitialized); |
| 539 TRACE_EVENT0("Video Decoder", "EVDA::DecodeBufferTask"); | 659 TRACE_EVENT0("Video Decoder", "EVDA::DecodeBufferTask"); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 557 return; | 677 return; |
| 558 } | 678 } |
| 559 linked_ptr<BitstreamBufferRef>& buffer_ref = decoder_input_queue_.front(); | 679 linked_ptr<BitstreamBufferRef>& buffer_ref = decoder_input_queue_.front(); |
| 560 if (decoder_delay_bitstream_buffer_id_ == buffer_ref->input_id) { | 680 if (decoder_delay_bitstream_buffer_id_ == buffer_ref->input_id) { |
| 561 // We're asked to delay decoding on this and subsequent buffers. | 681 // We're asked to delay decoding on this and subsequent buffers. |
| 562 return; | 682 return; |
| 563 } | 683 } |
| 564 | 684 |
| 565 // Setup to use the next buffer. | 685 // Setup to use the next buffer. |
| 566 decoder_current_bitstream_buffer_.reset(buffer_ref.release()); | 686 decoder_current_bitstream_buffer_.reset(buffer_ref.release()); |
| 567 decoder_input_queue_.pop(); | 687 decoder_input_queue_.pop_front(); |
| 568 DVLOG(3) << "DecodeBufferTask(): reading input_id=" | 688 DVLOG(3) << "DecodeBufferTask(): reading input_id=" |
| 569 << decoder_current_bitstream_buffer_->input_id | 689 << decoder_current_bitstream_buffer_->input_id |
| 570 << ", addr=" << (decoder_current_bitstream_buffer_->shm ? | 690 << ", addr=" << (decoder_current_bitstream_buffer_->shm ? |
| 571 decoder_current_bitstream_buffer_->shm->memory() : | 691 decoder_current_bitstream_buffer_->shm->memory() : |
| 572 NULL) | 692 NULL) |
| 573 << ", size=" << decoder_current_bitstream_buffer_->size; | 693 << ", size=" << decoder_current_bitstream_buffer_->size; |
| 574 } | 694 } |
| 575 bool schedule_task = false; | 695 bool schedule_task = false; |
| 576 const size_t size = decoder_current_bitstream_buffer_->size; | 696 const size_t size = decoder_current_bitstream_buffer_->size; |
| 577 size_t decoded_size = 0; | 697 size_t decoded_size = 0; |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 909 // buffer was prompted by a flush buffer, and should be queued even when | 1029 // buffer was prompted by a flush buffer, and should be queued even when |
| 910 // empty. | 1030 // empty. |
| 911 if (input_record.input_id >= 0 && input_record.bytes_used == 0) { | 1031 if (input_record.input_id >= 0 && input_record.bytes_used == 0) { |
| 912 input_record.input_id = -1; | 1032 input_record.input_id = -1; |
| 913 mfc_free_input_buffers_.push_back(decoder_current_input_buffer_); | 1033 mfc_free_input_buffers_.push_back(decoder_current_input_buffer_); |
| 914 decoder_current_input_buffer_ = -1; | 1034 decoder_current_input_buffer_ = -1; |
| 915 return true; | 1035 return true; |
| 916 } | 1036 } |
| 917 | 1037 |
| 918 // Queue it to MFC. | 1038 // Queue it to MFC. |
| 919 mfc_input_ready_queue_.push(decoder_current_input_buffer_); | 1039 mfc_input_ready_queue_.push_back(decoder_current_input_buffer_); |
| 920 decoder_current_input_buffer_ = -1; | 1040 decoder_current_input_buffer_ = -1; |
| 921 DVLOG(3) << "FlushInputFrame(): submitting input_id=" | 1041 DVLOG(3) << "FlushInputFrame(): submitting input_id=" |
| 922 << input_record.input_id; | 1042 << input_record.input_id; |
| 923 // Kick the MFC once since there's new available input for it. | 1043 // Kick the MFC once since there's new available input for it. |
| 924 EnqueueMfc(); | 1044 EnqueueMfc(); |
| 925 | 1045 |
| 926 return (decoder_state_ != kError); | 1046 return (decoder_state_ != kError); |
| 927 } | 1047 } |
| 928 | 1048 |
| 929 void ExynosVideoDecodeAccelerator::AssignPictureBuffersTask( | 1049 void ExynosVideoDecodeAccelerator::AssignPictureBuffersTask( |
| 930 scoped_ptr<PictureBufferArrayRef> pic_buffers) { | 1050 scoped_ptr<PictureBufferArrayRef> pic_buffers) { |
| 931 DVLOG(3) << "AssignPictureBuffersTask()"; | 1051 DVLOG(3) << "AssignPictureBuffersTask()"; |
| 932 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1052 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 933 DCHECK_NE(decoder_state_, kUninitialized); | 1053 DCHECK_NE(decoder_state_, kUninitialized); |
| 934 TRACE_EVENT0("Video Decoder", "EVDA::AssignPictureBuffersTask"); | 1054 TRACE_EVENT0("Video Decoder", "EVDA::AssignPictureBuffersTask"); |
| 935 | 1055 |
| 936 // We run AssignPictureBuffersTask even if we're in kResetting. | 1056 // We run AssignPictureBuffersTask even if we're in kResetting. |
| 937 if (decoder_state_ == kError) { | 1057 if (decoder_state_ == kError) { |
| 938 DVLOG(2) << "AssignPictureBuffersTask(): early out: kError state"; | 1058 DVLOG(2) << "AssignPictureBuffersTask(): early out: kError state"; |
| 939 return; | 1059 return; |
| 940 } | 1060 } |
| 941 | 1061 |
| 942 DCHECK_EQ(pic_buffers->picture_buffers.size(), mfc_output_buffer_map_.size()); | 1062 DCHECK_EQ(pic_buffers->picture_buffers.size(), gsc_output_buffer_map_.size()); |
| 943 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) { | 1063 for (size_t i = 0; i < gsc_output_buffer_map_.size(); ++i) { |
| 944 MfcOutputRecord& output_record = mfc_output_buffer_map_[i]; | |
| 945 PictureBufferArrayRef::PictureBufferRef& buffer_ref = | |
| 946 pic_buffers->picture_buffers[i]; | |
| 947 // We should be blank right now. | 1064 // We should be blank right now. |
| 948 DCHECK(!output_record.at_device); | 1065 GscOutputRecord& output_record = gsc_output_buffer_map_[i]; |
| 949 DCHECK(!output_record.at_client); | 1066 DCHECK_EQ(output_record.fd, -1); |
| 950 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); | 1067 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); |
| 951 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 1068 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
| 952 DCHECK_EQ(output_record.picture_id, -1); | 1069 DCHECK_EQ(output_record.picture_id, -1); |
| 953 DCHECK_EQ(output_record.cleared, false); | 1070 DCHECK_EQ(output_record.cleared, false); |
| 954 output_record.egl_image = buffer_ref.egl_image; | 1071 PictureBufferArrayRef::PictureBufferRef& buffer = |
| 955 output_record.picture_id = buffer_ref.picture_id; | 1072 pic_buffers->picture_buffers[i]; |
| 956 mfc_free_output_buffers_.push(i); | 1073 output_record.fd = buffer.egl_image_fd; |
| 957 DVLOG(3) << "AssignPictureBuffersTask(): buffer[" << i | 1074 output_record.egl_image = buffer.egl_image; |
| 958 << "]: picture_id=" << buffer_ref.picture_id; | 1075 output_record.picture_id = buffer.client_id; |
| 1076 |
| 1077 // Take ownership of the EGLImage and fd. |
| 1078 buffer.egl_image = EGL_NO_IMAGE_KHR; |
| 1079 buffer.egl_image_fd = -1; |
| 1080 // And add this buffer to the free list. |
| 1081 gsc_free_output_buffers_.push_back(i); |
| 959 } | 1082 } |
| 960 pic_buffers->picture_buffers.clear(); | |
| 961 | 1083 |
| 962 // We got buffers! Kick the MFC. | 1084 // We got buffers! Kick the GSC. |
| 963 EnqueueMfc(); | 1085 EnqueueGsc(); |
| 964 | 1086 |
| 965 if (decoder_state_ == kChangingResolution) | 1087 if (decoder_state_ == kChangingResolution) |
| 966 ResumeAfterResolutionChange(); | 1088 ResumeAfterResolutionChange(); |
| 967 } | 1089 } |
| 968 | 1090 |
| 969 void ExynosVideoDecodeAccelerator::ServiceDeviceTask(bool mfc_event_pending) { | 1091 void ExynosVideoDecodeAccelerator::ServiceDeviceTask(bool mfc_event_pending) { |
| 970 DVLOG(3) << "ServiceDeviceTask()"; | 1092 DVLOG(3) << "ServiceDeviceTask()"; |
| 971 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1093 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 972 DCHECK_NE(decoder_state_, kUninitialized); | 1094 DCHECK_NE(decoder_state_, kUninitialized); |
| 973 DCHECK_NE(decoder_state_, kInitialized); | 1095 DCHECK_NE(decoder_state_, kInitialized); |
| 974 DCHECK_NE(decoder_state_, kAfterReset); | 1096 DCHECK_NE(decoder_state_, kAfterReset); |
| 975 TRACE_EVENT0("Video Decoder", "EVDA::ServiceDeviceTask"); | 1097 TRACE_EVENT0("Video Decoder", "EVDA::ServiceDeviceTask"); |
| 976 | 1098 |
| 977 if (decoder_state_ == kResetting) { | 1099 if (decoder_state_ == kResetting) { |
| 978 DVLOG(2) << "ServiceDeviceTask(): early out: kResetting state"; | 1100 DVLOG(2) << "ServiceDeviceTask(): early out: kResetting state"; |
| 979 return; | 1101 return; |
| 980 } else if (decoder_state_ == kError) { | 1102 } else if (decoder_state_ == kError) { |
| 981 DVLOG(2) << "ServiceDeviceTask(): early out: kError state"; | 1103 DVLOG(2) << "ServiceDeviceTask(): early out: kError state"; |
| 982 return; | 1104 return; |
| 983 } else if (decoder_state_ == kChangingResolution) { | 1105 } else if (decoder_state_ == kChangingResolution) { |
| 984 DVLOG(2) << "ServiceDeviceTask(): early out: kChangingResolution state"; | 1106 DVLOG(2) << "ServiceDeviceTask(): early out: kChangingResolution state"; |
| 985 return; | 1107 return; |
| 986 } | 1108 } |
| 987 | 1109 |
| 988 if (mfc_event_pending) | 1110 if (mfc_event_pending) |
| 989 DequeueMfcEvents(); | 1111 DequeueMfcEvents(); |
| 990 DequeueMfc(); | 1112 DequeueMfc(); |
| 1113 DequeueGsc(); |
| 991 EnqueueMfc(); | 1114 EnqueueMfc(); |
| 1115 EnqueueGsc(); |
| 992 | 1116 |
| 993 // Clear the interrupt fd. | 1117 // Clear the interrupt fd. |
| 994 if (!ClearDevicePollInterrupt()) | 1118 if (!ClearDevicePollInterrupt()) |
| 995 return; | 1119 return; |
| 996 | 1120 |
| 997 unsigned int poll_fds = 0; | 1121 unsigned int poll_fds = 0; |
| 998 // Add MFC fd, if we should poll on it. | 1122 // Add MFC fd, if we should poll on it. |
| 999 // MFC can be polled as soon as either input or output buffers are queued. | 1123 // MFC can be polled as soon as either input or output buffers are queued. |
| 1000 if (mfc_input_buffer_queued_count_ + mfc_output_buffer_queued_count_ > 0) | 1124 if (mfc_input_buffer_queued_count_ + mfc_output_buffer_queued_count_ > 0) |
| 1001 poll_fds |= kPollMfc; | 1125 poll_fds |= kPollMfc; |
| 1126 // Add GSC fd, if we should poll on it. |
| 1127 // GSC has to wait until both input and output buffers are queued. |
| 1128 if (gsc_input_buffer_queued_count_ > 0 && gsc_output_buffer_queued_count_ > 0) |
| 1129 poll_fds |= kPollGsc; |
| 1002 | 1130 |
| 1003 // ServiceDeviceTask() should only ever be scheduled from DevicePollTask(), | 1131 // ServiceDeviceTask() should only ever be scheduled from DevicePollTask(), |
| 1004 // so either: | 1132 // so either: |
| 1005 // * device_poll_thread_ is running normally | 1133 // * device_poll_thread_ is running normally |
| 1006 // * device_poll_thread_ scheduled us, but then a ResetTask() or DestroyTask() | 1134 // * device_poll_thread_ scheduled us, but then a ResetTask() or DestroyTask() |
| 1007 // shut it down, in which case we're either in kResetting or kError states | 1135 // shut it down, in which case we're either in kResetting or kError states |
| 1008 // respectively, and we should have early-outed already. | 1136 // respectively, and we should have early-outed already. |
| 1009 DCHECK(device_poll_thread_.message_loop()); | 1137 DCHECK(device_poll_thread_.message_loop()); |
| 1010 // Queue the DevicePollTask() now. | 1138 // Queue the DevicePollTask() now. |
| 1011 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1139 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 1012 &ExynosVideoDecodeAccelerator::DevicePollTask, | 1140 &ExynosVideoDecodeAccelerator::DevicePollTask, |
| 1013 base::Unretained(this), | 1141 base::Unretained(this), |
| 1014 poll_fds)); | 1142 poll_fds)); |
| 1015 | 1143 |
| 1016 DVLOG(1) << "ServiceDeviceTask(): buffer counts: DEC[" | 1144 DVLOG(1) << "ServiceDeviceTask(): buffer counts: DEC[" |
| 1017 << decoder_input_queue_.size() << "->" | 1145 << decoder_input_queue_.size() << "->" |
| 1018 << mfc_input_ready_queue_.size() << "] => MFC[" | 1146 << mfc_input_ready_queue_.size() << "] => MFC[" |
| 1019 << mfc_free_input_buffers_.size() << "+" | 1147 << mfc_free_input_buffers_.size() << "+" |
| 1020 << mfc_input_buffer_queued_count_ << "/" | 1148 << mfc_input_buffer_queued_count_ << "/" |
| 1021 << mfc_input_buffer_map_.size() << "->" | 1149 << mfc_input_buffer_map_.size() << "->" |
| 1022 << mfc_free_output_buffers_.size() << "+" | 1150 << mfc_free_output_buffers_.size() << "+" |
| 1023 << mfc_output_buffer_queued_count_ << "/" | 1151 << mfc_output_buffer_queued_count_ << "/" |
| 1024 << mfc_output_buffer_map_.size() << "] => VDA[" | 1152 << mfc_output_buffer_map_.size() << "] => " |
| 1153 << mfc_output_gsc_input_queue_.size() << " => GSC[" |
| 1154 << gsc_free_input_buffers_.size() << "+" |
| 1155 << gsc_input_buffer_queued_count_ << "/" |
| 1156 << gsc_input_buffer_map_.size() << "->" |
| 1157 << gsc_free_output_buffers_.size() << "+" |
| 1158 << gsc_output_buffer_queued_count_ << "/" |
| 1159 << gsc_output_buffer_map_.size() << "] => VDA[" |
| 1025 << decoder_frames_at_client_ << "]"; | 1160 << decoder_frames_at_client_ << "]"; |
| 1026 | 1161 |
| 1027 ScheduleDecodeBufferTaskIfNeeded(); | 1162 ScheduleDecodeBufferTaskIfNeeded(); |
| 1028 StartResolutionChangeIfNeeded(); | 1163 StartResolutionChangeIfNeeded(); |
| 1029 } | 1164 } |
| 1030 | 1165 |
| 1031 void ExynosVideoDecodeAccelerator::EnqueueMfc() { | 1166 void ExynosVideoDecodeAccelerator::EnqueueMfc() { |
| 1032 DVLOG(3) << "EnqueueMfc()"; | 1167 DVLOG(3) << "EnqueueMfc()"; |
| 1033 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1168 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1034 DCHECK_NE(decoder_state_, kUninitialized); | 1169 DCHECK_NE(decoder_state_, kUninitialized); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1143 if (errno == EAGAIN) { | 1278 if (errno == EAGAIN) { |
| 1144 // EAGAIN if we're just out of buffers to dequeue. | 1279 // EAGAIN if we're just out of buffers to dequeue. |
| 1145 break; | 1280 break; |
| 1146 } | 1281 } |
| 1147 DPLOG(ERROR) << "DequeueMfc(): ioctl() failed: VIDIOC_DQBUF"; | 1282 DPLOG(ERROR) << "DequeueMfc(): ioctl() failed: VIDIOC_DQBUF"; |
| 1148 NOTIFY_ERROR(PLATFORM_FAILURE); | 1283 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1149 return; | 1284 return; |
| 1150 } | 1285 } |
| 1151 MfcOutputRecord& output_record = mfc_output_buffer_map_[dqbuf.index]; | 1286 MfcOutputRecord& output_record = mfc_output_buffer_map_[dqbuf.index]; |
| 1152 DCHECK(output_record.at_device); | 1287 DCHECK(output_record.at_device); |
| 1153 DCHECK(!output_record.at_client); | |
| 1154 DCHECK_NE(output_record.egl_image, EGL_NO_IMAGE_KHR); | |
| 1155 DCHECK_NE(output_record.picture_id, -1); | |
| 1156 output_record.at_device = false; | 1288 output_record.at_device = false; |
| 1157 if (dqbuf.m.planes[0].bytesused + dqbuf.m.planes[1].bytesused == 0) { | 1289 output_record.bytes_used[0] = dqbuf.m.planes[0].bytesused; |
| 1290 output_record.bytes_used[1] = dqbuf.m.planes[1].bytesused; |
| 1291 if (output_record.bytes_used[0] + output_record.bytes_used[1] == 0) { |
| 1158 // This is an empty output buffer returned as part of a flush. | 1292 // This is an empty output buffer returned as part of a flush. |
| 1159 mfc_free_output_buffers_.push(dqbuf.index); | 1293 mfc_free_output_buffers_.push_back(dqbuf.index); |
| 1294 output_record.input_id = -1; |
| 1160 } else { | 1295 } else { |
| 1161 DCHECK_GE(dqbuf.timestamp.tv_sec, 0); | 1296 // This is an output buffer with contents to pass down the pipe. |
| 1162 output_record.at_client = true; | 1297 mfc_output_gsc_input_queue_.push_back(dqbuf.index); |
| 1163 DVLOG(3) << "DequeueMfc(): returning input_id=" << dqbuf.timestamp.tv_sec | 1298 output_record.input_id = dqbuf.timestamp.tv_sec; |
| 1164 << " as picture_id=" << output_record.picture_id; | 1299 DCHECK(output_record.input_id >= 0); |
| 1165 const media::Picture& picture = | 1300 DVLOG(3) << "DequeueMfc(): dequeued input_id=" << output_record.input_id; |
| 1166 media::Picture(output_record.picture_id, dqbuf.timestamp.tv_sec); | 1301 // We don't count this output buffer dequeued yet, or add it to the free |
| 1167 pending_picture_ready_.push( | 1302 // list, as it has data GSC needs to process. |
| 1168 PictureRecord(output_record.cleared, picture)); | 1303 |
| 1169 SendPictureReady(); | 1304 // We have new frames in mfc_output_gsc_input_queue_. Kick the pipe. |
| 1170 output_record.cleared = true; | 1305 SetDevicePollInterrupt(); |
| 1171 decoder_frames_at_client_++; | |
| 1172 } | 1306 } |
| 1173 mfc_output_buffer_queued_count_--; | 1307 mfc_output_buffer_queued_count_--; |
| 1174 } | 1308 } |
| 1175 | 1309 |
| 1176 NotifyFlushDoneIfNeeded(); | 1310 NotifyFlushDoneIfNeeded(); |
| 1177 } | 1311 } |
| 1178 | 1312 |
| 1313 void ExynosVideoDecodeAccelerator::EnqueueGsc() { |
| 1314 DVLOG(3) << "EnqueueGsc()"; |
| 1315 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1316 DCHECK_NE(decoder_state_, kUninitialized); |
| 1317 DCHECK_NE(decoder_state_, kInitialized); |
| 1318 TRACE_EVENT0("Video Decoder", "EVDA::EnqueueGsc"); |
| 1319 |
| 1320 // Drain the pipe of completed MFC output buffers. |
| 1321 const int old_gsc_inputs_queued = gsc_input_buffer_queued_count_; |
| 1322 while (!mfc_output_gsc_input_queue_.empty() && |
| 1323 !gsc_free_input_buffers_.empty()) { |
| 1324 if (!EnqueueGscInputRecord()) |
| 1325 return; |
| 1326 } |
| 1327 if (old_gsc_inputs_queued == 0 && gsc_input_buffer_queued_count_ != 0) { |
| 1328 // We just started up a previously empty queue. |
| 1329 // Queue state changed; signal interrupt. |
| 1330 if (!SetDevicePollInterrupt()) |
| 1331 return; |
| 1332 // Start VIDIOC_STREAMON if we haven't yet. |
| 1333 if (!gsc_input_streamon_) { |
| 1334 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1335 IOCTL_OR_ERROR_RETURN(gsc_fd_, VIDIOC_STREAMON, &type); |
| 1336 gsc_input_streamon_ = true; |
| 1337 } |
| 1338 } |
| 1339 |
| 1340 if (gsc_input_buffer_queued_count_ != 0 && |
| 1341 gsc_output_buffer_queued_count_ == 0 && |
| 1342 !gsc_free_output_buffers_.empty()) { |
| 1343 const int old_gsc_outputs_queued = gsc_output_buffer_queued_count_; |
| 1344 if (!EnqueueGscOutputRecord()) |
| 1345 return; |
| 1346 if (old_gsc_outputs_queued == 0 && gsc_output_buffer_queued_count_ != 0) { |
| 1347 // We just started up a previously empty queue. |
| 1348 // Queue state changed; signal interrupt. |
| 1349 if (!SetDevicePollInterrupt()) |
| 1350 return; |
| 1351 // Start VIDIOC_STREAMON if we haven't yet. |
| 1352 if (!gsc_output_streamon_) { |
| 1353 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1354 IOCTL_OR_ERROR_RETURN(gsc_fd_, VIDIOC_STREAMON, &type); |
| 1355 gsc_output_streamon_ = true; |
| 1356 } |
| 1357 } |
| 1358 } |
| 1359 // Bug check: GSC is liable to race conditions if more than one buffer is |
| 1360 // simultaneously queued. |
| 1361 DCHECK_GE(1, gsc_output_buffer_queued_count_); |
| 1362 } |
| 1363 |
| 1364 void ExynosVideoDecodeAccelerator::DequeueGsc() { |
| 1365 DVLOG(3) << "DequeueGsc()"; |
| 1366 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1367 DCHECK_NE(decoder_state_, kUninitialized); |
| 1368 DCHECK_NE(decoder_state_, kInitialized); |
| 1369 DCHECK_NE(decoder_state_, kAfterReset); |
| 1370 TRACE_EVENT0("Video Decoder", "EVDA::DequeueGsc"); |
| 1371 |
| 1372 // Dequeue completed GSC input (VIDEO_OUTPUT) buffers, and recycle to the free |
| 1373 // list. Also recycle the corresponding MFC output buffers at this time. |
| 1374 struct v4l2_buffer dqbuf; |
| 1375 struct v4l2_plane planes[2]; |
| 1376 while (gsc_input_buffer_queued_count_ > 0) { |
| 1377 DCHECK(gsc_input_streamon_); |
| 1378 memset(&dqbuf, 0, sizeof(dqbuf)); |
| 1379 memset(planes, 0, sizeof(planes)); |
| 1380 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1381 dqbuf.memory = V4L2_MEMORY_DMABUF; |
| 1382 dqbuf.m.planes = planes; |
| 1383 dqbuf.length = 2; |
| 1384 if (ioctl(gsc_fd_, VIDIOC_DQBUF, &dqbuf) != 0) { |
| 1385 if (errno == EAGAIN) { |
| 1386 // EAGAIN if we're just out of buffers to dequeue. |
| 1387 break; |
| 1388 } |
| 1389 DPLOG(ERROR) << "DequeueGsc(): ioctl() failed: VIDIOC_DQBUF"; |
| 1390 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1391 return; |
| 1392 } |
| 1393 GscInputRecord& input_record = gsc_input_buffer_map_[dqbuf.index]; |
| 1394 MfcOutputRecord& output_record = |
| 1395 mfc_output_buffer_map_[input_record.mfc_output]; |
| 1396 DCHECK(input_record.at_device); |
| 1397 gsc_free_input_buffers_.push_back(dqbuf.index); |
| 1398 mfc_free_output_buffers_.push_back(input_record.mfc_output); |
| 1399 input_record.at_device = false; |
| 1400 input_record.mfc_output = -1; |
| 1401 output_record.input_id = -1; |
| 1402 gsc_input_buffer_queued_count_--; |
| 1403 } |
| 1404 |
| 1405 // Dequeue completed GSC output (VIDEO_CAPTURE) buffers, and send them off to |
| 1406 // the client. Don't recycle to its free list yet -- we can't do that until |
| 1407 // ReusePictureBuffer() returns it to us. |
| 1408 while (gsc_output_buffer_queued_count_ > 0) { |
| 1409 DCHECK(gsc_output_streamon_); |
| 1410 memset(&dqbuf, 0, sizeof(dqbuf)); |
| 1411 memset(planes, 0, sizeof(planes)); |
| 1412 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1413 dqbuf.memory = V4L2_MEMORY_DMABUF; |
| 1414 dqbuf.m.planes = planes; |
| 1415 dqbuf.length = 1; |
| 1416 if (ioctl(gsc_fd_, VIDIOC_DQBUF, &dqbuf) != 0) { |
| 1417 if (errno == EAGAIN) { |
| 1418 // EAGAIN if we're just out of buffers to dequeue. |
| 1419 break; |
| 1420 } |
| 1421 DPLOG(ERROR) << "DequeueGsc(): ioctl() failed: VIDIOC_DQBUF"; |
| 1422 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1423 return; |
| 1424 } |
| 1425 GscOutputRecord& output_record = gsc_output_buffer_map_[dqbuf.index]; |
| 1426 DCHECK(output_record.at_device); |
| 1427 DCHECK(!output_record.at_client); |
| 1428 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
| 1429 output_record.at_device = false; |
| 1430 output_record.at_client = true; |
| 1431 gsc_output_buffer_queued_count_--; |
| 1432 DVLOG(3) << "DequeueGsc(): returning input_id=" << dqbuf.timestamp.tv_sec |
| 1433 << " as picture_id=" << output_record.picture_id; |
| 1434 const media::Picture& picture = |
| 1435 media::Picture(output_record.picture_id, dqbuf.timestamp.tv_sec); |
| 1436 pending_picture_ready_.push(PictureRecord(output_record.cleared, picture)); |
| 1437 SendPictureReady(); |
| 1438 output_record.cleared = true; |
| 1439 decoder_frames_at_client_++; |
| 1440 } |
| 1441 |
| 1442 NotifyFlushDoneIfNeeded(); |
| 1443 } |
| 1444 |
| 1179 bool ExynosVideoDecodeAccelerator::EnqueueMfcInputRecord() { | 1445 bool ExynosVideoDecodeAccelerator::EnqueueMfcInputRecord() { |
| 1180 DVLOG(3) << "EnqueueMfcInputRecord()"; | 1446 DVLOG(3) << "EnqueueMfcInputRecord()"; |
| 1181 DCHECK(!mfc_input_ready_queue_.empty()); | 1447 DCHECK(!mfc_input_ready_queue_.empty()); |
| 1182 | 1448 |
| 1183 // Enqueue a MFC input (VIDEO_OUTPUT) buffer. | 1449 // Enqueue a MFC input (VIDEO_OUTPUT) buffer. |
| 1184 const int buffer = mfc_input_ready_queue_.front(); | 1450 const int buffer = mfc_input_ready_queue_.back(); |
| 1185 MfcInputRecord& input_record = mfc_input_buffer_map_[buffer]; | 1451 MfcInputRecord& input_record = mfc_input_buffer_map_[buffer]; |
| 1186 DCHECK(!input_record.at_device); | 1452 DCHECK(!input_record.at_device); |
| 1187 struct v4l2_buffer qbuf; | 1453 struct v4l2_buffer qbuf; |
| 1188 struct v4l2_plane qbuf_plane; | 1454 struct v4l2_plane qbuf_plane; |
| 1189 memset(&qbuf, 0, sizeof(qbuf)); | 1455 memset(&qbuf, 0, sizeof(qbuf)); |
| 1190 memset(&qbuf_plane, 0, sizeof(qbuf_plane)); | 1456 memset(&qbuf_plane, 0, sizeof(qbuf_plane)); |
| 1191 qbuf.index = buffer; | 1457 qbuf.index = buffer; |
| 1192 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1458 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1193 qbuf.timestamp.tv_sec = input_record.input_id; | 1459 qbuf.timestamp.tv_sec = input_record.input_id; |
| 1194 qbuf.memory = V4L2_MEMORY_MMAP; | 1460 qbuf.memory = V4L2_MEMORY_MMAP; |
| 1195 qbuf.m.planes = &qbuf_plane; | 1461 qbuf.m.planes = &qbuf_plane; |
| 1196 qbuf.m.planes[0].bytesused = input_record.bytes_used; | 1462 qbuf.m.planes[0].bytesused = input_record.bytes_used; |
| 1197 qbuf.length = 1; | 1463 qbuf.length = 1; |
| 1198 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QBUF, &qbuf); | 1464 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QBUF, &qbuf); |
| 1199 mfc_input_ready_queue_.pop(); | 1465 mfc_input_ready_queue_.pop_back(); |
| 1200 input_record.at_device = true; | 1466 input_record.at_device = true; |
| 1201 mfc_input_buffer_queued_count_++; | 1467 mfc_input_buffer_queued_count_++; |
| 1202 DVLOG(3) << "EnqueueMfcInputRecord(): enqueued input_id=" | 1468 DVLOG(3) << "EnqueueMfcInputRecord(): enqueued input_id=" |
| 1203 << input_record.input_id; | 1469 << input_record.input_id; |
| 1204 return true; | 1470 return true; |
| 1205 } | 1471 } |
| 1206 | 1472 |
| 1207 bool ExynosVideoDecodeAccelerator::EnqueueMfcOutputRecord() { | 1473 bool ExynosVideoDecodeAccelerator::EnqueueMfcOutputRecord() { |
| 1208 DVLOG(3) << "EnqueueMfcOutputRecord()"; | 1474 DVLOG(3) << "EnqueueMfcOutputRecord()"; |
| 1209 DCHECK(!mfc_free_output_buffers_.empty()); | 1475 DCHECK(!mfc_free_output_buffers_.empty()); |
| 1210 | 1476 |
| 1211 // Enqueue a MFC output (VIDEO_CAPTURE) buffer. | 1477 // Enqueue a MFC output (VIDEO_CAPTURE) buffer. |
| 1212 const int buffer = mfc_free_output_buffers_.front(); | 1478 const int buffer = mfc_free_output_buffers_.back(); |
| 1213 MfcOutputRecord& output_record = mfc_output_buffer_map_[buffer]; | 1479 MfcOutputRecord& output_record = mfc_output_buffer_map_[buffer]; |
| 1214 DCHECK(!output_record.at_device); | 1480 DCHECK(!output_record.at_device); |
| 1481 DCHECK_EQ(output_record.input_id, -1); |
| 1482 struct v4l2_buffer qbuf; |
| 1483 struct v4l2_plane qbuf_planes[2]; |
| 1484 memset(&qbuf, 0, sizeof(qbuf)); |
| 1485 memset(qbuf_planes, 0, sizeof(qbuf_planes)); |
| 1486 qbuf.index = buffer; |
| 1487 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1488 qbuf.memory = V4L2_MEMORY_MMAP; |
| 1489 qbuf.m.planes = qbuf_planes; |
| 1490 qbuf.length = 2; |
| 1491 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QBUF, &qbuf); |
| 1492 mfc_free_output_buffers_.pop_back(); |
| 1493 output_record.at_device = true; |
| 1494 mfc_output_buffer_queued_count_++; |
| 1495 return true; |
| 1496 } |
| 1497 |
| 1498 bool ExynosVideoDecodeAccelerator::EnqueueGscInputRecord() { |
| 1499 DVLOG(3) << "EnqueueGscInputRecord()"; |
| 1500 DCHECK(!gsc_free_input_buffers_.empty()); |
| 1501 |
| 1502 // Enqueue a GSC input (VIDEO_OUTPUT) buffer for a complete MFC output |
| 1503 // (VIDEO_CAPTURE) buffer. |
| 1504 const int mfc_buffer = mfc_output_gsc_input_queue_.front(); |
| 1505 const int gsc_buffer = gsc_free_input_buffers_.back(); |
| 1506 MfcOutputRecord& output_record = mfc_output_buffer_map_[mfc_buffer]; |
| 1507 DCHECK(!output_record.at_device); |
| 1508 GscInputRecord& input_record = gsc_input_buffer_map_[gsc_buffer]; |
| 1509 DCHECK(!input_record.at_device); |
| 1510 DCHECK_EQ(input_record.mfc_output, -1); |
| 1511 struct v4l2_buffer qbuf; |
| 1512 struct v4l2_plane qbuf_planes[2]; |
| 1513 memset(&qbuf, 0, sizeof(qbuf)); |
| 1514 memset(qbuf_planes, 0, sizeof(qbuf_planes)); |
| 1515 qbuf.index = gsc_buffer; |
| 1516 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1517 qbuf.timestamp.tv_sec = output_record.input_id; |
| 1518 qbuf.memory = V4L2_MEMORY_USERPTR; |
| 1519 qbuf.m.planes = qbuf_planes; |
| 1520 qbuf.m.planes[0].bytesused = output_record.bytes_used[0]; |
| 1521 qbuf.m.planes[0].length = mfc_output_buffer_size_[0]; |
| 1522 qbuf.m.planes[0].m.userptr = (unsigned long)output_record.address[0]; |
| 1523 qbuf.m.planes[1].bytesused = output_record.bytes_used[1]; |
| 1524 qbuf.m.planes[1].length = mfc_output_buffer_size_[1]; |
| 1525 qbuf.m.planes[1].m.userptr = (unsigned long)output_record.address[1]; |
| 1526 qbuf.length = 2; |
| 1527 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_QBUF, &qbuf); |
| 1528 mfc_output_gsc_input_queue_.pop_front(); |
| 1529 gsc_free_input_buffers_.pop_back(); |
| 1530 input_record.at_device = true; |
| 1531 input_record.mfc_output = mfc_buffer; |
| 1532 output_record.bytes_used[0] = 0; |
| 1533 output_record.bytes_used[1] = 0; |
| 1534 gsc_input_buffer_queued_count_++; |
| 1535 DVLOG(3) << "EnqueueGscInputRecord(): enqueued input_id=" |
| 1536 << output_record.input_id; |
| 1537 return true; |
| 1538 } |
| 1539 |
| 1540 bool ExynosVideoDecodeAccelerator::EnqueueGscOutputRecord() { |
| 1541 DVLOG(3) << "EnqueueGscOutputRecord()"; |
| 1542 DCHECK(!gsc_free_output_buffers_.empty()); |
| 1543 |
| 1544 // Enqueue a GSC output (VIDEO_CAPTURE) buffer. |
| 1545 const int buffer = gsc_free_output_buffers_.front(); |
| 1546 GscOutputRecord& output_record = gsc_output_buffer_map_[buffer]; |
| 1547 DCHECK(!output_record.at_device); |
| 1215 DCHECK(!output_record.at_client); | 1548 DCHECK(!output_record.at_client); |
| 1216 DCHECK_NE(output_record.egl_image, EGL_NO_IMAGE_KHR); | |
| 1217 DCHECK_NE(output_record.picture_id, -1); | |
| 1218 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { | 1549 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { |
| 1219 TRACE_EVENT0("Video Decoder", | 1550 TRACE_EVENT0( |
| 1220 "EVDA::EnqueueMfcOutputRecord: eglClientWaitSyncKHR"); | 1551 "Video Decoder", |
| 1552 "EVDA::EnqueueGscOutputRecord: eglClientWaitSyncKHR"); |
| 1221 // If we have to wait for completion, wait. Note that | 1553 // If we have to wait for completion, wait. Note that |
| 1222 // mfc_free_output_buffers_ is a FIFO queue, so we always wait on the | 1554 // gsc_free_output_buffers_ is a FIFO queue, so we always wait on the |
| 1223 // buffer that has been in the queue the longest. | 1555 // buffer that has been in the queue the longest. |
| 1224 eglClientWaitSyncKHR(egl_display_, output_record.egl_sync, 0, | 1556 eglClientWaitSyncKHR(egl_display_, output_record.egl_sync, 0, |
| 1225 EGL_FOREVER_KHR); | 1557 EGL_FOREVER_KHR); |
| 1226 eglDestroySyncKHR(egl_display_, output_record.egl_sync); | 1558 eglDestroySyncKHR(egl_display_, output_record.egl_sync); |
| 1227 output_record.egl_sync = EGL_NO_SYNC_KHR; | 1559 output_record.egl_sync = EGL_NO_SYNC_KHR; |
| 1228 } | 1560 } |
| 1229 struct v4l2_buffer qbuf; | 1561 struct v4l2_buffer qbuf; |
| 1230 struct v4l2_plane qbuf_planes[arraysize(output_record.fds)]; | 1562 struct v4l2_plane qbuf_plane; |
| 1231 memset(&qbuf, 0, sizeof(qbuf)); | 1563 memset(&qbuf, 0, sizeof(qbuf)); |
| 1232 memset(qbuf_planes, 0, sizeof(qbuf_planes)); | 1564 memset(&qbuf_plane, 0, sizeof(qbuf_plane)); |
| 1233 qbuf.index = buffer; | 1565 qbuf.index = buffer; |
| 1234 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1566 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1235 qbuf.memory = V4L2_MEMORY_MMAP; | 1567 qbuf.memory = V4L2_MEMORY_DMABUF; |
| 1236 qbuf.m.planes = qbuf_planes; | 1568 qbuf.m.planes = &qbuf_plane; |
| 1237 qbuf.length = arraysize(output_record.fds); | 1569 qbuf.m.planes[0].m.fd = output_record.fd; |
| 1238 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QBUF, &qbuf); | 1570 qbuf.length = 1; |
| 1239 mfc_free_output_buffers_.pop(); | 1571 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_QBUF, &qbuf); |
| 1572 gsc_free_output_buffers_.pop_front(); |
| 1240 output_record.at_device = true; | 1573 output_record.at_device = true; |
| 1241 mfc_output_buffer_queued_count_++; | 1574 gsc_output_buffer_queued_count_++; |
| 1242 return true; | 1575 return true; |
| 1243 } | 1576 } |
| 1244 | 1577 |
| 1245 void ExynosVideoDecodeAccelerator::ReusePictureBufferTask( | 1578 void ExynosVideoDecodeAccelerator::ReusePictureBufferTask( |
| 1246 int32 picture_buffer_id, scoped_ptr<EGLSyncKHRRef> egl_sync_ref) { | 1579 int32 picture_buffer_id, scoped_ptr<EGLSyncKHRRef> egl_sync_ref) { |
| 1247 DVLOG(3) << "ReusePictureBufferTask(): picture_buffer_id=" | 1580 DVLOG(3) << "ReusePictureBufferTask(): picture_buffer_id=" |
| 1248 << picture_buffer_id; | 1581 << picture_buffer_id; |
| 1249 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1582 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1250 TRACE_EVENT0("Video Decoder", "EVDA::ReusePictureBufferTask"); | 1583 TRACE_EVENT0("Video Decoder", "EVDA::ReusePictureBufferTask"); |
| 1251 | 1584 |
| 1252 // We run ReusePictureBufferTask even if we're in kResetting. | 1585 // We run ReusePictureBufferTask even if we're in kResetting. |
| 1253 if (decoder_state_ == kError) { | 1586 if (decoder_state_ == kError) { |
| 1254 DVLOG(2) << "ReusePictureBufferTask(): early out: kError state"; | 1587 DVLOG(2) << "ReusePictureBufferTask(): early out: kError state"; |
| 1255 return; | 1588 return; |
| 1256 } | 1589 } |
| 1257 | 1590 |
| 1258 if (decoder_state_ == kChangingResolution) { | 1591 if (decoder_state_ == kChangingResolution) { |
| 1259 DVLOG(2) << "ReusePictureBufferTask(): early out: kChangingResolution"; | 1592 DVLOG(2) << "ReusePictureBufferTask(): early out: kChangingResolution"; |
| 1260 return; | 1593 return; |
| 1261 } | 1594 } |
| 1262 | 1595 |
| 1263 size_t index; | 1596 size_t index; |
| 1264 for (index = 0; index < mfc_output_buffer_map_.size(); ++index) | 1597 for (index = 0; index < gsc_output_buffer_map_.size(); ++index) |
| 1265 if (mfc_output_buffer_map_[index].picture_id == picture_buffer_id) | 1598 if (gsc_output_buffer_map_[index].picture_id == picture_buffer_id) |
| 1266 break; | 1599 break; |
| 1267 | 1600 |
| 1268 if (index >= mfc_output_buffer_map_.size()) { | 1601 if (index >= gsc_output_buffer_map_.size()) { |
| 1269 DLOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not found"; | 1602 DLOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not found"; |
| 1270 NOTIFY_ERROR(INVALID_ARGUMENT); | 1603 NOTIFY_ERROR(INVALID_ARGUMENT); |
| 1271 return; | 1604 return; |
| 1272 } | 1605 } |
| 1273 | 1606 |
| 1274 MfcOutputRecord& output_record = mfc_output_buffer_map_[index]; | 1607 GscOutputRecord& output_record = gsc_output_buffer_map_[index]; |
| 1275 if (output_record.at_device || !output_record.at_client) { | 1608 if (output_record.at_device || !output_record.at_client) { |
| 1276 DLOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not reusable"; | 1609 DLOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not reusable"; |
| 1277 NOTIFY_ERROR(INVALID_ARGUMENT); | 1610 NOTIFY_ERROR(INVALID_ARGUMENT); |
| 1278 return; | 1611 return; |
| 1279 } | 1612 } |
| 1280 | 1613 |
| 1281 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 1614 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
| 1282 output_record.at_client = false; | 1615 output_record.at_client = false; |
| 1283 output_record.egl_sync = egl_sync_ref->egl_sync; | 1616 output_record.egl_sync = egl_sync_ref->egl_sync; |
| 1284 mfc_free_output_buffers_.push(index); | 1617 gsc_free_output_buffers_.push_back(index); |
| 1285 decoder_frames_at_client_--; | 1618 decoder_frames_at_client_--; |
| 1286 // Take ownership of the EGLSync. | 1619 // Take ownership of the EGLSync. |
| 1287 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR; | 1620 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR; |
| 1288 // We got a buffer back, so kick the MFC. | 1621 // We got a buffer back, so kick the GSC. |
| 1289 EnqueueMfc(); | 1622 EnqueueGsc(); |
| 1290 } | 1623 } |
| 1291 | 1624 |
| 1292 void ExynosVideoDecodeAccelerator::FlushTask() { | 1625 void ExynosVideoDecodeAccelerator::FlushTask() { |
| 1293 DVLOG(3) << "FlushTask()"; | 1626 DVLOG(3) << "FlushTask()"; |
| 1294 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1627 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1295 TRACE_EVENT0("Video Decoder", "EVDA::FlushTask"); | 1628 TRACE_EVENT0("Video Decoder", "EVDA::FlushTask"); |
| 1296 | 1629 |
| 1297 // Flush outstanding buffers. | 1630 // Flush outstanding buffers. |
| 1298 if (decoder_state_ == kInitialized || decoder_state_ == kAfterReset) { | 1631 if (decoder_state_ == kInitialized || decoder_state_ == kAfterReset) { |
| 1299 // There's nothing in the pipe, so return done immediately. | 1632 // There's nothing in the pipe, so return done immediately. |
| 1300 DVLOG(3) << "FlushTask(): returning flush"; | 1633 DVLOG(3) << "FlushTask(): returning flush"; |
| 1301 child_message_loop_proxy_->PostTask( | 1634 child_message_loop_proxy_->PostTask( |
| 1302 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_)); | 1635 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_)); |
| 1303 return; | 1636 return; |
| 1304 } else if (decoder_state_ == kError) { | 1637 } else if (decoder_state_ == kError) { |
| 1305 DVLOG(2) << "FlushTask(): early out: kError state"; | 1638 DVLOG(2) << "FlushTask(): early out: kError state"; |
| 1306 return; | 1639 return; |
| 1307 } | 1640 } |
| 1308 | 1641 |
| 1309 // We don't support stacked flushing. | 1642 // We don't support stacked flushing. |
| 1310 DCHECK(!decoder_flushing_); | 1643 DCHECK(!decoder_flushing_); |
| 1311 | 1644 |
| 1312 // Queue up an empty buffer -- this triggers the flush. | 1645 // Queue up an empty buffer -- this triggers the flush. |
| 1313 decoder_input_queue_.push( | 1646 decoder_input_queue_.push_back(linked_ptr<BitstreamBufferRef>( |
| 1314 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | 1647 new BitstreamBufferRef(io_client_, io_message_loop_proxy_, NULL, 0, |
| 1315 io_client_, io_message_loop_proxy_, NULL, 0, kFlushBufferId))); | 1648 kFlushBufferId))); |
| 1316 decoder_flushing_ = true; | 1649 decoder_flushing_ = true; |
| 1317 SendPictureReady(); // Send all pending PictureReady. | 1650 SendPictureReady(); // Send all pending PictureReady. |
| 1318 | 1651 |
| 1319 ScheduleDecodeBufferTaskIfNeeded(); | 1652 ScheduleDecodeBufferTaskIfNeeded(); |
| 1320 } | 1653 } |
| 1321 | 1654 |
| 1322 void ExynosVideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { | 1655 void ExynosVideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { |
| 1323 if (!decoder_flushing_) | 1656 if (!decoder_flushing_) |
| 1324 return; | 1657 return; |
| 1325 | 1658 |
| 1326 // Pipeline is empty when: | 1659 // Pipeline is empty when: |
| 1327 // * Decoder input queue is empty of non-delayed buffers. | 1660 // * Decoder input queue is empty of non-delayed buffers. |
| 1328 // * There is no currently filling input buffer. | 1661 // * There is no currently filling input buffer. |
| 1329 // * MFC input holding queue is empty. | 1662 // * MFC input holding queue is empty. |
| 1330 // * All MFC input (VIDEO_OUTPUT) buffers are returned. | 1663 // * All MFC input (VIDEO_OUTPUT) buffers are returned. |
| 1664 // * MFC -> GSC holding queue is empty. |
| 1665 // * All GSC input (VIDEO_OUTPUT) buffers are returned. |
| 1331 if (!decoder_input_queue_.empty()) { | 1666 if (!decoder_input_queue_.empty()) { |
| 1332 if (decoder_input_queue_.front()->input_id != | 1667 if (decoder_input_queue_.front()->input_id != |
| 1333 decoder_delay_bitstream_buffer_id_) | 1668 decoder_delay_bitstream_buffer_id_) |
| 1334 return; | 1669 return; |
| 1335 } | 1670 } |
| 1336 if (decoder_current_input_buffer_ != -1) | 1671 if (decoder_current_input_buffer_ != -1) |
| 1337 return; | 1672 return; |
| 1338 if ((mfc_input_ready_queue_.size() + mfc_input_buffer_queued_count_) != 0) | 1673 if ((mfc_input_ready_queue_.size() + |
| 1674 mfc_input_buffer_queued_count_ + mfc_output_gsc_input_queue_.size() + |
| 1675 gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ ) != 0) |
| 1339 return; | 1676 return; |
| 1340 | 1677 |
| 1341 // TODO(posciak): crbug.com/270039. MFC requires a streamoff-streamon | 1678 // TODO(posciak): crbug.com/270039. MFC requires a streamoff-streamon |
| 1342 // sequence after flush to continue, even if we are not resetting. This would | 1679 // sequence after flush to continue, even if we are not resetting. This would |
| 1343 // make sense, because we don't really want to resume from a non-resume point | 1680 // make sense, because we don't really want to resume from a non-resume point |
| 1344 // (e.g. not from an IDR) if we are flushed. | 1681 // (e.g. not from an IDR) if we are flushed. |
| 1345 // MSE player however triggers a Flush() on chunk end, but never Reset(). One | 1682 // MSE player however triggers a Flush() on chunk end, but never Reset(). One |
| 1346 // could argue either way, or even say that Flush() is not needed/harmful when | 1683 // could argue either way, or even say that Flush() is not needed/harmful when |
| 1347 // transitioning to next chunk. | 1684 // transitioning to next chunk. |
| 1348 // For now, do the streamoff-streamon cycle to satisfy MFC and not freeze when | 1685 // For now, do the streamoff-streamon cycle to satisfy MFC and not freeze when |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1386 // We stop streaming and clear buffer tracking info (not preserving | 1723 // We stop streaming and clear buffer tracking info (not preserving |
| 1387 // MFC inputs). | 1724 // MFC inputs). |
| 1388 // StopDevicePoll() unconditionally does _not_ destroy buffers, however. | 1725 // StopDevicePoll() unconditionally does _not_ destroy buffers, however. |
| 1389 if (!StopDevicePoll(false)) | 1726 if (!StopDevicePoll(false)) |
| 1390 return; | 1727 return; |
| 1391 | 1728 |
| 1392 DequeueMfcEvents(); | 1729 DequeueMfcEvents(); |
| 1393 | 1730 |
| 1394 resolution_change_pending_ = false; | 1731 resolution_change_pending_ = false; |
| 1395 decoder_current_bitstream_buffer_.reset(); | 1732 decoder_current_bitstream_buffer_.reset(); |
| 1396 while (!decoder_input_queue_.empty()) | 1733 decoder_input_queue_.clear(); |
| 1397 decoder_input_queue_.pop(); | |
| 1398 | 1734 |
| 1399 decoder_current_input_buffer_ = -1; | 1735 decoder_current_input_buffer_ = -1; |
| 1400 | 1736 |
| 1401 // If we were flushing, we'll never return any more BitstreamBuffers or | 1737 // If we were flushing, we'll never return any more BitstreamBuffers or |
| 1402 // PictureBuffers; they have all been dropped and returned by now. | 1738 // PictureBuffers; they have all been dropped and returned by now. |
| 1403 NotifyFlushDoneIfNeeded(); | 1739 NotifyFlushDoneIfNeeded(); |
| 1404 | 1740 |
| 1405 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening | 1741 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening |
| 1406 // jobs will early-out in the kResetting state. | 1742 // jobs will early-out in the kResetting state. |
| 1407 decoder_state_ = kResetting; | 1743 decoder_state_ = kResetting; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1444 | 1780 |
| 1445 // DestroyTask() should run regardless of decoder_state_. | 1781 // DestroyTask() should run regardless of decoder_state_. |
| 1446 | 1782 |
| 1447 // Stop streaming and the device_poll_thread_. | 1783 // Stop streaming and the device_poll_thread_. |
| 1448 StopDevicePoll(false); | 1784 StopDevicePoll(false); |
| 1449 | 1785 |
| 1450 decoder_current_bitstream_buffer_.reset(); | 1786 decoder_current_bitstream_buffer_.reset(); |
| 1451 decoder_current_input_buffer_ = -1; | 1787 decoder_current_input_buffer_ = -1; |
| 1452 decoder_decode_buffer_tasks_scheduled_ = 0; | 1788 decoder_decode_buffer_tasks_scheduled_ = 0; |
| 1453 decoder_frames_at_client_ = 0; | 1789 decoder_frames_at_client_ = 0; |
| 1454 while (!decoder_input_queue_.empty()) | 1790 decoder_input_queue_.clear(); |
| 1455 decoder_input_queue_.pop(); | |
| 1456 decoder_flushing_ = false; | 1791 decoder_flushing_ = false; |
| 1457 | 1792 |
| 1458 // Set our state to kError. Just in case. | 1793 // Set our state to kError. Just in case. |
| 1459 decoder_state_ = kError; | 1794 decoder_state_ = kError; |
| 1460 } | 1795 } |
| 1461 | 1796 |
| 1462 bool ExynosVideoDecodeAccelerator::StartDevicePoll() { | 1797 bool ExynosVideoDecodeAccelerator::StartDevicePoll() { |
| 1463 DVLOG(3) << "StartDevicePoll()"; | 1798 DVLOG(3) << "StartDevicePoll()"; |
| 1464 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1799 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1465 DCHECK(!device_poll_thread_.IsRunning()); | 1800 DCHECK(!device_poll_thread_.IsRunning()); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1496 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1831 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1497 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type); | 1832 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type); |
| 1498 } | 1833 } |
| 1499 mfc_input_streamon_ = false; | 1834 mfc_input_streamon_ = false; |
| 1500 } | 1835 } |
| 1501 if (mfc_output_streamon_) { | 1836 if (mfc_output_streamon_) { |
| 1502 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1837 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1503 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type); | 1838 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type); |
| 1504 } | 1839 } |
| 1505 mfc_output_streamon_ = false; | 1840 mfc_output_streamon_ = false; |
| 1841 if (gsc_input_streamon_) { |
| 1842 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1843 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_STREAMOFF, &type); |
| 1844 } |
| 1845 gsc_input_streamon_ = false; |
| 1846 if (gsc_output_streamon_) { |
| 1847 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1848 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_STREAMOFF, &type); |
| 1849 } |
| 1850 gsc_output_streamon_ = false; |
| 1506 | 1851 |
| 1507 // Reset all our accounting info. | 1852 // Reset all our accounting info. |
| 1508 if (!keep_mfc_input_state) { | 1853 if (!keep_mfc_input_state) { |
| 1509 while (!mfc_input_ready_queue_.empty()) | 1854 mfc_input_ready_queue_.clear(); |
| 1510 mfc_input_ready_queue_.pop(); | |
| 1511 mfc_free_input_buffers_.clear(); | 1855 mfc_free_input_buffers_.clear(); |
| 1512 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) { | 1856 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) { |
| 1513 mfc_free_input_buffers_.push_back(i); | 1857 mfc_free_input_buffers_.push_back(i); |
| 1514 mfc_input_buffer_map_[i].at_device = false; | 1858 mfc_input_buffer_map_[i].at_device = false; |
| 1515 mfc_input_buffer_map_[i].bytes_used = 0; | 1859 mfc_input_buffer_map_[i].bytes_used = 0; |
| 1516 mfc_input_buffer_map_[i].input_id = -1; | 1860 mfc_input_buffer_map_[i].input_id = -1; |
| 1517 } | 1861 } |
| 1518 mfc_input_buffer_queued_count_ = 0; | 1862 mfc_input_buffer_queued_count_ = 0; |
| 1519 } | 1863 } |
| 1520 while (!mfc_free_output_buffers_.empty()) | 1864 mfc_free_output_buffers_.clear(); |
| 1521 mfc_free_output_buffers_.pop(); | |
| 1522 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) { | 1865 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) { |
| 1523 MfcOutputRecord& output_record = mfc_output_buffer_map_[i]; | 1866 mfc_free_output_buffers_.push_back(i); |
| 1524 // Only mark those free that aren't being held by the VDA client. | 1867 mfc_output_buffer_map_[i].at_device = false; |
| 1525 if (!output_record.at_client) { | 1868 mfc_output_buffer_map_[i].input_id = -1; |
| 1526 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 1869 } |
| 1527 mfc_free_output_buffers_.push(i); | 1870 mfc_output_buffer_queued_count_ = 0; |
| 1528 mfc_output_buffer_map_[i].at_device = false; | 1871 mfc_output_gsc_input_queue_.clear(); |
| 1872 gsc_free_input_buffers_.clear(); |
| 1873 for (size_t i = 0; i < gsc_input_buffer_map_.size(); ++i) { |
| 1874 gsc_free_input_buffers_.push_back(i); |
| 1875 gsc_input_buffer_map_[i].at_device = false; |
| 1876 gsc_input_buffer_map_[i].mfc_output = -1; |
| 1877 } |
| 1878 gsc_input_buffer_queued_count_ = 0; |
| 1879 gsc_free_output_buffers_.clear(); |
| 1880 for (size_t i = 0; i < gsc_output_buffer_map_.size(); ++i) { |
| 1881 // Only mark those free that aren't being held by the VDA. |
| 1882 if (!gsc_output_buffer_map_[i].at_client) { |
| 1883 gsc_free_output_buffers_.push_back(i); |
| 1884 gsc_output_buffer_map_[i].at_device = false; |
| 1529 } | 1885 } |
| 1530 } | 1886 } |
| 1531 mfc_output_buffer_queued_count_ = 0; | 1887 gsc_output_buffer_queued_count_ = 0; |
| 1532 | 1888 |
| 1533 DVLOG(3) << "StopDevicePoll(): device poll stopped"; | 1889 DVLOG(3) << "StopDevicePoll(): device poll stopped"; |
| 1534 return true; | 1890 return true; |
| 1535 } | 1891 } |
| 1536 | 1892 |
| 1537 bool ExynosVideoDecodeAccelerator::SetDevicePollInterrupt() { | 1893 bool ExynosVideoDecodeAccelerator::SetDevicePollInterrupt() { |
| 1538 DVLOG(3) << "SetDevicePollInterrupt()"; | 1894 DVLOG(3) << "SetDevicePollInterrupt()"; |
| 1539 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1895 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1540 | 1896 |
| 1541 const uint64 buf = 1; | 1897 const uint64 buf = 1; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1565 return true; | 1921 return true; |
| 1566 } | 1922 } |
| 1567 | 1923 |
| 1568 void ExynosVideoDecodeAccelerator::StartResolutionChangeIfNeeded() { | 1924 void ExynosVideoDecodeAccelerator::StartResolutionChangeIfNeeded() { |
| 1569 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1925 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1570 DCHECK_EQ(decoder_state_, kDecoding); | 1926 DCHECK_EQ(decoder_state_, kDecoding); |
| 1571 | 1927 |
| 1572 if (!resolution_change_pending_) | 1928 if (!resolution_change_pending_) |
| 1573 return; | 1929 return; |
| 1574 | 1930 |
| 1575 DVLOG(3) << "No more work, initiate resolution change"; | 1931 if (!mfc_output_gsc_input_queue_.empty() || |
| 1932 gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ > 0) { |
| 1933 DVLOG(3) << "StartResolutionChangeIfNeeded(): waiting for GSC to finish."; |
| 1934 return; |
| 1935 } |
| 1936 |
| 1937 DVLOG(3) << "No more work for GSC, initiate resolution change"; |
| 1576 | 1938 |
| 1577 // Keep MFC input queue. | 1939 // Keep MFC input queue. |
| 1578 if (!StopDevicePoll(true)) | 1940 if (!StopDevicePoll(true)) |
| 1579 return; | 1941 return; |
| 1580 | 1942 |
| 1581 decoder_state_ = kChangingResolution; | 1943 decoder_state_ = kChangingResolution; |
| 1582 DCHECK(resolution_change_pending_); | 1944 DCHECK(resolution_change_pending_); |
| 1583 resolution_change_pending_ = false; | 1945 resolution_change_pending_ = false; |
| 1584 | 1946 |
| 1585 // Post a task to clean up buffers on child thread. This will also ensure | 1947 // Post a task to clean up buffers on child thread. This will also ensure |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1626 if (resolution_change_reset_pending_) { | 1988 if (resolution_change_reset_pending_) { |
| 1627 resolution_change_reset_pending_ = false; | 1989 resolution_change_reset_pending_ = false; |
| 1628 ResetTask(); | 1990 ResetTask(); |
| 1629 return; | 1991 return; |
| 1630 } | 1992 } |
| 1631 | 1993 |
| 1632 if (!StartDevicePoll()) | 1994 if (!StartDevicePoll()) |
| 1633 return; | 1995 return; |
| 1634 | 1996 |
| 1635 EnqueueMfc(); | 1997 EnqueueMfc(); |
| 1998 // Gsc will get enqueued in AssignPictureBuffersTask(). |
| 1636 ScheduleDecodeBufferTaskIfNeeded(); | 1999 ScheduleDecodeBufferTaskIfNeeded(); |
| 1637 } | 2000 } |
| 1638 | 2001 |
| 1639 void ExynosVideoDecodeAccelerator::DevicePollTask(unsigned int poll_fds) { | 2002 void ExynosVideoDecodeAccelerator::DevicePollTask(unsigned int poll_fds) { |
| 1640 DVLOG(3) << "DevicePollTask()"; | 2003 DVLOG(3) << "DevicePollTask()"; |
| 1641 DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current()); | 2004 DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current()); |
| 1642 TRACE_EVENT0("Video Decoder", "EVDA::DevicePollTask"); | 2005 TRACE_EVENT0("Video Decoder", "EVDA::DevicePollTask"); |
| 1643 | 2006 |
| 1644 // This routine just polls the set of device fds, and schedules a | 2007 // This routine just polls the set of device fds, and schedules a |
| 1645 // ServiceDeviceTask() on decoder_thread_ when processing needs to occur. | 2008 // ServiceDeviceTask() on decoder_thread_ when processing needs to occur. |
| 1646 // Other threads may notify this task to return early by writing to | 2009 // Other threads may notify this task to return early by writing to |
| 1647 // device_poll_interrupt_fd_. | 2010 // device_poll_interrupt_fd_. |
| 1648 struct pollfd pollfds[3]; | 2011 struct pollfd pollfds[3]; |
| 1649 nfds_t nfds; | 2012 nfds_t nfds; |
| 1650 int mfc_pollfd = -1; | 2013 int mfc_pollfd = -1; |
| 1651 | 2014 |
| 1652 // Add device_poll_interrupt_fd_; | 2015 // Add device_poll_interrupt_fd_; |
| 1653 pollfds[0].fd = device_poll_interrupt_fd_; | 2016 pollfds[0].fd = device_poll_interrupt_fd_; |
| 1654 pollfds[0].events = POLLIN | POLLERR; | 2017 pollfds[0].events = POLLIN | POLLERR; |
| 1655 nfds = 1; | 2018 nfds = 1; |
| 1656 | 2019 |
| 1657 if (poll_fds & kPollMfc) { | 2020 if (poll_fds & kPollMfc) { |
| 1658 DVLOG(3) << "DevicePollTask(): adding MFC to poll() set"; | 2021 DVLOG(3) << "DevicePollTask(): adding MFC to poll() set"; |
| 1659 pollfds[nfds].fd = mfc_fd_; | 2022 pollfds[nfds].fd = mfc_fd_; |
| 1660 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR | POLLPRI; | 2023 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR | POLLPRI; |
| 1661 mfc_pollfd = nfds; | 2024 mfc_pollfd = nfds; |
| 1662 nfds++; | 2025 nfds++; |
| 1663 } | 2026 } |
| 2027 // Add GSC fd, if we should poll on it. |
| 2028 // GSC has to wait until both input and output buffers are queued. |
| 2029 if (poll_fds & kPollGsc) { |
| 2030 DVLOG(3) << "DevicePollTask(): adding GSC to poll() set"; |
| 2031 pollfds[nfds].fd = gsc_fd_; |
| 2032 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR; |
| 2033 nfds++; |
| 2034 } |
| 1664 | 2035 |
| 1665 // Poll it! | 2036 // Poll it! |
| 1666 if (HANDLE_EINTR(poll(pollfds, nfds, -1)) == -1) { | 2037 if (HANDLE_EINTR(poll(pollfds, nfds, -1)) == -1) { |
| 1667 DPLOG(ERROR) << "DevicePollTask(): poll() failed"; | 2038 DPLOG(ERROR) << "DevicePollTask(): poll() failed"; |
| 1668 NOTIFY_ERROR(PLATFORM_FAILURE); | 2039 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1669 return; | 2040 return; |
| 1670 } | 2041 } |
| 1671 | 2042 |
| 1672 bool mfc_event_pending = (mfc_pollfd != -1 && | 2043 bool mfc_event_pending = (mfc_pollfd != -1 && |
| 1673 pollfds[mfc_pollfd].revents & POLLPRI); | 2044 pollfds[mfc_pollfd].revents & POLLPRI); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1730 | 2101 |
| 1731 return true; | 2102 return true; |
| 1732 } | 2103 } |
| 1733 | 2104 |
| 1734 bool ExynosVideoDecodeAccelerator::CreateBuffersForFormat( | 2105 bool ExynosVideoDecodeAccelerator::CreateBuffersForFormat( |
| 1735 const struct v4l2_format& format) { | 2106 const struct v4l2_format& format) { |
| 1736 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 2107 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1737 CHECK_EQ(format.fmt.pix_mp.num_planes, 2); | 2108 CHECK_EQ(format.fmt.pix_mp.num_planes, 2); |
| 1738 frame_buffer_size_.SetSize( | 2109 frame_buffer_size_.SetSize( |
| 1739 format.fmt.pix_mp.width, format.fmt.pix_mp.height); | 2110 format.fmt.pix_mp.width, format.fmt.pix_mp.height); |
| 2111 mfc_output_buffer_size_[0] = format.fmt.pix_mp.plane_fmt[0].sizeimage; |
| 2112 mfc_output_buffer_size_[1] = format.fmt.pix_mp.plane_fmt[1].sizeimage; |
| 1740 mfc_output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat; | 2113 mfc_output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat; |
| 1741 DCHECK_EQ(mfc_output_buffer_pixelformat_, V4L2_PIX_FMT_NV12M); | 2114 DCHECK_EQ(mfc_output_buffer_pixelformat_, V4L2_PIX_FMT_NV12MT_16X16); |
| 1742 DVLOG(3) << "CreateBuffersForFormat(): new resolution: " | 2115 DVLOG(3) << "CreateBuffersForFormat(): new resolution: " |
| 1743 << frame_buffer_size_.ToString(); | 2116 << frame_buffer_size_.ToString(); |
| 1744 | 2117 |
| 1745 if (!CreateMfcOutputBuffers()) | 2118 if (!CreateMfcOutputBuffers() || !CreateGscInputBuffers() || |
| 2119 !CreateGscOutputBuffers()) |
| 1746 return false; | 2120 return false; |
| 1747 | 2121 |
| 1748 return true; | 2122 return true; |
| 1749 } | 2123 } |
| 1750 | 2124 |
| 1751 bool ExynosVideoDecodeAccelerator::CreateMfcInputBuffers() { | 2125 bool ExynosVideoDecodeAccelerator::CreateMfcInputBuffers() { |
| 1752 DVLOG(3) << "CreateMfcInputBuffers()"; | 2126 DVLOG(3) << "CreateMfcInputBuffers()"; |
| 1753 // We always run this as we prepare to initialize. | 2127 // We always run this as we prepare to initialize. |
| 1754 DCHECK_EQ(decoder_state_, kUninitialized); | 2128 DCHECK_EQ(decoder_state_, kUninitialized); |
| 1755 DCHECK(!mfc_input_streamon_); | 2129 DCHECK(!mfc_input_streamon_); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1826 // Output format setup in Initialize(). | 2200 // Output format setup in Initialize(). |
| 1827 | 2201 |
| 1828 // Allocate the output buffers. | 2202 // Allocate the output buffers. |
| 1829 struct v4l2_requestbuffers reqbufs; | 2203 struct v4l2_requestbuffers reqbufs; |
| 1830 memset(&reqbufs, 0, sizeof(reqbufs)); | 2204 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 1831 reqbufs.count = mfc_output_dpb_size_ + kDpbOutputBufferExtraCount; | 2205 reqbufs.count = mfc_output_dpb_size_ + kDpbOutputBufferExtraCount; |
| 1832 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 2206 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1833 reqbufs.memory = V4L2_MEMORY_MMAP; | 2207 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 1834 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_REQBUFS, &reqbufs); | 2208 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_REQBUFS, &reqbufs); |
| 1835 | 2209 |
| 1836 // Create DMABUFs from output buffers. | 2210 // Fill our free-buffers list, and create DMABUFs from them. |
| 1837 mfc_output_buffer_map_.resize(reqbufs.count); | 2211 mfc_output_buffer_map_.resize(reqbufs.count); |
| 1838 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) { | 2212 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) { |
| 1839 MfcOutputRecord& output_record = mfc_output_buffer_map_[i]; | 2213 mfc_free_output_buffers_.push_back(i); |
| 1840 for (size_t j = 0; j < arraysize(output_record.fds); ++j) { | 2214 |
| 1841 // Export the DMABUF fd so we can export it as a texture. | 2215 // Query for the MEMORY_MMAP pointer. |
| 1842 struct v4l2_exportbuffer expbuf; | 2216 struct v4l2_plane planes[2]; |
| 1843 memset(&expbuf, 0, sizeof(expbuf)); | 2217 struct v4l2_buffer buffer; |
| 1844 expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 2218 memset(&buffer, 0, sizeof(buffer)); |
| 1845 expbuf.index = i; | 2219 memset(planes, 0, sizeof(planes)); |
| 1846 expbuf.plane = j; | 2220 buffer.index = i; |
| 1847 expbuf.flags = O_CLOEXEC; | 2221 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1848 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_EXPBUF, &expbuf); | 2222 buffer.memory = V4L2_MEMORY_MMAP; |
| 1849 output_record.fds[j] = expbuf.fd; | 2223 buffer.m.planes = planes; |
| 2224 buffer.length = 2; |
| 2225 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QUERYBUF, &buffer); |
| 2226 |
| 2227 // Get their user memory for GSC input. |
| 2228 for (int j = 0; j < 2; ++j) { |
| 2229 void* address = mmap(NULL, buffer.m.planes[j].length, |
| 2230 PROT_READ | PROT_WRITE, MAP_SHARED, mfc_fd_, |
| 2231 buffer.m.planes[j].m.mem_offset); |
| 2232 if (address == MAP_FAILED) { |
| 2233 DPLOG(ERROR) << "CreateMfcInputBuffers(): mmap() failed"; |
| 2234 return false; |
| 2235 } |
| 2236 mfc_output_buffer_map_[i].address[j] = address; |
| 2237 mfc_output_buffer_map_[i].length[j] = buffer.m.planes[j].length; |
| 1850 } | 2238 } |
| 1851 } | 2239 } |
| 1852 | 2240 |
| 1853 DVLOG(3) << "CreateMfcOutputBuffers(): ProvidePictureBuffers(): " | 2241 return true; |
| 1854 << "buffer_count=" << mfc_output_buffer_map_.size() | 2242 } |
| 1855 << ", width=" << frame_buffer_size_.width() | 2243 |
| 1856 << ", height=" << frame_buffer_size_.height(); | 2244 bool ExynosVideoDecodeAccelerator::CreateGscInputBuffers() { |
| 1857 child_message_loop_proxy_->PostTask(FROM_HERE, | 2245 DVLOG(3) << "CreateGscInputBuffers()"; |
| 1858 base::Bind(&Client::ProvidePictureBuffers, | 2246 DCHECK(decoder_state_ == kInitialized || |
| 1859 client_, | 2247 decoder_state_ == kChangingResolution); |
| 1860 mfc_output_buffer_map_.size(), | 2248 DCHECK(!gsc_input_streamon_); |
| 1861 frame_buffer_size_, | 2249 DCHECK(gsc_input_buffer_map_.empty()); |
| 1862 GL_TEXTURE_EXTERNAL_OES)); | 2250 |
| 2251 struct v4l2_format format; |
| 2252 memset(&format, 0, sizeof(format)); |
| 2253 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 2254 format.fmt.pix_mp.width = frame_buffer_size_.width(); |
| 2255 format.fmt.pix_mp.height = frame_buffer_size_.height(); |
| 2256 format.fmt.pix_mp.pixelformat = mfc_output_buffer_pixelformat_; |
| 2257 format.fmt.pix_mp.plane_fmt[0].sizeimage = mfc_output_buffer_size_[0]; |
| 2258 format.fmt.pix_mp.plane_fmt[1].sizeimage = mfc_output_buffer_size_[1]; |
| 2259 // NV12MT_16X16 is a tiled format for which bytesperline doesn't make too much |
| 2260 // sense. Convention seems to be to assume 8bpp for these tiled formats. |
| 2261 format.fmt.pix_mp.plane_fmt[0].bytesperline = frame_buffer_size_.width(); |
| 2262 format.fmt.pix_mp.plane_fmt[1].bytesperline = frame_buffer_size_.width(); |
| 2263 format.fmt.pix_mp.num_planes = 2; |
| 2264 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_FMT, &format); |
| 2265 |
| 2266 struct v4l2_control control; |
| 2267 memset(&control, 0, sizeof(control)); |
| 2268 control.id = V4L2_CID_ROTATE; |
| 2269 control.value = 0; |
| 2270 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_CTRL, &control); |
| 2271 |
| 2272 memset(&control, 0, sizeof(control)); |
| 2273 control.id = V4L2_CID_HFLIP; |
| 2274 control.value = 0; |
| 2275 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_CTRL, &control); |
| 2276 |
| 2277 memset(&control, 0, sizeof(control)); |
| 2278 control.id = V4L2_CID_VFLIP; |
| 2279 control.value = 0; |
| 2280 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_CTRL, &control); |
| 2281 |
| 2282 memset(&control, 0, sizeof(control)); |
| 2283 control.id = V4L2_CID_GLOBAL_ALPHA; |
| 2284 control.value = 255; |
| 2285 if (HANDLE_EINTR(ioctl(gsc_fd_, VIDIOC_S_CTRL, &control)) != 0) { |
| 2286 memset(&control, 0, sizeof(control)); |
| 2287 control.id = V4L2_CID_ALPHA_COMPONENT; |
| 2288 control.value = 255; |
| 2289 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_CTRL, &control); |
| 2290 } |
| 2291 |
| 2292 struct v4l2_requestbuffers reqbufs; |
| 2293 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 2294 reqbufs.count = kGscInputBufferCount; |
| 2295 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 2296 reqbufs.memory = V4L2_MEMORY_USERPTR; |
| 2297 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_REQBUFS, &reqbufs); |
| 2298 |
| 2299 gsc_input_buffer_map_.resize(reqbufs.count); |
| 2300 for (size_t i = 0; i < gsc_input_buffer_map_.size(); ++i) { |
| 2301 gsc_free_input_buffers_.push_back(i); |
| 2302 gsc_input_buffer_map_[i].mfc_output = -1; |
| 2303 } |
| 1863 | 2304 |
| 1864 return true; | 2305 return true; |
| 1865 } | 2306 } |
| 2307 |
| 2308 bool ExynosVideoDecodeAccelerator::CreateGscOutputBuffers() { |
| 2309 DVLOG(3) << "CreateGscOutputBuffers()"; |
| 2310 DCHECK(decoder_state_ == kInitialized || |
| 2311 decoder_state_ == kChangingResolution); |
| 2312 DCHECK(!gsc_output_streamon_); |
| 2313 DCHECK(gsc_output_buffer_map_.empty()); |
| 2314 |
| 2315 // GSC outputs into the EGLImages we create from the textures we are |
| 2316 // assigned. Assume RGBA8888 format. |
| 2317 struct v4l2_format format; |
| 2318 memset(&format, 0, sizeof(format)); |
| 2319 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 2320 format.fmt.pix_mp.width = frame_buffer_size_.width(); |
| 2321 format.fmt.pix_mp.height = frame_buffer_size_.height(); |
| 2322 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_RGB32; |
| 2323 format.fmt.pix_mp.plane_fmt[0].sizeimage = |
| 2324 frame_buffer_size_.width() * frame_buffer_size_.height() * 4; |
| 2325 format.fmt.pix_mp.plane_fmt[0].bytesperline = frame_buffer_size_.width() * 4; |
| 2326 format.fmt.pix_mp.num_planes = 1; |
| 2327 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_S_FMT, &format); |
| 2328 |
| 2329 struct v4l2_requestbuffers reqbufs; |
| 2330 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 2331 reqbufs.count = mfc_output_dpb_size_ + kDpbOutputBufferExtraCount; |
| 2332 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 2333 reqbufs.memory = V4L2_MEMORY_DMABUF; |
| 2334 IOCTL_OR_ERROR_RETURN_FALSE(gsc_fd_, VIDIOC_REQBUFS, &reqbufs); |
| 2335 |
| 2336 // We don't actually fill in the freelist or the map here. That happens once |
| 2337 // we have actual usable buffers, after AssignPictureBuffers(); |
| 2338 gsc_output_buffer_map_.resize(reqbufs.count); |
| 2339 |
| 2340 DVLOG(3) << "CreateGscOutputBuffers(): ProvidePictureBuffers(): " |
| 2341 << "buffer_count=" << gsc_output_buffer_map_.size() |
| 2342 << ", width=" << frame_buffer_size_.width() |
| 2343 << ", height=" << frame_buffer_size_.height(); |
| 2344 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 2345 &Client::ProvidePictureBuffers, client_, gsc_output_buffer_map_.size(), |
| 2346 gfx::Size(frame_buffer_size_.width(), frame_buffer_size_.height()), |
| 2347 GL_TEXTURE_2D)); |
| 2348 |
| 2349 return true; |
| 2350 } |
| 1866 | 2351 |
| 1867 void ExynosVideoDecodeAccelerator::DestroyMfcInputBuffers() { | 2352 void ExynosVideoDecodeAccelerator::DestroyMfcInputBuffers() { |
| 1868 DVLOG(3) << "DestroyMfcInputBuffers()"; | 2353 DVLOG(3) << "DestroyMfcInputBuffers()"; |
| 1869 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 2354 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 1870 DCHECK(!mfc_input_streamon_); | 2355 DCHECK(!mfc_input_streamon_); |
| 1871 | 2356 |
| 1872 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) { | 2357 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) { |
| 1873 if (mfc_input_buffer_map_[i].address != NULL) { | 2358 if (mfc_input_buffer_map_[i].address != NULL) { |
| 1874 munmap(mfc_input_buffer_map_[i].address, | 2359 munmap(mfc_input_buffer_map_[i].address, |
| 1875 mfc_input_buffer_map_[i].length); | 2360 mfc_input_buffer_map_[i].length); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1886 | 2371 |
| 1887 mfc_input_buffer_map_.clear(); | 2372 mfc_input_buffer_map_.clear(); |
| 1888 mfc_free_input_buffers_.clear(); | 2373 mfc_free_input_buffers_.clear(); |
| 1889 } | 2374 } |
| 1890 | 2375 |
| 1891 void ExynosVideoDecodeAccelerator::DestroyMfcOutputBuffers() { | 2376 void ExynosVideoDecodeAccelerator::DestroyMfcOutputBuffers() { |
| 1892 DVLOG(3) << "DestroyMfcOutputBuffers()"; | 2377 DVLOG(3) << "DestroyMfcOutputBuffers()"; |
| 1893 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 2378 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 1894 DCHECK(!mfc_output_streamon_); | 2379 DCHECK(!mfc_output_streamon_); |
| 1895 | 2380 |
| 1896 if (mfc_output_buffer_map_.size() != 0) { | 2381 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) { |
| 1897 if (!make_context_current_.Run()) { | 2382 if (mfc_output_buffer_map_[i].address[0] != NULL) |
| 1898 DLOG(ERROR) << "DestroyMfcOutputBuffers(): " | 2383 munmap(mfc_output_buffer_map_[i].address[0], |
| 1899 << "could not make context current"; | 2384 mfc_output_buffer_map_[i].length[0]); |
| 1900 } else { | 2385 if (mfc_output_buffer_map_[i].address[1] != NULL) |
| 1901 size_t i = 0; | 2386 munmap(mfc_output_buffer_map_[i].address[1], |
| 1902 do { | 2387 mfc_output_buffer_map_[i].length[1]); |
| 1903 MfcOutputRecord& output_record = mfc_output_buffer_map_[i]; | |
| 1904 for (size_t j = 0; j < arraysize(output_record.fds); ++j) { | |
| 1905 if (output_record.fds[j] != -1) | |
| 1906 HANDLE_EINTR(close(output_record.fds[j])); | |
| 1907 if (output_record.egl_image != EGL_NO_IMAGE_KHR) | |
| 1908 eglDestroyImageKHR(egl_display_, output_record.egl_image); | |
| 1909 if (output_record.egl_sync != EGL_NO_SYNC_KHR) | |
| 1910 eglDestroySyncKHR(egl_display_, output_record.egl_sync); | |
| 1911 } | |
| 1912 DVLOG(1) << "DestroyMfcOutputBuffers(): dismissing PictureBuffer id=" | |
| 1913 << output_record.picture_id; | |
| 1914 child_message_loop_proxy_->PostTask( | |
| 1915 FROM_HERE, | |
| 1916 base::Bind(&Client::DismissPictureBuffer, | |
| 1917 client_, | |
| 1918 output_record.picture_id)); | |
| 1919 i++; | |
| 1920 } while (i < mfc_output_buffer_map_.size()); | |
| 1921 } | |
| 1922 } | 2388 } |
| 1923 | 2389 |
| 1924 struct v4l2_requestbuffers reqbufs; | 2390 struct v4l2_requestbuffers reqbufs; |
| 1925 memset(&reqbufs, 0, sizeof(reqbufs)); | 2391 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 1926 reqbufs.count = 0; | 2392 reqbufs.count = 0; |
| 1927 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 2393 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1928 reqbufs.memory = V4L2_MEMORY_MMAP; | 2394 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 1929 if (ioctl(mfc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0) | 2395 if (ioctl(mfc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0) |
| 1930 DPLOG(ERROR) << "DestroyMfcOutputBuffers() ioctl() failed: VIDIOC_REQBUFS"; | 2396 DPLOG(ERROR) << "DestroyMfcOutputBuffers() ioctl() failed: VIDIOC_REQBUFS"; |
| 1931 | 2397 |
| 1932 mfc_output_buffer_map_.clear(); | 2398 mfc_output_buffer_map_.clear(); |
| 1933 while (!mfc_free_output_buffers_.empty()) | 2399 mfc_free_output_buffers_.clear(); |
| 1934 mfc_free_output_buffers_.pop(); | 2400 } |
| 2401 |
| 2402 void ExynosVideoDecodeAccelerator::DestroyGscInputBuffers() { |
| 2403 DVLOG(3) << "DestroyGscInputBuffers()"; |
| 2404 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 2405 DCHECK(!gsc_input_streamon_); |
| 2406 |
| 2407 struct v4l2_requestbuffers reqbufs; |
| 2408 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 2409 reqbufs.count = 0; |
| 2410 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 2411 reqbufs.memory = V4L2_MEMORY_DMABUF; |
| 2412 if (ioctl(gsc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0) |
| 2413 DPLOG(ERROR) << "DestroyGscInputBuffers(): ioctl() failed: VIDIOC_REQBUFS"; |
| 2414 |
| 2415 gsc_input_buffer_map_.clear(); |
| 2416 gsc_free_input_buffers_.clear(); |
| 2417 } |
| 2418 |
| 2419 void ExynosVideoDecodeAccelerator::DestroyGscOutputBuffers() { |
| 2420 DVLOG(3) << "DestroyGscOutputBuffers()"; |
| 2421 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 2422 DCHECK(!gsc_output_streamon_); |
| 2423 |
| 2424 if (gsc_output_buffer_map_.size() != 0) { |
| 2425 if (!make_context_current_.Run()) |
| 2426 DLOG(ERROR) << "DestroyGscOutputBuffers(): " |
| 2427 << "could not make context current"; |
| 2428 |
| 2429 size_t i = 0; |
| 2430 do { |
| 2431 GscOutputRecord& output_record = gsc_output_buffer_map_[i]; |
| 2432 if (output_record.fd != -1) |
| 2433 HANDLE_EINTR(close(output_record.fd)); |
| 2434 if (output_record.egl_image != EGL_NO_IMAGE_KHR) |
| 2435 eglDestroyImageKHR(egl_display_, output_record.egl_image); |
| 2436 if (output_record.egl_sync != EGL_NO_SYNC_KHR) |
| 2437 eglDestroySyncKHR(egl_display_, output_record.egl_sync); |
| 2438 if (client_) { |
| 2439 DVLOG(1) << "DestroyGscOutputBuffers(): " |
| 2440 << "dismissing PictureBuffer id=" << output_record.picture_id; |
| 2441 client_->DismissPictureBuffer(output_record.picture_id); |
| 2442 } |
| 2443 ++i; |
| 2444 } while (i < gsc_output_buffer_map_.size()); |
| 2445 } |
| 2446 |
| 2447 struct v4l2_requestbuffers reqbufs; |
| 2448 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 2449 reqbufs.count = 0; |
| 2450 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 2451 reqbufs.memory = V4L2_MEMORY_DMABUF; |
| 2452 if (ioctl(gsc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0) |
| 2453 DPLOG(ERROR) << "DestroyGscOutputBuffers(): ioctl() failed: VIDIOC_REQBUFS"; |
| 2454 |
| 2455 gsc_output_buffer_map_.clear(); |
| 2456 gsc_free_output_buffers_.clear(); |
| 1935 } | 2457 } |
| 1936 | 2458 |
| 1937 void ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers() { | 2459 void ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers() { |
| 1938 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 2460 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 1939 DVLOG(3) << "ResolutionChangeDestroyBuffers()"; | 2461 DVLOG(3) << "ResolutionChangeDestroyBuffers()"; |
| 1940 | 2462 |
| 2463 DestroyGscInputBuffers(); |
| 2464 DestroyGscOutputBuffers(); |
| 1941 DestroyMfcOutputBuffers(); | 2465 DestroyMfcOutputBuffers(); |
| 1942 | 2466 |
| 1943 // Finish resolution change on decoder thread. | 2467 // Finish resolution change on decoder thread. |
| 1944 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 2468 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 1945 &ExynosVideoDecodeAccelerator::FinishResolutionChange, | 2469 &ExynosVideoDecodeAccelerator::FinishResolutionChange, |
| 1946 base::Unretained(this))); | 2470 base::Unretained(this))); |
| 1947 } | 2471 } |
| 1948 | 2472 |
| 1949 void ExynosVideoDecodeAccelerator::SendPictureReady() { | 2473 void ExynosVideoDecodeAccelerator::SendPictureReady() { |
| 1950 DVLOG(3) << "SendPictureReady()"; | |
| 1951 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 2474 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1952 bool resetting_or_flushing = | 2475 bool resetting_or_flushing = |
| 1953 (decoder_state_ == kResetting || decoder_flushing_); | 2476 (decoder_state_ == kResetting || decoder_flushing_); |
| 1954 while (pending_picture_ready_.size() > 0) { | 2477 while (pending_picture_ready_.size() > 0) { |
| 1955 bool cleared = pending_picture_ready_.front().cleared; | 2478 bool cleared = pending_picture_ready_.front().cleared; |
| 1956 const media::Picture& picture = pending_picture_ready_.front().picture; | 2479 const media::Picture& picture = pending_picture_ready_.front().picture; |
| 1957 if (cleared && picture_clearing_count_ == 0) { | 2480 if (cleared && picture_clearing_count_ == 0) { |
| 1958 // This picture is cleared. Post it to IO thread to reduce latency. This | 2481 // This picture is cleared. Post it to IO thread to reduce latency. This |
| 1959 // should be the case after all pictures are cleared at the beginning. | 2482 // should be the case after all pictures are cleared at the beginning. |
| 1960 io_message_loop_proxy_->PostTask( | 2483 io_message_loop_proxy_->PostTask( |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1990 | 2513 |
| 1991 void ExynosVideoDecodeAccelerator::PictureCleared() { | 2514 void ExynosVideoDecodeAccelerator::PictureCleared() { |
| 1992 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; | 2515 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; |
| 1993 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 2516 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1994 DCHECK_GT(picture_clearing_count_, 0); | 2517 DCHECK_GT(picture_clearing_count_, 0); |
| 1995 picture_clearing_count_--; | 2518 picture_clearing_count_--; |
| 1996 SendPictureReady(); | 2519 SendPictureReady(); |
| 1997 } | 2520 } |
| 1998 | 2521 |
| 1999 } // namespace content | 2522 } // namespace content |
| OLD | NEW |