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

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/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 19 matching lines...) Expand all
357 368
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 376
366 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_, 377 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_,
367 egl_context_, 378 gl_context->GetHandle(),
368 buffers[i].texture_id(), 379 buffers[i].texture_id(),
369 coded_size_, 380 coded_size_,
370 i, 381 i,
371 output_format_fourcc_, 382 output_format_fourcc_,
372 output_planes_count_); 383 output_planes_count_);
373 if (egl_image == EGL_NO_IMAGE_KHR) { 384 if (egl_image == EGL_NO_IMAGE_KHR) {
374 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; 385 LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR";
375 // Ownership of EGLImages allocated in previous iterations of this loop 386 // Ownership of EGLImages allocated in previous iterations of this loop
376 // has been transferred to output_buffer_map_. After we error-out here 387 // has been transferred to output_buffer_map_. After we error-out here
377 // the destructor will handle their cleanup. 388 // the destructor will handle their cleanup.
378 NOTIFY_ERROR(PLATFORM_FAILURE); 389 NOTIFY_ERROR(PLATFORM_FAILURE);
379 return; 390 return;
380 } 391 }
381 392
382 output_record.egl_image = egl_image; 393 output_record.egl_image = egl_image;
383 output_record.picture_id = buffers[i].id(); 394 output_record.picture_id = buffers[i].id();
384 free_output_buffers_.push(i); 395 free_output_buffers_.push(i);
385 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i 396 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i
386 << "]: picture_id=" << output_record.picture_id; 397 << "]: picture_id=" << output_record.picture_id;
387 } 398 }
388 399
389 pictures_assigned_.Signal(); 400 pictures_assigned_.Signal();
390 } 401 }
391 402
392 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) { 403 void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) {
393 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id; 404 DVLOG(3) << "ReusePictureBuffer(): picture_buffer_id=" << picture_buffer_id;
394 // Must be run on child thread, as we'll insert a sync in the EGL context. 405 // Must be run on child thread, as we'll insert a sync in the EGL context.
395 DCHECK(child_task_runner_->BelongsToCurrentThread()); 406 DCHECK(child_task_runner_->BelongsToCurrentThread());
396 407
397 if (!make_context_current_.Run()) { 408 if (!make_context_current_cb_.Run()) {
398 LOG(ERROR) << "ReusePictureBuffer(): could not make context current"; 409 LOG(ERROR) << "ReusePictureBuffer(): could not make context current";
399 NOTIFY_ERROR(PLATFORM_FAILURE); 410 NOTIFY_ERROR(PLATFORM_FAILURE);
400 return; 411 return;
401 } 412 }
402 413
403 EGLSyncKHR egl_sync = EGL_NO_SYNC_KHR; 414 EGLSyncKHR egl_sync = EGL_NO_SYNC_KHR;
404 // TODO(posciak): crbug.com/450898. 415 // TODO(posciak): crbug.com/450898.
405 #if defined(ARCH_CPU_ARMEL) 416 #if defined(ARCH_CPU_ARMEL)
406 egl_sync = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL); 417 egl_sync = eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL);
407 if (egl_sync == EGL_NO_SYNC_KHR) { 418 if (egl_sync == EGL_NO_SYNC_KHR) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 // DestroyTask() will cause the decoder_thread_ to flush all tasks. 459 // DestroyTask() will cause the decoder_thread_ to flush all tasks.
449 decoder_thread_.Stop(); 460 decoder_thread_.Stop();
450 } else { 461 } else {
451 // Otherwise, call the destroy task directly. 462 // Otherwise, call the destroy task directly.
452 DestroyTask(); 463 DestroyTask();
453 } 464 }
454 465
455 delete this; 466 delete this;
456 } 467 }
457 468
458 bool V4L2VideoDecodeAccelerator::CanDecodeOnIOThread() { return true; } 469 bool V4L2VideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
470 const base::WeakPtr<Client>& decode_client,
471 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
472 decode_client_ = decode_client_;
473 decode_task_runner_ = decode_task_runner;
474 return true;
475 }
459 476
460 // static 477 // static
461 media::VideoDecodeAccelerator::SupportedProfiles 478 media::VideoDecodeAccelerator::SupportedProfiles
462 V4L2VideoDecodeAccelerator::GetSupportedProfiles() { 479 V4L2VideoDecodeAccelerator::GetSupportedProfiles() {
463 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); 480 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder);
464 if (!device) 481 if (!device)
465 return SupportedProfiles(); 482 return SupportedProfiles();
466 483
467 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_), 484 return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_),
468 supported_input_fourccs_); 485 supported_input_fourccs_);
469 } 486 }
470 487
471 void V4L2VideoDecodeAccelerator::DecodeTask( 488 void V4L2VideoDecodeAccelerator::DecodeTask(
472 const media::BitstreamBuffer& bitstream_buffer) { 489 const media::BitstreamBuffer& bitstream_buffer) {
473 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); 490 DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id();
474 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 491 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
475 DCHECK_NE(decoder_state_, kUninitialized); 492 DCHECK_NE(decoder_state_, kUninitialized);
476 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id", 493 TRACE_EVENT1("Video Decoder", "V4L2VDA::DecodeTask", "input_id",
477 bitstream_buffer.id()); 494 bitstream_buffer.id());
478 495
479 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( 496 scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef(
480 io_client_, io_task_runner_, 497 decode_client_, decode_task_runner_,
481 scoped_ptr<SharedMemoryRegion>( 498 scoped_ptr<SharedMemoryRegion>(
482 new SharedMemoryRegion(bitstream_buffer, true)), 499 new SharedMemoryRegion(bitstream_buffer, true)),
483 bitstream_buffer.id())); 500 bitstream_buffer.id()));
484 if (!bitstream_record->shm->Map()) { 501 if (!bitstream_record->shm->Map()) {
485 LOG(ERROR) << "Decode(): could not map bitstream_buffer"; 502 LOG(ERROR) << "Decode(): could not map bitstream_buffer";
486 NOTIFY_ERROR(UNREADABLE_INPUT); 503 NOTIFY_ERROR(UNREADABLE_INPUT);
487 return; 504 return;
488 } 505 }
489 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory(); 506 DVLOG(3) << "DecodeTask(): mapped at=" << bitstream_record->shm->memory();
490 507
(...skipping 772 matching lines...) Expand 10 before | Expand all | Expand 10 after
1263 DVLOG(2) << "FlushTask(): early out: kError state"; 1280 DVLOG(2) << "FlushTask(): early out: kError state";
1264 return; 1281 return;
1265 } 1282 }
1266 1283
1267 // We don't support stacked flushing. 1284 // We don't support stacked flushing.
1268 DCHECK(!decoder_flushing_); 1285 DCHECK(!decoder_flushing_);
1269 1286
1270 // Queue up an empty buffer -- this triggers the flush. 1287 // Queue up an empty buffer -- this triggers the flush.
1271 decoder_input_queue_.push( 1288 decoder_input_queue_.push(
1272 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef( 1289 linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef(
1273 io_client_, io_task_runner_, nullptr, kFlushBufferId))); 1290 decode_client_, decode_task_runner_, nullptr, kFlushBufferId)));
1274 decoder_flushing_ = true; 1291 decoder_flushing_ = true;
1275 SendPictureReady(); // Send all pending PictureReady. 1292 SendPictureReady(); // Send all pending PictureReady.
1276 1293
1277 ScheduleDecodeBufferTaskIfNeeded(); 1294 ScheduleDecodeBufferTaskIfNeeded();
1278 } 1295 }
1279 1296
1280 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() { 1297 void V4L2VideoDecodeAccelerator::NotifyFlushDoneIfNeeded() {
1281 if (!decoder_flushing_) 1298 if (!decoder_flushing_)
1282 return; 1299 return;
1283 1300
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after
1986 2003
1987 void V4L2VideoDecodeAccelerator::SendPictureReady() { 2004 void V4L2VideoDecodeAccelerator::SendPictureReady() {
1988 DVLOG(3) << "SendPictureReady()"; 2005 DVLOG(3) << "SendPictureReady()";
1989 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 2006 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1990 bool resetting_or_flushing = 2007 bool resetting_or_flushing =
1991 (decoder_state_ == kResetting || decoder_flushing_); 2008 (decoder_state_ == kResetting || decoder_flushing_);
1992 while (pending_picture_ready_.size() > 0) { 2009 while (pending_picture_ready_.size() > 0) {
1993 bool cleared = pending_picture_ready_.front().cleared; 2010 bool cleared = pending_picture_ready_.front().cleared;
1994 const media::Picture& picture = pending_picture_ready_.front().picture; 2011 const media::Picture& picture = pending_picture_ready_.front().picture;
1995 if (cleared && picture_clearing_count_ == 0) { 2012 if (cleared && picture_clearing_count_ == 0) {
1996 // This picture is cleared. Post it to IO thread to reduce latency. This 2013 // This picture is cleared. It can be posted to a thread different than
1997 // should be the case after all pictures are cleared at the beginning. 2014 // the main GPU thread to reduce latency. This should be the case after
1998 io_task_runner_->PostTask( 2015 // all pictures are cleared at the beginning.
1999 FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture)); 2016 decode_task_runner_->PostTask(
2017 FROM_HERE,
2018 base::Bind(&Client::PictureReady, decode_client_, picture));
2000 pending_picture_ready_.pop(); 2019 pending_picture_ready_.pop();
2001 } else if (!cleared || resetting_or_flushing) { 2020 } else if (!cleared || resetting_or_flushing) {
2002 DVLOG(3) << "SendPictureReady()" 2021 DVLOG(3) << "SendPictureReady()"
2003 << ". cleared=" << pending_picture_ready_.front().cleared 2022 << ". cleared=" << pending_picture_ready_.front().cleared
2004 << ", decoder_state_=" << decoder_state_ 2023 << ", decoder_state_=" << decoder_state_
2005 << ", decoder_flushing_=" << decoder_flushing_ 2024 << ", decoder_flushing_=" << decoder_flushing_
2006 << ", picture_clearing_count_=" << picture_clearing_count_; 2025 << ", picture_clearing_count_=" << picture_clearing_count_;
2007 // If the picture is not cleared, post it to the child thread because it 2026 // If the picture is not cleared, post it to the child thread because it
2008 // has to be cleared in the child thread. A picture only needs to be 2027 // has to be cleared in the child thread. A picture only needs to be
2009 // cleared once. If the decoder is resetting or flushing, send all 2028 // cleared once. If the decoder is resetting or flushing, send all
(...skipping 17 matching lines...) Expand all
2027 2046
2028 void V4L2VideoDecodeAccelerator::PictureCleared() { 2047 void V4L2VideoDecodeAccelerator::PictureCleared() {
2029 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; 2048 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_;
2030 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 2049 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
2031 DCHECK_GT(picture_clearing_count_, 0); 2050 DCHECK_GT(picture_clearing_count_, 0);
2032 picture_clearing_count_--; 2051 picture_clearing_count_--;
2033 SendPictureReady(); 2052 SendPictureReady();
2034 } 2053 }
2035 2054
2036 } // namespace content 2055 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698