[FFmpeg-devel] [RFC 3/6] Add V4L2 request API mpeg2 hwaccel
Jonas Karlman
jonas at kwiboo.se
Mon Apr 8 23:13:04 EEST 2019
Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
configure | 3 +
libavcodec/Makefile | 1 +
libavcodec/hwaccels.h | 1 +
libavcodec/mpeg12dec.c | 6 ++
libavcodec/v4l2_request_mpeg2.c | 154 ++++++++++++++++++++++++++++++++
5 files changed, 165 insertions(+)
create mode 100644 libavcodec/v4l2_request_mpeg2.c
diff --git a/configure b/configure
index ea3945d34a..79fa5530f1 100755
--- a/configure
+++ b/configure
@@ -2919,6 +2919,8 @@ mpeg2_dxva2_hwaccel_deps="dxva2"
mpeg2_dxva2_hwaccel_select="mpeg2video_decoder"
mpeg2_nvdec_hwaccel_deps="nvdec"
mpeg2_nvdec_hwaccel_select="mpeg2video_decoder"
+mpeg2_v4l2request_hwaccel_deps="v4l2_request mpeg2_v4l2_request"
+mpeg2_v4l2request_hwaccel_select="mpeg2video_decoder"
mpeg2_vaapi_hwaccel_deps="vaapi"
mpeg2_vaapi_hwaccel_select="mpeg2video_decoder"
mpeg2_vdpau_hwaccel_deps="vdpau"
@@ -6381,6 +6383,7 @@ check_cc vp8_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP8;"
check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;"
check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
+check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2_SLICE;"
check_headers sys/videoio.h
test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 796727dde7..a26c6b38ea 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -889,6 +889,7 @@ OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL) += dxva2_mpeg2.o
OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL) += nvdec_mpeg12.o
OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec_other.o
+OBJS-$(CONFIG_MPEG2_V4L2REQUEST_HWACCEL) += v4l2_request_mpeg2.o
OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o
OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL) += vdpau_mpeg12.o
OBJS-$(CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
index 7d73da8676..ef54de2a3b 100644
--- a/libavcodec/hwaccels.h
+++ b/libavcodec/hwaccels.h
@@ -47,6 +47,7 @@ extern const AVHWAccel ff_mpeg2_d3d11va_hwaccel;
extern const AVHWAccel ff_mpeg2_d3d11va2_hwaccel;
extern const AVHWAccel ff_mpeg2_nvdec_hwaccel;
extern const AVHWAccel ff_mpeg2_dxva2_hwaccel;
+extern const AVHWAccel ff_mpeg2_v4l2request_hwaccel;
extern const AVHWAccel ff_mpeg2_vaapi_hwaccel;
extern const AVHWAccel ff_mpeg2_vdpau_hwaccel;
extern const AVHWAccel ff_mpeg2_videotoolbox_hwaccel;
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 83e537884b..305127bc94 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -1156,6 +1156,9 @@ static const enum AVPixelFormat mpeg2_hwaccel_pixfmt_list_420[] = {
#endif
#if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL
AV_PIX_FMT_VIDEOTOOLBOX,
+#endif
+#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL
+ AV_PIX_FMT_DRM_PRIME,
#endif
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NONE
@@ -2941,6 +2944,9 @@ AVCodec ff_mpeg2video_decoder = {
#endif
#if CONFIG_MPEG2_XVMC_HWACCEL
HWACCEL_XVMC(mpeg2),
+#endif
+#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL
+ HWACCEL_V4L2REQUEST(mpeg2),
#endif
NULL
},
diff --git a/libavcodec/v4l2_request_mpeg2.c b/libavcodec/v4l2_request_mpeg2.c
new file mode 100644
index 0000000000..782b9c2471
--- /dev/null
+++ b/libavcodec/v4l2_request_mpeg2.c
@@ -0,0 +1,154 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hwaccel.h"
+#include "mpegvideo.h"
+#include "v4l2_request.h"
+
+typedef struct V4L2RequestControlsMPEG2 {
+ struct v4l2_ctrl_mpeg2_slice_params slice_params;
+ struct v4l2_ctrl_mpeg2_quantization quantization;
+} V4L2RequestControlsMPEG2;
+
+static int v4l2_request_mpeg2_start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
+{
+ const MpegEncContext *s = avctx->priv_data;
+ V4L2RequestControlsMPEG2 *controls = s->current_picture_ptr->hwaccel_picture_private;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)s->current_picture_ptr->f->data[0];
+
+ controls->slice_params = (struct v4l2_ctrl_mpeg2_slice_params) {
+ .bit_size = 0,
+ .data_bit_offset = 0,
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Slice */
+ .quantiser_scale_code = s->qscale >> 1,
+
+ .sequence = {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */
+ .horizontal_size = s->width,
+ .vertical_size = s->height,
+ .vbv_buffer_size = req->output.size,
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */
+ .profile_and_level_indication = 0,
+ .progressive_sequence = s->progressive_sequence,
+ .chroma_format = s->chroma_format,
+ },
+
+ .picture = {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture header */
+ .picture_coding_type = s->pict_type,
+
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Picture coding extension */
+ .f_code[0][0] = s->mpeg_f_code[0][0],
+ .f_code[0][1] = s->mpeg_f_code[0][1],
+ .f_code[1][0] = s->mpeg_f_code[1][0],
+ .f_code[1][1] = s->mpeg_f_code[1][1],
+ .intra_dc_precision = s->intra_dc_precision,
+ .picture_structure = s->picture_structure,
+ .top_field_first = s->top_field_first,
+ .frame_pred_frame_dct = s->frame_pred_frame_dct,
+ .concealment_motion_vectors = s->concealment_motion_vectors,
+ .q_scale_type = s->q_scale_type,
+ .intra_vlc_format = s->intra_vlc_format,
+ .alternate_scan = s->alternate_scan,
+ .repeat_first_field = s->repeat_first_field,
+ .progressive_frame = s->progressive_frame,
+ },
+ };
+
+ switch (s->pict_type) {
+ case AV_PICTURE_TYPE_B:
+ controls->slice_params.backward_ref_ts = ff_v4l2_request_get_capture_timestamp(s->next_picture.f);
+ // fall-through
+ case AV_PICTURE_TYPE_P:
+ controls->slice_params.forward_ref_ts = ff_v4l2_request_get_capture_timestamp(s->last_picture.f);
+ }
+
+ controls->quantization = (struct v4l2_ctrl_mpeg2_quantization) {
+ /* ISO/IEC 13818-2, ITU-T Rec. H.262: Quant matrix extension */
+ .load_intra_quantiser_matrix = 1,
+ .load_non_intra_quantiser_matrix = 1,
+ .load_chroma_intra_quantiser_matrix = 1,
+ .load_chroma_non_intra_quantiser_matrix = 1,
+ };
+
+ for (int i = 0; i < 64; i++) {
+ int n = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+ controls->quantization.intra_quantiser_matrix[i] = s->intra_matrix[n];
+ controls->quantization.non_intra_quantiser_matrix[i] = s->inter_matrix[n];
+ controls->quantization.chroma_intra_quantiser_matrix[i] = s->chroma_intra_matrix[n];
+ controls->quantization.chroma_non_intra_quantiser_matrix[i] = s->chroma_inter_matrix[n];
+ }
+
+ return ff_v4l2_request_reset_frame(avctx, s->current_picture_ptr->f);
+}
+
+static int v4l2_request_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
+{
+ const MpegEncContext *s = avctx->priv_data;
+
+ return ff_v4l2_request_append_output_buffer(avctx, s->current_picture_ptr->f, buffer, size);
+}
+
+static int v4l2_request_mpeg2_end_frame(AVCodecContext *avctx)
+{
+ const MpegEncContext *s = avctx->priv_data;
+ V4L2RequestControlsMPEG2 *controls = s->current_picture_ptr->hwaccel_picture_private;
+ V4L2RequestDescriptor *req = (V4L2RequestDescriptor*)s->current_picture_ptr->f->data[0];
+
+ struct v4l2_ext_control control[] = {
+ {
+ .id = V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS,
+ .ptr = &controls->slice_params,
+ .size = sizeof(controls->slice_params),
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION,
+ .ptr = &controls->quantization,
+ .size = sizeof(controls->quantization),
+ },
+ };
+
+ controls->slice_params.bit_size = req->output.used * 8;
+
+ return ff_v4l2_request_decode_frame(avctx, s->current_picture_ptr->f, control, FF_ARRAY_ELEMS(control));
+}
+
+static int v4l2_request_mpeg2_init(AVCodecContext *avctx)
+{
+ return ff_v4l2_request_init(avctx, V4L2_PIX_FMT_MPEG2_SLICE, 1024 * 1024, NULL, 0);
+}
+
+const AVHWAccel ff_mpeg2_v4l2request_hwaccel = {
+ .name = "mpeg2_v4l2request",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_MPEG2VIDEO,
+ .pix_fmt = AV_PIX_FMT_DRM_PRIME,
+ .start_frame = v4l2_request_mpeg2_start_frame,
+ .decode_slice = v4l2_request_mpeg2_decode_slice,
+ .end_frame = v4l2_request_mpeg2_end_frame,
+ .frame_priv_data_size = sizeof(V4L2RequestControlsMPEG2),
+ .init = v4l2_request_mpeg2_init,
+ .uninit = ff_v4l2_request_uninit,
+ .priv_data_size = sizeof(V4L2RequestContext),
+ .frame_params = ff_v4l2_request_frame_params,
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
+};
--
2.17.1
More information about the ffmpeg-devel
mailing list