Commit e891e09f authored by Francois Buergisser's avatar Francois Buergisser Committed by Commit Bot

media/gpu/v4l2: support new and legacy H264 in Chromium

Move current Chromium H264 accelerator to legacy and add support for
new H264 headers.
The use of new or legacy H264 accelerator is decided by whether the driver
supports request API or not.

BUG=chromium:987856
TEST=VDA unittest with test-25fps.h264 and frame validation on
     Minnie 3.14 and Kevin 4.4.

Change-Id: I103a0a8d08171ceb96f020c08125686d874ee41d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1723332Reviewed-by: default avatarAlexandre Courbot <acourbot@chromium.org>
Commit-Queue: Alexandre Courbot <acourbot@chromium.org>
Cr-Commit-Position: refs/heads/master@{#685472}
parent 61f89265
...@@ -35,6 +35,8 @@ source_set("v4l2") { ...@@ -35,6 +35,8 @@ source_set("v4l2") {
"v4l2_device.h", "v4l2_device.h",
"v4l2_h264_accelerator.cc", "v4l2_h264_accelerator.cc",
"v4l2_h264_accelerator.h", "v4l2_h264_accelerator.h",
"v4l2_h264_accelerator_legacy.cc",
"v4l2_h264_accelerator_legacy.h",
"v4l2_image_processor.cc", "v4l2_image_processor.cc",
"v4l2_image_processor.h", "v4l2_image_processor.h",
"v4l2_slice_video_decode_accelerator.cc", "v4l2_slice_video_decode_accelerator.cc",
......
...@@ -4,6 +4,12 @@ ...@@ -4,6 +4,12 @@
#include "media/gpu/v4l2/v4l2_h264_accelerator.h" #include "media/gpu/v4l2/v4l2_h264_accelerator.h"
// TODO(987856): prevent legacy headers being included from videodev2.h until
// v4.14
// support is deprecated.
#define _H264_CTRLS_LEGACY_H_
#include <linux/media/h264-ctrls.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <type_traits> #include <type_traits>
...@@ -23,8 +29,8 @@ struct V4L2H264AcceleratorPrivate { ...@@ -23,8 +29,8 @@ struct V4L2H264AcceleratorPrivate {
// TODO(posciak): This should be queried from hardware once supported. // TODO(posciak): This should be queried from hardware once supported.
static constexpr size_t kMaxSlices = 16; static constexpr size_t kMaxSlices = 16;
struct v4l2_ctrl_h264_slice_param v4l2_slice_params[kMaxSlices]; struct v4l2_ctrl_h264_slice_params v4l2_slice_params[kMaxSlices];
struct v4l2_ctrl_h264_decode_param v4l2_decode_param; struct v4l2_ctrl_h264_decode_params v4l2_decode_param;
}; };
class V4L2H264Picture : public H264Picture { class V4L2H264Picture : public H264Picture {
...@@ -97,7 +103,7 @@ void V4L2H264Accelerator::H264DPBToV4L2DPB( ...@@ -97,7 +103,7 @@ void V4L2H264Accelerator::H264DPBToV4L2DPB(
} }
struct v4l2_h264_dpb_entry& entry = priv_->v4l2_decode_param.dpb[i++]; struct v4l2_h264_dpb_entry& entry = priv_->v4l2_decode_param.dpb[i++];
entry.buf_index = index; entry.reference_ts = index;
entry.frame_num = pic->frame_num; entry.frame_num = pic->frame_num;
entry.pic_num = pic->pic_num; entry.pic_num = pic->pic_num;
entry.top_field_order_cnt = pic->top_field_order_cnt; entry.top_field_order_cnt = pic->top_field_order_cnt;
...@@ -306,7 +312,7 @@ H264Decoder::H264Accelerator::Status V4L2H264Accelerator::SubmitSlice( ...@@ -306,7 +312,7 @@ H264Decoder::H264Accelerator::Status V4L2H264Accelerator::SubmitSlice(
return Status::kFail; return Status::kFail;
} }
struct v4l2_ctrl_h264_slice_param& v4l2_slice_param = struct v4l2_ctrl_h264_slice_params& v4l2_slice_param =
priv_->v4l2_slice_params[num_slices_++]; priv_->v4l2_slice_params[num_slices_++];
memset(&v4l2_slice_param, 0, sizeof(v4l2_slice_param)); memset(&v4l2_slice_param, 0, sizeof(v4l2_slice_param));
...@@ -338,11 +344,12 @@ H264Decoder::H264Accelerator::Status V4L2H264Accelerator::SubmitSlice( ...@@ -338,11 +344,12 @@ H264Decoder::H264Accelerator::Status V4L2H264Accelerator::SubmitSlice(
#define SET_V4L2_SPARM_FLAG_IF(cond, flag) \ #define SET_V4L2_SPARM_FLAG_IF(cond, flag) \
v4l2_slice_param.flags |= ((slice_hdr->cond) ? (flag) : 0) v4l2_slice_param.flags |= ((slice_hdr->cond) ? (flag) : 0)
SET_V4L2_SPARM_FLAG_IF(field_pic_flag, V4L2_SLICE_FLAG_FIELD_PIC); SET_V4L2_SPARM_FLAG_IF(field_pic_flag, V4L2_H264_SLICE_FLAG_FIELD_PIC);
SET_V4L2_SPARM_FLAG_IF(bottom_field_flag, V4L2_SLICE_FLAG_BOTTOM_FIELD); SET_V4L2_SPARM_FLAG_IF(bottom_field_flag, V4L2_H264_SLICE_FLAG_BOTTOM_FIELD);
SET_V4L2_SPARM_FLAG_IF(direct_spatial_mv_pred_flag, SET_V4L2_SPARM_FLAG_IF(direct_spatial_mv_pred_flag,
V4L2_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED); V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED);
SET_V4L2_SPARM_FLAG_IF(sp_for_switch_flag, V4L2_SLICE_FLAG_SP_FOR_SWITCH); SET_V4L2_SPARM_FLAG_IF(sp_for_switch_flag,
V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH);
#undef SET_V4L2_SPARM_FLAG_IF #undef SET_V4L2_SPARM_FLAG_IF
struct v4l2_h264_pred_weight_table* pred_weight_table = struct v4l2_h264_pred_weight_table* pred_weight_table =
...@@ -422,7 +429,9 @@ H264Decoder::H264Accelerator::Status V4L2H264Accelerator::SubmitDecode( ...@@ -422,7 +429,9 @@ H264Decoder::H264Accelerator::Status V4L2H264Accelerator::SubmitDecode(
H264PictureToV4L2DecodeSurface(pic.get()); H264PictureToV4L2DecodeSurface(pic.get());
priv_->v4l2_decode_param.num_slices = num_slices_; priv_->v4l2_decode_param.num_slices = num_slices_;
priv_->v4l2_decode_param.idr_pic_flag = pic->idr; if (pic->idr) {
priv_->v4l2_decode_param.flags |= 1;
}
priv_->v4l2_decode_param.top_field_order_cnt = pic->top_field_order_cnt; priv_->v4l2_decode_param.top_field_order_cnt = pic->top_field_order_cnt;
priv_->v4l2_decode_param.bottom_field_order_cnt = pic->bottom_field_order_cnt; priv_->v4l2_decode_param.bottom_field_order_cnt = pic->bottom_field_order_cnt;
...@@ -430,13 +439,13 @@ H264Decoder::H264Accelerator::Status V4L2H264Accelerator::SubmitDecode( ...@@ -430,13 +439,13 @@ H264Decoder::H264Accelerator::Status V4L2H264Accelerator::SubmitDecode(
std::vector<struct v4l2_ext_control> ctrls; std::vector<struct v4l2_ext_control> ctrls;
memset(&ctrl, 0, sizeof(ctrl)); memset(&ctrl, 0, sizeof(ctrl));
ctrl.id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAM; ctrl.id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS;
ctrl.size = sizeof(priv_->v4l2_slice_params); ctrl.size = sizeof(priv_->v4l2_slice_params);
ctrl.ptr = priv_->v4l2_slice_params; ctrl.ptr = priv_->v4l2_slice_params;
ctrls.push_back(ctrl); ctrls.push_back(ctrl);
memset(&ctrl, 0, sizeof(ctrl)); memset(&ctrl, 0, sizeof(ctrl));
ctrl.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAM; ctrl.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS;
ctrl.size = sizeof(priv_->v4l2_decode_param); ctrl.size = sizeof(priv_->v4l2_decode_param);
ctrl.ptr = &priv_->v4l2_decode_param; ctrl.ptr = &priv_->v4l2_decode_param;
ctrls.push_back(ctrl); ctrls.push_back(ctrl);
......
This diff is collapsed.
// Copyright 2019 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_V4L2_V4L2_H264_ACCELERATOR_LEGACY_H_
#define MEDIA_GPU_V4L2_V4L2_H264_ACCELERATOR_LEGACY_H_
#include <memory>
#include <vector>
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "media/gpu/h264_decoder.h"
#include "media/gpu/h264_dpb.h"
namespace media {
class V4L2Device;
class V4L2DecodeSurface;
class V4L2DecodeSurfaceHandler;
struct V4L2LegacyH264AcceleratorPrivate;
class V4L2LegacyH264Accelerator : public H264Decoder::H264Accelerator {
public:
using Status = H264Decoder::H264Accelerator::Status;
explicit V4L2LegacyH264Accelerator(V4L2DecodeSurfaceHandler* surface_handler,
V4L2Device* device);
~V4L2LegacyH264Accelerator() override;
// H264Decoder::H264Accelerator implementation.
scoped_refptr<H264Picture> CreateH264Picture() override;
Status 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,
scoped_refptr<H264Picture> pic) override;
Status SubmitSlice(const H264PPS* pps,
const H264SliceHeader* slice_hdr,
const H264Picture::Vector& ref_pic_list0,
const H264Picture::Vector& ref_pic_list1,
scoped_refptr<H264Picture> pic,
const uint8_t* data,
size_t size,
const std::vector<SubsampleEntry>& subsamples) override;
Status SubmitDecode(scoped_refptr<H264Picture> pic) override;
bool OutputPicture(scoped_refptr<H264Picture> pic) override;
void Reset() override;
private:
// Max size of reference list.
static constexpr size_t kDPBIndicesListSize = 32;
void H264PictureListToDPBIndicesList(const H264Picture::Vector& src_pic_list,
uint8_t dst_list[kDPBIndicesListSize]);
void H264DPBToV4L2DPB(
const H264DPB& dpb,
std::vector<scoped_refptr<V4L2DecodeSurface>>* ref_surfaces);
scoped_refptr<V4L2DecodeSurface> H264PictureToV4L2DecodeSurface(
H264Picture* pic);
size_t num_slices_;
V4L2DecodeSurfaceHandler* const surface_handler_;
V4L2Device* const device_;
// Contains the kernel-specific structures that we don't want to expose
// outside of the compilation unit.
const std::unique_ptr<V4L2LegacyH264AcceleratorPrivate> priv_;
DISALLOW_COPY_AND_ASSIGN(V4L2LegacyH264Accelerator);
};
} // namespace media
#endif // MEDIA_GPU_V4L2_V4L2_H264_ACCELERATOR_LEGACY_H_
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "media/gpu/macros.h" #include "media/gpu/macros.h"
#include "media/gpu/v4l2/v4l2_decode_surface.h" #include "media/gpu/v4l2/v4l2_decode_surface.h"
#include "media/gpu/v4l2/v4l2_h264_accelerator.h" #include "media/gpu/v4l2/v4l2_h264_accelerator.h"
#include "media/gpu/v4l2/v4l2_h264_accelerator_legacy.h"
#include "media/gpu/v4l2/v4l2_vp8_accelerator.h" #include "media/gpu/v4l2/v4l2_vp8_accelerator.h"
#include "media/gpu/v4l2/v4l2_vp9_accelerator.h" #include "media/gpu/v4l2/v4l2_vp9_accelerator.h"
#include "ui/gl/gl_context.h" #include "ui/gl/gl_context.h"
...@@ -274,8 +275,13 @@ bool V4L2SliceVideoDecodeAccelerator::Initialize(const Config& config, ...@@ -274,8 +275,13 @@ bool V4L2SliceVideoDecodeAccelerator::Initialize(const Config& config,
} }
if (video_profile_ >= H264PROFILE_MIN && video_profile_ <= H264PROFILE_MAX) { if (video_profile_ >= H264PROFILE_MIN && video_profile_ <= H264PROFILE_MAX) {
decoder_.reset(new H264Decoder( if (supports_requests_) {
std::make_unique<V4L2H264Accelerator>(this, device_.get()))); decoder_.reset(new H264Decoder(
std::make_unique<V4L2H264Accelerator>(this, device_.get())));
} else {
decoder_.reset(new H264Decoder(
std::make_unique<V4L2LegacyH264Accelerator>(this, device_.get())));
}
} else if (video_profile_ >= VP8PROFILE_MIN && } else if (video_profile_ >= VP8PROFILE_MIN &&
video_profile_ <= VP8PROFILE_MAX) { video_profile_ <= VP8PROFILE_MAX) {
decoder_.reset(new VP8Decoder( decoder_.reset(new VP8Decoder(
......
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