Skip to content

Commit 4ab54ad

Browse files
author
jianfeng.zheng
committed
cavs: support vaapi hwaccel decoding
see intel/libva#738 Signed-off-by: jianfeng.zheng <[email protected]>
1 parent 3a02675 commit 4ab54ad

File tree

7 files changed

+284
-5
lines changed

7 files changed

+284
-5
lines changed

configure

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2463,6 +2463,7 @@ HAVE_LIST="
24632463
xmllint
24642464
zlib_gzip
24652465
openvino2
2466+
va_profile_avs
24662467
"
24672468

24682469
# options emitted with CONFIG_ prefix but not available on the command line
@@ -3202,6 +3203,7 @@ wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel"
32023203
wmv3_nvdec_hwaccel_select="vc1_nvdec_hwaccel"
32033204
wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel"
32043205
wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel"
3206+
cavs_vaapi_hwaccel_deps="vaapi va_profile_avs VAPictureParameterBufferAVS"
32053207

32063208
# hardware-accelerated codecs
32073209
mediafoundation_deps="mftransform_h MFCreateAlignedMemoryBuffer"
@@ -7175,6 +7177,18 @@ if enabled vaapi; then
71757177
check_type "va/va.h va/va_enc_vp8.h" "VAEncPictureParameterBufferVP8"
71767178
check_type "va/va.h va/va_enc_vp9.h" "VAEncPictureParameterBufferVP9"
71777179
check_type "va/va.h va/va_enc_av1.h" "VAEncPictureParameterBufferAV1"
7180+
7181+
#
7182+
# Using 'VA_CHECK_VERSION' in source codes make things easy. But we have to wait
7183+
# until newly added VAProfile being distributed by VAAPI released version.
7184+
#
7185+
# Before or after that, we can use auto-detection to keep version compatibility.
7186+
# It always works.
7187+
#
7188+
disable va_profile_avs &&
7189+
test_code cc va/va.h "VAProfile p1 = VAProfileAVSJizhun, p2 = VAProfileAVSGuangdian;" &&
7190+
enable va_profile_avs
7191+
enabled va_profile_avs && check_type "va/va.h va/va_dec_avs.h" "VAPictureParameterBufferAVS"
71787192
fi
71797193

71807194
if enabled_all opencl libdrm ; then

libavcodec/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,7 @@ OBJS-$(CONFIG_VP9_VAAPI_HWACCEL) += vaapi_vp9.o
10551055
OBJS-$(CONFIG_VP9_VDPAU_HWACCEL) += vdpau_vp9.o
10561056
OBJS-$(CONFIG_VP9_VIDEOTOOLBOX_HWACCEL) += videotoolbox_vp9.o
10571057
OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec.o
1058+
OBJS-$(CONFIG_CAVS_VAAPI_HWACCEL) += vaapi_cavs.o
10581059

10591060
# Objects duplicated from other libraries for shared builds
10601061
SHLIBOBJS += log2_tab.o reverse.o

libavcodec/cavs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,14 @@ typedef struct AVSFrame {
167167
AVFrame *f;
168168
int poc;
169169
int outputed;
170+
171+
AVBufferRef *hwaccel_priv_buf;
172+
void *hwaccel_picture_private;
170173
} AVSFrame;
171174

