Commit 3c39a16d authored by Jernej Skrabec's avatar Jernej Skrabec Committed by Mauro Carvalho Chehab
Browse files

media: cedrus: Add support for VP8 decoding



VP8 in Cedrus shares same engine as H264.

Note that it seems necessary to call bitstream parsing functions,
to parse frame header, otherwise decoded image is garbage. This is
contrary to what is driver supposed to do. However, values are not
really used, so this might be acceptable. It's possible that bitstream
parsing functions set some internal VPU state, which is later necessary
for proper decoding. Biggest suspect is "VP8 probs update" trigger.

Signed-off-by: default avatarJernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: default avatarEmmanuel Gil Peyrot <linkmauve@linkmauve.fr>
Reviewed-by: default avatarEzequiel Garcia <ezequiel@collabora.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent b4b3564c
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -2,4 +2,5 @@
obj-$(CONFIG_VIDEO_SUNXI_CEDRUS) += sunxi-cedrus.o

sunxi-cedrus-y = cedrus.o cedrus_video.o cedrus_hw.o cedrus_dec.o \
		 cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o
		 cedrus_mpeg2.o cedrus_h264.o cedrus_h265.o \
		 cedrus_vp8.o
+8 −0
Original line number Diff line number Diff line
@@ -142,6 +142,13 @@ static const struct cedrus_control cedrus_controls[] = {
		.codec		= CEDRUS_CODEC_H265,
		.required	= false,
	},
	{
		.cfg = {
			.id		= V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER,
		},
		.codec		= CEDRUS_CODEC_VP8,
		.required	= true,
	},
};

#define CEDRUS_CONTROLS_COUNT	ARRAY_SIZE(cedrus_controls)
@@ -393,6 +400,7 @@ static int cedrus_probe(struct platform_device *pdev)
	dev->dec_ops[CEDRUS_CODEC_MPEG2] = &cedrus_dec_ops_mpeg2;
	dev->dec_ops[CEDRUS_CODEC_H264] = &cedrus_dec_ops_h264;
	dev->dec_ops[CEDRUS_CODEC_H265] = &cedrus_dec_ops_h265;
	dev->dec_ops[CEDRUS_CODEC_VP8] = &cedrus_dec_ops_vp8;

	mutex_init(&dev->dev_mutex);

+24 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-contig.h>

#include <linux/iopoll.h>
#include <linux/platform_device.h>

#define CEDRUS_NAME			"cedrus"
@@ -37,6 +38,7 @@ enum cedrus_codec {
	CEDRUS_CODEC_MPEG2,
	CEDRUS_CODEC_H264,
	CEDRUS_CODEC_H265,
	CEDRUS_CODEC_VP8,
	CEDRUS_CODEC_LAST,
};

@@ -78,6 +80,10 @@ struct cedrus_h265_run {
	const struct v4l2_ctrl_hevc_slice_params	*slice_params;
};

struct cedrus_vp8_run {
	const struct v4l2_ctrl_vp8_frame_header		*frame_params;
};

struct cedrus_run {
	struct vb2_v4l2_buffer	*src;
	struct vb2_v4l2_buffer	*dst;
@@ -86,6 +92,7 @@ struct cedrus_run {
		struct cedrus_h264_run	h264;
		struct cedrus_mpeg2_run	mpeg2;
		struct cedrus_h265_run	h265;
		struct cedrus_vp8_run	vp8;
	};
};

@@ -137,6 +144,14 @@ struct cedrus_ctx {
			void		*neighbor_info_buf;
			dma_addr_t	neighbor_info_buf_addr;
		} h265;
		struct {
			unsigned int	last_frame_p_type;
			unsigned int	last_filter_type;
			unsigned int	last_sharpness_level;

			u8		*entropy_probs_buf;
			dma_addr_t	entropy_probs_buf_dma;
		} vp8;
	} codec;
};

@@ -183,6 +198,7 @@ struct cedrus_dev {
extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2;
extern struct cedrus_dec_ops cedrus_dec_ops_h264;
extern struct cedrus_dec_ops cedrus_dec_ops_h265;
extern struct cedrus_dec_ops cedrus_dec_ops_vp8;

static inline void cedrus_write(struct cedrus_dev *dev, u32 reg, u32 val)
{
@@ -194,6 +210,14 @@ static inline u32 cedrus_read(struct cedrus_dev *dev, u32 reg)
	return readl(dev->base + reg);
}

static inline u32 cedrus_wait_for(struct cedrus_dev *dev, u32 reg, u32 flag)
{
	u32 value;

	return readl_poll_timeout_atomic(dev->base + reg, value,
			(value & flag) == 0, 10, 1000);
}

static inline dma_addr_t cedrus_buf_addr(struct vb2_buffer *buf,
					 struct v4l2_pix_format *pix_fmt,
					 unsigned int plane)
+5 −0
Original line number Diff line number Diff line
@@ -70,6 +70,11 @@ void cedrus_device_run(void *priv)
			V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS);
		break;

	case V4L2_PIX_FMT_VP8_FRAME:
		run.vp8.frame_params = cedrus_find_control_data(ctx,
			V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER);
		break;

	default:
		break;
	}
+2 −0
Original line number Diff line number Diff line
@@ -47,7 +47,9 @@ int cedrus_engine_enable(struct cedrus_ctx *ctx, enum cedrus_codec codec)
		reg |= VE_MODE_DEC_MPEG;
		break;

	/* H.264 and VP8 both use the same decoding mode bit. */
	case CEDRUS_CODEC_H264:
	case CEDRUS_CODEC_VP8:
		reg |= VE_MODE_DEC_H264;
		break;

Loading