Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(387)

Side by Side Diff: content/common/gpu/media/v4l2_video_decode_accelerator.cc

Issue 1745903002: Introduce GpuVideoDecodeAcceleratorFactory. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
200 DestroyInputBuffers(); 197 DestroyInputBuffers();
201 DestroyOutputBuffers(); 198 DestroyOutputBuffers();
202 199
203 // These maps have members that should be manually destroyed, e.g. file 200 // These maps have members that should be manually destroyed, e.g. file
204 // descriptors, mmap() segments, etc. 201 // descriptors, mmap() segments, etc.
205 DCHECK(input_buffer_map_.empty()); 202 DCHECK(input_buffer_map_.empty());
206 DCHECK(output_buffer_map_.empty()); 203 DCHECK(output_buffer_map_.empty());
207 } 204 }
208 205
209 bool V4L2VideoDecodeAccelerator::Initialize(const Config& config, 206 bool V4L2VideoDecodeAccelerator::Initialize(const Config& config,
210 Client* client) { 207 Client* client) {
211 DVLOG(3) << "Initialize()"; 208 DVLOG(3) << "Initialize()";
212 DCHECK(child_task_runner_->BelongsToCurrentThread()); 209 DCHECK(child_task_runner_->BelongsToCurrentThread());
213 DCHECK_EQ(decoder_state_, kUninitialized); 210 DCHECK_EQ(decoder_state_, kUninitialized);
214 211
212 if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) {
213 NOTREACHED() << "GL callbacks are required for this VDA";
214 return false;
215 }
216
215 if (config.is_encrypted) { 217 if (config.is_encrypted) {
216 NOTREACHED() << "Encrypted streams are not supported for this VDA"; 218 NOTREACHED() << "Encrypted streams are not supported for this VDA";
217 return false; 219 return false;
218 } 220 }
219 221
220 if (!device_->SupportsDecodeProfileForV4L2PixelFormats( 222 if (!device_->SupportsDecodeProfileForV4L2PixelFormats(
221 config.profile, arraysize(supported_input_fourccs_), 223 config.profile, arraysize(supported_input_fourccs_),
222 supported_input_fourccs_)) { 224 supported_input_fourccs_)) {
223 DVLOG(1) << "Initialize(): unsupported profile=" << config.profile; 225 DVLOG(1) << "Initialize(): unsupported profile=" << config.profile;
224 return false; 226 return false;
225 } 227 }
226 228
227 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); 229 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
228 client_ = client_ptr_factory_->GetWeakPtr(); 230 client_ = client_ptr_factory_->GetWeakPtr();
231 // If we haven't been set up to decode on separate thread via
232 // TryInitializeDecodeOnSeparateThread(), use the main thread/client for
233 // decode tasks.
234 if (!decode_task_runner_) {
235 decode_task_runner_ = child_task_runner_;
236 DCHECK(!decode_client_);
237 decode_client_ = client_;
238 }
229 239
230 video_profile_ = config.profile; 240 video_profile_ = config.profile;
231 241
232 if (egl_display_ == EGL_NO_DISPLAY) { 242 if (egl_display_ == EGL_NO_DISPLAY) {
233 LOG(ERROR) << "Initialize(): could not get EGLDisplay"; 243 LOG(ERROR) << "Initialize(): could not get EGLDisplay";
234 return false; 244 return false;
235 } 245 }
236 246
237 // We need the context to be initialized to query extensions. 247 // We need the context to be initialized to query extensions.
238 if (!make_context_current_.Run()) { 248 if (!make_context_current_cb_.Run()) {
239 LOG(ERROR) << "Initialize(): could not make context current"; 249 LOG(ERROR) << "Initialize(): could not make context current";
240 return false; 250 return false;
241 } 251 }
242 252
243 // TODO(posciak): crbug.com/450898. 253 // TODO(posciak): crbug.com/450898.
244 #if defined(ARCH_CPU_ARMEL) 254 #if defined(ARCH_CPU_ARMEL)
245 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) { 255 if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) {
246 LOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync"; 256 LOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync";
247 return false; 257 return false;
248 } 258 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 base::IgnoreResult(&V4L2VideoDecodeAccelerator::StartDevicePoll), 299 base::IgnoreResult(&V4L2VideoDecodeAccelerator::StartDevicePoll),
290 base::Unretained(this))); 300 base::Unretained(this)));
291 301
292 return true; 302 return true;
293 } 303 }
294 304
295 void V4L2VideoDecodeAccelerator::Decode( 305 void V4L2VideoDecodeAccelerator::Decode(
296 const media::BitstreamBuffer& bitstream_buffer) { 306 const media::BitstreamBuffer& bitstream_buffer) {
297 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() 307 DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id()
298 << ", size=" << bitstream_buffer.size(); 308 << ", size=" << bitstream_buffer.size();
299 DCHECK(io_task_runner_->BelongsToCurrentThread()); 309 DCHECK(decode_task_runner_->BelongsToCurrentThread());
300 310
301 if (bitstream_buffer.id() < 0) { 311 if (bitstream_buffer.id() < 0) {
302 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); 312 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id();
303 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) 313 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle()))
304 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); 314 base::SharedMemory::CloseHandle(bitstream_buffer.handle());
305 NOTIFY_ERROR(INVALID_ARGUMENT); 315 NOTIFY_ERROR(INVALID_ARGUMENT);
306 return; 316 return;
307 } 317 }
308 318
309 // DecodeTask() will take care of running a DecodeBufferTask(). 319 // DecodeTask() will take care of running a DecodeBufferTask().
(...skipping 11 matching lines...) Expand all
321 output_dpb_size_ + kDpbOutputBufferExtraCount; 331 output_dpb_size_ + kDpbOutputBufferExtraCount;
322 332
323 if (buffers.size() < req_buffer_count) { 333 if (buffers.size() < req_buffer_count) {
324 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture" 334 LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture"
325 " buffers. (Got " << buffers.size() 335 " buffers. (Got " << buffers.size()
326 << ", requested " << req_buffer_count << ")"; 336 << ", requested " << req_buffer_count << ")";
327 NOTIFY_ERROR(INVALID_ARGUMENT); 337 NOTIFY_ERROR(INVALID_ARGUMENT);
328 return; 338 return;
329 } 339 }
330 340
331 if (!make_context_current_.Run()) { 341 gfx::GLContext* gl_context = get_gl_context_cb_.Run();
342 if (!gl_context || !make_context_current_cb_.Run()) {
332 LOG(ERROR) << "AssignPictureBuffers(): could not make context current"; 343 LOG(ERROR) << "AssignPictureBuffers(): could not make context current";
333 NOTIFY_ERROR(PLATFORM_FAILURE); 344 NOTIFY_ERROR(PLATFORM_FAILURE);
334 return; 345 return;
335 } 346 }
336 347
337 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); 348 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0);
338 349
339 // It's safe to manipulate all the buffer state here, because the decoder 350 // It's safe to manipulate all the buffer state here, because the decoder
340 // thread is waiting on pictures_assigned_. 351 // thread is waiting on pictures_assigned_.
341 352
(...skipping 19 matching lines...) Expand all
361 372
362 OutputRecord& output_record = output_buffer_map_[i]; 373 OutputRecord& output_record = output_buffer_map_[i];
363 DCHECK(!output_record.at_device); 374 DCHECK(!output_record.at_device);
364 DCHECK(!output_record.at_client); 375 DCHECK(!output_record.at_client);
365 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); 376 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR);
366 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); 377 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
367 DCHECK_EQ(output_record.picture_id, -1); 378 DCHECK_EQ(output_record.picture_id, -1);
368 DCHECK_EQ(output_record.cleared, false); 379 DCHECK_EQ(output_record.cleared, false);
369 380
370 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_, 381 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_,
371 egl_context_, 382 gl_context->GetHandle(),
372 buffers[i].texture_id(), 383 buffers[i].texture_id(),
373 coded_size_, 384 coded_size_,
374 i, 385 i,
375 output_format_fourcc_, 386 output_format_fourcc_,
376 output_planes_count_); 387 output_planes_count_);
377 if (egl_image == EGL_NO_IMAGE_KHR) { 388 if (egl_image == EGL_NO_IMAGE_KHR) {
378 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; 389 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR";
379 // Ownership of EGLImages allocated in previous iterations of this loop 390 // Ownership of EGLImages allocated in previous iterations of this loop
380 // has been transferred to output_buffer_map_. After we error-out here 391 // has been transferred to output_buffer_map_. After we error-out here
381 // the destructor will handle their cleanup. 392 // the destructor will handle their cleanup.
382 NOTIFY_ERROR(PLATFORM_FAILURE); 393 NOTIFY_ERROR(PLATFORM_FAILURE);
383 return; 394 return;
384 } 395 }
385 396
386 output_record.egl_image = egl_image; 397 output_record.egl_image = egl_image;
387 output_record.picture_id = buffers[i].id(); 398 output_record.picture_id = buffers[i].id();
388 free_output_buffers_.push(i); 399 free_output_buffers_.push(i);
389 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i 400 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i
390 << "]: picture_id=" << output_record.picture_id; 401 << "]: picture_id=" << output_record.picture_id;
391 } 402 }
392 403
393 pictures_assigned_.Signal(); 404 pictures_assigned_.Signal();
394 } 405 }
395 406
396 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) { 407 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) {
397 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; 408 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. 409 // Must be run on child thread, as we'll insert a sync in the EGL context.
399 DCHECK(child_task_runner_->BelongsToCurrentThread()); 410 DCHECK(child_task_runner_->BelongsToCurrentThread());
400 411
401 if (!make_context_current_.Run()) { 412 if (!make_context_current_cb_.Run()) {
402 LOG(ERROR) << "ReusePictureBuffer(): could not make context current"; 413 LOG(ERROR) << "ReusePictureBuffer(): could not make context current";
403 NOTIFY_ERROR(PLATFORM_FAILURE); 414 NOTIFY_ERROR(PLATFORM_FAILURE);
404 return; 415 return;
405 } 416 }
406 417
407 EGLSyncKHR egl_sync = EGL_NO_SYNC_KHR; 418 EGLSyncKHR egl_sync = EGL_NO_SYNC_KHR;
408 // TODO(posciak): crbug.com/450898. 419 // TODO(posciak): crbug.com/450898.
409 #if defined(ARCH_CPU_ARMEL) 420 #if defined(ARCH_CPU_ARMEL)
410 egl_sync = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); 421 egl_sync = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL);
411 if (egl_sync == EGL_NO_SYNC_KHR) { 422 if (egl_sync == EGL_NO_SYNC_KHR) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 // DestroyTask() will cause the decoder_thread_ to flush all tasks. 463 // DestroyTask() will cause the decoder_thread_ to flush all tasks.
453 decoder_thread_.Stop(); 464 decoder_thread_.Stop();
454 } else { 465 } else {
455 // Otherwise, call the destroy task directly. 466 // Otherwise, call the destroy task directly.
456 DestroyTask(); 467 DestroyTask();
457 } 468 }
458 469
459 delete this; 470 delete this;
460 } 471 }
461 472
462 bool V4L2VideoDecodeAccelerator::CanDecodeOnIOThread() { return true; } 473 bool V4L2VideoDecodeAccelerator::TryInitializeDecodeOnSeparateThread(
474 const base::WeakPtr<Client>& decode_client,
475 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
476 decode_client_ = decode_client_;
477 decode_task_runner_ = decode_task_runner;
478 return true;
479 }
463 480
464 // static 481 // static
465 media::VideoDecodeAccelerator::SupportedProfiles 482 media::VideoDecodeAccelerator::SupportedProfiles
466 V4L2VideoDecodeAccelerator::GetSupportedProfiles() { 483 V4L2VideoDecodeAccelerator::GetSupportedProfiles() {
467 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); 484 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder);
468 if (!device) 485 if (!device)
469 return SupportedProfiles(); 486 return SupportedProfiles();
470 487
471 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), 488 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_),
472 supported_input_fourccs_); 489 supported_input_fourccs_);
473 } 490 }
474 491
475 void V4L2VideoDecodeAccelerator::DecodeTask( 492 void V4L2VideoDecodeAccelerator::DecodeTask(
476 const media::BitstreamBuffer& bitstream_buffer) { 493 const media::BitstreamBuffer& bitstream_buffer) {
477 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); 494 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id();
478 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 495 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
479 DCHECK_NE(decoder_state_, kUninitialized); 496 DCHECK_NE(decoder_state_, kUninitialized);
480 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", 497 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id",
481 bitstream_buffer.id()); 498 bitstream_buffer.id());
482 499
483 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( 500 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef(
484 io_client_, io_task_runner_, 501 decode_client_, decode_task_runner_,
485 new base::SharedMemory(bitstream_buffer.handle(), true), 502 new base::SharedMemory(bitstream_buffer.handle(), true),
486 bitstream_buffer.size(), bitstream_buffer.id())); 503 bitstream_buffer.size(), bitstream_buffer.id()));
487 if (!bitstream_record->shm->Map(bitstream_buffer.size())) { 504 if (!bitstream_record->shm->Map(bitstream_buffer.size())) {
488 LOG(ERROR) << "Decode(): could not map bitstream_buffer"; 505 LOG(ERROR) << "Decode(): could not map bitstream_buffer";
489 NOTIFY_ERROR(UNREADABLE_INPUT); 506 NOTIFY_ERROR(UNREADABLE_INPUT);
490 return; 507 return;
491 } 508 }
492 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory(); 509 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory();
493 510
494 if (decoder_state_ == kResetting || decoder_flushing_) { 511 if (decoder_state_ == kResetting || decoder_flushing_) {
(...skipping 774 matching lines...) Expand 10 before | Expand all | Expand 10 after
1269 DVLOG(2) << "FlushTask(): early out: kError state"; 1286 DVLOG(2) << "FlushTask(): early out: kError state";
1270 return; 1287 return;
1271 } 1288 }
1272 1289
1273 // We don't support stacked flushing. 1290 // We don't support stacked flushing.
1274 DCHECK(!decoder_flushing_); 1291 DCHECK(!decoder_flushing_);
1275 1292
1276 // Queue up an empty buffer -- this triggers the flush. 1293 // Queue up an empty buffer -- this triggers the flush.
1277 decoder_input_queue_.push( 1294 decoder_input_queue_.push(
1278 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( 1295 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef(
1279 io_client_, io_task_runner_, NULL, 0, kFlushBufferId))); 1296 decode_client_, decode_task_runner_, NULL, 0, kFlushBufferId)));
1280 decoder_flushing_ = true; 1297 decoder_flushing_ = true;
1281 SendPictureReady(); // Send all pending PictureReady. 1298 SendPictureReady(); // Send all pending PictureReady.
1282 1299
1283 ScheduleDecodeBufferTaskIfNeeded(); 1300 ScheduleDecodeBufferTaskIfNeeded();
1284 } 1301 }
1285 1302
1286 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { 1303 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() {
1287 if (!decoder_flushing_) 1304 if (!decoder_flushing_)
1288 return; 1305 return;
1289 1306
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after
1992 2009
1993 void V4L2VideoDecodeAccelerator::SendPictureReady() { 2010 void V4L2VideoDecodeAccelerator::SendPictureReady() {
1994 DVLOG(3) << "SendPictureReady()"; 2011 DVLOG(3) << "SendPictureReady()";
1995 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 2012 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1996 bool resetting_or_flushing = 2013 bool resetting_or_flushing =
1997 (decoder_state_ == kResetting || decoder_flushing_); 2014 (decoder_state_ == kResetting || decoder_flushing_);
1998 while (pending_picture_ready_.size() > 0) { 2015 while (pending_picture_ready_.size() > 0) {
1999 bool cleared = pending_picture_ready_.front().cleared; 2016 bool cleared = pending_picture_ready_.front().cleared;
2000 const media::Picture& picture = pending_picture_ready_.front().picture; 2017 const media::Picture& picture = pending_picture_ready_.front().picture;
2001 if (cleared && picture_clearing_count_ == 0) { 2018 if (cleared && picture_clearing_count_ == 0) {
2002 // This picture is cleared. Post it to IO thread to reduce latency. This 2019 // 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. 2020 // the main GPU thread to reduce latency. This should be the case after
2004 io_task_runner_->PostTask( 2021 // all pictures are cleared at the beginning.
2005 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture)); 2022 decode_task_runner_->PostTask(
2023 FROM_HERE,
2024 base::Bind(&Client::PictureReady, decode_client_, picture));
2006 pending_picture_ready_.pop(); 2025 pending_picture_ready_.pop();
2007 } else if (!cleared || resetting_or_flushing) { 2026 } else if (!cleared || resetting_or_flushing) {
2008 DVLOG(3) << "SendPictureReady()" 2027 DVLOG(3) << "SendPictureReady()"
2009 << ". cleared=" << pending_picture_ready_.front().cleared 2028 << ". cleared=" << pending_picture_ready_.front().cleared
2010 << ", decoder_state_=" << decoder_state_ 2029 << ", decoder_state_=" << decoder_state_
2011 << ", decoder_flushing_=" << decoder_flushing_ 2030 << ", decoder_flushing_=" << decoder_flushing_
2012 << ", picture_clearing_count_=" << picture_clearing_count_; 2031 << ", picture_clearing_count_=" << picture_clearing_count_;
2013 // If the picture is not cleared, post it to the child thread because it 2032 // 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 2033 // 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 2034 // cleared once. If the decoder is resetting or flushing, send all
(...skipping 17 matching lines...) Expand all
2033 2052
2034 void V4L2VideoDecodeAccelerator::PictureCleared() { 2053 void V4L2VideoDecodeAccelerator::PictureCleared() {
2035 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; 2054 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_;
2036 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 2055 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
2037 DCHECK_GT(picture_clearing_count_, 0); 2056 DCHECK_GT(picture_clearing_count_, 0);
2038 picture_clearing_count_--; 2057 picture_clearing_count_--;
2039 SendPictureReady(); 2058 SendPictureReady();
2040 } 2059 }
2041 2060
2042 } // namespace content 2061 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698