diff --git a/src/drivers/Qt/AviRecord.cpp b/src/drivers/Qt/AviRecord.cpp index af0b44a9..94e4c758 100644 --- a/src/drivers/Qt/AviRecord.cpp +++ b/src/drivers/Qt/AviRecord.cpp @@ -317,11 +317,13 @@ namespace VFW { static bool cmpSet = false; static COMPVARS cmpvars; -static DWORD dwFlags = 0; +//static DWORD dwFlags = 0; static BITMAPINFOHEADER bmapIn; static LPBITMAPINFOHEADER bmapOut = NULL; static DWORD frameNum = 0; static DWORD dwQuality = 0; +static DWORD icErrCount = 0; +static DWORD flagsOut = 0; static LPVOID outBuf = NULL; static int chooseConfig(int width, int height) @@ -371,7 +373,9 @@ static int chooseConfig(int width, int height) static int init( int width, int height ) { void *h; + ICINFO icInfo; DWORD dwFormatSize, dwCompressBufferSize; + bool qualitySupported = false; memset( &bmapIn, 0, sizeof(bmapIn)); bmapIn.biSize = sizeof(BITMAPINFOHEADER); @@ -384,6 +388,45 @@ static int init( int width, int height ) dwFormatSize = ICCompressGetFormatSize( cmpvars.hic, &bmapIn ); + if ( ICGetInfo( cmpvars.hic, &icInfo, sizeof(icInfo) ) ) + { + printf("Name : %ls\n" , icInfo.szName ); + printf("Flags: 0x%08X", icInfo.dwFlags ); + + if ( icInfo.dwFlags & VIDCF_CRUNCH ) + { + printf(" VIDCF_CRUNCH "); + } + + if ( icInfo.dwFlags & VIDCF_TEMPORAL ) + { + printf(" VIDCF_TEMPORAL "); + } + + if ( icInfo.dwFlags & VIDCF_TEMPORAL ) + { + printf(" VIDCF_TEMPORAL "); + } + + if ( icInfo.dwFlags & VIDCF_QUALITY ) + { + printf(" VIDCF_QUALITY "); + qualitySupported = true; + } + + if ( icInfo.dwFlags & VIDCF_FASTTEMPORALC ) + { + printf(" VIDCF_FASTTEMPORALC "); + } + + if ( icInfo.dwFlags & VIDCF_FASTTEMPORALD ) + { + printf(" VIDCF_FASTTEMPORALD "); + } + printf("\n"); + + } + //printf("Format Size:%i %zi\n", dwFormatSize, sizeof(BITMAPINFOHEADER)); h = GlobalAlloc(GHND, dwFormatSize); @@ -402,12 +445,23 @@ static int init( int width, int height ) outBuf = (LPVOID)GlobalLock(h); //dwQuality = ICGetDefaultQuality( cmpvars.hic ); - dwQuality = cmpvars.lQ; + if ( qualitySupported ) + { + dwQuality = cmpvars.lQ; + } + else + { + dwQuality = 0; + } //printf("Quality Setting: %i\n", dwQuality ); ICCompressBegin( cmpvars.hic, &bmapIn, bmapOut ); + frameNum = 0; + flagsOut = 0; + icErrCount = 0; + return 0; } @@ -429,12 +483,17 @@ static int close(void) static int encode_frame( unsigned char *inBuf, int width, int height ) { DWORD ret; - DWORD flagsOut = 0, reserved = 0; + DWORD reserved = 0; int bytesWritten = 0; + if ( icErrCount > 10 ) + { + return -1; + } + ret = ICCompress( cmpvars.hic, - dwFlags, + 0, bmapOut, outBuf, &bmapIn, @@ -448,9 +507,15 @@ static int encode_frame( unsigned char *inBuf, int width, int height ) if ( ret == ICERR_OK ) { - //printf("Compressing Frame:%i Size:%i\n", frameNum, bmapOut->biSizeImage); + //printf("Compressing Frame:%i Size:%i Flags:%08X\n", + // frameNum, bmapOut->biSizeImage, flagsOut ); bytesWritten = bmapOut->biSizeImage; - gwavi->add_frame( (unsigned char*)outBuf, bytesWritten ); + gwavi->add_frame( (unsigned char*)outBuf, bytesWritten, flagsOut ); + } + else + { + printf("Compression Error Frame:%i\n", frameNum); + icErrCount++; } return bytesWritten; diff --git a/src/drivers/Qt/avi/avi-utils.cpp b/src/drivers/Qt/avi/avi-utils.cpp index e57f0386..947886cb 100644 --- a/src/drivers/Qt/avi/avi-utils.cpp +++ b/src/drivers/Qt/avi/avi-utils.cpp @@ -465,7 +465,7 @@ gwavi_t::write_index(FILE *fp) long marker, t; unsigned int offset = 4; unsigned int r; - char fourcc[8]; + //char fourcc[8]; if (offsets.size() == 0 ) { @@ -487,7 +487,7 @@ gwavi_t::write_index(FILE *fp) { //peak_chunk( fp, offset, fourcc, &r ); - if ((offsets[i] & 0x80000000) == 0) + if ( offsets[i].type == 0) { write_chars(fp, "00dc"); //printf("Index: %u \n", offset ); @@ -495,23 +495,31 @@ gwavi_t::write_index(FILE *fp) else { write_chars(fp, "01wb"); - offsets[i] &= 0x7fffffff; } - if (write_int(fp, 0x10) == -1) - goto write_int_failed; + + if ( offsets[i].keyFrame ) + { + if (write_int(fp, 0x10) == -1) + goto write_int_failed; + } + else + { + if (write_int(fp, 0x00) == -1) + goto write_int_failed; + } if (write_int(fp, offset) == -1) goto write_int_failed; - if (write_int(fp, offsets[i]) == -1) + if (write_int(fp, offsets[i].len) == -1) goto write_int_failed; - r = offsets[i] % WORD_SIZE; + r = offsets[i].len % WORD_SIZE; if ( r > 0 ) { r = WORD_SIZE - r; } - offset = offset + offsets[i] + 8 + r; + offset = offset + offsets[i].len + 8 + r; } if ((t = ftell(fp)) == -1) { diff --git a/src/drivers/Qt/avi/gwavi.cpp b/src/drivers/Qt/avi/gwavi.cpp index 2878c079..492fdfc0 100644 --- a/src/drivers/Qt/avi/gwavi.cpp +++ b/src/drivers/Qt/avi/gwavi.cpp @@ -279,10 +279,10 @@ write_chars_bin_failed: * @return 0 on success, -1 on error. */ int -gwavi_t::add_frame( unsigned char *buffer, size_t len) +gwavi_t::add_frame( unsigned char *buffer, size_t len, unsigned int flags) { - size_t maxi_pad; /* if your frame is raggin, give it some paddin' */ - size_t t; + size_t t, maxi_pad; /* if your frame is raggin, give it some paddin' */ + gwavi_index_rec_t idx; if ( !buffer) { (void)fputs("gwavi and/or buffer argument cannot be NULL", @@ -306,7 +306,11 @@ gwavi_t::add_frame( unsigned char *buffer, size_t len) //printf("Frame Offset: %li\n", ftell(out) - movi_fpos ); - offsets.push_back( (unsigned int)(len) ); + idx.len = len; + idx.type = 0; + idx.keyFrame = (flags & IF_KEYFRAME) ? 1 : 0; + + offsets.push_back( idx ); if (write_chars_bin(out, "00dc", 4) == -1) { (void)fprintf(stderr, "gwavi_add_frame: write_chars_bin() " @@ -346,8 +350,8 @@ gwavi_t::add_frame( unsigned char *buffer, size_t len) int gwavi_t::add_audio( unsigned char *buffer, size_t len) { - size_t maxi_pad; /* in case audio bleeds over the 4 byte boundary */ - size_t t; + size_t t, maxi_pad; /* in case audio bleeds over the 4 byte boundary */ + gwavi_index_rec_t idx; if ( !buffer) { @@ -362,7 +366,11 @@ gwavi_t::add_audio( unsigned char *buffer, size_t len) maxi_pad = WORD_SIZE - maxi_pad; } - offsets.push_back( (unsigned int)((len) | 0x80000000) ); + idx.len = len; + idx.type = 1; + idx.keyFrame = 0; + + offsets.push_back( idx ); if (write_chars_bin(out,"01wb",4) == -1) { diff --git a/src/drivers/Qt/avi/gwavi.h b/src/drivers/Qt/avi/gwavi.h index 98e1403b..eed36868 100644 --- a/src/drivers/Qt/avi/gwavi.h +++ b/src/drivers/Qt/avi/gwavi.h @@ -140,11 +140,24 @@ struct gwavi_audio_t unsigned int samples_per_second; }; +struct gwavi_index_rec_t +{ + unsigned int len; + unsigned char type; + unsigned char keyFrame; + unsigned char resv[2]; +}; + #pragma pack( pop ) class gwavi_t { public: + static const int WORD_SIZE = 2; + static const unsigned int IF_LIST = 0x00000001; + static const unsigned int IF_KEYFRAME = 0x00000010; + static const unsigned int IF_NO_TIME = 0x00000100; + gwavi_t(void); ~gwavi_t(void); @@ -154,7 +167,7 @@ class gwavi_t int close(void); - int add_frame( unsigned char *buffer, size_t len); + int add_frame( unsigned char *buffer, size_t len, unsigned int flags = IF_KEYFRAME); int add_audio( unsigned char *buffer, size_t len); @@ -168,8 +181,6 @@ class gwavi_t int printHeaders(void); - static const int WORD_SIZE = 2; - private: FILE *in; FILE *out; @@ -179,7 +190,7 @@ class gwavi_t struct gwavi_stream_header_t stream_header_a; struct gwavi_stream_format_a_t stream_format_a; long marker; - std::vector offsets; + std::vector offsets; long movi_fpos; int bits_per_pixel; char fourcc[8];