summaryrefslogtreecommitdiff
path: root/src/renderer
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2006-01-05 04:00:54 +0000
committerTim Angus <tim@ngus.net>2006-01-05 04:00:54 +0000
commit4e6ae21de9bc373801b68a28b66067480bda4288 (patch)
tree0ffa6b987d2ca06daacc7abffe453a4336b3b6da /src/renderer
parent436df98d2345c4caee3f415e75f009f96ef77697 (diff)
* Merged ioq3-460
- avi exporter - cl_autoRecordDemo - .asm dependencies
Diffstat (limited to 'src/renderer')
-rw-r--r--src/renderer/tr_backend.c3
-rw-r--r--src/renderer/tr_cmds.c27
-rw-r--r--src/renderer/tr_image.c58
-rw-r--r--src/renderer/tr_init.c47
-rw-r--r--src/renderer/tr_local.h18
-rw-r--r--src/renderer/tr_public.h3
6 files changed, 155 insertions, 1 deletions
diff --git a/src/renderer/tr_backend.c b/src/renderer/tr_backend.c
index 73449586..9c9b841a 100644
--- a/src/renderer/tr_backend.c
+++ b/src/renderer/tr_backend.c
@@ -1082,6 +1082,9 @@ void RB_ExecuteRenderCommands( const void *data ) {
case RC_SCREENSHOT:
data = RB_TakeScreenshotCmd( data );
break;
+ case RC_VIDEOFRAME:
+ data = RB_TakeVideoFrameCmd( data );
+ break;
case RC_END_OF_LIST:
default:
diff --git a/src/renderer/tr_cmds.c b/src/renderer/tr_cmds.c
index bbcf6385..d637aec0 100644
--- a/src/renderer/tr_cmds.c
+++ b/src/renderer/tr_cmds.c
@@ -446,3 +446,30 @@ void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {
backEnd.pc.msec = 0;
}
+/*
+=============
+RE_TakeVideoFrame
+=============
+*/
+void RE_TakeVideoFrame( int width, int height,
+ byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg )
+{
+ videoFrameCommand_t *cmd;
+
+ if( !tr.registered ) {
+ return;
+ }
+
+ cmd = R_GetCommandBuffer( sizeof( *cmd ) );
+ if( !cmd ) {
+ return;
+ }
+
+ cmd->commandId = RC_VIDEOFRAME;
+
+ cmd->width = width;
+ cmd->height = height;
+ cmd->captureBuffer = captureBuffer;
+ cmd->encodeBuffer = encodeBuffer;
+ cmd->motionJpeg = motionJpeg;
+}
diff --git a/src/renderer/tr_image.c b/src/renderer/tr_image.c
index a3efa2f1..692f00c6 100644
--- a/src/renderer/tr_image.c
+++ b/src/renderer/tr_image.c
@@ -1853,6 +1853,64 @@ void SaveJPG(char * filename, int quality, int image_width, int image_height, un
/* And we're done! */
}
+/*
+=================
+SaveJPGToBuffer
+=================
+*/
+int SaveJPGToBuffer( byte *buffer, int quality,
+ int image_width, int image_height,
+ byte *image_buffer )
+{
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
+ int row_stride; /* physical row width in image buffer */
+
+ /* Step 1: allocate and initialize JPEG compression object */
+ cinfo.err = jpeg_std_error(&jerr);
+ /* Now we can initialize the JPEG compression object. */
+ jpeg_create_compress(&cinfo);
+
+ /* Step 2: specify data destination (eg, a file) */
+ /* Note: steps 2 and 3 can be done in either order. */
+ jpegDest(&cinfo, buffer, image_width*image_height*4);
+
+ /* Step 3: set parameters for compression */
+ cinfo.image_width = image_width; /* image width and height, in pixels */
+ cinfo.image_height = image_height;
+ cinfo.input_components = 4; /* # of color components per pixel */
+ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
+
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
+
+ /* Step 4: Start compressor */
+ jpeg_start_compress(&cinfo, TRUE);
+
+ /* Step 5: while (scan lines remain to be written) */
+ /* jpeg_write_scanlines(...); */
+ row_stride = image_width * 4; /* JSAMPLEs per row in image_buffer */
+
+ while (cinfo.next_scanline < cinfo.image_height) {
+ /* jpeg_write_scanlines expects an array of pointers to scanlines.
+ * Here the array is only one element long, but you could pass
+ * more than one scanline at a time if that's more convenient.
+ */
+ row_pointer[0] = & image_buffer[((cinfo.image_height-1)*row_stride)-cinfo.next_scanline * row_stride];
+ (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+ }
+
+ /* Step 6: Finish compression */
+ jpeg_finish_compress(&cinfo);
+
+ /* Step 7: release JPEG compression object */
+ jpeg_destroy_compress(&cinfo);
+
+ /* And we're done! */
+ return hackSize;
+}
+
//===================================================================
/*
diff --git a/src/renderer/tr_init.c b/src/renderer/tr_init.c
index a3fd2ca6..79c910d1 100644
--- a/src/renderer/tr_init.c
+++ b/src/renderer/tr_init.c
@@ -701,6 +701,51 @@ void R_ScreenShotJPEG_f (void) {
//============================================================================
/*
+==================
+RB_TakeVideoFrameCmd
+==================
+*/
+const void *RB_TakeVideoFrameCmd( const void *data )
+{
+ const videoFrameCommand_t *cmd;
+ int frameSize;
+ int i;
+
+ cmd = (const videoFrameCommand_t *)data;
+
+ qglReadPixels( 0, 0, cmd->width, cmd->height, GL_RGBA,
+ GL_UNSIGNED_BYTE, cmd->captureBuffer );
+
+ // gamma correct
+ if( ( tr.overbrightBits > 0 ) && glConfig.deviceSupportsGamma )
+ R_GammaCorrect( cmd->captureBuffer, cmd->width * cmd->height * 4 );
+
+ if( cmd->motionJpeg )
+ {
+ frameSize = SaveJPGToBuffer( cmd->encodeBuffer, 95,
+ cmd->width, cmd->height, cmd->captureBuffer );
+ }
+ else
+ {
+ frameSize = cmd->width * cmd->height * 4;
+
+ // Vertically flip the image
+ for( i = 0; i < cmd->height; i++ )
+ {
+ Com_Memcpy( &cmd->encodeBuffer[ i * ( cmd->width * 4 ) ],
+ &cmd->captureBuffer[ ( cmd->height - i - 1 ) * ( cmd->width * 4 ) ],
+ cmd->width * 4 );
+ }
+ }
+
+ ri.CL_WriteAVIVideoFrame( cmd->encodeBuffer, frameSize );
+
+ return (const void *)(cmd + 1);
+}
+
+//============================================================================
+
+/*
** GL_SetDefaultState
*/
void GL_SetDefaultState( void )
@@ -1202,5 +1247,7 @@ refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) {
re.GetEntityToken = R_GetEntityToken;
re.inPVS = R_inPVS;
+ re.TakeVideoFrame = RE_TakeVideoFrame;
+
return &re;
}
diff --git a/src/renderer/tr_local.h b/src/renderer/tr_local.h
index 4119efac..7efed35d 100644
--- a/src/renderer/tr_local.h
+++ b/src/renderer/tr_local.h
@@ -1216,6 +1216,7 @@ skin_t *R_GetSkinByHandle( qhandle_t hSkin );
int R_ComputeLOD( trRefEntity_t *ent );
+const void *RB_TakeVideoFrameCmd( const void *data );
//
// tr_shader.c
@@ -1580,6 +1581,15 @@ typedef struct {
qboolean jpeg;
} screenshotCommand_t;
+typedef struct {
+ int commandId;
+ int width;
+ int height;
+ byte *captureBuffer;
+ byte *encodeBuffer;
+ qboolean motionJpeg;
+} videoFrameCommand_t;
+
typedef enum {
RC_END_OF_LIST,
RC_SET_COLOR,
@@ -1587,7 +1597,8 @@ typedef enum {
RC_DRAW_SURFS,
RC_DRAW_BUFFER,
RC_SWAP_BUFFERS,
- RC_SCREENSHOT
+ RC_SCREENSHOT,
+ RC_VIDEOFRAME
} renderCommand_t;
@@ -1636,6 +1647,11 @@ void RE_StretchPic ( float x, float y, float w, float h,
void RE_BeginFrame( stereoFrame_t stereoFrame );
void RE_EndFrame( int *frontEndMsec, int *backEndMsec );
void SaveJPG(char * filename, int quality, int image_width, int image_height, unsigned char *image_buffer);
+int SaveJPGToBuffer( byte *buffer, int quality,
+ int image_width, int image_height,
+ byte *image_buffer );
+void RE_TakeVideoFrame( int width, int height,
+ byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg );
// font stuff
void R_InitFreeType( void );
diff --git a/src/renderer/tr_public.h b/src/renderer/tr_public.h
index 92801ac4..e4e4d047 100644
--- a/src/renderer/tr_public.h
+++ b/src/renderer/tr_public.h
@@ -98,6 +98,8 @@ typedef struct {
void (*RemapShader)(const char *oldShader, const char *newShader, const char *offsetTime);
qboolean (*GetEntityToken)( char *buffer, int size );
qboolean (*inPVS)( const vec3_t p1, const vec3_t p2 );
+
+ void (*TakeVideoFrame)( int h, int w, byte* captureBuffer, byte *encodeBuffer, qboolean motionJpeg );
} refexport_t;
//
@@ -157,6 +159,7 @@ typedef struct {
int (*CIN_PlayCinematic)( const char *arg0, int xpos, int ypos, int width, int height, int bits);
e_status (*CIN_RunCinematic) (int handle);
+ void (*CL_WriteAVIVideoFrame)( const byte *buffer, int size );
} refimport_t;