Skip to content

Commit

Permalink
cavs: support vaapi hwaccel decoding
Browse files Browse the repository at this point in the history
see intel/libva#738

Signed-off-by: jianfeng.zheng <[email protected]>
  • Loading branch information
jianfeng.zheng committed Jan 21, 2024
1 parent 3a02675 commit 4ab54ad
Show file tree
Hide file tree
Showing 7 changed files with 284 additions and 5 deletions.
14 changes: 14 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -2463,6 +2463,7 @@ HAVE_LIST="
xmllint
zlib_gzip
openvino2
va_profile_avs
"

# options emitted with CONFIG_ prefix but not available on the command line
Expand Down Expand Up @@ -3202,6 +3203,7 @@ wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel"
wmv3_nvdec_hwaccel_select="vc1_nvdec_hwaccel"
wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel"
wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel"
cavs_vaapi_hwaccel_deps="vaapi va_profile_avs VAPictureParameterBufferAVS"

# hardware-accelerated codecs
mediafoundation_deps="mftransform_h MFCreateAlignedMemoryBuffer"
Expand Down Expand Up @@ -7175,6 +7177,18 @@ if enabled vaapi; then
check_type "va/va.h va/va_enc_vp8.h" "VAEncPictureParameterBufferVP8"
check_type "va/va.h va/va_enc_vp9.h" "VAEncPictureParameterBufferVP9"
check_type "va/va.h va/va_enc_av1.h" "VAEncPictureParameterBufferAV1"

#
# Using 'VA_CHECK_VERSION' in source codes make things easy. But we have to wait
# until newly added VAProfile being distributed by VAAPI released version.
#
# Before or after that, we can use auto-detection to keep version compatibility.
# It always works.
#
disable va_profile_avs &&
test_code cc va/va.h "VAProfile p1 = VAProfileAVSJizhun, p2 = VAProfileAVSGuangdian;" &&
enable va_profile_avs
enabled va_profile_avs && check_type "va/va.h va/va_dec_avs.h" "VAPictureParameterBufferAVS"
fi

if enabled_all opencl libdrm ; then
Expand Down
1 change: 1 addition & 0 deletions libavcodec/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,7 @@ OBJS-$(CONFIG_VP9_VAAPI_HWACCEL) += vaapi_vp9.o
OBJS-$(CONFIG_VP9_VDPAU_HWACCEL) += vdpau_vp9.o
OBJS-$(CONFIG_VP9_VIDEOTOOLBOX_HWACCEL) += videotoolbox_vp9.o
OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec.o
OBJS-$(CONFIG_CAVS_VAAPI_HWACCEL) += vaapi_cavs.o

# Objects duplicated from other libraries for shared builds
SHLIBOBJS += log2_tab.o reverse.o
Expand Down
4 changes: 4 additions & 0 deletions libavcodec/cavs.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,14 @@ typedef struct AVSFrame {
AVFrame *f;
int poc;
int outputed;

AVBufferRef *hwaccel_priv_buf;
void *hwaccel_picture_private;
} AVSFrame;

