| Index: content/common/gpu/media/vt_video_decode_accelerator.cc
|
| diff --git a/content/common/gpu/media/vt_video_decode_accelerator.cc b/content/common/gpu/media/vt_video_decode_accelerator.cc
|
| index dedb15d5e215baae0ef923a901b1bfe0069b294d..62658fb70dfd64018f7a1c6a256adde726639372 100644
|
| --- a/content/common/gpu/media/vt_video_decode_accelerator.cc
|
| +++ b/content/common/gpu/media/vt_video_decode_accelerator.cc
|
| @@ -2,6 +2,8 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| +#include <algorithm>
|
| +
|
| #include <CoreVideo/CoreVideo.h>
|
| #include <OpenGL/CGLIOSurface.h>
|
| #include <OpenGL/gl.h>
|
| @@ -13,7 +15,6 @@
|
| #include "content/common/gpu/media/vt_video_decode_accelerator.h"
|
| #include "content/public/common/content_switches.h"
|
| #include "media/base/limits.h"
|
| -#include "media/filters/h264_parser.h"
|
| #include "ui/gl/scoped_binders.h"
|
|
|
| using content_common_gpu_media::kModuleVt;
|
| @@ -38,8 +39,9 @@ static const int kNALUHeaderLength = 4;
|
| // requirements are low, as we don't need the textures to be backed by storage.
|
| static const int kNumPictureBuffers = media::limits::kMaxVideoFrames + 1;
|
|
|
| -// TODO(sandersd): Use the configured reorder window instead.
|
| -static const int kMinReorderQueueSize = 4;
|
| +// Maximum number of frames to queue for reordering before we stop asking for
|
| +// more. (NotifyEndOfBitstreamBuffer() is called when frames are moved into the
|
| +// reorder queue.)
|
| static const int kMaxReorderQueueSize = 16;
|
|
|
| // Route decoded frame callbacks back into the VTVideoDecodeAccelerator.
|
| @@ -63,7 +65,7 @@ VTVideoDecodeAccelerator::Task::~Task() {
|
| }
|
|
|
| VTVideoDecodeAccelerator::Frame::Frame(int32_t bitstream_id)
|
| - : bitstream_id(bitstream_id), pic_order_cnt(0) {
|
| + : bitstream_id(bitstream_id), pic_order_cnt(0), reorder_window(0) {
|
| }
|
|
|
| VTVideoDecodeAccelerator::Frame::~Frame() {
|
| @@ -74,12 +76,13 @@ bool VTVideoDecodeAccelerator::FrameOrder::operator()(
|
| const linked_ptr<Frame>& rhs) const {
|
| if (lhs->pic_order_cnt != rhs->pic_order_cnt)
|
| return lhs->pic_order_cnt > rhs->pic_order_cnt;
|
| - // If the pic_order is the same, fallback on using the bitstream order.
|
| - // TODO(sandersd): Assign a sequence number in Decode().
|
| + // If |pic_order_cnt| is the same, fall back on using the bitstream order.
|
| + // TODO(sandersd): Assign a sequence number in Decode() and use that instead.
|
| + // TODO(sandersd): Using the sequence number, ensure that frames older than
|
| + // |kMaxReorderQueueSize| are ordered first, regardless of |pic_order_cnt|.
|
| return lhs->bitstream_id > rhs->bitstream_id;
|
| }
|
|
|
| -
|
| VTVideoDecodeAccelerator::VTVideoDecodeAccelerator(
|
| CGLContextObj cgl_context,
|
| const base::Callback<bool(void)>& make_context_current)
|
| @@ -318,8 +321,8 @@ void VTVideoDecodeAccelerator::DecodeTask(
|
| return;
|
|
|
| case media::H264NALU::kNonIDRSlice:
|
| - // TODO(sandersd): Check that there has been an SPS or IDR slice since
|
| - // the last reset.
|
| + // TODO(sandersd): Check that there has been an IDR slice since the
|
| + // last reset.
|
| case media::H264NALU::kIDRSlice:
|
| {
|
| // TODO(sandersd): Make sure this only happens once per frame.
|
| @@ -333,8 +336,8 @@ void VTVideoDecodeAccelerator::DecodeTask(
|
| return;
|
| }
|
|
|
| - // TODO(sandersd): Keep a cache of recent SPS/PPS units instead of
|
| - // only the most recent ones.
|
| + // TODO(sandersd): Maintain a cache of configurations and reconfigure
|
| + // only when a slice references a new config.
|
| DCHECK_EQ(slice_hdr.pic_parameter_set_id, last_pps_id_);
|
| const media::H264PPS* pps =
|
| parser_.GetPPS(slice_hdr.pic_parameter_set_id);
|
| @@ -352,9 +355,16 @@ void VTVideoDecodeAccelerator::DecodeTask(
|
| return;
|
| }
|
|
|
| - // TODO(sandersd): Compute pic_order_cnt.
|
| - DCHECK(!slice_hdr.field_pic_flag);
|
| - frame->pic_order_cnt = 0;
|
| + if (!poc_.ComputePicOrderCnt(sps, slice_hdr, &frame->pic_order_cnt)) {
|
| + NotifyError(UNREADABLE_INPUT);
|
| + return;
|
| + }
|
| +
|
| + if (sps->vui_parameters_present_flag &&
|
| + sps->bitstream_restriction_flag) {
|
| + frame->reorder_window = std::min(sps->max_num_reorder_frames,
|
| + kMaxReorderQueueSize - 1);
|
| + }
|
| }
|
| default:
|
| nalus.push_back(nalu);
|
| @@ -618,6 +628,12 @@ bool VTVideoDecodeAccelerator::ProcessTaskQueue() {
|
| case TASK_RESET:
|
| DCHECK_EQ(task.type, pending_flush_tasks_.front());
|
| if (reorder_queue_.size() == 0) {
|
| + last_sps_id_ = -1;
|
| + last_pps_id_ = -1;
|
| + last_sps_.clear();
|
| + last_spsext_.clear();
|
| + last_pps_.clear();
|
| + poc_.Reset();
|
| pending_flush_tasks_.pop();
|
| client_->NotifyResetDone();
|
| task_queue_.pop();
|
| @@ -645,7 +661,9 @@ bool VTVideoDecodeAccelerator::ProcessReorderQueue() {
|
| bool flushing = !task_queue_.empty() &&
|
| (task_queue_.front().type != TASK_FRAME ||
|
| task_queue_.front().frame->pic_order_cnt == 0);
|
| - if (flushing || reorder_queue_.size() >= kMinReorderQueueSize) {
|
| +
|
| + size_t reorder_window = std::max(0, reorder_queue_.top()->reorder_window);
|
| + if (flushing || reorder_queue_.size() > reorder_window) {
|
| if (ProcessFrame(*reorder_queue_.top())) {
|
| reorder_queue_.pop();
|
| return true;
|
|
|