bool Decimate::get2(uint32_t *fn,ADMImage *data)
{
    bool forced = false;
    double metric;
    char buf[256];
    
    deciMate *_param=&configuration;
    int cycle=configuration.cycle;
    int sourceFrame = (nextFrame*cycle)/(cycle-1);
    int cycleStartFrame = (sourceFrame / cycle) * cycle;
    int useframe,dropframe;
    *fn=nextFrame;
    int inframe=nextFrame;
    ADMImage *src,*next;
    GETFRAME(sourceFrame, src);
    if(!src)
    {
        ADM_info("Decimate: End of video stream, cannot get frame %d\n",useframe);
        vidCache->unlockAll();
        return false;
    }
    nextFrame++;
    /* Delete the duplicate in the longest string of duplicates. */
    FindDuplicate2(cycleStartFrame, &dropframe, &forced);
    if (sourceFrame >= dropframe) 
        sourceFrame++;
    GETFRAME(sourceFrame, src);
    if(!src)
    {
        vidCache->unlockAll();
        return false;
    }
    data->duplicate(src);
    vidCache->unlockAll();
    if (configuration.show == true)
    {
        int start = (useframe / _param->cycle) * _param->cycle;


        sprintf(buf, "Decimate %d", 0);			DrawString(data, 0, 0, buf);
        sprintf(buf, "Copyright 2003 Donald Graft");			    DrawString(data, 0, 1, buf);
        sprintf(buf,"in frm %d, use frm %d", inframe, useframe);	DrawString(data, 0, 3, buf);
        sprintf(buf,"%d: %3.2f (%s)", cycleStartFrame, showmetrics[0], Dshow[0] ? "new" : "dup");	DrawString(data, 0, 4, buf);
        sprintf(buf,"%d: %3.2f (%s)", cycleStartFrame + 1, showmetrics[1],Dshow[1] ? "new" : "dup");DrawString(data, 0, 5, buf);
        sprintf(buf,"%d: %3.2f (%s)", cycleStartFrame + 2, showmetrics[2],Dshow[2] ? "new" : "dup");DrawString(data, 0, 6, buf);
        sprintf(buf,"%d: %3.2f (%s)", cycleStartFrame + 3, showmetrics[3],Dshow[3] ? "new" : "dup");DrawString(data, 0, 7, buf);
        sprintf(buf,"%d: %3.2f (%s)", cycleStartFrame + 4, showmetrics[4],Dshow[4] ? "new" : "dup");DrawString(data, 0, 8, buf);
        sprintf(buf,"Dropping frm %d%s", dropframe, last_forced == true ? " forced!" : "");
        DrawString(data, 0, 9, buf);
    }
    if (configuration.debug)
    {	
        sprintf(buf,"Decimate: inframe %d useframe %d\n", inframe, useframe);
        OutputDebugString(buf);
    }
    return true;
}
/**
    \fn getNextFrame
*/
bool Telecide::getNextFrame(uint32_t *frameNumber,ADMImage *output_image)
{
uint32_t pframe,nframe;

ADMImage *fc=NULL;
ADMImage *fp=NULL;
ADMImage *fn=NULL;
ADMImage *dst=NULL;
uint8_t *dstp;

ADMImage *final=NULL;
uint8_t *finalp;

unsigned int lowest;
unsigned int predicted;
unsigned int predicted_metric;
teleCide *_param=&configuration;


        *frameNumber=nextFrame;
        bool lastFrame=false;
        aprintf("telecide : frame %d\n",(int)nextFrame);
        // Get the current frame.
        uint32_t frame=nextFrame;
        if (frame < 0) frame = 0;
        
        GETFRAME(frame, fc);
        if(!fc)
        {
            ADM_warning("Telecide:Cannot get frame\n");
            vidCache->unlockAll();
            return false;
        }
        nextFrame++;
        output_image->copyInfo(fc); // copy timing information...

        // Get the previous frame.
        pframe = frame == 0 ? 0 : frame - 1;
        GETFRAME(pframe, fp);

        // Get the next frame metrics, we might need them.        
        nframe = frame + 1;
        GETFRAME(nframe, fn);
        if(!fn)
        {
            nframe=frame;
            GETFRAME(nframe, fn);
            ADM_assert(fn);
            lastFrame=true;
        }

        int pitch = fc->GetPitch(PLANAR_Y);
        
        
        int w = info.width;
        int h = info.height; 
        int hover2 = h >>1;
        int wover2 = w >>1;

        dst=output_image;
        int dpitch = dst->GetPitch(PLANAR_Y);

        // Ensure that the metrics for the frames
        // after the current frame are in the cache. They will be used for
        // pattern guidance.
        if (guide != GUIDE_NONE)
        {
                aprintf("Loop starting at %d +1, cycle=%d\n",frame,cycle);
                for (int y = frame + 1; y <= frame + cycle + 1; y++)
                {
                        if (lastFrame==true ) break;
                        if (CacheQuery(y, &p, &pblock, &c, &cblock) == false)
                        {
                                ADMImage *lc,*lp;

                                GETFRAME(y, lc);
                                GETFRAME(y == 0 ? 1 : y - 1, lp);
                                if(lc && lp)
                                    CalculateMetrics(y, lc,lp); //crp, crpU, crpV, prp, prpU, prpV);
                        }
                }
        }

        /* Check for manual overrides of the field matching. */
        
        found = false;
        film = true;
        
        inpattern = false;
        vthresh = vthresh_saved;
        back = back_saved;
        // Get the metrics for the current-previous (p), current-current (c), and current-next (n) match candidates.
        if (CacheQuery(frame, &p, &pblock, &c, &cblock) == false)
        {
                CalculateMetrics(frame, fc, fp); //fcrp, fcrpU, fcrpV, fprp, fprpU, fprpV);
                CacheQuery(frame, &p, &pblock, &c, &cblock);
        }
        if (CacheQuery(nframe, &np, &npblock, &nc, &ncblock) == false)
        {
                CalculateMetrics(nframe, fn,fc); //fnrp, fnrpU, fnrpV, fcrp, fcrpU, fcrpV);
                CacheQuery(nframe, &np, &npblock, &nc, &ncblock);
        }

        // Determine the best candidate match.
        if (found != true)
        {
                lowest = c;
                chosen = C;
                if (back == ALWAYS_BACK && p < lowest)
                {
                        lowest = p;
                        chosen = P;
                }
                if (np < lowest)
                {
                        lowest = np;
                        chosen = N;
                }
        }
        if ((frame == 0 && chosen == P) || (lastFrame==true && chosen == N))
        {
                chosen = C;
                lowest = c;
        }

        // See if we can apply pattern guidance.
        mismatch = 100.0;
        if (guide != GUIDE_NONE)
        {
                bool hard = false;
                if (frame >= cycle && PredictHardYUY2(frame, &predicted, &predicted_metric) == true)
                {
                        inpattern = true;
                        mismatch = 0.0;
                        hard = true;
                        if (chosen != predicted)
                        {
                                // The chosen frame doesn't match the prediction.
                                if (predicted_metric == 0) mismatch = 0.0;
                                else mismatch = (100.0*abs((int)predicted_metric - (int)lowest))/predicted_metric;
                                if (mismatch < gthresh)
                                {
                                        // It's close enough, so use the predicted one.
                                        if (found != true)
                                        {
                                                chosen = predicted;
                                                override = true;
                                        }
                                }
void  vidUnblend::Findblend(int frame, int *bblend)

{
	int f, x, y,pitchY,row_sizeY,heightY;
	ADMImage *store[5];
	const unsigned char *storepY[5];
	float t;
	float metric02, metric13, metric24;
	int metric_count02, metric_count13, metric_count24;
	int count02, count13, count24;
	float p0, p1, p2, p3, p4;
	float percent02, percent13, percent24;
        int vi_height=_info.height;
        int vi_width=_info.width;
		
	if (firsttime == true || frame == 0)
	{
		firsttime=false;
		reference=0;
	}

	for (f = 0; f <= 4; f++)
	{
		GETFRAME(frame + f - 1, store[f]);
		storepY[f] = store[f]->data; //store[f]->GetReadPtr(PLANAR_Y);
	}

    pitchY = _info.width;    //store[0]->GetPitch(PLANAR_Y);
    row_sizeY = _info.width; //store[0]->GetRowSize(PLANAR_Y);
    heightY = _info.height;  //store[0]->GetHeight(PLANAR_Y);
		
	metric_count02=1;
	metric02=0;
	metric_count13=1;
	metric13=0;
	metric_count24=1;
	metric24=0;
	count02=0;
	count13=0;
	count24=0;

	for ( y=0; y<vi_height-1; y=y+2) 
	{
	    for ( x=0; x<row_sizeY-1; x=x+2) {
			
			p0 = (float)(storepY[0][x] + storepY[0][x+pitchY])/2;
			p1 = (float)(storepY[1][x] + storepY[1][x+pitchY])/2;
			p2 = (float)(storepY[2][x] + storepY[2][x+pitchY])/2;
			p3 = (float)(storepY[3][x] + storepY[3][x+pitchY])/2;
			p4 = (float)(storepY[4][x] + storepY[4][x+pitchY])/2;
			
			t=1000;
			if (fabs(p1- p3)>_param->threshold ) {
				t = 255 * (p2 - p1)/(p3 - p1);	// tmax = +-255/1   tmin = +-1/255
				if (t>32 && t<224) {
					count13++;
					metric_count13++;
					metric13 = metric13 + t;
				} else {
					count13--;
				}
			}

			// prev frame
			if (fabs(p0 - p2)>_param->threshold ) {
				t = 255 * (p1 - p0)/(p2 - p0);
				if (t>32 && t<224) {
					count02++;
					metric02 = metric02 + t;
					metric_count02++;
				} else {
					count02--;
				}
			}
			// next frame
			if (fabs(p2 - p4)>_param->threshold ) {
				t = 255 * (p3 - p2)/(p4 - p2);
				if (t>32 && t<224) {
					count24++;
					metric24 = metric24 + t;
					metric_count24++;
				} else {
					count24--;
				}
			}
		}

		storepY[0] += 2 * pitchY;
		storepY[1] += 2 * pitchY;
		storepY[2] += 2 * pitchY;
		storepY[3] += 2 * pitchY;
		storepY[4] += 2 * pitchY;
	}

	metric02 = metric02 / metric_count02;
	metric13 = metric13 / metric_count13;
	metric24 = metric24 / metric_count24;

	percent02 = (float)200 * count02 / (vi_height * vi_width);
	percent13 = (float)200 * count13 / (vi_height * vi_width);
	percent24 = (float)200 * count24 / (vi_height * vi_width);

        if(_param->show)
        {
                printf("PC02:%f PC13:%f PC24:%f\n",percent02,percent13,percent24);
                printf("Metric13:%f \n",metric13);
        }

	if (percent13>_param->dthresh && (percent02<_param->dthresh ) && (percent24<_param->dthresh )) 
	{
                if(_param->show) printf("BLENDED\n");
		if (metric13<128 && metric13>32) reference=(-1);
		else if(metric13>128 && metric13<224) reference=1;
	}
	else reference=0;
	
	*bblend = reference;
	
}
//______________________________________________________________________
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;
	}
Exemple #5
0
void
CAnimManager::LoadAnimFile(int fd, bool removeUncompressed)
{
	#define ROUNDSIZE(x) if((x) & 3) (x) += 4 - ((x)&3)
	struct IfpHeader {
		char ident[4];
		RwUInt32 size;
	};
	IfpHeader anpk, info, name, dgan, cpan, anim;
	int numANPK;
	char buf[256];
	float *fbuf = (float*)buf;

	CFileMgr::Read(fd, &anpk, sizeof(IfpHeader));
	if(strncmp(anpk.ident, "ANLF", 4) == 0){
		ROUNDSIZE(anpk.size);
		CFileMgr::Read(fd, buf, anpk.size);
		numANPK = *(int*)buf;
	}else if(strncmp(anpk.ident, "ANPK", 4) == 0){
		CFileMgr::Seek(fd, -8, 1);
		numANPK = 1;
	}

	for(int i = 0; i < numANPK; i++){
		CFileMgr::Read(fd, &anpk, sizeof(IfpHeader));
		ROUNDSIZE(anpk.size);
		CFileMgr::Read(fd, &info, sizeof(IfpHeader));
		ROUNDSIZE(info.size);
		CFileMgr::Read(fd, buf, info.size);
		CAnimBlock *animBlock = &CAnimManager::ms_aAnimBlocks[CAnimManager::ms_numAnimBlocks++];
		strncpy(animBlock->name, buf+4, 24);
		animBlock->numAnims = *(int*)buf;
		animBlock->animIndex = CAnimManager::ms_numAnimations;
		for(int j = 0; j < animBlock->numAnims; j++){
			CAnimBlendHierarchy *hier = &CAnimManager::ms_aAnimations[CAnimManager::ms_numAnimations++];
			CFileMgr::Read(fd, &name, sizeof(IfpHeader));
			ROUNDSIZE(name.size);
			CFileMgr::Read(fd, buf, name.size);
			hier->SetName(buf);

			CFileMgr::Read(fd, &dgan, sizeof(IfpHeader));
			ROUNDSIZE(dgan.size);
			CFileMgr::Read(fd, &info, sizeof(IfpHeader));
			ROUNDSIZE(info.size);
			CFileMgr::Read(fd, buf, info.size);

			hier->numSequences = *(int*)buf;
			void *mem = gta_nw(sizeof(CAnimBlendSequence)*hier->numSequences + 8);
			hier->blendSequences = (CAnimBlendSequence*)construct_array(mem, &CAnimBlendSequence::ctor, &CAnimBlendSequence::dtor,
			                                                            sizeof(CAnimBlendSequence), hier->numSequences);
			CAnimBlendSequence *seq = hier->blendSequences;
			for(int k = 0; k < hier->numSequences; k++, seq++){
				CFileMgr::Read(fd, &cpan, sizeof(IfpHeader));
				ROUNDSIZE(dgan.size);
				CFileMgr::Read(fd, &anim, sizeof(IfpHeader));
				ROUNDSIZE(anim.size);
				CFileMgr::Read(fd, buf, anim.size);
				if(anim.size == 44)
					seq->SetBoneTag(*(int*)(buf+40));
				seq->SetName(buf);
				int numFrames = *(int*)(buf+28);
				if(numFrames == 0)
					continue;
				CFileMgr::Read(fd, &info, sizeof(info));
				if(strncmp(info.ident, "KR00", 4) == 0){
					seq->SetNumFrames(numFrames, 0);
					RFrame *frame = (RFrame*)GETFRAME(seq, 0);
					for(int l = 0; l < numFrames; l++, frame++){
						CFileMgr::Read(fd, buf, 0x14);
						frame->rot.x = -fbuf[0];
						frame->rot.y = -fbuf[1];
						frame->rot.z = -fbuf[2];
						frame->rot.w = fbuf[3];
						frame->time = fbuf[4];
					}
				}else if(strncmp(info.ident, "KRT0", 4) == 0){
					seq->SetNumFrames(numFrames, 1);
					RTFrame *frame = (RTFrame*)GETFRAME(seq, 0);
					for(int l = 0; l < numFrames; l++, frame++){
						CFileMgr::Read(fd, buf, 0x20);
						frame->rot.x = -fbuf[0];
						frame->rot.y = -fbuf[1];
						frame->rot.z = -fbuf[2];
						frame->rot.w = fbuf[3];
						frame->pos.x = fbuf[4];
						frame->pos.y = fbuf[5];
						frame->pos.z = fbuf[6];
						frame->time = fbuf[7];
					}
				}else if(strncmp(info.ident, "KRTS", 4) == 0){
					seq->SetNumFrames(numFrames, 1);
					RTFrame *frame = (RTFrame*)GETFRAME(seq, 0);
					for(int l = 0; l < numFrames; l++, frame++){
						CFileMgr::Read(fd, buf, 0x2C);
						frame->rot.x = -fbuf[0];
						frame->rot.y = -fbuf[1];
						frame->rot.z = -fbuf[2];
						frame->rot.w = fbuf[3];
						frame->pos.x = fbuf[4];
						frame->pos.y = fbuf[5];
						frame->pos.z = fbuf[6];
						frame->time = fbuf[10];
					}
				}
				for(int l = seq->numFrames-1; l > 0; l--){
					RFrame *f1 = (RFrame*)GETFRAME(seq, l);
					RFrame *f2 = (RFrame*)GETFRAME(seq, l-1);
					f1->time -= f2->time;
				}
			}
			hier->RemoveQuaternionFlips();
			if(removeUncompressed)
				hier->RemoveUncompressedData();
			else
				hier->CalcTotalTime();
		}
	}
}
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;
}