Added functionality to properly encode keyframes into AVI file for Qt GUI.

This commit is contained in:
mjbudd77 2021-08-31 13:10:16 -04:00
parent 15c4a729b9
commit 8d3a27e1a5
4 changed files with 117 additions and 25 deletions

View File

@ -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 );
if ( qualitySupported )
{
dwQuality = cmpvars.lQ; 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;

View File

@ -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 ( offsets[i].keyFrame )
{
if (write_int(fp, 0x10) == -1) if (write_int(fp, 0x10) == -1)
goto write_int_failed; 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) {

View File

@ -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)
{ {

View File

@ -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];