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

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

Issue 491163002: Implement flushing in VTVideoDecodeAccelerator. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Correct QueueAction(ACTION_DESTROY). Created 6 years, 2 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
« no previous file with comments | « content/common/gpu/media/vt_video_decode_accelerator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <CoreVideo/CoreVideo.h> 5 #include <CoreVideo/CoreVideo.h>
6 #include <OpenGL/CGLIOSurface.h> 6 #include <OpenGL/CGLIOSurface.h>
7 #include <OpenGL/gl.h> 7 #include <OpenGL/gl.h>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 22 matching lines...) Expand all
33 33
34 // Route decoded frame callbacks back into the VTVideoDecodeAccelerator. 34 // Route decoded frame callbacks back into the VTVideoDecodeAccelerator.
35 static void OutputThunk( 35 static void OutputThunk(
36 void* decompression_output_refcon, 36 void* decompression_output_refcon,
37 void* source_frame_refcon, 37 void* source_frame_refcon,
38 OSStatus status, 38 OSStatus status,
39 VTDecodeInfoFlags info_flags, 39 VTDecodeInfoFlags info_flags,
40 CVImageBufferRef image_buffer, 40 CVImageBufferRef image_buffer,
41 CMTime presentation_time_stamp, 41 CMTime presentation_time_stamp,
42 CMTime presentation_duration) { 42 CMTime presentation_duration) {
43 // TODO(sandersd): Implement flush-before-delete to guarantee validity.
44 VTVideoDecodeAccelerator* vda = 43 VTVideoDecodeAccelerator* vda =
45 reinterpret_cast<VTVideoDecodeAccelerator*>(decompression_output_refcon); 44 reinterpret_cast<VTVideoDecodeAccelerator*>(decompression_output_refcon);
46 int32_t bitstream_id = reinterpret_cast<intptr_t>(source_frame_refcon); 45 int32_t bitstream_id = reinterpret_cast<intptr_t>(source_frame_refcon);
47 vda->Output(bitstream_id, status, image_buffer); 46 vda->Output(bitstream_id, status, image_buffer);
48 } 47 }
49 48
50 VTVideoDecodeAccelerator::DecodedFrame::DecodedFrame( 49 VTVideoDecodeAccelerator::DecodedFrame::DecodedFrame(
51 int32_t bitstream_id, 50 int32_t bitstream_id,
52 CVImageBufferRef image_buffer) 51 CVImageBufferRef image_buffer)
53 : bitstream_id(bitstream_id), 52 : bitstream_id(bitstream_id),
54 image_buffer(image_buffer) { 53 image_buffer(image_buffer) {
55 } 54 }
56 55
57 VTVideoDecodeAccelerator::DecodedFrame::~DecodedFrame() { 56 VTVideoDecodeAccelerator::DecodedFrame::~DecodedFrame() {
58 } 57 }
59 58
59 VTVideoDecodeAccelerator::PendingAction::PendingAction(
60 Action action,
61 int32_t bitstream_id)
62 : action(action),
63 bitstream_id(bitstream_id) {
64 }
65
66 VTVideoDecodeAccelerator::PendingAction::~PendingAction() {
67 }
68
60 VTVideoDecodeAccelerator::VTVideoDecodeAccelerator(CGLContextObj cgl_context) 69 VTVideoDecodeAccelerator::VTVideoDecodeAccelerator(CGLContextObj cgl_context)
61 : cgl_context_(cgl_context), 70 : cgl_context_(cgl_context),
62 client_(NULL), 71 client_(NULL),
63 format_(NULL), 72 format_(NULL),
64 session_(NULL), 73 session_(NULL),
65 gpu_task_runner_(base::ThreadTaskRunnerHandle::Get()), 74 gpu_task_runner_(base::ThreadTaskRunnerHandle::Get()),
66 weak_this_factory_(this), 75 weak_this_factory_(this),
67 decoder_thread_("VTDecoderThread") { 76 decoder_thread_("VTDecoderThread") {
68 callback_.decompressionOutputCallback = OutputThunk; 77 callback_.decompressionOutputCallback = OutputThunk;
69 callback_.decompressionOutputRefCon = this; 78 callback_.decompressionOutputRefCon = this;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 base::ScopedCFTypeRef<CFNumberRef> cf_height(CFINT(coded_dimensions.height)); 162 base::ScopedCFTypeRef<CFNumberRef> cf_height(CFINT(coded_dimensions.height));
154 #undef CFINT 163 #undef CFINT
155 CFDictionarySetValue( 164 CFDictionarySetValue(
156 image_config, kCVPixelBufferPixelFormatTypeKey, cf_pixel_format); 165 image_config, kCVPixelBufferPixelFormatTypeKey, cf_pixel_format);
157 CFDictionarySetValue(image_config, kCVPixelBufferWidthKey, cf_width); 166 CFDictionarySetValue(image_config, kCVPixelBufferWidthKey, cf_width);
158 CFDictionarySetValue(image_config, kCVPixelBufferHeightKey, cf_height); 167 CFDictionarySetValue(image_config, kCVPixelBufferHeightKey, cf_height);
159 CFDictionarySetValue( 168 CFDictionarySetValue(
160 image_config, kCVPixelBufferOpenGLCompatibilityKey, kCFBooleanTrue); 169 image_config, kCVPixelBufferOpenGLCompatibilityKey, kCFBooleanTrue);
161 170
162 // TODO(sandersd): Check if the session is already compatible. 171 // TODO(sandersd): Check if the session is already compatible.
163 // TODO(sandersd): Flush.
164 session_.reset(); 172 session_.reset();
165 CHECK(!VTDecompressionSessionCreate( 173 CHECK(!VTDecompressionSessionCreate(
166 kCFAllocatorDefault, 174 kCFAllocatorDefault,
167 format_, // video_format_description 175 format_, // video_format_description
168 decoder_config, // video_decoder_specification 176 decoder_config, // video_decoder_specification
169 image_config, // destination_image_buffer_attributes 177 image_config, // destination_image_buffer_attributes
170 &callback_, // output_callback 178 &callback_, // output_callback
171 session_.InitializeInto())); 179 session_.InitializeInto()));
172 180
173 // If the size has changed, trigger a request for new picture buffers. 181 // If the size has changed, trigger a request for new picture buffers.
182 // TODO(sandersd): Move to SendPictures(), and use this just as a hint for an
183 // upcoming size change.
174 gfx::Size new_coded_size(coded_dimensions.width, coded_dimensions.height); 184 gfx::Size new_coded_size(coded_dimensions.width, coded_dimensions.height);
175 if (coded_size_ != new_coded_size) { 185 if (coded_size_ != new_coded_size) {
176 coded_size_ = new_coded_size; 186 coded_size_ = new_coded_size;
177 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( 187 gpu_task_runner_->PostTask(FROM_HERE, base::Bind(
178 &VTVideoDecodeAccelerator::SizeChangedTask, 188 &VTVideoDecodeAccelerator::SizeChangedTask,
179 weak_this_factory_.GetWeakPtr(), 189 weak_this_factory_.GetWeakPtr(),
180 coded_size_));; 190 coded_size_));;
181 } 191 }
182 } 192 }
183 193
184 void VTVideoDecodeAccelerator::Decode(const media::BitstreamBuffer& bitstream) { 194 void VTVideoDecodeAccelerator::Decode(const media::BitstreamBuffer& bitstream) {
185 DCHECK(CalledOnValidThread()); 195 DCHECK(CalledOnValidThread());
186 // TODO(sandersd): Test what happens if bitstream buffers are passed to VT out 196 CHECK_GE(bitstream.id(), 0) << "Negative bitstream_id";
187 // of order. 197 pending_bitstream_ids_.push(bitstream.id());
188 decoder_thread_.message_loop_proxy()->PostTask(FROM_HERE, base::Bind( 198 decoder_thread_.message_loop_proxy()->PostTask(FROM_HERE, base::Bind(
189 &VTVideoDecodeAccelerator::DecodeTask, base::Unretained(this), 199 &VTVideoDecodeAccelerator::DecodeTask, base::Unretained(this),
190 bitstream)); 200 bitstream));
191 } 201 }
192 202
193 // TODO(sandersd): Proper error reporting instead of CHECKs. 203 // TODO(sandersd): Proper error reporting instead of CHECKs.
194 void VTVideoDecodeAccelerator::DecodeTask( 204 void VTVideoDecodeAccelerator::DecodeTask(
195 const media::BitstreamBuffer bitstream) { 205 const media::BitstreamBuffer bitstream) {
196 DCHECK(decoder_thread_.message_loop_proxy()->BelongsToCurrentThread()); 206 DCHECK(decoder_thread_.message_loop_proxy()->BelongsToCurrentThread());
197 207
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 nalus.push_back(nalu); 239 nalus.push_back(nalu);
230 data_size += kNALUHeaderLength + nalu.size; 240 data_size += kNALUHeaderLength + nalu.size;
231 } 241 }
232 } 242 }
233 243
234 // 2. Initialize VideoToolbox. 244 // 2. Initialize VideoToolbox.
235 // TODO(sandersd): Reinitialize when there are new parameter sets. 245 // TODO(sandersd): Reinitialize when there are new parameter sets.
236 if (!session_) 246 if (!session_)
237 ConfigureDecoder(config_nalu_data_ptrs, config_nalu_data_sizes); 247 ConfigureDecoder(config_nalu_data_ptrs, config_nalu_data_sizes);
238 248
249 // If there are no non-configuration units, immediately return an empty
250 // (ie. dropped) frame. It is an error to create a MemoryBlock with zero
251 // size.
252 if (!data_size) {
253 gpu_task_runner_->PostTask(FROM_HERE, base::Bind(
254 &VTVideoDecodeAccelerator::OutputTask,
255 weak_this_factory_.GetWeakPtr(),
256 DecodedFrame(bitstream.id(), NULL)));
257 return;
258 }
259
239 // 3. Allocate a memory-backed CMBlockBuffer for the translated data. 260 // 3. Allocate a memory-backed CMBlockBuffer for the translated data.
240 base::ScopedCFTypeRef<CMBlockBufferRef> data; 261 base::ScopedCFTypeRef<CMBlockBufferRef> data;
241 CHECK(!CMBlockBufferCreateWithMemoryBlock( 262 CHECK(!CMBlockBufferCreateWithMemoryBlock(
242 kCFAllocatorDefault, 263 kCFAllocatorDefault,
243 NULL, // &memory_block 264 NULL, // &memory_block
244 data_size, // block_length 265 data_size, // block_length
245 kCFAllocatorDefault, // block_allocator 266 kCFAllocatorDefault, // block_allocator
246 NULL, // &custom_block_source 267 NULL, // &custom_block_source
247 0, // offset_to_data 268 0, // offset_to_data
248 data_size, // data_length 269 data_size, // data_length
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 CFRetain(image_buffer); 325 CFRetain(image_buffer);
305 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( 326 gpu_task_runner_->PostTask(FROM_HERE, base::Bind(
306 &VTVideoDecodeAccelerator::OutputTask, 327 &VTVideoDecodeAccelerator::OutputTask,
307 weak_this_factory_.GetWeakPtr(), 328 weak_this_factory_.GetWeakPtr(),
308 DecodedFrame(bitstream_id, image_buffer))); 329 DecodedFrame(bitstream_id, image_buffer)));
309 } 330 }
310 331
311 void VTVideoDecodeAccelerator::OutputTask(DecodedFrame frame) { 332 void VTVideoDecodeAccelerator::OutputTask(DecodedFrame frame) {
312 DCHECK(CalledOnValidThread()); 333 DCHECK(CalledOnValidThread());
313 decoded_frames_.push(frame); 334 decoded_frames_.push(frame);
314 SendPictures(); 335 ProcessDecodedFrames();
315 } 336 }
316 337
317 void VTVideoDecodeAccelerator::SizeChangedTask(gfx::Size coded_size) { 338 void VTVideoDecodeAccelerator::SizeChangedTask(gfx::Size coded_size) {
318 DCHECK(CalledOnValidThread()); 339 DCHECK(CalledOnValidThread());
319 texture_size_ = coded_size; 340 texture_size_ = coded_size;
320 // TODO(sandersd): Dismiss existing picture buffers. 341 // TODO(sandersd): Dismiss existing picture buffers.
321 client_->ProvidePictureBuffers( 342 client_->ProvidePictureBuffers(
322 kNumPictureBuffers, texture_size_, GL_TEXTURE_RECTANGLE_ARB); 343 kNumPictureBuffers, texture_size_, GL_TEXTURE_RECTANGLE_ARB);
323 } 344 }
324 345
325 void VTVideoDecodeAccelerator::AssignPictureBuffers( 346 void VTVideoDecodeAccelerator::AssignPictureBuffers(
326 const std::vector<media::PictureBuffer>& pictures) { 347 const std::vector<media::PictureBuffer>& pictures) {
327 DCHECK(CalledOnValidThread()); 348 DCHECK(CalledOnValidThread());
328 349
329 for (size_t i = 0; i < pictures.size(); i++) { 350 for (size_t i = 0; i < pictures.size(); i++) {
330 CHECK(!texture_ids_.count(pictures[i].id())); 351 CHECK(!texture_ids_.count(pictures[i].id()));
331 available_picture_ids_.push(pictures[i].id()); 352 available_picture_ids_.push(pictures[i].id());
332 texture_ids_[pictures[i].id()] = pictures[i].texture_id(); 353 texture_ids_[pictures[i].id()] = pictures[i].texture_id();
333 } 354 }
334 355
335 // Pictures are not marked as uncleared until this method returns. They will 356 // Pictures are not marked as uncleared until after this method returns, and
336 // become broken if they are used before that happens. 357 // they will be broken if they are used before that happens. So, schedule
358 // future work after that happens.
337 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( 359 gpu_task_runner_->PostTask(FROM_HERE, base::Bind(
338 &VTVideoDecodeAccelerator::SendPictures, 360 &VTVideoDecodeAccelerator::ProcessDecodedFrames,
339 weak_this_factory_.GetWeakPtr())); 361 weak_this_factory_.GetWeakPtr()));
340 } 362 }
341 363
342 void VTVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_id) { 364 void VTVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_id) {
343 DCHECK(CalledOnValidThread()); 365 DCHECK(CalledOnValidThread());
344 DCHECK_EQ(CFGetRetainCount(picture_bindings_[picture_id]), 1); 366 DCHECK_EQ(CFGetRetainCount(picture_bindings_[picture_id]), 1);
345 picture_bindings_.erase(picture_id); 367 picture_bindings_.erase(picture_id);
346 available_picture_ids_.push(picture_id); 368 available_picture_ids_.push(picture_id);
347 SendPictures(); 369 ProcessDecodedFrames();
348 } 370 }
349 371
350 // TODO(sandersd): Proper error reporting instead of CHECKs. 372 void VTVideoDecodeAccelerator::CompleteAction(Action action) {
351 void VTVideoDecodeAccelerator::SendPictures() {
352 DCHECK(CalledOnValidThread()); 373 DCHECK(CalledOnValidThread());
353 if (available_picture_ids_.empty() || decoded_frames_.empty()) 374 switch (action) {
354 return; 375 case ACTION_FLUSH:
376 client_->NotifyFlushDone();
377 break;
378 case ACTION_RESET:
379 client_->NotifyResetDone();
380 break;
381 case ACTION_DESTROY:
382 delete this;
383 break;
384 }
385 }
386
387 void VTVideoDecodeAccelerator::CompleteActions(int32_t bitstream_id) {
388 DCHECK(CalledOnValidThread());
389 while (!pending_actions_.empty() &&
390 pending_actions_.front().bitstream_id == bitstream_id) {
391 CompleteAction(pending_actions_.front().action);
392 pending_actions_.pop();
393 }
394 }
395
396 void VTVideoDecodeAccelerator::ProcessDecodedFrames() {
397 DCHECK(CalledOnValidThread());
398
399 while (!decoded_frames_.empty()) {
400 if (pending_actions_.empty()) {
401 // No pending actions; send frames normally.
402 SendPictures(pending_bitstream_ids_.back());
403 return;
404 }
405
406 int32_t next_action_bitstream_id = pending_actions_.front().bitstream_id;
407 int32_t last_sent_bitstream_id = -1;
408 switch (pending_actions_.front().action) {
409 case ACTION_FLUSH:
410 // Send frames normally.
411 last_sent_bitstream_id = SendPictures(next_action_bitstream_id);
412 break;
413
414 case ACTION_RESET:
415 // Drop decoded frames.
416 while (!decoded_frames_.empty() &&
417 last_sent_bitstream_id != next_action_bitstream_id) {
418 last_sent_bitstream_id = decoded_frames_.front().bitstream_id;
419 decoded_frames_.pop();
420 DCHECK_EQ(pending_bitstream_ids_.front(), last_sent_bitstream_id);
421 pending_bitstream_ids_.pop();
422 client_->NotifyEndOfBitstreamBuffer(last_sent_bitstream_id);
423 }
424 break;
425
426 case ACTION_DESTROY:
427 // Drop decoded frames, without bookkeeping.
428 while (!decoded_frames_.empty()) {
429 last_sent_bitstream_id = decoded_frames_.front().bitstream_id;
430 decoded_frames_.pop();
431 }
432 break;
433 }
434
435 // If we ran out of buffers (or pictures), no more progress can be made
436 // until more frames are decoded.
437 if (last_sent_bitstream_id != next_action_bitstream_id)
438 return;
439
440 // Handle ACTION_DESTORY specially; it is an error to access any members
Pawel Osciak 2014/09/26 15:30:49 s/DESTORY/DESTROY/
sandersd (OOO until July 31) 2014/09/26 17:28:52 Done.
441 // after CompleteAction() because it deletes |this|.
442 if (pending_actions_.front().action == ACTION_DESTROY) {
443 CompleteAction(ACTION_DESTROY);
Pawel Osciak 2014/09/26 15:30:49 This can't go under the switch?
sandersd (OOO until July 31) 2014/09/26 17:28:52 Done.
444 return;
445 }
446
447 // Complete all actions pending for this |bitstream_id|, then loop to see
448 // if progress can be made on the next action.
449 CompleteActions(next_action_bitstream_id);
450 }
451 }
452
453 int32_t VTVideoDecodeAccelerator::SendPictures(int32_t up_to_bitstream_id) {
454 DCHECK(CalledOnValidThread());
455 DCHECK(!decoded_frames_.empty());
456
457 if (available_picture_ids_.empty())
458 return -1;
355 459
356 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(cgl_context_); 460 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(cgl_context_);
357 glEnable(GL_TEXTURE_RECTANGLE_ARB); 461 glEnable(GL_TEXTURE_RECTANGLE_ARB);
358 462
359 while (!available_picture_ids_.empty() && !decoded_frames_.empty()) { 463 int32_t last_sent_bitstream_id = -1;
464 while (!available_picture_ids_.empty() &&
465 !decoded_frames_.empty() &&
466 last_sent_bitstream_id != up_to_bitstream_id) {
467 DecodedFrame frame = decoded_frames_.front();
468 decoded_frames_.pop();
469 DCHECK_EQ(pending_bitstream_ids_.front(), frame.bitstream_id);
470 pending_bitstream_ids_.pop();
360 int32_t picture_id = available_picture_ids_.front(); 471 int32_t picture_id = available_picture_ids_.front();
361 available_picture_ids_.pop(); 472 available_picture_ids_.pop();
362 DecodedFrame frame = decoded_frames_.front();
363 decoded_frames_.pop();
364 IOSurfaceRef surface = CVPixelBufferGetIOSurface(frame.image_buffer);
365 473
366 gfx::ScopedTextureBinder 474 CVImageBufferRef image_buffer = frame.image_buffer.get();
367 texture_binder(GL_TEXTURE_RECTANGLE_ARB, texture_ids_[picture_id]); 475 if (image_buffer) {
368 CHECK(!CGLTexImageIOSurface2D( 476 IOSurfaceRef surface = CVPixelBufferGetIOSurface(image_buffer);
369 cgl_context_, // ctx
370 GL_TEXTURE_RECTANGLE_ARB, // target
371 GL_RGB, // internal_format
372 texture_size_.width(), // width
373 texture_size_.height(), // height
374 GL_YCBCR_422_APPLE, // format
375 GL_UNSIGNED_SHORT_8_8_APPLE, // type
376 surface, // io_surface
377 0)); // plane
378 477
379 picture_bindings_[picture_id] = frame.image_buffer; 478 // TODO(sandersd): Find out why this sometimes fails due to no GL context.
380 client_->PictureReady(media::Picture( 479 gfx::ScopedTextureBinder
381 picture_id, frame.bitstream_id, gfx::Rect(texture_size_))); 480 texture_binder(GL_TEXTURE_RECTANGLE_ARB, texture_ids_[picture_id]);
481 CHECK(!CGLTexImageIOSurface2D(
482 cgl_context_, // ctx
483 GL_TEXTURE_RECTANGLE_ARB, // target
484 GL_RGB, // internal_format
485 texture_size_.width(), // width
486 texture_size_.height(), // height
487 GL_YCBCR_422_APPLE, // format
488 GL_UNSIGNED_SHORT_8_8_APPLE, // type
489 surface, // io_surface
490 0)); // plane
491
492 picture_bindings_[picture_id] = frame.image_buffer;
493 client_->PictureReady(media::Picture(
494 picture_id, frame.bitstream_id, gfx::Rect(texture_size_)));
495 }
496
382 client_->NotifyEndOfBitstreamBuffer(frame.bitstream_id); 497 client_->NotifyEndOfBitstreamBuffer(frame.bitstream_id);
498 last_sent_bitstream_id = frame.bitstream_id;
383 } 499 }
384 500
385 glDisable(GL_TEXTURE_RECTANGLE_ARB); 501 glDisable(GL_TEXTURE_RECTANGLE_ARB);
502 return last_sent_bitstream_id;
503 }
504
505 void VTVideoDecodeAccelerator::FlushTask() {
506 DCHECK(decoder_thread_.message_loop_proxy()->BelongsToCurrentThread());
507 CHECK(!VTDecompressionSessionFinishDelayedFrames(session_));
508 }
509
510 void VTVideoDecodeAccelerator::QueueAction(Action action) {
511 DCHECK(CalledOnValidThread());
512 if (pending_bitstream_ids_.empty()) {
513 // If there are no pending frames, all actions complete immediately.
514 CompleteAction(action);
515 } else {
516 // Otherwise, queue the action.
517 pending_actions_.push(PendingAction(action, pending_bitstream_ids_.back()));
518
519 // Request a flush to make sure the action will eventually complete.
520 decoder_thread_.message_loop_proxy()->PostTask(FROM_HERE, base::Bind(
521 &VTVideoDecodeAccelerator::FlushTask, base::Unretained(this)));
522
523 // See if we can make progress now that there is a new pending action.
524 ProcessDecodedFrames();
525 }
386 } 526 }
387 527
388 void VTVideoDecodeAccelerator::Flush() { 528 void VTVideoDecodeAccelerator::Flush() {
389 DCHECK(CalledOnValidThread()); 529 DCHECK(CalledOnValidThread());
390 // TODO(sandersd): Trigger flush, sending frames. 530 QueueAction(ACTION_FLUSH);
391 } 531 }
392 532
393 void VTVideoDecodeAccelerator::Reset() { 533 void VTVideoDecodeAccelerator::Reset() {
394 DCHECK(CalledOnValidThread()); 534 DCHECK(CalledOnValidThread());
395 // TODO(sandersd): Trigger flush, discarding frames. 535 QueueAction(ACTION_RESET);
396 } 536 }
397 537
398 void VTVideoDecodeAccelerator::Destroy() { 538 void VTVideoDecodeAccelerator::Destroy() {
399 DCHECK(CalledOnValidThread()); 539 DCHECK(CalledOnValidThread());
400 // TODO(sandersd): Trigger flush, discarding frames, and wait for them. 540 // Drop any other pending actions.
401 delete this; 541 while (!pending_actions_.empty())
542 pending_actions_.pop();
543 // Return all bitstream buffers.
544 while (!pending_bitstream_ids_.empty()) {
545 client_->NotifyEndOfBitstreamBuffer(pending_bitstream_ids_.front());
546 pending_bitstream_ids_.pop();
547 }
548 QueueAction(ACTION_DESTROY);
402 } 549 }
403 550
404 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() { 551 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() {
405 return false; 552 return false;
406 } 553 }
407 554
408 } // namespace content 555 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/vt_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698