void VaapiDecoderH264::initPicturePOC2(VaapiPictureH264 * picture, H264SliceHdr * sliceHdr) { H264PPS *const pps = sliceHdr->pps; H264SPS *const sps = pps->sequence; const int32_t maxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4); int32_t prevFrameNumOffset, tempPOC; if (m_prevPicHasMMCO5) prevFrameNumOffset = 0; else prevFrameNumOffset = m_frameNumOffset; // (8-11) if (VAAPI_H264_PICTURE_IS_IDR(picture)) m_frameNumOffset = 0; else if (m_prevFrameNum > m_frameNum) m_frameNumOffset = prevFrameNumOffset + maxFrameNum; else m_frameNumOffset = prevFrameNumOffset; // (8-12) if (VAAPI_H264_PICTURE_IS_IDR(picture)) tempPOC = 0; else if (!VAAPI_PICTURE_IS_REFERENCE(picture)) tempPOC = 2 * (m_frameNumOffset + m_frameNum) - 1; else tempPOC = 2 * (m_frameNumOffset + m_frameNum); // (8-13) if (picture->m_structure != VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD) m_fieldPoc[TOP_FIELD] = tempPOC; if (picture->m_structure != VAAPI_PICTURE_STRUCTURE_TOP_FIELD) m_fieldPoc[BOTTOM_FIELD] = tempPOC; }
bool VaapiDPBManager::execRefPicMarking(const PicturePtr& pic, bool * hasMMCO5) { *hasMMCO5 = false; if (!VAAPI_PICTURE_IS_REFERENCE(pic)) { return true; } if (!VAAPI_H264_PICTURE_IS_IDR(pic)) { H264SliceHdr* header = pic->getLastSliceHeader(); H264DecRefPicMarking *const decRefPicMarking = &header->dec_ref_pic_marking; if (decRefPicMarking->adaptive_ref_pic_marking_mode_flag) { if (!execRefPicMarkingAdaptive(pic, decRefPicMarking, hasMMCO5)) return false; } else { if (!execRefPicMarkingSlidingWindow(pic)) return false; } } return true; }
bool VaapiFrameStore::hasReference() { uint32_t i; for (i = 0; i < m_numBuffers; i++) { if (!m_buffers[i]) continue; if (VAAPI_PICTURE_IS_REFERENCE(m_buffers[i])) return true; } return false; }
bool VaapiDPBManager::addDPB(const VaapiFrameStore::Ptr& newFrameStore, const PicturePtr& pic) { uint32_t i, j; VaapiFrameStore::Ptr frameStore; #ifdef __ENABLE_DEBUG__ debugDPBStatus(); #endif outputImmediateBFrame(); // Remove all unused pictures if (!VAAPI_H264_PICTURE_IS_IDR(pic)) { i = 0; while (i < DPBLayer->DPBCount) { frameStore = DPBLayer->DPB[i]; if (!frameStore->m_outputNeeded && !frameStore->hasReference()) { removeDPBIndex(i); } else i++; } } // C.4.5.1 - Storage and marking of a reference decoded picture into the DPB if (VAAPI_PICTURE_IS_REFERENCE(pic)) { while (DPBLayer->DPBCount == DPBLayer->DPBSize) { if (!bumpDPB()) return false; } DPBLayer->DPB[DPBLayer->DPBCount++] = newFrameStore; if (pic->m_outputFlag) { pic->m_outputNeeded = true; newFrameStore->m_outputNeeded++; } } // C.4.5.2 - Storage and marking of a non-reference decoded picture into the DPB else { if (!pic->m_outputFlag) return true; while (DPBLayer->DPBCount == DPBLayer->DPBSize) { bool foundPicture = false; for (i = 0; !foundPicture && i < DPBLayer->DPBCount; i++) { frameStore = DPBLayer->DPB[i]; if (!frameStore->m_outputNeeded) continue; for (j = 0; !foundPicture && j < frameStore->m_numBuffers; j++) foundPicture = frameStore->m_buffers[j]->m_outputNeeded && frameStore->m_buffers[j]->m_POC < pic->m_POC; } if (!foundPicture) { bool ret = true; if (newFrameStore->hasFrame()) { ret = outputDPB(newFrameStore, pic); } else { m_prevFrameStore = newFrameStore; // wait for a complete frame to render } return ret; } if (!bumpDPB()) return false; } DPBLayer->DPB[DPBLayer->DPBCount++] = newFrameStore; pic->m_outputNeeded = true; newFrameStore->m_outputNeeded++; } return true; }
bool VaapiDecoderH264::fillPicture(VaapiPictureH264 * picture, H264SliceHdr * sliceHdr, H264NalUnit * nalu) { uint32_t i, n; H264PPS *const pps = picture->m_pps; H264SPS *const sps = pps->sequence; VaapiDecPicBufLayer *DPBLayer = m_DPBManager->DPBLayer; VaapiBufObject *picParamObj = picture->m_picParam; VAPictureParameterBufferH264 *picParam = (VAPictureParameterBufferH264 *) picParamObj->map(); /* Fill in VAPictureParameterBufferH264 */ vaapiFillPicture(&picParam->CurrPic, picture, 0); for (i = 0, n = 0; i < DPBLayer->DPBCount; i++) { VaapiFrameStore *const frameStore = DPBLayer->DPB[i]; if (frameStore && frameStore->hasReference()) vaapiFillPicture(&picParam->ReferenceFrames[n++], frameStore->m_buffers[0], frameStore->m_structure); } for (; n < N_ELEMENTS(picParam->ReferenceFrames); n++) vaapiInitPicture(&picParam->ReferenceFrames[n]); #define COPY_FIELD(s, f) \ picParam->f = (s)->f #define COPY_BFM(a, s, f) \ picParam->a.bits.f = (s)->f picParam->picture_width_in_mbs_minus1 = m_mbWidth - 1; picParam->picture_height_in_mbs_minus1 = m_mbHeight - 1; picParam->frame_num = m_frameNum; COPY_FIELD(sps, bit_depth_luma_minus8); COPY_FIELD(sps, bit_depth_chroma_minus8); COPY_FIELD(sps, num_ref_frames); COPY_FIELD(pps, num_slice_groups_minus1); COPY_FIELD(pps, slice_group_map_type); COPY_FIELD(pps, slice_group_change_rate_minus1); COPY_FIELD(pps, pic_init_qp_minus26); COPY_FIELD(pps, pic_init_qs_minus26); COPY_FIELD(pps, chroma_qp_index_offset); COPY_FIELD(pps, second_chroma_qp_index_offset); picParam->seq_fields.value = 0; /* reset all bits */ picParam->seq_fields.bits.residual_colour_transform_flag = sps->separate_colour_plane_flag; picParam->seq_fields.bits.MinLumaBiPredSize8x8 = sps->level_idc >= 31; /* A.3.3.2 */ COPY_BFM(seq_fields, sps, chroma_format_idc); COPY_BFM(seq_fields, sps, gaps_in_frame_num_value_allowed_flag); COPY_BFM(seq_fields, sps, frame_mbs_only_flag); COPY_BFM(seq_fields, sps, mb_adaptive_frame_field_flag); COPY_BFM(seq_fields, sps, direct_8x8_inference_flag); COPY_BFM(seq_fields, sps, log2_max_frame_num_minus4); COPY_BFM(seq_fields, sps, pic_order_cnt_type); COPY_BFM(seq_fields, sps, log2_max_pic_order_cnt_lsb_minus4); COPY_BFM(seq_fields, sps, delta_pic_order_always_zero_flag); picParam->pic_fields.value = 0; /* reset all bits */ picParam->pic_fields.bits.field_pic_flag = sliceHdr->field_pic_flag; picParam->pic_fields.bits.reference_pic_flag = VAAPI_PICTURE_IS_REFERENCE(picture); COPY_BFM(pic_fields, pps, entropy_coding_mode_flag); COPY_BFM(pic_fields, pps, weighted_pred_flag); COPY_BFM(pic_fields, pps, weighted_bipred_idc); COPY_BFM(pic_fields, pps, transform_8x8_mode_flag); COPY_BFM(pic_fields, pps, constrained_intra_pred_flag); COPY_BFM(pic_fields, pps, pic_order_present_flag); COPY_BFM(pic_fields, pps, deblocking_filter_control_present_flag); COPY_BFM(pic_fields, pps, redundant_pic_cnt_present_flag); picParamObj->unmap(); return true; }
void VaapiDecoderH264::initPicturePOC1(VaapiPictureH264 * picture, H264SliceHdr * sliceHdr) { H264PPS *const pps = sliceHdr->pps; H264SPS *const sps = pps->sequence; const int32_t maxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4); int32_t prevFrameNumOffset, absFrameNum, expectedPOC; uint32_t i; if (m_prevPicHasMMCO5) prevFrameNumOffset = 0; else prevFrameNumOffset = m_frameNumOffset; // (8-6) if (VAAPI_H264_PICTURE_IS_IDR(picture)) m_frameNumOffset = 0; else if (m_prevFrameNum > m_frameNum) m_frameNumOffset = prevFrameNumOffset + maxFrameNum; else m_frameNumOffset = prevFrameNumOffset; // (8-7) if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0) absFrameNum = m_frameNumOffset + m_frameNum; else absFrameNum = 0; if (!VAAPI_PICTURE_IS_REFERENCE(picture) && absFrameNum > 0) absFrameNum = absFrameNum - 1; if (absFrameNum > 0) { int32_t expectedDeltaPerPocCycle; int32_t pocCycleCnt, frameNumInPocCycle; expectedDeltaPerPocCycle = 0; for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++) expectedDeltaPerPocCycle += sps->offset_for_ref_frame[i]; // (8-8) pocCycleCnt = (absFrameNum - 1) / sps->num_ref_frames_in_pic_order_cnt_cycle; frameNumInPocCycle = (absFrameNum - 1) % sps->num_ref_frames_in_pic_order_cnt_cycle; // (8-9) expectedPOC = pocCycleCnt * expectedDeltaPerPocCycle; for (i = 0; (int32_t) i <= frameNumInPocCycle; i++) expectedPOC += sps->offset_for_ref_frame[i]; } else expectedPOC = 0; if (!VAAPI_PICTURE_IS_REFERENCE(picture)) expectedPOC += sps->offset_for_non_ref_pic; // (8-10) switch (picture->m_structure) { case VAAPI_PICTURE_STRUCTURE_FRAME: m_fieldPoc[TOP_FIELD] = expectedPOC + sliceHdr->delta_pic_order_cnt[0]; m_fieldPoc[BOTTOM_FIELD] = m_fieldPoc[TOP_FIELD] + sps->offset_for_top_to_bottom_field + sliceHdr->delta_pic_order_cnt[1]; break; case VAAPI_PICTURE_STRUCTURE_TOP_FIELD: m_fieldPoc[TOP_FIELD] = expectedPOC + sliceHdr->delta_pic_order_cnt[0]; break; case VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD: m_fieldPoc[BOTTOM_FIELD] = expectedPOC + sps->offset_for_top_to_bottom_field + sliceHdr->delta_pic_order_cnt[0]; break; } }
bool VaapiDecoderH264::isNewPicture(H264NalUnit * nalu, H264SliceHdr * sliceHdr) { H264PPS *const pps = sliceHdr->pps; H264SPS *const sps = pps->sequence; VaapiSliceH264 *slice; H264SliceHdr *prevSliceHdr; if (!m_currentPicture) return true; slice = (VaapiSliceH264 *) (m_currentPicture->getLastSlice()); if (!slice) return false; prevSliceHdr = &slice->m_sliceHdr; #define CHECK_EXPR(expr, field_name) do { \ if (!(expr)) { \ DEBUG(field_name " differs in value"); \ return true; \ } \ } while (0) #define CHECK_VALUE(newSliceHdr, oldSliceHdr, field) \ CHECK_EXPR(((newSliceHdr)->field == (oldSliceHdr)->field), #field) /* frame_num differs in value, regardless of inferred values to 0 */ CHECK_VALUE(sliceHdr, prevSliceHdr, frame_num); /* picParameter_set_id differs in value */ CHECK_VALUE(sliceHdr, prevSliceHdr, pps); /* field_pic_flag differs in value */ CHECK_VALUE(sliceHdr, prevSliceHdr, field_pic_flag); /* bottom_field_flag is present in both and differs in value */ if (sliceHdr->field_pic_flag && prevSliceHdr->field_pic_flag) CHECK_VALUE(sliceHdr, prevSliceHdr, bottom_field_flag); /* nal_ref_idc differs in value with one of the nal_ref_idc values is 0 */ CHECK_EXPR(((VAAPI_PICTURE_IS_REFERENCE(m_currentPicture) ^ (nalu->ref_idc != 0)) == 0), "nal_ref_idc"); /* POC type is 0 for both and either pic_order_cnt_lsb differs in value or delta_pic_order_cnt_bottom differs in value */ if (sps->pic_order_cnt_type == 0) { CHECK_VALUE(sliceHdr, prevSliceHdr, pic_order_cnt_lsb); if (pps->pic_order_present_flag && !sliceHdr->field_pic_flag) CHECK_VALUE(sliceHdr, prevSliceHdr, delta_pic_order_cnt_bottom); } /* POC type is 1 for both and either delta_pic_order_cnt[0] differs in value or delta_pic_order_cnt[1] differs in value */ else if (sps->pic_order_cnt_type == 1) { CHECK_VALUE(sliceHdr, prevSliceHdr, delta_pic_order_cnt[0]); CHECK_VALUE(sliceHdr, prevSliceHdr, delta_pic_order_cnt[1]); } /* IdrPicFlag differs in value */ CHECK_EXPR(((VAAPI_H264_PICTURE_IS_IDR(m_currentPicture) ^ (nalu->type == H264_NAL_SLICE_IDR)) == 0), "IdrPicFlag"); /* IdrPicFlag is equal to 1 for both and idr_pic_id differs in value */ if (VAAPI_H264_PICTURE_IS_IDR(m_currentPicture)) CHECK_VALUE(sliceHdr, prevSliceHdr, idr_pic_id); #undef CHECK_EXPR #undef CHECK_VALUE return false; }