4#define AVI_MASTER_INDEX_SIZE 640
6typedef struct capturevideostate_avi_formatspecific_s
23 unsigned char riffbufferdata[128];
28 const char *riffstackfourcc[4];
31#define LOAD_FORMATSPECIFIC_AVI() capturevideostate_avi_formatspecific_t *format = (capturevideostate_avi_formatspecific_t *) cls.capturevideo.formatspecific
37 format->riffbuffer.maxsize =
sizeof(
format->riffbufferdata);
45 if (
format->riffbuffer.cursize > 0)
48 cls.capturevideo.error =
true;
50 format->riffbuffer.cursize = 0;
51 format->riffbuffer.overflowed =
false;
58 if (
format->riffbuffer.cursize > 0)
61 cls.capturevideo.error =
true;
62 format->riffbuffer.cursize = 0;
63 format->riffbuffer.overflowed =
false;
72 cls.capturevideo.error =
true;
79 if (
format->riffbuffer.cursize + 4 >
format->riffbuffer.maxsize)
87 if (
format->riffbuffer.cursize + 2 >
format->riffbuffer.maxsize)
95 if (
format->riffbuffer.cursize + (
int)
strlen(chunkfourcc) >
format->riffbuffer.maxsize)
119 if (listtypefourcc && sizeHint >= 0)
124 format->riffstacksizehint[
format->riffstacklevel] = sizeHint;
126 format->riffstackfourcc[
format->riffstacklevel] = chunkfourcc;
137 unsigned char sizebytes[4];
142 sizehint =
format->riffstacksizehint[
format->riffstacklevel];
150 Con_Printf(
CON_WARN "WARNING: invalid size hint %d when writing video data (actual size: %d)\n", (
int) sizehint,
x);
151 for(
i = 0;
i <=
format->riffstacklevel; ++
i)
156 sizebytes[0] = (
x) & 0xff;sizebytes[1] = (
x >> 8) & 0xff;sizebytes[2] = (
x >> 16) & 0xff;sizebytes[3] = (
x >> 24) & 0xff;
157 if(
FS_Seek(
cls.capturevideo.videofile, -(
x + 4), SEEK_END) >= 0)
159 FS_Write(
cls.capturevideo.videofile, sizebytes, 4);
161 FS_Seek(
cls.capturevideo.videofile, 0, SEEK_END);
172 if(
buf->cursize + extralen >
buf->maxsize)
174 int oldsize =
buf->maxsize;
177 buf->maxsize =
max(
buf->maxsize * 2, 4096);
191 Sys_Error(
"SCR_CaptureVideo_RIFF_IndexEntry called on non-seekable AVI");
193 if (
format->riffstacklevel != 2)
194 Sys_Error(
"SCR_Capturevideo_RIFF_IndexEntry: RIFF stack level is %i (should be 2)\n",
format->riffstacklevel);
212 Sys_Error(
"SCR_CaptureVideo_RIFF_MakeIxChunk called on non-seekable AVI");
218 for(
i = 0;
i <
format->riffindexbuffer.cursize;
i += 16)
219 if(!memcmp(
format->riffindexbuffer.data +
i, dwChunkId, 4))
223 for(
i = 0;
i <
format->riffindexbuffer.cursize;
i += 16)
224 if(!memcmp(
format->riffindexbuffer.data +
i, dwChunkId, 4))
236 for(
i = 0;
i <
format->riffindexbuffer.cursize;
i += 16)
237 if(!memcmp(
format->riffindexbuffer.data +
i, dwChunkId, 4))
239 unsigned int *p = (
unsigned int *) (
format->riffindexbuffer.data +
i);
240 unsigned int flags = p[1];
241 unsigned int rpos = p[2];
242 unsigned int size = p[3];
254 if(
FS_Seek(
cls.capturevideo.videofile, masteridx_start + 16 * *masteridx_count, SEEK_SET) >= 0)
263 if(
FS_Seek(
cls.capturevideo.videofile, masteridx_counter, SEEK_SET) >= 0)
269 FS_Seek(
cls.capturevideo.videofile, 0, SEEK_END);
277 if(
format->videofile_ix_master_video_inuse_offset)
279 if(
format->videofile_ix_master_audio_inuse_offset)
282 if(
final &&
format->videofile_firstchunkframes_offset)
289 format->riffindexbuffer.cursize = 0;
291 while (
format->riffstacklevel > 0)
294 if(
format->videofile_firstchunkframes_offset)
296 Con_DPrintf(
"Finishing first chunk (%d frames)\n",
cls.capturevideo.frame);
297 if(
FS_Seek(
cls.capturevideo.videofile,
format->videofile_firstchunkframes_offset, SEEK_SET) >= 0)
302 FS_Seek(
cls.capturevideo.videofile, 0, SEEK_END);
303 format->videofile_firstchunkframes_offset = 0;
306 Con_DPrintf(
"Finishing another chunk (%d frames)\n",
cls.capturevideo.frame);
314 if (
format->riffstacklevel != 2)
315 Sys_Error(
"SCR_CaptureVideo_RIFF_OverflowCheck: chunk stack leakage!\n");
327 if (8 + cursize + framesize +
format->riffindexbuffer.cursize + 8 +
format->riffindexbuffer.cursize + 64 > 1<<30)
333 format->videofile_ix_movistart =
format->riffstackstartoffset[1];
341 int blockr, blockg, blockb;
343 unsigned char *
b, *out;
353 *out =
cls.capturevideo.yuvnormalizetable[0][
cls.capturevideo.rgbtoyuvscaletable[0][0][blockr] +
cls.capturevideo.rgbtoyuvscaletable[0][1][blockg] +
cls.capturevideo.rgbtoyuvscaletable[0][2][blockb]];
358 int inpitch =
width*4;
361 blockr = (
b[2] +
b[6] +
b[inpitch+2] +
b[inpitch+6]) >> 2;
362 blockg = (
b[1] +
b[5] +
b[inpitch+1] +
b[inpitch+5]) >> 2;
363 blockb = (
b[0] +
b[4] +
b[inpitch+0] +
b[inpitch+4]) >> 2;
365 out[0 ] =
cls.capturevideo.yuvnormalizetable[1][
cls.capturevideo.rgbtoyuvscaletable[1][0][blockr] +
cls.capturevideo.rgbtoyuvscaletable[1][1][blockg] +
cls.capturevideo.rgbtoyuvscaletable[1][2][blockb] + 128];
367 out[outoffset] =
cls.capturevideo.yuvnormalizetable[2][
cls.capturevideo.rgbtoyuvscaletable[2][0][blockr] +
cls.capturevideo.rgbtoyuvscaletable[2][1][blockg] +
cls.capturevideo.rgbtoyuvscaletable[2][2][blockb] + 128];
377 unsigned char *out =
cls.capturevideo.outbuffer;
415 if(
format->videofile_totalframes_offset1)
416 if(
FS_Seek(
cls.capturevideo.videofile,
format->videofile_totalframes_offset1, SEEK_SET) >= 0)
421 if(
format->videofile_totalframes_offset2)
422 if(
FS_Seek(
cls.capturevideo.videofile,
format->videofile_totalframes_offset2, SEEK_SET) >= 0)
427 if (
cls.capturevideo.soundrate)
429 if(
format->videofile_totalsampleframes_offset)
430 if(
FS_Seek(
cls.capturevideo.videofile,
format->videofile_totalsampleframes_offset, SEEK_SET) >= 0)
438 if (
format->riffindexbuffer.data)
445 cls.capturevideo.videofile =
NULL;
455 unsigned char* out_ptr;
459 for(
i = 0, out_ptr = bufstereo16le;
i <
length;
i++, out_ptr += 4)
464 n0 =
bound(-32768, n0, 32767);
465 out_ptr[0] = (
unsigned char)n0;
466 out_ptr[1] = (
unsigned char)(n0 >> 8);
469 n1 =
bound(-32768, n1, 32767);
470 out_ptr[2] = (
unsigned char)n1;
471 out_ptr[3] = (
unsigned char)(n1 >> 8);
507 cls.capturevideo.format = CAPTUREVIDEOFORMAT_AVI_I420;
508 cls.capturevideo.formatextension =
"avi";
509 cls.capturevideo.videofile =
FS_OpenRealFile(
va(vabuf,
sizeof(vabuf),
"%s.%s",
cls.capturevideo.basename,
cls.capturevideo.formatextension),
"wb",
false);
510 if (!
cls.capturevideo.videofile)
512 Con_Printf(
CON_ERROR "Failed to open video file \"%s\", cancelling video capture.\n", vabuf);
513 cls.capturevideo.error =
true;
536 if (
cls.capturevideo.soundrate)
624 if (
cls.capturevideo.soundrate)
677 format->videofile_ix_master_audio_inuse =
format->videofile_ix_master_video_inuse = 0;
700 const char *junkfiller =
"[ DarkPlaces junk data ]";
710 format->videofile_ix_movistart =
format->riffstackstartoffset[1];
713 if (
format->riffstacklevel != 2)
714 Sys_Error(
"SCR_CaptureVideo_BeginVideo: broken AVI writing code (stack level is %i (should be 2) at end of headers)\n",
format->riffstacklevel);
static void SCR_CaptureVideo_RIFF_WriteFourCC(const char *chunkfourcc)
static void SCR_CaptureVideo_Avi_VideoFrames(int num, u8 *in)
static void GrowBuf(sizebuf_t *buf, int extralen)
static void SCR_CaptureVideo_RIFF_Write32(int n)
static void SCR_CaptureVideo_RIFF_OverflowCheck(int framesize)
static void SCR_CaptureVideo_RIFF_WriteTerminatedString(const char *string)
static void SCR_CaptureVideo_RIFF_Pop(void)
void SCR_CaptureVideo_Avi_BeginVideo(void)
static void SCR_CaptureVideo_RIFF_Start(void)
#define LOAD_FORMATSPECIFIC_AVI()
static void SCR_CaptureVideo_RIFF_IndexEntry(const char *chunkfourcc, int chunksize, int flags)
static fs_offset_t SCR_CaptureVideo_RIFF_GetPosition(void)
static void SCR_CaptureVideo_RIFF_FlushNoIncrease(void)
static void SCR_CaptureVideo_Avi_EndVideo(void)
static void SCR_CaptureVideo_ConvertFrame_BGRA_to_I420_flip(int width, int height, unsigned char *instart, unsigned char *outstart)
static void SCR_CaptureVideo_RIFF_MakeIxChunk(const char *fcc, const char *dwChunkId, fs_offset_t masteridx_counter, int *masteridx_count, fs_offset_t masteridx_start)
static void SCR_CaptureVideo_RIFF_Flush(void)
static void SCR_CaptureVideo_RIFF_WriteBytes(const unsigned char *data, size_t size)
static void SCR_CaptureVideo_RIFF_Write16(int n)
#define AVI_MASTER_INDEX_SIZE
static void SCR_CaptureVideo_RIFF_Finish(qbool final)
static void SCR_CaptureVideo_Avi_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
static void SCR_CaptureVideo_RIFF_Push(const char *chunkfourcc, const char *listtypefourcc, fs_offset_t sizeHint)
static unsigned char olddata[NET_MAXMESSAGE]
void MSG_WriteShort(sizebuf_t *sb, int c)
void MSG_WriteString(sizebuf_t *sb, const char *s)
void MSG_WriteLong(sizebuf_t *sb, int c)
void MSG_WriteUnterminatedString(sizebuf_t *sb, const char *s)
char * va(char *buf, size_t buflen, const char *format,...)
void FindFraction(double val, int *num, int *denom, int denomMax)
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
char engineversion[128]
version string for the corner of the console, crash messages, status command, etc
fs_offset_t FS_Write(qfile_t *file, const void *data, size_t datasize)
fs_offset_t FS_Tell(qfile_t *file)
int FS_Seek(qfile_t *file, fs_offset_t offset, int whence)
qfile_t * FS_OpenRealFile(const char *filepath, const char *mode, qbool quiet)
static int(ZEXPORT *qz_inflate)(z_stream *strm
int FS_Close(qfile_t *file)
GLenum GLsizei GLsizei height
GLenum GLuint GLenum GLsizei length
GLint GLint GLint GLsizei GLsizei GLenum format
GLint GLenum GLint GLint y
GLsizeiptr const GLvoid * data
GLuint GLuint GLintptr offset
GLenum GLuint GLenum GLsizei const GLchar * buf
#define bound(min, num, max)
static portable_sampleframe_t paintbuffer[PAINTBUFFER_SIZE]
exported for capturevideo so ogg can see all channels
float sample[SND_LISTENERS]
viddef_mode_t mode
currently active video mode
void Sys_Error(const char *error,...) DP_FUNC_PRINTF(1) DP_FUNC_NORETURN
Causes the entire program to exit ASAP.
viddef_t vid
global video state
#define Mem_Alloc(pool, size)