OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <dlfcn.h> | 5 #include <dlfcn.h> |
6 #include <errno.h> | 6 #include <errno.h> |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <linux/videodev2.h> | 8 #include <linux/videodev2.h> |
9 #include <poll.h> | 9 #include <poll.h> |
10 #include <sys/eventfd.h> | 10 #include <sys/eventfd.h> |
11 #include <sys/ioctl.h> | 11 #include <sys/ioctl.h> |
12 #include <sys/mman.h> | 12 #include <sys/mman.h> |
13 | 13 |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
16 #include "base/memory/shared_memory.h" | 16 #include "base/memory/shared_memory.h" |
17 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
18 #include "base/message_loop/message_loop_proxy.h" | |
19 #include "base/numerics/safe_conversions.h" | 18 #include "base/numerics/safe_conversions.h" |
| 19 #include "base/thread_task_runner_handle.h" |
20 #include "base/trace_event/trace_event.h" | 20 #include "base/trace_event/trace_event.h" |
21 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" | 21 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" |
22 #include "media/base/media_switches.h" | 22 #include "media/base/media_switches.h" |
23 #include "media/filters/h264_parser.h" | 23 #include "media/filters/h264_parser.h" |
24 #include "ui/gfx/geometry/rect.h" | 24 #include "ui/gfx/geometry/rect.h" |
25 #include "ui/gl/scoped_binders.h" | 25 #include "ui/gl/scoped_binders.h" |
26 | 26 |
27 #define NOTIFY_ERROR(x) \ | 27 #define NOTIFY_ERROR(x) \ |
28 do { \ | 28 do { \ |
29 LOG(ERROR) << "Setting error state:" << x; \ | 29 LOG(ERROR) << "Setting error state:" << x; \ |
(...skipping 28 matching lines...) Expand all Loading... |
58 // TODO(posciak): remove once we update linux-headers. | 58 // TODO(posciak): remove once we update linux-headers. |
59 #ifndef V4L2_EVENT_RESOLUTION_CHANGE | 59 #ifndef V4L2_EVENT_RESOLUTION_CHANGE |
60 #define V4L2_EVENT_RESOLUTION_CHANGE 5 | 60 #define V4L2_EVENT_RESOLUTION_CHANGE 5 |
61 #endif | 61 #endif |
62 | 62 |
63 } // anonymous namespace | 63 } // anonymous namespace |
64 | 64 |
65 struct V4L2VideoDecodeAccelerator::BitstreamBufferRef { | 65 struct V4L2VideoDecodeAccelerator::BitstreamBufferRef { |
66 BitstreamBufferRef( | 66 BitstreamBufferRef( |
67 base::WeakPtr<Client>& client, | 67 base::WeakPtr<Client>& client, |
68 scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy, | 68 scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, |
69 base::SharedMemory* shm, | 69 base::SharedMemory* shm, |
70 size_t size, | 70 size_t size, |
71 int32 input_id); | 71 int32 input_id); |
72 ~BitstreamBufferRef(); | 72 ~BitstreamBufferRef(); |
73 const base::WeakPtr<Client> client; | 73 const base::WeakPtr<Client> client; |
74 const scoped_refptr<base::MessageLoopProxy> client_message_loop_proxy; | 74 const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner; |
75 const scoped_ptr<base::SharedMemory> shm; | 75 const scoped_ptr<base::SharedMemory> shm; |
76 const size_t size; | 76 const size_t size; |
77 size_t bytes_used; | 77 size_t bytes_used; |
78 const int32 input_id; | 78 const int32 input_id; |
79 }; | 79 }; |
80 | 80 |
81 struct V4L2VideoDecodeAccelerator::EGLSyncKHRRef { | 81 struct V4L2VideoDecodeAccelerator::EGLSyncKHRRef { |
82 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); | 82 EGLSyncKHRRef(EGLDisplay egl_display, EGLSyncKHR egl_sync); |
83 ~EGLSyncKHRRef(); | 83 ~EGLSyncKHRRef(); |
84 EGLDisplay const egl_display; | 84 EGLDisplay const egl_display; |
85 EGLSyncKHR egl_sync; | 85 EGLSyncKHR egl_sync; |
86 }; | 86 }; |
87 | 87 |
88 struct V4L2VideoDecodeAccelerator::PictureRecord { | 88 struct V4L2VideoDecodeAccelerator::PictureRecord { |
89 PictureRecord(bool cleared, const media::Picture& picture); | 89 PictureRecord(bool cleared, const media::Picture& picture); |
90 ~PictureRecord(); | 90 ~PictureRecord(); |
91 bool cleared; // Whether the texture is cleared and safe to render from. | 91 bool cleared; // Whether the texture is cleared and safe to render from. |
92 media::Picture picture; // The decoded picture. | 92 media::Picture picture; // The decoded picture. |
93 }; | 93 }; |
94 | 94 |
95 V4L2VideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( | 95 V4L2VideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef( |
96 base::WeakPtr<Client>& client, | 96 base::WeakPtr<Client>& client, |
97 scoped_refptr<base::MessageLoopProxy>& client_message_loop_proxy, | 97 scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner, |
98 base::SharedMemory* shm, size_t size, int32 input_id) | 98 base::SharedMemory* shm, |
| 99 size_t size, |
| 100 int32 input_id) |
99 : client(client), | 101 : client(client), |
100 client_message_loop_proxy(client_message_loop_proxy), | 102 client_task_runner(client_task_runner), |
101 shm(shm), | 103 shm(shm), |
102 size(size), | 104 size(size), |
103 bytes_used(0), | 105 bytes_used(0), |
104 input_id(input_id) { | 106 input_id(input_id) { |
105 } | 107 } |
106 | 108 |
107 V4L2VideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { | 109 V4L2VideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() { |
108 if (input_id >= 0) { | 110 if (input_id >= 0) { |
109 client_message_loop_proxy->PostTask(FROM_HERE, base::Bind( | 111 client_task_runner->PostTask( |
110 &Client::NotifyEndOfBitstreamBuffer, client, input_id)); | 112 FROM_HERE, |
| 113 base::Bind(&Client::NotifyEndOfBitstreamBuffer, client, input_id)); |
111 } | 114 } |
112 } | 115 } |
113 | 116 |
114 V4L2VideoDecodeAccelerator::EGLSyncKHRRef::EGLSyncKHRRef( | 117 V4L2VideoDecodeAccelerator::EGLSyncKHRRef::EGLSyncKHRRef( |
115 EGLDisplay egl_display, EGLSyncKHR egl_sync) | 118 EGLDisplay egl_display, EGLSyncKHR egl_sync) |
116 : egl_display(egl_display), | 119 : egl_display(egl_display), |
117 egl_sync(egl_sync) { | 120 egl_sync(egl_sync) { |
118 } | 121 } |
119 | 122 |
120 V4L2VideoDecodeAccelerator::EGLSyncKHRRef::~EGLSyncKHRRef() { | 123 V4L2VideoDecodeAccelerator::EGLSyncKHRRef::~EGLSyncKHRRef() { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 : cleared(cleared), picture(picture) {} | 156 : cleared(cleared), picture(picture) {} |
154 | 157 |
155 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {} | 158 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {} |
156 | 159 |
157 V4L2VideoDecodeAccelerator::V4L2VideoDecodeAccelerator( | 160 V4L2VideoDecodeAccelerator::V4L2VideoDecodeAccelerator( |
158 EGLDisplay egl_display, | 161 EGLDisplay egl_display, |
159 EGLContext egl_context, | 162 EGLContext egl_context, |
160 const base::WeakPtr<Client>& io_client, | 163 const base::WeakPtr<Client>& io_client, |
161 const base::Callback<bool(void)>& make_context_current, | 164 const base::Callback<bool(void)>& make_context_current, |
162 const scoped_refptr<V4L2Device>& device, | 165 const scoped_refptr<V4L2Device>& device, |
163 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy) | 166 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) |
164 : child_message_loop_proxy_(base::MessageLoopProxy::current()), | 167 : child_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
165 io_message_loop_proxy_(io_message_loop_proxy), | 168 io_task_runner_(io_task_runner), |
166 io_client_(io_client), | 169 io_client_(io_client), |
167 decoder_thread_("V4L2DecoderThread"), | 170 decoder_thread_("V4L2DecoderThread"), |
168 decoder_state_(kUninitialized), | 171 decoder_state_(kUninitialized), |
169 device_(device), | 172 device_(device), |
170 decoder_delay_bitstream_buffer_id_(-1), | 173 decoder_delay_bitstream_buffer_id_(-1), |
171 decoder_current_input_buffer_(-1), | 174 decoder_current_input_buffer_(-1), |
172 decoder_decode_buffer_tasks_scheduled_(0), | 175 decoder_decode_buffer_tasks_scheduled_(0), |
173 decoder_frames_at_client_(0), | 176 decoder_frames_at_client_(0), |
174 decoder_flushing_(false), | 177 decoder_flushing_(false), |
175 resolution_change_pending_(false), | 178 resolution_change_pending_(false), |
(...skipping 26 matching lines...) Expand all Loading... |
202 | 205 |
203 // These maps have members that should be manually destroyed, e.g. file | 206 // These maps have members that should be manually destroyed, e.g. file |
204 // descriptors, mmap() segments, etc. | 207 // descriptors, mmap() segments, etc. |
205 DCHECK(input_buffer_map_.empty()); | 208 DCHECK(input_buffer_map_.empty()); |
206 DCHECK(output_buffer_map_.empty()); | 209 DCHECK(output_buffer_map_.empty()); |
207 } | 210 } |
208 | 211 |
209 bool V4L2VideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, | 212 bool V4L2VideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, |
210 Client* client) { | 213 Client* client) { |
211 DVLOG(3) << "Initialize()"; | 214 DVLOG(3) << "Initialize()"; |
212 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 215 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
213 DCHECK_EQ(decoder_state_, kUninitialized); | 216 DCHECK_EQ(decoder_state_, kUninitialized); |
214 | 217 |
215 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); | 218 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); |
216 client_ = client_ptr_factory_->GetWeakPtr(); | 219 client_ = client_ptr_factory_->GetWeakPtr(); |
217 | 220 |
218 switch (profile) { | 221 switch (profile) { |
219 case media::H264PROFILE_BASELINE: | 222 case media::H264PROFILE_BASELINE: |
220 DVLOG(2) << "Initialize(): profile H264PROFILE_BASELINE"; | 223 DVLOG(2) << "Initialize(): profile H264PROFILE_BASELINE"; |
221 break; | 224 break; |
222 case media::H264PROFILE_MAIN: | 225 case media::H264PROFILE_MAIN: |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 base::IgnoreResult(&V4L2VideoDecodeAccelerator::StartDevicePoll), | 303 base::IgnoreResult(&V4L2VideoDecodeAccelerator::StartDevicePoll), |
301 base::Unretained(this))); | 304 base::Unretained(this))); |
302 | 305 |
303 return true; | 306 return true; |
304 } | 307 } |
305 | 308 |
306 void V4L2VideoDecodeAccelerator::Decode( | 309 void V4L2VideoDecodeAccelerator::Decode( |
307 const media::BitstreamBuffer& bitstream_buffer) { | 310 const media::BitstreamBuffer& bitstream_buffer) { |
308 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() | 311 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() |
309 << ", size=" << bitstream_buffer.size(); | 312 << ", size=" << bitstream_buffer.size(); |
310 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); | 313 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
311 | 314 |
312 // DecodeTask() will take care of running a DecodeBufferTask(). | 315 // DecodeTask() will take care of running a DecodeBufferTask(). |
313 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 316 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
314 &V4L2VideoDecodeAccelerator::DecodeTask, base::Unretained(this), | 317 &V4L2VideoDecodeAccelerator::DecodeTask, base::Unretained(this), |
315 bitstream_buffer)); | 318 bitstream_buffer)); |
316 } | 319 } |
317 | 320 |
318 void V4L2VideoDecodeAccelerator::AssignPictureBuffers( | 321 void V4L2VideoDecodeAccelerator::AssignPictureBuffers( |
319 const std::vector<media::PictureBuffer>& buffers) { | 322 const std::vector<media::PictureBuffer>& buffers) { |
320 DVLOG(3) << "AssignPictureBuffers(): buffer_count=" << buffers.size(); | 323 DVLOG(3) << "AssignPictureBuffers(): buffer_count=" << buffers.size(); |
321 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 324 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
322 | 325 |
323 if (buffers.size() != output_buffer_map_.size()) { | 326 if (buffers.size() != output_buffer_map_.size()) { |
324 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" | 327 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" |
325 " buffers. (Got " << buffers.size() | 328 " buffers. (Got " << buffers.size() |
326 << ", requested " << output_buffer_map_.size() << ")"; | 329 << ", requested " << output_buffer_map_.size() << ")"; |
327 NOTIFY_ERROR(INVALID_ARGUMENT); | 330 NOTIFY_ERROR(INVALID_ARGUMENT); |
328 return; | 331 return; |
329 } | 332 } |
330 | 333 |
331 if (!make_context_current_.Run()) { | 334 if (!make_context_current_.Run()) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i | 375 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i |
373 << "]: picture_id=" << output_record.picture_id; | 376 << "]: picture_id=" << output_record.picture_id; |
374 } | 377 } |
375 | 378 |
376 pictures_assigned_.Signal(); | 379 pictures_assigned_.Signal(); |
377 } | 380 } |
378 | 381 |
379 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { | 382 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { |
380 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; | 383 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; |
381 // Must be run on child thread, as we'll insert a sync in the EGL context. | 384 // Must be run on child thread, as we'll insert a sync in the EGL context. |
382 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 385 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
383 | 386 |
384 if (!make_context_current_.Run()) { | 387 if (!make_context_current_.Run()) { |
385 LOG(ERROR) << "ReusePictureBuffer(): could not make context current"; | 388 LOG(ERROR) << "ReusePictureBuffer(): could not make context current"; |
386 NOTIFY_ERROR(PLATFORM_FAILURE); | 389 NOTIFY_ERROR(PLATFORM_FAILURE); |
387 return; | 390 return; |
388 } | 391 } |
389 | 392 |
390 EGLSyncKHR egl_sync = EGL_NO_SYNC_KHR; | 393 EGLSyncKHR egl_sync = EGL_NO_SYNC_KHR; |
391 // TODO(posciak): crbug.com/450898. | 394 // TODO(posciak): crbug.com/450898. |
392 #if defined(ARCH_CPU_ARMEL) | 395 #if defined(ARCH_CPU_ARMEL) |
393 egl_sync = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); | 396 egl_sync = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); |
394 if (egl_sync == EGL_NO_SYNC_KHR) { | 397 if (egl_sync == EGL_NO_SYNC_KHR) { |
395 LOG(ERROR) << "ReusePictureBuffer(): eglCreateSyncKHR() failed"; | 398 LOG(ERROR) << "ReusePictureBuffer(): eglCreateSyncKHR() failed"; |
396 NOTIFY_ERROR(PLATFORM_FAILURE); | 399 NOTIFY_ERROR(PLATFORM_FAILURE); |
397 return; | 400 return; |
398 } | 401 } |
399 #endif | 402 #endif |
400 | 403 |
401 scoped_ptr<EGLSyncKHRRef> egl_sync_ref(new EGLSyncKHRRef( | 404 scoped_ptr<EGLSyncKHRRef> egl_sync_ref(new EGLSyncKHRRef( |
402 egl_display_, egl_sync)); | 405 egl_display_, egl_sync)); |
403 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 406 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
404 &V4L2VideoDecodeAccelerator::ReusePictureBufferTask, | 407 &V4L2VideoDecodeAccelerator::ReusePictureBufferTask, |
405 base::Unretained(this), picture_buffer_id, base::Passed(&egl_sync_ref))); | 408 base::Unretained(this), picture_buffer_id, base::Passed(&egl_sync_ref))); |
406 } | 409 } |
407 | 410 |
408 void V4L2VideoDecodeAccelerator::Flush() { | 411 void V4L2VideoDecodeAccelerator::Flush() { |
409 DVLOG(3) << "Flush()"; | 412 DVLOG(3) << "Flush()"; |
410 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 413 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
411 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 414 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
412 &V4L2VideoDecodeAccelerator::FlushTask, base::Unretained(this))); | 415 &V4L2VideoDecodeAccelerator::FlushTask, base::Unretained(this))); |
413 } | 416 } |
414 | 417 |
415 void V4L2VideoDecodeAccelerator::Reset() { | 418 void V4L2VideoDecodeAccelerator::Reset() { |
416 DVLOG(3) << "Reset()"; | 419 DVLOG(3) << "Reset()"; |
417 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 420 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
418 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 421 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
419 &V4L2VideoDecodeAccelerator::ResetTask, base::Unretained(this))); | 422 &V4L2VideoDecodeAccelerator::ResetTask, base::Unretained(this))); |
420 } | 423 } |
421 | 424 |
422 void V4L2VideoDecodeAccelerator::Destroy() { | 425 void V4L2VideoDecodeAccelerator::Destroy() { |
423 DVLOG(3) << "Destroy()"; | 426 DVLOG(3) << "Destroy()"; |
424 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 427 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
425 | 428 |
426 // We're destroying; cancel all callbacks. | 429 // We're destroying; cancel all callbacks. |
427 client_ptr_factory_.reset(); | 430 client_ptr_factory_.reset(); |
428 weak_this_factory_.InvalidateWeakPtrs(); | 431 weak_this_factory_.InvalidateWeakPtrs(); |
429 | 432 |
430 // If the decoder thread is running, destroy using posted task. | 433 // If the decoder thread is running, destroy using posted task. |
431 if (decoder_thread_.IsRunning()) { | 434 if (decoder_thread_.IsRunning()) { |
432 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 435 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
433 &V4L2VideoDecodeAccelerator::DestroyTask, base::Unretained(this))); | 436 &V4L2VideoDecodeAccelerator::DestroyTask, base::Unretained(this))); |
434 pictures_assigned_.Signal(); | 437 pictures_assigned_.Signal(); |
(...skipping 24 matching lines...) Expand all Loading... |
459 | 462 |
460 void V4L2VideoDecodeAccelerator::DecodeTask( | 463 void V4L2VideoDecodeAccelerator::DecodeTask( |
461 const media::BitstreamBuffer& bitstream_buffer) { | 464 const media::BitstreamBuffer& bitstream_buffer) { |
462 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); | 465 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); |
463 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 466 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
464 DCHECK_NE(decoder_state_, kUninitialized); | 467 DCHECK_NE(decoder_state_, kUninitialized); |
465 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", | 468 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", |
466 bitstream_buffer.id()); | 469 bitstream_buffer.id()); |
467 | 470 |
468 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( | 471 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( |
469 io_client_, io_message_loop_proxy_, | 472 io_client_, io_task_runner_, |
470 new base::SharedMemory(bitstream_buffer.handle(), true), | 473 new base::SharedMemory(bitstream_buffer.handle(), true), |
471 bitstream_buffer.size(), bitstream_buffer.id())); | 474 bitstream_buffer.size(), bitstream_buffer.id())); |
472 if (!bitstream_record->shm->Map(bitstream_buffer.size())) { | 475 if (!bitstream_record->shm->Map(bitstream_buffer.size())) { |
473 LOG(ERROR) << "Decode(): could not map bitstream_buffer"; | 476 LOG(ERROR) << "Decode(): could not map bitstream_buffer"; |
474 NOTIFY_ERROR(UNREADABLE_INPUT); | 477 NOTIFY_ERROR(UNREADABLE_INPUT); |
475 return; | 478 return; |
476 } | 479 } |
477 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory(); | 480 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory(); |
478 | 481 |
479 if (decoder_state_ == kResetting || decoder_flushing_) { | 482 if (decoder_state_ == kResetting || decoder_flushing_) { |
(...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 | 1239 |
1237 void V4L2VideoDecodeAccelerator::FlushTask() { | 1240 void V4L2VideoDecodeAccelerator::FlushTask() { |
1238 DVLOG(3) << "FlushTask()"; | 1241 DVLOG(3) << "FlushTask()"; |
1239 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1242 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1240 TRACE_EVENT0("Video Decoder", "V4L2VDA::FlushTask"); | 1243 TRACE_EVENT0("Video Decoder", "V4L2VDA::FlushTask"); |
1241 | 1244 |
1242 // Flush outstanding buffers. | 1245 // Flush outstanding buffers. |
1243 if (decoder_state_ == kInitialized || decoder_state_ == kAfterReset) { | 1246 if (decoder_state_ == kInitialized || decoder_state_ == kAfterReset) { |
1244 // There's nothing in the pipe, so return done immediately. | 1247 // There's nothing in the pipe, so return done immediately. |
1245 DVLOG(3) << "FlushTask(): returning flush"; | 1248 DVLOG(3) << "FlushTask(): returning flush"; |
1246 child_message_loop_proxy_->PostTask( | 1249 child_task_runner_->PostTask(FROM_HERE, |
1247 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_)); | 1250 base::Bind(&Client::NotifyFlushDone, client_)); |
1248 return; | 1251 return; |
1249 } else if (decoder_state_ == kError) { | 1252 } else if (decoder_state_ == kError) { |
1250 DVLOG(2) << "FlushTask(): early out: kError state"; | 1253 DVLOG(2) << "FlushTask(): early out: kError state"; |
1251 return; | 1254 return; |
1252 } | 1255 } |
1253 | 1256 |
1254 // We don't support stacked flushing. | 1257 // We don't support stacked flushing. |
1255 DCHECK(!decoder_flushing_); | 1258 DCHECK(!decoder_flushing_); |
1256 | 1259 |
1257 // Queue up an empty buffer -- this triggers the flush. | 1260 // Queue up an empty buffer -- this triggers the flush. |
1258 decoder_input_queue_.push( | 1261 decoder_input_queue_.push( |
1259 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | 1262 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( |
1260 io_client_, io_message_loop_proxy_, NULL, 0, kFlushBufferId))); | 1263 io_client_, io_task_runner_, NULL, 0, kFlushBufferId))); |
1261 decoder_flushing_ = true; | 1264 decoder_flushing_ = true; |
1262 SendPictureReady(); // Send all pending PictureReady. | 1265 SendPictureReady(); // Send all pending PictureReady. |
1263 | 1266 |
1264 ScheduleDecodeBufferTaskIfNeeded(); | 1267 ScheduleDecodeBufferTaskIfNeeded(); |
1265 } | 1268 } |
1266 | 1269 |
1267 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { | 1270 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { |
1268 if (!decoder_flushing_) | 1271 if (!decoder_flushing_) |
1269 return; | 1272 return; |
1270 | 1273 |
(...skipping 23 matching lines...) Expand all Loading... |
1294 // when doing MSE. This should be harmless otherwise. | 1297 // when doing MSE. This should be harmless otherwise. |
1295 if (!StopDevicePoll(false)) | 1298 if (!StopDevicePoll(false)) |
1296 return; | 1299 return; |
1297 | 1300 |
1298 if (!StartDevicePoll()) | 1301 if (!StartDevicePoll()) |
1299 return; | 1302 return; |
1300 | 1303 |
1301 decoder_delay_bitstream_buffer_id_ = -1; | 1304 decoder_delay_bitstream_buffer_id_ = -1; |
1302 decoder_flushing_ = false; | 1305 decoder_flushing_ = false; |
1303 DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush"; | 1306 DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush"; |
1304 child_message_loop_proxy_->PostTask( | 1307 child_task_runner_->PostTask(FROM_HERE, |
1305 FROM_HERE, base::Bind(&Client::NotifyFlushDone, client_)); | 1308 base::Bind(&Client::NotifyFlushDone, client_)); |
1306 | 1309 |
1307 // While we were flushing, we early-outed DecodeBufferTask()s. | 1310 // While we were flushing, we early-outed DecodeBufferTask()s. |
1308 ScheduleDecodeBufferTaskIfNeeded(); | 1311 ScheduleDecodeBufferTaskIfNeeded(); |
1309 } | 1312 } |
1310 | 1313 |
1311 void V4L2VideoDecodeAccelerator::ResetTask() { | 1314 void V4L2VideoDecodeAccelerator::ResetTask() { |
1312 DVLOG(3) << "ResetTask()"; | 1315 DVLOG(3) << "ResetTask()"; |
1313 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1316 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1314 TRACE_EVENT0("Video Decoder", "V4L2VDA::ResetTask"); | 1317 TRACE_EVENT0("Video Decoder", "V4L2VDA::ResetTask"); |
1315 | 1318 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1381 if (output_buffer_map_.empty()) { | 1384 if (output_buffer_map_.empty()) { |
1382 // We must have gotten Reset() before we had a chance to request buffers | 1385 // We must have gotten Reset() before we had a chance to request buffers |
1383 // from the client. | 1386 // from the client. |
1384 decoder_state_ = kInitialized; | 1387 decoder_state_ = kInitialized; |
1385 } else { | 1388 } else { |
1386 decoder_state_ = kAfterReset; | 1389 decoder_state_ = kAfterReset; |
1387 } | 1390 } |
1388 | 1391 |
1389 decoder_partial_frame_pending_ = false; | 1392 decoder_partial_frame_pending_ = false; |
1390 decoder_delay_bitstream_buffer_id_ = -1; | 1393 decoder_delay_bitstream_buffer_id_ = -1; |
1391 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 1394 child_task_runner_->PostTask(FROM_HERE, |
1392 &Client::NotifyResetDone, client_)); | 1395 base::Bind(&Client::NotifyResetDone, client_)); |
1393 | 1396 |
1394 // While we were resetting, we early-outed DecodeBufferTask()s. | 1397 // While we were resetting, we early-outed DecodeBufferTask()s. |
1395 ScheduleDecodeBufferTaskIfNeeded(); | 1398 ScheduleDecodeBufferTaskIfNeeded(); |
1396 } | 1399 } |
1397 | 1400 |
1398 void V4L2VideoDecodeAccelerator::DestroyTask() { | 1401 void V4L2VideoDecodeAccelerator::DestroyTask() { |
1399 DVLOG(3) << "DestroyTask()"; | 1402 DVLOG(3) << "DestroyTask()"; |
1400 TRACE_EVENT0("Video Decoder", "V4L2VDA::DestroyTask"); | 1403 TRACE_EVENT0("Video Decoder", "V4L2VDA::DestroyTask"); |
1401 | 1404 |
1402 // DestroyTask() should run regardless of decoder_state_. | 1405 // DestroyTask() should run regardless of decoder_state_. |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1517 // Keep input queue. | 1520 // Keep input queue. |
1518 if (!StopDevicePoll(true)) | 1521 if (!StopDevicePoll(true)) |
1519 return; | 1522 return; |
1520 | 1523 |
1521 decoder_state_ = kChangingResolution; | 1524 decoder_state_ = kChangingResolution; |
1522 DCHECK(resolution_change_pending_); | 1525 DCHECK(resolution_change_pending_); |
1523 resolution_change_pending_ = false; | 1526 resolution_change_pending_ = false; |
1524 | 1527 |
1525 // Post a task to clean up buffers on child thread. This will also ensure | 1528 // Post a task to clean up buffers on child thread. This will also ensure |
1526 // that we won't accept ReusePictureBuffer() anymore after that. | 1529 // that we won't accept ReusePictureBuffer() anymore after that. |
1527 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 1530 child_task_runner_->PostTask( |
1528 &V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers, | 1531 FROM_HERE, |
1529 weak_this_)); | 1532 base::Bind(&V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers, |
| 1533 weak_this_)); |
1530 } | 1534 } |
1531 | 1535 |
1532 void V4L2VideoDecodeAccelerator::FinishResolutionChange() { | 1536 void V4L2VideoDecodeAccelerator::FinishResolutionChange() { |
1533 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1537 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1534 DCHECK_EQ(decoder_state_, kChangingResolution); | 1538 DCHECK_EQ(decoder_state_, kChangingResolution); |
1535 DVLOG(3) << "FinishResolutionChange()"; | 1539 DVLOG(3) << "FinishResolutionChange()"; |
1536 | 1540 |
1537 if (decoder_state_ == kError) { | 1541 if (decoder_state_ == kError) { |
1538 DVLOG(2) << "FinishResolutionChange(): early out: kError state"; | 1542 DVLOG(2) << "FinishResolutionChange(): early out: kError state"; |
1539 return; | 1543 return; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1585 // All processing should happen on ServiceDeviceTask(), since we shouldn't | 1589 // All processing should happen on ServiceDeviceTask(), since we shouldn't |
1586 // touch decoder state from this thread. | 1590 // touch decoder state from this thread. |
1587 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1591 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
1588 &V4L2VideoDecodeAccelerator::ServiceDeviceTask, | 1592 &V4L2VideoDecodeAccelerator::ServiceDeviceTask, |
1589 base::Unretained(this), event_pending)); | 1593 base::Unretained(this), event_pending)); |
1590 } | 1594 } |
1591 | 1595 |
1592 void V4L2VideoDecodeAccelerator::NotifyError(Error error) { | 1596 void V4L2VideoDecodeAccelerator::NotifyError(Error error) { |
1593 DVLOG(2) << "NotifyError()"; | 1597 DVLOG(2) << "NotifyError()"; |
1594 | 1598 |
1595 if (!child_message_loop_proxy_->BelongsToCurrentThread()) { | 1599 if (!child_task_runner_->BelongsToCurrentThread()) { |
1596 child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 1600 child_task_runner_->PostTask( |
1597 &V4L2VideoDecodeAccelerator::NotifyError, weak_this_, error)); | 1601 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::NotifyError, |
| 1602 weak_this_, error)); |
1598 return; | 1603 return; |
1599 } | 1604 } |
1600 | 1605 |
1601 if (client_) { | 1606 if (client_) { |
1602 client_->NotifyError(error); | 1607 client_->NotifyError(error); |
1603 client_ptr_factory_.reset(); | 1608 client_ptr_factory_.reset(); |
1604 } | 1609 } |
1605 } | 1610 } |
1606 | 1611 |
1607 void V4L2VideoDecodeAccelerator::SetErrorState(Error error) { | 1612 void V4L2VideoDecodeAccelerator::SetErrorState(Error error) { |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1834 reqbufs.count = output_dpb_size_ + kDpbOutputBufferExtraCount; | 1839 reqbufs.count = output_dpb_size_ + kDpbOutputBufferExtraCount; |
1835 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1840 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
1836 reqbufs.memory = V4L2_MEMORY_MMAP; | 1841 reqbufs.memory = V4L2_MEMORY_MMAP; |
1837 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); | 1842 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); |
1838 | 1843 |
1839 output_buffer_map_.resize(reqbufs.count); | 1844 output_buffer_map_.resize(reqbufs.count); |
1840 | 1845 |
1841 DVLOG(3) << "CreateOutputBuffers(): ProvidePictureBuffers(): " | 1846 DVLOG(3) << "CreateOutputBuffers(): ProvidePictureBuffers(): " |
1842 << "buffer_count=" << output_buffer_map_.size() | 1847 << "buffer_count=" << output_buffer_map_.size() |
1843 << ", coded_size=" << coded_size_.ToString(); | 1848 << ", coded_size=" << coded_size_.ToString(); |
1844 child_message_loop_proxy_->PostTask(FROM_HERE, | 1849 child_task_runner_->PostTask( |
1845 base::Bind(&Client::ProvidePictureBuffers, | 1850 FROM_HERE, base::Bind(&Client::ProvidePictureBuffers, client_, |
1846 client_, | 1851 output_buffer_map_.size(), coded_size_, |
1847 output_buffer_map_.size(), | 1852 device_->GetTextureTarget())); |
1848 coded_size_, | |
1849 device_->GetTextureTarget())); | |
1850 | 1853 |
1851 // Wait for the client to call AssignPictureBuffers() on the Child thread. | 1854 // Wait for the client to call AssignPictureBuffers() on the Child thread. |
1852 // We do this, because if we continue decoding without finishing buffer | 1855 // We do this, because if we continue decoding without finishing buffer |
1853 // allocation, we may end up Resetting before AssignPictureBuffers arrives, | 1856 // allocation, we may end up Resetting before AssignPictureBuffers arrives, |
1854 // resulting in unnecessary complications and subtle bugs. | 1857 // resulting in unnecessary complications and subtle bugs. |
1855 // For example, if the client calls Decode(Input1), Reset(), Decode(Input2) | 1858 // For example, if the client calls Decode(Input1), Reset(), Decode(Input2) |
1856 // in a sequence, and Decode(Input1) results in us getting here and exiting | 1859 // in a sequence, and Decode(Input1) results in us getting here and exiting |
1857 // without waiting, we might end up running Reset{,Done}Task() before | 1860 // without waiting, we might end up running Reset{,Done}Task() before |
1858 // AssignPictureBuffers is scheduled, thus cleaning up and pushing buffers | 1861 // AssignPictureBuffers is scheduled, thus cleaning up and pushing buffers |
1859 // to the free_output_buffers_ map twice. If we somehow marked buffers as | 1862 // to the free_output_buffers_ map twice. If we somehow marked buffers as |
1860 // not ready, we'd need special handling for restarting the second Decode | 1863 // not ready, we'd need special handling for restarting the second Decode |
1861 // task and delaying it anyway. | 1864 // task and delaying it anyway. |
1862 // Waiting here is not very costly and makes reasoning about different | 1865 // Waiting here is not very costly and makes reasoning about different |
1863 // situations much simpler. | 1866 // situations much simpler. |
1864 pictures_assigned_.Wait(); | 1867 pictures_assigned_.Wait(); |
1865 | 1868 |
1866 Enqueue(); | 1869 Enqueue(); |
1867 return true; | 1870 return true; |
1868 } | 1871 } |
1869 | 1872 |
1870 void V4L2VideoDecodeAccelerator::DestroyInputBuffers() { | 1873 void V4L2VideoDecodeAccelerator::DestroyInputBuffers() { |
1871 DVLOG(3) << "DestroyInputBuffers()"; | 1874 DVLOG(3) << "DestroyInputBuffers()"; |
1872 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1875 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
1873 DCHECK(!input_streamon_); | 1876 DCHECK(!input_streamon_); |
1874 | 1877 |
1875 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { | 1878 for (size_t i = 0; i < input_buffer_map_.size(); ++i) { |
1876 if (input_buffer_map_[i].address != NULL) { | 1879 if (input_buffer_map_[i].address != NULL) { |
1877 device_->Munmap(input_buffer_map_[i].address, | 1880 device_->Munmap(input_buffer_map_[i].address, |
1878 input_buffer_map_[i].length); | 1881 input_buffer_map_[i].length); |
1879 } | 1882 } |
1880 } | 1883 } |
1881 | 1884 |
1882 struct v4l2_requestbuffers reqbufs; | 1885 struct v4l2_requestbuffers reqbufs; |
1883 memset(&reqbufs, 0, sizeof(reqbufs)); | 1886 memset(&reqbufs, 0, sizeof(reqbufs)); |
1884 reqbufs.count = 0; | 1887 reqbufs.count = 0; |
1885 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 1888 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
1886 reqbufs.memory = V4L2_MEMORY_MMAP; | 1889 reqbufs.memory = V4L2_MEMORY_MMAP; |
1887 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); | 1890 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); |
1888 | 1891 |
1889 input_buffer_map_.clear(); | 1892 input_buffer_map_.clear(); |
1890 free_input_buffers_.clear(); | 1893 free_input_buffers_.clear(); |
1891 } | 1894 } |
1892 | 1895 |
1893 bool V4L2VideoDecodeAccelerator::DestroyOutputBuffers() { | 1896 bool V4L2VideoDecodeAccelerator::DestroyOutputBuffers() { |
1894 DVLOG(3) << "DestroyOutputBuffers()"; | 1897 DVLOG(3) << "DestroyOutputBuffers()"; |
1895 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1898 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
1896 DCHECK(!output_streamon_); | 1899 DCHECK(!output_streamon_); |
1897 bool success = true; | 1900 bool success = true; |
1898 | 1901 |
1899 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { | 1902 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { |
1900 OutputRecord& output_record = output_buffer_map_[i]; | 1903 OutputRecord& output_record = output_buffer_map_[i]; |
1901 | 1904 |
1902 if (output_record.egl_image != EGL_NO_IMAGE_KHR) { | 1905 if (output_record.egl_image != EGL_NO_IMAGE_KHR) { |
1903 if (device_->DestroyEGLImage(egl_display_, output_record.egl_image) != | 1906 if (device_->DestroyEGLImage(egl_display_, output_record.egl_image) != |
1904 EGL_TRUE) { | 1907 EGL_TRUE) { |
1905 DVLOG(1) << __func__ << " DestroyEGLImage failed."; | 1908 DVLOG(1) << __func__ << " DestroyEGLImage failed."; |
1906 success = false; | 1909 success = false; |
1907 } | 1910 } |
1908 } | 1911 } |
1909 | 1912 |
1910 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { | 1913 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { |
1911 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) { | 1914 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) { |
1912 DVLOG(1) << __func__ << " eglDestroySyncKHR failed."; | 1915 DVLOG(1) << __func__ << " eglDestroySyncKHR failed."; |
1913 success = false; | 1916 success = false; |
1914 } | 1917 } |
1915 } | 1918 } |
1916 | 1919 |
1917 DVLOG(1) << "DestroyOutputBuffers(): dismissing PictureBuffer id=" | 1920 DVLOG(1) << "DestroyOutputBuffers(): dismissing PictureBuffer id=" |
1918 << output_record.picture_id; | 1921 << output_record.picture_id; |
1919 child_message_loop_proxy_->PostTask( | 1922 child_task_runner_->PostTask( |
1920 FROM_HERE, | 1923 FROM_HERE, base::Bind(&Client::DismissPictureBuffer, client_, |
1921 base::Bind( | 1924 output_record.picture_id)); |
1922 &Client::DismissPictureBuffer, client_, output_record.picture_id)); | |
1923 } | 1925 } |
1924 | 1926 |
1925 struct v4l2_requestbuffers reqbufs; | 1927 struct v4l2_requestbuffers reqbufs; |
1926 memset(&reqbufs, 0, sizeof(reqbufs)); | 1928 memset(&reqbufs, 0, sizeof(reqbufs)); |
1927 reqbufs.count = 0; | 1929 reqbufs.count = 0; |
1928 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; | 1930 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
1929 reqbufs.memory = V4L2_MEMORY_MMAP; | 1931 reqbufs.memory = V4L2_MEMORY_MMAP; |
1930 if (device_->Ioctl(VIDIOC_REQBUFS, &reqbufs) != 0) { | 1932 if (device_->Ioctl(VIDIOC_REQBUFS, &reqbufs) != 0) { |
1931 PLOG(ERROR) << "DestroyOutputBuffers() ioctl() failed: VIDIOC_REQBUFS"; | 1933 PLOG(ERROR) << "DestroyOutputBuffers() ioctl() failed: VIDIOC_REQBUFS"; |
1932 success = false; | 1934 success = false; |
1933 } | 1935 } |
1934 | 1936 |
1935 output_buffer_map_.clear(); | 1937 output_buffer_map_.clear(); |
1936 while (!free_output_buffers_.empty()) | 1938 while (!free_output_buffers_.empty()) |
1937 free_output_buffers_.pop(); | 1939 free_output_buffers_.pop(); |
1938 | 1940 |
1939 return success; | 1941 return success; |
1940 } | 1942 } |
1941 | 1943 |
1942 void V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers() { | 1944 void V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers() { |
1943 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); | 1945 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
1944 DVLOG(3) << "ResolutionChangeDestroyBuffers()"; | 1946 DVLOG(3) << "ResolutionChangeDestroyBuffers()"; |
1945 | 1947 |
1946 if (!DestroyOutputBuffers()) { | 1948 if (!DestroyOutputBuffers()) { |
1947 LOG(ERROR) << __func__ << " Failed destroying output buffers."; | 1949 LOG(ERROR) << __func__ << " Failed destroying output buffers."; |
1948 NOTIFY_ERROR(PLATFORM_FAILURE); | 1950 NOTIFY_ERROR(PLATFORM_FAILURE); |
1949 return; | 1951 return; |
1950 } | 1952 } |
1951 | 1953 |
1952 // Finish resolution change on decoder thread. | 1954 // Finish resolution change on decoder thread. |
1953 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 1955 decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
1954 &V4L2VideoDecodeAccelerator::FinishResolutionChange, | 1956 &V4L2VideoDecodeAccelerator::FinishResolutionChange, |
1955 base::Unretained(this))); | 1957 base::Unretained(this))); |
1956 } | 1958 } |
1957 | 1959 |
1958 void V4L2VideoDecodeAccelerator::SendPictureReady() { | 1960 void V4L2VideoDecodeAccelerator::SendPictureReady() { |
1959 DVLOG(3) << "SendPictureReady()"; | 1961 DVLOG(3) << "SendPictureReady()"; |
1960 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 1962 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1961 bool resetting_or_flushing = | 1963 bool resetting_or_flushing = |
1962 (decoder_state_ == kResetting || decoder_flushing_); | 1964 (decoder_state_ == kResetting || decoder_flushing_); |
1963 while (pending_picture_ready_.size() > 0) { | 1965 while (pending_picture_ready_.size() > 0) { |
1964 bool cleared = pending_picture_ready_.front().cleared; | 1966 bool cleared = pending_picture_ready_.front().cleared; |
1965 const media::Picture& picture = pending_picture_ready_.front().picture; | 1967 const media::Picture& picture = pending_picture_ready_.front().picture; |
1966 if (cleared && picture_clearing_count_ == 0) { | 1968 if (cleared && picture_clearing_count_ == 0) { |
1967 // This picture is cleared. Post it to IO thread to reduce latency. This | 1969 // This picture is cleared. Post it to IO thread to reduce latency. This |
1968 // should be the case after all pictures are cleared at the beginning. | 1970 // should be the case after all pictures are cleared at the beginning. |
1969 io_message_loop_proxy_->PostTask( | 1971 io_task_runner_->PostTask( |
1970 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture)); | 1972 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture)); |
1971 pending_picture_ready_.pop(); | 1973 pending_picture_ready_.pop(); |
1972 } else if (!cleared || resetting_or_flushing) { | 1974 } else if (!cleared || resetting_or_flushing) { |
1973 DVLOG(3) << "SendPictureReady()" | 1975 DVLOG(3) << "SendPictureReady()" |
1974 << ". cleared=" << pending_picture_ready_.front().cleared | 1976 << ". cleared=" << pending_picture_ready_.front().cleared |
1975 << ", decoder_state_=" << decoder_state_ | 1977 << ", decoder_state_=" << decoder_state_ |
1976 << ", decoder_flushing_=" << decoder_flushing_ | 1978 << ", decoder_flushing_=" << decoder_flushing_ |
1977 << ", picture_clearing_count_=" << picture_clearing_count_; | 1979 << ", picture_clearing_count_=" << picture_clearing_count_; |
1978 // If the picture is not cleared, post it to the child thread because it | 1980 // If the picture is not cleared, post it to the child thread because it |
1979 // has to be cleared in the child thread. A picture only needs to be | 1981 // has to be cleared in the child thread. A picture only needs to be |
1980 // cleared once. If the decoder is resetting or flushing, send all | 1982 // cleared once. If the decoder is resetting or flushing, send all |
1981 // pictures to ensure PictureReady arrive before reset or flush done. | 1983 // pictures to ensure PictureReady arrive before reset or flush done. |
1982 child_message_loop_proxy_->PostTaskAndReply( | 1984 child_task_runner_->PostTaskAndReply( |
1983 FROM_HERE, | 1985 FROM_HERE, base::Bind(&Client::PictureReady, client_, picture), |
1984 base::Bind(&Client::PictureReady, client_, picture), | |
1985 // Unretained is safe. If Client::PictureReady gets to run, |this| is | 1986 // Unretained is safe. If Client::PictureReady gets to run, |this| is |
1986 // alive. Destroy() will wait the decode thread to finish. | 1987 // alive. Destroy() will wait the decode thread to finish. |
1987 base::Bind(&V4L2VideoDecodeAccelerator::PictureCleared, | 1988 base::Bind(&V4L2VideoDecodeAccelerator::PictureCleared, |
1988 base::Unretained(this))); | 1989 base::Unretained(this))); |
1989 picture_clearing_count_++; | 1990 picture_clearing_count_++; |
1990 pending_picture_ready_.pop(); | 1991 pending_picture_ready_.pop(); |
1991 } else { | 1992 } else { |
1992 // This picture is cleared. But some pictures are about to be cleared on | 1993 // This picture is cleared. But some pictures are about to be cleared on |
1993 // the child thread. To preserve the order, do not send this until those | 1994 // the child thread. To preserve the order, do not send this until those |
1994 // pictures are cleared. | 1995 // pictures are cleared. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2027 gfx::Size new_coded_size(base::checked_cast<int>(format.fmt.pix_mp.width), | 2028 gfx::Size new_coded_size(base::checked_cast<int>(format.fmt.pix_mp.width), |
2028 base::checked_cast<int>(format.fmt.pix_mp.height)); | 2029 base::checked_cast<int>(format.fmt.pix_mp.height)); |
2029 if (coded_size_ != new_coded_size) { | 2030 if (coded_size_ != new_coded_size) { |
2030 DVLOG(3) << "IsResolutionChangeNecessary(): Resolution change detected"; | 2031 DVLOG(3) << "IsResolutionChangeNecessary(): Resolution change detected"; |
2031 return true; | 2032 return true; |
2032 } | 2033 } |
2033 return false; | 2034 return false; |
2034 } | 2035 } |
2035 | 2036 |
2036 } // namespace content | 2037 } // namespace content |
OLD | NEW |