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/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
19 #include "base/numerics/safe_conversions.h" | 19 #include "base/numerics/safe_conversions.h" |
20 #include "base/thread_task_runner_handle.h" | 20 #include "base/thread_task_runner_handle.h" |
21 #include "base/trace_event/trace_event.h" | 21 #include "base/trace_event/trace_event.h" |
22 #include "build/build_config.h" | 22 #include "build/build_config.h" |
23 #include "content/common/gpu/media/shared_memory_region.h" | 23 #include "content/common/gpu/media/shared_memory_region.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 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 | 147 |
147 V4L2VideoDecodeAccelerator::PictureRecord::PictureRecord( | 148 V4L2VideoDecodeAccelerator::PictureRecord::PictureRecord( |
148 bool cleared, | 149 bool cleared, |
149 const media::Picture& picture) | 150 const media::Picture& picture) |
150 : cleared(cleared), picture(picture) {} | 151 : cleared(cleared), picture(picture) {} |
151 | 152 |
152 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {} | 153 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {} |
153 | 154 |
154 V4L2VideoDecodeAccelerator::V4L2VideoDecodeAccelerator( | 155 V4L2VideoDecodeAccelerator::V4L2VideoDecodeAccelerator( |
155 EGLDisplay egl_display, | 156 EGLDisplay egl_display, |
156 EGLContext egl_context, | 157 const GetGLContextCallback& get_gl_context_cb, |
157 const base::WeakPtr<Client>& io_client, | 158 const MakeGLContextCurrentCallback& make_context_current_cb, |
158 const base::Callback<bool(void)>& make_context_current, | 159 const scoped_refptr<V4L2Device>& device) |
159 const scoped_refptr<V4L2Device>& device, | |
160 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) | |
161 : child_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 160 : child_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
162 io_task_runner_(io_task_runner), | |
163 io_client_(io_client), | |
164 decoder_thread_("V4L2DecoderThread"), | 161 decoder_thread_("V4L2DecoderThread"), |
165 decoder_state_(kUninitialized), | 162 decoder_state_(kUninitialized), |
166 device_(device), | 163 device_(device), |
167 decoder_delay_bitstream_buffer_id_(-1), | 164 decoder_delay_bitstream_buffer_id_(-1), |
168 decoder_current_input_buffer_(-1), | 165 decoder_current_input_buffer_(-1), |
169 decoder_decode_buffer_tasks_scheduled_(0), | 166 decoder_decode_buffer_tasks_scheduled_(0), |
170 decoder_frames_at_client_(0), | 167 decoder_frames_at_client_(0), |
171 decoder_flushing_(false), | 168 decoder_flushing_(false), |
172 resolution_change_reset_pending_(false), | 169 resolution_change_reset_pending_(false), |
173 decoder_partial_frame_pending_(false), | 170 decoder_partial_frame_pending_(false), |
174 input_streamon_(false), | 171 input_streamon_(false), |
175 input_buffer_queued_count_(0), | 172 input_buffer_queued_count_(0), |
176 output_streamon_(false), | 173 output_streamon_(false), |
177 output_buffer_queued_count_(0), | 174 output_buffer_queued_count_(0), |
178 output_dpb_size_(0), | 175 output_dpb_size_(0), |
179 output_planes_count_(0), | 176 output_planes_count_(0), |
180 picture_clearing_count_(0), | 177 picture_clearing_count_(0), |
181 pictures_assigned_(false, false), | 178 pictures_assigned_(false, false), |
182 device_poll_thread_("V4L2DevicePollThread"), | 179 device_poll_thread_("V4L2DevicePollThread"), |
183 make_context_current_(make_context_current), | |
184 egl_display_(egl_display), | 180 egl_display_(egl_display), |
185 egl_context_(egl_context), | 181 get_gl_context_cb_(get_gl_context_cb), |
| 182 make_context_current_cb_(make_context_current_cb), |
186 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), | 183 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), |
187 output_format_fourcc_(0), | 184 output_format_fourcc_(0), |
188 weak_this_factory_(this) { | 185 weak_this_factory_(this) { |
189 weak_this_ = weak_this_factory_.GetWeakPtr(); | 186 weak_this_ = weak_this_factory_.GetWeakPtr(); |
190 } | 187 } |
191 | 188 |
192 V4L2VideoDecodeAccelerator::~V4L2VideoDecodeAccelerator() { | 189 V4L2VideoDecodeAccelerator::~V4L2VideoDecodeAccelerator() { |
193 DCHECK(!decoder_thread_.IsRunning()); | 190 DCHECK(!decoder_thread_.IsRunning()); |
194 DCHECK(!device_poll_thread_.IsRunning()); | 191 DCHECK(!device_poll_thread_.IsRunning()); |
195 | 192 |
196 DestroyInputBuffers(); | 193 DestroyInputBuffers(); |
197 DestroyOutputBuffers(); | 194 DestroyOutputBuffers(); |
198 | 195 |
199 // These maps have members that should be manually destroyed, e.g. file | 196 // These maps have members that should be manually destroyed, e.g. file |
200 // descriptors, mmap() segments, etc. | 197 // descriptors, mmap() segments, etc. |
201 DCHECK(input_buffer_map_.empty()); | 198 DCHECK(input_buffer_map_.empty()); |
202 DCHECK(output_buffer_map_.empty()); | 199 DCHECK(output_buffer_map_.empty()); |
203 } | 200 } |
204 | 201 |
205 bool V4L2VideoDecodeAccelerator::Initialize(const Config& config, | 202 bool V4L2VideoDecodeAccelerator::Initialize(const Config& config, |
206 Client* client) { | 203 Client* client) { |
207 DVLOG(3) << "Initialize()"; | 204 DVLOG(3) << "Initialize()"; |
208 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 205 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
209 DCHECK_EQ(decoder_state_, kUninitialized); | 206 DCHECK_EQ(decoder_state_, kUninitialized); |
210 | 207 |
| 208 if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) { |
| 209 NOTREACHED() << "GL callbacks are required for this VDA"; |
| 210 return false; |
| 211 } |
| 212 |
211 if (config.is_encrypted) { | 213 if (config.is_encrypted) { |
212 NOTREACHED() << "Encrypted streams are not supported for this VDA"; | 214 NOTREACHED() << "Encrypted streams are not supported for this VDA"; |
213 return false; | 215 return false; |
214 } | 216 } |
215 | 217 |
216 if (!device_->SupportsDecodeProfileForV4L2PixelFormats( | 218 if (!device_->SupportsDecodeProfileForV4L2PixelFormats( |
217 config.profile, arraysize(supported_input_fourccs_), | 219 config.profile, arraysize(supported_input_fourccs_), |
218 supported_input_fourccs_)) { | 220 supported_input_fourccs_)) { |
219 DVLOG(1) << "Initialize(): unsupported profile=" << config.profile; | 221 DVLOG(1) << "Initialize(): unsupported profile=" << config.profile; |
220 return false; | 222 return false; |
221 } | 223 } |
222 | 224 |
223 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); | 225 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); |
224 client_ = client_ptr_factory_->GetWeakPtr(); | 226 client_ = client_ptr_factory_->GetWeakPtr(); |
| 227 // If we haven't been set up to decode on separate thread via |
| 228 // TryToSetupDecodeOnSeparateThread(), use the main thread/client for |
| 229 // decode tasks. |
| 230 if (!decode_task_runner_) { |
| 231 decode_task_runner_ = child_task_runner_; |
| 232 DCHECK(!decode_client_); |
| 233 decode_client_ = client_; |
| 234 } |
225 | 235 |
226 video_profile_ = config.profile; | 236 video_profile_ = config.profile; |
227 | 237 |
228 if (egl_display_ == EGL_NO_DISPLAY) { | 238 if (egl_display_ == EGL_NO_DISPLAY) { |
229 LOG(ERROR) << "Initialize(): could not get EGLDisplay"; | 239 LOG(ERROR) << "Initialize(): could not get EGLDisplay"; |
230 return false; | 240 return false; |
231 } | 241 } |
232 | 242 |
233 // We need the context to be initialized to query extensions. | 243 // We need the context to be initialized to query extensions. |
234 if (!make_context_current_.Run()) { | 244 if (!make_context_current_cb_.Run()) { |
235 LOG(ERROR) << "Initialize(): could not make context current"; | 245 LOG(ERROR) << "Initialize(): could not make context current"; |
236 return false; | 246 return false; |
237 } | 247 } |
238 | 248 |
239 // TODO(posciak): crbug.com/450898. | 249 // TODO(posciak): crbug.com/450898. |
240 #if defined(ARCH_CPU_ARMEL) | 250 #if defined(ARCH_CPU_ARMEL) |
241 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) { | 251 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) { |
242 LOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync"; | 252 LOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync"; |
243 return false; | 253 return false; |
244 } | 254 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 base::IgnoreResult(&V4L2VideoDecodeAccelerator::StartDevicePoll), | 295 base::IgnoreResult(&V4L2VideoDecodeAccelerator::StartDevicePoll), |
286 base::Unretained(this))); | 296 base::Unretained(this))); |
287 | 297 |
288 return true; | 298 return true; |
289 } | 299 } |
290 | 300 |
291 void V4L2VideoDecodeAccelerator::Decode( | 301 void V4L2VideoDecodeAccelerator::Decode( |
292 const media::BitstreamBuffer& bitstream_buffer) { | 302 const media::BitstreamBuffer& bitstream_buffer) { |
293 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() | 303 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() |
294 << ", size=" << bitstream_buffer.size(); | 304 << ", size=" << bitstream_buffer.size(); |
295 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 305 DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
296 | 306 |
297 if (bitstream_buffer.id() < 0) { | 307 if (bitstream_buffer.id() < 0) { |
298 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); | 308 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); |
299 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) | 309 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) |
300 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); | 310 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); |
301 NOTIFY_ERROR(INVALID_ARGUMENT); | 311 NOTIFY_ERROR(INVALID_ARGUMENT); |
302 return; | 312 return; |
303 } | 313 } |
304 | 314 |
305 // DecodeTask() will take care of running a DecodeBufferTask(). | 315 // DecodeTask() will take care of running a DecodeBufferTask(). |
(...skipping 11 matching lines...) Expand all Loading... |
317 output_dpb_size_ + kDpbOutputBufferExtraCount; | 327 output_dpb_size_ + kDpbOutputBufferExtraCount; |
318 | 328 |
319 if (buffers.size() < req_buffer_count) { | 329 if (buffers.size() < req_buffer_count) { |
320 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" | 330 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" |
321 " buffers. (Got " << buffers.size() | 331 " buffers. (Got " << buffers.size() |
322 << ", requested " << req_buffer_count << ")"; | 332 << ", requested " << req_buffer_count << ")"; |
323 NOTIFY_ERROR(INVALID_ARGUMENT); | 333 NOTIFY_ERROR(INVALID_ARGUMENT); |
324 return; | 334 return; |
325 } | 335 } |
326 | 336 |
327 if (!make_context_current_.Run()) { | 337 gfx::GLContext* gl_context = get_gl_context_cb_.Run(); |
| 338 if (!gl_context || !make_context_current_cb_.Run()) { |
328 LOG(ERROR) << "AssignPictureBuffers(): could not make context current"; | 339 LOG(ERROR) << "AssignPictureBuffers(): could not make context current"; |
329 NOTIFY_ERROR(PLATFORM_FAILURE); | 340 NOTIFY_ERROR(PLATFORM_FAILURE); |
330 return; | 341 return; |
331 } | 342 } |
332 | 343 |
333 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); | 344 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); |
334 | 345 |
335 // It's safe to manipulate all the buffer state here, because the decoder | 346 // It's safe to manipulate all the buffer state here, because the decoder |
336 // thread is waiting on pictures_assigned_. | 347 // thread is waiting on pictures_assigned_. |
337 | 348 |
(...skipping 20 matching lines...) Expand all Loading... |
358 OutputRecord& output_record = output_buffer_map_[i]; | 369 OutputRecord& output_record = output_buffer_map_[i]; |
359 DCHECK(!output_record.at_device); | 370 DCHECK(!output_record.at_device); |
360 DCHECK(!output_record.at_client); | 371 DCHECK(!output_record.at_client); |
361 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); | 372 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); |
362 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); | 373 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); |
363 DCHECK_EQ(output_record.picture_id, -1); | 374 DCHECK_EQ(output_record.picture_id, -1); |
364 DCHECK_EQ(output_record.cleared, false); | 375 DCHECK_EQ(output_record.cleared, false); |
365 DCHECK_LE(1u, buffers[i].texture_ids().size()); | 376 DCHECK_LE(1u, buffers[i].texture_ids().size()); |
366 | 377 |
367 EGLImageKHR egl_image = device_->CreateEGLImage( | 378 EGLImageKHR egl_image = device_->CreateEGLImage( |
368 egl_display_, egl_context_, buffers[i].texture_ids()[0], coded_size_, i, | 379 egl_display_, gl_context->GetHandle(), buffers[i].texture_ids()[0], |
369 output_format_fourcc_, output_planes_count_); | 380 coded_size_, i, output_format_fourcc_, output_planes_count_); |
370 if (egl_image == EGL_NO_IMAGE_KHR) { | 381 if (egl_image == EGL_NO_IMAGE_KHR) { |
371 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; | 382 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; |
372 // Ownership of EGLImages allocated in previous iterations of this loop | 383 // Ownership of EGLImages allocated in previous iterations of this loop |
373 // has been transferred to output_buffer_map_. After we error-out here | 384 // has been transferred to output_buffer_map_. After we error-out here |
374 // the destructor will handle their cleanup. | 385 // the destructor will handle their cleanup. |
375 NOTIFY_ERROR(PLATFORM_FAILURE); | 386 NOTIFY_ERROR(PLATFORM_FAILURE); |
376 return; | 387 return; |
377 } | 388 } |
378 | 389 |
379 output_record.egl_image = egl_image; | 390 output_record.egl_image = egl_image; |
380 output_record.picture_id = buffers[i].id(); | 391 output_record.picture_id = buffers[i].id(); |
381 free_output_buffers_.push(i); | 392 free_output_buffers_.push(i); |
382 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i | 393 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i |
383 << "]: picture_id=" << output_record.picture_id; | 394 << "]: picture_id=" << output_record.picture_id; |
384 } | 395 } |
385 | 396 |
386 pictures_assigned_.Signal(); | 397 pictures_assigned_.Signal(); |
387 } | 398 } |
388 | 399 |
389 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) { | 400 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) { |
390 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; | 401 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; |
391 // Must be run on child thread, as we'll insert a sync in the EGL context. | 402 // Must be run on child thread, as we'll insert a sync in the EGL context. |
392 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 403 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
393 | 404 |
394 if (!make_context_current_.Run()) { | 405 if (!make_context_current_cb_.Run()) { |
395 LOG(ERROR) << "ReusePictureBuffer(): could not make context current"; | 406 LOG(ERROR) << "ReusePictureBuffer(): could not make context current"; |
396 NOTIFY_ERROR(PLATFORM_FAILURE); | 407 NOTIFY_ERROR(PLATFORM_FAILURE); |
397 return; | 408 return; |
398 } | 409 } |
399 | 410 |
400 EGLSyncKHR egl_sync = EGL_NO_SYNC_KHR; | 411 EGLSyncKHR egl_sync = EGL_NO_SYNC_KHR; |
401 // TODO(posciak): crbug.com/450898. | 412 // TODO(posciak): crbug.com/450898. |
402 #if defined(ARCH_CPU_ARMEL) | 413 #if defined(ARCH_CPU_ARMEL) |
403 egl_sync = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); | 414 egl_sync = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); |
404 if (egl_sync == EGL_NO_SYNC_KHR) { | 415 if (egl_sync == EGL_NO_SYNC_KHR) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 // DestroyTask() will cause the decoder_thread_ to flush all tasks. | 456 // DestroyTask() will cause the decoder_thread_ to flush all tasks. |
446 decoder_thread_.Stop(); | 457 decoder_thread_.Stop(); |
447 } else { | 458 } else { |
448 // Otherwise, call the destroy task directly. | 459 // Otherwise, call the destroy task directly. |
449 DestroyTask(); | 460 DestroyTask(); |
450 } | 461 } |
451 | 462 |
452 delete this; | 463 delete this; |
453 } | 464 } |
454 | 465 |
455 bool V4L2VideoDecodeAccelerator::CanDecodeOnIOThread() { return true; } | 466 bool V4L2VideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( |
| 467 const base::WeakPtr<Client>& decode_client, |
| 468 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { |
| 469 decode_client_ = decode_client_; |
| 470 decode_task_runner_ = decode_task_runner; |
| 471 return true; |
| 472 } |
456 | 473 |
457 // static | 474 // static |
458 media::VideoDecodeAccelerator::SupportedProfiles | 475 media::VideoDecodeAccelerator::SupportedProfiles |
459 V4L2VideoDecodeAccelerator::GetSupportedProfiles() { | 476 V4L2VideoDecodeAccelerator::GetSupportedProfiles() { |
460 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); | 477 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); |
461 if (!device) | 478 if (!device) |
462 return SupportedProfiles(); | 479 return SupportedProfiles(); |
463 | 480 |
464 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), | 481 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), |
465 supported_input_fourccs_); | 482 supported_input_fourccs_); |
466 } | 483 } |
467 | 484 |
468 void V4L2VideoDecodeAccelerator::DecodeTask( | 485 void V4L2VideoDecodeAccelerator::DecodeTask( |
469 const media::BitstreamBuffer& bitstream_buffer) { | 486 const media::BitstreamBuffer& bitstream_buffer) { |
470 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); | 487 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); |
471 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 488 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
472 DCHECK_NE(decoder_state_, kUninitialized); | 489 DCHECK_NE(decoder_state_, kUninitialized); |
473 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", | 490 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", |
474 bitstream_buffer.id()); | 491 bitstream_buffer.id()); |
475 | 492 |
476 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( | 493 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( |
477 io_client_, io_task_runner_, | 494 decode_client_, decode_task_runner_, |
478 scoped_ptr<SharedMemoryRegion>( | 495 scoped_ptr<SharedMemoryRegion>( |
479 new SharedMemoryRegion(bitstream_buffer, true)), | 496 new SharedMemoryRegion(bitstream_buffer, true)), |
480 bitstream_buffer.id())); | 497 bitstream_buffer.id())); |
481 if (!bitstream_record->shm->Map()) { | 498 if (!bitstream_record->shm->Map()) { |
482 LOG(ERROR) << "Decode(): could not map bitstream_buffer"; | 499 LOG(ERROR) << "Decode(): could not map bitstream_buffer"; |
483 NOTIFY_ERROR(UNREADABLE_INPUT); | 500 NOTIFY_ERROR(UNREADABLE_INPUT); |
484 return; | 501 return; |
485 } | 502 } |
486 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory(); | 503 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory(); |
487 | 504 |
(...skipping 772 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1260 DVLOG(2) << "FlushTask(): early out: kError state"; | 1277 DVLOG(2) << "FlushTask(): early out: kError state"; |
1261 return; | 1278 return; |
1262 } | 1279 } |
1263 | 1280 |
1264 // We don't support stacked flushing. | 1281 // We don't support stacked flushing. |
1265 DCHECK(!decoder_flushing_); | 1282 DCHECK(!decoder_flushing_); |
1266 | 1283 |
1267 // Queue up an empty buffer -- this triggers the flush. | 1284 // Queue up an empty buffer -- this triggers the flush. |
1268 decoder_input_queue_.push( | 1285 decoder_input_queue_.push( |
1269 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( | 1286 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( |
1270 io_client_, io_task_runner_, nullptr, kFlushBufferId))); | 1287 decode_client_, decode_task_runner_, nullptr, kFlushBufferId))); |
1271 decoder_flushing_ = true; | 1288 decoder_flushing_ = true; |
1272 SendPictureReady(); // Send all pending PictureReady. | 1289 SendPictureReady(); // Send all pending PictureReady. |
1273 | 1290 |
1274 ScheduleDecodeBufferTaskIfNeeded(); | 1291 ScheduleDecodeBufferTaskIfNeeded(); |
1275 } | 1292 } |
1276 | 1293 |
1277 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { | 1294 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { |
1278 if (!decoder_flushing_) | 1295 if (!decoder_flushing_) |
1279 return; | 1296 return; |
1280 | 1297 |
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1983 | 2000 |
1984 void V4L2VideoDecodeAccelerator::SendPictureReady() { | 2001 void V4L2VideoDecodeAccelerator::SendPictureReady() { |
1985 DVLOG(3) << "SendPictureReady()"; | 2002 DVLOG(3) << "SendPictureReady()"; |
1986 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 2003 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
1987 bool resetting_or_flushing = | 2004 bool resetting_or_flushing = |
1988 (decoder_state_ == kResetting || decoder_flushing_); | 2005 (decoder_state_ == kResetting || decoder_flushing_); |
1989 while (pending_picture_ready_.size() > 0) { | 2006 while (pending_picture_ready_.size() > 0) { |
1990 bool cleared = pending_picture_ready_.front().cleared; | 2007 bool cleared = pending_picture_ready_.front().cleared; |
1991 const media::Picture& picture = pending_picture_ready_.front().picture; | 2008 const media::Picture& picture = pending_picture_ready_.front().picture; |
1992 if (cleared && picture_clearing_count_ == 0) { | 2009 if (cleared && picture_clearing_count_ == 0) { |
1993 // This picture is cleared. Post it to IO thread to reduce latency. This | 2010 // This picture is cleared. It can be posted to a thread different than |
1994 // should be the case after all pictures are cleared at the beginning. | 2011 // the main GPU thread to reduce latency. This should be the case after |
1995 io_task_runner_->PostTask( | 2012 // all pictures are cleared at the beginning. |
1996 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture)); | 2013 decode_task_runner_->PostTask( |
| 2014 FROM_HERE, |
| 2015 base::Bind(&Client::PictureReady, decode_client_, picture)); |
1997 pending_picture_ready_.pop(); | 2016 pending_picture_ready_.pop(); |
1998 } else if (!cleared || resetting_or_flushing) { | 2017 } else if (!cleared || resetting_or_flushing) { |
1999 DVLOG(3) << "SendPictureReady()" | 2018 DVLOG(3) << "SendPictureReady()" |
2000 << ". cleared=" << pending_picture_ready_.front().cleared | 2019 << ". cleared=" << pending_picture_ready_.front().cleared |
2001 << ", decoder_state_=" << decoder_state_ | 2020 << ", decoder_state_=" << decoder_state_ |
2002 << ", decoder_flushing_=" << decoder_flushing_ | 2021 << ", decoder_flushing_=" << decoder_flushing_ |
2003 << ", picture_clearing_count_=" << picture_clearing_count_; | 2022 << ", picture_clearing_count_=" << picture_clearing_count_; |
2004 // If the picture is not cleared, post it to the child thread because it | 2023 // If the picture is not cleared, post it to the child thread because it |
2005 // has to be cleared in the child thread. A picture only needs to be | 2024 // has to be cleared in the child thread. A picture only needs to be |
2006 // cleared once. If the decoder is resetting or flushing, send all | 2025 // cleared once. If the decoder is resetting or flushing, send all |
(...skipping 17 matching lines...) Expand all Loading... |
2024 | 2043 |
2025 void V4L2VideoDecodeAccelerator::PictureCleared() { | 2044 void V4L2VideoDecodeAccelerator::PictureCleared() { |
2026 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; | 2045 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; |
2027 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); | 2046 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
2028 DCHECK_GT(picture_clearing_count_, 0); | 2047 DCHECK_GT(picture_clearing_count_, 0); |
2029 picture_clearing_count_--; | 2048 picture_clearing_count_--; |
2030 SendPictureReady(); | 2049 SendPictureReady(); |
2031 } | 2050 } |
2032 | 2051 |
2033 } // namespace content | 2052 } // namespace content |
OLD | NEW |