OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <algorithm> | 5 #include <algorithm> |
6 | 6 |
7 #include <CoreVideo/CoreVideo.h> | 7 #include <CoreVideo/CoreVideo.h> |
8 #include <OpenGL/CGLIOSurface.h> | 8 #include <OpenGL/CGLIOSurface.h> |
9 #include <OpenGL/gl.h> | 9 #include <OpenGL/gl.h> |
10 | 10 |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 } | 352 } |
353 const uint8_t* buf = static_cast<uint8_t*>(memory.memory()); | 353 const uint8_t* buf = static_cast<uint8_t*>(memory.memory()); |
354 | 354 |
355 // NALUs are stored with Annex B format in the bitstream buffer (start codes), | 355 // NALUs are stored with Annex B format in the bitstream buffer (start codes), |
356 // but VideoToolbox expects AVC format (length headers), so we must rewrite | 356 // but VideoToolbox expects AVC format (length headers), so we must rewrite |
357 // the data. | 357 // the data. |
358 // | 358 // |
359 // Locate relevant NALUs and compute the size of the rewritten data. Also | 359 // Locate relevant NALUs and compute the size of the rewritten data. Also |
360 // record any parameter sets for VideoToolbox initialization. | 360 // record any parameter sets for VideoToolbox initialization. |
361 bool config_changed = false; | 361 bool config_changed = false; |
| 362 bool has_slice = false; |
362 size_t data_size = 0; | 363 size_t data_size = 0; |
363 std::vector<media::H264NALU> nalus; | 364 std::vector<media::H264NALU> nalus; |
364 parser_.SetStream(buf, size); | 365 parser_.SetStream(buf, size); |
365 media::H264NALU nalu; | 366 media::H264NALU nalu; |
366 while (true) { | 367 while (true) { |
367 media::H264Parser::Result result = parser_.AdvanceToNextNALU(&nalu); | 368 media::H264Parser::Result result = parser_.AdvanceToNextNALU(&nalu); |
368 if (result == media::H264Parser::kEOStream) | 369 if (result == media::H264Parser::kEOStream) |
369 break; | 370 break; |
370 if (result != media::H264Parser::kOk) { | 371 if (result != media::H264Parser::kOk) { |
371 DLOG(ERROR) << "Failed to find H.264 NALU"; | 372 DLOG(ERROR) << "Failed to find H.264 NALU"; |
(...skipping 24 matching lines...) Expand all Loading... |
396 if (parser_.ParsePPS(&last_pps_id_) != media::H264Parser::kOk) { | 397 if (parser_.ParsePPS(&last_pps_id_) != media::H264Parser::kOk) { |
397 DLOG(ERROR) << "Could not parse PPS"; | 398 DLOG(ERROR) << "Could not parse PPS"; |
398 NotifyError(UNREADABLE_INPUT); | 399 NotifyError(UNREADABLE_INPUT); |
399 return; | 400 return; |
400 } | 401 } |
401 break; | 402 break; |
402 | 403 |
403 case media::H264NALU::kSliceDataA: | 404 case media::H264NALU::kSliceDataA: |
404 case media::H264NALU::kSliceDataB: | 405 case media::H264NALU::kSliceDataB: |
405 case media::H264NALU::kSliceDataC: | 406 case media::H264NALU::kSliceDataC: |
406 DLOG(ERROR) << "Coded slide data partitions not implemented."; | |
407 NotifyError(PLATFORM_FAILURE); | |
408 return; | |
409 | |
410 case media::H264NALU::kNonIDRSlice: | 407 case media::H264NALU::kNonIDRSlice: |
411 // TODO(sandersd): Check that there has been an IDR slice since the | 408 // TODO(sandersd): Check that there has been an IDR slice since the |
412 // last reset. | 409 // last reset. |
413 case media::H264NALU::kIDRSlice: | 410 case media::H264NALU::kIDRSlice: |
414 { | 411 // Compute the |pic_order_cnt| for the picture from the first slice. |
415 // TODO(sandersd): Make sure this only happens once per frame. | 412 // TODO(sandersd): Make sure that any further slices are part of the |
416 DCHECK_EQ(frame->pic_order_cnt, 0); | 413 // same picture or a redundant coded picture. |
417 | 414 if (!has_slice) { |
418 media::H264SliceHeader slice_hdr; | 415 media::H264SliceHeader slice_hdr; |
419 result = parser_.ParseSliceHeader(nalu, &slice_hdr); | 416 result = parser_.ParseSliceHeader(nalu, &slice_hdr); |
420 if (result != media::H264Parser::kOk) { | 417 if (result != media::H264Parser::kOk) { |
421 DLOG(ERROR) << "Could not parse slice header"; | 418 DLOG(ERROR) << "Could not parse slice header"; |
422 NotifyError(UNREADABLE_INPUT); | 419 NotifyError(UNREADABLE_INPUT); |
423 return; | 420 return; |
424 } | 421 } |
425 | 422 |
426 // TODO(sandersd): Maintain a cache of configurations and reconfigure | 423 // TODO(sandersd): Maintain a cache of configurations and reconfigure |
427 // only when a slice references a new config. | 424 // only when a slice references a new config. |
(...skipping 18 matching lines...) Expand all Loading... |
446 NotifyError(UNREADABLE_INPUT); | 443 NotifyError(UNREADABLE_INPUT); |
447 return; | 444 return; |
448 } | 445 } |
449 | 446 |
450 if (sps->vui_parameters_present_flag && | 447 if (sps->vui_parameters_present_flag && |
451 sps->bitstream_restriction_flag) { | 448 sps->bitstream_restriction_flag) { |
452 frame->reorder_window = std::min(sps->max_num_reorder_frames, | 449 frame->reorder_window = std::min(sps->max_num_reorder_frames, |
453 kMaxReorderQueueSize - 1); | 450 kMaxReorderQueueSize - 1); |
454 } | 451 } |
455 } | 452 } |
| 453 has_slice = true; |
456 default: | 454 default: |
457 nalus.push_back(nalu); | 455 nalus.push_back(nalu); |
458 data_size += kNALUHeaderLength + nalu.size; | 456 data_size += kNALUHeaderLength + nalu.size; |
459 break; | 457 break; |
460 } | 458 } |
461 } | 459 } |
462 | 460 |
463 // Initialize VideoToolbox. | 461 // Initialize VideoToolbox. |
464 // TODO(sandersd): Instead of assuming that the last SPS and PPS units are | 462 // TODO(sandersd): Instead of assuming that the last SPS and PPS units are |
465 // always the correct ones, maintain a cache of recent SPS and PPS units and | 463 // always the correct ones, maintain a cache of recent SPS and PPS units and |
466 // select from them using the slice header. | 464 // select from them using the slice header. |
467 if (config_changed) { | 465 if (config_changed) { |
468 if (last_sps_.size() == 0 || last_pps_.size() == 0) { | 466 if (last_sps_.size() == 0 || last_pps_.size() == 0) { |
469 DLOG(ERROR) << "Invalid configuration data"; | 467 DLOG(ERROR) << "Invalid configuration data"; |
470 NotifyError(INVALID_ARGUMENT); | 468 NotifyError(INVALID_ARGUMENT); |
471 return; | 469 return; |
472 } | 470 } |
473 if (!ConfigureDecoder()) | 471 if (!ConfigureDecoder()) |
474 return; | 472 return; |
475 } | 473 } |
476 | 474 |
477 // If there are no non-configuration units, drop the bitstream buffer by | 475 // If there are no image slices, drop the bitstream buffer by returning an |
478 // returning an empty frame. | 476 // empty frame. |
479 if (!data_size) { | 477 if (!has_slice) { |
480 if (!FinishDelayedFrames()) | 478 if (!FinishDelayedFrames()) |
481 return; | 479 return; |
482 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( | 480 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( |
483 &VTVideoDecodeAccelerator::DecodeDone, weak_this_, frame)); | 481 &VTVideoDecodeAccelerator::DecodeDone, weak_this_, frame)); |
484 return; | 482 return; |
485 } | 483 } |
486 | 484 |
487 // If the session is not configured by this point, fail. | 485 // If the session is not configured by this point, fail. |
488 if (!session_) { | 486 if (!session_) { |
489 DLOG(ERROR) << "Image slice without configuration"; | 487 DLOG(ERROR) << "Image slice without configuration"; |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 assigned_bitstream_ids_.clear(); | 885 assigned_bitstream_ids_.clear(); |
888 state_ = STATE_DESTROYING; | 886 state_ = STATE_DESTROYING; |
889 QueueFlush(TASK_DESTROY); | 887 QueueFlush(TASK_DESTROY); |
890 } | 888 } |
891 | 889 |
892 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() { | 890 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() { |
893 return false; | 891 return false; |
894 } | 892 } |
895 | 893 |
896 } // namespace content | 894 } // namespace content |
OLD | NEW |