Commit 11edd699 authored by Miguel Casas's avatar Miguel Casas Committed by Commit Bot

media/gpu/vaapi: manage VP8 VABufferIDs lifetime in the decoder

Decoding a bitstream in VA has two steps: one, submitting the parsed
parameters and encoded chunk as VABufferIDs, and two, executing the
decode. This CL transfers managing the lifetime of the VABufferIDs to
VP8VaapiVideoDecoderDelegate, avoiding vaCreateBuffer() calls.

vaapi_utils' FillVP8DataStructures() needs to be changed to operate
on VA-API structs passed as parameter, which in turn forces a bit
of changes in the webp decoder.

This is verified via chrome:tracing and codepen.io/full/qzYXba that
plays 4 1280x572 VP8 videos at the same time. Tracing is captured for
a few seconds, and basically we avoid calling the vaCreateBuffer(),
which takes ~50us every time, reducing the overall decode time from
~0.439ms to ~0.307ms on my CML (kohaku), ~25% reduction. Improvements
are of course extremely small, the advantages of this CL are in
reducing lock/unlock churn and associated contention. This benefit
grows with the amount of decodes (e.g. Meet grid scenarios).

Bug: b/166646505
Change-Id: I6b0e2dc21ad94e2e1c9ab3696fba037d5b88830b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2412132
Commit-Queue: Miguel Casas <mcasas@chromium.org>
Reviewed-by: default avatarAndres Calderon Jaramillo <andrescj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#809676}
parent d42639ba
...@@ -190,20 +190,20 @@ bool ScopedVASurface::IsValid() const { ...@@ -190,20 +190,20 @@ bool ScopedVASurface::IsValid() const {
va_rt_format_ != kInvalidVaRtFormat; va_rt_format_ != kInvalidVaRtFormat;
} }
bool FillVP8DataStructures(VaapiWrapper* vaapi_wrapper, void FillVP8DataStructures(const Vp8FrameHeader& frame_header,
VASurfaceID va_surface_id, const Vp8ReferenceFrameVector& reference_frames,
const Vp8FrameHeader& frame_header, VAIQMatrixBufferVP8* iq_matrix_buf,
const Vp8ReferenceFrameVector& reference_frames) { VAProbabilityDataBufferVP8* prob_buf,
DCHECK_NE(va_surface_id, VA_INVALID_SURFACE); VAPictureParameterBufferVP8* pic_param,
DCHECK(vaapi_wrapper); VASliceParameterBufferVP8* slice_param) {
const Vp8SegmentationHeader& sgmnt_hdr = frame_header.segmentation_hdr; const Vp8SegmentationHeader& sgmnt_hdr = frame_header.segmentation_hdr;
const Vp8QuantizationHeader& quant_hdr = frame_header.quantization_hdr; const Vp8QuantizationHeader& quant_hdr = frame_header.quantization_hdr;
VAIQMatrixBufferVP8 iq_matrix_buf{}; static_assert(base::size(decltype(iq_matrix_buf->quantization_index){}) ==
static_assert(base::size(iq_matrix_buf.quantization_index) == kMaxMBSegments, kMaxMBSegments,
"incorrect quantization matrix segment size"); "incorrect quantization matrix segment size");
static_assert(base::size(iq_matrix_buf.quantization_index[0]) == 6, static_assert(
"incorrect quantization matrix Q index size"); base::size(decltype(iq_matrix_buf->quantization_index){}[0]) == 6,
"incorrect quantization matrix Q index size");
for (size_t i = 0; i < kMaxMBSegments; ++i) { for (size_t i = 0; i < kMaxMBSegments; ++i) {
int q = quant_hdr.y_ac_qi; int q = quant_hdr.y_ac_qi;
...@@ -217,52 +217,54 @@ bool FillVP8DataStructures(VaapiWrapper* vaapi_wrapper, ...@@ -217,52 +217,54 @@ bool FillVP8DataStructures(VaapiWrapper* vaapi_wrapper,
} }
#define CLAMP_Q(q) base::ClampToRange(q, 0, 127) #define CLAMP_Q(q) base::ClampToRange(q, 0, 127)
iq_matrix_buf.quantization_index[i][0] = CLAMP_Q(q); iq_matrix_buf->quantization_index[i][0] = CLAMP_Q(q);
iq_matrix_buf.quantization_index[i][1] = CLAMP_Q(q + quant_hdr.y_dc_delta); iq_matrix_buf->quantization_index[i][1] = CLAMP_Q(q + quant_hdr.y_dc_delta);
iq_matrix_buf.quantization_index[i][2] = CLAMP_Q(q + quant_hdr.y2_dc_delta); iq_matrix_buf->quantization_index[i][2] =
iq_matrix_buf.quantization_index[i][3] = CLAMP_Q(q + quant_hdr.y2_ac_delta); CLAMP_Q(q + quant_hdr.y2_dc_delta);
iq_matrix_buf.quantization_index[i][4] = CLAMP_Q(q + quant_hdr.uv_dc_delta); iq_matrix_buf->quantization_index[i][3] =
iq_matrix_buf.quantization_index[i][5] = CLAMP_Q(q + quant_hdr.uv_ac_delta); CLAMP_Q(q + quant_hdr.y2_ac_delta);
iq_matrix_buf->quantization_index[i][4] =
CLAMP_Q(q + quant_hdr.uv_dc_delta);
iq_matrix_buf->quantization_index[i][5] =
CLAMP_Q(q + quant_hdr.uv_ac_delta);
#undef CLAMP_Q #undef CLAMP_Q
} }
const Vp8EntropyHeader& entr_hdr = frame_header.entropy_hdr; const Vp8EntropyHeader& entr_hdr = frame_header.entropy_hdr;
VAProbabilityDataBufferVP8 prob_buf{}; CheckedMemcpy(prob_buf->dct_coeff_probs, entr_hdr.coeff_probs);
CheckedMemcpy(prob_buf.dct_coeff_probs, entr_hdr.coeff_probs);
VAPictureParameterBufferVP8 pic_param{}; pic_param->frame_width = frame_header.width;
pic_param.frame_width = frame_header.width; pic_param->frame_height = frame_header.height;
pic_param.frame_height = frame_header.height;
const auto last_frame = reference_frames.GetFrame(Vp8RefType::VP8_FRAME_LAST); const auto last_frame = reference_frames.GetFrame(Vp8RefType::VP8_FRAME_LAST);
if (last_frame) { if (last_frame) {
pic_param.last_ref_frame = pic_param->last_ref_frame =
last_frame->AsVaapiVP8Picture()->GetVASurfaceID(); last_frame->AsVaapiVP8Picture()->GetVASurfaceID();
} else { } else {
pic_param.last_ref_frame = VA_INVALID_SURFACE; pic_param->last_ref_frame = VA_INVALID_SURFACE;
} }
const auto golden_frame = const auto golden_frame =
reference_frames.GetFrame(Vp8RefType::VP8_FRAME_GOLDEN); reference_frames.GetFrame(Vp8RefType::VP8_FRAME_GOLDEN);
if (golden_frame) { if (golden_frame) {
pic_param.golden_ref_frame = pic_param->golden_ref_frame =
golden_frame->AsVaapiVP8Picture()->GetVASurfaceID(); golden_frame->AsVaapiVP8Picture()->GetVASurfaceID();
} else { } else {
pic_param.golden_ref_frame = VA_INVALID_SURFACE; pic_param->golden_ref_frame = VA_INVALID_SURFACE;
} }
const auto alt_frame = const auto alt_frame =
reference_frames.GetFrame(Vp8RefType::VP8_FRAME_ALTREF); reference_frames.GetFrame(Vp8RefType::VP8_FRAME_ALTREF);
if (alt_frame) if (alt_frame)
pic_param.alt_ref_frame = alt_frame->AsVaapiVP8Picture()->GetVASurfaceID(); pic_param->alt_ref_frame = alt_frame->AsVaapiVP8Picture()->GetVASurfaceID();
else else
pic_param.alt_ref_frame = VA_INVALID_SURFACE; pic_param->alt_ref_frame = VA_INVALID_SURFACE;
pic_param.out_of_loop_frame = VA_INVALID_SURFACE; pic_param->out_of_loop_frame = VA_INVALID_SURFACE;
const Vp8LoopFilterHeader& lf_hdr = frame_header.loopfilter_hdr; const Vp8LoopFilterHeader& lf_hdr = frame_header.loopfilter_hdr;
#define FHDR_TO_PP_PF(a, b) pic_param.pic_fields.bits.a = (b) #define FHDR_TO_PP_PF(a, b) pic_param->pic_fields.bits.a = (b)
FHDR_TO_PP_PF(key_frame, frame_header.IsKeyframe() ? 0 : 1); FHDR_TO_PP_PF(key_frame, frame_header.IsKeyframe() ? 0 : 1);
FHDR_TO_PP_PF(version, frame_header.version); FHDR_TO_PP_PF(version, frame_header.version);
FHDR_TO_PP_PF(segmentation_enabled, sgmnt_hdr.segmentation_enabled); FHDR_TO_PP_PF(segmentation_enabled, sgmnt_hdr.segmentation_enabled);
...@@ -280,10 +282,10 @@ bool FillVP8DataStructures(VaapiWrapper* vaapi_wrapper, ...@@ -280,10 +282,10 @@ bool FillVP8DataStructures(VaapiWrapper* vaapi_wrapper,
FHDR_TO_PP_PF(loop_filter_disable, lf_hdr.level == 0); FHDR_TO_PP_PF(loop_filter_disable, lf_hdr.level == 0);
#undef FHDR_TO_PP_PF #undef FHDR_TO_PP_PF
CheckedMemcpy(pic_param.mb_segment_tree_probs, sgmnt_hdr.segment_prob); CheckedMemcpy(pic_param->mb_segment_tree_probs, sgmnt_hdr.segment_prob);
static_assert(std::extent<decltype(sgmnt_hdr.lf_update_value)>() == static_assert(std::extent<decltype(sgmnt_hdr.lf_update_value)>() ==
std::extent<decltype(pic_param.loop_filter_level)>(), std::extent<decltype(pic_param->loop_filter_level)>(),
"loop filter level arrays mismatch"); "loop filter level arrays mismatch");
for (size_t i = 0; i < base::size(sgmnt_hdr.lf_update_value); ++i) { for (size_t i = 0; i < base::size(sgmnt_hdr.lf_update_value); ++i) {
int lf_level = lf_hdr.level; int lf_level = lf_hdr.level;
...@@ -296,61 +298,53 @@ bool FillVP8DataStructures(VaapiWrapper* vaapi_wrapper, ...@@ -296,61 +298,53 @@ bool FillVP8DataStructures(VaapiWrapper* vaapi_wrapper,
} }
} }
pic_param.loop_filter_level[i] = base::ClampToRange(lf_level, 0, 63); pic_param->loop_filter_level[i] = base::ClampToRange(lf_level, 0, 63);
} }
static_assert( static_assert(
std::extent<decltype(lf_hdr.ref_frame_delta)>() == std::extent<decltype(lf_hdr.ref_frame_delta)>() ==
std::extent<decltype(pic_param.loop_filter_deltas_ref_frame)>(), std::extent<decltype(pic_param->loop_filter_deltas_ref_frame)>(),
"loop filter deltas arrays size mismatch"); "loop filter deltas arrays size mismatch");
static_assert(std::extent<decltype(lf_hdr.mb_mode_delta)>() == static_assert(std::extent<decltype(lf_hdr.mb_mode_delta)>() ==
std::extent<decltype(pic_param.loop_filter_deltas_mode)>(), std::extent<decltype(pic_param->loop_filter_deltas_mode)>(),
"loop filter deltas arrays size mismatch"); "loop filter deltas arrays size mismatch");
static_assert(std::extent<decltype(lf_hdr.ref_frame_delta)>() == static_assert(std::extent<decltype(lf_hdr.ref_frame_delta)>() ==
std::extent<decltype(lf_hdr.mb_mode_delta)>(), std::extent<decltype(lf_hdr.mb_mode_delta)>(),
"loop filter deltas arrays size mismatch"); "loop filter deltas arrays size mismatch");
for (size_t i = 0; i < base::size(lf_hdr.ref_frame_delta); ++i) { for (size_t i = 0; i < base::size(lf_hdr.ref_frame_delta); ++i) {
pic_param.loop_filter_deltas_ref_frame[i] = lf_hdr.ref_frame_delta[i]; pic_param->loop_filter_deltas_ref_frame[i] = lf_hdr.ref_frame_delta[i];
pic_param.loop_filter_deltas_mode[i] = lf_hdr.mb_mode_delta[i]; pic_param->loop_filter_deltas_mode[i] = lf_hdr.mb_mode_delta[i];
} }
#define FHDR_TO_PP(a) pic_param.a = frame_header.a #define FHDR_TO_PP(a) pic_param->a = frame_header.a
FHDR_TO_PP(prob_skip_false); FHDR_TO_PP(prob_skip_false);
FHDR_TO_PP(prob_intra); FHDR_TO_PP(prob_intra);
FHDR_TO_PP(prob_last); FHDR_TO_PP(prob_last);
FHDR_TO_PP(prob_gf); FHDR_TO_PP(prob_gf);
#undef FHDR_TO_PP #undef FHDR_TO_PP
CheckedMemcpy(pic_param.y_mode_probs, entr_hdr.y_mode_probs); CheckedMemcpy(pic_param->y_mode_probs, entr_hdr.y_mode_probs);
CheckedMemcpy(pic_param.uv_mode_probs, entr_hdr.uv_mode_probs); CheckedMemcpy(pic_param->uv_mode_probs, entr_hdr.uv_mode_probs);
CheckedMemcpy(pic_param.mv_probs, entr_hdr.mv_probs); CheckedMemcpy(pic_param->mv_probs, entr_hdr.mv_probs);
pic_param.bool_coder_ctx.range = frame_header.bool_dec_range; pic_param->bool_coder_ctx.range = frame_header.bool_dec_range;
pic_param.bool_coder_ctx.value = frame_header.bool_dec_value; pic_param->bool_coder_ctx.value = frame_header.bool_dec_value;
pic_param.bool_coder_ctx.count = frame_header.bool_dec_count; pic_param->bool_coder_ctx.count = frame_header.bool_dec_count;
VASliceParameterBufferVP8 slice_param{}; slice_param->slice_data_size = frame_header.frame_size;
slice_param.slice_data_size = frame_header.frame_size; slice_param->slice_data_offset = frame_header.first_part_offset;
slice_param.slice_data_offset = frame_header.first_part_offset; slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
slice_param.slice_data_flag = VA_SLICE_DATA_FLAG_ALL; slice_param->macroblock_offset = frame_header.macroblock_bit_offset;
slice_param.macroblock_offset = frame_header.macroblock_bit_offset;
// Number of DCT partitions plus control partition. // Number of DCT partitions plus control partition.
slice_param.num_of_partitions = frame_header.num_of_dct_partitions + 1; slice_param->num_of_partitions = frame_header.num_of_dct_partitions + 1;
// Per VAAPI, this size only includes the size of the macroblock data in // Per VAAPI, this size only includes the size of the macroblock data in
// the first partition (in bytes), so we have to subtract the header size. // the first partition (in bytes), so we have to subtract the header size.
slice_param.partition_size[0] = slice_param->partition_size[0] =
frame_header.first_part_size - frame_header.first_part_size -
((frame_header.macroblock_bit_offset + 7) / 8); ((frame_header.macroblock_bit_offset + 7) / 8);
for (size_t i = 0; i < frame_header.num_of_dct_partitions; ++i) for (size_t i = 0; i < frame_header.num_of_dct_partitions; ++i)
slice_param.partition_size[i + 1] = frame_header.dct_partition_sizes[i]; slice_param->partition_size[i + 1] = frame_header.dct_partition_sizes[i];
return vaapi_wrapper->SubmitBuffers(
{{VAIQMatrixBufferType, sizeof(iq_matrix_buf), &iq_matrix_buf},
{VAProbabilityBufferType, sizeof(prob_buf), &prob_buf},
{VAPictureParameterBufferType, sizeof(pic_param), &pic_param},
{VASliceParameterBufferType, sizeof(slice_param), &slice_param},
{VASliceDataBufferType, frame_header.frame_size, frame_header.data}});
} }
} // namespace media } // namespace media
...@@ -174,12 +174,13 @@ class ScopedID { ...@@ -174,12 +174,13 @@ class ScopedID {
ReleaseCB release_cb_; ReleaseCB release_cb_;
}; };
// Adapts |frame_header| to the Vaapi data types, prepping it for consumption by // Adapts |frame_header| to the Vaapi data types.
// |vaapi_wrapper| void FillVP8DataStructures(const Vp8FrameHeader& frame_header,
bool FillVP8DataStructures(VaapiWrapper* vaapi_wrapper, const Vp8ReferenceFrameVector& reference_frames,
VASurfaceID va_surface_id, VAIQMatrixBufferVP8* iq_matrix_buf,
const Vp8FrameHeader& frame_header, VAProbabilityDataBufferVP8* prob_buf,
const Vp8ReferenceFrameVector& reference_frames); VAPictureParameterBufferVP8* pic_param,
VASliceParameterBufferVP8* slice_param);
} // namespace media } // namespace media
#endif // MEDIA_GPU_VAAPI_VAAPI_UTILS_H_ #endif // MEDIA_GPU_VAAPI_VAAPI_UTILS_H_
...@@ -1066,7 +1066,8 @@ void VaapiVideoDecodeAccelerator::Cleanup() { ...@@ -1066,7 +1066,8 @@ void VaapiVideoDecodeAccelerator::Cleanup() {
// Notify |decoder_delegate_| of an imminent VAContextID destruction, so it // Notify |decoder_delegate_| of an imminent VAContextID destruction, so it
// can destroy any internal structures making use of it. At this point // can destroy any internal structures making use of it. At this point
// |decoder_thread_| is stopped so we can access these from |task_runner_|. // |decoder_thread_| is stopped so we can access |decoder_delegate_| from
// |task_runner_|.
decoder_delegate_->OnVAContextDestructionSoon(); decoder_delegate_->OnVAContextDestructionSoon();
vaapi_wrapper_->DestroyContext(); vaapi_wrapper_->DestroyContext();
......
...@@ -120,14 +120,24 @@ VaapiImageDecodeStatus VaapiWebPDecoder::AllocateVASurfaceAndSubmitVABuffers( ...@@ -120,14 +120,24 @@ VaapiImageDecodeStatus VaapiWebPDecoder::AllocateVASurfaceAndSubmitVABuffers(
} }
DCHECK(scoped_va_context_and_surface_->IsValid()); DCHECK(scoped_va_context_and_surface_->IsValid());
} }
DCHECK_NE(scoped_va_context_and_surface_->id(), VA_INVALID_SURFACE);
if (!FillVP8DataStructures(vaapi_wrapper_.get(),
scoped_va_context_and_surface_->id(), VAIQMatrixBufferVP8 iq_matrix_buf{};
*parse_result, Vp8ReferenceFrameVector())) { VAProbabilityDataBufferVP8 prob_buf{};
return VaapiImageDecodeStatus::kSubmitVABuffersFailed; VAPictureParameterBufferVP8 pic_param{};
} VASliceParameterBufferVP8 slice_param{};
FillVP8DataStructures(*parse_result, Vp8ReferenceFrameVector(),
return VaapiImageDecodeStatus::kSuccess; &iq_matrix_buf, &prob_buf, &pic_param, &slice_param);
const bool success = vaapi_wrapper_->SubmitBuffers(
{{VAIQMatrixBufferType, sizeof(iq_matrix_buf), &iq_matrix_buf},
{VAProbabilityBufferType, sizeof(prob_buf), &prob_buf},
{VAPictureParameterBufferType, sizeof(pic_param), &pic_param},
{VASliceParameterBufferType, sizeof(slice_param), &slice_param},
{VASliceDataBufferType, parse_result->frame_size, parse_result->data}});
return success ? VaapiImageDecodeStatus::kSuccess
: VaapiImageDecodeStatus::kSubmitVABuffersFailed;
} }
} // namespace media } // namespace media
...@@ -18,7 +18,12 @@ VP8VaapiVideoDecoderDelegate::VP8VaapiVideoDecoderDelegate( ...@@ -18,7 +18,12 @@ VP8VaapiVideoDecoderDelegate::VP8VaapiVideoDecoderDelegate(
scoped_refptr<VaapiWrapper> vaapi_wrapper) scoped_refptr<VaapiWrapper> vaapi_wrapper)
: VaapiVideoDecoderDelegate(vaapi_dec, std::move(vaapi_wrapper)) {} : VaapiVideoDecoderDelegate(vaapi_dec, std::move(vaapi_wrapper)) {}
VP8VaapiVideoDecoderDelegate::~VP8VaapiVideoDecoderDelegate() = default; VP8VaapiVideoDecoderDelegate::~VP8VaapiVideoDecoderDelegate() {
DCHECK(!iq_matrix_);
DCHECK(!prob_buffer_);
DCHECK(!picture_params_);
DCHECK(!slice_params_);
}
scoped_refptr<VP8Picture> VP8VaapiVideoDecoderDelegate::CreateVP8Picture() { scoped_refptr<VP8Picture> VP8VaapiVideoDecoderDelegate::CreateVP8Picture() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
...@@ -35,14 +40,63 @@ bool VP8VaapiVideoDecoderDelegate::SubmitDecode( ...@@ -35,14 +40,63 @@ bool VP8VaapiVideoDecoderDelegate::SubmitDecode(
TRACE_EVENT0("media,gpu", "VP8VaapiVideoDecoderDelegate::SubmitDecode"); TRACE_EVENT0("media,gpu", "VP8VaapiVideoDecoderDelegate::SubmitDecode");
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto va_surface_id = pic->AsVaapiVP8Picture()->va_surface()->id(); const auto va_surface_id = pic->AsVaapiVP8Picture()->va_surface()->id();
DCHECK_NE(va_surface_id, VA_INVALID_SURFACE);
if (!FillVP8DataStructures(vaapi_wrapper_.get(), va_surface_id, VAIQMatrixBufferVP8 iq_matrix_buf{};
*pic->frame_hdr, reference_frames)) { VAProbabilityDataBufferVP8 prob_buf{};
return false; VAPictureParameterBufferVP8 pic_param{};
VASliceParameterBufferVP8 slice_param{};
const Vp8FrameHeader* const header = pic->frame_hdr.get();
DCHECK(header);
FillVP8DataStructures(*header, reference_frames, &iq_matrix_buf, &prob_buf,
&pic_param, &slice_param);
if (!iq_matrix_) {
iq_matrix_ = vaapi_wrapper_->CreateVABuffer(VAIQMatrixBufferType,
sizeof(iq_matrix_buf));
if (!iq_matrix_)
return false;
}
if (!prob_buffer_) {
prob_buffer_ = vaapi_wrapper_->CreateVABuffer(VAProbabilityBufferType,
sizeof(prob_buf));
if (!prob_buffer_)
return false;
} }
if (!picture_params_) {
picture_params_ = vaapi_wrapper_->CreateVABuffer(
VAPictureParameterBufferType, sizeof(pic_param));
if (!picture_params_)
return false;
}
if (!slice_params_) {
slice_params_ = vaapi_wrapper_->CreateVABuffer(VASliceParameterBufferType,
sizeof(slice_param));
if (!slice_params_)
return false;
}
// |encoded_data| cannot be reused even when it's of the appropriate size, due
// to strange stutterings in e.g. Gen 9.5.
std::unique_ptr<ScopedVABuffer> encoded_data =
vaapi_wrapper_->CreateVABuffer(VASliceDataBufferType, header->frame_size);
if (!encoded_data)
return false;
return vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(va_surface_id); return vaapi_wrapper_->MapAndCopyAndExecute(
va_surface_id,
{{iq_matrix_->id(),
{iq_matrix_->type(), iq_matrix_->size(), &iq_matrix_buf}},
{prob_buffer_->id(),
{prob_buffer_->type(), prob_buffer_->size(), &prob_buf}},
{picture_params_->id(),
{picture_params_->type(), picture_params_->size(), &pic_param}},
{slice_params_->id(),
{slice_params_->type(), slice_params_->size(), &slice_param}},
{encoded_data->id(),
{encoded_data->type(), header->frame_size, header->data}}});
} }
bool VP8VaapiVideoDecoderDelegate::OutputPicture( bool VP8VaapiVideoDecoderDelegate::OutputPicture(
...@@ -56,4 +110,12 @@ bool VP8VaapiVideoDecoderDelegate::OutputPicture( ...@@ -56,4 +110,12 @@ bool VP8VaapiVideoDecoderDelegate::OutputPicture(
return true; return true;
} }
void VP8VaapiVideoDecoderDelegate::OnVAContextDestructionSoon() {
// Destroy the member ScopedVABuffers below since they refer to a VAContextID
// that will be destroyed soon. iq_matrix_.reset();
prob_buffer_.reset();
picture_params_.reset();
slice_params_.reset();
}
} // namespace media } // namespace media
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
namespace media { namespace media {
class ScopedVABuffer;
class VP8Picture; class VP8Picture;
class VP8VaapiVideoDecoderDelegate : public VP8Decoder::VP8Accelerator, class VP8VaapiVideoDecoderDelegate : public VP8Decoder::VP8Accelerator,
...@@ -29,6 +30,15 @@ class VP8VaapiVideoDecoderDelegate : public VP8Decoder::VP8Accelerator, ...@@ -29,6 +30,15 @@ class VP8VaapiVideoDecoderDelegate : public VP8Decoder::VP8Accelerator,
const Vp8ReferenceFrameVector& reference_frames) override; const Vp8ReferenceFrameVector& reference_frames) override;
bool OutputPicture(scoped_refptr<VP8Picture> pic) override; bool OutputPicture(scoped_refptr<VP8Picture> pic) override;
// VaapiVideoDecoderDelegate impl.
void OnVAContextDestructionSoon() override;
private:
std::unique_ptr<ScopedVABuffer> iq_matrix_;
std::unique_ptr<ScopedVABuffer> prob_buffer_;
std::unique_ptr<ScopedVABuffer> picture_params_;
std::unique_ptr<ScopedVABuffer> slice_params_;
DISALLOW_COPY_AND_ASSIGN(VP8VaapiVideoDecoderDelegate); DISALLOW_COPY_AND_ASSIGN(VP8VaapiVideoDecoderDelegate);
}; };
......
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