typedef struct AVSContext {
AVCodecContext *avctx;
int got_pix_fmt;
BlockDSPContext bdsp;
H264ChromaContext h264chroma;
VideoDSPContext vdsp;
Expand Down
101 changes: 96 additions & 5 deletions libavcodec/cavsdec.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@
* @author Stefan Gehrer <[email protected]>
*/

#include "config_components.h"
#include "libavutil/avassert.h"
#include "libavutil/emms.h"
#include "avcodec.h"
#include "get_bits.h"
#include "golomb.h"
#include "hwaccel_internal.h"
#include "hwconfig.h"
#include "profiles.h"
#include "cavs.h"
#include "codec_internal.h"
Expand Down Expand Up @@ -1002,9 +1005,9 @@ static inline int decode_slice_header(AVSContext *h, GetBitContext *gb)
}
h->mb_weight_pred_flag = get_bits1(gb);
if (!h->avctx->hwaccel) {
av_log(h->avctx, AV_LOG_ERROR,
"weighted prediction not yet supported\n");
}
av_log(h->avctx, AV_LOG_ERROR,
"weighted prediction not yet supported\n");
}
}
}
if (h->aec_flag) {
Expand Down Expand Up @@ -1115,6 +1118,46 @@ static inline int check_for_slice(AVSContext *h)
* frame level
*
****************************************************************************/
static int hwaccel_pic(AVSContext *h)
{
int ret = 0;
int stc = -1;
const uint8_t *frm_start = align_get_bits(&h->gb);
const uint8_t *frm_end = h->gb.buffer_end;
const uint8_t *slc_start = frm_start;
const uint8_t *slc_end = frm_end;
GetBitContext gb = h->gb;
const FFHWAccel *hwaccel = ffhwaccel(h->avctx->hwaccel);

ret = hwaccel->start_frame(h->avctx, NULL, 0);
if (ret < 0)
return ret;

for (slc_start = frm_start; slc_start + 4 < frm_end; slc_start = slc_end) {
slc_end = avpriv_find_start_code(slc_start + 4, frm_end, &stc);
if (slc_end < frm_end) {
slc_end -= 4;
}

init_get_bits(&h->gb, slc_start, (slc_end - slc_start) * 8);
if (!check_for_slice(h)) {
break;
}

ret = hwaccel->decode_slice(h->avctx, slc_start, slc_end - slc_start);
if (ret < 0) {
break;
}
}

h->gb = gb;
skip_bits(&h->gb, (slc_start - frm_start) * 8);

if (ret < 0)
return ret;

return hwaccel->end_frame(h->avctx);
}

/**
* @brief remove frame out of dpb
Expand All @@ -1125,6 +1168,9 @@ static void cavs_frame_unref(AVSFrame *frame)
if (!frame->f || !frame->f->buf[0])
return;

av_buffer_unref(&frame->hwaccel_priv_buf);
frame->hwaccel_picture_private = NULL;

av_frame_unref(frame->f);
}

Expand Down Expand Up @@ -1219,6 +1265,17 @@ static int decode_pic(AVSContext *h)
if (ret < 0)
return ret;

if (h->avctx->hwaccel) {
const FFHWAccel *hwaccel = ffhwaccel(h->avctx->hwaccel);
av_assert0(!h->cur.hwaccel_picture_private);
if (hwaccel->frame_priv_data_size) {
h->cur.hwaccel_priv_buf = av_buffer_allocz(hwaccel->frame_priv_data_size);
if (!h->cur.hwaccel_priv_buf)
return AVERROR(ENOMEM);
h->cur.hwaccel_picture_private = h->cur.hwaccel_priv_buf->data;
}
}

if (!h->edge_emu_buffer) {
int alloc_size = FFALIGN(FFABS(h->cur.f->linesize[0]) + 32, 32);
h->edge_emu_buffer = av_mallocz(alloc_size * 2 * 24);
Expand Down Expand Up @@ -1247,7 +1304,9 @@ static int decode_pic(AVSContext *h)
av_log(h->avctx, AV_LOG_ERROR, "poc=%d/%d/%d, dist=%d/%d\n",
h->DPB[1].poc, h->DPB[0].poc, h->cur.poc, h->dist[0], h->dist[1]);
av_log(h->avctx, AV_LOG_ERROR, "sym_factor %d too large\n", h->sym_factor);
return AVERROR_INVALIDDATA;

if (!h->avctx->hwaccel)
return AVERROR_INVALIDDATA;
}
} else {
h->direct_den[0] = h->dist[0] ? 16384 / h->dist[0] : 0;
Expand Down Expand Up @@ -1332,7 +1391,9 @@ static int decode_pic(AVSContext *h)
}

ret = 0;
if (h->cur.f->pict_type == AV_PICTURE_TYPE_I) {
if (h->avctx->hwaccel) {
ret = hwaccel_pic(h);
} else if (h->cur.f->pict_type == AV_PICTURE_TYPE_I) {
do {
check_for_slice(h);
ret = decode_mb_i(h, 0);
Expand Down Expand Up @@ -1503,6 +1564,20 @@ static int cavs_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
return ret;
avctx->profile = h->profile;
avctx->level = h->level;
if (!h->got_pix_fmt) {
h->got_pix_fmt = 1;
ret = ff_get_format(avctx, avctx->codec->pix_fmts);
if (ret < 0)
return ret;

avctx->pix_fmt = ret;

if (h->profile == AV_PROFILE_CAVS_GUANGDIAN && !avctx->hwaccel) {
av_log(avctx, AV_LOG_ERROR, "Your platform doesn't suppport hardware"
" accelerated for CAVS Guangdian Profile decoding.\n");
return AVERROR(ENOTSUP);
}
}
break;
case PIC_I_START_CODE:
if (!h->got_keyframe) {
Expand Down Expand Up @@ -1577,6 +1652,14 @@ static int cavs_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
return (buf_ptr - avpkt->data);
}

static const enum AVPixelFormat cavs_hwaccel_pixfmt_list_420[] = {
#if CONFIG_CAVS_VAAPI_HWACCEL
AV_PIX_FMT_VAAPI,
#endif
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NONE
};

const FFCodec ff_cavs_decoder = {
.p.name = "cavs",
CODEC_LONG_NAME("Chinese AVS (Audio Video Standard) (AVS1-P2, JiZhun profile)"),
Expand All @@ -1589,4 +1672,12 @@ const FFCodec ff_cavs_decoder = {
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
.flush = cavs_flush,
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
.p.pix_fmts = cavs_hwaccel_pixfmt_list_420,
.hw_configs = (const AVCodecHWConfigInternal *const []) {
#if CONFIG_CAVS_VAAPI_HWACCEL
HWACCEL_VAAPI(cavs),
#endif
NULL
},
.p.profiles = NULL_IF_CONFIG_SMALL(ff_cavs_profiles),
};
1 change: 1 addition & 0 deletions libavcodec/hwaccels.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,6 @@ extern const struct FFHWAccel ff_wmv3_dxva2_hwaccel;
extern const struct FFHWAccel ff_wmv3_nvdec_hwaccel;
extern const struct FFHWAccel ff_wmv3_vaapi_hwaccel;
extern const struct FFHWAccel ff_wmv3_vdpau_hwaccel;
extern const struct FFHWAccel ff_cavs_vaapi_hwaccel;

#endif /* AVCODEC_HWACCELS_H */
Loading

0 comments on commit 4ab54ad

Please sign in to comment.