[Libva] Help!
Tony Di Croce
dicroce at gmail.com
Thu Jan 8 14:28:15 PST 2015
While adapting the encoding example to my use at some point I broke bitrate
control... Basically, no matter what I set the bitrate to I get the same
video out of libva. Here is my code:
#include "VAKit/VAH264Encoder.h"
#include "VAKit/BitStream.h"
#include "VAKit/NALTypes.h"
#include "XSDK/XException.h"
using namespace VAKit;
using namespace std;
using namespace XSDK;
using namespace AVKit;
const size_t MAX_FRAME_NUM = (2<<16);
const size_t MAX_PIC_ORDER_CNT_LSB = (2<<8);
const size_t LOG_2_MAX_FRAME_NUM = 16;
const size_t LOG_2_MAX_PIC_ORDER_CNT_LSB = 8;
const int32_t H264_MAXREF = (1<<16|1);
const int32_t FRAME_P = 0;
const int32_t FRAME_I = 2;
const int32_t FRAME_IDR = 7;
static const size_t DEFAULT_PADDING = 16;
static const size_t DEFAULT_ENCODE_BUFFER_SIZE = (1024*1024);
static const size_t DEFAULT_EXTRADATA_BUFFER_SIZE = (1024*256);
VAH264Encoder::VAH264Encoder( const struct AVKit::CodecOptions& options,
bool annexB ) :
_devicePath(),
_annexB( annexB ),
_fd(-1),
_display(),
_h264Profile( VAProfileH264High ),
_configID( 0 ),
_srcSurfaceID( 0 ),
_codedBufID( 0 ),
_refSurfaceIDs(),
_contextID(0),
_seqParam(),
_picParam(),
_sliceParam(),
_currentCurrPic(),
_referenceFrames(),
_refPicListP(),
_constraintSetFlag( 0 ),
_h264EntropyMode( 1 ), /* cabac */
_frameWidth( 0 ),
_frameWidthMBAligned( 0 ),
_frameHeight( 0 ),
_frameHeightMBAligned( 0 ),
_frameBitRate( 0 ),
_intraPeriod( 15 ),
_currentIDRDisplay( 0 ),
_currentFrameNum( 0 ),
_currentFrameType( 0 ),
_timeBaseNum( 0 ),
_timeBaseDen( 0 ),
_extraData(),
_pkt(),
_options( options )
{
if( options.device_path.IsNull() )
X_THROW(("device_path needed for VAH264Encoder."));
_devicePath = options.device_path.Value();
_fd = open( _devicePath.c_str(), O_RDWR );
if( _fd <= 0 )
X_THROW(("Unable to open %s",_devicePath.c_str()));
_display = (VADisplay)vaGetDisplayDRM( _fd );
if( !options.width.IsNull() )
{
_frameWidth = options.width.Value();
_frameWidthMBAligned = (_frameWidth + 15) & (~15);
}
else X_THROW(( "Required option missing: width" ));
if( !options.height.IsNull() )
{
_frameHeight = options.height.Value();
_frameHeightMBAligned = (_frameHeight + 15) & (~15);
}
else X_THROW(( "Required option missing: height" ));
if( !options.bit_rate.IsNull() )
_frameBitRate = options.bit_rate.Value();
// _frameBitRate = (options.bit_rate.Value() / 1024) / 8;
else X_THROW(( "Required option missing: bit_rate" ));
if( !options.gop_size.IsNull() )
_intraPeriod = options.gop_size.Value();
if( !options.time_base_num.IsNull() )
_timeBaseNum = options.time_base_num.Value();
else X_THROW(("Required option missing: time_base.num"));
if( !options.time_base_den.IsNull() )
_timeBaseDen = options.time_base_den.Value();
else X_THROW(("Required option missing: time_base.den"));
int major_ver = 0, minor_ver = 0;
VAStatus status = vaInitialize( _display, &major_ver, &minor_ver );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaInitialize (%s).", vaErrorStr(status) ));
switch( _h264Profile )
{
case VAProfileH264Baseline:
_constraintSetFlag |= (1 << 0); /* Annex A.2.1 */
_h264EntropyMode = 0;
break;
case VAProfileH264ConstrainedBaseline:
_constraintSetFlag |= (1 << 0 | 1 << 1); /* Annex A.2.2 */
_h264EntropyMode = 0;
break;
case VAProfileH264Main:
_constraintSetFlag |= (1 << 1); /* Annex A.2.2 */
break;
case VAProfileH264High:
_constraintSetFlag |= (1 << 3); /* Annex A.2.4 */
break;
default:
_h264Profile = VAProfileH264Baseline;
_constraintSetFlag |= (1 << 0); /* Annex A.2.1 */
break;
}
VAConfigAttrib configAttrib[VAConfigAttribTypeMax];
int configAttribNum = 0;
configAttrib[configAttribNum].type = VAConfigAttribRTFormat;
configAttrib[configAttribNum].value = VA_RT_FORMAT_YUV420;
configAttribNum++;
configAttrib[configAttribNum].type = VAConfigAttribRateControl;
configAttrib[configAttribNum].value = VA_RC_VBR;
configAttribNum++;
configAttrib[configAttribNum].type = VAConfigAttribEncPackedHeaders;
configAttrib[configAttribNum].value = VA_ENC_PACKED_HEADER_NONE;
configAttrib[configAttribNum].value = VA_ENC_PACKED_HEADER_SEQUENCE |
VA_ENC_PACKED_HEADER_PICTURE;
configAttribNum++;
status = vaCreateConfig( _display,
_h264Profile,
VAEntrypointEncSlice,
&configAttrib[0],
configAttribNum,
&_configID );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaCreateConfig (%s).", vaErrorStr(status) ));
// Configuration below this point can be thought of as specific to a
particular
// encoder channel. I point this out because we might want to split
this out
// someday.
/* create source surfaces */
status = vaCreateSurfaces( _display,
VA_RT_FORMAT_YUV420,
_frameWidthMBAligned,
_frameHeightMBAligned,
&_srcSurfaceID,
1,
NULL,
0 );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaCreateSurfaces (%s).", vaErrorStr(status) ));
/* create reference surfaces */
status = vaCreateSurfaces( _display,
VA_RT_FORMAT_YUV420,
_frameWidthMBAligned,
_frameHeightMBAligned,
&_refSurfaceIDs[0],
SURFACE_NUM,
NULL,
0 );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaCreateSurfaces (%s).", vaErrorStr(status) ));
VASurfaceID* tmp_surfaceid = (VASurfaceID*)calloc( 2,
sizeof(VASurfaceID) );
memcpy( tmp_surfaceid, &_srcSurfaceID, sizeof(VASurfaceID) );
memcpy( tmp_surfaceid + 1, &_refSurfaceIDs, sizeof(VASurfaceID) );
/* Create a context for this encode pipe */
status = vaCreateContext( _display,
_configID,
_frameWidthMBAligned,
_frameHeightMBAligned,
VA_PROGRESSIVE,
tmp_surfaceid,
2,
&_contextID );
free(tmp_surfaceid);
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaCreateContext (%s).", vaErrorStr(status) ));
status = vaCreateBuffer( _display,
_contextID,
VAEncCodedBufferType,
(_frameWidthMBAligned * _frameHeightMBAligned
* 400) / (16*16),
1,
NULL,
&_codedBufID );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaCreateBuffer (%s).", vaErrorStr(status) ));
}
VAH264Encoder::~VAH264Encoder() throw()
{
vaDestroyBuffer( _display, _codedBufID );
vaDestroyContext( _display, _contextID );
vaDestroySurfaces( _display, &_refSurfaceIDs[0], SURFACE_NUM );
vaDestroySurfaces( _display, &_srcSurfaceID, 1 );
vaDestroyConfig( _display, _configID );
vaTerminate( _display );
close( _fd );
}
size_t VAH264Encoder::EncodeYUV420P( uint8_t* pic,
uint8_t* output,
size_t outputSize,
AVKit::FrameType type )
{
VAImage image;
vaDeriveImage( _display, _srcSurfaceID, &image );
_UploadImage( pic, image, _frameWidth, _frameHeight );
_currentFrameType = _ComputeCurrentFrameType( _currentFrameNum,
_intraPeriod,
type );
if( _currentFrameType == FRAME_IDR )
{
_numShortTerm = 0;
_currentFrameNum = 0;
_currentIDRDisplay = _currentFrameNum;
}
VAStatus status = vaBeginPicture( _display, _contextID, _srcSurfaceID );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaBeginPicture (%s).", vaErrorStr(status) ));
if( _currentFrameType == FRAME_IDR )
{
_RenderSequence();
_RenderPicture( false );
_RenderPackedSPS();
_RenderPackedPPS();
if( !_extraData.Get() )
{
BitStream seqBS;
BuildPackedSeqBuffer( seqBS,
_seqParam,
_h264Profile,
_constraintSetFlag,
_timeBaseNum,
_timeBaseDen,
_frameBitRate / 8 );
// _frameBitRate * 1024 * 8 );
BitStream ppsBS;
BuildPackedPicBuffer( ppsBS, _picParam );
_extraData = new XMemory;
memcpy( &_extraData->Extend(seqBS.Size()), seqBS.Map(),
seqBS.Size() );
memcpy( &_extraData->Extend(ppsBS.Size()), ppsBS.Map(),
ppsBS.Size() );
}
}
else _RenderPicture( false );
_RenderSlice();
status = vaEndPicture( _display, _contextID );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaEndPicture (%s).", vaErrorStr(status) ));
_UpdateReferenceFrames();
status = vaSyncSurface( _display, _srcSurfaceID );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaSyncSurface (%s).", vaErrorStr(status) ));
VACodedBufferSegment* bufList = NULL;
status = vaMapBuffer( _display, _codedBufID, (void **)(&bufList) );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaMapBuffer (%s).", vaErrorStr(status) ));
VACodedBufferSegment* current = bufList;
uint32_t accumSize = 0;
while( current != NULL )
{
accumSize += current->size;
current = (VACodedBufferSegment*)current->next;
}
if( outputSize < accumSize )
X_THROW(("Not enough room in output buffer."));
uint8_t* dst = output;
while( bufList != NULL )
{
memcpy( dst, bufList->buf, bufList->size );
dst += bufList->size;
bufList = (VACodedBufferSegment*)bufList->next;
}
vaUnmapBuffer( _display, _codedBufID );
return accumSize;
}
XIRef<XMemory> VAH264Encoder::EncodeYUV420P( XIRef<XMemory> input,
AVKit::FrameType type )
{
XIRef<XMemory> frame = new XMemory( DEFAULT_ENCODE_BUFFER_SIZE +
DEFAULT_PADDING );
uint8_t* p = &frame->Extend( DEFAULT_ENCODE_BUFFER_SIZE );
size_t outputSize = EncodeYUV420P( input->Map(),
p,
frame->GetDataSize(),
type );
frame->ResizeData( outputSize );
return frame;
}
bool VAH264Encoder::LastWasKey() const
{
return (_currentFrameType == FRAME_IDR) ? true : (_currentFrameType ==
FRAME_I) ? true : false;
}
struct CodecOptions VAH264Encoder::GetOptions() const
{
return _options;
}
XIRef<XMemory> VAH264Encoder::GetExtraData() const
{
if( _extraData->GetDataSize() == 0 )
X_THROW(("Decode one frame before call to GetExtraData()."));
return _extraData;
}
int32_t VAH264Encoder::_ComputeCurrentFrameType( uint32_t currentFrameNum,
int32_t intraPeriod,
AVKit::FrameType type )
const
{
if( type == FRAME_TYPE_AUTO_GOP )
{
if( (currentFrameNum % intraPeriod) == 0 )
{
if( currentFrameNum == 0 )
return FRAME_IDR;
else return FRAME_I;
}
return FRAME_P;
}
else
{
if( type == FRAME_TYPE_KEY )
{
if( currentFrameNum == 0 )
return FRAME_IDR;
else return FRAME_I;
}
else return FRAME_P;
}
}
void VAH264Encoder::_UpdateReferenceFrames()
{
_currentCurrPic.flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
_numShortTerm++;
if( _numShortTerm > SURFACE_NUM )
_numShortTerm = SURFACE_NUM;
for( int i = _numShortTerm - 1; i > 0; i-- )
_referenceFrames[i] = _referenceFrames[i-1];
_referenceFrames[0] = _currentCurrPic;
_currentFrameNum++;
if( _currentFrameNum > MAX_FRAME_NUM )
_currentFrameNum = 0;
}
void VAH264Encoder::_UpdateRefPicList()
{
uint32_t current_poc = _currentCurrPic.TopFieldOrderCnt;
if( _currentFrameType == FRAME_P )
memcpy( _refPicListP, _referenceFrames, _numShortTerm *
sizeof(VAPictureH264));
}
void VAH264Encoder::_RenderSequence()
{
VABufferID seq_param_buf, rc_param_buf, misc_param_tmpbuf, render_id[2];
VAStatus status;
VAEncMiscParameterBuffer *misc_param, *misc_param_tmp;
VAEncMiscParameterRateControl *misc_rate_ctrl;
_seqParam.level_idc = 41 /*SH_LEVEL_3*/;
_seqParam.picture_width_in_mbs = _frameWidthMBAligned / 16;
_seqParam.picture_height_in_mbs = _frameHeightMBAligned / 16;
// _seqParam.bits_per_second = _frameBitRate * 1024 * 8;
_seqParam.bits_per_second = _frameBitRate / 8;
_seqParam.intra_period = _intraPeriod;
_seqParam.intra_idr_period = _intraPeriod * 64;
_seqParam.ip_period = 1;
_seqParam.max_num_ref_frames = NUM_REFERENCE_FRAMES;
_seqParam.seq_fields.bits.frame_mbs_only_flag = 1;
_seqParam.time_scale = 900;
_seqParam.num_units_in_tick = _timeBaseDen;
_seqParam.seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 =
LOG_2_MAX_PIC_ORDER_CNT_LSB - 4;
_seqParam.seq_fields.bits.log2_max_frame_num_minus4 =
LOG_2_MAX_FRAME_NUM - 4;
_seqParam.seq_fields.bits.frame_mbs_only_flag = 1;
_seqParam.seq_fields.bits.chroma_format_idc = 1;
_seqParam.seq_fields.bits.direct_8x8_inference_flag = 1;
if( _frameWidth != _frameWidthMBAligned || _frameHeight !=
_frameHeightMBAligned )
{
_seqParam.frame_cropping_flag = 1;
_seqParam.frame_crop_left_offset = 0;
_seqParam.frame_crop_right_offset = (_frameWidthMBAligned -
_frameWidth) / 2;
_seqParam.frame_crop_top_offset = 0;
_seqParam.frame_crop_bottom_offset = (_frameHeightMBAligned -
_frameHeight) / 2;
}
status = vaCreateBuffer( _display,
_contextID,
VAEncSequenceParameterBufferType,
sizeof(_seqParam),
1,
&_seqParam,
&seq_param_buf );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaCreateBuffer (%s).", vaErrorStr(status) ));
// Rate control...
status = vaCreateBuffer( _display,
_contextID,
VAEncMiscParameterBufferType,
sizeof(VAEncMiscParameterBuffer) +
sizeof(VAEncMiscParameterRateControl),
1,
NULL,
&rc_param_buf );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaCreateBuffer (%s).", vaErrorStr(status) ));
vaMapBuffer( _display, rc_param_buf,(void **)&misc_param);
if( !misc_param )
X_THROW(( "Unable to vaMapBuffer." ));
misc_param->type = VAEncMiscParameterTypeRateControl;
misc_rate_ctrl = (VAEncMiscParameterRateControl *)misc_param->data;
memset( misc_rate_ctrl, 0, sizeof(*misc_rate_ctrl) );
// misc_rate_ctrl->bits_per_second = _frameBitRate * 1024 * 8;
misc_rate_ctrl->bits_per_second = _frameBitRate / 8;
misc_rate_ctrl->target_percentage = 66;
misc_rate_ctrl->window_size = 1000;
misc_rate_ctrl->initial_qp = 26;
misc_rate_ctrl->min_qp = 1;
misc_rate_ctrl->basic_unit_size = 0;
vaUnmapBuffer( _display, rc_param_buf );
// Push buffers to hardware...
render_id[0] = seq_param_buf;
render_id[1] = rc_param_buf;
// According to documentation, vaRenderPicture recycles the buffers
given to it
// so we apparently do not owe vaDestroyBuffers() for the above buffers.
status = vaRenderPicture( _display, _contextID, &render_id[0], 2 );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaRenderPicture (%s).", vaErrorStr(status) ));
}
int32_t VAH264Encoder::_CalcPOC( int32_t picOrderCntLSB )
{
static int picOrderCntMsbRef = 0, picOrderCntLsbRef = 0;
int prevPicOrderCntMsb = 0, prevPicOrderCntLsb = 0;
int picOrderCntMsb = 0, topFieldOrderCnt = 0;
if( _currentFrameType == FRAME_IDR )
prevPicOrderCntMsb = prevPicOrderCntLsb = 0;
else {
prevPicOrderCntMsb = picOrderCntMsbRef;
prevPicOrderCntLsb = picOrderCntLsbRef;
}
if( (picOrderCntLSB < prevPicOrderCntLsb) &&
((prevPicOrderCntLsb - picOrderCntLSB) >=
(int)(MAX_PIC_ORDER_CNT_LSB / 2)))
picOrderCntMsb = prevPicOrderCntMsb + MAX_PIC_ORDER_CNT_LSB;
else if( (picOrderCntLSB > prevPicOrderCntLsb) &&
((picOrderCntLSB - prevPicOrderCntLsb) >
(int)(MAX_PIC_ORDER_CNT_LSB / 2)))
picOrderCntMsb = prevPicOrderCntMsb - MAX_PIC_ORDER_CNT_LSB;
else
picOrderCntMsb = prevPicOrderCntMsb;
topFieldOrderCnt = picOrderCntMsb + picOrderCntLSB;
picOrderCntMsbRef = picOrderCntMsb;
picOrderCntLsbRef = picOrderCntLSB;
return topFieldOrderCnt;
}
void VAH264Encoder::_RenderPicture( bool done )
{
VABufferID pic_param_buf;
_picParam.CurrPic.picture_id = _refSurfaceIDs[(_currentFrameNum %
SURFACE_NUM)];
_picParam.CurrPic.frame_idx = _currentFrameNum;
_picParam.CurrPic.flags = 0;
_picParam.CurrPic.TopFieldOrderCnt =
_CalcPOC((_currentFrameNum - _currentIDRDisplay) %
MAX_PIC_ORDER_CNT_LSB);
_picParam.CurrPic.BottomFieldOrderCnt =
_picParam.CurrPic.TopFieldOrderCnt;
_currentCurrPic = _picParam.CurrPic;
memcpy( _picParam.ReferenceFrames,
_referenceFrames,
_numShortTerm*sizeof(VAPictureH264) );
for (int i = _numShortTerm; i < SURFACE_NUM; i++)
{
_picParam.ReferenceFrames[i].picture_id = VA_INVALID_SURFACE;
_picParam.ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID;
}
_picParam.pic_fields.bits.idr_pic_flag = (_currentFrameType ==
FRAME_IDR);
_picParam.pic_fields.bits.reference_pic_flag = 1;
_picParam.pic_fields.bits.entropy_coding_mode_flag = _h264EntropyMode;
_picParam.pic_fields.bits.deblocking_filter_control_present_flag = 1;
_picParam.frame_num = _currentFrameNum;
_picParam.coded_buf = _codedBufID;
_picParam.last_picture = (done)?1:0;
_picParam.pic_init_qp = 26;
VAStatus status = vaCreateBuffer( _display,
_contextID,
VAEncPictureParameterBufferType,
sizeof(_picParam),
1,
&_picParam,
&pic_param_buf );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaCreateBuffer (%s).", vaErrorStr(status) ));
status = vaRenderPicture( _display,
_contextID,
&pic_param_buf,
1 );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaRenderPicture (%s).", vaErrorStr(status) ));
}
void VAH264Encoder::_RenderPackedPPS()
{
BitStream ppsBS;
BuildPackedPicBuffer( ppsBS, _picParam );
VAEncPackedHeaderParameterBuffer packedheader_param_buffer;
packedheader_param_buffer.type = VAEncPackedHeaderPicture;
packedheader_param_buffer.bit_length = ppsBS.SizeInBits();
packedheader_param_buffer.has_emulation_bytes = 0;
VABufferID packedpic_para_bufid;
VAStatus va_status = vaCreateBuffer( _display,
_contextID,
VAEncPackedHeaderParameterBufferType,
sizeof(packedheader_param_buffer),
1,
&packedheader_param_buffer,
&packedpic_para_bufid );
if( va_status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaCreateBuffer (%s).", vaErrorStr(va_status)
));
VABufferID packedpic_data_bufid;
va_status = vaCreateBuffer( _display,
_contextID,
VAEncPackedHeaderDataBufferType,
(ppsBS.SizeInBits() + 7) / 8,
1,
ppsBS.Map(),
&packedpic_data_bufid );
if( va_status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaCreateBuffer (%s).", vaErrorStr(va_status)
));
VABufferID render_id[2];
render_id[0] = packedpic_para_bufid;
render_id[1] = packedpic_data_bufid;
va_status = vaRenderPicture( _display, _contextID, render_id, 2 );
if( va_status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaRenderPicture (%s).", vaErrorStr(va_status)
));
}
void VAH264Encoder::_RenderPackedSPS()
{
BitStream seqBS;
BuildPackedSeqBuffer( seqBS,
_seqParam,
_h264Profile,
_constraintSetFlag,
_timeBaseNum,
_timeBaseDen,
_frameBitRate / 8 );
// _frameBitRate * 1024 * 8 );
VAEncPackedHeaderParameterBuffer packedheader_param_buffer;
packedheader_param_buffer.type = VAEncPackedHeaderSequence;
packedheader_param_buffer.bit_length = seqBS.SizeInBits();
packedheader_param_buffer.has_emulation_bytes = 0;
VABufferID packedseq_para_bufid;
VAStatus va_status = vaCreateBuffer( _display,
_contextID,
VAEncPackedHeaderParameterBufferType,
sizeof(packedheader_param_buffer),
1,
&packedheader_param_buffer,
&packedseq_para_bufid );
if( va_status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaCreateBuffer (%s).", vaErrorStr(va_status)
));
VABufferID packedseq_data_bufid;
va_status = vaCreateBuffer( _display,
_contextID,
VAEncPackedHeaderDataBufferType,
(seqBS.SizeInBits() + 7) / 8,
1,
seqBS.Map(),
&packedseq_data_bufid);
if( va_status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaCreateBuffer (%s).", vaErrorStr(va_status)
));
VABufferID render_id[2];
render_id[0] = packedseq_para_bufid;
render_id[1] = packedseq_data_bufid;
va_status = vaRenderPicture( _display, _contextID, render_id, 2 );
if( va_status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaRenderPicture (%s).", vaErrorStr(va_status)
));
}
void VAH264Encoder::_RenderSlice()
{
VABufferID slice_param_buf;
_UpdateRefPicList();
/* one frame, one slice */
_sliceParam.macroblock_address = 0;
_sliceParam.num_macroblocks = _frameWidthMBAligned *
_frameHeightMBAligned/(16*16); /*Measured by MB*/
_sliceParam.slice_type = (_currentFrameType ==
FRAME_IDR)?2:_currentFrameType;
_sliceParam.slice_qp_delta = 0;
if( _currentFrameType == FRAME_IDR )
{
if( _currentFrameNum != 0 )
++_sliceParam.idr_pic_id;
}
else if( _currentFrameType == FRAME_P )
{
int refpiclist0_max = H264_MAXREF & 0xffff;
memcpy( _sliceParam.RefPicList0,
_refPicListP,
refpiclist0_max*sizeof(VAPictureH264) );
for (int i = refpiclist0_max; i < 32; i++)
{
_sliceParam.RefPicList0[i].picture_id = VA_INVALID_SURFACE;
_sliceParam.RefPicList0[i].flags = VA_PICTURE_H264_INVALID;
}
}
_sliceParam.slice_alpha_c0_offset_div2 = 0;
_sliceParam.slice_beta_offset_div2 = 0;
_sliceParam.direct_spatial_mv_pred_flag = 1;
_sliceParam.pic_order_cnt_lsb = (_currentFrameNum - _currentIDRDisplay)
% MAX_PIC_ORDER_CNT_LSB;
VAStatus status = vaCreateBuffer( _display,
_contextID,
VAEncSliceParameterBufferType,
sizeof(_sliceParam),
1,
&_sliceParam,
&slice_param_buf );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaCreateBuffer (%s).", vaErrorStr(status) ));
status = vaRenderPicture( _display,
_contextID,
&slice_param_buf,
1 );
if( status != VA_STATUS_SUCCESS )
X_THROW(( "Unable to vaCreateBuffer (%s).", vaErrorStr(status) ));
}
void VAH264Encoder::_UploadImage( uint8_t* yv12, VAImage& image, uint16_t
width, uint16_t height )
{
assert( image.num_planes == 2 );
unsigned char* p = NULL;
vaMapBuffer( _display, image.buf, (void **)&p );
if( !p )
X_THROW(( "Unable to vaMapBuffer." ));
uint8_t* sy = yv12;
uint8_t* su = sy + (width * height);
uint8_t* sv = su + ((width/2)*(height/2));
uint8_t* dy = p + image.offsets[0];
uint8_t* duv = p + image.offsets[1];
for( size_t i = 0; i < height; i++ )
{
memcpy( dy, sy, width );
dy += image.pitches[0];
sy += width;
}
for( size_t i = 0; i < (height/2); i++ )
{
uint8_t* dst = duv;
for( size_t ii = 0; ii < (width/2); ii++ )
{
*dst = *su;
dst++;
su++;
*dst = *sv;
dst++;
sv++;
}
duv += image.pitches[1];
}
vaUnmapBuffer( _display, image.buf );
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/libva/attachments/20150108/0580afc2/attachment-0001.html>
More information about the Libva
mailing list