172175
typedef struct AVSContext {
173176
AVCodecContext *avctx;
177+
int got_pix_fmt;
174178
BlockDSPContext bdsp;
175179
H264ChromaContext h264chroma;
176180
VideoDSPContext vdsp;

libavcodec/cavsdec.c

Lines changed: 96 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,14 @@
2525
* @author Stefan Gehrer <[email protected]>
2626
*/
2727

28+
#include "config_components.h"
2829
#include "libavutil/avassert.h"
2930
#include "libavutil/emms.h"
3031
#include "avcodec.h"
3132
#include "get_bits.h"
3233
#include "golomb.h"
34+
#include "hwaccel_internal.h"
35+
#include "hwconfig.h"
3336
#include "profiles.h"
3437
#include "cavs.h"
3538
#include "codec_internal.h"
@@ -1002,9 +1005,9 @@ static inline int decode_slice_header(AVSContext *h, GetBitContext *gb)
10021005
}
10031006
h->mb_weight_pred_flag = get_bits1(gb);
10041007
if (!h->avctx->hwaccel) {
1005-
av_log(h->avctx, AV_LOG_ERROR,
1006-
"weighted prediction not yet supported\n");
1007-
}
1008+
av_log(h->avctx, AV_LOG_ERROR,
1009+
"weighted prediction not yet supported\n");
1010+
}
10081011
}
10091012
}
10101013
if (h->aec_flag) {
@@ -1115,6 +1118,46 @@ static inline int check_for_slice(AVSContext *h)
11151118
* frame level
11161119
*
11171120
****************************************************************************/
1121+
static int hwaccel_pic(AVSContext *h)
1122+
{
1123+
int ret = 0;
1124+
int stc = -1;
1125+
const uint8_t *frm_start = align_get_bits(&h->gb);
1126+
const uint8_t *frm_end = h->gb.buffer_end;
1127+
const uint8_t *slc_start = frm_start;
1128+
const uint8_t *slc_end = frm_end;
1129+
GetBitContext gb = h->gb;
1130+
const FFHWAccel *hwaccel = ffhwaccel(h->avctx->hwaccel);
1131+
1132+
ret = hwaccel->start_frame(h->avctx, NULL, 0);
1133+
if (ret < 0)
1134+
return ret;
1135+
1136+
for (slc_start = frm_start; slc_start + 4 < frm_end; slc_start = slc_end) {
1137+
slc_end = avpriv_find_start_code(slc_start + 4, frm_end, &stc);
1138+
if (slc_end < frm_end) {
1139+
slc_end -= 4;
1140+
}
1141+
1142+
init_get_bits(&h->gb, slc_start, (slc_end - slc_start) * 8);
1143+
if (!check_for_slice(h)) {
1144+
break;
1145+
}
1146+
1147+
ret = hwaccel->decode_slice(h->avctx, slc_start, slc_end - slc_start);
1148+
if (ret < 0) {
1149+
break;
1150+
}
1151+
}
1152+
1153+
h->gb = gb;
1154+
skip_bits(&h->gb, (slc_start - frm_start) * 8);
1155+
1156+
if (ret < 0)
1157+
return ret;
1158+
1159+
return hwaccel->end_frame(h->avctx);
1160+
}
11181161

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

1171+
av_buffer_unref(&frame->hwaccel_priv_buf);
1172+
frame->hwaccel_picture_private = NULL;
1173+
11281174
av_frame_unref(frame->f);
11291175
}
11301176

@@ -1219,6 +1265,17 @@ static int decode_pic(AVSContext *h)
12191265
if (ret < 0)
12201266
return ret;
12211267

1268+
if (h->avctx->hwaccel) {
1269+
const FFHWAccel *hwaccel = ffhwaccel(h->avctx->hwaccel);
1270+
av_assert0(!h->cur.hwaccel_picture_private);
1271+
if (hwaccel->frame_priv_data_size) {
1272+
h->cur.hwaccel_priv_buf = av_buffer_allocz(hwaccel->frame_priv_data_size);
1273+
if (!h->cur.hwaccel_priv_buf)
1274+
return AVERROR(ENOMEM);
1275+
h->cur.hwaccel_picture_private = h->cur.hwaccel_priv_buf->data;
1276+
}
1277+
}
1278+
12221279
if (!h->edge_emu_buffer) {
12231280
int alloc_size = FFALIGN(FFABS(h->cur.f->linesize[0]) + 32, 32);
12241281
h->edge_emu_buffer = av_mallocz(alloc_size * 2 * 24);
@@ -1247,7 +1304,9 @@ static int decode_pic(AVSContext *h)
12471304
av_log(h->avctx, AV_LOG_ERROR, "poc=%d/%d/%d, dist=%d/%d\n",
12481305
h->DPB[1].poc, h->DPB[0].poc, h->cur.poc, h->dist[0], h->dist[1]);
12491306
av_log(h->avctx, AV_LOG_ERROR, "sym_factor %d too large\n", h->sym_factor);
1250-
return AVERROR_INVALIDDATA;
1307+
1308+
if (!h->avctx->hwaccel)
1309+
return AVERROR_INVALIDDATA;
12511310
}
12521311
} else {
12531312
h->direct_den[0] = h->dist[0] ? 16384 / h->dist[0] : 0;
@@ -1332,7 +1391,9 @@ static int decode_pic(AVSContext *h)
13321391
}
13331392

