bool VaapiEncoderH264::ensureSequence(const PicturePtr& picture) { VAEncSequenceParameterBufferH264* seqParam; if (!picture->editSequence(seqParam) || !fill(seqParam)) { ERROR("failed to create sequence parameter buffer (SPS)"); return false; } if (picture->isIdr() && !ensureSequenceHeader(picture, seqParam)) { ERROR ("failed to create packed sequence header buffer"); return false; } return true; }
bool VaapiEncoderH264:: referenceListUpdate (const PicturePtr& picture, const SurfacePtr& surface) { if (VAAPI_PICTURE_TYPE_B == picture->m_type) { return true; } if (picture->isIdr()) { m_refList.clear(); } else if (m_refList.size() >= m_maxRefFrames) { m_refList.pop_back(); } ReferencePtr ref(new VaapiEncoderH264Ref(picture, surface)); m_refList.push_front(ref); // descending order for short-term reference list assert (m_refList.size() <= m_maxRefFrames); return true; }
/* Fills in VA picture parameter buffer */ bool VaapiEncoderH264::fill(VAEncPictureParameterBufferH264* picParam, const PicturePtr& picture, const SurfacePtr& surface) const { uint32_t i = 0; /* reference list, */ picParam->CurrPic.picture_id = surface->getID(); picParam->CurrPic.TopFieldOrderCnt = picture->m_poc; if (picture->m_type != VAAPI_PICTURE_TYPE_I) { for (i = 0; i < m_refList.size(); i++) { picParam->ReferenceFrames[i].picture_id = m_refList[i]->m_pic->getID(); picParam->ReferenceFrames[i].TopFieldOrderCnt = m_refList[i]->m_poc; picParam->ReferenceFrames[i].flags |= VA_PICTURE_H264_SHORT_TERM_REFERENCE; } } for (; i < 16; ++i) { picParam->ReferenceFrames[i].picture_id = VA_INVALID_ID; } picParam->coded_buf = picture->m_codedBuffer->getID(); picParam->pic_parameter_set_id = 0; picParam->seq_parameter_set_id = 0; picParam->last_picture = 0; /* means last encoding picture */ picParam->frame_num = picture->m_frameNum; picParam->pic_init_qp = initQP(); picParam->num_ref_idx_l0_active_minus1 = (m_maxRefList0Count ? (m_maxRefList0Count - 1) : 0); picParam->num_ref_idx_l1_active_minus1 = (m_maxRefList1Count ? (m_maxRefList1Count - 1) : 0); picParam->chroma_qp_index_offset = 0; picParam->second_chroma_qp_index_offset = 0; /* set picture fields */ picParam->pic_fields.bits.idr_pic_flag = picture->isIdr(); picParam->pic_fields.bits.reference_pic_flag = (picture->m_type != VAAPI_PICTURE_TYPE_B); picParam->pic_fields.bits.entropy_coding_mode_flag = m_useCabac; picParam->pic_fields.bits.transform_8x8_mode_flag = m_useDct8x8; /* enable debloking */ picParam->pic_fields.bits.deblocking_filter_control_present_flag = TRUE; return TRUE; }
bool VaapiEncoderH264::ensurePicture (const PicturePtr& picture, const SurfacePtr& surface) { VAEncPictureParameterBufferH264 *picParam; if (!pictureReferenceListSet(picture)) { ERROR ("reference list reorder failed"); return false; } if (!picture->editPicture(picParam) || !fill(picParam, picture, surface)) { ERROR("failed to create picture parameter buffer (PPS)"); return false; } if (picture->isIdr() && !ensurePictureHeader (picture, picParam)) { ERROR ("set picture packed header failed"); return false; } return true; }
// calls immediately after reorder, // it makes sure I frame are encoded immediately, so P frames can be pushed to the front of the m_reorderFrameList. // it also makes sure input thread and output thread runs in parallel Encode_Status VaapiEncoderH264::doEncode(const SurfacePtr& surface, uint64_t timeStamp, bool forceKeyFrame) { FUNC_ENTER(); Encode_Status ret; ret = reorder(surface, timeStamp, forceKeyFrame); if (ret != ENCODE_SUCCESS) return ret; while (m_reorderState == VAAPI_ENC_REORD_DUMP_FRAMES) { if (!m_maxCodedbufSize) ensureCodedBufferSize(); CodedBufferPtr codedBuffer = VaapiCodedBuffer::create(m_context, m_maxCodedbufSize); if (!codedBuffer) return ENCODE_NO_MEMORY; PicturePtr picture = m_reorderFrameList.front(); m_reorderFrameList.pop_front(); picture->m_codedBuffer = codedBuffer; if (m_reorderFrameList.empty()) m_reorderState = VAAPI_ENC_REORD_WAIT_FRAMES; ret = encodePicture(picture); if (ret != ENCODE_SUCCESS) { return ret; } codedBuffer->setFlag(ENCODE_BUFFERFLAG_ENDOFFRAME); INFO("picture->m_type: 0x%x\n", picture->m_type); if (picture->isIdr()) { codedBuffer->setFlag(ENCODE_BUFFERFLAG_SYNCFRAME); } if (!output(picture)) return ENCODE_INVALID_PARAMS; } INFO(); return ENCODE_SUCCESS; }