/**
 * get addresses of current picture buffer (Current picture is usually a picture to feed into image filter.)
 * If color space conversion is necessary, own1 will be used.
 * If color space conversion is not necessary, picture buffer will not be copied.
 *
 * @param[in] csp requested color space.
 * @param[in,out] pict current picture (will be modifed if necessary)
 * @param[in] full
 * @param[in,out] src[4] pointer to the array to receive the addresses
 * *return true if color space is changed.
 * stride will be set to TimgFilter::stride1
 */
bool TimgFilter::getCur(uint64_t csp,TffPict &pict,int full,const unsigned char **src[4])
{
    uint64_t wasAdj=pict.csp&FF_CSP_FLAGS_YUV_ADJ;
    csp_yuv_adj_to_plane(pict.csp,&pict.cspInfo,pict.rectFull.dy,pict.data,pict.stride);
    csp_yuv_order(pict.csp,pict.data,pict.stride);

    // if color space is different or FF_CSP_FLAGS_YUV_ADJ is different
    if (((csp&FF_CSPS_MASK)&(pict.csp&FF_CSPS_MASK))==0 || ((csp&FF_CSP_FLAGS_YUV_ADJ) && !wasAdj)) {
        if (!convert1) {
            convert1=new Tconvert(deci,pict.rectFull.dx,pict.rectFull.dy);
        }
        pict.convertCSP(csp_bestMatch(pict.csp,csp&FF_CSPS_MASK)|(csp&(FF_CSP_FLAGS_VFLIP|FF_CSP_FLAGS_YUV_ADJ|FF_CSP_FLAGS_YUV_ORDER)),own1,convert1);
        pict.setRO(false);
    }

    bool cspChanged=csp1!=pict.csp;
    csp1=pict.csp;
    const Trect &r=pictRect; //full?pict.rectFull:pict.rectClip;
    unsigned int i = 0;
    for (; i<pict.cspInfo.numPlanes; i++) {
        if (src[i]) {
            *src[i]=pict.data[i]+(full?0:pict.diff[i])+(pictHalf?r.x*pict.cspInfo.Bpp>>pict.cspInfo.shiftX[i]:0);
        }
        stride1[i]=pict.stride[i];
        dx1[i]=r.dx>>pict.cspInfo.shiftX[i];
        dy1[i]=r.dy>>pict.cspInfo.shiftY[i];
    }
    for (; i<4; i++) {
        src[i] = NULL;
        stride1[i] = 0;
        dx1[i] = 0;
        dy1[i] = 0;
    }
    return cspChanged;
}
STDMETHODIMP_(LRESULT) TffdshowEnc::compress(const BITMAPINFOHEADER *inhdr, const uint8_t *src, size_t /*srclen*/, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop)
{
    if (firstrun) {
        firstrun = false;
        showTrayIcon();
    }

    _mm_empty();
    inColorspace = getBMPcolorspace(inhdr, coSettings->incsps);
    if (inColorspace == FF_CSP_NULL) {
        return ICERR_BADFORMAT;
    }
    if (coSettings->flip) {
        inColorspace ^= FF_CSP_FLAGS_VFLIP;
    }
    if (globalSettings->isDyInterlaced && dy > (unsigned int)globalSettings->dyInterlaced) {
        inColorspace |= FF_CSP_FLAGS_INTERLACED;
    }
    params.quant = -1;
    params.frametype = FRAME_TYPE::UNKNOWN;
    params.keyframe = false;
    switch (cfgcomode) {
        case ENC_MODE::CBR:
        case ENC_MODE::VBR_QUAL:
            break;
        case ENC_MODE::VBR_QUANT:
            params.quant = getQuantQuant();
            break;
        case ENC_MODE::UNKNOWN:
            break;
        default:
            DPRINTF(_l("Invalid encoding mode"));
            return ICERR_ERROR;
    }

    params.gray = !!coSettings->gray;

    //if (!src || !srclen) return ICERR_ERROR;

    if (pict.csp != inColorspace) {
        pict.csp = inColorspace;
        pict.cspInfo = *csp_getInfo(pict.csp);
    }
    pict.setSize(dx, dy);
    pict.data[0] = (unsigned char*)src;
    pict.stride[0] = dx * pict.cspInfo.Bpp;
    if (src) {
        csp_yuv_adj_to_plane(pict.csp, &pict.cspInfo, dy, pict.data, pict.stride);
        csp_yuv_order(pict.csp, pict.data, pict.stride);
        csp_vflip(pict.csp, &pict.cspInfo, pict.data, pict.stride, dy);
    }

    if (!coSettings->isProc || !ffproc) {
        bool directYV12 = false;
        for (Tcsps::const_iterator c = enccsps.begin(); c != enccsps.end(); c++)
            if (*c == pict.csp) {
                directYV12 = true;
                break;
            }
        if (!directYV12) {
            if (!convert) {
                convert = new Tconvert(this, dx, dy);
            }
            if (!ownpict.data[0]) {
                ownpict.alloc(dx, dy, enccsp, ownpictbuf);
            }
            if (src) {
                convert->convert(pict, ownpict.csp, ownpict.data, ownpict.stride);
            }
            //srclen=ownpict.cspInfo.bpp*ownpict.rectFull.dx*ownpict.rectFull.dy/8;
            pict = ownpict;
            if (!src) {
                pict.data[0] = NULL;
            }
        }
    }

    params.length = 0;
    params.priv = NULL;
    pict.rtStart = rtStart;
    pict.rtStop = rtStop;
    if (src && coSettings->isProc && ffproc) {
        HRESULT hr = ffproc->processPict(params.framenum, pict, enccsp);
        if (hr == S_OK) {
            hr = src ? enc->compress(pict, params) : enc->flushEnc(pict, params);
        }
        return hr;
    } else {
        return src ? enc->compress(pict, params) : enc->flushEnc(pict, params);
    }
}