[Libva] Help!
Zhao, Yakui
yakui.zhao at intel.com
Thu Jan 8 16:02:04 PST 2015
On Thu, 2015-01-08 at 14:28 -0800, Tony Di Croce wrote:
> 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:
>
>
Are you using the intel-vaapi driver downloaded from:
http://cgit.freedesktop.org/vaapi/intel-driver/
It will be better that you can take a look at the encoding example of :
http://cgit.freedesktop.org/vaapi/libva/
It can be found under the directory of libva/test/encode/
Thanks.
Yakui
> #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 );
> }
>
>
> _______________________________________________
> Libva mailing list
> Libva at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/libva
More information about the Libva
mailing list