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; }
void VaapiDecoderH264::initPicturePOC0(VaapiPictureH264 * picture, H264SliceHdr * sliceHdr) { H264PPS *const pps = sliceHdr->pps; H264SPS *const sps = pps->sequence; const int32_t MaxPicOrderCntLsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); int32_t tempPOC; if (VAAPI_H264_PICTURE_IS_IDR(picture)) { m_prevPOCMsb = 0; m_prevPOCLsb = 0; } else if (m_prevPicHasMMCO5) { m_prevPOCMsb = 0; m_prevPOCLsb = (m_prevPicStructure == VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD ? 0 : m_fieldPoc[TOP_FIELD]); } else { m_prevPOCMsb = m_POCMsb; m_prevPOCLsb = m_POCLsb; } // (8-3) m_POCLsb = sliceHdr->pic_order_cnt_lsb; if (m_POCLsb < m_prevPOCLsb && (m_prevPOCLsb - m_POCLsb) >= (MaxPicOrderCntLsb / 2)) m_POCMsb = m_prevPOCMsb + MaxPicOrderCntLsb; else if (m_POCLsb > m_prevPOCLsb && (m_POCLsb - m_prevPOCLsb) > (MaxPicOrderCntLsb / 2)) m_POCMsb = m_prevPOCMsb - MaxPicOrderCntLsb; else m_POCMsb = m_prevPOCMsb; tempPOC = m_POCMsb + m_POCLsb; switch (picture->m_structure) { case VAAPI_PICTURE_STRUCTURE_FRAME: // (8-4, 8-5) m_fieldPoc[TOP_FIELD] = tempPOC; m_fieldPoc[BOTTOM_FIELD] = tempPOC + sliceHdr->delta_pic_order_cnt_bottom; break; case VAAPI_PICTURE_STRUCTURE_TOP_FIELD: // (8-4) m_fieldPoc[TOP_FIELD] = tempPOC; break; case VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD: // (8-5) m_fieldPoc[BOTTOM_FIELD] = tempPOC; break; } }
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::initPicture(VaapiPictureH264 * picture, H264SliceHdr * sliceHdr, H264NalUnit * nalu) { H264SPS *const sps = sliceHdr->pps->sequence; m_prevFrameNum = m_frameNum; m_frameNum = sliceHdr->frame_num; picture->m_frameNum = m_frameNum; picture->m_frameNumWrap = m_frameNum; picture->m_outputFlag = true; /* XXX: conformant to Annex A only */ picture->m_timeStamp = m_currentPTS; /* Reset decoder state for IDR pictures */ if (nalu->idr_pic_flag) { DEBUG("H264: IDR frame detected"); VAAPI_PICTURE_FLAG_SET(picture, VAAPI_PICTURE_FLAG_IDR); m_DPBManager->flushDPB(); m_prevFrame = NULL; } /* Initialize slice type */ switch (sliceHdr->type % 5) { case H264_P_SLICE: picture->m_type = VAAPI_PICTURE_TYPE_P; break; case H264_B_SLICE: picture->m_type = VAAPI_PICTURE_TYPE_B; break; case H264_I_SLICE: picture->m_type = VAAPI_PICTURE_TYPE_I; break; case H264_SP_SLICE: picture->m_type = VAAPI_PICTURE_TYPE_SP; break; case H264_SI_SLICE: picture->m_type = VAAPI_PICTURE_TYPE_SI; break; } /* Initialize picture structure */ if (!sliceHdr->field_pic_flag) picture->m_picStructure = VAAPI_PICTURE_STRUCTURE_FRAME; else { VAAPI_PICTURE_FLAG_SET(picture, VAAPI_PICTURE_FLAG_INTERLACED); if (!sliceHdr->bottom_field_flag) picture->m_picStructure = VAAPI_PICTURE_STRUCTURE_TOP_FIELD; else picture->m_picStructure = VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD; } picture->m_structure = picture->m_picStructure; /* Initialize reference flags */ if (nalu->ref_idc) { H264DecRefPicMarking *const decRefPicMarking = &sliceHdr->dec_ref_pic_marking; if (VAAPI_H264_PICTURE_IS_IDR(picture) && decRefPicMarking->long_term_reference_flag) { VAAPI_PICTURE_FLAG_SET(picture, VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE); } else { VAAPI_PICTURE_FLAG_SET(picture, VAAPI_PICTURE_FLAG_SHORT_TERM_REFERENCE); } } initPicturePOC(picture, sliceHdr); m_DPBManager->initPictureRefs(picture, sliceHdr, m_frameNum); 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; }