Chromium Code Reviews| 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 <libdrm/drm_fourcc.h> |
| 9 #include <linux/videodev2.h> | 9 #include <linux/videodev2.h> |
| 10 #include <poll.h> | 10 #include <poll.h> |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 | 26 |
| 27 #define NOTIFY_ERROR(x) \ | 27 #define NOTIFY_ERROR(x) \ |
| 28 do { \ | 28 do { \ |
| 29 SetDecoderState(kError); \ | 29 SetDecoderState(kError); \ |
| 30 DLOG(ERROR) << "calling NotifyError(): " << x; \ | 30 DLOG(ERROR) << "calling NotifyError(): " << x; \ |
| 31 NotifyError(x); \ | 31 NotifyError(x); \ |
| 32 } while (0) | 32 } while (0) |
| 33 | 33 |
| 34 #define IOCTL_OR_ERROR_RETURN(fd, type, arg) \ | 34 #define IOCTL_OR_ERROR_RETURN(fd, type, arg) \ |
| 35 do { \ | 35 do { \ |
| 36 if (HANDLE_EINTR(ioctl(fd, type, arg) != 0)) { \ | 36 if (HANDLE_EINTR(device->dev_ioctl(fd, type, arg) != 0)) { \ |
|
Pawel Osciak
2013/12/24 03:45:24
Please ensure device isn't NULL.
| |
| 37 DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \ | 37 DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \ |
| 38 NOTIFY_ERROR(PLATFORM_FAILURE); \ | 38 NOTIFY_ERROR(PLATFORM_FAILURE); \ |
| 39 return; \ | 39 return; \ |
| 40 } \ | 40 } \ |
| 41 } while (0) | 41 } while (0) |
| 42 | 42 |
| 43 #define IOCTL_OR_ERROR_RETURN_FALSE(fd, type, arg) \ | 43 #define IOCTL_OR_ERROR_RETURN_FALSE(fd, type, arg) \ |
| 44 do { \ | 44 do { \ |
| 45 if (HANDLE_EINTR(ioctl(fd, type, arg) != 0)) { \ | 45 if (HANDLE_EINTR(device->dev_ioctl(fd, type, arg) != 0)) { \ |
| 46 DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \ | 46 DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \ |
| 47 NOTIFY_ERROR(PLATFORM_FAILURE); \ | 47 NOTIFY_ERROR(PLATFORM_FAILURE); \ |
| 48 return false; \ | 48 return false; \ |
| 49 } \ | 49 } \ |
| 50 } while (0) | 50 } while (0) |
| 51 | 51 |
| 52 namespace { | 52 namespace { |
| 53 | 53 |
| 54 // TODO(posciak): remove once we update linux-headers. | 54 // TODO(posciak): remove once we update linux-headers. |
| 55 #ifndef V4L2_EVENT_RESOLUTION_CHANGE | 55 #ifndef V4L2_EVENT_RESOLUTION_CHANGE |
| 56 #define V4L2_EVENT_RESOLUTION_CHANGE 5 | 56 #define V4L2_EVENT_RESOLUTION_CHANGE 5 |
| 57 #endif | 57 #endif |
| 58 | 58 |
| 59 const char kExynosMfcDevice[] = "/dev/mfc-dec"; | 59 const char kExynosMfcDevice[] = "/dev/mfc-dec"; |
|
Pawel Osciak
2013/12/24 03:45:24
This should be a property of the ExynosV4L2Device
| |
| 60 | 60 |
| 61 } // anonymous namespace | 61 } // anonymous namespace |
| 62 | 62 |
| 63 struct ExynosVideoDecodeAccelerator::BitstreamBufferRef { | 63 int V4L2VideoDecodeAccelerator :: ExynosV4L2Device :: dev_open (const char *fd, |
|
Pawel Osciak
2013/12/24 03:45:24
Extract to separate file. Also style (spacing, ind
| |
| 64 int flags) { | |
| 65 return HANDLE_EINTR(open(fd,flags)); | |
| 66 } | |
| 67 | |
| 68 int V4L2VideoDecodeAccelerator :: ExynosV4L2Device :: dev_ioctl (int fd, | |
| 69 int flags, void *arg) { | |
| 70 return ioctl(fd, flags, arg); | |
|
Pawel Osciak
2013/12/24 03:45:24
HANDLE_EINTR?
| |
| 71 } | |
| 72 | |
| 73 int V4L2VideoDecodeAccelerator :: ExynosV4L2Device :: dev_close (int fd) { | |
| 74 return close(fd); | |
| 75 } | |
| 76 | |
| 77 int V4L2VideoDecodeAccelerator :: ExynosV4L2Device :: dev_poll ( | |
| 78 struct pollfd *fds, nfds_t nfds, int n) { | |
| 79 return poll(fds, nfds, n); | |
|
Pawel Osciak
2013/12/24 03:45:24
HANDLE_EINTR?
| |
| 80 } | |
| 81 | |
| 82 void* V4L2VideoDecodeAccelerator :: ExynosV4L2Device :: dev_mmap (void *addr, | |
| 83 unsigned int len, int prot, int flags, int fd, unsigned int offset) { | |
| 84 return mmap(addr, len, prot, flags, fd, offset); | |
| 85 } | |
| 86 | |
| 87 void V4L2VideoDecodeAccelerator :: ExynosV4L2Device :: dev_munmap (void *addr, | |
| 88 unsigned int len) { | |
| 89 munmap(addr,len); | |
| 90 } | |
| 91 | |
| 92 struct V4L2VideoDecodeAccelerator::BitstreamBufferRef { | |
| 64 BitstreamBufferRef( | 93 BitstreamBufferRef( |
| 65 base::WeakPtr<Client>& client, | 94 base::WeakPtr<Client>& client, |
| 66 scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy, | 95 scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy, |
| 67 base::SharedMemory* shm, | 96 base::SharedMemory* shm, |
| 68 size_t size, | 97 size_t size, |
| 69 int32 input_id); | 98 int32 input_id); |
| 70 ~BitstreamBufferRef(); | 99 ~BitstreamBufferRef(); |
| 71 const base::WeakPtr<Client> client; | 100 const base::WeakPtr<Client> client; |
| 72 const scoped_refptr<base::MessageLoopProxy> client_message_loop_proxy; | 101 const scoped_refptr<base::MessageLoopProxy> client_message_loop_proxy; |
| 73 const scoped_ptr<base::SharedMemory> shm; | 102 const scoped_ptr<base::SharedMemory> shm; |
| 74 const size_t size; | 103 const size_t size; |
| 75 off_t bytes_used; | 104 off_t bytes_used; |
| 76 const int32 input_id; | 105 const int32 input_id; |
| 77 }; | 106 }; |
| 78 | 107 |
| 79 struct ExynosVideoDecodeAccelerator::PictureBufferArrayRef { | 108 struct V4L2VideoDecodeAccelerator::PictureBufferArrayRef { |
| 80 PictureBufferArrayRef(EGLDisplay egl_display); | 109 PictureBufferArrayRef(EGLDisplay egl_display); |
| 81 ~PictureBufferArrayRef(); | 110 ~PictureBufferArrayRef(); |
| 82 | 111 |
| 83 struct PictureBufferRef { | 112 struct PictureBufferRef { |
| 84 PictureBufferRef(EGLImageKHR egl_image, int32 picture_id) | 113 PictureBufferRef(EGLImageKHR egl_image, int32 picture_id) |
| 85 : egl_image(egl_image), picture_id(picture_id) {} | 114 : egl_image(egl_image), picture_id(picture_id) {} |
| 86 EGLImageKHR egl_image; | 115 EGLImageKHR egl_image; |
| 87 int32 picture_id; | 116 int32 picture_id; |
| 88 }; | 117 }; |
| 89 | 118 |
| 90 EGLDisplay const egl_display; | 119 EGLDisplay const egl_display; |
| 91 std::vector<PictureBufferRef> picture_buffers; | 120 std::vector<PictureBufferRef> picture_buffers; |
| 92 }; | 121 }; |
| 93 | 122 |
| 94 struct ExynosVideoDecodeAccelerator::EGLSyncKHRRef { | 123 struct V4L2VideoDecodeAccelerator::EGLSyncKHRRef { |
| 95 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); | 124 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); |
| 96 ~EGLSyncKHRRef(); | 125 ~EGLSyncKHRRef(); |
| 97 EGLDisplay const egl_display; | 126 EGLDisplay const egl_display; |
| 98 EGLSyncKHR egl_sync; | 127 EGLSyncKHR egl_sync; |
| 99 }; | 128 }; |
| 100 | 129 |
| 101 struct ExynosVideoDecodeAccelerator::PictureRecord { | 130 struct V4L2VideoDecodeAccelerator::PictureRecord { |
| 102 PictureRecord(bool cleared, const media::Picture& picture); | 131 PictureRecord(bool cleared, const media::Picture& picture); |
| 103 ~PictureRecord(); | 132 ~PictureRecord(); |
| 104 bool cleared; // Whether the texture is cleared and safe to render from. | 133 bool cleared; // Whether the texture is cleared and safe to render from. |
| 105 media::Picture picture; // The decoded picture. | 134 media::Picture picture; // The decoded picture. |
| 106 }; | 135 }; |
| 107 | 136 |
| 108 ExynosVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( | 137 V4L2VideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( |
| 109 base::WeakPtr<Client>& client, | 138 base::WeakPtr<Client>& client, |
| 110 scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy, | 139 scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy, |
| 111 base::SharedMemory* shm, size_t size, int32 input_id) | 140 base::SharedMemory* shm, size_t size, int32 input_id) |
| 112 : client(client), | 141 : client(client), |
| 113 client_message_loop_proxy(client_message_loop_proxy), | 142 client_message_loop_proxy(client_message_loop_proxy), |
| 114 shm(shm), | 143 shm(shm), |
| 115 size(size), | 144 size(size), |
| 116 bytes_used(0), | 145 bytes_used(0), |
| 117 input_id(input_id) { | 146 input_id(input_id) { |
| 118 } | 147 } |
| 119 | 148 |
| 120 ExynosVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { | 149 V4L2VideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { |
| 121 if (input_id >= 0) { | 150 if (input_id >= 0) { |
| 122 client_message_loop_proxy->PostTask(FROM_HERE, base::Bind( | 151 client_message_loop_proxy->PostTask(FROM_HERE, base::Bind( |
| 123 &Client::NotifyEndOfBitstreamBuffer, client, input_id)); | 152 &Client::NotifyEndOfBitstreamBuffer, client, input_id)); |
| 124 } | 153 } |
| 125 } | 154 } |
| 126 | 155 |
| 127 ExynosVideoDecodeAccelerator::PictureBufferArrayRef::PictureBufferArrayRef( | 156 V4L2VideoDecodeAccelerator::PictureBufferArrayRef::PictureBufferArrayRef( |
| 128 EGLDisplay egl_display) | 157 EGLDisplay egl_display) |
| 129 : egl_display(egl_display) {} | 158 : egl_display(egl_display) {} |
| 130 | 159 |
| 131 ExynosVideoDecodeAccelerator::PictureBufferArrayRef::~PictureBufferArrayRef() { | 160 V4L2VideoDecodeAccelerator::PictureBufferArrayRef::~PictureBufferArrayRef() { |
| 132 for (size_t i = 0; i < picture_buffers.size(); ++i) { | 161 for (size_t i = 0; i < picture_buffers.size(); ++i) { |
| 133 EGLImageKHR egl_image = picture_buffers[i].egl_image; | 162 EGLImageKHR egl_image = picture_buffers[i].egl_image; |
| 134 if (egl_image != EGL_NO_IMAGE_KHR) | 163 if (egl_image != EGL_NO_IMAGE_KHR) |
| 135 eglDestroyImageKHR(egl_display, egl_image); | 164 eglDestroyImageKHR(egl_display, egl_image); |
| 136 } | 165 } |
| 137 } | 166 } |
| 138 | 167 |
| 139 ExynosVideoDecodeAccelerator::EGLSyncKHRRef::EGLSyncKHRRef( | 168 V4L2VideoDecodeAccelerator::EGLSyncKHRRef::EGLSyncKHRRef( |
| 140 EGLDisplay egl_display, EGLSyncKHR egl_sync) | 169 EGLDisplay egl_display, EGLSyncKHR egl_sync) |
| 141 : egl_display(egl_display), | 170 : egl_display(egl_display), |
| 142 egl_sync(egl_sync) { | 171 egl_sync(egl_sync) { |
| 143 } | 172 } |
| 144 | 173 |
| 145 ExynosVideoDecodeAccelerator::EGLSyncKHRRef::~EGLSyncKHRRef() { | 174 V4L2VideoDecodeAccelerator::EGLSyncKHRRef::~EGLSyncKHRRef() { |
| 146 if (egl_sync != EGL_NO_SYNC_KHR) | 175 if (egl_sync != EGL_NO_SYNC_KHR) |
| 147 eglDestroySyncKHR(egl_display, egl_sync); | 176 eglDestroySyncKHR(egl_display, egl_sync); |
| 148 } | 177 } |
| 149 | 178 |
| 150 ExynosVideoDecodeAccelerator::MfcInputRecord::MfcInputRecord() | 179 V4L2VideoDecodeAccelerator::MfcInputRecord::MfcInputRecord() |
| 151 : at_device(false), | 180 : at_device(false), |
| 152 address(NULL), | 181 address(NULL), |
| 153 length(0), | 182 length(0), |
| 154 bytes_used(0), | 183 bytes_used(0), |
| 155 input_id(-1) { | 184 input_id(-1) { |
| 156 } | 185 } |
| 157 | 186 |
| 158 ExynosVideoDecodeAccelerator::MfcInputRecord::~MfcInputRecord() { | 187 V4L2VideoDecodeAccelerator::MfcInputRecord::~MfcInputRecord() { |
| 159 } | 188 } |
| 160 | 189 |
| 161 ExynosVideoDecodeAccelerator::MfcOutputRecord::MfcOutputRecord() | 190 V4L2VideoDecodeAccelerator::MfcOutputRecord::MfcOutputRecord() |
| 162 : at_device(false), | 191 : at_device(false), |
| 163 at_client(false), | 192 at_client(false), |
| 164 egl_image(EGL_NO_IMAGE_KHR), | 193 egl_image(EGL_NO_IMAGE_KHR), |
| 165 egl_sync(EGL_NO_SYNC_KHR), | 194 egl_sync(EGL_NO_SYNC_KHR), |
| 166 picture_id(-1), | 195 picture_id(-1), |
| 167 cleared(false) { | 196 cleared(false) { |
| 168 for (size_t i = 0; i < arraysize(fds); ++i) | 197 for (size_t i = 0; i < arraysize(fds); ++i) |
| 169 fds[i] = -1; | 198 fds[i] = -1; |
| 170 } | 199 } |
| 171 | 200 |
| 172 ExynosVideoDecodeAccelerator::MfcOutputRecord::~MfcOutputRecord() {} | 201 V4L2VideoDecodeAccelerator::MfcOutputRecord::~MfcOutputRecord() {} |
| 173 | 202 |
| 174 ExynosVideoDecodeAccelerator::PictureRecord::PictureRecord( | 203 V4L2VideoDecodeAccelerator::PictureRecord::PictureRecord( |
| 175 bool cleared, | 204 bool cleared, |
| 176 const media::Picture& picture) | 205 const media::Picture& picture) |
| 177 : cleared(cleared), picture(picture) {} | 206 : cleared(cleared), picture(picture) {} |
| 178 | 207 |
| 179 ExynosVideoDecodeAccelerator::PictureRecord::~PictureRecord() {} | 208 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {} |
| 180 | 209 |
| 181 ExynosVideoDecodeAccelerator::ExynosVideoDecodeAccelerator( | 210 V4L2VideoDecodeAccelerator::V4L2VideoDecodeAccelerator( |
| 182 EGLDisplay egl_display, | 211 EGLDisplay egl_display, |
| 183 EGLContext egl_context, | |
| 184 Client* client, | 212 Client* client, |
| 185 const base::WeakPtr<Client>& io_client, | 213 const base::WeakPtr<Client>& io_client, |
| 186 const base::Callback<bool(void)>& make_context_current, | 214 const base::Callback<bool(void)>& make_context_current, |
| 187 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy) | 215 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy) |
| 188 : child_message_loop_proxy_(base::MessageLoopProxy::current()), | 216 : child_message_loop_proxy_(base::MessageLoopProxy::current()), |
| 189 io_message_loop_proxy_(io_message_loop_proxy), | 217 io_message_loop_proxy_(io_message_loop_proxy), |
| 190 weak_this_(base::AsWeakPtr(this)), | 218 weak_this_(base::AsWeakPtr(this)), |
| 191 client_ptr_factory_(client), | 219 client_ptr_factory_(client), |
| 192 client_(client_ptr_factory_.GetWeakPtr()), | 220 client_(client_ptr_factory_.GetWeakPtr()), |
| 193 io_client_(io_client), | 221 io_client_(io_client), |
| 194 decoder_thread_("ExynosDecoderThread"), | 222 decoder_thread_("V4L2DecoderThread"), |
| 195 decoder_state_(kUninitialized), | 223 decoder_state_(kUninitialized), |
| 196 decoder_delay_bitstream_buffer_id_(-1), | 224 decoder_delay_bitstream_buffer_id_(-1), |
| 197 decoder_current_input_buffer_(-1), | 225 decoder_current_input_buffer_(-1), |
| 198 decoder_decode_buffer_tasks_scheduled_(0), | 226 decoder_decode_buffer_tasks_scheduled_(0), |
| 199 decoder_frames_at_client_(0), | 227 decoder_frames_at_client_(0), |
| 200 decoder_flushing_(false), | 228 decoder_flushing_(false), |
| 201 resolution_change_pending_(false), | 229 resolution_change_pending_(false), |
| 202 resolution_change_reset_pending_(false), | 230 resolution_change_reset_pending_(false), |
| 203 decoder_partial_frame_pending_(false), | 231 decoder_partial_frame_pending_(false), |
| 204 mfc_fd_(-1), | 232 videodec_fd_(-1), |
| 205 mfc_input_streamon_(false), | 233 mfc_input_streamon_(false), |
| 206 mfc_input_buffer_queued_count_(0), | 234 mfc_input_buffer_queued_count_(0), |
| 207 mfc_output_streamon_(false), | 235 mfc_output_streamon_(false), |
| 208 mfc_output_buffer_queued_count_(0), | 236 mfc_output_buffer_queued_count_(0), |
| 209 mfc_output_buffer_pixelformat_(0), | 237 mfc_output_buffer_pixelformat_(0), |
| 210 mfc_output_dpb_size_(0), | 238 mfc_output_dpb_size_(0), |
| 211 picture_clearing_count_(0), | 239 picture_clearing_count_(0), |
| 212 device_poll_thread_("ExynosDevicePollThread"), | 240 device_poll_thread_("V4L2DevicePollThread"), |
| 213 device_poll_interrupt_fd_(-1), | 241 device_poll_interrupt_fd_(-1), |
| 214 make_context_current_(make_context_current), | 242 make_context_current_(make_context_current), |
| 215 egl_display_(egl_display), | 243 egl_display_(egl_display), |
| 216 egl_context_(egl_context), | |
| 217 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN) {} | 244 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN) {} |
| 218 | 245 |
| 219 ExynosVideoDecodeAccelerator::~ExynosVideoDecodeAccelerator() { | 246 V4L2VideoDecodeAccelerator::~V4L2VideoDecodeAccelerator() { |
| 220 DCHECK(!decoder_thread_.IsRunning()); | 247 DCHECK(!decoder_thread_.IsRunning()); |
| 221 DCHECK(!device_poll_thread_.IsRunning()); | 248 DCHECK(!device_poll_thread_.IsRunning()); |
| 222 | 249 |
| 223 if (device_poll_interrupt_fd_ != -1) { | 250 if (device_poll_interrupt_fd_ != -1) { |
| 224 close(device_poll_interrupt_fd_); | 251 device->dev_close(device_poll_interrupt_fd_); |
|
Pawel Osciak
2013/12/24 03:45:24
What if device has never been allocated (before In
| |
| 225 device_poll_interrupt_fd_ = -1; | 252 device_poll_interrupt_fd_ = -1; |
| 226 } | 253 } |
| 227 if (mfc_fd_ != -1) { | 254 if (videodec_fd_ != -1) { |
| 228 DestroyMfcInputBuffers(); | 255 DestroyMfcInputBuffers(); |
| 229 DestroyMfcOutputBuffers(); | 256 DestroyMfcOutputBuffers(); |
| 230 close(mfc_fd_); | 257 device->dev_close(videodec_fd_); |
| 231 mfc_fd_ = -1; | 258 videodec_fd_ = -1; |
| 232 } | 259 } |
| 233 | 260 |
| 234 // These maps have members that should be manually destroyed, e.g. file | 261 // These maps have members that should be manually destroyed, e.g. file |
| 235 // descriptors, mmap() segments, etc. | 262 // descriptors, mmap() segments, etc. |
| 236 DCHECK(mfc_input_buffer_map_.empty()); | 263 DCHECK(mfc_input_buffer_map_.empty()); |
| 237 DCHECK(mfc_output_buffer_map_.empty()); | 264 DCHECK(mfc_output_buffer_map_.empty()); |
| 238 } | 265 } |
| 239 | 266 |
| 240 bool ExynosVideoDecodeAccelerator::Initialize( | 267 bool V4L2VideoDecodeAccelerator::Initialize( |
| 241 media::VideoCodecProfile profile) { | 268 media::VideoCodecProfile profile) { |
| 242 DVLOG(3) << "Initialize()"; | 269 DVLOG(3) << "Initialize()"; |
| 243 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 270 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 244 DCHECK_EQ(decoder_state_, kUninitialized); | 271 DCHECK_EQ(decoder_state_, kUninitialized); |
| 245 | 272 |
| 246 switch (profile) { | 273 switch (profile) { |
| 247 case media::H264PROFILE_BASELINE: | 274 case media::H264PROFILE_BASELINE: |
| 248 DVLOG(2) << "Initialize(): profile H264PROFILE_BASELINE"; | 275 DVLOG(2) << "Initialize(): profile H264PROFILE_BASELINE"; |
| 249 break; | 276 break; |
| 250 case media::H264PROFILE_MAIN: | 277 case media::H264PROFILE_MAIN: |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 261 return false; | 288 return false; |
| 262 }; | 289 }; |
| 263 video_profile_ = profile; | 290 video_profile_ = profile; |
| 264 | 291 |
| 265 if (egl_display_ == EGL_NO_DISPLAY) { | 292 if (egl_display_ == EGL_NO_DISPLAY) { |
| 266 DLOG(ERROR) << "Initialize(): could not get EGLDisplay"; | 293 DLOG(ERROR) << "Initialize(): could not get EGLDisplay"; |
| 267 NOTIFY_ERROR(PLATFORM_FAILURE); | 294 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 268 return false; | 295 return false; |
| 269 } | 296 } |
| 270 | 297 |
| 271 if (egl_context_ == EGL_NO_CONTEXT) { | |
| 272 DLOG(ERROR) << "Initialize(): could not get EGLContext"; | |
| 273 NOTIFY_ERROR(PLATFORM_FAILURE); | |
| 274 return false; | |
| 275 } | |
| 276 | |
| 277 // We need the context to be initialized to query extensions. | 298 // We need the context to be initialized to query extensions. |
| 278 if (!make_context_current_.Run()) { | 299 if (!make_context_current_.Run()) { |
| 279 DLOG(ERROR) << "Initialize(): could not make context current"; | 300 DLOG(ERROR) << "Initialize(): could not make context current"; |
| 280 NOTIFY_ERROR(PLATFORM_FAILURE); | 301 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 281 return false; | 302 return false; |
| 282 } | 303 } |
| 283 | 304 |
| 284 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) { | 305 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) { |
| 285 DLOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync"; | 306 DLOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync"; |
| 286 NOTIFY_ERROR(PLATFORM_FAILURE); | 307 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 287 return false; | 308 return false; |
| 288 } | 309 } |
| 289 | 310 |
| 290 // Open the video devices. | 311 // Open the video devices. |
| 291 DVLOG(2) << "Initialize(): opening MFC device: " << kExynosMfcDevice; | 312 DVLOG(2) << "Initialize(): opening MFC device: " << kExynosMfcDevice; |
|
Pawel Osciak
2013/12/24 03:45:24
Please scrub Exynos from this class.
| |
| 292 mfc_fd_ = HANDLE_EINTR(open(kExynosMfcDevice, | 313 device = new ExynosV4L2Device; |
|
Pawel Osciak
2013/12/24 03:45:24
I don't see this being freed anywhere.?
In any cas
| |
| 293 O_RDWR | O_NONBLOCK | O_CLOEXEC)); | 314 |
| 294 if (mfc_fd_ == -1) { | 315 videodec_fd_ = device->dev_open(kExynosMfcDevice, |
| 316 O_RDWR | O_NONBLOCK | O_CLOEXEC); | |
| 317 | |
| 318 if (videodec_fd_ == -1) { | |
| 295 DPLOG(ERROR) << "Initialize(): could not open MFC device: " | 319 DPLOG(ERROR) << "Initialize(): could not open MFC device: " |
| 296 << kExynosMfcDevice; | 320 << kExynosMfcDevice; |
| 297 NOTIFY_ERROR(PLATFORM_FAILURE); | 321 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 298 return false; | 322 return false; |
| 299 } | 323 } |
| 300 | 324 |
| 301 // Create the interrupt fd. | 325 // Create the interrupt fd. |
| 302 DCHECK_EQ(device_poll_interrupt_fd_, -1); | 326 DCHECK_EQ(device_poll_interrupt_fd_, -1); |
| 303 device_poll_interrupt_fd_ = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); | 327 device_poll_interrupt_fd_ = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); |
|
Pawel Osciak
2013/12/24 03:45:24
This could be extracted as well I think?
| |
| 304 if (device_poll_interrupt_fd_ == -1) { | 328 if (device_poll_interrupt_fd_ == -1) { |
| 305 DPLOG(ERROR) << "Initialize(): eventfd() failed"; | 329 DPLOG(ERROR) << "Initialize(): eventfd() failed"; |
| 306 NOTIFY_ERROR(PLATFORM_FAILURE); | 330 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 307 return false; | 331 return false; |
| 308 } | 332 } |
| 309 | 333 |
| 310 // Capabilities check. | 334 // Capabilities check. |
| 311 struct v4l2_capability caps; | 335 struct v4l2_capability caps; |
| 312 const __u32 kCapsRequired = | 336 const __u32 kCapsRequired = |
| 313 V4L2_CAP_VIDEO_CAPTURE_MPLANE | | 337 V4L2_CAP_VIDEO_CAPTURE_MPLANE | |
| 314 V4L2_CAP_VIDEO_OUTPUT_MPLANE | | 338 V4L2_CAP_VIDEO_OUTPUT_MPLANE | |
| 315 V4L2_CAP_STREAMING; | 339 V4L2_CAP_STREAMING; |
| 316 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QUERYCAP, &caps); | 340 IOCTL_OR_ERROR_RETURN_FALSE(videodec_fd_, VIDIOC_QUERYCAP, &caps); |
| 317 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { | 341 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { |
| 318 DLOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP" | 342 DLOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP" |
| 319 ", caps check failed: 0x" << std::hex << caps.capabilities; | 343 ", caps check failed: 0x" << std::hex << caps.capabilities; |
| 320 NOTIFY_ERROR(PLATFORM_FAILURE); | 344 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 321 return false; | 345 return false; |
| 322 } | 346 } |
| 323 | 347 |
| 324 if (!CreateMfcInputBuffers()) | 348 if (!CreateMfcInputBuffers()) |
| 325 return false; | 349 return false; |
| 326 | 350 |
| 327 // MFC output format has to be setup before streaming starts. | 351 // MFC output format has to be setup before streaming starts. |
| 328 struct v4l2_format format; | 352 struct v4l2_format format; |
| 329 memset(&format, 0, sizeof(format)); | 353 memset(&format, 0, sizeof(format)); |
| 330 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 354 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 331 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; | 355 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; |
| 332 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_S_FMT, &format); | 356 IOCTL_OR_ERROR_RETURN_FALSE(videodec_fd_, VIDIOC_S_FMT, &format); |
| 333 | 357 |
| 334 // Subscribe to the resolution change event. | 358 // Subscribe to the resolution change event. |
| 335 struct v4l2_event_subscription sub; | 359 struct v4l2_event_subscription sub; |
| 336 memset(&sub, 0, sizeof(sub)); | 360 memset(&sub, 0, sizeof(sub)); |
| 337 sub.type = V4L2_EVENT_RESOLUTION_CHANGE; | 361 sub.type = V4L2_EVENT_RESOLUTION_CHANGE; |
| 338 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_SUBSCRIBE_EVENT, &sub); | 362 IOCTL_OR_ERROR_RETURN_FALSE(videodec_fd_, VIDIOC_SUBSCRIBE_EVENT, &sub); |
| 339 | 363 |
| 340 // Initialize format-specific bits. | 364 // Initialize format-specific bits. |
| 341 if (video_profile_ >= media::H264PROFILE_MIN && | 365 if (video_profile_ >= media::H264PROFILE_MIN && |
| 342 video_profile_ <= media::H264PROFILE_MAX) { | 366 video_profile_ <= media::H264PROFILE_MAX) { |
| 343 decoder_h264_parser_.reset(new content::H264Parser()); | 367 decoder_h264_parser_.reset(new content::H264Parser()); |
| 344 } | 368 } |
| 345 | 369 |
| 346 if (!decoder_thread_.Start()) { | 370 if (!decoder_thread_.Start()) { |
| 347 DLOG(ERROR) << "Initialize(): decoder thread failed to start"; | 371 DLOG(ERROR) << "Initialize(): decoder thread failed to start"; |
| 348 NOTIFY_ERROR(PLATFORM_FAILURE); | 372 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 349 return false; | 373 return false; |
| 350 } | 374 } |
| 351 | 375 |
| 352 SetDecoderState(kInitialized); | 376 SetDecoderState(kInitialized); |
| 353 | 377 |
| 354 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 378 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 355 &Client::NotifyInitializeDone, client_)); | 379 &Client::NotifyInitializeDone, client_)); |
| 356 return true; | 380 return true; |
| 357 } | 381 } |
| 358 | 382 |
| 359 void ExynosVideoDecodeAccelerator::Decode( | 383 void V4L2VideoDecodeAccelerator::Decode( |
| 360 const media::BitstreamBuffer& bitstream_buffer) { | 384 const media::BitstreamBuffer& bitstream_buffer) { |
| 361 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() | 385 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() |
| 362 << ", size=" << bitstream_buffer.size(); | 386 << ", size=" << bitstream_buffer.size(); |
| 363 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 387 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); |
| 364 | 388 |
| 365 // DecodeTask() will take care of running a DecodeBufferTask(). | 389 // DecodeTask() will take care of running a DecodeBufferTask(). |
| 366 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 390 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 367 &ExynosVideoDecodeAccelerator::DecodeTask, base::Unretained(this), | 391 &V4L2VideoDecodeAccelerator::DecodeTask, base::Unretained(this), |
| 368 bitstream_buffer)); | 392 bitstream_buffer)); |
| 369 } | 393 } |
| 370 | 394 |
| 371 void ExynosVideoDecodeAccelerator::AssignPictureBuffers( | 395 void V4L2VideoDecodeAccelerator::AssignPictureBuffers( |
| 372 const std::vector<media::PictureBuffer>& buffers) { | 396 const std::vector<media::PictureBuffer>& buffers) { |
| 373 DVLOG(3) << "AssignPictureBuffers(): buffer_count=" << buffers.size(); | 397 DVLOG(3) << "AssignPictureBuffers(): buffer_count=" << buffers.size(); |
| 374 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 398 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 375 | 399 |
| 376 if (buffers.size() != mfc_output_buffer_map_.size()) { | 400 if (buffers.size() != mfc_output_buffer_map_.size()) { |
| 377 DLOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" | 401 DLOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" |
| 378 " buffers. (Got " << buffers.size() | 402 " buffers. (Got " << buffers.size() |
| 379 << ", requested " << mfc_output_buffer_map_.size() << ")"; | 403 << ", requested " << mfc_output_buffer_map_.size() << ")"; |
| 380 NOTIFY_ERROR(INVALID_ARGUMENT); | 404 NOTIFY_ERROR(INVALID_ARGUMENT); |
| 381 return; | 405 return; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 416 return; | 440 return; |
| 417 } | 441 } |
| 418 | 442 |
| 419 glBindTexture(GL_TEXTURE_EXTERNAL_OES, buffers[i].texture_id()); | 443 glBindTexture(GL_TEXTURE_EXTERNAL_OES, buffers[i].texture_id()); |
| 420 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image); | 444 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image); |
| 421 picture_buffers_ref->picture_buffers.push_back( | 445 picture_buffers_ref->picture_buffers.push_back( |
| 422 PictureBufferArrayRef::PictureBufferRef(egl_image, buffers[i].id())); | 446 PictureBufferArrayRef::PictureBufferRef(egl_image, buffers[i].id())); |
| 423 } | 447 } |
| 424 decoder_thread_.message_loop()->PostTask( | 448 decoder_thread_.message_loop()->PostTask( |
| 425 FROM_HERE, | 449 FROM_HERE, |
| 426 base::Bind(&ExynosVideoDecodeAccelerator::AssignPictureBuffersTask, | 450 base::Bind(&V4L2VideoDecodeAccelerator::AssignPictureBuffersTask, |
| 427 base::Unretained(this), | 451 base::Unretained(this), |
| 428 base::Passed(&picture_buffers_ref))); | 452 base::Passed(&picture_buffers_ref))); |
| 429 } | 453 } |
| 430 | 454 |
| 431 void ExynosVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { | 455 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { |
| 432 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; | 456 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; |
| 433 // Must be run on child thread, as we'll insert a sync in the EGL context. | 457 // Must be run on child thread, as we'll insert a sync in the EGL context. |
| 434 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 458 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 435 | 459 |
| 436 if (!make_context_current_.Run()) { | 460 if (!make_context_current_.Run()) { |
| 437 DLOG(ERROR) << "ReusePictureBuffer(): could not make context current"; | 461 DLOG(ERROR) << "ReusePictureBuffer(): could not make context current"; |
| 438 NOTIFY_ERROR(PLATFORM_FAILURE); | 462 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 439 return; | 463 return; |
| 440 } | 464 } |
| 441 | 465 |
| 442 EGLSyncKHR egl_sync = | 466 EGLSyncKHR egl_sync = |
| 443 eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); | 467 eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); |
| 444 if (egl_sync == EGL_NO_SYNC_KHR) { | 468 if (egl_sync == EGL_NO_SYNC_KHR) { |
| 445 DLOG(ERROR) << "ReusePictureBuffer(): eglCreateSyncKHR() failed"; | 469 DLOG(ERROR) << "ReusePictureBuffer(): eglCreateSyncKHR() failed"; |
| 446 NOTIFY_ERROR(PLATFORM_FAILURE); | 470 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 447 return; | 471 return; |
| 448 } | 472 } |
| 449 | 473 |
| 450 scoped_ptr<EGLSyncKHRRef> egl_sync_ref(new EGLSyncKHRRef( | 474 scoped_ptr<EGLSyncKHRRef> egl_sync_ref(new EGLSyncKHRRef( |
| 451 egl_display_, egl_sync)); | 475 egl_display_, egl_sync)); |
| 452 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 476 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 453 &ExynosVideoDecodeAccelerator::ReusePictureBufferTask, | 477 &V4L2VideoDecodeAccelerator::ReusePictureBufferTask, |
| 454 base::Unretained(this), picture_buffer_id, base::Passed(&egl_sync_ref))); | 478 base::Unretained(this), picture_buffer_id, base::Passed(&egl_sync_ref))); |
| 455 } | 479 } |
| 456 | 480 |
| 457 void ExynosVideoDecodeAccelerator::Flush() { | 481 void V4L2VideoDecodeAccelerator::Flush() { |
| 458 DVLOG(3) << "Flush()"; | 482 DVLOG(3) << "Flush()"; |
| 459 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 483 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 460 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 484 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 461 &ExynosVideoDecodeAccelerator::FlushTask, base::Unretained(this))); | 485 &V4L2VideoDecodeAccelerator::FlushTask, base::Unretained(this))); |
| 462 } | 486 } |
| 463 | 487 |
| 464 void ExynosVideoDecodeAccelerator::Reset() { | 488 void V4L2VideoDecodeAccelerator::Reset() { |
| 465 DVLOG(3) << "Reset()"; | 489 DVLOG(3) << "Reset()"; |
| 466 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 490 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 467 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 491 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 468 &ExynosVideoDecodeAccelerator::ResetTask, base::Unretained(this))); | 492 &V4L2VideoDecodeAccelerator::ResetTask, base::Unretained(this))); |
| 469 } | 493 } |
| 470 | 494 |
| 471 void ExynosVideoDecodeAccelerator::Destroy() { | 495 void V4L2VideoDecodeAccelerator::Destroy() { |
| 472 DVLOG(3) << "Destroy()"; | 496 DVLOG(3) << "Destroy()"; |
| 473 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 497 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 474 | 498 |
| 475 // We're destroying; cancel all callbacks. | 499 // We're destroying; cancel all callbacks. |
| 476 client_ptr_factory_.InvalidateWeakPtrs(); | 500 client_ptr_factory_.InvalidateWeakPtrs(); |
| 477 | 501 |
| 478 // If the decoder thread is running, destroy using posted task. | 502 // If the decoder thread is running, destroy using posted task. |
| 479 if (decoder_thread_.IsRunning()) { | 503 if (decoder_thread_.IsRunning()) { |
| 480 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 504 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 481 &ExynosVideoDecodeAccelerator::DestroyTask, base::Unretained(this))); | 505 &V4L2VideoDecodeAccelerator::DestroyTask, base::Unretained(this))); |
| 482 // DestroyTask() will cause the decoder_thread_ to flush all tasks. | 506 // DestroyTask() will cause the decoder_thread_ to flush all tasks. |
| 483 decoder_thread_.Stop(); | 507 decoder_thread_.Stop(); |
| 484 } else { | 508 } else { |
| 485 // Otherwise, call the destroy task directly. | 509 // Otherwise, call the destroy task directly. |
| 486 DestroyTask(); | 510 DestroyTask(); |
| 487 } | 511 } |
| 488 | 512 |
| 489 // Set to kError state just in case. | 513 // Set to kError state just in case. |
| 490 SetDecoderState(kError); | 514 SetDecoderState(kError); |
| 491 | 515 |
| 492 delete this; | 516 delete this; |
| 493 } | 517 } |
| 494 | 518 |
| 495 bool ExynosVideoDecodeAccelerator::CanDecodeOnIOThread() { return true; } | 519 bool V4L2VideoDecodeAccelerator::CanDecodeOnIOThread() { return true; } |
| 496 | 520 |
| 497 void ExynosVideoDecodeAccelerator::DecodeTask( | 521 void V4L2VideoDecodeAccelerator::DecodeTask( |
| 498 const media::BitstreamBuffer& bitstream_buffer) { | 522 const media::BitstreamBuffer& bitstream_buffer) { |
| 499 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); | 523 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); |
| 500 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 524 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 501 DCHECK_NE(decoder_state_, kUninitialized); | 525 DCHECK_NE(decoder_state_, kUninitialized); |
| 502 TRACE_EVENT1("Video Decoder", "EVDA::DecodeTask", "input_id", | 526 TRACE_EVENT1("Video Decoder", "EVDA::DecodeTask", "input_id", |
| 503 bitstream_buffer.id()); | 527 bitstream_buffer.id()); |
| 504 | 528 |
| 505 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( | 529 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( |
| 506 io_client_, io_message_loop_proxy_, | 530 io_client_, io_message_loop_proxy_, |
| 507 new base::SharedMemory(bitstream_buffer.handle(), true), | 531 new base::SharedMemory(bitstream_buffer.handle(), true), |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 525 DVLOG(2) << "DecodeTask(): early out: kError state"; | 549 DVLOG(2) << "DecodeTask(): early out: kError state"; |
| 526 return; | 550 return; |
| 527 } | 551 } |
| 528 | 552 |
| 529 decoder_input_queue_.push( | 553 decoder_input_queue_.push( |
| 530 linked_ptr<BitstreamBufferRef>(bitstream_record.release())); | 554 linked_ptr<BitstreamBufferRef>(bitstream_record.release())); |
| 531 decoder_decode_buffer_tasks_scheduled_++; | 555 decoder_decode_buffer_tasks_scheduled_++; |
| 532 DecodeBufferTask(); | 556 DecodeBufferTask(); |
| 533 } | 557 } |
| 534 | 558 |
| 535 void ExynosVideoDecodeAccelerator::DecodeBufferTask() { | 559 void V4L2VideoDecodeAccelerator::DecodeBufferTask() { |
| 536 DVLOG(3) << "DecodeBufferTask()"; | 560 DVLOG(3) << "DecodeBufferTask()"; |
| 537 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 561 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 538 DCHECK_NE(decoder_state_, kUninitialized); | 562 DCHECK_NE(decoder_state_, kUninitialized); |
| 539 TRACE_EVENT0("Video Decoder", "EVDA::DecodeBufferTask"); | 563 TRACE_EVENT0("Video Decoder", "EVDA::DecodeBufferTask"); |
| 540 | 564 |
| 541 decoder_decode_buffer_tasks_scheduled_--; | 565 decoder_decode_buffer_tasks_scheduled_--; |
| 542 | 566 |
| 543 if (decoder_state_ == kResetting) { | 567 if (decoder_state_ == kResetting) { |
| 544 DVLOG(2) << "DecodeBufferTask(): early out: kResetting state"; | 568 DVLOG(2) << "DecodeBufferTask(): early out: kResetting state"; |
| 545 return; | 569 return; |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 646 // Our current bitstream buffer is done; return it. | 670 // Our current bitstream buffer is done; return it. |
| 647 int32 input_id = decoder_current_bitstream_buffer_->input_id; | 671 int32 input_id = decoder_current_bitstream_buffer_->input_id; |
| 648 DVLOG(3) << "DecodeBufferTask(): finished input_id=" << input_id; | 672 DVLOG(3) << "DecodeBufferTask(): finished input_id=" << input_id; |
| 649 // BitstreamBufferRef destructor calls NotifyEndOfBitstreamBuffer(). | 673 // BitstreamBufferRef destructor calls NotifyEndOfBitstreamBuffer(). |
| 650 decoder_current_bitstream_buffer_.reset(); | 674 decoder_current_bitstream_buffer_.reset(); |
| 651 } | 675 } |
| 652 ScheduleDecodeBufferTaskIfNeeded(); | 676 ScheduleDecodeBufferTaskIfNeeded(); |
| 653 } | 677 } |
| 654 } | 678 } |
| 655 | 679 |
| 656 bool ExynosVideoDecodeAccelerator::AdvanceFrameFragment( | 680 bool V4L2VideoDecodeAccelerator::AdvanceFrameFragment( |
| 657 const uint8* data, | 681 const uint8* data, |
| 658 size_t size, | 682 size_t size, |
| 659 size_t* endpos) { | 683 size_t* endpos) { |
| 660 if (video_profile_ >= media::H264PROFILE_MIN && | 684 if (video_profile_ >= media::H264PROFILE_MIN && |
| 661 video_profile_ <= media::H264PROFILE_MAX) { | 685 video_profile_ <= media::H264PROFILE_MAX) { |
| 662 // For H264, we need to feed HW one frame at a time. This is going to take | 686 // For H264, we need to feed HW one frame at a time. This is going to take |
| 663 // some parsing of our input stream. | 687 // some parsing of our input stream. |
| 664 decoder_h264_parser_->SetStream(data, size); | 688 decoder_h264_parser_->SetStream(data, size); |
| 665 content::H264NALU nalu; | 689 content::H264NALU nalu; |
| 666 content::H264Parser::Result result; | 690 content::H264Parser::Result result; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 726 DCHECK_GE(video_profile_, media::VP8PROFILE_MIN); | 750 DCHECK_GE(video_profile_, media::VP8PROFILE_MIN); |
| 727 DCHECK_LE(video_profile_, media::VP8PROFILE_MAX); | 751 DCHECK_LE(video_profile_, media::VP8PROFILE_MAX); |
| 728 // For VP8, we can just dump the entire buffer. No fragmentation needed, | 752 // For VP8, we can just dump the entire buffer. No fragmentation needed, |
| 729 // and we never return a partial frame. | 753 // and we never return a partial frame. |
| 730 *endpos = size; | 754 *endpos = size; |
| 731 decoder_partial_frame_pending_ = false; | 755 decoder_partial_frame_pending_ = false; |
| 732 return true; | 756 return true; |
| 733 } | 757 } |
| 734 } | 758 } |
| 735 | 759 |
| 736 void ExynosVideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() { | 760 void V4L2VideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() { |
| 737 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 761 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 738 | 762 |
| 739 // If we're behind on tasks, schedule another one. | 763 // If we're behind on tasks, schedule another one. |
| 740 int buffers_to_decode = decoder_input_queue_.size(); | 764 int buffers_to_decode = decoder_input_queue_.size(); |
| 741 if (decoder_current_bitstream_buffer_ != NULL) | 765 if (decoder_current_bitstream_buffer_ != NULL) |
| 742 buffers_to_decode++; | 766 buffers_to_decode++; |
| 743 if (decoder_decode_buffer_tasks_scheduled_ < buffers_to_decode) { | 767 if (decoder_decode_buffer_tasks_scheduled_ < buffers_to_decode) { |
| 744 decoder_decode_buffer_tasks_scheduled_++; | 768 decoder_decode_buffer_tasks_scheduled_++; |
| 745 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 769 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 746 &ExynosVideoDecodeAccelerator::DecodeBufferTask, | 770 &V4L2VideoDecodeAccelerator::DecodeBufferTask, |
| 747 base::Unretained(this))); | 771 base::Unretained(this))); |
| 748 } | 772 } |
| 749 } | 773 } |
| 750 | 774 |
| 751 bool ExynosVideoDecodeAccelerator::DecodeBufferInitial( | 775 bool V4L2VideoDecodeAccelerator::DecodeBufferInitial( |
| 752 const void* data, size_t size, size_t* endpos) { | 776 const void* data, size_t size, size_t* endpos) { |
| 753 DVLOG(3) << "DecodeBufferInitial(): data=" << data << ", size=" << size; | 777 DVLOG(3) << "DecodeBufferInitial(): data=" << data << ", size=" << size; |
| 754 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 778 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 755 DCHECK_NE(decoder_state_, kUninitialized); | 779 DCHECK_NE(decoder_state_, kUninitialized); |
| 756 DCHECK_NE(decoder_state_, kDecoding); | 780 DCHECK_NE(decoder_state_, kDecoding); |
| 757 DCHECK(!device_poll_thread_.IsRunning()); | 781 DCHECK(!device_poll_thread_.IsRunning()); |
| 758 // Initial decode. We haven't been able to get output stream format info yet. | 782 // Initial decode. We haven't been able to get output stream format info yet. |
| 759 // Get it, and start decoding. | 783 // Get it, and start decoding. |
| 760 | 784 |
| 761 // Copy in and send to HW. | 785 // Copy in and send to HW. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 802 | 826 |
| 803 // StartDevicePoll will raise the error if there is one. | 827 // StartDevicePoll will raise the error if there is one. |
| 804 if (!StartDevicePoll()) | 828 if (!StartDevicePoll()) |
| 805 return false; | 829 return false; |
| 806 | 830 |
| 807 decoder_state_ = kDecoding; | 831 decoder_state_ = kDecoding; |
| 808 ScheduleDecodeBufferTaskIfNeeded(); | 832 ScheduleDecodeBufferTaskIfNeeded(); |
| 809 return true; | 833 return true; |
| 810 } | 834 } |
| 811 | 835 |
| 812 bool ExynosVideoDecodeAccelerator::DecodeBufferContinue( | 836 bool V4L2VideoDecodeAccelerator::DecodeBufferContinue( |
| 813 const void* data, size_t size) { | 837 const void* data, size_t size) { |
| 814 DVLOG(3) << "DecodeBufferContinue(): data=" << data << ", size=" << size; | 838 DVLOG(3) << "DecodeBufferContinue(): data=" << data << ", size=" << size; |
| 815 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 839 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 816 DCHECK_EQ(decoder_state_, kDecoding); | 840 DCHECK_EQ(decoder_state_, kDecoding); |
| 817 | 841 |
| 818 // Both of these calls will set kError state if they fail. | 842 // Both of these calls will set kError state if they fail. |
| 819 // Only flush the frame if it's complete. | 843 // Only flush the frame if it's complete. |
| 820 return (AppendToInputFrame(data, size) && | 844 return (AppendToInputFrame(data, size) && |
| 821 (decoder_partial_frame_pending_ || FlushInputFrame())); | 845 (decoder_partial_frame_pending_ || FlushInputFrame())); |
| 822 } | 846 } |
| 823 | 847 |
| 824 bool ExynosVideoDecodeAccelerator::AppendToInputFrame( | 848 bool V4L2VideoDecodeAccelerator::AppendToInputFrame( |
| 825 const void* data, size_t size) { | 849 const void* data, size_t size) { |
| 826 DVLOG(3) << "AppendToInputFrame()"; | 850 DVLOG(3) << "AppendToInputFrame()"; |
| 827 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 851 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 828 DCHECK_NE(decoder_state_, kUninitialized); | 852 DCHECK_NE(decoder_state_, kUninitialized); |
| 829 DCHECK_NE(decoder_state_, kResetting); | 853 DCHECK_NE(decoder_state_, kResetting); |
| 830 DCHECK_NE(decoder_state_, kError); | 854 DCHECK_NE(decoder_state_, kError); |
| 831 // This routine can handle data == NULL and size == 0, which occurs when | 855 // This routine can handle data == NULL and size == 0, which occurs when |
| 832 // we queue an empty buffer for the purposes of flushing the pipe. | 856 // we queue an empty buffer for the purposes of flushing the pipe. |
| 833 | 857 |
| 834 // Flush if we're too big | 858 // Flush if we're too big |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 881 } | 905 } |
| 882 memcpy( | 906 memcpy( |
| 883 reinterpret_cast<uint8*>(input_record.address) + input_record.bytes_used, | 907 reinterpret_cast<uint8*>(input_record.address) + input_record.bytes_used, |
| 884 data, | 908 data, |
| 885 size); | 909 size); |
| 886 input_record.bytes_used += size; | 910 input_record.bytes_used += size; |
| 887 | 911 |
| 888 return true; | 912 return true; |
| 889 } | 913 } |
| 890 | 914 |
| 891 bool ExynosVideoDecodeAccelerator::FlushInputFrame() { | 915 bool V4L2VideoDecodeAccelerator::FlushInputFrame() { |
| 892 DVLOG(3) << "FlushInputFrame()"; | 916 DVLOG(3) << "FlushInputFrame()"; |
| 893 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 917 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 894 DCHECK_NE(decoder_state_, kUninitialized); | 918 DCHECK_NE(decoder_state_, kUninitialized); |
| 895 DCHECK_NE(decoder_state_, kResetting); | 919 DCHECK_NE(decoder_state_, kResetting); |
| 896 DCHECK_NE(decoder_state_, kError); | 920 DCHECK_NE(decoder_state_, kError); |
| 897 | 921 |
| 898 if (decoder_current_input_buffer_ == -1) | 922 if (decoder_current_input_buffer_ == -1) |
| 899 return true; | 923 return true; |
| 900 | 924 |
| 901 MfcInputRecord& input_record = | 925 MfcInputRecord& input_record = |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 919 mfc_input_ready_queue_.push(decoder_current_input_buffer_); | 943 mfc_input_ready_queue_.push(decoder_current_input_buffer_); |
| 920 decoder_current_input_buffer_ = -1; | 944 decoder_current_input_buffer_ = -1; |
| 921 DVLOG(3) << "FlushInputFrame(): submitting input_id=" | 945 DVLOG(3) << "FlushInputFrame(): submitting input_id=" |
| 922 << input_record.input_id; | 946 << input_record.input_id; |
| 923 // Kick the MFC once since there's new available input for it. | 947 // Kick the MFC once since there's new available input for it. |
| 924 EnqueueMfc(); | 948 EnqueueMfc(); |
| 925 | 949 |
| 926 return (decoder_state_ != kError); | 950 return (decoder_state_ != kError); |
| 927 } | 951 } |
| 928 | 952 |
| 929 void ExynosVideoDecodeAccelerator::AssignPictureBuffersTask( | 953 void V4L2VideoDecodeAccelerator::AssignPictureBuffersTask( |
| 930 scoped_ptr<PictureBufferArrayRef> pic_buffers) { | 954 scoped_ptr<PictureBufferArrayRef> pic_buffers) { |
| 931 DVLOG(3) << "AssignPictureBuffersTask()"; | 955 DVLOG(3) << "AssignPictureBuffersTask()"; |
| 932 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 956 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 933 DCHECK_NE(decoder_state_, kUninitialized); | 957 DCHECK_NE(decoder_state_, kUninitialized); |
| 934 TRACE_EVENT0("Video Decoder", "EVDA::AssignPictureBuffersTask"); | 958 TRACE_EVENT0("Video Decoder", "EVDA::AssignPictureBuffersTask"); |
| 935 | 959 |
| 936 // We run AssignPictureBuffersTask even if we're in kResetting. | 960 // We run AssignPictureBuffersTask even if we're in kResetting. |
| 937 if (decoder_state_ == kError) { | 961 if (decoder_state_ == kError) { |
| 938 DVLOG(2) << "AssignPictureBuffersTask(): early out: kError state"; | 962 DVLOG(2) << "AssignPictureBuffersTask(): early out: kError state"; |
| 939 return; | 963 return; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 959 } | 983 } |
| 960 pic_buffers->picture_buffers.clear(); | 984 pic_buffers->picture_buffers.clear(); |
| 961 | 985 |
| 962 // We got buffers! Kick the MFC. | 986 // We got buffers! Kick the MFC. |
| 963 EnqueueMfc(); | 987 EnqueueMfc(); |
| 964 | 988 |
| 965 if (decoder_state_ == kChangingResolution) | 989 if (decoder_state_ == kChangingResolution) |
| 966 ResumeAfterResolutionChange(); | 990 ResumeAfterResolutionChange(); |
| 967 } | 991 } |
| 968 | 992 |
| 969 void ExynosVideoDecodeAccelerator::ServiceDeviceTask(bool mfc_event_pending) { | 993 void V4L2VideoDecodeAccelerator::ServiceDeviceTask(bool mfc_event_pending) { |
| 970 DVLOG(3) << "ServiceDeviceTask()"; | 994 DVLOG(3) << "ServiceDeviceTask()"; |
| 971 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 995 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 972 DCHECK_NE(decoder_state_, kUninitialized); | 996 DCHECK_NE(decoder_state_, kUninitialized); |
| 973 DCHECK_NE(decoder_state_, kInitialized); | 997 DCHECK_NE(decoder_state_, kInitialized); |
| 974 DCHECK_NE(decoder_state_, kAfterReset); | 998 DCHECK_NE(decoder_state_, kAfterReset); |
| 975 TRACE_EVENT0("Video Decoder", "EVDA::ServiceDeviceTask"); | 999 TRACE_EVENT0("Video Decoder", "EVDA::ServiceDeviceTask"); |
| 976 | 1000 |
| 977 if (decoder_state_ == kResetting) { | 1001 if (decoder_state_ == kResetting) { |
| 978 DVLOG(2) << "ServiceDeviceTask(): early out: kResetting state"; | 1002 DVLOG(2) << "ServiceDeviceTask(): early out: kResetting state"; |
| 979 return; | 1003 return; |
| 980 } else if (decoder_state_ == kError) { | 1004 } else if (decoder_state_ == kError) { |
| 981 DVLOG(2) << "ServiceDeviceTask(): early out: kError state"; | 1005 DVLOG(2) << "ServiceDeviceTask(): early out: kError state"; |
| 982 return; | 1006 return; |
| 983 } else if (decoder_state_ == kChangingResolution) { | 1007 } else if (decoder_state_ == kChangingResolution) { |
| 984 DVLOG(2) << "ServiceDeviceTask(): early out: kChangingResolution state"; | 1008 DVLOG(2) << "ServiceDeviceTask(): early out: kChangingResolution state"; |
| 985 return; | 1009 return; |
| 986 } | 1010 } |
| 987 | 1011 |
| 988 if (mfc_event_pending) | 1012 if (mfc_event_pending) |
| 989 DequeueMfcEvents(); | 1013 DequeueMfcEvents(); |
| 990 DequeueMfc(); | 1014 DequeueMfc(); |
| 991 EnqueueMfc(); | 1015 EnqueueMfc(); |
| 992 | 1016 |
| 993 // Clear the interrupt fd. | 1017 // Clear the interrupt fd. |
| 994 if (!ClearDevicePollInterrupt()) | 1018 if (!device->ClearDevicePollInterrupt(device_poll_interrupt_fd_)) { |
| 1019 NOTIFY_ERROR(PLATFORM_FAILURE); | |
| 995 return; | 1020 return; |
| 1021 } | |
| 996 | 1022 |
| 997 unsigned int poll_fds = 0; | 1023 unsigned int poll_fds = 0; |
| 998 // Add MFC fd, if we should poll on it. | 1024 // Add MFC fd, if we should poll on it. |
| 999 // MFC can be polled as soon as either input or output buffers are queued. | 1025 // MFC can be polled as soon as either input or output buffers are queued. |
| 1000 if (mfc_input_buffer_queued_count_ + mfc_output_buffer_queued_count_ > 0) | 1026 if (mfc_input_buffer_queued_count_ + mfc_output_buffer_queued_count_ > 0) |
| 1001 poll_fds |= kPollMfc; | 1027 poll_fds |= kPollMfc; |
| 1002 | 1028 |
| 1003 // ServiceDeviceTask() should only ever be scheduled from DevicePollTask(), | 1029 // ServiceDeviceTask() should only ever be scheduled from DevicePollTask(), |
| 1004 // so either: | 1030 // so either: |
| 1005 // * device_poll_thread_ is running normally | 1031 // * device_poll_thread_ is running normally |
| 1006 // * device_poll_thread_ scheduled us, but then a ResetTask() or DestroyTask() | 1032 // * device_poll_thread_ scheduled us, but then a ResetTask() or DestroyTask() |
| 1007 // shut it down, in which case we're either in kResetting or kError states | 1033 // shut it down, in which case we're either in kResetting or kError states |
| 1008 // respectively, and we should have early-outed already. | 1034 // respectively, and we should have early-outed already. |
| 1009 DCHECK(device_poll_thread_.message_loop()); | 1035 DCHECK(device_poll_thread_.message_loop()); |
| 1010 // Queue the DevicePollTask() now. | 1036 // Queue the DevicePollTask() now. |
| 1011 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1037 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 1012 &ExynosVideoDecodeAccelerator::DevicePollTask, | 1038 &V4L2VideoDecodeAccelerator::DevicePollTask, |
| 1013 base::Unretained(this), | 1039 base::Unretained(this), |
| 1014 poll_fds)); | 1040 poll_fds)); |
| 1015 | 1041 |
| 1016 DVLOG(1) << "ServiceDeviceTask(): buffer counts: DEC[" | 1042 DVLOG(1) << "ServiceDeviceTask(): buffer counts: DEC[" |
| 1017 << decoder_input_queue_.size() << "->" | 1043 << decoder_input_queue_.size() << "->" |
| 1018 << mfc_input_ready_queue_.size() << "] => MFC[" | 1044 << mfc_input_ready_queue_.size() << "] => MFC[" |
| 1019 << mfc_free_input_buffers_.size() << "+" | 1045 << mfc_free_input_buffers_.size() << "+" |
| 1020 << mfc_input_buffer_queued_count_ << "/" | 1046 << mfc_input_buffer_queued_count_ << "/" |
| 1021 << mfc_input_buffer_map_.size() << "->" | 1047 << mfc_input_buffer_map_.size() << "->" |
| 1022 << mfc_free_output_buffers_.size() << "+" | 1048 << mfc_free_output_buffers_.size() << "+" |
| 1023 << mfc_output_buffer_queued_count_ << "/" | 1049 << mfc_output_buffer_queued_count_ << "/" |
| 1024 << mfc_output_buffer_map_.size() << "] => VDA[" | 1050 << mfc_output_buffer_map_.size() << "] => VDA[" |
| 1025 << decoder_frames_at_client_ << "]"; | 1051 << decoder_frames_at_client_ << "]"; |
| 1026 | 1052 |
| 1027 ScheduleDecodeBufferTaskIfNeeded(); | 1053 ScheduleDecodeBufferTaskIfNeeded(); |
| 1028 StartResolutionChangeIfNeeded(); | 1054 StartResolutionChangeIfNeeded(); |
| 1029 } | 1055 } |
| 1030 | 1056 |
| 1031 void ExynosVideoDecodeAccelerator::EnqueueMfc() { | 1057 void V4L2VideoDecodeAccelerator::EnqueueMfc() { |
| 1032 DVLOG(3) << "EnqueueMfc()"; | 1058 DVLOG(3) << "EnqueueMfc()"; |
| 1033 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1059 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1034 DCHECK_NE(decoder_state_, kUninitialized); | 1060 DCHECK_NE(decoder_state_, kUninitialized); |
| 1035 TRACE_EVENT0("Video Decoder", "EVDA::EnqueueMfc"); | 1061 TRACE_EVENT0("Video Decoder", "EVDA::EnqueueMfc"); |
| 1036 | 1062 |
| 1037 // Drain the pipe of completed decode buffers. | 1063 // Drain the pipe of completed decode buffers. |
| 1038 const int old_mfc_inputs_queued = mfc_input_buffer_queued_count_; | 1064 const int old_mfc_inputs_queued = mfc_input_buffer_queued_count_; |
| 1039 while (!mfc_input_ready_queue_.empty()) { | 1065 while (!mfc_input_ready_queue_.empty()) { |
| 1040 if (!EnqueueMfcInputRecord()) | 1066 if (!EnqueueMfcInputRecord()) |
| 1041 return; | 1067 return; |
| 1042 } | 1068 } |
| 1043 if (old_mfc_inputs_queued == 0 && mfc_input_buffer_queued_count_ != 0) { | 1069 if (old_mfc_inputs_queued == 0 && mfc_input_buffer_queued_count_ != 0) { |
| 1044 // We just started up a previously empty queue. | 1070 // We just started up a previously empty queue. |
| 1045 // Queue state changed; signal interrupt. | 1071 // Queue state changed; signal interrupt. |
| 1046 if (!SetDevicePollInterrupt()) | 1072 if (!device->SetDevicePollInterrupt(device_poll_interrupt_fd_)) { |
| 1073 NOTIFY_ERROR(PLATFORM_FAILURE); | |
| 1047 return; | 1074 return; |
| 1075 } | |
| 1048 // Start VIDIOC_STREAMON if we haven't yet. | 1076 // Start VIDIOC_STREAMON if we haven't yet. |
| 1049 if (!mfc_input_streamon_) { | 1077 if (!mfc_input_streamon_) { |
| 1050 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1078 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1051 IOCTL_OR_ERROR_RETURN(mfc_fd_, VIDIOC_STREAMON, &type); | 1079 IOCTL_OR_ERROR_RETURN(videodec_fd_, VIDIOC_STREAMON, &type); |
| 1052 mfc_input_streamon_ = true; | 1080 mfc_input_streamon_ = true; |
| 1053 } | 1081 } |
| 1054 } | 1082 } |
| 1055 | 1083 |
| 1056 // Enqueue all the MFC outputs we can. | 1084 // Enqueue all the MFC outputs we can. |
| 1057 const int old_mfc_outputs_queued = mfc_output_buffer_queued_count_; | 1085 const int old_mfc_outputs_queued = mfc_output_buffer_queued_count_; |
| 1058 while (!mfc_free_output_buffers_.empty()) { | 1086 while (!mfc_free_output_buffers_.empty()) { |
| 1059 if (!EnqueueMfcOutputRecord()) | 1087 if (!EnqueueMfcOutputRecord()) |
| 1060 return; | 1088 return; |
| 1061 } | 1089 } |
| 1062 if (old_mfc_outputs_queued == 0 && mfc_output_buffer_queued_count_ != 0) { | 1090 if (old_mfc_outputs_queued == 0 && mfc_output_buffer_queued_count_ != 0) { |
| 1063 // We just started up a previously empty queue. | 1091 // We just started up a previously empty queue. |
| 1064 // Queue state changed; signal interrupt. | 1092 // Queue state changed; signal interrupt. |
| 1065 if (!SetDevicePollInterrupt()) | 1093 if (!device->SetDevicePollInterrupt(device_poll_interrupt_fd_)) { |
| 1094 NOTIFY_ERROR(PLATFORM_FAILURE); | |
| 1066 return; | 1095 return; |
| 1096 } | |
| 1067 // Start VIDIOC_STREAMON if we haven't yet. | 1097 // Start VIDIOC_STREAMON if we haven't yet. |
| 1068 if (!mfc_output_streamon_) { | 1098 if (!mfc_output_streamon_) { |
| 1069 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1099 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1070 IOCTL_OR_ERROR_RETURN(mfc_fd_, VIDIOC_STREAMON, &type); | 1100 IOCTL_OR_ERROR_RETURN(videodec_fd_, VIDIOC_STREAMON, &type); |
| 1071 mfc_output_streamon_ = true; | 1101 mfc_output_streamon_ = true; |
| 1072 } | 1102 } |
| 1073 } | 1103 } |
| 1074 } | 1104 } |
| 1075 | 1105 |
| 1076 void ExynosVideoDecodeAccelerator::DequeueMfcEvents() { | 1106 void V4L2VideoDecodeAccelerator::DequeueMfcEvents() { |
| 1077 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1107 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1078 DCHECK_NE(decoder_state_, kUninitialized); | 1108 DCHECK_NE(decoder_state_, kUninitialized); |
| 1079 DVLOG(3) << "DequeueMfcEvents()"; | 1109 DVLOG(3) << "DequeueMfcEvents()"; |
| 1080 | 1110 |
| 1081 struct v4l2_event ev; | 1111 struct v4l2_event ev; |
| 1082 memset(&ev, 0, sizeof(ev)); | 1112 memset(&ev, 0, sizeof(ev)); |
| 1083 | 1113 |
| 1084 while (ioctl(mfc_fd_, VIDIOC_DQEVENT, &ev) == 0) { | 1114 while (device->dev_ioctl(videodec_fd_, VIDIOC_DQEVENT, &ev) == 0) { |
| 1085 if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) { | 1115 if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) { |
| 1086 DVLOG(3) << "DequeueMfcEvents(): got resolution change event."; | 1116 DVLOG(3) << "DequeueMfcEvents(): got resolution change event."; |
| 1087 DCHECK(!resolution_change_pending_); | 1117 DCHECK(!resolution_change_pending_); |
| 1088 resolution_change_pending_ = true; | 1118 resolution_change_pending_ = true; |
| 1089 } else { | 1119 } else { |
| 1090 DLOG(FATAL) << "DequeueMfcEvents(): got an event (" << ev.type | 1120 DLOG(FATAL) << "DequeueMfcEvents(): got an event (" << ev.type |
| 1091 << ") we haven't subscribed to."; | 1121 << ") we haven't subscribed to."; |
| 1092 } | 1122 } |
| 1093 } | 1123 } |
| 1094 } | 1124 } |
| 1095 | 1125 |
| 1096 void ExynosVideoDecodeAccelerator::DequeueMfc() { | 1126 void V4L2VideoDecodeAccelerator::DequeueMfc() { |
| 1097 DVLOG(3) << "DequeueMfc()"; | 1127 DVLOG(3) << "DequeueMfc()"; |
| 1098 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1128 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1099 DCHECK_NE(decoder_state_, kUninitialized); | 1129 DCHECK_NE(decoder_state_, kUninitialized); |
| 1100 TRACE_EVENT0("Video Decoder", "EVDA::DequeueMfc"); | 1130 TRACE_EVENT0("Video Decoder", "EVDA::DequeueMfc"); |
| 1101 | 1131 |
| 1102 // Dequeue completed MFC input (VIDEO_OUTPUT) buffers, and recycle to the free | 1132 // Dequeue completed MFC input (VIDEO_OUTPUT) buffers, and recycle to the free |
| 1103 // list. | 1133 // list. |
| 1104 struct v4l2_buffer dqbuf; | 1134 struct v4l2_buffer dqbuf; |
| 1105 struct v4l2_plane planes[2]; | 1135 struct v4l2_plane planes[2]; |
| 1106 while (mfc_input_buffer_queued_count_ > 0) { | 1136 while (mfc_input_buffer_queued_count_ > 0) { |
| 1107 DCHECK(mfc_input_streamon_); | 1137 DCHECK(mfc_input_streamon_); |
| 1108 memset(&dqbuf, 0, sizeof(dqbuf)); | 1138 memset(&dqbuf, 0, sizeof(dqbuf)); |
| 1109 memset(planes, 0, sizeof(planes)); | 1139 memset(planes, 0, sizeof(planes)); |
| 1110 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1140 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1111 dqbuf.memory = V4L2_MEMORY_MMAP; | 1141 dqbuf.memory = V4L2_MEMORY_MMAP; |
| 1112 dqbuf.m.planes = planes; | 1142 dqbuf.m.planes = planes; |
| 1113 dqbuf.length = 1; | 1143 dqbuf.length = 1; |
| 1114 if (ioctl(mfc_fd_, VIDIOC_DQBUF, &dqbuf) != 0) { | 1144 if (device->dev_ioctl(videodec_fd_, VIDIOC_DQBUF, &dqbuf) != 0) { |
| 1115 if (errno == EAGAIN) { | 1145 if (errno == EAGAIN) { |
| 1116 // EAGAIN if we're just out of buffers to dequeue. | 1146 // EAGAIN if we're just out of buffers to dequeue. |
| 1117 break; | 1147 break; |
| 1118 } | 1148 } |
| 1119 DPLOG(ERROR) << "DequeueMfc(): ioctl() failed: VIDIOC_DQBUF"; | 1149 DPLOG(ERROR) << "DequeueMfc(): ioctl() failed: VIDIOC_DQBUF"; |
| 1120 NOTIFY_ERROR(PLATFORM_FAILURE); | 1150 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1121 return; | 1151 return; |
| 1122 } | 1152 } |
| 1123 MfcInputRecord& input_record = mfc_input_buffer_map_[dqbuf.index]; | 1153 MfcInputRecord& input_record = mfc_input_buffer_map_[dqbuf.index]; |
| 1124 DCHECK(input_record.at_device); | 1154 DCHECK(input_record.at_device); |
| 1125 mfc_free_input_buffers_.push_back(dqbuf.index); | 1155 mfc_free_input_buffers_.push_back(dqbuf.index); |
| 1126 input_record.at_device = false; | 1156 input_record.at_device = false; |
| 1127 input_record.bytes_used = 0; | 1157 input_record.bytes_used = 0; |
| 1128 input_record.input_id = -1; | 1158 input_record.input_id = -1; |
| 1129 mfc_input_buffer_queued_count_--; | 1159 mfc_input_buffer_queued_count_--; |
| 1130 } | 1160 } |
| 1131 | 1161 |
| 1132 // Dequeue completed MFC output (VIDEO_CAPTURE) buffers, and queue to the | 1162 // Dequeue completed MFC output (VIDEO_CAPTURE) buffers, and queue to the |
| 1133 // completed queue. | 1163 // completed queue. |
| 1134 while (mfc_output_buffer_queued_count_ > 0) { | 1164 while (mfc_output_buffer_queued_count_ > 0) { |
| 1135 DCHECK(mfc_output_streamon_); | 1165 DCHECK(mfc_output_streamon_); |
| 1136 memset(&dqbuf, 0, sizeof(dqbuf)); | 1166 memset(&dqbuf, 0, sizeof(dqbuf)); |
| 1137 memset(planes, 0, sizeof(planes)); | 1167 memset(planes, 0, sizeof(planes)); |
| 1138 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1168 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1139 dqbuf.memory = V4L2_MEMORY_MMAP; | 1169 dqbuf.memory = V4L2_MEMORY_MMAP; |
| 1140 dqbuf.m.planes = planes; | 1170 dqbuf.m.planes = planes; |
| 1141 dqbuf.length = 2; | 1171 dqbuf.length = 2; |
| 1142 if (ioctl(mfc_fd_, VIDIOC_DQBUF, &dqbuf) != 0) { | 1172 if (device->dev_ioctl(videodec_fd_, VIDIOC_DQBUF, &dqbuf) != 0) { |
| 1143 if (errno == EAGAIN) { | 1173 if (errno == EAGAIN) { |
| 1144 // EAGAIN if we're just out of buffers to dequeue. | 1174 // EAGAIN if we're just out of buffers to dequeue. |
| 1145 break; | 1175 break; |
| 1146 } | 1176 } |
| 1147 DPLOG(ERROR) << "DequeueMfc(): ioctl() failed: VIDIOC_DQBUF"; | 1177 DPLOG(ERROR) << "DequeueMfc(): ioctl() failed: VIDIOC_DQBUF"; |
| 1148 NOTIFY_ERROR(PLATFORM_FAILURE); | 1178 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1149 return; | 1179 return; |
| 1150 } | 1180 } |
| 1151 MfcOutputRecord& output_record = mfc_output_buffer_map_[dqbuf.index]; | 1181 MfcOutputRecord& output_record = mfc_output_buffer_map_[dqbuf.index]; |
| 1152 DCHECK(output_record.at_device); | 1182 DCHECK(output_record.at_device); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1169 SendPictureReady(); | 1199 SendPictureReady(); |
| 1170 output_record.cleared = true; | 1200 output_record.cleared = true; |
| 1171 decoder_frames_at_client_++; | 1201 decoder_frames_at_client_++; |
| 1172 } | 1202 } |
| 1173 mfc_output_buffer_queued_count_--; | 1203 mfc_output_buffer_queued_count_--; |
| 1174 } | 1204 } |
| 1175 | 1205 |
| 1176 NotifyFlushDoneIfNeeded(); | 1206 NotifyFlushDoneIfNeeded(); |
| 1177 } | 1207 } |
| 1178 | 1208 |
| 1179 bool ExynosVideoDecodeAccelerator::EnqueueMfcInputRecord() { | 1209 bool V4L2VideoDecodeAccelerator::EnqueueMfcInputRecord() { |
| 1180 DVLOG(3) << "EnqueueMfcInputRecord()"; | 1210 DVLOG(3) << "EnqueueMfcInputRecord()"; |
| 1181 DCHECK(!mfc_input_ready_queue_.empty()); | 1211 DCHECK(!mfc_input_ready_queue_.empty()); |
| 1182 | 1212 |
| 1183 // Enqueue a MFC input (VIDEO_OUTPUT) buffer. | 1213 // Enqueue a MFC input (VIDEO_OUTPUT) buffer. |
| 1184 const int buffer = mfc_input_ready_queue_.front(); | 1214 const int buffer = mfc_input_ready_queue_.front(); |
| 1185 MfcInputRecord& input_record = mfc_input_buffer_map_[buffer]; | 1215 MfcInputRecord& input_record = mfc_input_buffer_map_[buffer]; |
| 1186 DCHECK(!input_record.at_device); | 1216 DCHECK(!input_record.at_device); |
| 1187 struct v4l2_buffer qbuf; | 1217 struct v4l2_buffer qbuf; |
| 1188 struct v4l2_plane qbuf_plane; | 1218 struct v4l2_plane qbuf_plane; |
| 1189 memset(&qbuf, 0, sizeof(qbuf)); | 1219 memset(&qbuf, 0, sizeof(qbuf)); |
| 1190 memset(&qbuf_plane, 0, sizeof(qbuf_plane)); | 1220 memset(&qbuf_plane, 0, sizeof(qbuf_plane)); |
| 1191 qbuf.index = buffer; | 1221 qbuf.index = buffer; |
| 1192 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1222 qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1193 qbuf.timestamp.tv_sec = input_record.input_id; | 1223 qbuf.timestamp.tv_sec = input_record.input_id; |
| 1194 qbuf.memory = V4L2_MEMORY_MMAP; | 1224 qbuf.memory = V4L2_MEMORY_MMAP; |
| 1195 qbuf.m.planes = &qbuf_plane; | 1225 qbuf.m.planes = &qbuf_plane; |
| 1196 qbuf.m.planes[0].bytesused = input_record.bytes_used; | 1226 qbuf.m.planes[0].bytesused = input_record.bytes_used; |
| 1197 qbuf.length = 1; | 1227 qbuf.length = 1; |
| 1198 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QBUF, &qbuf); | 1228 IOCTL_OR_ERROR_RETURN_FALSE(videodec_fd_, VIDIOC_QBUF, &qbuf); |
| 1199 mfc_input_ready_queue_.pop(); | 1229 mfc_input_ready_queue_.pop(); |
| 1200 input_record.at_device = true; | 1230 input_record.at_device = true; |
| 1201 mfc_input_buffer_queued_count_++; | 1231 mfc_input_buffer_queued_count_++; |
| 1202 DVLOG(3) << "EnqueueMfcInputRecord(): enqueued input_id=" | 1232 DVLOG(3) << "EnqueueMfcInputRecord(): enqueued input_id=" |
| 1203 << input_record.input_id; | 1233 << input_record.input_id; |
| 1204 return true; | 1234 return true; |
| 1205 } | 1235 } |
| 1206 | 1236 |
| 1207 bool ExynosVideoDecodeAccelerator::EnqueueMfcOutputRecord() { | 1237 bool V4L2VideoDecodeAccelerator::EnqueueMfcOutputRecord() { |
| 1208 DVLOG(3) << "EnqueueMfcOutputRecord()"; | 1238 DVLOG(3) << "EnqueueMfcOutputRecord()"; |
| 1209 DCHECK(!mfc_free_output_buffers_.empty()); | 1239 DCHECK(!mfc_free_output_buffers_.empty()); |
| 1210 | 1240 |
| 1211 // Enqueue a MFC output (VIDEO_CAPTURE) buffer. | 1241 // Enqueue a MFC output (VIDEO_CAPTURE) buffer. |
| 1212 const int buffer = mfc_free_output_buffers_.front(); | 1242 const int buffer = mfc_free_output_buffers_.front(); |
| 1213 MfcOutputRecord& output_record = mfc_output_buffer_map_[buffer]; | 1243 MfcOutputRecord& output_record = mfc_output_buffer_map_[buffer]; |
| 1214 DCHECK(!output_record.at_device); | 1244 DCHECK(!output_record.at_device); |
| 1215 DCHECK(!output_record.at_client); | 1245 DCHECK(!output_record.at_client); |
| 1216 DCHECK_NE(output_record.egl_image, EGL_NO_IMAGE_KHR); | 1246 DCHECK_NE(output_record.egl_image, EGL_NO_IMAGE_KHR); |
| 1217 DCHECK_NE(output_record.picture_id, -1); | 1247 DCHECK_NE(output_record.picture_id, -1); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1228 } | 1258 } |
| 1229 struct v4l2_buffer qbuf; | 1259 struct v4l2_buffer qbuf; |
| 1230 struct v4l2_plane qbuf_planes[arraysize(output_record.fds)]; | 1260 struct v4l2_plane qbuf_planes[arraysize(output_record.fds)]; |
| 1231 memset(&qbuf, 0, sizeof(qbuf)); | 1261 memset(&qbuf, 0, sizeof(qbuf)); |
| 1232 memset(qbuf_planes, 0, sizeof(qbuf_planes)); | 1262 memset(qbuf_planes, 0, sizeof(qbuf_planes)); |
| 1233 qbuf.index = buffer; | 1263 qbuf.index = buffer; |
| 1234 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1264 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1235 qbuf.memory = V4L2_MEMORY_MMAP; | 1265 qbuf.memory = V4L2_MEMORY_MMAP; |
| 1236 qbuf.m.planes = qbuf_planes; | 1266 qbuf.m.planes = qbuf_planes; |
| 1237 qbuf.length = arraysize(output_record.fds); | 1267 qbuf.length = arraysize(output_record.fds); |
| 1238 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QBUF, &qbuf); | 1268 IOCTL_OR_ERROR_RETURN_FALSE(videodec_fd_, VIDIOC_QBUF, &qbuf); |
| 1239 mfc_free_output_buffers_.pop(); | 1269 mfc_free_output_buffers_.pop(); |
| 1240 output_record.at_device = true; | 1270 output_record.at_device = true; |
| 1241 mfc_output_buffer_queued_count_++; | 1271 mfc_output_buffer_queued_count_++; |
| 1242 return true; | 1272 return true; |
| 1243 } | 1273 } |
| 1244 | 1274 |
| 1245 void ExynosVideoDecodeAccelerator::ReusePictureBufferTask( | 1275 void V4L2VideoDecodeAccelerator::ReusePictureBufferTask( |
| 1246 int32 picture_buffer_id, scoped_ptr<EGLSyncKHRRef> egl_sync_ref) { | 1276 int32 picture_buffer_id, scoped_ptr<EGLSyncKHRRef> egl_sync_ref) { |
| 1247 DVLOG(3) << "ReusePictureBufferTask(): picture_buffer_id=" | 1277 DVLOG(3) << "ReusePictureBufferTask(): picture_buffer_id=" |
| 1248 << picture_buffer_id; | 1278 << picture_buffer_id; |
| 1249 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1279 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1250 TRACE_EVENT0("Video Decoder", "EVDA::ReusePictureBufferTask"); | 1280 TRACE_EVENT0("Video Decoder", "EVDA::ReusePictureBufferTask"); |
| 1251 | 1281 |
| 1252 // We run ReusePictureBufferTask even if we're in kResetting. | 1282 // We run ReusePictureBufferTask even if we're in kResetting. |
| 1253 if (decoder_state_ == kError) { | 1283 if (decoder_state_ == kError) { |
| 1254 DVLOG(2) << "ReusePictureBufferTask(): early out: kError state"; | 1284 DVLOG(2) << "ReusePictureBufferTask(): early out: kError state"; |
| 1255 return; | 1285 return; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1282 output_record.at_client = false; | 1312 output_record.at_client = false; |
| 1283 output_record.egl_sync = egl_sync_ref->egl_sync; | 1313 output_record.egl_sync = egl_sync_ref->egl_sync; |
| 1284 mfc_free_output_buffers_.push(index); | 1314 mfc_free_output_buffers_.push(index); |
| 1285 decoder_frames_at_client_--; | 1315 decoder_frames_at_client_--; |
| 1286 // Take ownership of the EGLSync. | 1316 // Take ownership of the EGLSync. |
| 1287 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR; | 1317 egl_sync_ref->egl_sync = EGL_NO_SYNC_KHR; |
| 1288 // We got a buffer back, so kick the MFC. | 1318 // We got a buffer back, so kick the MFC. |
| 1289 EnqueueMfc(); | 1319 EnqueueMfc(); |
| 1290 } | 1320 } |
| 1291 | 1321 |
| 1292 void ExynosVideoDecodeAccelerator::FlushTask() { | 1322 void V4L2VideoDecodeAccelerator::FlushTask() { |
| 1293 DVLOG(3) << "FlushTask()"; | 1323 DVLOG(3) << "FlushTask()"; |
| 1294 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1324 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1295 TRACE_EVENT0("Video Decoder", "EVDA::FlushTask"); | 1325 TRACE_EVENT0("Video Decoder", "EVDA::FlushTask"); |
| 1296 | 1326 |
| 1297 // Flush outstanding buffers. | 1327 // Flush outstanding buffers. |
| 1298 if (decoder_state_ == kInitialized || decoder_state_ == kAfterReset) { | 1328 if (decoder_state_ == kInitialized || decoder_state_ == kAfterReset) { |
| 1299 // There's nothing in the pipe, so return done immediately. | 1329 // There's nothing in the pipe, so return done immediately. |
| 1300 DVLOG(3) << "FlushTask(): returning flush"; | 1330 DVLOG(3) << "FlushTask(): returning flush"; |
| 1301 child_message_loop_proxy_->PostTask( | 1331 child_message_loop_proxy_->PostTask( |
| 1302 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_)); | 1332 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_)); |
| 1303 return; | 1333 return; |
| 1304 } else if (decoder_state_ == kError) { | 1334 } else if (decoder_state_ == kError) { |
| 1305 DVLOG(2) << "FlushTask(): early out: kError state"; | 1335 DVLOG(2) << "FlushTask(): early out: kError state"; |
| 1306 return; | 1336 return; |
| 1307 } | 1337 } |
| 1308 | 1338 |
| 1309 // We don't support stacked flushing. | 1339 // We don't support stacked flushing. |
| 1310 DCHECK(!decoder_flushing_); | 1340 DCHECK(!decoder_flushing_); |
| 1311 | 1341 |
| 1312 // Queue up an empty buffer -- this triggers the flush. | 1342 // Queue up an empty buffer -- this triggers the flush. |
| 1313 decoder_input_queue_.push( | 1343 decoder_input_queue_.push( |
| 1314 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | 1344 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( |
| 1315 io_client_, io_message_loop_proxy_, NULL, 0, kFlushBufferId))); | 1345 io_client_, io_message_loop_proxy_, NULL, 0, kFlushBufferId))); |
| 1316 decoder_flushing_ = true; | 1346 decoder_flushing_ = true; |
| 1317 SendPictureReady(); // Send all pending PictureReady. | 1347 SendPictureReady(); // Send all pending PictureReady. |
| 1318 | 1348 |
| 1319 ScheduleDecodeBufferTaskIfNeeded(); | 1349 ScheduleDecodeBufferTaskIfNeeded(); |
| 1320 } | 1350 } |
| 1321 | 1351 |
| 1322 void ExynosVideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { | 1352 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { |
| 1323 if (!decoder_flushing_) | 1353 if (!decoder_flushing_) |
| 1324 return; | 1354 return; |
| 1325 | 1355 |
| 1326 // Pipeline is empty when: | 1356 // Pipeline is empty when: |
| 1327 // * Decoder input queue is empty of non-delayed buffers. | 1357 // * Decoder input queue is empty of non-delayed buffers. |
| 1328 // * There is no currently filling input buffer. | 1358 // * There is no currently filling input buffer. |
| 1329 // * MFC input holding queue is empty. | 1359 // * MFC input holding queue is empty. |
| 1330 // * All MFC input (VIDEO_OUTPUT) buffers are returned. | 1360 // * All MFC input (VIDEO_OUTPUT) buffers are returned. |
| 1331 if (!decoder_input_queue_.empty()) { | 1361 if (!decoder_input_queue_.empty()) { |
| 1332 if (decoder_input_queue_.front()->input_id != | 1362 if (decoder_input_queue_.front()->input_id != |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1356 decoder_delay_bitstream_buffer_id_ = -1; | 1386 decoder_delay_bitstream_buffer_id_ = -1; |
| 1357 decoder_flushing_ = false; | 1387 decoder_flushing_ = false; |
| 1358 DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush"; | 1388 DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush"; |
| 1359 child_message_loop_proxy_->PostTask( | 1389 child_message_loop_proxy_->PostTask( |
| 1360 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_)); | 1390 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_)); |
| 1361 | 1391 |
| 1362 // While we were flushing, we early-outed DecodeBufferTask()s. | 1392 // While we were flushing, we early-outed DecodeBufferTask()s. |
| 1363 ScheduleDecodeBufferTaskIfNeeded(); | 1393 ScheduleDecodeBufferTaskIfNeeded(); |
| 1364 } | 1394 } |
| 1365 | 1395 |
| 1366 void ExynosVideoDecodeAccelerator::ResetTask() { | 1396 void V4L2VideoDecodeAccelerator::ResetTask() { |
| 1367 DVLOG(3) << "ResetTask()"; | 1397 DVLOG(3) << "ResetTask()"; |
| 1368 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1398 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1369 TRACE_EVENT0("Video Decoder", "EVDA::ResetTask"); | 1399 TRACE_EVENT0("Video Decoder", "EVDA::ResetTask"); |
| 1370 | 1400 |
| 1371 if (decoder_state_ == kError) { | 1401 if (decoder_state_ == kError) { |
| 1372 DVLOG(2) << "ResetTask(): early out: kError state"; | 1402 DVLOG(2) << "ResetTask(): early out: kError state"; |
| 1373 return; | 1403 return; |
| 1374 } | 1404 } |
| 1375 | 1405 |
| 1376 // If we are in the middle of switching resolutions, postpone reset until | 1406 // If we are in the middle of switching resolutions, postpone reset until |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1397 | 1427 |
| 1398 // If we were flushing, we'll never return any more BitstreamBuffers or | 1428 // If we were flushing, we'll never return any more BitstreamBuffers or |
| 1399 // PictureBuffers; they have all been dropped and returned by now. | 1429 // PictureBuffers; they have all been dropped and returned by now. |
| 1400 NotifyFlushDoneIfNeeded(); | 1430 NotifyFlushDoneIfNeeded(); |
| 1401 | 1431 |
| 1402 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening | 1432 // Mark that we're resetting, then enqueue a ResetDoneTask(). All intervening |
| 1403 // jobs will early-out in the kResetting state. | 1433 // jobs will early-out in the kResetting state. |
| 1404 decoder_state_ = kResetting; | 1434 decoder_state_ = kResetting; |
| 1405 SendPictureReady(); // Send all pending PictureReady. | 1435 SendPictureReady(); // Send all pending PictureReady. |
| 1406 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1436 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 1407 &ExynosVideoDecodeAccelerator::ResetDoneTask, base::Unretained(this))); | 1437 &V4L2VideoDecodeAccelerator::ResetDoneTask, base::Unretained(this))); |
| 1408 } | 1438 } |
| 1409 | 1439 |
| 1410 void ExynosVideoDecodeAccelerator::ResetDoneTask() { | 1440 void V4L2VideoDecodeAccelerator::ResetDoneTask() { |
| 1411 DVLOG(3) << "ResetDoneTask()"; | 1441 DVLOG(3) << "ResetDoneTask()"; |
| 1412 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1442 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1413 TRACE_EVENT0("Video Decoder", "EVDA::ResetDoneTask"); | 1443 TRACE_EVENT0("Video Decoder", "EVDA::ResetDoneTask"); |
| 1414 | 1444 |
| 1415 if (decoder_state_ == kError) { | 1445 if (decoder_state_ == kError) { |
| 1416 DVLOG(2) << "ResetDoneTask(): early out: kError state"; | 1446 DVLOG(2) << "ResetDoneTask(): early out: kError state"; |
| 1417 return; | 1447 return; |
| 1418 } | 1448 } |
| 1419 | 1449 |
| 1420 // We might have received a resolution change event while we were waiting | 1450 // We might have received a resolution change event while we were waiting |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1434 decoder_state_ = kAfterReset; | 1464 decoder_state_ = kAfterReset; |
| 1435 decoder_partial_frame_pending_ = false; | 1465 decoder_partial_frame_pending_ = false; |
| 1436 decoder_delay_bitstream_buffer_id_ = -1; | 1466 decoder_delay_bitstream_buffer_id_ = -1; |
| 1437 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 1467 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 1438 &Client::NotifyResetDone, client_)); | 1468 &Client::NotifyResetDone, client_)); |
| 1439 | 1469 |
| 1440 // While we were resetting, we early-outed DecodeBufferTask()s. | 1470 // While we were resetting, we early-outed DecodeBufferTask()s. |
| 1441 ScheduleDecodeBufferTaskIfNeeded(); | 1471 ScheduleDecodeBufferTaskIfNeeded(); |
| 1442 } | 1472 } |
| 1443 | 1473 |
| 1444 void ExynosVideoDecodeAccelerator::DestroyTask() { | 1474 void V4L2VideoDecodeAccelerator::DestroyTask() { |
| 1445 DVLOG(3) << "DestroyTask()"; | 1475 DVLOG(3) << "DestroyTask()"; |
| 1446 TRACE_EVENT0("Video Decoder", "EVDA::DestroyTask"); | 1476 TRACE_EVENT0("Video Decoder", "EVDA::DestroyTask"); |
| 1447 | 1477 |
| 1448 // DestroyTask() should run regardless of decoder_state_. | 1478 // DestroyTask() should run regardless of decoder_state_. |
| 1449 | 1479 |
| 1450 // Stop streaming and the device_poll_thread_. | 1480 // Stop streaming and the device_poll_thread_. |
| 1451 StopDevicePoll(false); | 1481 StopDevicePoll(false); |
| 1452 | 1482 |
| 1453 decoder_current_bitstream_buffer_.reset(); | 1483 decoder_current_bitstream_buffer_.reset(); |
| 1454 decoder_current_input_buffer_ = -1; | 1484 decoder_current_input_buffer_ = -1; |
| 1455 decoder_decode_buffer_tasks_scheduled_ = 0; | 1485 decoder_decode_buffer_tasks_scheduled_ = 0; |
| 1456 decoder_frames_at_client_ = 0; | 1486 decoder_frames_at_client_ = 0; |
| 1457 while (!decoder_input_queue_.empty()) | 1487 while (!decoder_input_queue_.empty()) |
| 1458 decoder_input_queue_.pop(); | 1488 decoder_input_queue_.pop(); |
| 1459 decoder_flushing_ = false; | 1489 decoder_flushing_ = false; |
| 1460 | 1490 |
| 1461 // Set our state to kError. Just in case. | 1491 // Set our state to kError. Just in case. |
| 1462 decoder_state_ = kError; | 1492 decoder_state_ = kError; |
| 1463 } | 1493 } |
| 1464 | 1494 |
| 1465 bool ExynosVideoDecodeAccelerator::StartDevicePoll() { | 1495 bool V4L2VideoDecodeAccelerator::StartDevicePoll() { |
| 1466 DVLOG(3) << "StartDevicePoll()"; | 1496 DVLOG(3) << "StartDevicePoll()"; |
| 1467 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1497 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1468 DCHECK(!device_poll_thread_.IsRunning()); | 1498 DCHECK(!device_poll_thread_.IsRunning()); |
| 1469 | 1499 |
| 1470 // Start up the device poll thread and schedule its first DevicePollTask(). | 1500 // Start up the device poll thread and schedule its first DevicePollTask(). |
| 1471 if (!device_poll_thread_.Start()) { | 1501 if (!device_poll_thread_.Start()) { |
| 1472 DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; | 1502 DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; |
| 1473 NOTIFY_ERROR(PLATFORM_FAILURE); | 1503 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1474 return false; | 1504 return false; |
| 1475 } | 1505 } |
| 1476 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1506 device_poll_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 1477 &ExynosVideoDecodeAccelerator::DevicePollTask, | 1507 &V4L2VideoDecodeAccelerator::DevicePollTask, |
| 1478 base::Unretained(this), | 1508 base::Unretained(this), |
| 1479 0)); | 1509 0)); |
| 1480 | 1510 |
| 1481 return true; | 1511 return true; |
| 1482 } | 1512 } |
| 1483 | 1513 |
| 1484 bool ExynosVideoDecodeAccelerator::StopDevicePoll(bool keep_mfc_input_state) { | 1514 bool V4L2VideoDecodeAccelerator::StopDevicePoll(bool keep_mfc_input_state) { |
| 1485 DVLOG(3) << "StopDevicePoll()"; | 1515 DVLOG(3) << "StopDevicePoll()"; |
| 1486 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1516 if (decoder_thread_.IsRunning()) |
| 1517 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | |
| 1487 | 1518 |
| 1488 // Signal the DevicePollTask() to stop, and stop the device poll thread. | 1519 // Signal the DevicePollTask() to stop, and stop the device poll thread. |
| 1489 if (!SetDevicePollInterrupt()) | 1520 if (!device->SetDevicePollInterrupt(device_poll_interrupt_fd_)) { |
| 1521 NOTIFY_ERROR(PLATFORM_FAILURE); | |
| 1490 return false; | 1522 return false; |
| 1523 } | |
| 1491 device_poll_thread_.Stop(); | 1524 device_poll_thread_.Stop(); |
| 1492 // Clear the interrupt now, to be sure. | 1525 // Clear the interrupt now, to be sure. |
| 1493 if (!ClearDevicePollInterrupt()) | 1526 if (!device->ClearDevicePollInterrupt(device_poll_interrupt_fd_)) { |
| 1527 NOTIFY_ERROR(PLATFORM_FAILURE); | |
| 1494 return false; | 1528 return false; |
| 1529 } | |
| 1495 | 1530 |
| 1496 // Stop streaming. | 1531 // Stop streaming. |
| 1497 if (!keep_mfc_input_state) { | 1532 if (!keep_mfc_input_state) { |
| 1498 if (mfc_input_streamon_) { | 1533 if (mfc_input_streamon_) { |
| 1499 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1534 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1500 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type); | 1535 IOCTL_OR_ERROR_RETURN_FALSE(videodec_fd_, VIDIOC_STREAMOFF, &type); |
| 1501 } | 1536 } |
| 1502 mfc_input_streamon_ = false; | 1537 mfc_input_streamon_ = false; |
| 1503 } | 1538 } |
| 1504 if (mfc_output_streamon_) { | 1539 if (mfc_output_streamon_) { |
| 1505 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1540 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1506 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type); | 1541 IOCTL_OR_ERROR_RETURN_FALSE(videodec_fd_, VIDIOC_STREAMOFF, &type); |
| 1507 } | 1542 } |
| 1508 mfc_output_streamon_ = false; | 1543 mfc_output_streamon_ = false; |
| 1509 | 1544 |
| 1510 // Reset all our accounting info. | 1545 // Reset all our accounting info. |
| 1511 if (!keep_mfc_input_state) { | 1546 if (!keep_mfc_input_state) { |
| 1512 while (!mfc_input_ready_queue_.empty()) | 1547 while (!mfc_input_ready_queue_.empty()) |
| 1513 mfc_input_ready_queue_.pop(); | 1548 mfc_input_ready_queue_.pop(); |
| 1514 mfc_free_input_buffers_.clear(); | 1549 mfc_free_input_buffers_.clear(); |
| 1515 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) { | 1550 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) { |
| 1516 mfc_free_input_buffers_.push_back(i); | 1551 mfc_free_input_buffers_.push_back(i); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1530 mfc_free_output_buffers_.push(i); | 1565 mfc_free_output_buffers_.push(i); |
| 1531 mfc_output_buffer_map_[i].at_device = false; | 1566 mfc_output_buffer_map_[i].at_device = false; |
| 1532 } | 1567 } |
| 1533 } | 1568 } |
| 1534 mfc_output_buffer_queued_count_ = 0; | 1569 mfc_output_buffer_queued_count_ = 0; |
| 1535 | 1570 |
| 1536 DVLOG(3) << "StopDevicePoll(): device poll stopped"; | 1571 DVLOG(3) << "StopDevicePoll(): device poll stopped"; |
| 1537 return true; | 1572 return true; |
| 1538 } | 1573 } |
| 1539 | 1574 |
| 1540 bool ExynosVideoDecodeAccelerator::SetDevicePollInterrupt() { | 1575 bool V4L2VideoDecodeAccelerator:: ExynosV4L2Device :: SetDevicePollInterrupt(int fd) { |
|
Pawel Osciak
2013/12/24 03:45:24
Please keep methods of one class together (althoug
| |
| 1541 DVLOG(3) << "SetDevicePollInterrupt()"; | 1576 DVLOG(3) << "SetDevicePollInterrupt()"; |
| 1542 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | |
| 1543 | 1577 |
| 1544 const uint64 buf = 1; | 1578 const uint64 buf = 1; |
| 1545 if (HANDLE_EINTR(write(device_poll_interrupt_fd_, &buf, sizeof(buf))) == -1) { | 1579 if (HANDLE_EINTR(write(fd, &buf, sizeof(buf))) == -1) { |
| 1546 DPLOG(ERROR) << "SetDevicePollInterrupt(): write() failed"; | 1580 DPLOG(ERROR) << "SetDevicePollInterrupt(): write() failed"; |
| 1547 NOTIFY_ERROR(PLATFORM_FAILURE); | |
| 1548 return false; | 1581 return false; |
| 1549 } | 1582 } |
| 1550 return true; | 1583 return true; |
| 1551 } | 1584 } |
| 1552 | 1585 |
| 1553 bool ExynosVideoDecodeAccelerator::ClearDevicePollInterrupt() { | 1586 bool V4L2VideoDecodeAccelerator:: ExynosV4L2Device :: ClearDevicePollInterrupt(i nt fd) { |
| 1554 DVLOG(3) << "ClearDevicePollInterrupt()"; | 1587 DVLOG(3) << "ClearDevicePollInterrupt()"; |
| 1555 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | |
| 1556 | 1588 |
| 1557 uint64 buf; | 1589 uint64 buf; |
| 1558 if (HANDLE_EINTR(read(device_poll_interrupt_fd_, &buf, sizeof(buf))) == -1) { | 1590 if (HANDLE_EINTR(read(fd, &buf, sizeof(buf))) == -1) { |
| 1559 if (errno == EAGAIN) { | 1591 if (errno == EAGAIN) { |
| 1560 // No interrupt flag set, and we're reading nonblocking. Not an error. | 1592 // No interrupt flag set, and we're reading nonblocking. Not an error. |
| 1561 return true; | 1593 return true; |
| 1562 } else { | 1594 } else { |
| 1563 DPLOG(ERROR) << "ClearDevicePollInterrupt(): read() failed"; | 1595 DPLOG(ERROR) << "ClearDevicePollInterrupt(): read() failed"; |
| 1564 NOTIFY_ERROR(PLATFORM_FAILURE); | |
| 1565 return false; | 1596 return false; |
| 1566 } | 1597 } |
| 1567 } | 1598 } |
| 1568 return true; | 1599 return true; |
| 1569 } | 1600 } |
| 1570 | 1601 |
| 1571 void ExynosVideoDecodeAccelerator::StartResolutionChangeIfNeeded() { | 1602 void V4L2VideoDecodeAccelerator::StartResolutionChangeIfNeeded() { |
| 1572 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1603 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1573 DCHECK_EQ(decoder_state_, kDecoding); | 1604 DCHECK_EQ(decoder_state_, kDecoding); |
| 1574 | 1605 |
| 1575 if (!resolution_change_pending_) | 1606 if (!resolution_change_pending_) |
| 1576 return; | 1607 return; |
| 1577 | 1608 |
| 1578 DVLOG(3) << "No more work, initiate resolution change"; | 1609 DVLOG(3) << "No more work, initiate resolution change"; |
| 1579 | 1610 |
| 1580 // Keep MFC input queue. | 1611 // Keep MFC input queue. |
| 1581 if (!StopDevicePoll(true)) | 1612 if (!StopDevicePoll(true)) |
| 1582 return; | 1613 return; |
| 1583 | 1614 |
| 1584 decoder_state_ = kChangingResolution; | 1615 decoder_state_ = kChangingResolution; |
| 1585 DCHECK(resolution_change_pending_); | 1616 DCHECK(resolution_change_pending_); |
| 1586 resolution_change_pending_ = false; | 1617 resolution_change_pending_ = false; |
| 1587 | 1618 |
| 1588 // Post a task to clean up buffers on child thread. This will also ensure | 1619 // Post a task to clean up buffers on child thread. This will also ensure |
| 1589 // that we won't accept ReusePictureBuffer() anymore after that. | 1620 // that we won't accept ReusePictureBuffer() anymore after that. |
| 1590 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 1621 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 1591 &ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers, | 1622 &V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers, |
| 1592 weak_this_)); | 1623 weak_this_)); |
| 1593 } | 1624 } |
| 1594 | 1625 |
| 1595 void ExynosVideoDecodeAccelerator::FinishResolutionChange() { | 1626 void V4L2VideoDecodeAccelerator::FinishResolutionChange() { |
| 1596 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1627 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1597 DVLOG(3) << "FinishResolutionChange()"; | 1628 DVLOG(3) << "FinishResolutionChange()"; |
| 1598 | 1629 |
| 1599 if (decoder_state_ == kError) { | 1630 if (decoder_state_ == kError) { |
| 1600 DVLOG(2) << "FinishResolutionChange(): early out: kError state"; | 1631 DVLOG(2) << "FinishResolutionChange(): early out: kError state"; |
| 1601 return; | 1632 return; |
| 1602 } | 1633 } |
| 1603 | 1634 |
| 1604 struct v4l2_format format; | 1635 struct v4l2_format format; |
| 1605 bool again; | 1636 bool again; |
| 1606 bool ret = GetFormatInfo(&format, &again); | 1637 bool ret = GetFormatInfo(&format, &again); |
| 1607 if (!ret || again) { | 1638 if (!ret || again) { |
| 1608 DVLOG(3) << "Couldn't get format information after resolution change"; | 1639 DVLOG(3) << "Couldn't get format information after resolution change"; |
| 1609 NOTIFY_ERROR(PLATFORM_FAILURE); | 1640 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1610 return; | 1641 return; |
| 1611 } | 1642 } |
| 1612 | 1643 |
| 1613 if (!CreateBuffersForFormat(format)) { | 1644 if (!CreateBuffersForFormat(format)) { |
| 1614 DVLOG(3) << "Couldn't reallocate buffers after resolution change"; | 1645 DVLOG(3) << "Couldn't reallocate buffers after resolution change"; |
| 1615 NOTIFY_ERROR(PLATFORM_FAILURE); | 1646 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1616 return; | 1647 return; |
| 1617 } | 1648 } |
| 1618 | 1649 |
| 1619 // From here we stay in kChangingResolution and wait for | 1650 // From here we stay in kChangingResolution and wait for |
| 1620 // AssignPictureBuffers() before we can resume. | 1651 // AssignPictureBuffers() before we can resume. |
| 1621 } | 1652 } |
| 1622 | 1653 |
| 1623 void ExynosVideoDecodeAccelerator::ResumeAfterResolutionChange() { | 1654 void V4L2VideoDecodeAccelerator::ResumeAfterResolutionChange() { |
| 1624 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1655 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1625 DVLOG(3) << "ResumeAfterResolutionChange()"; | 1656 DVLOG(3) << "ResumeAfterResolutionChange()"; |
| 1626 | 1657 |
| 1627 decoder_state_ = kDecoding; | 1658 decoder_state_ = kDecoding; |
| 1628 | 1659 |
| 1629 if (resolution_change_reset_pending_) { | 1660 if (resolution_change_reset_pending_) { |
| 1630 resolution_change_reset_pending_ = false; | 1661 resolution_change_reset_pending_ = false; |
| 1631 ResetTask(); | 1662 ResetTask(); |
| 1632 return; | 1663 return; |
| 1633 } | 1664 } |
| 1634 | 1665 |
| 1635 if (!StartDevicePoll()) | 1666 if (!StartDevicePoll()) |
| 1636 return; | 1667 return; |
| 1637 | 1668 |
| 1638 EnqueueMfc(); | 1669 EnqueueMfc(); |
| 1639 ScheduleDecodeBufferTaskIfNeeded(); | 1670 ScheduleDecodeBufferTaskIfNeeded(); |
| 1640 } | 1671 } |
| 1641 | 1672 |
| 1642 void ExynosVideoDecodeAccelerator::DevicePollTask(unsigned int poll_fds) { | 1673 void V4L2VideoDecodeAccelerator::DevicePollTask(unsigned int poll_fds) { |
| 1643 DVLOG(3) << "DevicePollTask()"; | 1674 DVLOG(3) << "DevicePollTask()"; |
| 1644 DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current()); | 1675 DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current()); |
| 1645 TRACE_EVENT0("Video Decoder", "EVDA::DevicePollTask"); | 1676 TRACE_EVENT0("Video Decoder", "EVDA::DevicePollTask"); |
| 1646 | 1677 |
| 1647 // This routine just polls the set of device fds, and schedules a | 1678 // This routine just polls the set of device fds, and schedules a |
| 1648 // ServiceDeviceTask() on decoder_thread_ when processing needs to occur. | 1679 // ServiceDeviceTask() on decoder_thread_ when processing needs to occur. |
| 1649 // Other threads may notify this task to return early by writing to | 1680 // Other threads may notify this task to return early by writing to |
| 1650 // device_poll_interrupt_fd_. | 1681 // device_poll_interrupt_fd_. |
| 1651 struct pollfd pollfds[3]; | 1682 struct pollfd pollfds[3]; |
| 1652 nfds_t nfds; | 1683 nfds_t nfds; |
| 1653 int mfc_pollfd = -1; | 1684 int mfc_pollfd = -1; |
| 1654 | 1685 |
| 1655 // Add device_poll_interrupt_fd_; | 1686 // Add device_poll_interrupt_fd_; |
| 1656 pollfds[0].fd = device_poll_interrupt_fd_; | 1687 pollfds[0].fd = device_poll_interrupt_fd_; |
| 1657 pollfds[0].events = POLLIN | POLLERR; | 1688 pollfds[0].events = POLLIN | POLLERR; |
| 1658 nfds = 1; | 1689 nfds = 1; |
| 1659 | 1690 |
| 1660 if (poll_fds & kPollMfc) { | 1691 if (poll_fds & kPollMfc) { |
| 1661 DVLOG(3) << "DevicePollTask(): adding MFC to poll() set"; | 1692 DVLOG(3) << "DevicePollTask(): adding MFC to poll() set"; |
| 1662 pollfds[nfds].fd = mfc_fd_; | 1693 pollfds[nfds].fd = videodec_fd_; |
| 1663 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR | POLLPRI; | 1694 pollfds[nfds].events = POLLIN | POLLOUT | POLLERR | POLLPRI; |
| 1664 mfc_pollfd = nfds; | 1695 mfc_pollfd = nfds; |
| 1665 nfds++; | 1696 nfds++; |
| 1666 } | 1697 } |
| 1667 | 1698 |
| 1668 // Poll it! | 1699 // Poll it! |
| 1669 if (HANDLE_EINTR(poll(pollfds, nfds, -1)) == -1) { | 1700 if (HANDLE_EINTR(device->dev_poll(pollfds, nfds, -1)) == -1) { |
| 1670 DPLOG(ERROR) << "DevicePollTask(): poll() failed"; | 1701 DPLOG(ERROR) << "DevicePollTask(): poll() failed"; |
| 1671 NOTIFY_ERROR(PLATFORM_FAILURE); | 1702 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1672 return; | 1703 return; |
| 1673 } | 1704 } |
| 1674 | 1705 |
| 1675 bool mfc_event_pending = (mfc_pollfd != -1 && | 1706 bool mfc_event_pending = (mfc_pollfd != -1 && |
| 1676 pollfds[mfc_pollfd].revents & POLLPRI); | 1707 pollfds[mfc_pollfd].revents & POLLPRI); |
| 1677 | 1708 |
| 1678 // All processing should happen on ServiceDeviceTask(), since we shouldn't | 1709 // All processing should happen on ServiceDeviceTask(), since we shouldn't |
| 1679 // touch decoder state from this thread. | 1710 // touch decoder state from this thread. |
| 1680 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1711 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 1681 &ExynosVideoDecodeAccelerator::ServiceDeviceTask, | 1712 &V4L2VideoDecodeAccelerator::ServiceDeviceTask, |
| 1682 base::Unretained(this), mfc_event_pending)); | 1713 base::Unretained(this), mfc_event_pending)); |
| 1683 } | 1714 } |
| 1684 | 1715 |
| 1685 void ExynosVideoDecodeAccelerator::NotifyError(Error error) { | 1716 void V4L2VideoDecodeAccelerator::NotifyError(Error error) { |
| 1686 DVLOG(2) << "NotifyError()"; | 1717 DVLOG(2) << "NotifyError()"; |
| 1687 | 1718 |
| 1688 if (!child_message_loop_proxy_->BelongsToCurrentThread()) { | 1719 if (!child_message_loop_proxy_->BelongsToCurrentThread()) { |
| 1689 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 1720 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 1690 &ExynosVideoDecodeAccelerator::NotifyError, weak_this_, error)); | 1721 &V4L2VideoDecodeAccelerator::NotifyError, weak_this_, error)); |
| 1691 return; | 1722 return; |
| 1692 } | 1723 } |
| 1693 | 1724 |
| 1694 if (client_) { | 1725 if (client_) { |
| 1695 client_->NotifyError(error); | 1726 client_->NotifyError(error); |
| 1696 client_ptr_factory_.InvalidateWeakPtrs(); | 1727 client_ptr_factory_.InvalidateWeakPtrs(); |
| 1697 } | 1728 } |
| 1698 } | 1729 } |
| 1699 | 1730 |
| 1700 void ExynosVideoDecodeAccelerator::SetDecoderState(State state) { | 1731 void V4L2VideoDecodeAccelerator::SetDecoderState(State state) { |
| 1701 DVLOG(3) << "SetDecoderState(): state=" << state; | 1732 DVLOG(3) << "SetDecoderState(): state=" << state; |
| 1702 | 1733 |
| 1703 // We can touch decoder_state_ only if this is the decoder thread or the | 1734 // We can touch decoder_state_ only if this is the decoder thread or the |
| 1704 // decoder thread isn't running. | 1735 // decoder thread isn't running. |
| 1705 if (decoder_thread_.message_loop() != NULL && | 1736 if (decoder_thread_.message_loop() != NULL && |
| 1706 decoder_thread_.message_loop() != base::MessageLoop::current()) { | 1737 decoder_thread_.message_loop() != base::MessageLoop::current()) { |
| 1707 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1738 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 1708 &ExynosVideoDecodeAccelerator::SetDecoderState, | 1739 &V4L2VideoDecodeAccelerator::SetDecoderState, |
| 1709 base::Unretained(this), state)); | 1740 base::Unretained(this), state)); |
| 1710 } else { | 1741 } else { |
| 1711 decoder_state_ = state; | 1742 decoder_state_ = state; |
| 1712 } | 1743 } |
| 1713 } | 1744 } |
| 1714 | 1745 |
| 1715 bool ExynosVideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format, | 1746 bool V4L2VideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format, |
| 1716 bool* again) { | 1747 bool* again) { |
| 1717 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1748 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1718 | 1749 |
| 1719 *again = false; | 1750 *again = false; |
| 1720 memset(format, 0, sizeof(*format)); | 1751 memset(format, 0, sizeof(*format)); |
| 1721 format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1752 format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1722 if (HANDLE_EINTR(ioctl(mfc_fd_, VIDIOC_G_FMT, format)) != 0) { | 1753 if (HANDLE_EINTR(device->dev_ioctl(videodec_fd_, VIDIOC_G_FMT, format)) != 0) { |
| 1723 if (errno == EINVAL) { | 1754 if (errno == EINVAL) { |
| 1724 // EINVAL means we haven't seen sufficient stream to decode the format. | 1755 // EINVAL means we haven't seen sufficient stream to decode the format. |
| 1725 *again = true; | 1756 *again = true; |
| 1726 return true; | 1757 return true; |
| 1727 } else { | 1758 } else { |
| 1728 DPLOG(ERROR) << "DecodeBufferInitial(): ioctl() failed: VIDIOC_G_FMT"; | 1759 DPLOG(ERROR) << "DecodeBufferInitial(): ioctl() failed: VIDIOC_G_FMT"; |
| 1729 NOTIFY_ERROR(PLATFORM_FAILURE); | 1760 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 1730 return false; | 1761 return false; |
| 1731 } | 1762 } |
| 1732 } | 1763 } |
| 1733 | 1764 |
| 1734 return true; | 1765 return true; |
| 1735 } | 1766 } |
| 1736 | 1767 |
| 1737 bool ExynosVideoDecodeAccelerator::CreateBuffersForFormat( | 1768 bool V4L2VideoDecodeAccelerator::CreateBuffersForFormat( |
| 1738 const struct v4l2_format& format) { | 1769 const struct v4l2_format& format) { |
| 1739 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1770 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1740 CHECK_EQ(format.fmt.pix_mp.num_planes, 2); | 1771 CHECK_EQ(format.fmt.pix_mp.num_planes, 2); |
| 1741 frame_buffer_size_.SetSize( | 1772 frame_buffer_size_.SetSize( |
| 1742 format.fmt.pix_mp.width, format.fmt.pix_mp.height); | 1773 format.fmt.pix_mp.width, format.fmt.pix_mp.height); |
| 1743 mfc_output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat; | 1774 mfc_output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat; |
| 1744 DCHECK_EQ(mfc_output_buffer_pixelformat_, V4L2_PIX_FMT_NV12M); | 1775 DCHECK_EQ(mfc_output_buffer_pixelformat_, V4L2_PIX_FMT_NV12M); |
| 1745 DVLOG(3) << "CreateBuffersForFormat(): new resolution: " | 1776 DVLOG(3) << "CreateBuffersForFormat(): new resolution: " |
| 1746 << frame_buffer_size_.ToString(); | 1777 << frame_buffer_size_.ToString(); |
| 1747 | 1778 |
| 1748 if (!CreateMfcOutputBuffers()) | 1779 if (!CreateMfcOutputBuffers()) |
| 1749 return false; | 1780 return false; |
| 1750 | 1781 |
| 1751 return true; | 1782 return true; |
| 1752 } | 1783 } |
| 1753 | 1784 |
| 1754 bool ExynosVideoDecodeAccelerator::CreateMfcInputBuffers() { | 1785 bool V4L2VideoDecodeAccelerator::CreateMfcInputBuffers() { |
| 1755 DVLOG(3) << "CreateMfcInputBuffers()"; | 1786 DVLOG(3) << "CreateMfcInputBuffers()"; |
| 1756 // We always run this as we prepare to initialize. | 1787 // We always run this as we prepare to initialize. |
| 1757 DCHECK_EQ(decoder_state_, kUninitialized); | 1788 DCHECK_EQ(decoder_state_, kUninitialized); |
| 1758 DCHECK(!mfc_input_streamon_); | 1789 DCHECK(!mfc_input_streamon_); |
| 1759 DCHECK(mfc_input_buffer_map_.empty()); | 1790 DCHECK(mfc_input_buffer_map_.empty()); |
| 1760 | 1791 |
| 1761 __u32 pixelformat = 0; | 1792 __u32 pixelformat = 0; |
| 1762 if (video_profile_ >= media::H264PROFILE_MIN && | 1793 if (video_profile_ >= media::H264PROFILE_MIN && |
| 1763 video_profile_ <= media::H264PROFILE_MAX) { | 1794 video_profile_ <= media::H264PROFILE_MAX) { |
| 1764 pixelformat = V4L2_PIX_FMT_H264; | 1795 pixelformat = V4L2_PIX_FMT_H264; |
| 1765 } else if (video_profile_ >= media::VP8PROFILE_MIN && | 1796 } else if (video_profile_ >= media::VP8PROFILE_MIN && |
| 1766 video_profile_ <= media::VP8PROFILE_MAX) { | 1797 video_profile_ <= media::VP8PROFILE_MAX) { |
| 1767 pixelformat = V4L2_PIX_FMT_VP8; | 1798 pixelformat = V4L2_PIX_FMT_VP8; |
| 1768 } else { | 1799 } else { |
| 1769 NOTREACHED(); | 1800 NOTREACHED(); |
| 1770 } | 1801 } |
| 1771 | 1802 |
| 1772 struct v4l2_format format; | 1803 struct v4l2_format format; |
| 1773 memset(&format, 0, sizeof(format)); | 1804 memset(&format, 0, sizeof(format)); |
| 1774 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1805 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1775 format.fmt.pix_mp.pixelformat = pixelformat; | 1806 format.fmt.pix_mp.pixelformat = pixelformat; |
| 1776 format.fmt.pix_mp.plane_fmt[0].sizeimage = kMfcInputBufferMaxSize; | 1807 format.fmt.pix_mp.plane_fmt[0].sizeimage = kMfcInputBufferMaxSize; |
| 1777 format.fmt.pix_mp.num_planes = 1; | 1808 format.fmt.pix_mp.num_planes = 1; |
| 1778 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_S_FMT, &format); | 1809 IOCTL_OR_ERROR_RETURN_FALSE(videodec_fd_, VIDIOC_S_FMT, &format); |
| 1779 | 1810 |
| 1780 struct v4l2_requestbuffers reqbufs; | 1811 struct v4l2_requestbuffers reqbufs; |
| 1781 memset(&reqbufs, 0, sizeof(reqbufs)); | 1812 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 1782 reqbufs.count = kMfcInputBufferCount; | 1813 reqbufs.count = kMfcInputBufferCount; |
| 1783 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1814 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1784 reqbufs.memory = V4L2_MEMORY_MMAP; | 1815 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 1785 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_REQBUFS, &reqbufs); | 1816 IOCTL_OR_ERROR_RETURN_FALSE(videodec_fd_, VIDIOC_REQBUFS, &reqbufs); |
| 1786 mfc_input_buffer_map_.resize(reqbufs.count); | 1817 mfc_input_buffer_map_.resize(reqbufs.count); |
| 1787 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) { | 1818 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) { |
| 1788 mfc_free_input_buffers_.push_back(i); | 1819 mfc_free_input_buffers_.push_back(i); |
| 1789 | 1820 |
| 1790 // Query for the MEMORY_MMAP pointer. | 1821 // Query for the MEMORY_MMAP pointer. |
| 1791 struct v4l2_plane planes[1]; | 1822 struct v4l2_plane planes[1]; |
| 1792 struct v4l2_buffer buffer; | 1823 struct v4l2_buffer buffer; |
| 1793 memset(&buffer, 0, sizeof(buffer)); | 1824 memset(&buffer, 0, sizeof(buffer)); |
| 1794 memset(planes, 0, sizeof(planes)); | 1825 memset(planes, 0, sizeof(planes)); |
| 1795 buffer.index = i; | 1826 buffer.index = i; |
| 1796 buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1827 buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1797 buffer.memory = V4L2_MEMORY_MMAP; | 1828 buffer.memory = V4L2_MEMORY_MMAP; |
| 1798 buffer.m.planes = planes; | 1829 buffer.m.planes = planes; |
| 1799 buffer.length = 1; | 1830 buffer.length = 1; |
| 1800 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_QUERYBUF, &buffer); | 1831 IOCTL_OR_ERROR_RETURN_FALSE(videodec_fd_, VIDIOC_QUERYBUF, &buffer); |
| 1801 void* address = mmap(NULL, buffer.m.planes[0].length, | 1832 void* address = device->dev_mmap(NULL, buffer.m.planes[0].length, |
| 1802 PROT_READ | PROT_WRITE, MAP_SHARED, mfc_fd_, | 1833 PROT_READ | PROT_WRITE, MAP_SHARED, videodec_fd_, |
| 1803 buffer.m.planes[0].m.mem_offset); | 1834 buffer.m.planes[0].m.mem_offset); |
| 1804 if (address == MAP_FAILED) { | 1835 if (address == MAP_FAILED) { |
| 1805 DPLOG(ERROR) << "CreateMfcInputBuffers(): mmap() failed"; | 1836 DPLOG(ERROR) << "CreateMfcInputBuffers(): mmap() failed"; |
| 1806 return false; | 1837 return false; |
| 1807 } | 1838 } |
| 1808 mfc_input_buffer_map_[i].address = address; | 1839 mfc_input_buffer_map_[i].address = address; |
| 1809 mfc_input_buffer_map_[i].length = buffer.m.planes[0].length; | 1840 mfc_input_buffer_map_[i].length = buffer.m.planes[0].length; |
| 1810 } | 1841 } |
| 1811 | 1842 |
| 1812 return true; | 1843 return true; |
| 1813 } | 1844 } |
| 1814 | 1845 |
| 1815 bool ExynosVideoDecodeAccelerator::CreateMfcOutputBuffers() { | 1846 bool V4L2VideoDecodeAccelerator::CreateMfcOutputBuffers() { |
| 1816 DVLOG(3) << "CreateMfcOutputBuffers()"; | 1847 DVLOG(3) << "CreateMfcOutputBuffers()"; |
| 1817 DCHECK(decoder_state_ == kInitialized || | 1848 DCHECK(decoder_state_ == kInitialized || |
| 1818 decoder_state_ == kChangingResolution); | 1849 decoder_state_ == kChangingResolution); |
| 1819 DCHECK(!mfc_output_streamon_); | 1850 DCHECK(!mfc_output_streamon_); |
| 1820 DCHECK(mfc_output_buffer_map_.empty()); | 1851 DCHECK(mfc_output_buffer_map_.empty()); |
| 1821 | 1852 |
| 1822 // Number of MFC output buffers we need. | 1853 // Number of MFC output buffers we need. |
| 1823 struct v4l2_control ctrl; | 1854 struct v4l2_control ctrl; |
| 1824 memset(&ctrl, 0, sizeof(ctrl)); | 1855 memset(&ctrl, 0, sizeof(ctrl)); |
| 1825 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; | 1856 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; |
| 1826 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_G_CTRL, &ctrl); | 1857 IOCTL_OR_ERROR_RETURN_FALSE(videodec_fd_, VIDIOC_G_CTRL, &ctrl); |
| 1827 mfc_output_dpb_size_ = ctrl.value; | 1858 mfc_output_dpb_size_ = ctrl.value; |
| 1828 | 1859 |
| 1829 // Output format setup in Initialize(). | 1860 // Output format setup in Initialize(). |
| 1830 | 1861 |
| 1831 // Allocate the output buffers. | 1862 // Allocate the output buffers. |
| 1832 struct v4l2_requestbuffers reqbufs; | 1863 struct v4l2_requestbuffers reqbufs; |
| 1833 memset(&reqbufs, 0, sizeof(reqbufs)); | 1864 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 1834 reqbufs.count = mfc_output_dpb_size_ + kDpbOutputBufferExtraCount; | 1865 reqbufs.count = mfc_output_dpb_size_ + kDpbOutputBufferExtraCount; |
| 1835 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1866 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1836 reqbufs.memory = V4L2_MEMORY_MMAP; | 1867 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 1837 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_REQBUFS, &reqbufs); | 1868 IOCTL_OR_ERROR_RETURN_FALSE(videodec_fd_, VIDIOC_REQBUFS, &reqbufs); |
| 1838 | 1869 |
| 1839 // Create DMABUFs from output buffers. | 1870 // Create DMABUFs from output buffers. |
| 1840 mfc_output_buffer_map_.resize(reqbufs.count); | 1871 mfc_output_buffer_map_.resize(reqbufs.count); |
| 1841 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) { | 1872 for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) { |
| 1842 MfcOutputRecord& output_record = mfc_output_buffer_map_[i]; | 1873 MfcOutputRecord& output_record = mfc_output_buffer_map_[i]; |
| 1843 for (size_t j = 0; j < arraysize(output_record.fds); ++j) { | 1874 for (size_t j = 0; j < arraysize(output_record.fds); ++j) { |
| 1844 // Export the DMABUF fd so we can export it as a texture. | 1875 // Export the DMABUF fd so we can export it as a texture. |
| 1845 struct v4l2_exportbuffer expbuf; | 1876 struct v4l2_exportbuffer expbuf; |
| 1846 memset(&expbuf, 0, sizeof(expbuf)); | 1877 memset(&expbuf, 0, sizeof(expbuf)); |
| 1847 expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1878 expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1848 expbuf.index = i; | 1879 expbuf.index = i; |
| 1849 expbuf.plane = j; | 1880 expbuf.plane = j; |
| 1850 expbuf.flags = O_CLOEXEC; | 1881 expbuf.flags = O_CLOEXEC; |
| 1851 IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_EXPBUF, &expbuf); | 1882 IOCTL_OR_ERROR_RETURN_FALSE(videodec_fd_, VIDIOC_EXPBUF, &expbuf); |
| 1852 output_record.fds[j] = expbuf.fd; | 1883 output_record.fds[j] = expbuf.fd; |
| 1853 } | 1884 } |
| 1854 } | 1885 } |
| 1855 | 1886 |
| 1856 DVLOG(3) << "CreateMfcOutputBuffers(): ProvidePictureBuffers(): " | 1887 DVLOG(3) << "CreateMfcOutputBuffers(): ProvidePictureBuffers(): " |
| 1857 << "buffer_count=" << mfc_output_buffer_map_.size() | 1888 << "buffer_count=" << mfc_output_buffer_map_.size() |
| 1858 << ", width=" << frame_buffer_size_.width() | 1889 << ", width=" << frame_buffer_size_.width() |
| 1859 << ", height=" << frame_buffer_size_.height(); | 1890 << ", height=" << frame_buffer_size_.height(); |
| 1860 child_message_loop_proxy_->PostTask(FROM_HERE, | 1891 child_message_loop_proxy_->PostTask(FROM_HERE, |
| 1861 base::Bind(&Client::ProvidePictureBuffers, | 1892 base::Bind(&Client::ProvidePictureBuffers, |
| 1862 client_, | 1893 client_, |
| 1863 mfc_output_buffer_map_.size(), | 1894 mfc_output_buffer_map_.size(), |
| 1864 frame_buffer_size_, | 1895 frame_buffer_size_, |
| 1865 GL_TEXTURE_EXTERNAL_OES)); | 1896 GL_TEXTURE_EXTERNAL_OES)); |
| 1866 | 1897 |
| 1867 return true; | 1898 return true; |
| 1868 } | 1899 } |
| 1869 | 1900 |
| 1870 void ExynosVideoDecodeAccelerator::DestroyMfcInputBuffers() { | 1901 void V4L2VideoDecodeAccelerator::DestroyMfcInputBuffers() { |
| 1871 DVLOG(3) << "DestroyMfcInputBuffers()"; | 1902 DVLOG(3) << "DestroyMfcInputBuffers()"; |
| 1872 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1903 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 1873 DCHECK(!mfc_input_streamon_); | 1904 DCHECK(!mfc_input_streamon_); |
| 1874 | 1905 |
| 1875 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) { | 1906 for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) { |
| 1876 if (mfc_input_buffer_map_[i].address != NULL) { | 1907 if (mfc_input_buffer_map_[i].address != NULL) { |
| 1877 munmap(mfc_input_buffer_map_[i].address, | 1908 device->dev_munmap(mfc_input_buffer_map_[i].address, |
| 1878 mfc_input_buffer_map_[i].length); | 1909 mfc_input_buffer_map_[i].length); |
| 1879 } | 1910 } |
| 1880 } | 1911 } |
| 1881 | 1912 |
| 1882 struct v4l2_requestbuffers reqbufs; | 1913 struct v4l2_requestbuffers reqbufs; |
| 1883 memset(&reqbufs, 0, sizeof(reqbufs)); | 1914 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 1884 reqbufs.count = 0; | 1915 reqbufs.count = 0; |
| 1885 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1916 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 1886 reqbufs.memory = V4L2_MEMORY_MMAP; | 1917 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 1887 if (ioctl(mfc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0) | 1918 if (device->dev_ioctl(videodec_fd_, VIDIOC_REQBUFS, &reqbufs) != 0) |
| 1888 DPLOG(ERROR) << "DestroyMfcInputBuffers(): ioctl() failed: VIDIOC_REQBUFS"; | 1919 DPLOG(ERROR) << "DestroyMfcInputBuffers(): ioctl() failed: VIDIOC_REQBUFS"; |
| 1889 | 1920 |
| 1890 mfc_input_buffer_map_.clear(); | 1921 mfc_input_buffer_map_.clear(); |
| 1891 mfc_free_input_buffers_.clear(); | 1922 mfc_free_input_buffers_.clear(); |
| 1892 } | 1923 } |
| 1893 | 1924 |
| 1894 void ExynosVideoDecodeAccelerator::DestroyMfcOutputBuffers() { | 1925 void V4L2VideoDecodeAccelerator::DestroyMfcOutputBuffers() { |
| 1895 DVLOG(3) << "DestroyMfcOutputBuffers()"; | 1926 DVLOG(3) << "DestroyMfcOutputBuffers()"; |
| 1896 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1927 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 1897 DCHECK(!mfc_output_streamon_); | 1928 DCHECK(!mfc_output_streamon_); |
| 1898 | 1929 |
| 1899 if (mfc_output_buffer_map_.size() != 0) { | 1930 if (mfc_output_buffer_map_.size() != 0) { |
| 1931 // TODO(sheu, posciak): Making the context current should not be required | |
| 1932 // anymore. Remove it and verify (crbug.com/327869). | |
| 1900 if (!make_context_current_.Run()) { | 1933 if (!make_context_current_.Run()) { |
| 1901 DLOG(ERROR) << "DestroyMfcOutputBuffers(): " | 1934 DLOG(ERROR) << "DestroyMfcOutputBuffers(): " |
| 1902 << "could not make context current"; | 1935 << "could not make context current"; |
| 1903 } else { | 1936 } else { |
| 1904 size_t i = 0; | 1937 size_t i = 0; |
| 1905 do { | 1938 do { |
| 1906 MfcOutputRecord& output_record = mfc_output_buffer_map_[i]; | 1939 MfcOutputRecord& output_record = mfc_output_buffer_map_[i]; |
| 1907 for (size_t j = 0; j < arraysize(output_record.fds); ++j) { | 1940 for (size_t j = 0; j < arraysize(output_record.fds); ++j) { |
| 1908 if (output_record.fds[j] != -1) | 1941 if (output_record.fds[j] != -1) |
| 1909 close(output_record.fds[j]); | 1942 device->dev_close(output_record.fds[j]); |
| 1910 if (output_record.egl_image != EGL_NO_IMAGE_KHR) | 1943 if (output_record.egl_image != EGL_NO_IMAGE_KHR) |
| 1911 eglDestroyImageKHR(egl_display_, output_record.egl_image); | 1944 eglDestroyImageKHR(egl_display_, output_record.egl_image); |
| 1912 if (output_record.egl_sync != EGL_NO_SYNC_KHR) | 1945 if (output_record.egl_sync != EGL_NO_SYNC_KHR) |
| 1913 eglDestroySyncKHR(egl_display_, output_record.egl_sync); | 1946 eglDestroySyncKHR(egl_display_, output_record.egl_sync); |
| 1914 } | 1947 } |
| 1915 DVLOG(1) << "DestroyMfcOutputBuffers(): dismissing PictureBuffer id=" | 1948 DVLOG(1) << "DestroyMfcOutputBuffers(): dismissing PictureBuffer id=" |
| 1916 << output_record.picture_id; | 1949 << output_record.picture_id; |
| 1917 child_message_loop_proxy_->PostTask( | 1950 child_message_loop_proxy_->PostTask( |
| 1918 FROM_HERE, | 1951 FROM_HERE, |
| 1919 base::Bind(&Client::DismissPictureBuffer, | 1952 base::Bind(&Client::DismissPictureBuffer, |
| 1920 client_, | 1953 client_, |
| 1921 output_record.picture_id)); | 1954 output_record.picture_id)); |
| 1922 i++; | 1955 i++; |
| 1923 } while (i < mfc_output_buffer_map_.size()); | 1956 } while (i < mfc_output_buffer_map_.size()); |
| 1924 } | 1957 } |
| 1925 } | 1958 } |
| 1926 | 1959 |
| 1927 struct v4l2_requestbuffers reqbufs; | 1960 struct v4l2_requestbuffers reqbufs; |
| 1928 memset(&reqbufs, 0, sizeof(reqbufs)); | 1961 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 1929 reqbufs.count = 0; | 1962 reqbufs.count = 0; |
| 1930 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1963 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 1931 reqbufs.memory = V4L2_MEMORY_MMAP; | 1964 reqbufs.memory = V4L2_MEMORY_MMAP; |
| 1932 if (ioctl(mfc_fd_, VIDIOC_REQBUFS, &reqbufs) != 0) | 1965 if (device->dev_ioctl(videodec_fd_, VIDIOC_REQBUFS, &reqbufs) != 0) |
| 1933 DPLOG(ERROR) << "DestroyMfcOutputBuffers() ioctl() failed: VIDIOC_REQBUFS"; | 1966 DPLOG(ERROR) << "DestroyMfcOutputBuffers() ioctl() failed: VIDIOC_REQBUFS"; |
| 1934 | 1967 |
| 1935 mfc_output_buffer_map_.clear(); | 1968 mfc_output_buffer_map_.clear(); |
| 1936 while (!mfc_free_output_buffers_.empty()) | 1969 while (!mfc_free_output_buffers_.empty()) |
| 1937 mfc_free_output_buffers_.pop(); | 1970 mfc_free_output_buffers_.pop(); |
| 1938 } | 1971 } |
| 1939 | 1972 |
| 1940 void ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers() { | 1973 void V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers() { |
| 1941 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1974 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
| 1942 DVLOG(3) << "ResolutionChangeDestroyBuffers()"; | 1975 DVLOG(3) << "ResolutionChangeDestroyBuffers()"; |
| 1943 | 1976 |
| 1944 DestroyMfcOutputBuffers(); | 1977 DestroyMfcOutputBuffers(); |
| 1945 | 1978 |
| 1946 // Finish resolution change on decoder thread. | 1979 // Finish resolution change on decoder thread. |
| 1947 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1980 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
| 1948 &ExynosVideoDecodeAccelerator::FinishResolutionChange, | 1981 &V4L2VideoDecodeAccelerator::FinishResolutionChange, |
| 1949 base::Unretained(this))); | 1982 base::Unretained(this))); |
| 1950 } | 1983 } |
| 1951 | 1984 |
| 1952 void ExynosVideoDecodeAccelerator::SendPictureReady() { | 1985 void V4L2VideoDecodeAccelerator::SendPictureReady() { |
| 1953 DVLOG(3) << "SendPictureReady()"; | 1986 DVLOG(3) << "SendPictureReady()"; |
| 1954 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1987 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1955 bool resetting_or_flushing = | 1988 bool resetting_or_flushing = |
| 1956 (decoder_state_ == kResetting || decoder_flushing_); | 1989 (decoder_state_ == kResetting || decoder_flushing_); |
| 1957 while (pending_picture_ready_.size() > 0) { | 1990 while (pending_picture_ready_.size() > 0) { |
| 1958 bool cleared = pending_picture_ready_.front().cleared; | 1991 bool cleared = pending_picture_ready_.front().cleared; |
| 1959 const media::Picture& picture = pending_picture_ready_.front().picture; | 1992 const media::Picture& picture = pending_picture_ready_.front().picture; |
| 1960 if (cleared && picture_clearing_count_ == 0) { | 1993 if (cleared && picture_clearing_count_ == 0) { |
| 1961 // This picture is cleared. Post it to IO thread to reduce latency. This | 1994 // This picture is cleared. Post it to IO thread to reduce latency. This |
| 1962 // should be the case after all pictures are cleared at the beginning. | 1995 // should be the case after all pictures are cleared at the beginning. |
| 1963 io_message_loop_proxy_->PostTask( | 1996 io_message_loop_proxy_->PostTask( |
| 1964 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture)); | 1997 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture)); |
| 1965 pending_picture_ready_.pop(); | 1998 pending_picture_ready_.pop(); |
| 1966 } else if (!cleared || resetting_or_flushing) { | 1999 } else if (!cleared || resetting_or_flushing) { |
| 1967 DVLOG(3) << "SendPictureReady()" | 2000 DVLOG(3) << "SendPictureReady()" |
| 1968 << ". cleared=" << pending_picture_ready_.front().cleared | 2001 << ". cleared=" << pending_picture_ready_.front().cleared |
| 1969 << ", decoder_state_=" << decoder_state_ | 2002 << ", decoder_state_=" << decoder_state_ |
| 1970 << ", decoder_flushing_=" << decoder_flushing_ | 2003 << ", decoder_flushing_=" << decoder_flushing_ |
| 1971 << ", picture_clearing_count_=" << picture_clearing_count_; | 2004 << ", picture_clearing_count_=" << picture_clearing_count_; |
| 1972 // If the picture is not cleared, post it to the child thread because it | 2005 // If the picture is not cleared, post it to the child thread because it |
| 1973 // has to be cleared in the child thread. A picture only needs to be | 2006 // has to be cleared in the child thread. A picture only needs to be |
| 1974 // cleared once. If the decoder is resetting or flushing, send all | 2007 // cleared once. If the decoder is resetting or flushing, send all |
| 1975 // pictures to ensure PictureReady arrive before reset or flush done. | 2008 // pictures to ensure PictureReady arrive before reset or flush done. |
| 1976 child_message_loop_proxy_->PostTaskAndReply( | 2009 child_message_loop_proxy_->PostTaskAndReply( |
| 1977 FROM_HERE, | 2010 FROM_HERE, |
| 1978 base::Bind(&Client::PictureReady, client_, picture), | 2011 base::Bind(&Client::PictureReady, client_, picture), |
| 1979 // Unretained is safe. If Client::PictureReady gets to run, |this| is | 2012 // Unretained is safe. If Client::PictureReady gets to run, |this| is |
| 1980 // alive. Destroy() will wait the decode thread to finish. | 2013 // alive. Destroy() will wait the decode thread to finish. |
| 1981 base::Bind(&ExynosVideoDecodeAccelerator::PictureCleared, | 2014 base::Bind(&V4L2VideoDecodeAccelerator::PictureCleared, |
| 1982 base::Unretained(this))); | 2015 base::Unretained(this))); |
| 1983 picture_clearing_count_++; | 2016 picture_clearing_count_++; |
| 1984 pending_picture_ready_.pop(); | 2017 pending_picture_ready_.pop(); |
| 1985 } else { | 2018 } else { |
| 1986 // This picture is cleared. But some pictures are about to be cleared on | 2019 // This picture is cleared. But some pictures are about to be cleared on |
| 1987 // the child thread. To preserve the order, do not send this until those | 2020 // the child thread. To preserve the order, do not send this until those |
| 1988 // pictures are cleared. | 2021 // pictures are cleared. |
| 1989 break; | 2022 break; |
| 1990 } | 2023 } |
| 1991 } | 2024 } |
| 1992 } | 2025 } |
| 1993 | 2026 |
| 1994 void ExynosVideoDecodeAccelerator::PictureCleared() { | 2027 void V4L2VideoDecodeAccelerator::PictureCleared() { |
| 1995 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; | 2028 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; |
| 1996 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 2029 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
| 1997 DCHECK_GT(picture_clearing_count_, 0); | 2030 DCHECK_GT(picture_clearing_count_, 0); |
| 1998 picture_clearing_count_--; | 2031 picture_clearing_count_--; |
| 1999 SendPictureReady(); | 2032 SendPictureReady(); |
| 2000 } | 2033 } |
| 2001 | 2034 |
| 2002 } // namespace content | 2035 } // namespace content |
| OLD | NEW |