mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-11-26 05:50:57 +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
|
||||
|
||||
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: 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:
|
||||
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:
|
||||
CL_CloseAVI();
|
||||
|
|
|
@ -41,6 +41,12 @@ cvar_t* cl_showSend;
|
|||
cvar_t *cl_timedemo;
|
||||
cvar_t *cl_aviFrameRate;
|
||||
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_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 );
|
||||
}
|
||||
|
||||
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,
|
||||
"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 },
|
||||
{
|
||||
&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_aviFrameRate;
|
||||
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_inGameVideo;
|
||||
|
@ -547,12 +553,12 @@ qbool CL_Netchan_Process( netchan_t *chan, msg_t *msg );
|
|||
//
|
||||
// cl_avi.c
|
||||
//
|
||||
qbool CL_OpenAVIForWriting( const char *fileNameNoExt, qbool reOpen );
|
||||
void CL_TakeVideoFrame( void );
|
||||
qbool CL_OpenAVIForWriting( const char *fileNameNoExt );
|
||||
void CL_TakeVideoFrame();
|
||||
void CL_WriteAVIVideoFrame( const byte *imageBuffer, int size );
|
||||
void CL_WriteAVIAudioFrame( const byte *pcmBuffer, int size );
|
||||
qbool CL_CloseAVI( void );
|
||||
qbool CL_VideoRecording( void );
|
||||
qbool CL_CloseAVI();
|
||||
qbool CL_VideoRecording();
|
||||
|
||||
//
|
||||
// cl_download.cpp
|
||||
|
|
|
@ -174,6 +174,14 @@ or configs will never get loaded from disk!
|
|||
#define MAX_SEARCH_PATHS 4096
|
||||
#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 {
|
||||
char *name; // name of the file
|
||||
unsigned long pos; // file info position in zip
|
||||
|
@ -228,6 +236,7 @@ typedef union {
|
|||
typedef struct {
|
||||
qfile_gut file;
|
||||
qbool unique;
|
||||
qbool isPipe;
|
||||
} qfile_ut;
|
||||
|
||||
typedef struct {
|
||||
|
@ -316,6 +325,7 @@ static fileHandle_t FS_HandleForFile()
|
|||
{
|
||||
for ( int i = 1; i < MAX_FILE_HANDLES; ++i ) {
|
||||
if ( fsh[i].handleFiles.file.o == NULL ) {
|
||||
Com_Memset( &fsh[i], 0, sizeof( fsh[i] ) );
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -378,7 +388,7 @@ FS_ReplaceSeparators
|
|||
Fix things up differently for win/unix/mac
|
||||
====================
|
||||
*/
|
||||
static void FS_ReplaceSeparators( char *path ) {
|
||||
void FS_ReplaceSeparators( char *path ) {
|
||||
char *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
|
||||
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] ) );
|
||||
}
|
||||
|
@ -757,6 +771,21 @@ fileHandle_t FS_FOpenFileWrite( const char *filename ) {
|
|||
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
|
||||
|
|
|
@ -677,6 +677,8 @@ void FS_FreeFileList( char **list );
|
|||
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"
|
||||
|
||||
void FS_ReplaceSeparators( char *path );
|
||||
|
||||
char* FS_BuildOSPath( const char *base, const char *game, const char *qpath );
|
||||
|
||||
int FS_LoadStack();
|
||||
|
@ -687,6 +689,8 @@ int FS_GetModList( char *listbuf, int bufsize );
|
|||
fileHandle_t FS_FOpenFileWrite( const char *qpath );
|
||||
// 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 );
|
||||
int FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp );
|
||||
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;
|
||||
}
|
||||
|
||||
// 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
|
||||
WIN_InitMonitorList();
|
||||
|
||||
|
|
Loading…
Reference in a new issue