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

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

Issue 1839193003: Reland: Introduce GpuVideoDecodeAcceleratorFactory. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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/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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698