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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 4
0
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;
}