//----------------------------------------------------------
const char * CSingleAllocTextBlock::StoreText(const char * textIn, bool doDuplicateCheck)
{
	const char * reply = NULL;

	if (textIn)
	{
		reply = doDuplicateCheck ? FindDuplicate(textIn) : NULL;
		if (reply == NULL)
		{
			CRY_ASSERT_MESSAGE(m_mem != NULL, "No memory has been allocated!");
			if (cry_strncpy(m_mem + m_numBytesUsed, textIn, m_sizeNeeded - m_numBytesUsed))
			{
				reply = m_mem + m_numBytesUsed;
				m_numBytesUsed += strlen(reply) + 1;
				if (doDuplicateCheck)
				{
					RememberPossibleDuplicate(reply);
				}
			}
#ifndef _RELEASE
			else
			{
				GameWarning("Tried to store too much text in a single-alloc text block of size %" PRISIZE_T " (%" PRISIZE_T " bytes have already been used, no room for '%s')", m_sizeNeeded, m_numBytesUsed, textIn);
			}
#endif
		}
		SingleAllocTextBlockLog ("Storing a copy of '%s', now used %u/%u bytes, %u bytes left", textIn, m_numBytesUsed, m_sizeNeeded, m_sizeNeeded - m_numBytesUsed);
	}

	CRY_ASSERT_TRACE (m_numBytesUsed <= m_sizeNeeded, ("Counters have been set to invalid values! Apparently used %d/%d bytes!", m_numBytesUsed, m_sizeNeeded));

	return reply;
}
void CHuiFxEffectCache::CreateL(MHuiFxEffectCacheNode *aNode)
    { // registration of fxml file
    MHuiFxEffectCacheNode *cachedNode = Find(aNode);
    MHuiFxEffectCacheNode *dupNode = FindDuplicate(aNode);
    if (cachedNode)
       { // found in cache => duplicate registration => no need to do anything
       cachedNode->Ref(1);
       delete aNode;
       }
    else if (dupNode)
        { // found same file already being loaded
        dupNode->Ref(1);
        delete aNode;
        }
    else
       { // not found in cache, so insert it and start parsing the effect.
       TInt id = UniqueId();
       IDNode n = { id, aNode };
       iDuplicateEffects.Append(n);

       TRAPD(err, aNode->HeavyOperationL(this, id)); // from empty to this instance
       if (err != KErrNone)
           {
           iDuplicateEffects.Remove(iDuplicateEffects.Count()-1);
           User::Leave(err);
           }
       }
    }
