Exemple #1
0
Encode_Status VaapiEncoderH264::encodePicture(const PicturePtr& picture)
{
    Encode_Status ret = ENCODE_FAIL;

    SurfacePtr reconstruct = createSurface();
    if (!reconstruct)
        return ret;
    {
        AutoLock locker(m_paramLock);

#ifdef __BUILD_GET_MV__
        uint32_t size;
        void *buffer = NULL;
        getMVBufferSize(&size);
        if (!picture->editMVBuffer(buffer, &size))
            return ret;
#endif
        if (!ensureSequence (picture))
            return ret;
        if (!ensureMiscParams (picture.get()))
            return ret;
        if (!ensurePicture(picture, reconstruct))
            return ret;
        if (!ensureSlices (picture))
            return ret;
    }
    if (!picture->encode())
        return ret;

    if (!referenceListUpdate (picture, reconstruct))
        return ret;

    return ENCODE_SUCCESS;
}
static void
setH264PictureReference(VaapiDecPictureH264* picture,
                        uint32_t referenceFlags, bool otherField)
{
    VAAPI_PICTURE_FLAG_UNSET(picture, VAAPI_PICTURE_FLAGS_REFERENCE);
    VAAPI_PICTURE_FLAG_SET(picture, referenceFlags);

    PicturePtr strong;
    if (!otherField || !(strong = picture->m_otherField.lock()))
        return ;
    VaapiDecPictureH264* other = strong.get();
    VAAPI_PICTURE_FLAG_UNSET(other, VAAPI_PICTURE_FLAGS_REFERENCE);
    VAAPI_PICTURE_FLAG_SET(other, referenceFlags);
}
bool VaapiDPBManager::execDummyPictureMarking(const PicturePtr& dummyPic,
                                              const SliceHeaderPtr& sliceHdr,
                                              int32_t frameNum)
{
    initPictureRefLists(dummyPic);
    initPictureRefsPicNum(dummyPic, sliceHdr, frameNum);
    if (!execRefPicMarkingSlidingWindow(dummyPic))
        return false;
    removeShortReference(dummyPic);
    /* add to short reference */
    DPBLayer->shortRef[DPBLayer->shortRefCount++] = dummyPic.get();

    return true;
}
bool VaapiDPBManager::execRefPicMarkingSlidingWindow(const PicturePtr& picture)
{
    H264PPS *const pps = picture->m_pps;
    H264SPS *const sps = pps->sequence;
    VaapiDecPictureH264 *refPicture;
    uint32_t i, m, maxNumRefFrames;

    if (!VAAPI_PICTURE_IS_FIRST_FIELD(picture))
        return true;

    maxNumRefFrames = sps->num_ref_frames;

    if (maxNumRefFrames == 0)
        maxNumRefFrames = 1;
    if (!VAAPI_PICTURE_IS_FRAME(picture))
        maxNumRefFrames <<= 1;

    if (DPBLayer->shortRefCount + DPBLayer->longRefCount < maxNumRefFrames)
        return true;
    if (DPBLayer->shortRefCount < 1)
        return false;

    for (m = 0, i = 1; i < DPBLayer->shortRefCount; i++) {
        VaapiDecPictureH264 *const pic = DPBLayer->shortRef[i];
        if (pic->m_frameNumWrap < DPBLayer->shortRef[m]->m_frameNumWrap)
            m = i;
    }

    refPicture = DPBLayer->shortRef[m];
    setH264PictureReference(refPicture, 0, true);
    ARRAY_REMOVE_INDEX(DPBLayer->shortRef, m);

    /* Both fields need to be marked as "unused for reference", so
       remove the other field from the shortRef[] list as well */
    if (!VAAPI_PICTURE_IS_FRAME(picture)) {
        PicturePtr strong = refPicture->m_otherField.lock();
        VaapiDecPictureH264* other = strong.get();
        if (other) {
            for (i = 0; i < DPBLayer->shortRefCount; i++) {
                if (DPBLayer->shortRef[i] == other) {
                    ARRAY_REMOVE_INDEX(DPBLayer->shortRef, i);
                    break;
                }
            }
        }
    }

    return true;
}
void VaapiDPBManager::removeShortReference(const PicturePtr& picture)
{
    VaapiDecPictureH264 *refPicture;
    uint32_t i;
    uint32_t frameNum = picture->m_frameNum;

    PicturePtr strong = picture->m_otherField.lock();
    VaapiDecPictureH264* other = strong.get();
    for (i = 0; i < DPBLayer->shortRefCount; ++i) {
        if (DPBLayer->shortRef[i]->m_frameNum == frameNum) {
            refPicture = DPBLayer->shortRef[i];
            if (refPicture != other) {
                setH264PictureReference(refPicture, 0, false);
                ARRAY_REMOVE_INDEX(DPBLayer->shortRef, i);
            }
            return;
        }
    }
}
bool VaapiDPBManager::outputDPB(const VaapiFrameStore::Ptr &frameStore,
                                const PicturePtr& picture)
{
    picture->m_outputNeeded = false;

    PicturePtr frame;
    if (frameStore) {
        if (--frameStore->m_outputNeeded > 0)
            return true;
        frame = frameStore->m_buffers[0];
    }

    DEBUG("DPB: output picture(Addr:%p, Poc:%d)", picture.get(), picture->m_POC);

//FIXME:
#if 0
    if (!frameStore)
        picture->m_surfBuf->status &= ~SURFACE_DECODING;
#endif
    return m_decoder->outputPicture(frame) == DECODE_SUCCESS;
}
bool VaapiDPBManager::execRefPicMarkingAdaptive1(const PicturePtr& picture,
                                                 H264RefPicMarking *refPicMarking,
                                                 uint32_t MMCO)
{
    uint32_t picNumX, i;
    int32_t longTermFrameIdx;
    VaapiDecPictureH264 *refPicture;
    int32_t foundIdx = 0;

    switch (MMCO) {
    case 1:
        {
            picNumX = getPicNumX(picture, refPicMarking);
            foundIdx = findShortRermReference(picNumX);
            if (foundIdx < 0)
                return false;

            i = (uint32_t) foundIdx;
            setH264PictureReference(DPBLayer->shortRef[i], 0,
                                    VAAPI_PICTURE_IS_FRAME(picture));
            ARRAY_REMOVE_INDEX(DPBLayer->shortRef, i);
        }
        break;
    case 2:
        {
            foundIdx =
                findLongTermReference(refPicMarking->long_term_pic_num);
            if (foundIdx < 0)
                return false;

            i = (uint32_t) foundIdx;
            setH264PictureReference(DPBLayer->longRef[i], 0,
                                    VAAPI_PICTURE_IS_FRAME(picture));
            ARRAY_REMOVE_INDEX(DPBLayer->longRef, i);
        }
        break;
    case 3:
        {
            for (i = 0; i < DPBLayer->longRefCount; i++) {
                if ((int32_t) DPBLayer->longRef[i]->m_longTermFrameIdx ==
                    refPicMarking->long_term_frame_idx)
                    break;
            }

            if (i != DPBLayer->longRefCount) {
                setH264PictureReference(DPBLayer->longRef[i], 0, true);
                ARRAY_REMOVE_INDEX(DPBLayer->longRef, i);
            }

            picNumX = getPicNumX(picture, refPicMarking);
            foundIdx = findShortRermReference(picNumX);
            if (foundIdx < 0)
                return false;

            i = (uint32_t) foundIdx;
            refPicture = DPBLayer->shortRef[i];
            ARRAY_REMOVE_INDEX(DPBLayer->shortRef, i);
            DPBLayer->longRef[DPBLayer->longRefCount++] = refPicture;

            refPicture->m_longTermFrameIdx =
                refPicMarking->long_term_frame_idx;
            setH264PictureReference(refPicture,
                                    VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE,
                                    VAAPI_PICTURE_IS_FRAME(picture));
        }
        break;
    case 4:
        {
            longTermFrameIdx =
                refPicMarking->max_long_term_frame_idx_plus1 - 1;

            for (i = 0; i < DPBLayer->longRefCount; i++) {
                if (DPBLayer->longRef[i]->m_longTermFrameIdx <=
                    longTermFrameIdx)
                    continue;
                setH264PictureReference(DPBLayer->longRef[i], 0, false);
                ARRAY_REMOVE_INDEX(DPBLayer->longRef, i);
                i--;
            }
        }
        break;
    case 5:
        {
            flushDPB();
            /* The picture shall be inferred to have had frame_num equal to 0 (7.4.3) */
            picture->m_frameNum = 0;

            /* Update TopFieldOrderCnt and BottomFieldOrderCnt (8.2.1) */
            if (picture->m_structure !=
                VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD)
                picture->m_fieldPoc[TOP_FIELD] -= picture->m_POC;
            if (picture->m_structure != VAAPI_PICTURE_STRUCTURE_TOP_FIELD)
                picture->m_fieldPoc[BOTTOM_FIELD] -= picture->m_POC;

            picture->m_POC = 0;

            if (VAAPI_H264_PICTURE_IS_SHORT_TERM_REFERENCE(picture))
                removeShortReference(picture);
        }
        break;
    case 6:
        {
            picture->m_longTermFrameIdx =
                refPicMarking->long_term_frame_idx;
            setH264PictureReference(picture.get(),
                                    VAAPI_PICTURE_FLAG_LONG_TERM_REFERENCE,
                                    false);
        }
        break;
    default:
        ERROR("unsupported MMCO type %d", MMCO);
        break;
    }
    return true;
}