Added functionality to properly encode keyframes into AVI file for Qt GUI.
This commit is contained in:
parent
15c4a729b9
commit
8d3a27e1a5
|
@ -317,11 +317,13 @@ namespace VFW
|
||||||
{
|
{
|
||||||
static bool cmpSet = false;
|
static bool cmpSet = false;
|
||||||
static COMPVARS cmpvars;
|
static COMPVARS cmpvars;
|
||||||
static DWORD dwFlags = 0;
|
//static DWORD dwFlags = 0;
|
||||||
static BITMAPINFOHEADER bmapIn;
|
static BITMAPINFOHEADER bmapIn;
|
||||||
static LPBITMAPINFOHEADER bmapOut = NULL;
|
static LPBITMAPINFOHEADER bmapOut = NULL;
|
||||||
static DWORD frameNum = 0;
|
static DWORD frameNum = 0;
|
||||||
static DWORD dwQuality = 0;
|
static DWORD dwQuality = 0;
|
||||||
|
static DWORD icErrCount = 0;
|
||||||
|
static DWORD flagsOut = 0;
|
||||||
static LPVOID outBuf = NULL;
|
static LPVOID outBuf = NULL;
|
||||||
|
|
||||||
static int chooseConfig(int width, int height)
|
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 )
|
static int init( int width, int height )
|
||||||
{
|
{
|
||||||
void *h;
|
void *h;
|
||||||
|
ICINFO icInfo;
|
||||||
DWORD dwFormatSize, dwCompressBufferSize;
|
DWORD dwFormatSize, dwCompressBufferSize;
|
||||||
|
bool qualitySupported = false;
|
||||||
|
|
||||||
memset( &bmapIn, 0, sizeof(bmapIn));
|
memset( &bmapIn, 0, sizeof(bmapIn));
|
||||||
bmapIn.biSize = sizeof(BITMAPINFOHEADER);
|
bmapIn.biSize = sizeof(BITMAPINFOHEADER);
|
||||||
|
@ -384,6 +388,45 @@ static int init( int width, int height )
|
||||||
|
|
||||||
dwFormatSize = ICCompressGetFormatSize( cmpvars.hic, &bmapIn );
|
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));
|
//printf("Format Size:%i %zi\n", dwFormatSize, sizeof(BITMAPINFOHEADER));
|
||||||
|
|
||||||
h = GlobalAlloc(GHND, dwFormatSize);
|
h = GlobalAlloc(GHND, dwFormatSize);
|
||||||
|
@ -402,12 +445,23 @@ static int init( int width, int height )
|
||||||
outBuf = (LPVOID)GlobalLock(h);
|
outBuf = (LPVOID)GlobalLock(h);
|
||||||
|
|
||||||
//dwQuality = ICGetDefaultQuality( cmpvars.hic );
|
//dwQuality = ICGetDefaultQuality( cmpvars.hic );
|
||||||
dwQuality = cmpvars.lQ;
|
if ( qualitySupported )
|
||||||
|
{
|
||||||
|
dwQuality = cmpvars.lQ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dwQuality = 0;
|
||||||
|
}
|
||||||
|
|
||||||
//printf("Quality Setting: %i\n", dwQuality );
|
//printf("Quality Setting: %i\n", dwQuality );
|
||||||
|
|
||||||
ICCompressBegin( cmpvars.hic, &bmapIn, bmapOut );
|
ICCompressBegin( cmpvars.hic, &bmapIn, bmapOut );
|
||||||
|
|
||||||
|
frameNum = 0;
|
||||||
|
flagsOut = 0;
|
||||||
|
icErrCount = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,12 +483,17 @@ static int close(void)
|
||||||
static int encode_frame( unsigned char *inBuf, int width, int height )
|
static int encode_frame( unsigned char *inBuf, int width, int height )
|
||||||
{
|
{
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
DWORD flagsOut = 0, reserved = 0;
|
DWORD reserved = 0;
|
||||||
int bytesWritten = 0;
|
int bytesWritten = 0;
|
||||||
|
|
||||||
|
if ( icErrCount > 10 )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
ret = ICCompress(
|
ret = ICCompress(
|
||||||
cmpvars.hic,
|
cmpvars.hic,
|
||||||
dwFlags,
|
0,
|
||||||
bmapOut,
|
bmapOut,
|
||||||
outBuf,
|
outBuf,
|
||||||
&bmapIn,
|
&bmapIn,
|
||||||
|
@ -448,9 +507,15 @@ static int encode_frame( unsigned char *inBuf, int width, int height )
|
||||||
|
|
||||||
if ( ret == ICERR_OK )
|
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;
|
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;
|
return bytesWritten;
|
||||||
|
|
|
@ -465,7 +465,7 @@ gwavi_t::write_index(FILE *fp)
|
||||||
long marker, t;
|
long marker, t;
|
||||||
unsigned int offset = 4;
|
unsigned int offset = 4;
|
||||||
unsigned int r;
|
unsigned int r;
|
||||||
char fourcc[8];
|
//char fourcc[8];
|
||||||
|
|
||||||
if (offsets.size() == 0 )
|
if (offsets.size() == 0 )
|
||||||
{
|
{
|
||||||
|
@ -487,7 +487,7 @@ gwavi_t::write_index(FILE *fp)
|
||||||
{
|
{
|
||||||
//peak_chunk( fp, offset, fourcc, &r );
|
//peak_chunk( fp, offset, fourcc, &r );
|
||||||
|
|
||||||
if ((offsets[i] & 0x80000000) == 0)
|
if ( offsets[i].type == 0)
|
||||||
{
|
{
|
||||||
write_chars(fp, "00dc");
|
write_chars(fp, "00dc");
|
||||||
//printf("Index: %u \n", offset );
|
//printf("Index: %u \n", offset );
|
||||||
|
@ -495,23 +495,31 @@ gwavi_t::write_index(FILE *fp)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
write_chars(fp, "01wb");
|
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)
|
if (write_int(fp, offset) == -1)
|
||||||
goto write_int_failed;
|
goto write_int_failed;
|
||||||
if (write_int(fp, offsets[i]) == -1)
|
if (write_int(fp, offsets[i].len) == -1)
|
||||||
goto write_int_failed;
|
goto write_int_failed;
|
||||||
|
|
||||||
r = offsets[i] % WORD_SIZE;
|
r = offsets[i].len % WORD_SIZE;
|
||||||
|
|
||||||
if ( r > 0 )
|
if ( r > 0 )
|
||||||
{
|
{
|
||||||
r = WORD_SIZE - r;
|
r = WORD_SIZE - r;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = offset + offsets[i] + 8 + r;
|
offset = offset + offsets[i].len + 8 + r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((t = ftell(fp)) == -1) {
|
if ((t = ftell(fp)) == -1) {
|
||||||
|
|
|
@ -279,10 +279,10 @@ write_chars_bin_failed:
|
||||||
* @return 0 on success, -1 on error.
|
* @return 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
int
|
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, maxi_pad; /* if your frame is raggin, give it some paddin' */
|
||||||
size_t t;
|
gwavi_index_rec_t idx;
|
||||||
|
|
||||||
if ( !buffer) {
|
if ( !buffer) {
|
||||||
(void)fputs("gwavi and/or buffer argument cannot be NULL",
|
(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 );
|
//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) {
|
if (write_chars_bin(out, "00dc", 4) == -1) {
|
||||||
(void)fprintf(stderr, "gwavi_add_frame: write_chars_bin() "
|
(void)fprintf(stderr, "gwavi_add_frame: write_chars_bin() "
|
||||||
|
@ -346,8 +350,8 @@ gwavi_t::add_frame( unsigned char *buffer, size_t len)
|
||||||
int
|
int
|
||||||
gwavi_t::add_audio( unsigned char *buffer, size_t len)
|
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, maxi_pad; /* in case audio bleeds over the 4 byte boundary */
|
||||||
size_t t;
|
gwavi_index_rec_t idx;
|
||||||
|
|
||||||
if ( !buffer)
|
if ( !buffer)
|
||||||
{
|
{
|
||||||
|
@ -362,7 +366,11 @@ gwavi_t::add_audio( unsigned char *buffer, size_t len)
|
||||||
maxi_pad = WORD_SIZE - maxi_pad;
|
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)
|
if (write_chars_bin(out,"01wb",4) == -1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -140,11 +140,24 @@ struct gwavi_audio_t
|
||||||
unsigned int samples_per_second;
|
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 )
|
#pragma pack( pop )
|
||||||
|
|
||||||
class gwavi_t
|
class gwavi_t
|
||||||
{
|
{
|
||||||
public:
|
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);
|
||||||
~gwavi_t(void);
|
~gwavi_t(void);
|
||||||
|
|
||||||
|
@ -154,7 +167,7 @@ class gwavi_t
|
||||||
|
|
||||||
int close(void);
|
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);
|
int add_audio( unsigned char *buffer, size_t len);
|
||||||
|
|
||||||
|
@ -168,8 +181,6 @@ class gwavi_t
|
||||||
|
|
||||||
int printHeaders(void);
|
int printHeaders(void);
|
||||||
|
|
||||||
static const int WORD_SIZE = 2;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FILE *in;
|
FILE *in;
|
||||||
FILE *out;
|
FILE *out;
|
||||||
|
@ -179,7 +190,7 @@ class gwavi_t
|
||||||
struct gwavi_stream_header_t stream_header_a;
|
struct gwavi_stream_header_t stream_header_a;
|
||||||
struct gwavi_stream_format_a_t stream_format_a;
|
struct gwavi_stream_format_a_t stream_format_a;
|
||||||
long marker;
|
long marker;
|
||||||
std::vector <unsigned int> offsets;
|
std::vector <gwavi_index_rec_t> offsets;
|
||||||
long movi_fpos;
|
long movi_fpos;
|
||||||
int bits_per_pixel;
|
int bits_per_pixel;
|
||||||
char fourcc[8];
|
char fourcc[8];
|
||||||
|
|
Loading…
Reference in New Issue