+ int outoffset = (width/2)*(height/2);
+ //return SCR_ScreenShot(filename, cl_capturevideo_buffer, cl_capturevideo_buffer + vid.realwidth * vid.realheight * 3, cl_capturevideo_buffer + vid.realwidth * vid.realheight * 6, vid.realx, vid.realy, vid.realwidth, vid.realheight, false, false, false, jpeg);
+ // speed is critical here, so do saving as directly as possible
+ switch (cl_capturevideo_format)
+ {
+ case CAPTUREVIDEOFORMAT_RAWYV12:
+ // FIXME: width/height must be multiple of 2, enforce this?
+ qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cl_capturevideo_buffer);
+ CHECKGLERROR
+ // process one line at a time, and CbCr every other line at 2 pixel intervals
+ for (y = 0;y < height;y++)
+ {
+ // 1x1 Y
+ for (b = cl_capturevideo_buffer + (height-1-y)*width*3, out = cl_capturevideo_buffer + width*height*3 + y*width, x = 0;x < width;x++, b += 3, out++)
+ *out = cl_capturevideo_yuvnormalizetable[0][cl_capturevideo_rgbtoyuvscaletable[0][0][b[0]] + cl_capturevideo_rgbtoyuvscaletable[0][1][b[1]] + cl_capturevideo_rgbtoyuvscaletable[0][2][b[2]]];
+ if ((y & 1) == 0)
+ {
+ // 2x2 Cb and Cr planes
+#if 1
+ // low quality, no averaging
+ for (b = cl_capturevideo_buffer + (height-2-y)*width*3, out = cl_capturevideo_buffer + width*height*3 + width*height + (y/2)*(width/2), x = 0;x < width/2;x++, b += 6, out++)
+ {
+ // Cr
+ out[0 ] = cl_capturevideo_yuvnormalizetable[2][cl_capturevideo_rgbtoyuvscaletable[2][0][b[0]] + cl_capturevideo_rgbtoyuvscaletable[2][1][b[1]] + cl_capturevideo_rgbtoyuvscaletable[2][2][b[2]] + 128];
+ // Cb
+ out[outoffset] = cl_capturevideo_yuvnormalizetable[1][cl_capturevideo_rgbtoyuvscaletable[1][0][b[0]] + cl_capturevideo_rgbtoyuvscaletable[1][1][b[1]] + cl_capturevideo_rgbtoyuvscaletable[1][2][b[2]] + 128];
+ }
+#else
+ // high quality, averaging
+ int inpitch = width*3;
+ for (b = cl_capturevideo_buffer + (height-2-y)*width*3, out = cl_capturevideo_buffer + width*height*3 + width*height + (y/2)*(width/2), x = 0;x < width/2;x++, b += 6, out++)
+ {
+ int blockr, blockg, blockb;
+ blockr = (b[0] + b[3] + b[inpitch+0] + b[inpitch+3]) >> 2;
+ blockg = (b[1] + b[4] + b[inpitch+1] + b[inpitch+4]) >> 2;
+ blockb = (b[2] + b[5] + b[inpitch+2] + b[inpitch+5]) >> 2;
+ // Cr
+ out[0 ] = cl_capturevideo_yuvnormalizetable[2][cl_capturevideo_rgbtoyuvscaletable[2][0][blockr] + cl_capturevideo_rgbtoyuvscaletable[2][1][blockg] + cl_capturevideo_rgbtoyuvscaletable[2][2][blockb] + 128];
+ // Cb
+ out[outoffset] = cl_capturevideo_yuvnormalizetable[1][cl_capturevideo_rgbtoyuvscaletable[1][0][blockr] + cl_capturevideo_rgbtoyuvscaletable[1][1][blockg] + cl_capturevideo_rgbtoyuvscaletable[1][2][blockb] + 128];
+ }
+#endif
+ }
+ }
+ for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++)
+ if (!FS_Write (cl_capturevideo_videofile, cl_capturevideo_buffer + width*height*3, width*height+(width/2)*(height/2)*2))
+ return false;
+ return true;
+ case CAPTUREVIDEOFORMAT_RAWRGB:
+ qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cl_capturevideo_buffer);
+ CHECKGLERROR
+ for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++)
+ if (!FS_Write (cl_capturevideo_videofile, cl_capturevideo_buffer, width*height*3))
+ return false;
+ return true;
+ case CAPTUREVIDEOFORMAT_JPEG:
+ qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cl_capturevideo_buffer);
+ CHECKGLERROR
+ for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++)
+ {
+ sprintf(filename, "video/dp%06d.jpg", cl_capturevideo_frame);
+ if (!JPEG_SaveImage_preflipped (filename, width, height, cl_capturevideo_buffer))
+ return false;
+ }
+ return true;
+ case CAPTUREVIDEOFORMAT_TARGA:
+ //return Image_WriteTGARGB_preflipped (filename, width, height, cl_capturevideo_buffer, cl_capturevideo_buffer + vid.realwidth * vid.realheight * 3, );
+ memset (cl_capturevideo_buffer, 0, 18);
+ cl_capturevideo_buffer[2] = 2; // uncompressed type
+ cl_capturevideo_buffer[12] = (width >> 0) & 0xFF;
+ cl_capturevideo_buffer[13] = (width >> 8) & 0xFF;
+ cl_capturevideo_buffer[14] = (height >> 0) & 0xFF;
+ cl_capturevideo_buffer[15] = (height >> 8) & 0xFF;
+ cl_capturevideo_buffer[16] = 24; // pixel size
+ qglReadPixels (x, y, width, height, GL_BGR, GL_UNSIGNED_BYTE, cl_capturevideo_buffer + 18);
+ CHECKGLERROR
+ for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++)
+ {
+ sprintf(filename, "video/dp%06d.tga", cl_capturevideo_frame);
+ if (!FS_WriteFile (filename, cl_capturevideo_buffer, width*height*3 + 18))
+ return false;
+ }
+ return true;
+ default:
+ return false;
+ }
+}