@ -27,6 +27,7 @@
# include <x265.h>
# include <float.h>
# include "libavutil/avassert.h"
# include "libavutil/internal.h"
# include "libavutil/common.h"
# include "libavutil/opt.h"
@ -39,6 +40,12 @@
# include "atsc_a53.h"
# include "sei.h"
typedef struct ReorderedData {
int64_t reordered_opaque ;
int in_use ;
} ReorderedData ;
typedef struct libx265Context {
const AVClass * class ;
@ -59,6 +66,9 @@ typedef struct libx265Context {
int udu_sei ;
int a53_cc ;
ReorderedData * rd ;
int nb_rd ;
/**
* If the encoder does not support ROI then warn the first time we
* encounter a frame with ROI side data .
@ -81,6 +91,40 @@ static int is_keyframe(NalUnitType naltype)
}
}
static int rd_get ( libx265Context * ctx )
{
const int add = 16 ;
ReorderedData * tmp ;
int idx ;
for ( int i = 0 ; i < ctx - > nb_rd ; i + + )
if ( ! ctx - > rd [ i ] . in_use ) {
ctx - > rd [ i ] . in_use = 1 ;
return i ;
}
tmp = av_realloc_array ( ctx - > rd , ctx - > nb_rd + add , sizeof ( * ctx - > rd ) ) ;
if ( ! tmp )
return AVERROR ( ENOMEM ) ;
memset ( tmp + ctx - > nb_rd , 0 , sizeof ( * tmp ) * add ) ;
ctx - > rd = tmp ;
ctx - > nb_rd + = add ;
idx = ctx - > nb_rd - add ;
ctx - > rd [ idx ] . in_use = 1 ;
return idx ;
}
static void rd_release ( libx265Context * ctx , int idx )
{
av_assert0 ( idx > = 0 & & idx < ctx - > nb_rd ) ;
memset ( & ctx - > rd [ idx ] , 0 , sizeof ( ctx - > rd [ idx ] ) ) ;
}
static av_cold int libx265_encode_close ( AVCodecContext * avctx )
{
libx265Context * ctx = avctx - > priv_data ;
@ -88,6 +132,8 @@ static av_cold int libx265_encode_close(AVCodecContext *avctx)
ctx - > api - > param_free ( ctx - > params ) ;
av_freep ( & ctx - > sei_data ) ;
av_freep ( & ctx - > rd ) ;
if ( ctx - > encoder )
ctx - > api - > encoder_close ( ctx - > encoder ) ;
@ -499,12 +545,18 @@ static av_cold int libx265_encode_set_roi(libx265Context *ctx, const AVFrame *fr
return 0 ;
}
static void free_picture ( x265_picture * pic )
static void free_picture ( libx265Context * ctx , x265_picture * pic )
{
x265_sei * sei = & pic - > userSEI ;
for ( int i = 0 ; i < sei - > numPayloads ; i + + )
av_free ( sei - > payloads [ i ] . payload ) ;
av_freep ( & pic - > userData ) ;
if ( pic - > userData ) {
int idx = ( int ) ( intptr_t ) pic - > userData - 1 ;
rd_release ( ctx , idx ) ;
pic - > userData = NULL ;
}
av_freep ( & pic - > quantOffsets ) ;
sei - > numPayloads = 0 ;
}
@ -549,13 +601,18 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
return ret ;
if ( pic - > reordered_opaque ) {
x265pic . userData = av_malloc ( sizeof ( pic - > reordered_opaque ) ) ;
if ( ! x265pic . userData ) {
free_picture ( & x265pic ) ;
return AVERROR ( ENOMEM ) ;
ReorderedData * rd ;
int rd_idx = rd_get ( ctx ) ;
if ( rd_idx < 0 ) {
free_picture ( ctx , & x265pic ) ;
return rd_idx ;
}
memcpy ( x265pic . userData , & pic - > reordered_opaque , sizeof ( pic - > reordered_opaque ) ) ;
x265pic . userData = ( void * ) ( intptr_t ) ( rd_idx + 1 ) ;
rd = & ctx - > rd [ rd_idx ] ;
rd - > reordered_opaque = pic - > reordered_opaque ;
}
if ( ctx - > a53_cc ) {
@ -574,7 +631,7 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
( sei - > numPayloads + 1 ) * sizeof ( * sei_payload ) ) ;
if ( ! tmp ) {
av_free ( sei_data ) ;
free_picture ( & x265pic ) ;
free_picture ( ctx , & x265pic ) ;
return AVERROR ( ENOMEM ) ;
}
ctx - > sei_data = tmp ;
@ -600,7 +657,7 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
& ctx - > sei_data_size ,
( sei - > numPayloads + 1 ) * sizeof ( * sei_payload ) ) ;
if ( ! tmp ) {
free_picture ( & x265pic ) ;
free_picture ( ctx , & x265pic ) ;
return AVERROR ( ENOMEM ) ;
}
ctx - > sei_data = tmp ;
@ -608,7 +665,7 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
sei_payload = & sei - > payloads [ sei - > numPayloads ] ;
sei_payload - > payload = av_memdup ( side_data - > data , side_data - > size ) ;
if ( ! sei_payload - > payload ) {
free_picture ( & x265pic ) ;
free_picture ( ctx , & x265pic ) ;
return AVERROR ( ENOMEM ) ;
}
sei_payload - > payloadSize = side_data - > size ;
@ -680,8 +737,12 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
ff_side_data_set_encoder_stats ( pkt , x265pic_out . frameData . qp * FF_QP2LAMBDA , NULL , 0 , pict_type ) ;
if ( x265pic_out . userData ) {
memcpy ( & avctx - > reordered_opaque , x265pic_out . userData , sizeof ( avctx - > reordered_opaque ) ) ;
av_freep ( & x265pic_out . userData ) ;
int idx = ( int ) ( intptr_t ) x265pic_out . userData - 1 ;
ReorderedData * rd = & ctx - > rd [ idx ] ;
avctx - > reordered_opaque = rd - > reordered_opaque ;
rd_release ( ctx , idx ) ;
} else
avctx - > reordered_opaque = 0 ;