예제 #1
0
// compare image helper
int CCapsImage::CompareImage()
{
	PDISKTRACKINFO pti=di.pdt;

	int res=imgeOk;

	// default track size
	pti->tracklen=pti->ci.trksize;

	// generate 1 revolution
	pti->trackcnt=1;

	// unformatted track ignored
	if (pti->ci.dentype == cpdenNoise)
		pti->trackcnt=0;

	pti->tracklen*=pti->trackcnt;

	// allocate and set buffer
	if (pti->tracklen) {
		pti->trackbuf=new UBYTE[pti->tracklen];
		memset(pti->trackbuf, 0, pti->tracklen);
	}

	// set track size and pointer
	pti->trackdata[0]=pti->trackbuf;
	pti->tracksize[0]=0;
	pti->trackstart[0]=0;

	// decoder start position is always 0
	pti->comppos=0;
	pti->sdpos=0;

	// decode blocks
	if (pti->trackcnt) {
		int eblk=pti->compeblk;
		if (eblk < 0)
			eblk=pti->ci.blkcnt;
		else
			eblk++;

		for (int blk=pti->compsblk; blk < eblk; blk++)
			if ((res=CompareBlock(blk)) != imgeOk)
				return res;
	}

	pti->tracksize[0]=pti->comppos;
	return res;
}
예제 #2
0
    void run()
    {
        bool doDecode = false;

        static const int samples = 450*1024;
        static const int inputBufferSize = samples;
        static const int sampleSpaceBefore = 256;
        static const int sampleSpaceAfter = 256;

        FileHandle in = File("captured.zdr", true).openRead();
        UInt64 inputFileSizeRemaining = in.size();
        Array<Byte> inputBuffer(inputBufferSize);
        int inputBufferRemaining = 0;
        Byte* inputPointer = 0;
        z_stream zs;
        memset(&zs, 0, sizeof(z_stream));
        if (inflateInit(&zs) != Z_OK)
            throw Exception("inflateInit failed");

        Array<Byte> buffer(sampleSpaceBefore + samples + sampleSpaceAfter);
        Byte* b = &buffer[0] + sampleSpaceBefore;
        for (int i = 0; i < sampleSpaceBefore; ++i)
            b[i - sampleSpaceBefore] = 0;
        for (int i = 0; i < sampleSpaceAfter; ++i)
            b[i + samples] = 0;
        int outputBytesRemaining = samples;

        Vector outputSize;
        NTSCCaptureDecoder<UInt32> decoder;
         
        if (doDecode) 
            outputSize = Vector(1280, 720);
        else
            outputSize = Vector(1824, 253);
        Bitmap<UInt32> decoded(outputSize);
        if (doDecode)
            decoder.setOutputBuffer(
                decoded.subBitmap(Vector(160, 0), Vector(960, 720)));
        else
            decoder.setOutputBuffer(decoded);
        decoded.fill(0);
        decoder.setInputBuffer(b);
        decoder.setOutputPixelsPerLine(1140);
        decoder.setYScale(3);
        decoder.setDoDecode(doDecode);

        _handle = fopen("u:\\captured2.avi","wb");
        if (!_handle)
            throw Exception("Can't open file");

        _VectorCount = 1;
        _VectorTable[0].x = _VectorTable[0].y = 0;
        for (int s = 1; s <= 10; ++s) {
            for (int y = -s; y <= s; ++y)
                for (int x = -s; x <= s; ++x) {
                    if (abs(x) == s || abs(y) == s) {
                        _VectorTable[_VectorCount].x = x;
                        _VectorTable[_VectorCount].y = y;
                        ++_VectorCount;
                    }
                }
        }
        memset(&_zstream, 0, sizeof(_zstream));

        _pitch = outputSize.x + 2*MAX_VECTOR;
        if (deflateInit(&_zstream, 4) != Z_OK)
            throw Exception("deflateInit failed");

        _bufSize = 4*outputSize.x*outputSize.y + 2*(1+(outputSize.x/8)) * (1+(outputSize.y/8))+1024;
        _bufSize += _bufSize / 1000;

        _buf = malloc(_bufSize);
        if (!_buf)
            throw Exception("Out of memory");
        _index = (UInt8*)malloc(16*4096);
        if (!_buf)
            throw Exception("Out of memory");
        _indexsize = 16*4096;
        _indexused = 8;

        for (int i = 0; i < AVI_HEADER_SIZE; ++i)
            fputc(0, _handle);
        _frames = 0;
        _written = 0;
        _audioused = 0;
        _audiowritten = 0;

        int blockwidth = 16;
        int blockheight = 16;
        _pixelsize = 4;
        _bufsize = (outputSize.y + 2*MAX_VECTOR)*_pitch*_pixelsize+2048;

        _buf1.allocate(_bufsize);
        _buf2.allocate(_bufsize);
        _work.allocate(_bufsize);

        int xblocks = (outputSize.x/blockwidth);
        int xleft = outputSize.x % blockwidth;
        if (xleft)
            ++xblocks;
        int yblocks = (outputSize.y/blockheight);
        int yleft = outputSize.y % blockheight;
        if (yleft)
            ++yblocks;
        _blockcount = yblocks*xblocks;
        _blocks = new FrameBlock[_blockcount];

        int i = 0;
        for (int y = 0; y < yblocks; ++y) {
            for (int x = 0; x < xblocks; ++x) {
                _blocks[i].start = ((y*blockheight) + MAX_VECTOR)*_pitch+
                    x*blockwidth + MAX_VECTOR;
                if (xleft && x == xblocks - 1) {
                    _blocks[i].dx = xleft;
                } else {
                    _blocks[i].dx = blockwidth;
                }
                if (yleft && y == yblocks - 1) {
                    _blocks[i].dy = yleft;
                } else {
                    _blocks[i].dy = blockheight;
                }
                ++i;
            }
        }

        memset(&_buf1[0], 0, _bufsize);
        memset(&_buf2[0], 0, _bufsize);
        memset(&_work[0], 0, _bufsize);
        _oldframe = &_buf1[0];
        _newframe = &_buf2[0];

        do {
            if (inputBufferRemaining == 0) {
                int bytesToRead = inputBufferSize;
                if (bytesToRead > inputFileSizeRemaining)
                    bytesToRead = inputFileSizeRemaining;
                inputPointer = &inputBuffer[0];
                in.read(inputPointer, bytesToRead);
                inputBufferRemaining = bytesToRead;
                inputFileSizeRemaining -= bytesToRead;
            }
            zs.avail_in = inputBufferRemaining;
            zs.next_in = inputPointer;
            zs.avail_out = outputBytesRemaining;
            zs.next_out = b + samples - outputBytesRemaining;
            int r = inflate(&zs, Z_SYNC_FLUSH);
            if (r != Z_STREAM_END && r != Z_OK)
                throw Exception("inflate failed");
            outputBytesRemaining = zs.avail_out;
            inputPointer = zs.next_in;
            inputBufferRemaining = zs.avail_in;

            if (outputBytesRemaining == 0) {
                if (inflateReset(&zs) != Z_OK)
                    throw Exception("inflateReset failed");
                outputBytesRemaining = samples;
                console.write(".");
                decoder.decode();

                bool keyFrame = false;
                if (_frames % 300 == 0)
                    keyFrame = true;
                 keyFrame = true;

                /* replace oldframe with new frame */
                unsigned char* copyFrame = _newframe;
                _newframe = _oldframe;
                _oldframe = copyFrame;

                compress.linesDone = 0;
                compress.writeSize = _bufSize;
                compress.writeDone = 1;
                compress.writeBuf = (unsigned char *)_buf;
                /* Set a pointer to the first byte which will contain info about this frame */
                unsigned char* firstByte = compress.writeBuf;
                *firstByte = 0;
                //Reset the work buffer
                _workUsed = 0;
                _workPos = 0;
                if (keyFrame) {
                    /* Make a keyframe */
                    *firstByte |= Mask_KeyFrame;
                    KeyframeHeader* header = (KeyframeHeader *)(compress.writeBuf + compress.writeDone);
                    header->high_version = 0; // DBZV_VERSION_HIGH;
                    header->low_version = 1; // DBZV_VERSION_LOW;
                    header->compression = 1; // COMPRESSION_ZLIB
    		        header->format = 8; // ZMBV_FORMAT_32BPP
                    header->blockwidth = 16;
                    header->blockheight = 16;
                    compress.writeDone += sizeof(KeyframeHeader);
                    /* Copy the new frame directly over */
                    /* Restart deflate */
                    deflateReset(&_zstream);
                }

                for (int i = 0; i < outputSize.y; ++i) {
                    void* rowPointer = decoded.data() + decoded.stride()*i;
                    unsigned char* destStart = _newframe + _pixelsize*(MAX_VECTOR+(compress.linesDone+MAX_VECTOR)*_pitch);
                    memcpy(destStart, rowPointer, outputSize.x * _pixelsize);
                    destStart += _pitch * _pixelsize;
                    compress.linesDone++;
                }

                if ((*compress.writeBuf) & Mask_KeyFrame) {
                    /* Add the full frame data */
                    unsigned char* readFrame = _newframe + _pixelsize*(MAX_VECTOR+MAX_VECTOR*_pitch);	
                    for (int i = 0; i < outputSize.y; ++i) {
                        memcpy(&_work[_workUsed], readFrame, outputSize.x*_pixelsize);
                        readFrame += _pitch*_pixelsize;
                        _workUsed += outputSize.x*_pixelsize;
                    }
                }
                else {
                    /* Add the delta frame data */
                    int written = 0;
                    int lastvector = 0;
                    signed char* vectors = (signed char*)&_work[_workUsed];
                    /* Align the following xor data on 4 byte boundary*/
                    _workUsed = (_workUsed + _blockcount*2 + 3) & ~3;
                    int totalx = 0;
                    int totaly = 0;
                    for (int b = 0; b < _blockcount; ++b) {
                        FrameBlock* block = &_blocks[b];
                        int bestvx = 0;
                        int bestvy = 0;
                        int bestchange = CompareBlock(0, 0, block);
                        int possibles = 64;
                        for (int v = 0; v < _VectorCount && possibles; ++v) {
                            if (bestchange < 4)
                                break;
                            int vx = _VectorTable[v].x;
                            int vy = _VectorTable[v].y;
                            if (PossibleBlock(vx, vy, block) < 4) {
                                --possibles;
                                int testchange = CompareBlock(vx, vy, block);
                                if (testchange < bestchange) {
                                    bestchange = testchange;
                                    bestvx = vx;
                                    bestvy = vy;
                                }
                            }
                        }
                        vectors[b*2+0] = (bestvx << 1);
                        vectors[b*2+1] = (bestvy << 1);
                        if (bestchange) {
                            vectors[b*2+0] |= 1;
                            long* pold=((long*)_oldframe) + block->start + bestvy*_pitch + bestvx;
                            long* pnew=((long*)_newframe) + block->start;
                            for (int y = 0; y < block->dy; ++y) {
                                for (int x = 0; x < block->dx; ++x) {
                                    *((long*)&_work[_workUsed]) = pnew[x] ^ pold[x];
                                    _workUsed += sizeof(long);
                                }
                                pold += _pitch;
                                pnew += _pitch;
                            }
                        }
                    }
                }
                /* Create the actual frame with compression */
                _zstream.next_in = (Bytef *)&_work[0];
                _zstream.avail_in = _workUsed;
                _zstream.total_in = 0;

                _zstream.next_out = (Bytef *)(compress.writeBuf + compress.writeDone);
                _zstream.avail_out = compress.writeSize - compress.writeDone;
                _zstream.total_out = 0;
                int res = deflate(&_zstream, Z_SYNC_FLUSH);
                int written = compress.writeDone + _zstream.total_out;

                CAPTURE_AddAviChunk( "00dc", written, _buf, keyFrame ? 0x10 : 0x0);
                ++_frames;

                //void CAPTURE_AddWave(UInt32 freq, UInt32 len, SInt16 * data)
                //{
                //    UInt left = WAVE_BUF - _audioused;
                //    if (left > len)
                //        left = len;
                //    memcpy( &_audiobuf[_audioused], data, left*4);
                //    _audioused += left;
                //    _audiorate = freq;
                //}

                //if ( capture.video.audioused ) {
                //    CAPTURE_AddAviChunk( "01wb", _audioused * 4, _audiobuf, 0);
                //    _audiowritten = _audioused*4;
                //    _audioused = 0;
                //}
            }

        } while (inputFileSizeRemaining != 0);

        if (inflateEnd(&zs) != Z_OK)
            throw Exception("inflateEnd failed");

        int main_list;
        _header_pos = 0;
        /* Try and write an avi header */
        AVIOUT4("RIFF");                    // Riff header
        AVIOUTd(AVI_HEADER_SIZE + _written - 8 + _indexused);
        AVIOUT4("AVI ");
        AVIOUT4("LIST");                    // List header
        main_list = _header_pos;
        AVIOUTd(0);				            // TODO size of list
        AVIOUT4("hdrl");

        AVIOUT4("avih");
        AVIOUTd(56);                         /* # of bytes to follow */
        AVIOUTd((11*912*262*2)/315);         /* Microseconds per frame */  // 1752256/105 ~= 16688
        AVIOUTd(0);
        AVIOUTd(0);                         /* PaddingGranularity (whatever that might be) */
        AVIOUTd(0x110);                     /* Flags,0x10 has index, 0x100 interleaved */
        AVIOUTd(_frames);      /* TotalFrames */
        AVIOUTd(0);                         /* InitialFrames */
        AVIOUTd(2);                         /* Stream count */
        AVIOUTd(0);                         /* SuggestedBufferSize */
        AVIOUTd(outputSize.x);       /* Width */
        AVIOUTd(outputSize.y);      /* Height */
        AVIOUTd(0);                         /* TimeScale:  Unit used to measure time */
        AVIOUTd(0);                         /* DataRate:   Data rate of playback     */
        AVIOUTd(0);                         /* StartTime:  Starting time of AVI data */
        AVIOUTd(0);                         /* DataLength: Size of AVI data chunk    */

        /* Video stream list */
        AVIOUT4("LIST");
        AVIOUTd(4 + 8 + 56 + 8 + 40);       /* Size of the list */
        AVIOUT4("strl");
        /* video stream header */
        AVIOUT4("strh");
        AVIOUTd(56);                        /* # of bytes to follow */
        AVIOUT4("vids");                    /* Type */
        AVIOUT4(CODEC_4CC);		            /* Handler */
        AVIOUTd(0);                         /* Flags */
        AVIOUTd(0);                         /* Reserved, MS says: wPriority, wLanguage */
        AVIOUTd(0);                         /* InitialFrames */
        AVIOUTd(82137);                     /* Scale */                                // 11*912*262
        AVIOUTd(4921875);                   /* Rate: Rate/Scale == samples/second */   // 157500000
        AVIOUTd(0);                         /* Start */
        AVIOUTd(_frames);      /* Length */
        AVIOUTd(0);                  /* SuggestedBufferSize */
        AVIOUTd(~0);                 /* Quality */
        AVIOUTd(0);                  /* SampleSize */
        AVIOUTd(0);                  /* Frame */
        AVIOUTd(0);                  /* Frame */
        /* The video stream format */
        AVIOUT4("strf");
        AVIOUTd(40);                 /* # of bytes to follow */
        AVIOUTd(40);                 /* Size */
        AVIOUTd(outputSize.x);         /* Width */
        AVIOUTd(outputSize.y);        /* Height */
//		OUTSHRT(1); OUTSHRT(24);     /* Planes, Count */
        AVIOUTd(0);
        AVIOUT4(CODEC_4CC);          /* Compression */
        AVIOUTd(outputSize.x*outputSize.y*4);  /* SizeImage (in bytes?) */
        AVIOUTd(0);                  /* XPelsPerMeter */
        AVIOUTd(0);                  /* YPelsPerMeter */
        AVIOUTd(0);                  /* ClrUsed: Number of colors used */
        AVIOUTd(0);                  /* ClrImportant: Number of colors important */

        /* Audio stream list */
        AVIOUT4("LIST");
        AVIOUTd(4 + 8 + 56 + 8 + 16);  /* Length of list in bytes */
        AVIOUT4("strl");
        /* The audio stream header */
        AVIOUT4("strh");
        AVIOUTd(56);            /* # of bytes to follow */
        AVIOUT4("auds");
        AVIOUTd(0);             /* Format (Optionally) */
        AVIOUTd(0);             /* Flags */
        AVIOUTd(0);             /* Reserved, MS says: wPriority, wLanguage */
        AVIOUTd(0);             /* InitialFrames */
        AVIOUTd(4);    /* Scale */
        AVIOUTd(_audiorate*4);             /* Rate, actual rate is scale/rate */
        AVIOUTd(0);             /* Start */
        if (!_audiorate)
            _audiorate = 1;
        AVIOUTd(_audiowritten/4);   /* Length */
        AVIOUTd(0);             /* SuggestedBufferSize */
        AVIOUTd(~0);            /* Quality */
        AVIOUTd(4);				/* SampleSize */
        AVIOUTd(0);             /* Frame */
        AVIOUTd(0);             /* Frame */
        /* The audio stream format */
        AVIOUT4("strf");
        AVIOUTd(16);            /* # of bytes to follow */
        AVIOUTw(1);             /* Format, WAVE_ZMBV_FORMAT_PCM */
        AVIOUTw(2);             /* Number of channels */
        AVIOUTd(_audiorate);          /* SamplesPerSec */
        AVIOUTd(_audiorate*4);        /* AvgBytesPerSec*/
        AVIOUTw(4);             /* BlockAlign */
        AVIOUTw(16);            /* BitsPerSample */
        int nmain = _header_pos - main_list - 4;
        /* Finish stream list, i.e. put number of bytes in the list to proper pos */

        int njunk = AVI_HEADER_SIZE - 8 - 12 - _header_pos;
        AVIOUT4("JUNK");
        AVIOUTd(njunk);
        /* Fix the size of the main list */
        _header_pos = main_list;
        AVIOUTd(nmain);
        _header_pos = AVI_HEADER_SIZE - 12;
        AVIOUT4("LIST");
        AVIOUTd(_written + 4); /* Length of list in bytes */
        AVIOUT4("movi");
        /* First add the index table to the end */
        memcpy(_index, "idx1", 4);
        host_writed(_index+4, _indexused - 8 );
        fwrite(_index, 1, _indexused, _handle);
        fseek(_handle, 0, SEEK_SET);
        fwrite(&_avi_header, 1, AVI_HEADER_SIZE, _handle);
        fclose(_handle);
        free(_index);
        free(_buf);
        _handle = 0;
    }