//----------------------------------------------------------
void CSingleAllocTextBlock::IncreaseSizeNeeded(const char * textIn, bool doDuplicateCheck)
{
	CRY_ASSERT_MESSAGE(m_mem == NULL, "Shouldn't try and increase size after memory allocation!");

	if (textIn)
	{
		size_t lengthIncludingTerminator = strlen(textIn) + 1;
		if (doDuplicateCheck == false || FindDuplicate(textIn) == NULL)
		{
			if (doDuplicateCheck)
			{
				RememberPossibleDuplicate(textIn);
			}
			m_sizeNeeded += lengthIncludingTerminator;
		}
		m_sizeNeededWithoutUsingDuplicates += lengthIncludingTerminator;
	}
}
//______________________________________________________________________
uint8_t Decimate::getFrameNumberNoAlloc(uint32_t frame, uint32_t *len,
				ADMImage *data,uint32_t *flags)
{
	int dropframe, useframe, nextfrm, wY, wUV, hY, hUV, x, y, pitchY, pitchUV, dpitchY, dpitchUV;
	ADMImage  *src, *next, *dst;
	unsigned char *srcrpY, *nextrpY, *dstwpY;
	unsigned char *srcrpU, *nextrpU, *dstwpU;
	unsigned char *srcrpV, *nextrpV, *dstwpV;
	uint32_t inframe=frame;
	double metric;
	char buf[255];

	*len=(_info.width*_info.height*3)>>1;
	num_frames_hi = _in->getInfo()->nb_frames; /* FIXME MEANX */
	if (_param->mode == 0)
	{
		bool forced = false;
		int start;

		/* Normal decimation. Remove the frame most similar to its preceding frame. */
		/* Determine the correct frame to use and get it. */
		useframe = inframe + inframe / (_param->cycle - 1);
		start = (useframe /  _param->cycle) * _param->cycle;
		FindDuplicate((useframe / _param->cycle) * _param->cycle, &dropframe, &metric, &forced);
		if (useframe >= dropframe) useframe++;
		GETFRAME(useframe, src);
		if (show == true)
		{
			sprintf(buf, "Decimate %s", VERSION);
			DrawString(src, 0, 0, buf);
			sprintf(buf, "Copyright 2003 Donald Graft");
			DrawString(src, 0, 1, buf);
			sprintf(buf,"%d: %3.2f", start, showmetrics[0]);
			DrawString(src, 0, 3, buf);
			sprintf(buf,"%d: %3.2f", start + 1, showmetrics[1]);
			DrawString(src, 0, 4, buf);
			sprintf(buf,"%d: %3.2f", start + 2, showmetrics[2]);
			DrawString(src, 0, 5, buf);
			sprintf(buf,"%d: %3.2f", start + 3, showmetrics[3]);
			DrawString(src, 0, 6, buf);
			sprintf(buf,"%d: %3.2f", start + 4, showmetrics[4]);
			DrawString(src, 0, 7, buf);
			sprintf(buf,"in frm %d, use frm %d", inframe, useframe);
			DrawString(src, 0, 8, buf);
			sprintf(buf,"dropping frm %d%s", dropframe, last_forced == true ? ", forced!" : "");
			DrawString(src, 0, 9, buf);
		}
		if (debug)
		{	
			if (!(inframe % _param->cycle))
			{
				sprintf(buf,"Decimate: %d: %3.2f\n", start, showmetrics[0]);
				OutputDebugString(buf);
				sprintf(buf,"Decimate: %d: %3.2f\n", start + 1, showmetrics[1]);
				OutputDebugString(buf);
				sprintf(buf,"Decimate: %d: %3.2f\n", start + 2, showmetrics[2]);
				OutputDebugString(buf);
				sprintf(buf,"Decimate: %d: %3.2f\n", start + 3, showmetrics[3]);
				OutputDebugString(buf);
				sprintf(buf,"Decimate: %d: %3.2f\n", start + 4, showmetrics[4]);
				OutputDebugString(buf);
			}
			sprintf(buf,"Decimate: in frm %d, use frm %d\n", inframe, useframe);
			OutputDebugString(buf);
			sprintf(buf,"Decimate: dropping frm %d%s\n", dropframe, last_forced == true ? ", forced!" : "");
			OutputDebugString(buf);
		}
	    //return src;
	        //memcpy(data,src,*len);

		data->duplicate(src);
		vidCache->unlockAll();
		  
		return 1;
	}
	else if (_param->mode == 1)
	{
		bool forced = false;
		int start = (inframe / _param->cycle) * _param->cycle;
		unsigned int hint, film = 1;

		GETFRAME(inframe, src);
	    	srcrpY = YPLANE(src); //(unsigned char *) src->GetReadPtr(PLANAR_Y);
		if (GetHintingData(srcrpY, &hint) == false)
		{
			film = hint & PROGRESSIVE;
//			if (film) OutputDebugString("film\n");
//			else OutputDebugString("video\n");
		}

		/* Find the most similar frame as above but replace it with a blend of
		   the preceding and following frames. */
		num_frames_hi = _in->getInfo()->nb_frames; /* FIXME MEANX */
		FindDuplicate((inframe / _param->cycle) * _param->cycle, &dropframe, &metric, &forced);
		if (!film || inframe != dropframe || (_param->threshold && metric > _param->threshold))
		{
			if (show == true)
			{

				sprintf(buf, "Decimate %s", VERSION);
				DrawString(src, 0, 0, buf);
				sprintf(buf, "Copyright 2003 Donald Graft");
				DrawString(src, 0, 1, buf);
				sprintf(buf,"%d: %3.2f", start, showmetrics[0]);
				DrawString(src, 0, 3, buf);
				sprintf(buf,"%d: %3.2f", start + 1, showmetrics[1]);
				DrawString(src, 0, 4, buf);
				sprintf(buf,"%d: %3.2f", start + 2, showmetrics[2]);
				DrawString(src, 0, 5, buf);
				sprintf(buf,"%d: %3.2f", start + 3, showmetrics[3]);
				DrawString(src, 0, 6, buf);
				sprintf(buf,"%d: %3.2f", start + 4, showmetrics[4]);
				DrawString(src, 0, 7, buf);
				sprintf(buf,"infrm %d", inframe);
				DrawString(src, 0, 8, buf);
				if (last_forced == false)
					sprintf(buf,"chose %d, passing through", dropframe);
				else
					sprintf(buf,"chose %d, passing through, forced!", dropframe);
				DrawString(src, 0, 9, buf);
			}
			if (debug)
			{
				if (!(inframe % _param->cycle))
				{
					sprintf(buf,"Decimate: %d: %3.2f\n", start, showmetrics[0]);
					OutputDebugString(buf);
					sprintf(buf,"Decimate: %d: %3.2f\n", start + 1, showmetrics[1]);
					OutputDebugString(buf);
					sprintf(buf,"Decimate: %d: %3.2f\n", start + 2, showmetrics[2]);
					OutputDebugString(buf);
					sprintf(buf,"Decimate: %d: %3.2f\n", start + 3, showmetrics[3]);
					OutputDebugString(buf);
					sprintf(buf,"Decimate: %d: %3.2f\n", start + 4, showmetrics[4]);
					OutputDebugString(buf);
				}
				sprintf(buf,"Decimate: in frm %d\n", inframe);
				OutputDebugString(buf);
				if (last_forced == false)
					sprintf(buf,"Decimate: chose %d, passing through\n", dropframe);
				else
					sprintf(buf,"Decimate: chose %d, passing through, forced!\n", dropframe);
				OutputDebugString(buf);
			}
			//return src;
			//memcpy(data,src,*len);

			data->duplicate(src);
			vidCache->unlockAll();
			return 1;
		}
		if (inframe < _in->getInfo()->nb_frames - 1) /* FIXME MEANX*/
			nextfrm = inframe + 1;
		else
			nextfrm = _in->getInfo()->nb_frames - 1;
		if (debug)
		{
			if (!(inframe % _param->cycle))
			{
				sprintf(buf,"Decimate: %d: %3.2f\n", start, showmetrics[0]);
				OutputDebugString(buf);
				sprintf(buf,"Decimate: %d: %3.2f\n", start + 1, showmetrics[1]);
				OutputDebugString(buf);
				sprintf(buf,"Decimate: %d: %3.2f\n", start + 2, showmetrics[2]);
				OutputDebugString(buf);
				sprintf(buf,"Decimate: %d: %3.2f\n", start + 3, showmetrics[3]);
				OutputDebugString(buf);
				sprintf(buf,"Decimate: %d: %3.2f\n", start + 4, showmetrics[4]);
				OutputDebugString(buf);
			}
			sprintf(buf,"Decimate: in frm %d\n", inframe);
			OutputDebugString(buf);
			if (last_forced == false)
				sprintf(buf,"Decimate: chose %d, blending %d and %d\n", dropframe, inframe, nextfrm);
			else
				sprintf(buf,"Decimate: chose %d, blending %d and %d, forced!\n", dropframe, inframe, nextfrm);
			OutputDebugString(buf);
		}
		GETFRAME(nextfrm, next);
		dst = data; //env->NewVideoFrame(vi);
		pitchY = _info.width; //src->GetPitch(PLANAR_Y);
		dpitchY = _info.width; //dst->GetPitch(PLANAR_Y);
		wY = _info.width; //src->GetRowSize(PLANAR_Y);
		hY = _info.height; //src->GetHeight(PLANAR_Y);
		pitchUV = _info.width>>1;// src->GetPitch(PLANAR_V);
		dpitchUV =_info.width>>1;// dst->GetPitch(PLANAR_V);
		wUV = _info.width>>1;//src->GetRowSize(PLANAR_V);
		hUV = _info.height>>1;//src->GetHeight(PLANAR_V);
		
		nextrpY = YPLANE(next); //next->GetReadPtr(PLANAR_Y);
		dstwpY = YPLANE( dst); //dst->GetWritePtr(PLANAR_Y);
#ifdef DECIMATE_MMX_BUILD_PLANE
		if (CpuCaps::hasSSE()) 
		{
			isse_blend_decimate_plane(dstwpY, srcrpY, nextrpY, wY, hY);
		} else {
#endif
			for (y = 0; y < hY; y++)
			{
				for (x = 0; x < wY; x++)
				{
					dstwpY[x] = ((int)srcrpY[x] + (int)nextrpY[x] ) >> 1;  
				}
				srcrpY += pitchY;
				nextrpY += pitchY;
				dstwpY += dpitchY;
			}
#ifdef DECIMATE_MMX_BUILD_PLANE
		}
#endif
		srcrpU =   UPLANE(src);//->GetReadPtr(PLANAR_U);
		nextrpU =   UPLANE(next);//->GetReadPtr(PLANAR_U);
		dstwpU =  UPLANE(dst);//->GetWritePtr(PLANAR_U);
#ifdef DECIMATE_MMX_BUILD_PLANE
		if (CpuCaps::hasSSE()) 
		{
			isse_blend_decimate_plane(dstwpU, srcrpU, nextrpU, wUV, hUV);
		} else {
#endif
			for (y = 0; y < hUV; y++)
			{
				for (x = 0; x < wUV; x++)
				{
					dstwpU[x] = ((int)srcrpU[x] + (int)nextrpU[x]) >> 1;
				}
				srcrpU += pitchUV;
				nextrpU += pitchUV;
				dstwpU += dpitchUV;
			}
#ifdef DECIMATE_MMX_BUILD_PLANE
		}
#endif
		srcrpV =   VPLANE(src);//->GetReadPtr(PLANAR_V);
		nextrpV =   VPLANE(next);//->GetReadPtr(PLANAR_V);
		dstwpV =   VPLANE(dst);//->GetWritePtr(PLANAR_V);

#ifdef DECIMATE_MMX_BUILD_PLANE
		if (CpuCaps::hasSSE()) { 
			isse_blend_decimate_plane(dstwpV, srcrpV, nextrpV, wUV, hUV );
		} else {
#endif
			for (y = 0; y < hUV; y++)
			{
				for (x = 0; x < wUV; x++)
				{
					dstwpV[x] = ((int)srcrpV[x] + + (int)nextrpV[x]) >> 1;
				}
				srcrpV += pitchUV;
				nextrpV += pitchUV;
				dstwpV += dpitchUV;
			}
#ifdef DECIMATE_MMX_BUILD_PLANE
		}
#endif
		if (show == true)
		{

			sprintf(buf, "Decimate %s", VERSION);
			DrawString(dst, 0, 0, buf);
			sprintf(buf, "Copyright 2003 Donald Graft");
			DrawString(dst, 0, 1, buf);
			sprintf(buf,"%d: %3.2f", start, showmetrics[0]);
			DrawString(dst, 0, 3, buf);
			sprintf(buf,"%d: %3.2f", start + 1, showmetrics[1]);
			DrawString(dst, 0, 4, buf);
			sprintf(buf,"%d: %3.2f", start + 2, showmetrics[2]);
			DrawString(dst, 0, 5, buf);
			sprintf(buf,"%d: %3.2f", start + 3, showmetrics[3]);
			DrawString(dst, 0, 6, buf);
			sprintf(buf,"%d: %3.2f", start + 4, showmetrics[4]);
			DrawString(dst, 0, 7, buf);
			sprintf(buf,"infrm %d", inframe);
			DrawString(dst, 0, 8, buf);
			if (last_forced == false)
				sprintf(buf,"chose %d, blending %d and %d",dropframe, inframe, nextfrm);
			else
				sprintf(buf,"chose %d, blending %d and %d, forced!", dropframe, inframe, nextfrm);
			DrawString(dst, 0, 9, buf);
		}
		//return dst;
		//memcpy(data,dst,*len);

		data->duplicate(dst);
		vidCache->unlockAll();		
		return 1;
	}
bool Decimate::get3(uint32_t *fn,ADMImage *data)
{
    bool forced = false;
    ADMImage *src,*next;
    int     dropframe;
    double  metric;
    char buf[256];
    
    deciMate *_param=&configuration;
    /* Decimate by removing a duplicate from film cycles and doing a
       blend rate conversion on the video cycles. */
    if (_param->cycle != 5)//	env->ThrowError("Decimate: mode=3 requires cycle=5");
    {
        ADM_error("Decimate: mode=3 requires cycle=5\n");
        return false;
    }
    int     sourceFrame = (nextFrame*5)/4;
    int     cycleStartFrame = (sourceFrame /5) * 5;
    
    *fn=nextFrame;
    GETFRAME(sourceFrame, src);
    if(!src)
    {
        ADM_info("Decimate: End of video stream, cannot get frame %d\n",sourceFrame);
        vidCache->unlockAll();
        return false;
    }
    int inframe=nextFrame;
    nextFrame++;
    FindDuplicate(cycleStartFrame, &dropframe, &metric, &forced);
    /* Use hints from Telecide about film versus video. Also use the difference
       metric of the most similar frame in the cycle; if it exceeds threshold,
       assume it's a video cycle. */
    if (!(inframe % 4))
    {
        all_video_cycle = false;
        if (_param->threshold && metric > _param->threshold)
        {
            all_video_cycle = true;
        }
        if ((hints_invalid == false) &&
            (!(hints[0] & PROGRESSIVE) ||
             !(hints[1] & PROGRESSIVE) ||
             !(hints[2] & PROGRESSIVE) ||
             !(hints[3] & PROGRESSIVE) ||
             !(hints[4] & PROGRESSIVE)))
        {
            all_video_cycle = true;
        }
    }
    if (all_video_cycle == false)
    {
        /* It's film, so decimate in the normal way. */
        if (sourceFrame >= dropframe) sourceFrame++;
        GETFRAME(sourceFrame, src);
        if(!src)
        {
            vidCache->unlockAll();
            return false;
        }
        data->duplicate(src);    
        vidCache->unlockAll();		
        DrawShow(data, sourceFrame, forced, dropframe, metric, inframe);			
        return true; // return src;
    }
    else 
    {
        switch(inframe %4)
        {
            case 0:
                /* It's a video cycle. Output the first frame of the cycle. */
                GETFRAME(sourceFrame, src);
                data->duplicate(src);
                vidCache->unlockAll();		
                break;
            case 3:
                /* It's a video cycle. Output the last frame of the cycle. */
                GETFRAME(sourceFrame+1, src);
                if(!src)
                {
                    vidCache->unlockAll();		
                    return false;
                }
                data->duplicate(src);
                vidCache->unlockAll();		
                break;
            case 1: case 2:
                /* It's a video cycle. Make blends for the remaining frames. */
                if ((inframe % 4) == 1)  // MEANX dont understand the difference ?
                {
                    GETFRAME(sourceFrame, src);
                    GETFRAME(sourceFrame+1, next);
                    if(!next) next=src;
                }
                else
                {
                    GETFRAME(sourceFrame + 1, src);
                    GETFRAME(sourceFrame, next);
                    if(!src) src=next;
                }
                data->blend(src,next);
                vidCache->unlockAll();
                break;
            default:
                ADM_assert(0);break;
        }
        DrawShow(data, 0, forced, dropframe, metric, inframe);
        return true; // return src;			
    }
    GETFRAME(sourceFrame, src); // MEANX : not sure (jw detected a problem here)
    data->duplicate(src);
    vidCache->unlockAll();		
    DrawShow(data, 0, forced, dropframe, metric, inframe);
	return true;
}
bool Decimate::get1(uint32_t *fn,ADMImage *data)
{
    bool    forced = false;
    ADMImage *src,*next;
    int useframe,dropframe;
    deciMate *_param=&configuration;
    int cycle=configuration.cycle;
    int sourceFrame = (nextFrame*cycle)/(cycle-1);
    int  cycleStartFrame = (sourceFrame / cycle) * cycle;
    unsigned int hint, film = 1;
    int inframe=nextFrame;
    double metric;
    char buf[256];
    
    GETFRAME(sourceFrame, src);
    if(!src)
    {
        ADM_info("Decimate: End of video stream, cannot get frame %d\n",useframe);
        vidCache->unlockAll();
        return false;
    }
    *fn=nextFrame;
    nextFrame++;


    if (GetHintingData(YPLANE(src), &hint) == false)
    {
        film = hint & PROGRESSIVE;
    }

    /* Find the most similar frame as above but replace it with a blend of
       the preceding and following frames. */
    FindDuplicate(cycleStartFrame, &dropframe, &metric, &forced);
    if (!film || sourceFrame != dropframe || (_param->threshold && metric > _param->threshold))
    {
        data->duplicate(src);
        vidCache->unlockAll();
        if (configuration.show == true)
        {

            sprintf(buf, "Decimate %d", 0);				DrawString(data, 0, 0, buf);
            sprintf(buf, "Copyright 2003 Donald Graft");				DrawString(data, 0, 1, buf);
            sprintf(buf,"%d: %3.2f", cycleStartFrame, showmetrics[0]);		    DrawString(data, 0, 3, buf);
            sprintf(buf,"%d: %3.2f", cycleStartFrame + 1, showmetrics[1]);		DrawString(data, 0, 4, buf);
            sprintf(buf,"%d: %3.2f", cycleStartFrame + 2, showmetrics[2]);		DrawString(data, 0, 5, buf);
            sprintf(buf,"%d: %3.2f", cycleStartFrame + 3, showmetrics[3]);		DrawString(data, 0, 6, buf);
            sprintf(buf,"%d: %3.2f", cycleStartFrame + 4, showmetrics[4]);		DrawString(data, 0, 7, buf);
            sprintf(buf,"infrm %d", inframe);
            DrawString(data, 0, 8, buf);
            if (last_forced == false)
                sprintf(buf,"chose %d, passing through", dropframe);
            else
                sprintf(buf,"chose %d, passing through, forced!", dropframe);
            DrawString(data, 0, 9, buf);
        }
        if (configuration.debug)
        {
            if (!(inframe % _param->cycle))
            {
                OutputDebugString("Decimate: %d: %3.2f\n", start, showmetrics[0]);
                OutputDebugString("Decimate: %d: %3.2f\n", start + 1, showmetrics[1]);
                OutputDebugString("Decimate: %d: %3.2f\n", start + 2, showmetrics[2]);
                OutputDebugString("Decimate: %d: %3.2f\n", start + 3, showmetrics[3]);
                OutputDebugString("Decimate: %d: %3.2f\n", start + 4, showmetrics[4]);
            }
            OutputDebugString("Decimate: in frm %d\n", inframe);
            
            if (last_forced == false)
            {
                OutputDebugString("Decimate: chose %d, passing through\n", dropframe);
            }
            else
            {
                OutputDebugString("Decimate: chose %d, passing through, forced!\n", dropframe);
            }
        }
        return true;
    }
    if (configuration.debug)
    {
        if (!(inframe % _param->cycle))
        {
            OutputDebugString( "Decimate: %d: %3.2f\n", start, showmetrics[0]);
            OutputDebugString( "Decimate: %d: %3.2f\n", start + 1, showmetrics[1]);
            OutputDebugString( "Decimate: %d: %3.2f\n", start + 2, showmetrics[2]);
            OutputDebugString( "Decimate: %d: %3.2f\n", start + 3, showmetrics[3]);
            OutputDebugString( "Decimate: %d: %3.2f\n", start + 4, showmetrics[4]);
        }
        OutputDebugString("Decimate: in frm %d\n", inframe);
        
        if (last_forced == false)
        {
            OutputDebugString("Decimate: chose %d, blending %d and %d\n", dropframe, inframe, nextfrm);
        }
        else
        {
            OutputDebugString("Decimate: chose %d, blending %d and %d, forced!\n", dropframe, inframe, nextfrm);
        }			
    }
    // Blend current frame with next frame
    GETFRAME(sourceFrame+1, next);
    if(!next)
        data->duplicate(src);
    else
        data->blend(src,next);
    vidCache->unlockAll();		
    if (configuration.show == true)
    {

        sprintf(buf, "Decimate %d", 0);			DrawString(data, 0, 0, buf);
        sprintf(buf, "Copyright 2003 Donald Graft");			DrawString(data, 0, 1, buf);
        sprintf(buf,"%d: %3.2f", cycleStartFrame, showmetrics[0]);		DrawString(data, 0, 3, buf);
        sprintf(buf,"%d: %3.2f", cycleStartFrame + 1, showmetrics[1]);	DrawString(data, 0, 4, buf);
        sprintf(buf,"%d: %3.2f", cycleStartFrame + 2, showmetrics[2]);	DrawString(data, 0, 5, buf);
        sprintf(buf,"%d: %3.2f", cycleStartFrame + 3, showmetrics[3]);	DrawString(data, 0, 6, buf);
        sprintf(buf,"%d: %3.2f", cycleStartFrame + 4, showmetrics[4]);	DrawString(data, 0, 7, buf);
        sprintf(buf,"infrm %d", inframe);
        DrawString(data, 0, 8, buf);
        if (last_forced == false)
            sprintf(buf,"chose %d, blending %d and %d",dropframe, sourceFrame, sourceFrame+1);
        else
            sprintf(buf,"chose %d, blending %d and %d, forced!", dropframe, sourceFrame, sourceFrame+1);
        DrawString(data, 0, 9, buf);
    }
    
    return true;
}
/**
        \fn get0
        \brief A B C... if B is close enough to A discard it.
*/
bool Decimate::get0(uint32_t *fn,ADMImage *data)
{
    
    bool forced = false;
    ADMImage *src,*next;
    double metric;
    char buf[256];
    int useframe,dropframe;
    int start;
    deciMate *_param=&configuration;
    /* Normal decimation. Remove the frame most similar to its preceding frame. */
    /* Determine the correct frame to use and get it. */
    int cycle=configuration.cycle;
    int sourceFrame = (nextFrame*cycle)/(cycle-1);
    int cycleStartFrame = (sourceFrame / cycle) * cycle;
    int inframe=nextFrame;
    *fn=nextFrame;
    GETFRAME(sourceFrame, src);
    if(!src)
    {
        ADM_info("Decimate: End of video stream, cannot get frame %d\n",useframe);
        vidCache->unlockAll();
        return false;
    }
    nextFrame++;

    
    FindDuplicate(cycleStartFrame, &dropframe, &metric, &forced);
    if (sourceFrame >= dropframe) sourceFrame++;
    GETFRAME(sourceFrame, src);
    if(!src)
    {
        vidCache->unlockAll();
        return false;
    }
    data->duplicate(src);
    vidCache->unlockAll();

    if (configuration.show == true)
    {
        sprintf(buf, "Decimate %d", 0);			                DrawString(data, 0, 0, buf);
        sprintf(buf, "Copyright 2003 Donald Graft");			DrawString(data, 0, 1, buf);
        sprintf(buf,"%d: %3.2f", start, showmetrics[0]);		DrawString(data, 0, 3, buf);
        sprintf(buf,"%d: %3.2f", start + 1, showmetrics[1]);	DrawString(data, 0, 4, buf);
        sprintf(buf,"%d: %3.2f", start + 2, showmetrics[2]);	DrawString(data, 0, 5, buf);
        sprintf(buf,"%d: %3.2f", start + 3, showmetrics[3]);	DrawString(data, 0, 6, buf);
        sprintf(buf,"%d: %3.2f", start + 4, showmetrics[4]);	DrawString(data, 0, 7, buf);
        sprintf(buf,"in frm %d, use frm %d", inframe, useframe);DrawString(data, 0, 8, buf);
        sprintf(buf,"dropping frm %d%s", dropframe, last_forced == true ? ", forced!" : "");
        DrawString(data, 0, 9, buf);
    }
    if (configuration.debug)
    {	
        if (!(inframe % _param->cycle))
        {
            OutputDebugString("Decimate: %d: %3.2f\n", start, showmetrics[0]);
            OutputDebugString("Decimate: %d: %3.2f\n", start + 1, showmetrics[1]);
            OutputDebugString("Decimate: %d: %3.2f\n", start + 2, showmetrics[2]);
            OutputDebugString("Decimate: %d: %3.2f\n", start + 3, showmetrics[3]);
            OutputDebugString("Decimate: %d: %3.2f\n", start + 4, showmetrics[4]);
        }
        OutputDebugString("Decimate: in frm %d, use frm %d\n", inframe, useframe);
        OutputDebugString("Decimate: dropping frm %d%s\n", dropframe, last_forced == true ? ", forced!" : "");
    }		  
    return true;
}