mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-11-10 06:31:48 +00:00
added FFmpeg support for A/V capture compression
This commit is contained in:
parent
9a6e253dc3
commit
3cea7e0c3d
8 changed files with 631 additions and 530 deletions
|
@ -4,6 +4,16 @@ See the end of this file for known issues.
|
||||||
|
|
||||||
DD Mmm YY - 1.54
|
DD Mmm YY - 1.54
|
||||||
|
|
||||||
|
add: FFmpeg piping support for compression of audio/video captures
|
||||||
|
cl_ffmpeg <0|1> (default: 0) uses FFmpeg instead of writing raw .avi files
|
||||||
|
cl_ffmpegCommand <string> are the FFmpeg command-line options for the output file
|
||||||
|
cl_ffmpegExePath <string> (default: "ffmpeg") is the path of the FFmpeg executable to use
|
||||||
|
note that the path cannot contain spaces on Windows
|
||||||
|
cl_ffmpegOutPath <string> (default: "") is the video output directory
|
||||||
|
leave empty to write to cpma/videos as with .avi files
|
||||||
|
cl_ffmpegOutExt <string> (default: "mp4") is the output file extension
|
||||||
|
cl_ffmpegLog <0|1> (default: 0) enables the creation of 1 log file per capture
|
||||||
|
|
||||||
add: togglegui and toggleguiinput to toggle (the mouse input of) the built-in GUI system
|
add: togglegui and toggleguiinput to toggle (the mouse input of) the built-in GUI system
|
||||||
|
|
||||||
add: key binds starting with "keycatchgui" always take precedence over everything else
|
add: key binds starting with "keycatchgui" always take precedence over everything else
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -698,7 +698,7 @@ static intptr_t CL_CgameSystemCalls( intptr_t *args )
|
||||||
|
|
||||||
case CG_EXT_NDP_STARTVIDEO:
|
case CG_EXT_NDP_STARTVIDEO:
|
||||||
Cvar_Set( cl_aviFrameRate->name, va( "%d", (int)args[2] ) );
|
Cvar_Set( cl_aviFrameRate->name, va( "%d", (int)args[2] ) );
|
||||||
return CL_OpenAVIForWriting( va( "videos/%s", (const char*)VMA(1) ), qfalse );
|
return CL_OpenAVIForWriting( VMA(1) );
|
||||||
|
|
||||||
case CG_EXT_NDP_STOPVIDEO:
|
case CG_EXT_NDP_STOPVIDEO:
|
||||||
CL_CloseAVI();
|
CL_CloseAVI();
|
||||||
|
|
|
@ -41,6 +41,12 @@ cvar_t* cl_showSend;
|
||||||
cvar_t *cl_timedemo;
|
cvar_t *cl_timedemo;
|
||||||
cvar_t *cl_aviFrameRate;
|
cvar_t *cl_aviFrameRate;
|
||||||
cvar_t *cl_aviMotionJpeg;
|
cvar_t *cl_aviMotionJpeg;
|
||||||
|
cvar_t *cl_ffmpeg;
|
||||||
|
cvar_t *cl_ffmpegCommand;
|
||||||
|
cvar_t *cl_ffmpegExePath;
|
||||||
|
cvar_t *cl_ffmpegOutPath;
|
||||||
|
cvar_t *cl_ffmpegOutExt;
|
||||||
|
cvar_t *cl_ffmpegLog;
|
||||||
|
|
||||||
cvar_t *cl_allowDownload;
|
cvar_t *cl_allowDownload;
|
||||||
cvar_t *cl_inGameVideo;
|
cvar_t *cl_inGameVideo;
|
||||||
|
@ -1951,7 +1957,7 @@ static void CL_Video_f()
|
||||||
1900+t.tm_year, 1+t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec );
|
1900+t.tm_year, 1+t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec );
|
||||||
}
|
}
|
||||||
|
|
||||||
CL_OpenAVIForWriting( va( "videos/%s", s ), qfalse );
|
CL_OpenAVIForWriting( s );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2148,6 +2154,41 @@ static const cvarTableItem_t cl_cvars[] =
|
||||||
&cl_aviMotionJpeg, "cl_aviMotionJpeg", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_cl_aviMotionJpeg,
|
&cl_aviMotionJpeg, "cl_aviMotionJpeg", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_cl_aviMotionJpeg,
|
||||||
"AVI motion JPEG", CVARCAT_DEMO, "", ""
|
"AVI motion JPEG", CVARCAT_DEMO, "", ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
&cl_ffmpeg, "cl_ffmpeg", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL,
|
||||||
|
"use FFmpeg for video export\n"
|
||||||
|
"Pipes video through FFmpeg instead of writing raw .avi files.",
|
||||||
|
"Use FFmpeg", CVARCAT_DEMO, "Uses FFmpeg instead of writing raw .avi files", ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&cl_ffmpegCommand, "cl_ffmpegCommand", "-movflags faststart -bf 2 -c:v libx264 -preset medium -crf 23 -vf format=yuv420p -c:a aac -b:a 320k",
|
||||||
|
CVAR_ARCHIVE, CVART_STRING, NULL, NULL,
|
||||||
|
"FFmpeg encode settings\n"
|
||||||
|
"The full command-line options for the output file.",
|
||||||
|
"FFmpeg encode settings", CVARCAT_DEMO, "Command-line options for the output file", ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&cl_ffmpegExePath, "cl_ffmpegExePath", "ffmpeg", CVAR_ARCHIVE, CVART_STRING, NULL, NULL,
|
||||||
|
"FFmpeg executable path\n"
|
||||||
|
"The path cannot contain spaces.",
|
||||||
|
"FFmpeg executable path", CVARCAT_DEMO, "The path cannot contain spaces", ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&cl_ffmpegOutPath, "cl_ffmpegOutPath", "", CVAR_ARCHIVE, CVART_STRING, NULL, NULL,
|
||||||
|
"FFmpeg output directory\n"
|
||||||
|
"Leave empty to write to cpma/videos as with .avi files.",
|
||||||
|
"FFmpeg output directory", CVARCAT_DEMO, "Leave empty to write to cpma/videos as with .avi files", ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&cl_ffmpegOutExt, "cl_ffmpegOutExt", "mp4", CVAR_ARCHIVE, CVART_STRING, NULL, NULL, "FFmpeg output file extension",
|
||||||
|
"FFmpeg output file extension", CVARCAT_DEMO, "", ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&cl_ffmpegLog, "cl_ffmpegLog", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL,
|
||||||
|
"FFmpeg log file creation\n"
|
||||||
|
"Creates 1 log file per capture.",
|
||||||
|
"FFmpeg log file creation", CVARCAT_DEMO, "Creates 1 log file per capture", ""
|
||||||
|
},
|
||||||
{ &rconAddress, "rconAddress", "", 0, CVART_STRING, NULL, NULL, help_rconAddress },
|
{ &rconAddress, "rconAddress", "", 0, CVART_STRING, NULL, NULL, help_rconAddress },
|
||||||
{
|
{
|
||||||
&cl_maxpackets, "cl_maxpackets", "125", CVAR_ARCHIVE, CVART_INTEGER, "15", "125", "max. packet upload rate",
|
&cl_maxpackets, "cl_maxpackets", "125", CVAR_ARCHIVE, CVART_INTEGER, "15", "125", "max. packet upload rate",
|
||||||
|
|
|
@ -371,6 +371,12 @@ extern cvar_t *cl_serverStatusResendTime;
|
||||||
extern cvar_t *cl_timedemo;
|
extern cvar_t *cl_timedemo;
|
||||||
extern cvar_t *cl_aviFrameRate;
|
extern cvar_t *cl_aviFrameRate;
|
||||||
extern cvar_t *cl_aviMotionJpeg;
|
extern cvar_t *cl_aviMotionJpeg;
|
||||||
|
extern cvar_t *cl_ffmpeg;
|
||||||
|
extern cvar_t *cl_ffmpegCommand;
|
||||||
|
extern cvar_t *cl_ffmpegExePath;
|
||||||
|
extern cvar_t *cl_ffmpegOutPath;
|
||||||
|
extern cvar_t *cl_ffmpegOutExt;
|
||||||
|
extern cvar_t *cl_ffmpegLog;
|
||||||
|
|
||||||
extern cvar_t *cl_allowDownload; // 0=off, 1=CNQ3, -1=id
|
extern cvar_t *cl_allowDownload; // 0=off, 1=CNQ3, -1=id
|
||||||
extern cvar_t *cl_inGameVideo;
|
extern cvar_t *cl_inGameVideo;
|
||||||
|
@ -547,12 +553,12 @@ qbool CL_Netchan_Process( netchan_t *chan, msg_t *msg );
|
||||||
//
|
//
|
||||||
// cl_avi.c
|
// cl_avi.c
|
||||||
//
|
//
|
||||||
qbool CL_OpenAVIForWriting( const char *fileNameNoExt, qbool reOpen );
|
qbool CL_OpenAVIForWriting( const char *fileNameNoExt );
|
||||||
void CL_TakeVideoFrame( void );
|
void CL_TakeVideoFrame();
|
||||||
void CL_WriteAVIVideoFrame( const byte *imageBuffer, int size );
|
void CL_WriteAVIVideoFrame( const byte *imageBuffer, int size );
|
||||||
void CL_WriteAVIAudioFrame( const byte *pcmBuffer, int size );
|
void CL_WriteAVIAudioFrame( const byte *pcmBuffer, int size );
|
||||||
qbool CL_CloseAVI( void );
|
qbool CL_CloseAVI();
|
||||||
qbool CL_VideoRecording( void );
|
qbool CL_VideoRecording();
|
||||||
|
|
||||||
//
|
//
|
||||||
// cl_download.cpp
|
// cl_download.cpp
|
||||||
|
|
|
@ -174,6 +174,14 @@ or configs will never get loaded from disk!
|
||||||
#define MAX_SEARCH_PATHS 4096
|
#define MAX_SEARCH_PATHS 4096
|
||||||
#define MAX_FILEHASH_SIZE 1024
|
#define MAX_FILEHASH_SIZE 1024
|
||||||
|
|
||||||
|
#if defined( _WIN32 )
|
||||||
|
#define Sys_OpenPipeWrite(Command) _popen(Command, "wb")
|
||||||
|
#define Sys_ClosePipe(Pipe) _pclose(Pipe)
|
||||||
|
#else
|
||||||
|
#define Sys_OpenPipeWrite(Command) popen(Command, "w")
|
||||||
|
#define Sys_ClosePipe(Pipe) pclose(Pipe)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct fileInPack_s {
|
typedef struct fileInPack_s {
|
||||||
char *name; // name of the file
|
char *name; // name of the file
|
||||||
unsigned long pos; // file info position in zip
|
unsigned long pos; // file info position in zip
|
||||||
|
@ -228,6 +236,7 @@ typedef union {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
qfile_gut file;
|
qfile_gut file;
|
||||||
qbool unique;
|
qbool unique;
|
||||||
|
qbool isPipe;
|
||||||
} qfile_ut;
|
} qfile_ut;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -316,6 +325,7 @@ static fileHandle_t FS_HandleForFile()
|
||||||
{
|
{
|
||||||
for ( int i = 1; i < MAX_FILE_HANDLES; ++i ) {
|
for ( int i = 1; i < MAX_FILE_HANDLES; ++i ) {
|
||||||
if ( fsh[i].handleFiles.file.o == NULL ) {
|
if ( fsh[i].handleFiles.file.o == NULL ) {
|
||||||
|
Com_Memset( &fsh[i], 0, sizeof( fsh[i] ) );
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,7 +388,7 @@ FS_ReplaceSeparators
|
||||||
Fix things up differently for win/unix/mac
|
Fix things up differently for win/unix/mac
|
||||||
====================
|
====================
|
||||||
*/
|
*/
|
||||||
static void FS_ReplaceSeparators( char *path ) {
|
void FS_ReplaceSeparators( char *path ) {
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
for ( s = path ; *s ; s++ ) {
|
for ( s = path ; *s ; s++ ) {
|
||||||
|
@ -711,7 +721,11 @@ void FS_FCloseFile( fileHandle_t f ) {
|
||||||
|
|
||||||
// we didn't find it as a pak, so close it as a unique file
|
// we didn't find it as a pak, so close it as a unique file
|
||||||
if (fsh[f].handleFiles.file.o) {
|
if (fsh[f].handleFiles.file.o) {
|
||||||
fclose (fsh[f].handleFiles.file.o);
|
if (fsh[f].handleFiles.isPipe) {
|
||||||
|
Sys_ClosePipe( fsh[f].handleFiles.file.o );
|
||||||
|
} else {
|
||||||
|
fclose( fsh[f].handleFiles.file.o );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Com_Memset( &fsh[f], 0, sizeof( fsh[f] ) );
|
Com_Memset( &fsh[f], 0, sizeof( fsh[f] ) );
|
||||||
}
|
}
|
||||||
|
@ -757,6 +771,21 @@ fileHandle_t FS_FOpenFileWrite( const char *filename ) {
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileHandle_t FS_OpenPipeWrite( const char* command ) {
|
||||||
|
fileHandle_t f = FS_HandleForFile();
|
||||||
|
fsh[f].zipFile = qfalse;
|
||||||
|
|
||||||
|
fsh[f].handleFiles.file.o = Sys_OpenPipeWrite( command );
|
||||||
|
fsh[f].handleFiles.isPipe = qtrue;
|
||||||
|
Q_strncpyz( fsh[f].name, "$pipe", sizeof(fsh[f].name));
|
||||||
|
fsh[f].handleSync = qfalse;
|
||||||
|
if ( !fsh[f].handleFiles.file.o ) {
|
||||||
|
f = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===========
|
===========
|
||||||
FS_FOpenFileAppend
|
FS_FOpenFileAppend
|
||||||
|
|
|
@ -677,6 +677,8 @@ void FS_FreeFileList( char **list );
|
||||||
qbool FS_FileExists( const char *file ); // checks in current game dir
|
qbool FS_FileExists( const char *file ); // checks in current game dir
|
||||||
qbool FS_FileExistsEx( const char *file, qbool curGameDir ); // if curGameDir is qfalse, checks in "baseq3"
|
qbool FS_FileExistsEx( const char *file, qbool curGameDir ); // if curGameDir is qfalse, checks in "baseq3"
|
||||||
|
|
||||||
|
void FS_ReplaceSeparators( char *path );
|
||||||
|
|
||||||
char* FS_BuildOSPath( const char *base, const char *game, const char *qpath );
|
char* FS_BuildOSPath( const char *base, const char *game, const char *qpath );
|
||||||
|
|
||||||
int FS_LoadStack();
|
int FS_LoadStack();
|
||||||
|
@ -687,6 +689,8 @@ int FS_GetModList( char *listbuf, int bufsize );
|
||||||
fileHandle_t FS_FOpenFileWrite( const char *qpath );
|
fileHandle_t FS_FOpenFileWrite( const char *qpath );
|
||||||
// will properly create any needed paths and deal with seperater character issues
|
// will properly create any needed paths and deal with seperater character issues
|
||||||
|
|
||||||
|
fileHandle_t FS_OpenPipeWrite( const char* command );
|
||||||
|
|
||||||
fileHandle_t FS_SV_FOpenFileWrite( const char *filename );
|
fileHandle_t FS_SV_FOpenFileWrite( const char *filename );
|
||||||
int FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp );
|
int FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp );
|
||||||
void FS_SV_Rename( const char *from, const char *to );
|
void FS_SV_Rename( const char *from, const char *to );
|
||||||
|
|
|
@ -1059,6 +1059,12 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prevent child processes from spawning a command prompt window
|
||||||
|
#ifndef DEDICATED
|
||||||
|
AllocConsole();
|
||||||
|
ShowWindow( GetConsoleWindow(), SW_HIDE );
|
||||||
|
#endif
|
||||||
|
|
||||||
// done here so the early console can be shown on the primary monitor
|
// done here so the early console can be shown on the primary monitor
|
||||||
WIN_InitMonitorList();
|
WIN_InitMonitorList();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue