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+
15801663const 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};
0 commit comments