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