Commit 9dd0a7c1 authored by Miguel Casas's avatar Miguel Casas Committed by Commit Bot

vaapi deco cleanup: extract H264, VP8 and VP9 accelerators

vaapi_video_decode_accelerator.* have three inner classes for H264, VP8
and VP9 decoding. To reduce the size of the file(s), this CL extracts
those into their own files. No new code is introduced in those new files,
but VideoDecodeAccelerator needs to make 3 methods public in order for
those not-anymore-internal classes to work (idea for next CL would be to
make those into an interface that VaapiVDA implements).

Test: Compile and run in simplechrome on soraka. Ran h264, vp8, vp9
videos of crosvideo.appspot.com, verified GpuVideoDecoder engaged.

Bug: 717265
Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: I054b39a330f3876031fd30d6e3e36878322d9036
Reviewed-on: https://chromium-review.googlesource.com/922811Reviewed-by: default avatarDaniele Castagna <dcastagna@chromium.org>
Commit-Queue: Miguel Casas <mcasas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537800}
parent cd434aed
......@@ -71,6 +71,12 @@ source_set("vaapi") {
"vaapi_video_decode_accelerator.h",
"vaapi_video_encode_accelerator.cc",
"vaapi_video_encode_accelerator.h",
"vaapi_h264_accelerator.cc",
"vaapi_h264_accelerator.h",
"vaapi_vp8_accelerator.cc",
"vaapi_vp8_accelerator.h",
"vaapi_vp9_accelerator.cc",
"vaapi_vp9_accelerator.h",
"vaapi_wrapper.cc",
"vaapi_wrapper.h",
] + get_target_outputs(":libva_generate_stubs")
......
This diff is collapsed.
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_VAAPI_VAAPI_H264_ACCELERATOR_H_
#define MEDIA_GPU_VAAPI_VAAPI_H264_ACCELERATOR_H_
#include <va/va.h>
#include "base/sequence_checker.h"
#include "media/filters/vp9_parser.h"
#include "media/gpu/h264_decoder.h"
#include "media/gpu/media_gpu_export.h"
namespace media {
class H264Picture;
class VaapiDecodeSurface;
class VaapiVideoDecodeAccelerator;
class VaapiWrapper;
class MEDIA_GPU_EXPORT VaapiH264Accelerator
: public H264Decoder::H264Accelerator {
public:
VaapiH264Accelerator(VaapiVideoDecodeAccelerator* vaapi_dec,
VaapiWrapper* vaapi_wrapper);
~VaapiH264Accelerator() override;
// H264Decoder::H264Accelerator implementation.
scoped_refptr<H264Picture> CreateH264Picture() override;
bool SubmitFrameMetadata(const H264SPS* sps,
const H264PPS* pps,
const H264DPB& dpb,
const H264Picture::Vector& ref_pic_listp0,
const H264Picture::Vector& ref_pic_listb0,
const H264Picture::Vector& ref_pic_listb1,
const scoped_refptr<H264Picture>& pic) override;
bool SubmitSlice(const H264PPS* pps,
const H264SliceHeader* slice_hdr,
const H264Picture::Vector& ref_pic_list0,
const H264Picture::Vector& ref_pic_list1,
const scoped_refptr<H264Picture>& pic,
const uint8_t* data,
size_t size) override;
bool SubmitDecode(const scoped_refptr<H264Picture>& pic) override;
bool OutputPicture(const scoped_refptr<H264Picture>& pic) override;
void Reset() override;
private:
scoped_refptr<VaapiDecodeSurface> H264PictureToVaapiDecodeSurface(
const scoped_refptr<H264Picture>& pic);
void FillVAPicture(VAPictureH264* va_pic, scoped_refptr<H264Picture> pic);
int FillVARefFramesFromDPB(const H264DPB& dpb,
VAPictureH264* va_pics,
int num_pics);
VaapiWrapper* vaapi_wrapper_;
VaapiVideoDecodeAccelerator* vaapi_dec_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(VaapiH264Accelerator);
};
} // namespace media
#endif // MEDIA_GPU_VAAPI_VAAPI_H264_ACCELERATOR_H_
......@@ -30,7 +30,6 @@
#include "media/gpu/gpu_video_decode_accelerator_helpers.h"
#include "media/gpu/media_gpu_export.h"
#include "media/gpu/shared_memory_region.h"
#include "media/gpu/vaapi/vaapi_decode_surface.h"
#include "media/gpu/vaapi/vaapi_picture_factory.h"
#include "media/gpu/vaapi/vaapi_wrapper.h"
#include "media/video/picture.h"
......@@ -43,7 +42,11 @@ class GLImage;
namespace media {
class AcceleratedVideoDecoder;
class VaapiDecodeSurface;
class VaapiPicture;
class VaapiH264Accelerator;
class VaapiVP8Accelerator;
class VaapiVP9Accelerator;
// Class to provide video decode acceleration for Intel systems with hardware
// support for it, and on which libva is available.
......@@ -83,11 +86,27 @@ class MEDIA_GPU_EXPORT VaapiVideoDecodeAccelerator
static VideoDecodeAccelerator::SupportedProfiles GetSupportedProfiles();
//
// Below methods are used by accelerator implementations.
//
// Decode of |dec_surface| is ready to be submitted and all codec-specific
// settings are set in hardware.
bool DecodeSurface(const scoped_refptr<VaapiDecodeSurface>& dec_surface);
// |dec_surface| is ready to be outputted once decode is finished.
// This can be called before decode is actually done in hardware, and this
// method is responsible for maintaining the ordering, i.e. the surfaces have
// to be outputted in the same order as SurfaceReady is called.
// On Intel, we don't have to explicitly maintain the ordering however, as the
// driver will maintain ordering, as well as dependencies, and will process
// each submitted command in order, and run each command only if its
// dependencies are ready.
void SurfaceReady(const scoped_refptr<VaapiDecodeSurface>& dec_surface);
// Return a new VaapiDecodeSurface for decoding into, or nullptr if not
// available.
scoped_refptr<VaapiDecodeSurface> CreateSurface();
private:
friend class VaapiVideoDecodeAcceleratorTest;
class VaapiH264Accelerator;
class VaapiVP8Accelerator;
class VaapiVP9Accelerator;
// An input buffer with id provided by the client and awaiting consumption.
class InputBuffer;
......@@ -172,27 +191,6 @@ class MEDIA_GPU_EXPORT VaapiVideoDecodeAccelerator
// Check if the surfaces have been released or post ourselves for later.
void TryFinishSurfaceSetChange();
//
// Below methods are used by accelerator implementations.
//
// Decode of |dec_surface| is ready to be submitted and all codec-specific
// settings are set in hardware.
bool DecodeSurface(const scoped_refptr<VaapiDecodeSurface>& dec_surface);
// |dec_surface| is ready to be outputted once decode is finished.
// This can be called before decode is actually done in hardware, and this
// method is responsible for maintaining the ordering, i.e. the surfaces have
// to be outputted in the same order as SurfaceReady is called.
// On Intel, we don't have to explicitly maintain the ordering however, as the
// driver will maintain ordering, as well as dependencies, and will process
// each submitted command in order, and run each command only if its
// dependencies are ready.
void SurfaceReady(const scoped_refptr<VaapiDecodeSurface>& dec_surface);
// Return a new VaapiDecodeSurface for decoding into, or nullptr if not
// available.
scoped_refptr<VaapiDecodeSurface> CreateSurface();
// VAVDA state.
enum State {
// Initialize() not called yet or failed.
......
This diff is collapsed.
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_VAAPI_VAAPI_VP8_ACCELERATOR_H_
#define MEDIA_GPU_VAAPI_VAAPI_VP8_ACCELERATOR_H_
#include "base/sequence_checker.h"
#include "media/filters/vp8_parser.h"
#include "media/gpu/media_gpu_export.h"
#include "media/gpu/vp8_decoder.h"
namespace media {
class VP8Picture;
class VaapiDecodeSurface;
class VaapiVideoDecodeAccelerator;
class VaapiWrapper;
class MEDIA_GPU_EXPORT VaapiVP8Accelerator : public VP8Decoder::VP8Accelerator {
public:
VaapiVP8Accelerator(VaapiVideoDecodeAccelerator* vaapi_dec,
VaapiWrapper* vaapi_wrapper);
~VaapiVP8Accelerator() override;
// VP8Decoder::VP8Accelerator implementation.
scoped_refptr<VP8Picture> CreateVP8Picture() override;
bool SubmitDecode(const scoped_refptr<VP8Picture>& pic,
const Vp8FrameHeader* frame_hdr,
const scoped_refptr<VP8Picture>& last_frame,
const scoped_refptr<VP8Picture>& golden_frame,
const scoped_refptr<VP8Picture>& alt_frame) override;
bool OutputPicture(const scoped_refptr<VP8Picture>& pic) override;
private:
scoped_refptr<VaapiDecodeSurface> VP8PictureToVaapiDecodeSurface(
const scoped_refptr<VP8Picture>& pic);
VaapiWrapper* vaapi_wrapper_;
VaapiVideoDecodeAccelerator* vaapi_dec_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(VaapiVP8Accelerator);
};
} // namespace media
#endif // MEDIA_GPU_VAAPI_VAAPI_VP8_ACCELERATOR_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/gpu/vaapi/vaapi_vp9_accelerator.h"
#include "media/gpu/vaapi/vaapi_decode_surface.h"
#include "media/gpu/vaapi/vaapi_video_decode_accelerator.h"
#include "media/gpu/vaapi/vaapi_wrapper.h"
#include "media/gpu/vp9_picture.h"
#define ARRAY_MEMCPY_CHECKED(to, from) \
do { \
static_assert(sizeof(to) == sizeof(from), \
#from " and " #to " arrays must be of same size"); \
memcpy(to, from, sizeof(to)); \
} while (0)
namespace media {
class VaapiVP9Picture : public VP9Picture {
public:
explicit VaapiVP9Picture(scoped_refptr<VaapiDecodeSurface> surface)
: dec_surface_(surface) {}
VaapiVP9Picture* AsVaapiVP9Picture() override { return this; }
scoped_refptr<VaapiDecodeSurface> dec_surface() { return dec_surface_; }
private:
~VaapiVP9Picture() override {}
scoped_refptr<VaapiDecodeSurface> dec_surface_;
DISALLOW_COPY_AND_ASSIGN(VaapiVP9Picture);
};
VaapiVP9Accelerator::VaapiVP9Accelerator(VaapiVideoDecodeAccelerator* vaapi_dec,
VaapiWrapper* vaapi_wrapper)
: vaapi_wrapper_(vaapi_wrapper), vaapi_dec_(vaapi_dec) {
DCHECK(vaapi_wrapper_);
DCHECK(vaapi_dec_);
DETACH_FROM_SEQUENCE(sequence_checker_);
}
VaapiVP9Accelerator::~VaapiVP9Accelerator() {
// TODO(mcasas): consider enabling the checker, https://crbug.com/789160
// CHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
scoped_refptr<VP9Picture> VaapiVP9Accelerator::CreateVP9Picture() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
scoped_refptr<VaapiDecodeSurface> va_surface = vaapi_dec_->CreateSurface();
if (!va_surface)
return nullptr;
return new VaapiVP9Picture(std::move(va_surface));
}
bool VaapiVP9Accelerator::SubmitDecode(
const scoped_refptr<VP9Picture>& pic,
const Vp9SegmentationParams& seg,
const Vp9LoopFilterParams& lf,
const std::vector<scoped_refptr<VP9Picture>>& ref_pictures,
const base::Closure& done_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// |done_cb| should be null as we return false from IsFrameContextRequired().
DCHECK(done_cb.is_null());
VADecPictureParameterBufferVP9 pic_param;
memset(&pic_param, 0, sizeof(pic_param));
const Vp9FrameHeader* frame_hdr = pic->frame_hdr.get();
DCHECK(frame_hdr);
pic_param.frame_width = base::checked_cast<uint16_t>(frame_hdr->frame_width);
pic_param.frame_height =
base::checked_cast<uint16_t>(frame_hdr->frame_height);
CHECK_EQ(ref_pictures.size(), arraysize(pic_param.reference_frames));
for (size_t i = 0; i < arraysize(pic_param.reference_frames); ++i) {
VASurfaceID va_surface_id;
if (ref_pictures[i]) {
scoped_refptr<VaapiDecodeSurface> surface =
VP9PictureToVaapiDecodeSurface(ref_pictures[i]);
va_surface_id = surface->va_surface()->id();
} else {
va_surface_id = VA_INVALID_SURFACE;
}
pic_param.reference_frames[i] = va_surface_id;
}
#define FHDR_TO_PP_PF1(a) pic_param.pic_fields.bits.a = frame_hdr->a
#define FHDR_TO_PP_PF2(a, b) pic_param.pic_fields.bits.a = b
FHDR_TO_PP_PF2(subsampling_x, frame_hdr->subsampling_x == 1);
FHDR_TO_PP_PF2(subsampling_y, frame_hdr->subsampling_y == 1);
FHDR_TO_PP_PF2(frame_type, frame_hdr->IsKeyframe() ? 0 : 1);
FHDR_TO_PP_PF1(show_frame);
FHDR_TO_PP_PF1(error_resilient_mode);
FHDR_TO_PP_PF1(intra_only);
FHDR_TO_PP_PF1(allow_high_precision_mv);
FHDR_TO_PP_PF2(mcomp_filter_type, frame_hdr->interpolation_filter);
FHDR_TO_PP_PF1(frame_parallel_decoding_mode);
FHDR_TO_PP_PF1(reset_frame_context);
FHDR_TO_PP_PF1(refresh_frame_context);
FHDR_TO_PP_PF2(frame_context_idx, frame_hdr->frame_context_idx_to_save_probs);
FHDR_TO_PP_PF2(segmentation_enabled, seg.enabled);
FHDR_TO_PP_PF2(segmentation_temporal_update, seg.temporal_update);
FHDR_TO_PP_PF2(segmentation_update_map, seg.update_map);
FHDR_TO_PP_PF2(last_ref_frame, frame_hdr->ref_frame_idx[0]);
FHDR_TO_PP_PF2(last_ref_frame_sign_bias,
frame_hdr->ref_frame_sign_bias[Vp9RefType::VP9_FRAME_LAST]);
FHDR_TO_PP_PF2(golden_ref_frame, frame_hdr->ref_frame_idx[1]);
FHDR_TO_PP_PF2(golden_ref_frame_sign_bias,
frame_hdr->ref_frame_sign_bias[Vp9RefType::VP9_FRAME_GOLDEN]);
FHDR_TO_PP_PF2(alt_ref_frame, frame_hdr->ref_frame_idx[2]);
FHDR_TO_PP_PF2(alt_ref_frame_sign_bias,
frame_hdr->ref_frame_sign_bias[Vp9RefType::VP9_FRAME_ALTREF]);
FHDR_TO_PP_PF2(lossless_flag, frame_hdr->quant_params.IsLossless());
#undef FHDR_TO_PP_PF2
#undef FHDR_TO_PP_PF1
pic_param.filter_level = lf.level;
pic_param.sharpness_level = lf.sharpness;
pic_param.log2_tile_rows = frame_hdr->tile_rows_log2;
pic_param.log2_tile_columns = frame_hdr->tile_cols_log2;
pic_param.frame_header_length_in_bytes = frame_hdr->uncompressed_header_size;
pic_param.first_partition_size = frame_hdr->header_size_in_bytes;
ARRAY_MEMCPY_CHECKED(pic_param.mb_segment_tree_probs, seg.tree_probs);
ARRAY_MEMCPY_CHECKED(pic_param.segment_pred_probs, seg.pred_probs);
pic_param.profile = frame_hdr->profile;
pic_param.bit_depth = frame_hdr->bit_depth;
DCHECK((pic_param.profile == 0 && pic_param.bit_depth == 8) ||
(pic_param.profile == 2 && pic_param.bit_depth == 10));
if (!vaapi_wrapper_->SubmitBuffer(VAPictureParameterBufferType,
sizeof(pic_param), &pic_param))
return false;
VASliceParameterBufferVP9 slice_param;
memset(&slice_param, 0, sizeof(slice_param));
slice_param.slice_data_size = frame_hdr->frame_size;
slice_param.slice_data_offset = 0;
slice_param.slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
static_assert(arraysize(Vp9SegmentationParams::feature_enabled) ==
arraysize(slice_param.seg_param),
"seg_param array of incorrect size");
for (size_t i = 0; i < arraysize(slice_param.seg_param); ++i) {
VASegmentParameterVP9& seg_param = slice_param.seg_param[i];
#define SEG_TO_SP_SF(a, b) seg_param.segment_flags.fields.a = b
SEG_TO_SP_SF(
segment_reference_enabled,
seg.FeatureEnabled(i, Vp9SegmentationParams::SEG_LVL_REF_FRAME));
SEG_TO_SP_SF(segment_reference,
seg.FeatureData(i, Vp9SegmentationParams::SEG_LVL_REF_FRAME));
SEG_TO_SP_SF(segment_reference_skipped,
seg.FeatureEnabled(i, Vp9SegmentationParams::SEG_LVL_SKIP));
#undef SEG_TO_SP_SF
ARRAY_MEMCPY_CHECKED(seg_param.filter_level, lf.lvl[i]);
seg_param.luma_dc_quant_scale = seg.y_dequant[i][0];
seg_param.luma_ac_quant_scale = seg.y_dequant[i][1];
seg_param.chroma_dc_quant_scale = seg.uv_dequant[i][0];
seg_param.chroma_ac_quant_scale = seg.uv_dequant[i][1];
}
if (!vaapi_wrapper_->SubmitBuffer(VASliceParameterBufferType,
sizeof(slice_param), &slice_param))
return false;
void* non_const_ptr = const_cast<uint8_t*>(frame_hdr->data);
if (!vaapi_wrapper_->SubmitBuffer(VASliceDataBufferType,
frame_hdr->frame_size, non_const_ptr))
return false;
scoped_refptr<VaapiDecodeSurface> dec_surface =
VP9PictureToVaapiDecodeSurface(pic);
return vaapi_dec_->DecodeSurface(dec_surface);
}
bool VaapiVP9Accelerator::OutputPicture(const scoped_refptr<VP9Picture>& pic) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
scoped_refptr<VaapiDecodeSurface> dec_surface =
VP9PictureToVaapiDecodeSurface(pic);
dec_surface->set_visible_rect(pic->visible_rect);
vaapi_dec_->SurfaceReady(dec_surface);
return true;
}
bool VaapiVP9Accelerator::IsFrameContextRequired() const {
return false;
}
bool VaapiVP9Accelerator::GetFrameContext(const scoped_refptr<VP9Picture>& pic,
Vp9FrameContext* frame_ctx) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
NOTIMPLEMENTED() << "Frame context update not supported";
return false;
}
scoped_refptr<VaapiDecodeSurface>
VaapiVP9Accelerator::VP9PictureToVaapiDecodeSurface(
const scoped_refptr<VP9Picture>& pic) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
VaapiVP9Picture* vaapi_pic = pic->AsVaapiVP9Picture();
CHECK(vaapi_pic);
return vaapi_pic->dec_surface();
}
} // namespace media
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_VAAPI_VAAPI_VP9_ACCELERATOR_H_
#define MEDIA_GPU_VAAPI_VAAPI_VP9_ACCELERATOR_H_
#include "base/sequence_checker.h"
#include "media/filters/vp9_parser.h"
#include "media/gpu/media_gpu_export.h"
#include "media/gpu/vp9_decoder.h"
namespace media {
class VP9Picture;
class VaapiDecodeSurface;
class VaapiVideoDecodeAccelerator;
class VaapiWrapper;
class MEDIA_GPU_EXPORT VaapiVP9Accelerator : public VP9Decoder::VP9Accelerator {
public:
VaapiVP9Accelerator(VaapiVideoDecodeAccelerator* vaapi_dec,
VaapiWrapper* vaapi_wrapper);
~VaapiVP9Accelerator() override;
// VP9Decoder::VP9Accelerator implementation.
scoped_refptr<VP9Picture> CreateVP9Picture() override;
bool SubmitDecode(const scoped_refptr<VP9Picture>& pic,
const Vp9SegmentationParams& seg,
const Vp9LoopFilterParams& lf,
const std::vector<scoped_refptr<VP9Picture>>& ref_pictures,
const base::Closure& done_cb) override;
bool OutputPicture(const scoped_refptr<VP9Picture>& pic) override;
bool IsFrameContextRequired() const override;
bool GetFrameContext(const scoped_refptr<VP9Picture>& pic,
Vp9FrameContext* frame_ctx) override;
private:
scoped_refptr<VaapiDecodeSurface> VP9PictureToVaapiDecodeSurface(
const scoped_refptr<VP9Picture>& pic);
VaapiWrapper* vaapi_wrapper_;
VaapiVideoDecodeAccelerator* vaapi_dec_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(VaapiVP9Accelerator);
};
} // namespace media
#endif // MEDIA_GPU_VAAPI_VAAPI_VP9_ACCELERATOR_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment