avcodec: Add V4L2 Request API mpeg2 hwaccel
Add a V4L2 Request API hwaccel for MPEG2. Support for MPEG2 is enabled when Linux kernel headers declare the control id V4L2_CID_STATELESS_MPEG2_SEQUENCE, added in v5.14. This also change v4l2_request hwaccel to use autodetect in configure. Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
This commit is contained in:
parent
49cbf00a3a
commit
969a4e8c36
5 changed files with 197 additions and 2 deletions
7
configure
vendored
7
configure
vendored
|
|
@ -367,7 +367,7 @@ External library support:
|
|||
--enable-omx-rpi enable OpenMAX IL code for Raspberry Pi [no]
|
||||
--enable-rkmpp enable Rockchip Media Process Platform code [no]
|
||||
--disable-v4l2-m2m disable V4L2 mem2mem code [autodetect]
|
||||
--enable-v4l2-request enable V4L2 Request API code [no]
|
||||
--disable-v4l2-request disable V4L2 Request API code [autodetect]
|
||||
--disable-vaapi disable Video Acceleration API (mainly Unix/Intel) code [autodetect]
|
||||
--disable-vdpau disable Nvidia Video Decode and Presentation API for Unix code [autodetect]
|
||||
--disable-videotoolbox disable VideoToolbox code [autodetect]
|
||||
|
|
@ -2068,6 +2068,7 @@ HWACCEL_AUTODETECT_LIBRARY_LIST="
|
|||
videotoolbox
|
||||
vulkan
|
||||
v4l2_m2m
|
||||
v4l2_request
|
||||
"
|
||||
|
||||
# catchall list of things that require external libs to link
|
||||
|
|
@ -2089,7 +2090,6 @@ HWACCEL_LIBRARY_LIST="
|
|||
mmal
|
||||
omx
|
||||
opencl
|
||||
v4l2_request
|
||||
"
|
||||
|
||||
DOCUMENT_LIST="
|
||||
|
|
@ -3339,6 +3339,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"
|
||||
|
|
@ -7478,6 +7480,7 @@ if enabled v4l2_m2m; then
|
|||
fi
|
||||
|
||||
if enabled v4l2_request; then
|
||||
check_cc mpeg2_v4l2_request linux/videodev2.h "int i = V4L2_CID_STATELESS_MPEG2_SEQUENCE"
|
||||
check_cc v4l2_m2m_hold_capture_buf linux/videodev2.h "int i = V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF"
|
||||
check_func_headers "linux/media.h linux/videodev2.h" v4l2_timeval_to_ns
|
||||
check_pkg_config libudev libudev libudev.h udev_new
|
||||
|
|
|
|||
|
|
@ -1084,6 +1084,7 @@ OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
|
|||
OBJS-$(CONFIG_MPEG2_D3D12VA_HWACCEL) += dxva2_mpeg2.o d3d12va_mpeg2.o
|
||||
OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL) += nvdec_mpeg12.o
|
||||
OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec.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
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ extern const struct FFHWAccel ff_mpeg2_d3d11va2_hwaccel;
|
|||
extern const struct FFHWAccel ff_mpeg2_d3d12va_hwaccel;
|
||||
extern const struct FFHWAccel ff_mpeg2_dxva2_hwaccel;
|
||||
extern const struct FFHWAccel ff_mpeg2_nvdec_hwaccel;
|
||||
extern const struct FFHWAccel ff_mpeg2_v4l2request_hwaccel;
|
||||
extern const struct FFHWAccel ff_mpeg2_vaapi_hwaccel;
|
||||
extern const struct FFHWAccel ff_mpeg2_vdpau_hwaccel;
|
||||
extern const struct FFHWAccel ff_mpeg2_videotoolbox_hwaccel;
|
||||
|
|
|
|||
|
|
@ -821,6 +821,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
|
||||
|
|
@ -2736,6 +2739,9 @@ const FFCodec ff_mpeg2video_decoder = {
|
|||
#endif
|
||||
#if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL
|
||||
HWACCEL_VIDEOTOOLBOX(mpeg2),
|
||||
#endif
|
||||
#if CONFIG_MPEG2_V4L2REQUEST_HWACCEL
|
||||
HWACCEL_V4L2REQUEST(mpeg2),
|
||||
#endif
|
||||
NULL
|
||||
},
|
||||
|
|
|
|||
184
libavcodec/v4l2_request_mpeg2.c
Normal file
184
libavcodec/v4l2_request_mpeg2.c
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* 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 "config.h"
|
||||
|
||||
#include "hwaccel_internal.h"
|
||||
#include "hwconfig.h"
|
||||
#include "mathops.h"
|
||||
#include "mpegvideo.h"
|
||||
#include "v4l2_request.h"
|
||||
|
||||
typedef struct V4L2RequestControlsMPEG2 {
|
||||
V4L2RequestPictureContext pic;
|
||||
struct v4l2_ctrl_mpeg2_sequence sequence;
|
||||
struct v4l2_ctrl_mpeg2_picture picture;
|
||||
struct v4l2_ctrl_mpeg2_quantisation quantisation;
|
||||
} V4L2RequestControlsMPEG2;
|
||||
|
||||
static int v4l2_request_mpeg2_start_frame(AVCodecContext *avctx,
|
||||
av_unused const AVBufferRef *buf_ref,
|
||||
av_unused const uint8_t *buffer,
|
||||
av_unused uint32_t size)
|
||||
{
|
||||
const MpegEncContext *s = avctx->priv_data;
|
||||
V4L2RequestControlsMPEG2 *controls = s->cur_pic.ptr->hwaccel_picture_private;
|
||||
int ret;
|
||||
|
||||
ret = ff_v4l2_request_start_frame(avctx, &controls->pic, s->cur_pic.ptr->f);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
controls->sequence = (struct v4l2_ctrl_mpeg2_sequence) {
|
||||
/* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence header */
|
||||
.horizontal_size = s->width,
|
||||
.vertical_size = s->height,
|
||||
.vbv_buffer_size = controls->pic.output->size,
|
||||
|
||||
/* ISO/IEC 13818-2, ITU-T Rec. H.262: Sequence extension */
|
||||
.profile_and_level_indication = 0,
|
||||
.chroma_format = s->chroma_format,
|
||||
};
|
||||
|
||||
if (s->progressive_sequence)
|
||||
controls->sequence.flags |= V4L2_MPEG2_SEQ_FLAG_PROGRESSIVE;
|
||||
|
||||
controls->picture = (struct v4l2_ctrl_mpeg2_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],
|
||||
.picture_structure = s->picture_structure,
|
||||
.intra_dc_precision = s->intra_dc_precision,
|
||||
};
|
||||
|
||||
if (s->top_field_first)
|
||||
controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_TOP_FIELD_FIRST;
|
||||
|
||||
if (s->frame_pred_frame_dct)
|
||||
controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_FRAME_PRED_DCT;
|
||||
|
||||
if (s->concealment_motion_vectors)
|
||||
controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_CONCEALMENT_MV;
|
||||
|
||||
if (s->intra_vlc_format)
|
||||
controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_INTRA_VLC;
|
||||
|
||||
if (s->q_scale_type)
|
||||
controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_Q_SCALE_TYPE;
|
||||
|
||||
if (s->alternate_scan)
|
||||
controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_ALT_SCAN;
|
||||
|
||||
if (s->repeat_first_field)
|
||||
controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_REPEAT_FIRST;
|
||||
|
||||
if (s->progressive_frame)
|
||||
controls->picture.flags |= V4L2_MPEG2_PIC_FLAG_PROGRESSIVE;
|
||||
|
||||
switch (s->pict_type) {
|
||||
case AV_PICTURE_TYPE_B:
|
||||
if (s->next_pic.ptr)
|
||||
controls->picture.backward_ref_ts =
|
||||
ff_v4l2_request_get_capture_timestamp(s->next_pic.ptr->f);
|
||||
// fall-through
|
||||
case AV_PICTURE_TYPE_P:
|
||||
if (s->last_pic.ptr)
|
||||
controls->picture.forward_ref_ts =
|
||||
ff_v4l2_request_get_capture_timestamp(s->last_pic.ptr->f);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 64; i++) {
|
||||
int n = s->idsp.idct_permutation[ff_zigzag_direct[i]];
|
||||
controls->quantisation.intra_quantiser_matrix[i] = s->intra_matrix[n];
|
||||
controls->quantisation.non_intra_quantiser_matrix[i] = s->inter_matrix[n];
|
||||
controls->quantisation.chroma_intra_quantiser_matrix[i] = s->chroma_intra_matrix[n];
|
||||
controls->quantisation.chroma_non_intra_quantiser_matrix[i] = s->chroma_inter_matrix[n];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int v4l2_request_mpeg2_decode_slice(AVCodecContext *avctx,
|
||||
const uint8_t *buffer, uint32_t size)
|
||||
{
|
||||
const MpegEncContext *s = avctx->priv_data;
|
||||
V4L2RequestControlsMPEG2 *controls = s->cur_pic.ptr->hwaccel_picture_private;
|
||||
|
||||
return ff_v4l2_request_append_output(avctx, &controls->pic, buffer, size);
|
||||
}
|
||||
|
||||
static int v4l2_request_mpeg2_end_frame(AVCodecContext *avctx)
|
||||
{
|
||||
const MpegEncContext *s = avctx->priv_data;
|
||||
V4L2RequestControlsMPEG2 *controls = s->cur_pic.ptr->hwaccel_picture_private;
|
||||
|
||||
struct v4l2_ext_control control[] = {
|
||||
{
|
||||
.id = V4L2_CID_STATELESS_MPEG2_SEQUENCE,
|
||||
.ptr = &controls->sequence,
|
||||
.size = sizeof(controls->sequence),
|
||||
},
|
||||
{
|
||||
.id = V4L2_CID_STATELESS_MPEG2_PICTURE,
|
||||
.ptr = &controls->picture,
|
||||
.size = sizeof(controls->picture),
|
||||
},
|
||||
{
|
||||
.id = V4L2_CID_STATELESS_MPEG2_QUANTISATION,
|
||||
.ptr = &controls->quantisation,
|
||||
.size = sizeof(controls->quantisation),
|
||||
},
|
||||
};
|
||||
|
||||
return ff_v4l2_request_decode_frame(avctx, &controls->pic,
|
||||
control, FF_ARRAY_ELEMS(control));
|
||||
}
|
||||
|
||||
static int v4l2_request_mpeg2_init(AVCodecContext *avctx)
|
||||
{
|
||||
return ff_v4l2_request_init(avctx, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
static int v4l2_request_mpeg2_frame_params(AVCodecContext *avctx,
|
||||
AVBufferRef *hw_frames_ctx)
|
||||
{
|
||||
return ff_v4l2_request_frame_params(avctx, hw_frames_ctx,
|
||||
V4L2_PIX_FMT_MPEG2_SLICE, 8);
|
||||
}
|
||||
|
||||
const FFHWAccel ff_mpeg2_v4l2request_hwaccel = {
|
||||
.p.name = "mpeg2_v4l2request",
|
||||
.p.type = AVMEDIA_TYPE_VIDEO,
|
||||
.p.id = AV_CODEC_ID_MPEG2VIDEO,
|
||||
.p.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,
|
||||
.flush = ff_v4l2_request_flush,
|
||||
.frame_priv_data_size = sizeof(V4L2RequestControlsMPEG2),
|
||||
.init = v4l2_request_mpeg2_init,
|
||||
.uninit = ff_v4l2_request_uninit,
|
||||
.priv_data_size = sizeof(V4L2RequestContext),
|
||||
.frame_params = v4l2_request_mpeg2_frame_params,
|
||||
.caps_internal = HWACCEL_CAP_ASYNC_SAFE,
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue