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

Unified Diff: media/gpu/v4l2_slice_video_decode_accelerator.cc

Issue 2229353002: V4L2SVDA: Add a VP9Accelerator implementation utilizing the V4L2 VP9 frame API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: compilation fixes Created 4 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/gpu/v4l2_slice_video_decode_accelerator.h ('k') | media/gpu/vaapi_video_decode_accelerator.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/gpu/v4l2_slice_video_decode_accelerator.cc
diff --git a/media/gpu/v4l2_slice_video_decode_accelerator.cc b/media/gpu/v4l2_slice_video_decode_accelerator.cc
index 4f3e7e073901396973cb76f6e23cb50520de45ce..e672f72f68c497cab7dd2c7276a01d6c03667333 100644
--- a/media/gpu/v4l2_slice_video_decode_accelerator.cc
+++ b/media/gpu/v4l2_slice_video_decode_accelerator.cc
@@ -66,7 +66,7 @@ namespace media {
// static
const uint32_t V4L2SliceVideoDecodeAccelerator::supported_input_fourccs_[] = {
- V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME,
+ V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME, V4L2_PIX_FMT_VP9_FRAME,
};
class V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface
@@ -80,7 +80,7 @@ class V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface
const ReleaseCB& release_cb);
// Mark the surface as decoded. This will also release all references, as
- // they are not needed anymore.
+ // they are not needed anymore and execute the done callback, if not null.
void SetDecoded();
bool decoded() const { return decoded_; }
@@ -94,6 +94,14 @@ class V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface
void SetReferenceSurfaces(
const std::vector<scoped_refptr<V4L2DecodeSurface>>& ref_surfaces);
+ // If provided via this method, |done_cb| callback will be executed after
+ // decoding into this surface is finished. The callback is reset afterwards,
+ // so it needs to be set again before each decode operation.
+ void SetDecodeDoneCallback(const base::Closure& done_cb) {
+ DCHECK(done_cb_.is_null());
+ done_cb_ = done_cb;
+ }
+
std::string ToString() const;
private:
@@ -107,6 +115,7 @@ class V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface
bool decoded_;
ReleaseCB release_cb_;
+ base::Closure done_cb_;
std::vector<scoped_refptr<V4L2DecodeSurface>> reference_surfaces_;
@@ -143,6 +152,10 @@ void V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface::SetDecoded() {
// We can now drop references to all reference surfaces for this surface
// as we are done with decoding.
reference_surfaces_.clear();
+
+ // And finally execute and drop the decode done callback, if set.
+ if (!done_cb_.is_null())
+ base::ResetAndReturn(&done_cb_).Run();
}
std::string V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface::ToString()
@@ -245,7 +258,7 @@ V4L2SliceVideoDecodeAccelerator::PictureRecord::~PictureRecord() {}
class V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator
: public H264Decoder::H264Accelerator {
public:
- V4L2H264Accelerator(V4L2SliceVideoDecodeAccelerator* v4l2_dec);
+ explicit V4L2H264Accelerator(V4L2SliceVideoDecodeAccelerator* v4l2_dec);
~V4L2H264Accelerator() override;
// H264Decoder::H264Accelerator implementation.
@@ -299,7 +312,7 @@ class V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator
class V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator
: public VP8Decoder::VP8Accelerator {
public:
- V4L2VP8Accelerator(V4L2SliceVideoDecodeAccelerator* v4l2_dec);
+ explicit V4L2VP8Accelerator(V4L2SliceVideoDecodeAccelerator* v4l2_dec);
~V4L2VP8Accelerator() override;
// VP8Decoder::VP8Accelerator implementation.
@@ -322,11 +335,46 @@ class V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator
DISALLOW_COPY_AND_ASSIGN(V4L2VP8Accelerator);
};
+class V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator
+ : public VP9Decoder::VP9Accelerator {
+ public:
+ explicit V4L2VP9Accelerator(V4L2SliceVideoDecodeAccelerator* v4l2_dec);
+ ~V4L2VP9Accelerator() override;
+
+ // VP9Decoder::VP9Accelerator implementation.
+ scoped_refptr<VP9Picture> CreateVP9Picture() override;
+
+ bool SubmitDecode(const scoped_refptr<VP9Picture>& pic,
+ const Vp9SegmentationParams& segm_params,
+ const Vp9LoopFilterParams& lf_params,
+ const std::vector<scoped_refptr<VP9Picture>>& ref_pictures,
+ const base::Closure& done_cb) override;
+
+ bool OutputPicture(const scoped_refptr<VP9Picture>& pic) override;
+
+ bool GetFrameContext(const scoped_refptr<VP9Picture>& pic,
+ Vp9FrameContext* frame_ctx) override;
+
+ bool IsFrameContextRequired() const override {
+ return device_needs_frame_context_;
+ }
+
+ private:
+ scoped_refptr<V4L2DecodeSurface> VP9PictureToV4L2DecodeSurface(
+ const scoped_refptr<VP9Picture>& pic);
+
+ bool device_needs_frame_context_;
+
+ V4L2SliceVideoDecodeAccelerator* v4l2_dec_;
+
+ DISALLOW_COPY_AND_ASSIGN(V4L2VP9Accelerator);
+};
+
// Codec-specific subclasses of software decoder picture classes.
// This allows us to keep decoders oblivious of our implementation details.
class V4L2H264Picture : public H264Picture {
public:
- V4L2H264Picture(
+ explicit V4L2H264Picture(
const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>&
dec_surface);
@@ -354,7 +402,7 @@ V4L2H264Picture::~V4L2H264Picture() {}
class V4L2VP8Picture : public VP8Picture {
public:
- V4L2VP8Picture(
+ explicit V4L2VP8Picture(
const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>&
dec_surface);
@@ -380,6 +428,34 @@ V4L2VP8Picture::V4L2VP8Picture(
V4L2VP8Picture::~V4L2VP8Picture() {}
+class V4L2VP9Picture : public VP9Picture {
+ public:
+ explicit V4L2VP9Picture(
+ const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>&
+ dec_surface);
+
+ V4L2VP9Picture* AsV4L2VP9Picture() override { return this; }
+ scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>
+ dec_surface() {
+ return dec_surface_;
+ }
+
+ private:
+ ~V4L2VP9Picture() override;
+
+ scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>
+ dec_surface_;
+
+ DISALLOW_COPY_AND_ASSIGN(V4L2VP9Picture);
+};
+
+V4L2VP9Picture::V4L2VP9Picture(
+ const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>&
+ dec_surface)
+ : dec_surface_(dec_surface) {}
+
+V4L2VP9Picture::~V4L2VP9Picture() {}
+
V4L2SliceVideoDecodeAccelerator::V4L2SliceVideoDecodeAccelerator(
const scoped_refptr<V4L2Device>& device,
EGLDisplay egl_display,
@@ -480,6 +556,10 @@ bool V4L2SliceVideoDecodeAccelerator::Initialize(const Config& config,
video_profile_ <= VP8PROFILE_MAX) {
vp8_accelerator_.reset(new V4L2VP8Accelerator(this));
decoder_.reset(new VP8Decoder(vp8_accelerator_.get()));
+ } else if (video_profile_ >= VP9PROFILE_MIN &&
+ video_profile_ <= VP9PROFILE_MAX) {
+ vp9_accelerator_.reset(new V4L2VP9Accelerator(this));
+ decoder_.reset(new VP9Decoder(vp9_accelerator_.get()));
} else {
NOTREACHED() << "Unsupported profile " << video_profile_;
return false;
@@ -983,6 +1063,7 @@ void V4L2SliceVideoDecodeAccelerator::Dequeue() {
TryOutputSurfaces();
ProcessPendingEventsIfNeeded();
+ ScheduleDecodeBufferTaskIfNeeded();
}
void V4L2SliceVideoDecodeAccelerator::NewEventPending() {
@@ -1354,6 +1435,10 @@ void V4L2SliceVideoDecodeAccelerator::DecodeBufferTask() {
DVLOGF(4) << "Ran out of surfaces";
return;
+ case AcceleratedVideoDecoder::kNeedContextUpdate:
+ DVLOGF(4) << "Awaiting context update";
+ return;
+
case AcceleratedVideoDecoder::kDecodeError:
DVLOGF(1) << "Error decoding stream";
NOTIFY_ERROR(PLATFORM_FAILURE);
@@ -2115,7 +2200,7 @@ bool V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::SubmitFrameMetadata(
V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD);
SET_V4L2_SPS_FLAG_IF(direct_8x8_inference_flag,
V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE);
-#undef SET_FLAG
+#undef SET_V4L2_SPS_FLAG_IF
memset(&ctrl, 0, sizeof(ctrl));
ctrl.id = V4L2_CID_MPEG_VIDEO_H264_SPS;
ctrl.size = sizeof(v4l2_sps);
@@ -2357,11 +2442,28 @@ bool V4L2SliceVideoDecodeAccelerator::SubmitSlice(int index,
bool V4L2SliceVideoDecodeAccelerator::SubmitExtControls(
struct v4l2_ext_controls* ext_ctrls) {
+ DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
DCHECK_GT(ext_ctrls->config_store, 0u);
IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_EXT_CTRLS, ext_ctrls);
return true;
}
+bool V4L2SliceVideoDecodeAccelerator::GetExtControls(
+ struct v4l2_ext_controls* ext_ctrls) {
+ DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
+ DCHECK_GT(ext_ctrls->config_store, 0u);
+ IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_G_EXT_CTRLS, ext_ctrls);
+ return true;
+}
+
+bool V4L2SliceVideoDecodeAccelerator::IsCtrlExposed(uint32_t ctrl_id) {
+ struct v4l2_queryctrl query_ctrl;
+ memset(&query_ctrl, 0, sizeof(query_ctrl));
+ query_ctrl.id = ctrl_id;
+
+ return (device_->Ioctl(VIDIOC_QUERYCTRL, &query_ctrl) == 0);
+}
+
bool V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::SubmitDecode(
const scoped_refptr<H264Picture>& pic) {
scoped_refptr<V4L2DecodeSurface> dec_surface =
@@ -2392,7 +2494,8 @@ bool V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::SubmitDecode(
ext_ctrls.count = ctrls.size();
ext_ctrls.controls = &ctrls[0];
ext_ctrls.config_store = dec_surface->config_store();
- v4l2_dec_->SubmitExtControls(&ext_ctrls);
+ if (!v4l2_dec_->SubmitExtControls(&ext_ctrls))
+ return false;
Reset();
@@ -2501,7 +2604,7 @@ static void FillV4L2QuantizationHeader(
v4l2_quant_hdr->uv_ac_delta = vp8_quant_hdr.uv_ac_delta;
}
-static void FillV4L2EntropyHeader(
+static void FillV4L2Vp8EntropyHeader(
const Vp8EntropyHeader& vp8_entropy_hdr,
struct v4l2_vp8_entropy_hdr* v4l2_entropy_hdr) {
ARRAY_MEMCPY_CHECKED(v4l2_entropy_hdr->coeff_probs,
@@ -2557,7 +2660,7 @@ bool V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::SubmitDecode(
FillV4L2QuantizationHeader(frame_hdr->quantization_hdr,
&v4l2_frame_hdr.quant_hdr);
- FillV4L2EntropyHeader(frame_hdr->entropy_hdr, &v4l2_frame_hdr.entropy_hdr);
+ FillV4L2Vp8EntropyHeader(frame_hdr->entropy_hdr, &v4l2_frame_hdr.entropy_hdr);
v4l2_frame_hdr.first_part_size =
base::checked_cast<__u32>(frame_hdr->first_part_size);
@@ -2648,6 +2751,372 @@ V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::
return v4l2_pic->dec_surface();
}
+V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::V4L2VP9Accelerator(
+ V4L2SliceVideoDecodeAccelerator* v4l2_dec)
+ : v4l2_dec_(v4l2_dec) {
+ DCHECK(v4l2_dec_);
+
+ device_needs_frame_context_ =
+ v4l2_dec_->IsCtrlExposed(V4L2_CID_MPEG_VIDEO_VP9_ENTROPY);
+ DVLOG_IF(1, device_needs_frame_context_)
+ << "Device requires frame context parsing";
+}
+
+V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::~V4L2VP9Accelerator() {}
+
+scoped_refptr<VP9Picture>
+V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::CreateVP9Picture() {
+ scoped_refptr<V4L2DecodeSurface> dec_surface = v4l2_dec_->CreateSurface();
+ if (!dec_surface)
+ return nullptr;
+
+ return new V4L2VP9Picture(dec_surface);
+}
+
+static void FillV4L2VP9LoopFilterParams(
+ const Vp9LoopFilterParams& vp9_lf_params,
+ struct v4l2_vp9_loop_filter_params* v4l2_lf_params) {
+#define SET_LF_PARAMS_FLAG_IF(cond, flag) \
+ v4l2_lf_params->flags |= ((vp9_lf_params.cond) ? (flag) : 0)
+ SET_LF_PARAMS_FLAG_IF(delta_enabled, V4L2_VP9_LOOP_FLTR_FLAG_DELTA_ENABLED);
+ SET_LF_PARAMS_FLAG_IF(delta_update, V4L2_VP9_LOOP_FLTR_FLAG_DELTA_UPDATE);
+#undef SET_LF_PARAMS_FLAG_IF
+
+ v4l2_lf_params->level = vp9_lf_params.level;
+ v4l2_lf_params->sharpness = vp9_lf_params.sharpness;
+
+ ARRAY_MEMCPY_CHECKED(v4l2_lf_params->deltas, vp9_lf_params.ref_deltas);
+ ARRAY_MEMCPY_CHECKED(v4l2_lf_params->mode_deltas, vp9_lf_params.mode_deltas);
+ ARRAY_MEMCPY_CHECKED(v4l2_lf_params->lvl_lookup, vp9_lf_params.lvl);
+}
+
+static void FillV4L2VP9QuantizationParams(
+ const Vp9QuantizationParams& vp9_quant_params,
+ struct v4l2_vp9_quantization_params* v4l2_q_params) {
+#define SET_Q_PARAMS_FLAG_IF(cond, flag) \
+ v4l2_q_params->flags |= ((vp9_quant_params.cond) ? (flag) : 0)
+ SET_Q_PARAMS_FLAG_IF(IsLossless(), V4L2_VP9_QUANT_PARAMS_FLAG_LOSSLESS);
+#undef SET_Q_PARAMS_FLAG_IF
+
+#define Q_PARAMS_TO_V4L2_Q_PARAMS(a) v4l2_q_params->a = vp9_quant_params.a
+ Q_PARAMS_TO_V4L2_Q_PARAMS(base_q_idx);
+ Q_PARAMS_TO_V4L2_Q_PARAMS(delta_q_y_dc);
+ Q_PARAMS_TO_V4L2_Q_PARAMS(delta_q_uv_dc);
+ Q_PARAMS_TO_V4L2_Q_PARAMS(delta_q_uv_ac);
+#undef Q_PARAMS_TO_V4L2_Q_PARAMS
+}
+
+static void FillV4L2VP9SegmentationParams(
+ const Vp9SegmentationParams& vp9_segm_params,
+ struct v4l2_vp9_segmentation_params* v4l2_segm_params) {
+#define SET_SEG_PARAMS_FLAG_IF(cond, flag) \
+ v4l2_segm_params->flags |= ((vp9_segm_params.cond) ? (flag) : 0)
+ SET_SEG_PARAMS_FLAG_IF(enabled, V4L2_VP9_SGMNT_PARAM_FLAG_ENABLED);
+ SET_SEG_PARAMS_FLAG_IF(update_map, V4L2_VP9_SGMNT_PARAM_FLAG_UPDATE_MAP);
+ SET_SEG_PARAMS_FLAG_IF(temporal_update,
+ V4L2_VP9_SGMNT_PARAM_FLAG_TEMPORAL_UPDATE);
+ SET_SEG_PARAMS_FLAG_IF(update_data, V4L2_VP9_SGMNT_PARAM_FLAG_UPDATE_DATA);
+ SET_SEG_PARAMS_FLAG_IF(abs_or_delta_update,
+ V4L2_VP9_SGMNT_PARAM_FLAG_ABS_OR_DELTA_UPDATE);
+#undef SET_SEG_PARAMS_FLAG_IF
+
+ ARRAY_MEMCPY_CHECKED(v4l2_segm_params->tree_probs,
+ vp9_segm_params.tree_probs);
+ ARRAY_MEMCPY_CHECKED(v4l2_segm_params->pred_probs,
+ vp9_segm_params.pred_probs);
+ ARRAY_MEMCPY_CHECKED(v4l2_segm_params->feature_data,
+ vp9_segm_params.feature_data);
+
+ static_assert(arraysize(v4l2_segm_params->feature_enabled) ==
+ arraysize(vp9_segm_params.feature_enabled) &&
+ arraysize(v4l2_segm_params->feature_enabled[0]) ==
+ arraysize(vp9_segm_params.feature_enabled[0]),
+ "feature_enabled arrays must be of same size");
+ for (size_t i = 0; i < arraysize(v4l2_segm_params->feature_enabled); ++i) {
+ for (size_t j = 0; j < arraysize(v4l2_segm_params->feature_enabled[i]);
+ ++j) {
+ v4l2_segm_params->feature_enabled[i][j] =
+ vp9_segm_params.feature_enabled[i][j];
+ }
+ }
+}
+
+static void FillV4L2Vp9EntropyContext(
+ const Vp9FrameContext& vp9_frame_ctx,
+ struct v4l2_vp9_entropy_ctx* v4l2_entropy_ctx) {
+#define ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(a) \
+ ARRAY_MEMCPY_CHECKED(v4l2_entropy_ctx->a, vp9_frame_ctx.a)
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(tx_probs_8x8);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(tx_probs_16x16);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(tx_probs_32x32);
+
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(coef_probs);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(skip_prob);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(inter_mode_probs);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(interp_filter_probs);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(is_inter_prob);
+
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(comp_mode_prob);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(single_ref_prob);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(comp_ref_prob);
+
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(y_mode_probs);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(uv_mode_probs);
+
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(partition_probs);
+
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_joint_probs);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_sign_prob);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_class_probs);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_class0_bit_prob);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_bits_prob);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_class0_fr_probs);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_fr_probs);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_class0_hp_prob);
+ ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_hp_prob);
+#undef ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR
+}
+
+bool V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::SubmitDecode(
+ const scoped_refptr<VP9Picture>& pic,
+ const Vp9SegmentationParams& segm_params,
+ const Vp9LoopFilterParams& lf_params,
+ const std::vector<scoped_refptr<VP9Picture>>& ref_pictures,
+ const base::Closure& done_cb) {
+ const Vp9FrameHeader* frame_hdr = pic->frame_hdr.get();
+ DCHECK(frame_hdr);
+
+ struct v4l2_ctrl_vp9_frame_hdr v4l2_frame_hdr;
+ memset(&v4l2_frame_hdr, 0, sizeof(v4l2_frame_hdr));
+
+#define FHDR_TO_V4L2_FHDR(a) v4l2_frame_hdr.a = frame_hdr->a
+ FHDR_TO_V4L2_FHDR(profile);
+ FHDR_TO_V4L2_FHDR(frame_type);
+
+ FHDR_TO_V4L2_FHDR(bit_depth);
+ FHDR_TO_V4L2_FHDR(color_range);
+ FHDR_TO_V4L2_FHDR(subsampling_x);
+ FHDR_TO_V4L2_FHDR(subsampling_y);
+
+ FHDR_TO_V4L2_FHDR(frame_width);
+ FHDR_TO_V4L2_FHDR(frame_height);
+ FHDR_TO_V4L2_FHDR(render_width);
+ FHDR_TO_V4L2_FHDR(render_height);
+
+ FHDR_TO_V4L2_FHDR(reset_frame_context);
+
+ FHDR_TO_V4L2_FHDR(interpolation_filter);
+ FHDR_TO_V4L2_FHDR(frame_context_idx);
+
+ FHDR_TO_V4L2_FHDR(tile_cols_log2);
+ FHDR_TO_V4L2_FHDR(tile_rows_log2);
+
+ FHDR_TO_V4L2_FHDR(header_size_in_bytes);
+#undef FHDR_TO_V4L2_FHDR
+ v4l2_frame_hdr.color_space = static_cast<uint8_t>(frame_hdr->color_space);
+
+ FillV4L2VP9QuantizationParams(frame_hdr->quant_params,
+ &v4l2_frame_hdr.quant_params);
+
+#define SET_V4L2_FRM_HDR_FLAG_IF(cond, flag) \
+ v4l2_frame_hdr.flags |= ((frame_hdr->cond) ? (flag) : 0)
+ SET_V4L2_FRM_HDR_FLAG_IF(show_frame, V4L2_VP9_FRAME_HDR_FLAG_SHOW_FRAME);
+ SET_V4L2_FRM_HDR_FLAG_IF(error_resilient_mode,
+ V4L2_VP9_FRAME_HDR_FLAG_ERR_RES);
+ SET_V4L2_FRM_HDR_FLAG_IF(intra_only, V4L2_VP9_FRAME_HDR_FLAG_FRAME_INTRA);
+ SET_V4L2_FRM_HDR_FLAG_IF(allow_high_precision_mv,
+ V4L2_VP9_FRAME_HDR_ALLOW_HIGH_PREC_MV);
+ SET_V4L2_FRM_HDR_FLAG_IF(refresh_frame_context,
+ V4L2_VP9_FRAME_HDR_REFRESH_FRAME_CTX);
+ SET_V4L2_FRM_HDR_FLAG_IF(frame_parallel_decoding_mode,
+ V4L2_VP9_FRAME_HDR_PARALLEL_DEC_MODE);
+#undef SET_V4L2_FRM_HDR_FLAG_IF
+
+ FillV4L2VP9LoopFilterParams(lf_params, &v4l2_frame_hdr.lf_params);
+ FillV4L2VP9SegmentationParams(segm_params, &v4l2_frame_hdr.sgmnt_params);
+
+ std::vector<struct v4l2_ext_control> ctrls;
+
+ struct v4l2_ext_control ctrl;
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_HDR;
+ ctrl.size = sizeof(v4l2_frame_hdr);
+ ctrl.p_vp9_frame_hdr = &v4l2_frame_hdr;
+ ctrls.push_back(ctrl);
+
+ struct v4l2_ctrl_vp9_decode_param v4l2_decode_param;
+ memset(&v4l2_decode_param, 0, sizeof(v4l2_decode_param));
+ DCHECK_EQ(ref_pictures.size(), arraysize(v4l2_decode_param.ref_frames));
+
+ std::vector<scoped_refptr<V4L2DecodeSurface>> ref_surfaces;
+ for (size_t i = 0; i < ref_pictures.size(); ++i) {
+ if (ref_pictures[i]) {
+ scoped_refptr<V4L2DecodeSurface> ref_surface =
+ VP9PictureToV4L2DecodeSurface(ref_pictures[i]);
+
+ v4l2_decode_param.ref_frames[i] = ref_surface->output_record();
+ ref_surfaces.push_back(ref_surface);
+ } else {
+ v4l2_decode_param.ref_frames[i] = VIDEO_MAX_FRAME;
+ }
+ }
+
+ static_assert(arraysize(v4l2_decode_param.active_ref_frames) ==
+ arraysize(frame_hdr->ref_frame_idx),
+ "active reference frame array sizes mismatch");
+
+ for (size_t i = 0; i < arraysize(frame_hdr->ref_frame_idx); ++i) {
+ uint8_t idx = frame_hdr->ref_frame_idx[i];
+ if (idx >= ref_pictures.size())
+ return false;
+
+ struct v4l2_vp9_reference_frame* v4l2_ref_frame =
+ &v4l2_decode_param.active_ref_frames[i];
+
+ scoped_refptr<VP9Picture> ref_pic = ref_pictures[idx];
+ if (ref_pic) {
+ scoped_refptr<V4L2DecodeSurface> ref_surface =
+ VP9PictureToV4L2DecodeSurface(ref_pic);
+ v4l2_ref_frame->buf_index = ref_surface->output_record();
+#define REF_TO_V4L2_REF(a) v4l2_ref_frame->a = ref_pic->frame_hdr->a
+ REF_TO_V4L2_REF(frame_width);
+ REF_TO_V4L2_REF(frame_height);
+ REF_TO_V4L2_REF(bit_depth);
+ REF_TO_V4L2_REF(subsampling_x);
+ REF_TO_V4L2_REF(subsampling_y);
+#undef REF_TO_V4L2_REF
+ } else {
+ v4l2_ref_frame->buf_index = VIDEO_MAX_FRAME;
+ }
+ }
+
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.id = V4L2_CID_MPEG_VIDEO_VP9_DECODE_PARAM;
+ ctrl.size = sizeof(v4l2_decode_param);
+ ctrl.p_vp9_decode_param = &v4l2_decode_param;
+ ctrls.push_back(ctrl);
+
+ // Defined outside of the if() clause below as it must remain valid until
+ // the call to SubmitExtControls().
+ struct v4l2_ctrl_vp9_entropy v4l2_entropy;
+ if (device_needs_frame_context_) {
+ memset(&v4l2_entropy, 0, sizeof(v4l2_entropy));
+ FillV4L2Vp9EntropyContext(frame_hdr->initial_frame_context,
+ &v4l2_entropy.initial_entropy_ctx);
+ FillV4L2Vp9EntropyContext(frame_hdr->frame_context,
+ &v4l2_entropy.current_entropy_ctx);
+ v4l2_entropy.tx_mode = frame_hdr->compressed_header.tx_mode;
+ v4l2_entropy.reference_mode = frame_hdr->compressed_header.reference_mode;
+
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.id = V4L2_CID_MPEG_VIDEO_VP9_ENTROPY;
+ ctrl.size = sizeof(v4l2_entropy);
+ ctrl.p_vp9_entropy = &v4l2_entropy;
+ ctrls.push_back(ctrl);
+ }
+
+ scoped_refptr<V4L2DecodeSurface> dec_surface =
+ VP9PictureToV4L2DecodeSurface(pic);
+
+ struct v4l2_ext_controls ext_ctrls;
+ memset(&ext_ctrls, 0, sizeof(ext_ctrls));
+ ext_ctrls.count = ctrls.size();
+ ext_ctrls.controls = &ctrls[0];
+ ext_ctrls.config_store = dec_surface->config_store();
+ if (!v4l2_dec_->SubmitExtControls(&ext_ctrls))
+ return false;
+
+ dec_surface->SetReferenceSurfaces(ref_surfaces);
+ dec_surface->SetDecodeDoneCallback(done_cb);
+
+ if (!v4l2_dec_->SubmitSlice(dec_surface->input_record(), frame_hdr->data,
+ frame_hdr->frame_size))
+ return false;
+
+ v4l2_dec_->DecodeSurface(dec_surface);
+ return true;
+}
+
+bool V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::OutputPicture(
+ const scoped_refptr<VP9Picture>& pic) {
+ scoped_refptr<V4L2DecodeSurface> dec_surface =
+ VP9PictureToV4L2DecodeSurface(pic);
+
+ v4l2_dec_->SurfaceReady(dec_surface);
+ return true;
+}
+
+static void FillVp9FrameContext(struct v4l2_vp9_entropy_ctx& v4l2_entropy_ctx,
+ Vp9FrameContext* vp9_frame_ctx) {
+#define ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(a) \
+ ARRAY_MEMCPY_CHECKED(vp9_frame_ctx->a, v4l2_entropy_ctx.a)
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(tx_probs_8x8);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(tx_probs_16x16);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(tx_probs_32x32);
+
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(coef_probs);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(skip_prob);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(inter_mode_probs);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(interp_filter_probs);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(is_inter_prob);
+
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(comp_mode_prob);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(single_ref_prob);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(comp_ref_prob);
+
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(y_mode_probs);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(uv_mode_probs);
+
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(partition_probs);
+
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_joint_probs);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_sign_prob);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_class_probs);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_class0_bit_prob);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_bits_prob);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_class0_fr_probs);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_fr_probs);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_class0_hp_prob);
+ ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_hp_prob);
+#undef ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX
+}
+
+bool V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::GetFrameContext(
+ const scoped_refptr<VP9Picture>& pic,
+ Vp9FrameContext* frame_ctx) {
+ struct v4l2_ctrl_vp9_entropy v4l2_entropy;
+ memset(&v4l2_entropy, 0, sizeof(v4l2_entropy));
+
+ struct v4l2_ext_control ctrl;
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.id = V4L2_CID_MPEG_VIDEO_VP9_ENTROPY;
+ ctrl.size = sizeof(v4l2_entropy);
+ ctrl.p_vp9_entropy = &v4l2_entropy;
+
+ scoped_refptr<V4L2DecodeSurface> dec_surface =
+ VP9PictureToV4L2DecodeSurface(pic);
+
+ struct v4l2_ext_controls ext_ctrls;
+ memset(&ext_ctrls, 0, sizeof(ext_ctrls));
+ ext_ctrls.count = 1;
+ ext_ctrls.controls = &ctrl;
+ ext_ctrls.config_store = dec_surface->config_store();
+
+ if (!v4l2_dec_->GetExtControls(&ext_ctrls))
+ return false;
+
+ FillVp9FrameContext(v4l2_entropy.current_entropy_ctx, frame_ctx);
+ return true;
+}
+
+scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>
+V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::
+ VP9PictureToV4L2DecodeSurface(const scoped_refptr<VP9Picture>& pic) {
+ V4L2VP9Picture* v4l2_pic = pic->AsV4L2VP9Picture();
+ CHECK(v4l2_pic);
+ return v4l2_pic->dec_surface();
+}
+
void V4L2SliceVideoDecodeAccelerator::DecodeSurface(
const scoped_refptr<V4L2DecodeSurface>& dec_surface) {
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
« no previous file with comments | « media/gpu/v4l2_slice_video_decode_accelerator.h ('k') | media/gpu/vaapi_video_decode_accelerator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698