13341393
ret = 0;
1335-
if (h->cur.f->pict_type == AV_PICTURE_TYPE_I) {
1394+
if (h->avctx->hwaccel) {
1395+
ret = hwaccel_pic(h);
1396+
} else if (h->cur.f->pict_type == AV_PICTURE_TYPE_I) {
13361397
do {
13371398
check_for_slice(h);
13381399
ret = decode_mb_i(h, 0);
@@ -1503,6 +1564,20 @@ static int cavs_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
15031564
return ret;
15041565
avctx->profile = h->profile;
15051566
avctx->level = h->level;
1567+
if (!h->got_pix_fmt) {
1568+
h->got_pix_fmt = 1;
1569+
ret = ff_get_format(avctx, avctx->codec->pix_fmts);
1570+
if (ret < 0)
1571+
return ret;
1572+
1573+
avctx->pix_fmt = ret;
1574+
1575+
if (h->profile == AV_PROFILE_CAVS_GUANGDIAN && !avctx->hwaccel) {
1576+
av_log(avctx, AV_LOG_ERROR, "Your platform doesn't suppport hardware"
1577+
" accelerated for CAVS Guangdian Profile decoding.\n");
1578+
return AVERROR(ENOTSUP);
1579+
}
1580+
}
15061581
break;
15071582
case PIC_I_START_CODE:
15081583
if (!h->got_keyframe) {
@@ -1577,6 +1652,14 @@ static int cavs_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
15771652
return (buf_ptr - avpkt->data);
15781653
}
15791654

1655+
static const enum AVPixelFormat cavs_hwaccel_pixfmt_list_420[] = {
1656+
#if CONFIG_CAVS_VAAPI_HWACCEL
1657+
AV_PIX_FMT_VAAPI,
1658+
#endif
1659+
AV_PIX_FMT_YUV420P,
1660+
AV_PIX_FMT_NONE
1661+
};
1662+
15801663
const FFCodec ff_cavs_decoder = {
15811664
.p.name = "cavs",
15821665
CODEC_LONG_NAME("Chinese AVS (Audio Video Standard) (AVS1-P2, JiZhun profile)"),
@@ -1589,4 +1672,12 @@ const FFCodec ff_cavs_decoder = {
15891672
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
15901673
.flush = cavs_flush,
15911674
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
1675+
.p.pix_fmts = cavs_hwaccel_pixfmt_list_420,
1676+
.hw_configs = (const AVCodecHWConfigInternal *const []) {
1677+
#if CONFIG_CAVS_VAAPI_HWACCEL
1678+
HWACCEL_VAAPI(cavs),
1679+
#endif
1680+
NULL
1681+
},
1682+
.p.profiles = NULL_IF_CONFIG_SMALL(ff_cavs_profiles),
15921683
};

libavcodec/hwaccels.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,5 +89,6 @@ extern const struct FFHWAccel ff_wmv3_dxva2_hwaccel;
8989
extern const struct FFHWAccel ff_wmv3_nvdec_hwaccel;
9090
extern const struct FFHWAccel ff_wmv3_vaapi_hwaccel;
9191
extern const struct FFHWAccel ff_wmv3_vdpau_hwaccel;
92+
extern const struct FFHWAccel ff_cavs_vaapi_hwaccel;
9293

9394
#endif /* AVCODEC_HWACCELS_H */

0 commit comments

Comments
 (0)