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

View File

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

View File

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

View File

@ -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 <unsigned int> offsets;
std::vector <gwavi_index_rec_t> offsets;
long movi_fpos;
int bits_per_pixel;
char fourcc[8];