@ -20,6 +20,7 @@
# include <string.h>
# include "libavutil/avassert.h"
# include "libavutil/common.h"
# include "libavutil/log.h"
# include "libavutil/pixdesc.h"
@ -887,6 +888,122 @@ fail:
return err ;
}
static av_cold int vaapi_encode_check_config ( AVCodecContext * avctx )
{
VAAPIEncodeContext * ctx = avctx - > priv_data ;
VAStatus vas ;
int i , n , err ;
VAProfile * profiles = NULL ;
VAEntrypoint * entrypoints = NULL ;
VAConfigAttrib attr [ ] = {
{ VAConfigAttribRateControl } ,
{ VAConfigAttribEncMaxRefFrames } ,
} ;
n = vaMaxNumProfiles ( ctx - > hwctx - > display ) ;
profiles = av_malloc_array ( n , sizeof ( VAProfile ) ) ;
if ( ! profiles ) {
err = AVERROR ( ENOMEM ) ;
goto fail ;
}
vas = vaQueryConfigProfiles ( ctx - > hwctx - > display , profiles , & n ) ;
if ( vas ! = VA_STATUS_SUCCESS ) {
av_log ( ctx , AV_LOG_ERROR , " Failed to query profiles: %d (%s). \n " ,
vas , vaErrorStr ( vas ) ) ;
err = AVERROR ( ENOSYS ) ;
goto fail ;
}
for ( i = 0 ; i < n ; i + + ) {
if ( profiles [ i ] = = ctx - > va_profile )
break ;
}
if ( i > = n ) {
av_log ( ctx , AV_LOG_ERROR , " Encoding profile not found (%d). \n " ,
ctx - > va_profile ) ;
err = AVERROR ( ENOSYS ) ;
goto fail ;
}
n = vaMaxNumEntrypoints ( ctx - > hwctx - > display ) ;
entrypoints = av_malloc_array ( n , sizeof ( VAEntrypoint ) ) ;
if ( ! entrypoints ) {
err = AVERROR ( ENOMEM ) ;
goto fail ;
}
vas = vaQueryConfigEntrypoints ( ctx - > hwctx - > display , ctx - > va_profile ,
entrypoints , & n ) ;
if ( vas ! = VA_STATUS_SUCCESS ) {
av_log ( ctx , AV_LOG_ERROR , " Failed to query entrypoints for "
" profile %u: %d (%s). \n " , ctx - > va_profile ,
vas , vaErrorStr ( vas ) ) ;
err = AVERROR ( ENOSYS ) ;
goto fail ;
}
for ( i = 0 ; i < n ; i + + ) {
if ( entrypoints [ i ] = = ctx - > va_entrypoint )
break ;
}
if ( i > = n ) {
av_log ( ctx , AV_LOG_ERROR , " Encoding entrypoint not found "
" (%d / %d). \n " , ctx - > va_profile , ctx - > va_entrypoint ) ;
err = AVERROR ( ENOSYS ) ;
goto fail ;
}
vas = vaGetConfigAttributes ( ctx - > hwctx - > display ,
ctx - > va_profile , ctx - > va_entrypoint ,
attr , FF_ARRAY_ELEMS ( attr ) ) ;
if ( vas ! = VA_STATUS_SUCCESS ) {
av_log ( avctx , AV_LOG_ERROR , " Failed to fetch config "
" attributes: %d (%s). \n " , vas , vaErrorStr ( vas ) ) ;
return AVERROR ( EINVAL ) ;
}
for ( i = 0 ; i < FF_ARRAY_ELEMS ( attr ) ; i + + ) {
if ( attr [ i ] . value = = VA_ATTRIB_NOT_SUPPORTED ) {
// Unfortunately we have to treat this as "don't know" and hope
// for the best, because the Intel MJPEG encoder returns this
// for all the interesting attributes.
continue ;
}
switch ( attr [ i ] . type ) {
case VAConfigAttribRateControl :
if ( ! ( ctx - > va_rc_mode & attr [ i ] . value ) ) {
av_log ( avctx , AV_LOG_ERROR , " Rate control mode is not "
" supported: %x \n " , attr [ i ] . value ) ;
err = AVERROR ( EINVAL ) ;
goto fail ;
}
break ;
case VAConfigAttribEncMaxRefFrames :
{
unsigned int ref_l0 = attr [ i ] . value & 0xffff ;
unsigned int ref_l1 = ( attr [ i ] . value > > 16 ) & 0xffff ;
if ( avctx - > gop_size > 1 & & ref_l0 < 1 ) {
av_log ( avctx , AV_LOG_ERROR , " P frames are not "
" supported (%x). \n " , attr [ i ] . value ) ;
err = AVERROR ( EINVAL ) ;
goto fail ;
}
if ( avctx - > max_b_frames > 0 & & ref_l1 < 1 ) {
av_log ( avctx , AV_LOG_ERROR , " B frames are not "
" supported (%x). \n " , attr [ i ] . value ) ;
err = AVERROR ( EINVAL ) ;
goto fail ;
}
}
break ;
}
}
err = 0 ;
fail :
av_freep ( & profiles ) ;
av_freep ( & entrypoints ) ;
return err ;
}
av_cold int ff_vaapi_encode_init ( AVCodecContext * avctx ,
const VAAPIEncodeType * type )
{
@ -907,6 +1024,9 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx,
ctx - > codec = type ;
ctx - > codec_options = ctx - > codec_options_data ;
ctx - > va_config = VA_INVALID_ID ;
ctx - > va_context = VA_INVALID_ID ;
ctx - > priv_data = av_mallocz ( type - > priv_data_size ) ;
if ( ! ctx - > priv_data ) {
err = AVERROR ( ENOMEM ) ;
@ -932,6 +1052,10 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx,
if ( err < 0 )
goto fail ;
err = vaapi_encode_check_config ( avctx ) ;
if ( err < 0 )
goto fail ;
vas = vaCreateConfig ( ctx - > hwctx - > display ,
ctx - > va_profile , ctx - > va_entrypoint ,
ctx - > config_attributes , ctx - > nb_config_attributes ,
@ -1088,11 +1212,15 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx)
vaapi_encode_free ( avctx , pic ) ;
}
if ( ctx - > va_context ! = VA_INVALID_ID )
if ( ctx - > va_context ! = VA_INVALID_ID ) {
vaDestroyContext ( ctx - > hwctx - > display , ctx - > va_context ) ;
ctx - > va_context = VA_INVALID_ID ;
}
if ( ctx - > va_config ! = VA_INVALID_ID )
if ( ctx - > va_config ! = VA_INVALID_ID ) {
vaDestroyConfig ( ctx - > hwctx - > display , ctx - > va_config ) ;
ctx - > va_config = VA_INVALID_ID ;
}
if ( ctx - > codec - > close )
ctx - > codec - > close ( avctx ) ;