void VaapiEncoderH264::resetParams () { m_levelIdc = level(); DEBUG("resetParams, ensureCodedBufferSize"); ensureCodedBufferSize(); if (ipPeriod() == 0) m_videoParamCommon.intraPeriod = 1; else m_numBFrames = ipPeriod() - 1; assert(intraPeriod() > ipPeriod()); m_keyPeriod = intraPeriod() * (m_videoParamAVC.idrInterval + 1); if (m_keyPeriod > MAX_IDR_PERIOD) m_keyPeriod = MAX_IDR_PERIOD; if (minQP() > initQP() || (rateControlMode()== RATE_CONTROL_CQP && minQP() < initQP())) minQP() = initQP(); if (m_numBFrames > (intraPeriod() + 1) / 2) m_numBFrames = (intraPeriod() + 1) / 2; /* init m_maxFrameNum, max_poc */ m_log2MaxFrameNum = h264_get_log2_max_frame_num (m_keyPeriod); assert (m_log2MaxFrameNum >= 4); m_maxFrameNum = (1 << m_log2MaxFrameNum); m_log2MaxPicOrderCnt = m_log2MaxFrameNum + 1; m_maxPicOrderCnt = (1 << m_log2MaxPicOrderCnt); m_maxRefList1Count = m_numBFrames > 0;//m_maxRefList1Count <=1, because of currenent order mechanism m_maxRefList0Count = numRefFrames(); if (m_maxRefList0Count >= m_maxOutputBuffer -1) m_maxRefList0Count = m_maxOutputBuffer -1; m_maxRefFrames = m_maxRefList0Count + m_maxRefList1Count; assert(m_maxRefFrames <= m_maxOutputBuffer); INFO("m_maxRefFrames: %d", m_maxRefFrames); resetGopStart(); }
Encode_Status VaapiEncoderH264::reorder(const SurfacePtr& surface, uint64_t timeStamp, bool forceKeyFrame) { if (!surface) return ENCODE_INVALID_PARAMS; PicturePtr picture(new VaapiEncPictureH264(m_context, surface, timeStamp)); bool isIdr = (m_frameIndex == 0 ||m_frameIndex >= keyFramePeriod() || forceKeyFrame); if (isIdr) { setIdrFrame (picture); m_reorderFrameList.push_back(picture); m_curFrameNum++; m_reorderState = VAAPI_ENC_REORD_DUMP_FRAMES; } else if (m_frameIndex % intraPeriod() == 0) { setIFrame (picture); m_reorderFrameList.push_front(picture); m_curFrameNum++; m_reorderState = VAAPI_ENC_REORD_DUMP_FRAMES; }else if (m_frameIndex % (m_numBFrames + 1) != 0) { setBFrame (picture); m_reorderFrameList.push_back(picture); } else { setPFrame (picture); m_reorderFrameList.push_front(picture); m_curFrameNum++; m_reorderState = VAAPI_ENC_REORD_DUMP_FRAMES; } picture->m_poc = ((m_frameIndex * 2) % m_maxPicOrderCnt); m_frameIndex++; return ENCODE_SUCCESS; }
void VaapiEncoderH264::resetParams () { m_levelIdc = level(); DEBUG("resetParams, ensureCodedBufferSize"); ensureCodedBufferSize(); if (ipPeriod() == 0) m_videoParamCommon.intraPeriod = 1; else m_numBFrames = ipPeriod() - 1; assert(intraPeriod() > ipPeriod()); if (keyFramePeriod() < intraPeriod()) keyFramePeriod() = intraPeriod(); if (keyFramePeriod() > MAX_IDR_PERIOD) keyFramePeriod() = MAX_IDR_PERIOD; if (minQP() > initQP() || (rateControlMode()== RATE_CONTROL_CQP && minQP() < initQP())) minQP() = initQP(); if (m_numBFrames > (intraPeriod() + 1) / 2) m_numBFrames = (intraPeriod() + 1) / 2; /* init m_maxFrameNum, max_poc */ m_log2MaxFrameNum = h264_get_log2_max_frame_num (keyFramePeriod()); assert (m_log2MaxFrameNum >= 4); m_maxFrameNum = (1 << m_log2MaxFrameNum); m_log2MaxPicOrderCnt = m_log2MaxFrameNum + 1; m_maxPicOrderCnt = (1 << m_log2MaxPicOrderCnt); m_maxRefList0Count = 1; m_maxRefList1Count = m_numBFrames > 0; m_maxRefFrames = m_maxRefList0Count + m_maxRefList1Count; INFO("m_maxRefFrames: %d", m_maxRefFrames); resetGopStart(); }
Encode_Status VaapiEncoderH264::reorder(const SurfacePtr& surface, uint64_t timeStamp, bool forceKeyFrame) { if (!surface) return ENCODE_INVALID_PARAMS; PicturePtr picture(new VaapiEncPictureH264(m_context, surface, timeStamp)); bool isIdr = (m_frameIndex == 0 ||m_frameIndex >= m_keyPeriod || forceKeyFrame); if (isIdr) { // If the last frame before IDR is B frame, set it to P frame. if (m_reorderFrameList.size()) { PicturePtr lastPic = m_reorderFrameList.back(); if (lastPic->m_type == VAAPI_PICTURE_TYPE_B) { lastPic->m_type = VAAPI_PICTURE_TYPE_P; m_reorderFrameList.pop_back(); m_reorderFrameList.push_front(lastPic); } } setIdrFrame (picture); m_reorderFrameList.push_back(picture); m_curFrameNum++; m_reorderState = VAAPI_ENC_REORD_DUMP_FRAMES; } else if (m_frameIndex % intraPeriod() == 0) { setIFrame (picture); m_reorderFrameList.push_front(picture); m_curFrameNum++; m_reorderState = VAAPI_ENC_REORD_DUMP_FRAMES; }else if (m_frameIndex % (m_numBFrames + 1) != 0) { setBFrame (picture); m_reorderFrameList.push_back(picture); } else { setPFrame (picture); m_reorderFrameList.push_front(picture); m_curFrameNum++; m_reorderState = VAAPI_ENC_REORD_DUMP_FRAMES; } picture->m_poc = ((m_frameIndex * 2) % m_maxPicOrderCnt); m_frameIndex++; return ENCODE_SUCCESS; }
bool VaapiEncoderH264::fill(VAEncSequenceParameterBufferH264* seqParam) const { seqParam->seq_parameter_set_id = 0; seqParam->level_idc = m_levelIdc; seqParam->intra_period = intraPeriod(); seqParam->intra_idr_period = seqParam->intra_period; seqParam->ip_period = 1 + m_numBFrames; seqParam->bits_per_second = bitRate(); seqParam->max_num_ref_frames = m_maxRefFrames; seqParam->picture_width_in_mbs = m_mbWidth; seqParam->picture_height_in_mbs = m_mbHeight; /*sequence field values */ seqParam->seq_fields.value = 0; seqParam->seq_fields.bits.chroma_format_idc = 1; seqParam->seq_fields.bits.frame_mbs_only_flag = 1; assert (m_log2MaxFrameNum >= 4); seqParam->seq_fields.bits.log2_max_frame_num_minus4 = m_log2MaxFrameNum - 4; /* picture order count */ seqParam->seq_fields.bits.pic_order_cnt_type = 0; assert (m_log2MaxPicOrderCnt >= 4); seqParam->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = m_log2MaxPicOrderCnt - 4; /* not used if pic_order_cnt_type == 0 */ if (seqParam->seq_fields.bits.pic_order_cnt_type == 1) { seqParam->seq_fields.bits.delta_pic_order_always_zero_flag = TRUE; } /* frame_cropping_flag */ const int cropRight = (16 * m_mbWidth - width()); const int cropBottom = (16 * m_mbHeight - height()); if (cropRight || cropBottom) { const int CHROMA_420 = 1; const int CHROMA_422 = 2; int chroma = seqParam->seq_fields.bits.chroma_format_idc; static const uint32_t subWidthC = (chroma == CHROMA_420 || chroma == CHROMA_422) ? 2 : 1; static const uint32_t subHeightC = chroma == CHROMA_420 ? 2 : 1; const uint32_t cropUnitX = subWidthC; const uint32_t cropUnitY = subHeightC * (2 - seqParam->seq_fields.bits.frame_mbs_only_flag); seqParam->frame_cropping_flag = 1; seqParam->frame_crop_right_offset = cropRight / cropUnitX; seqParam->frame_crop_bottom_offset = cropBottom / cropUnitY; } /* VUI parameters are always set, at least for timing_info (framerate) */ seqParam->vui_parameters_present_flag = TRUE; if (seqParam->vui_parameters_present_flag) { seqParam->vui_fields.bits.aspect_ratio_info_present_flag = FALSE; seqParam->vui_fields.bits.bitstream_restriction_flag = FALSE; seqParam->vui_fields.bits.timing_info_present_flag = TRUE; if (seqParam->vui_fields.bits.timing_info_present_flag) { seqParam->num_units_in_tick = frameRateDenom(); seqParam->time_scale = frameRateNum() * 2; } } return true; }