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 <string.h> | 10 #include <string.h> |
11 #include <sys/eventfd.h> | 11 #include <sys/eventfd.h> |
12 #include <sys/ioctl.h> | 12 #include <sys/ioctl.h> |
13 #include <sys/mman.h> | 13 #include <sys/mman.h> |
14 | 14 |
15 #include "base/bind.h" | 15 #include "base/bind.h" |
16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
17 #include "base/macros.h" | 17 #include "base/macros.h" |
18 #include "base/memory/shared_memory.h" | 18 #include "base/memory/shared_memory.h" |
19 #include "base/message_loop/message_loop.h" | 19 #include "base/message_loop/message_loop.h" |
20 #include "base/numerics/safe_conversions.h" | 20 #include "base/numerics/safe_conversions.h" |
21 #include "base/thread_task_runner_handle.h" | 21 #include "base/thread_task_runner_handle.h" |
22 #include "base/trace_event/trace_event.h" | 22 #include "base/trace_event/trace_event.h" |
23 #include "build/build_config.h" | 23 #include "build/build_config.h" |
24 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" | 24 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" |
25 #include "media/base/media_switches.h" | 25 #include "media/base/media_switches.h" |
26 #include "media/filters/h264_parser.h" | 26 #include "media/filters/h264_parser.h" |
27 #include "ui/gfx/geometry/rect.h" | 27 #include "ui/gfx/geometry/rect.h" |
| 28 #include "ui/gl/gl_context.h" |
28 #include "ui/gl/scoped_binders.h" | 29 #include "ui/gl/scoped_binders.h" |
29 | 30 |
30 #define NOTIFY_ERROR(x) \ | 31 #define NOTIFY_ERROR(x) \ |
31 do { \ | 32 do { \ |
32 LOG(ERROR) << "Setting error state:" << x; \ | 33 LOG(ERROR) << "Setting error state:" << x; \ |
33 SetErrorState(x); \ | 34 SetErrorState(x); \ |
34 } while (0) | 35 } while (0) |
35 | 36 |
36 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \ | 37 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \ |
37 do { \ | 38 do { \ |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 | 151 |
151 V4L2VideoDecodeAccelerator::PictureRecord::PictureRecord( | 152 V4L2VideoDecodeAccelerator::PictureRecord::PictureRecord( |
152 bool cleared, | 153 bool cleared, |
153 const media::Picture& picture) | 154 const media::Picture& picture) |
154 : cleared(cleared), picture(picture) {} | 155 : cleared(cleared), picture(picture) {} |
155 | 156 |
156 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {} | 157 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {} |
157 | 158 |
158 V4L2VideoDecodeAccelerator::V4L2VideoDecodeAccelerator( | 159 V4L2VideoDecodeAccelerator::V4L2VideoDecodeAccelerator( |
159 EGLDisplay egl_display, | 160 EGLDisplay egl_display, |
160 EGLContext egl_context, | 161 const gpu_vda_helpers::GetGLContextCb& get_gl_context_cb, |
161 const base::WeakPtr<Client>& io_client, | 162 const gpu_vda_helpers::MakeGLContextCurrentCb& make_context_current_cb, |
162 const base::Callback<bool(void)>& make_context_current, | 163 const scoped_refptr<V4L2Device>& device) |
163 const scoped_refptr<V4L2Device>& device, | |
164 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) | |
165 : child_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 164 : child_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
166 io_task_runner_(io_task_runner), | |
167 io_client_(io_client), | |
168 decoder_thread_("V4L2DecoderThread"), | 165 decoder_thread_("V4L2DecoderThread"), |
169 decoder_state_(kUninitialized), | 166 decoder_state_(kUninitialized), |
170 device_(device), | 167 device_(device), |
171 decoder_delay_bitstream_buffer_id_(-1), | 168 decoder_delay_bitstream_buffer_id_(-1), |
172 decoder_current_input_buffer_(-1), | 169 decoder_current_input_buffer_(-1), |
173 decoder_decode_buffer_tasks_scheduled_(0), | 170 decoder_decode_buffer_tasks_scheduled_(0), |
174 decoder_frames_at_client_(0), | 171 decoder_frames_at_client_(0), |
175 decoder_flushing_(false), | 172 decoder_flushing_(false), |
176 resolution_change_reset_pending_(false), | 173 resolution_change_reset_pending_(false), |
177 decoder_partial_frame_pending_(false), | 174 decoder_partial_frame_pending_(false), |
178 input_streamon_(false), | 175 input_streamon_(false), |
179 input_buffer_queued_count_(0), | 176 input_buffer_queued_count_(0), |
180 output_streamon_(false), | 177 output_streamon_(false), |
181 output_buffer_queued_count_(0), | 178 output_buffer_queued_count_(0), |
182 output_dpb_size_(0), | 179 output_dpb_size_(0), |
183 output_planes_count_(0), | 180 output_planes_count_(0), |
184 picture_clearing_count_(0), | 181 picture_clearing_count_(0), |
185 pictures_assigned_(false, false), | 182 pictures_assigned_(false, false), |
186 device_poll_thread_("V4L2DevicePollThread"), | 183 device_poll_thread_("V4L2DevicePollThread"), |
187 make_context_current_(make_context_current), | |
188 egl_display_(egl_display), | 184 egl_display_(egl_display), |
189 egl_context_(egl_context), | 185 get_gl_context_cb_(get_gl_context_cb), |
| 186 make_context_current_cb_(make_context_current_cb), |
190 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), | 187 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), |
191 output_format_fourcc_(0), | 188 output_format_fourcc_(0), |
192 weak_this_factory_(this) { | 189 weak_this_factory_(this) { |
193 weak_this_ = weak_this_factory_.GetWeakPtr(); | 190 weak_this_ = weak_this_factory_.GetWeakPtr(); |
194 } | 191 } |
195 | 192 |
196 V4L2VideoDecodeAccelerator::~V4L2VideoDecodeAccelerator() { | 193 V4L2VideoDecodeAccelerator::~V4L2VideoDecodeAccelerator() { |
197 DCHECK(!decoder_thread_.IsRunning()); | 194 DCHECK(!decoder_thread_.IsRunning()); |
198 DCHECK(!device_poll_thread_.IsRunning()); | 195 DCHECK(!device_poll_thread_.IsRunning()); |
199 | 196 |
(...skipping 19 matching lines...) Expand all Loading... |
219 | 216 |
220 if (!device_->SupportsDecodeProfileForV4L2PixelFormats( | 217 if (!device_->SupportsDecodeProfileForV4L2PixelFormats( |
221 config.profile, arraysize(supported_input_fourccs_), | 218 config.profile, arraysize(supported_input_fourccs_), |
222 supported_input_fourccs_)) { | 219 supported_input_fourccs_)) { |
223 DVLOG(1) << "Initialize(): unsupported profile=" << config.profile; | 220 DVLOG(1) << "Initialize(): unsupported profile=" << config.profile; |
224 return false; | 221 return false; |
225 } | 222 } |
226 | 223 |
227 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); | 224 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); |
228 client_ = client_ptr_factory_->GetWeakPtr(); | 225 client_ = client_ptr_factory_->GetWeakPtr(); |
| 226 // If we haven't been set up to decode on separate thread via |
| 227 // TryInitializeDecodeOnSeparateThread(), use the main thread/client for |
| 228 // decode tasks. |
| 229 if (!decode_task_runner_) { |
| 230 decode_task_runner_ = child_task_runner_; |
| 231 DCHECK(!decode_client_); |
| 232 decode_client_ = client_; |
| 233 } |
229 | 234 |
230 video_profile_ = config.profile; | 235 video_profile_ = config.profile; |
231 | 236 |
232 if (egl_display_ == EGL_NO_DISPLAY) { | 237 if (egl_display_ == EGL_NO_DISPLAY) { |
233 LOG(ERROR) << "Initialize(): could not get EGLDisplay"; | 238 LOG(ERROR) << "Initialize(): could not get EGLDisplay"; |
234 return false; | 239 return false; |
235 } | 240 } |
236 | 241 |
237 // We need the context to be initialized to query extensions. | 242 // We need the context to be initialized to query extensions. |
238 if (!make_context_current_.Run()) { | 243 if (!make_context_current_cb_.Run()) { |
239 LOG(ERROR) << "Initialize(): could not make context current"; | 244 LOG(ERROR) << "Initialize(): could not make context current"; |
240 return false; | 245 return false; |
241 } | 246 } |
242 | 247 |
243 // TODO(posciak): crbug.com/450898. | 248 // TODO(posciak): crbug.com/450898. |
244 #if defined(ARCH_CPU_ARMEL) | 249 #if defined(ARCH_CPU_ARMEL) |
245 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) { | 250 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) { |
246 LOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync"; | 251 LOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync"; |
247 return false; | 252 return false; |
248 } | 253 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 base::IgnoreResult(&V4L2VideoDecodeAccelerator::StartDevicePoll), | 294 base::IgnoreResult(&V4L2VideoDecodeAccelerator::StartDevicePoll), |
290 base::Unretained(this))); | 295 base::Unretained(this))); |
291 | 296 |
292 return true; | 297 return true; |
293 } | 298 } |
294 | 299 |
295 void V4L2VideoDecodeAccelerator::Decode( | 300 void V4L2VideoDecodeAccelerator::Decode( |
296 const media::BitstreamBuffer& bitstream_buffer) { | 301 const media::BitstreamBuffer& bitstream_buffer) { |
297 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() | 302 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() |
298 << ", size=" << bitstream_buffer.size(); | 303 << ", size=" << bitstream_buffer.size(); |
299 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 304 DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
300 | 305 |
301 if (bitstream_buffer.id() < 0) { | 306 if (bitstream_buffer.id() < 0) { |
302 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); | 307 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); |
303 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) | 308 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) |
304 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); | 309 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); |
305 NOTIFY_ERROR(INVALID_ARGUMENT); | 310 NOTIFY_ERROR(INVALID_ARGUMENT); |
306 return; | 311 return; |
307 } | 312 } |
308 | 313 |
309 // DecodeTask() will take care of running a DecodeBufferTask(). | 314 // DecodeTask() will take care of running a DecodeBufferTask(). |
(...skipping 11 matching lines...) Expand all Loading... |
321 output_dpb_size_ + kDpbOutputBufferExtraCount; | 326 output_dpb_size_ + kDpbOutputBufferExtraCount; |
322 | 327 |
323 if (buffers.size() < req_buffer_count) { | 328 if (buffers.size() < req_buffer_count) { |
324 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" | 329 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" |
325 " buffers. (Got " << buffers.size() | 330 " buffers. (Got " << buffers.size() |
326 << ", requested " << req_buffer_count << ")"; | 331 << ", requested " << req_buffer_count << ")"; |
327 NOTIFY_ERROR(INVALID_ARGUMENT); | 332 NOTIFY_ERROR(INVALID_ARGUMENT); |
328 return; | 333 return; |
329 } | 334 } |
330 | 335 |
331 if (!make_context_current_.Run()) { | 336 gfx::GLContext* gl_context = get_gl_context_cb_.Run(); |
| 337 if (!gl_context || !make_context_current_cb_.Run()) { |
332 LOG(ERROR) << "AssignPictureBuffers(): could not make context current"; | 338 LOG(ERROR) << "AssignPictureBuffers(): could not make context current"; |
333 NOTIFY_ERROR(PLATFORM_FAILURE); | 339 NOTIFY_ERROR(PLATFORM_FAILURE); |
334 return; | 340 return; |
335 } | 341 } |
336 | 342 |
337 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); | 343 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); |
338 | 344 |
339 // It's safe to manipulate all the buffer state here, because the decoder | 345 // It's safe to manipulate all the buffer state here, because the decoder |
340 // thread is waiting on pictures_assigned_. | 346 // thread is waiting on pictures_assigned_. |
341 | 347 |
(...skipping 19 matching lines...) Expand all Loading... |
361 | 367 |
362 OutputRecord& output_record = output_buffer_map_[i]; | 368 OutputRecord& output_record = output_buffer_map_[i]; |
363 DCHECK(!output_record.at_device); | 369 DCHECK(!output_record.at_device); |
364 DCHECK(!output_record.at_client); | 370 DCHECK(!output_record.at_client); |
365 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); | 371 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); |
366 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 372 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
367 DCHECK_EQ(output_record.picture_id, -1); | 373 DCHECK_EQ(output_record.picture_id, -1); |
368 DCHECK_EQ(output_record.cleared, false); | 374 DCHECK_EQ(output_record.cleared, false); |
369 | 375 |
370 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_, | 376 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_, |
371 egl_context_, | 377 gl_context->GetHandle(), |
372 buffers[i].texture_id(), | 378 buffers[i].texture_id(), |
373 coded_size_, | 379 coded_size_, |
374 i, | 380 i, |
375 output_format_fourcc_, | 381 output_format_fourcc_, |
376 output_planes_count_); | 382 output_planes_count_); |
377 if (egl_image == EGL_NO_IMAGE_KHR) { | 383 if (egl_image == EGL_NO_IMAGE_KHR) { |
378 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; | 384 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; |
379 // Ownership of EGLImages allocated in previous iterations of this loop | 385 // Ownership of EGLImages allocated in previous iterations of this loop |
380 // has been transferred to output_buffer_map_. After we error-out here | 386 // has been transferred to output_buffer_map_. After we error-out here |
381 // the destructor will handle their cleanup. | 387 // the destructor will handle their cleanup. |
382 NOTIFY_ERROR(PLATFORM_FAILURE); | 388 NOTIFY_ERROR(PLATFORM_FAILURE); |
383 return; | 389 return; |
384 } | 390 } |
385 | 391 |
386 output_record.egl_image = egl_image; | 392 output_record.egl_image = egl_image; |
387 output_record.picture_id = buffers[i].id(); | 393 output_record.picture_id = buffers[i].id(); |
388 free_output_buffers_.push(i); | 394 free_output_buffers_.push(i); |
389 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i | 395 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i |
390 << "]: picture_id=" << output_record.picture_id; | 396 << "]: picture_id=" << output_record.picture_id; |
391 } | 397 } |
392 | 398 |
393 pictures_assigned_.Signal(); | 399 pictures_assigned_.Signal(); |
394 } | 400 } |
395 | 401 |
396 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) { | 402 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) { |
397 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; | 403 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; |
398 // Must be run on child thread, as we'll insert a sync in the EGL context. | 404 // Must be run on child thread, as we'll insert a sync in the EGL context. |
399 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 405 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
400 | 406 |
401 if (!make_context_current_.Run()) { | 407 if (!make_context_current_cb_.Run()) { |
402 LOG(ERROR) << "ReusePictureBuffer(): could not make context current"; | 408 LOG(ERROR) << "ReusePictureBuffer(): could not make context current"; |
403 NOTIFY_ERROR(PLATFORM_FAILURE); | 409 NOTIFY_ERROR(PLATFORM_FAILURE); |
404 return; | 410 return; |
405 } | 411 } |
406 | 412 |
407 EGLSyncKHR egl_sync = EGL_NO_SYNC_KHR; | 413 EGLSyncKHR egl_sync = EGL_NO_SYNC_KHR; |
408 // TODO(posciak): crbug.com/450898. | 414 // TODO(posciak): crbug.com/450898. |
409 #if defined(ARCH_CPU_ARMEL) | 415 #if defined(ARCH_CPU_ARMEL) |
410 egl_sync = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); | 416 egl_sync = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); |
411 if (egl_sync == EGL_NO_SYNC_KHR) { | 417 if (egl_sync == EGL_NO_SYNC_KHR) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 // DestroyTask() will cause the decoder_thread_ to flush all tasks. | 458 // DestroyTask() will cause the decoder_thread_ to flush all tasks. |
453 decoder_thread_.Stop(); | 459 decoder_thread_.Stop(); |
454 } else { | 460 } else { |
455 // Otherwise, call the destroy task directly. | 461 // Otherwise, call the destroy task directly. |
456 DestroyTask(); | 462 DestroyTask(); |
457 } | 463 } |
458 | 464 |
459 delete this; | 465 delete this; |
460 } | 466 } |
461 | 467 |
462 bool V4L2VideoDecodeAccelerator::CanDecodeOnIOThread() { return true; } | 468 bool V4L2VideoDecodeAccelerator::TryInitializeDecodeOnSeparateThread( |
| 469 const base::WeakPtr<Client>& decode_client, |
| 470 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { |
| 471 decode_client_ = decode_client_; |
| 472 decode_task_runner_ = decode_task_runner; |
| 473 return true; |
| 474 } |
463 | 475 |
464 // static | 476 // static |
465 media::VideoDecodeAccelerator::SupportedProfiles | 477 media::VideoDecodeAccelerator::SupportedProfiles |
466 V4L2VideoDecodeAccelerator::GetSupportedProfiles() { | 478 V4L2VideoDecodeAccelerator::GetSupportedProfiles() { |
467 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); | 479 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); |
468 if (!device) | 480 if (!device) |
469 return SupportedProfiles(); | 481 return SupportedProfiles(); |
470 | 482 |
471 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), | 483 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), |
472 supported_input_fourccs_); | 484 supported_input_fourccs_); |
473 } | 485 } |
474 | 486 |
475 void V4L2VideoDecodeAccelerator::DecodeTask( | 487 void V4L2VideoDecodeAccelerator::DecodeTask( |
476 const media::BitstreamBuffer& bitstream_buffer) { | 488 const media::BitstreamBuffer& bitstream_buffer) { |
477 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); | 489 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); |
478 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 490 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
479 DCHECK_NE(decoder_state_, kUninitialized); | 491 DCHECK_NE(decoder_state_, kUninitialized); |
480 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", | 492 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", |
481 bitstream_buffer.id()); | 493 bitstream_buffer.id()); |
482 | 494 |
483 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( | 495 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( |
484 io_client_, io_task_runner_, | 496 decode_client_, decode_task_runner_, |
485 new base::SharedMemory(bitstream_buffer.handle(), true), | 497 new base::SharedMemory(bitstream_buffer.handle(), true), |
486 bitstream_buffer.size(), bitstream_buffer.id())); | 498 bitstream_buffer.size(), bitstream_buffer.id())); |
487 if (!bitstream_record->shm->Map(bitstream_buffer.size())) { | 499 if (!bitstream_record->shm->Map(bitstream_buffer.size())) { |
488 LOG(ERROR) << "Decode(): could not map bitstream_buffer"; | 500 LOG(ERROR) << "Decode(): could not map bitstream_buffer"; |
489 NOTIFY_ERROR(UNREADABLE_INPUT); | 501 NOTIFY_ERROR(UNREADABLE_INPUT); |
490 return; | 502 return; |
491 } | 503 } |
492 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory(); | 504 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory(); |
493 | 505 |
494 if (decoder_state_ == kResetting || decoder_flushing_) { | 506 if (decoder_state_ == kResetting || decoder_flushing_) { |
(...skipping 774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1269 DVLOG(2) << "FlushTask(): early out: kError state"; | 1281 DVLOG(2) << "FlushTask(): early out: kError state"; |
1270 return; | 1282 return; |
1271 } | 1283 } |
1272 | 1284 |
1273 // We don't support stacked flushing. | 1285 // We don't support stacked flushing. |
1274 DCHECK(!decoder_flushing_); | 1286 DCHECK(!decoder_flushing_); |
1275 | 1287 |
1276 // Queue up an empty buffer -- this triggers the flush. | 1288 // Queue up an empty buffer -- this triggers the flush. |
1277 decoder_input_queue_.push( | 1289 decoder_input_queue_.push( |
1278 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | 1290 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( |
1279 io_client_, io_task_runner_, NULL, 0, kFlushBufferId))); | 1291 decode_client_, decode_task_runner_, NULL, 0, kFlushBufferId))); |
1280 decoder_flushing_ = true; | 1292 decoder_flushing_ = true; |
1281 SendPictureReady(); // Send all pending PictureReady. | 1293 SendPictureReady(); // Send all pending PictureReady. |
1282 | 1294 |
1283 ScheduleDecodeBufferTaskIfNeeded(); | 1295 ScheduleDecodeBufferTaskIfNeeded(); |
1284 } | 1296 } |
1285 | 1297 |
1286 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { | 1298 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { |
1287 if (!decoder_flushing_) | 1299 if (!decoder_flushing_) |
1288 return; | 1300 return; |
1289 | 1301 |
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1992 | 2004 |
1993 void V4L2VideoDecodeAccelerator::SendPictureReady() { | 2005 void V4L2VideoDecodeAccelerator::SendPictureReady() { |
1994 DVLOG(3) << "SendPictureReady()"; | 2006 DVLOG(3) << "SendPictureReady()"; |
1995 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 2007 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1996 bool resetting_or_flushing = | 2008 bool resetting_or_flushing = |
1997 (decoder_state_ == kResetting || decoder_flushing_); | 2009 (decoder_state_ == kResetting || decoder_flushing_); |
1998 while (pending_picture_ready_.size() > 0) { | 2010 while (pending_picture_ready_.size() > 0) { |
1999 bool cleared = pending_picture_ready_.front().cleared; | 2011 bool cleared = pending_picture_ready_.front().cleared; |
2000 const media::Picture& picture = pending_picture_ready_.front().picture; | 2012 const media::Picture& picture = pending_picture_ready_.front().picture; |
2001 if (cleared && picture_clearing_count_ == 0) { | 2013 if (cleared && picture_clearing_count_ == 0) { |
2002 // This picture is cleared. Post it to IO thread to reduce latency. This | 2014 // This picture is cleared. It can be posted to a thread different than |
2003 // should be the case after all pictures are cleared at the beginning. | 2015 // the main GPU thread to reduce latency. This should be the case after |
2004 io_task_runner_->PostTask( | 2016 // all pictures are cleared at the beginning. |
2005 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture)); | 2017 decode_task_runner_->PostTask( |
| 2018 FROM_HERE, |
| 2019 base::Bind(&Client::PictureReady, decode_client_, picture)); |
2006 pending_picture_ready_.pop(); | 2020 pending_picture_ready_.pop(); |
2007 } else if (!cleared || resetting_or_flushing) { | 2021 } else if (!cleared || resetting_or_flushing) { |
2008 DVLOG(3) << "SendPictureReady()" | 2022 DVLOG(3) << "SendPictureReady()" |
2009 << ". cleared=" << pending_picture_ready_.front().cleared | 2023 << ". cleared=" << pending_picture_ready_.front().cleared |
2010 << ", decoder_state_=" << decoder_state_ | 2024 << ", decoder_state_=" << decoder_state_ |
2011 << ", decoder_flushing_=" << decoder_flushing_ | 2025 << ", decoder_flushing_=" << decoder_flushing_ |
2012 << ", picture_clearing_count_=" << picture_clearing_count_; | 2026 << ", picture_clearing_count_=" << picture_clearing_count_; |
2013 // If the picture is not cleared, post it to the child thread because it | 2027 // If the picture is not cleared, post it to the child thread because it |
2014 // has to be cleared in the child thread. A picture only needs to be | 2028 // has to be cleared in the child thread. A picture only needs to be |
2015 // cleared once. If the decoder is resetting or flushing, send all | 2029 // cleared once. If the decoder is resetting or flushing, send all |
(...skipping 17 matching lines...) Expand all Loading... |
2033 | 2047 |
2034 void V4L2VideoDecodeAccelerator::PictureCleared() { | 2048 void V4L2VideoDecodeAccelerator::PictureCleared() { |
2035 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; | 2049 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; |
2036 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 2050 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
2037 DCHECK_GT(picture_clearing_count_, 0); | 2051 DCHECK_GT(picture_clearing_count_, 0); |
2038 picture_clearing_count_--; | 2052 picture_clearing_count_--; |
2039 SendPictureReady(); | 2053 SendPictureReady(); |
2040 } | 2054 } |
2041 | 2055 |
2042 } // namespace content | 2056 } // namespace content |
OLD | NEW |