--- a/hedgewars/avwrapper/avwrapper.c Sun Mar 20 01:16:11 2016 -0400
+++ b/hedgewars/avwrapper/avwrapper.c Sun Mar 20 03:08:51 2016 -0400
@@ -333,15 +333,13 @@
g_pVFrame = av_frame_alloc();
if (!g_pVFrame)
return FatalError("Could not allocate frame");
+ av_frame_unref(g_pVFrame);
g_pVFrame->width = g_Width;
g_pVFrame->height = g_Height;
g_pVFrame->format = AV_PIX_FMT_YUV420P;
- g_pVFrame->linesize[0] = g_Width;
- g_pVFrame->linesize[1] = g_Width/2;
- g_pVFrame->linesize[2] = g_Width/2;
- g_pVFrame->linesize[3] = 0;
- return 0;
+
+ return avcodec_default_get_buffer2(g_pVideo, g_pVFrame, 0);
}
static int WriteFrame(AVFrame* pFrame)
@@ -418,11 +416,47 @@
}
}
-AVWRAP_DECL int AVWrapper_WriteFrame(uint8_t* pY, uint8_t* pCb, uint8_t* pCr)
+AVWRAP_DECL int AVWrapper_WriteFrame(uint8_t *buf)
{
- g_pVFrame->data[0] = pY;
- g_pVFrame->data[1] = pCb;
- g_pVFrame->data[2] = pCr;
+ int x, y, stride = g_Width * 4;
+ uint8_t *data[3];
+
+ // copy pointers, prepare source
+ memcpy(data, g_pVFrame->data, sizeof(data));
+ buf += (g_Height - 1) * stride;
+
+ // convert to YUV 4:2:0
+ for (y = 0; y < g_Height; y++) {
+ for (x = 0; x < g_Width; x++) {
+ int r = buf[x * 4 + 0];
+ int g = buf[x * 4 + 1];
+ int b = buf[x * 4 + 2];
+
+ int luma = (int)(0.299f * r + 0.587f * g + 0.114f * b);
+ data[0][x] = av_clip_uint8(luma);
+
+ if (!(x & 1) && !(y & 1)) {
+ int r = (buf[x * 4 + 0] + buf[(x + 1) * 4 + 0] +
+ buf[x * 4 + 0 + stride] + buf[(x + 1) * 4 + 0 + stride]) / 4;
+ int g = (buf[x * 4 + 1] + buf[(x + 1) * 4 + 1] +
+ buf[x * 4 + 1 + stride] + buf[(x + 1) * 4 + 1 + stride]) / 4;
+ int b = (buf[x * 4 + 2] + buf[(x + 1) * 4 + 2] +
+ buf[x * 4 + 2 + stride] + buf[(x + 1) * 4 + 2 + stride]) / 4;
+
+ int cr = (int)(-0.14713f * r - 0.28886f * g + 0.436f * b);
+ int cb = (int)( 0.615f * r - 0.51499f * g - 0.10001f * b);
+ data[1][x / 2] = av_clip_uint8(128 + cr);
+ data[2][x / 2] = av_clip_uint8(128 + cb);
+ }
+ }
+ buf += -stride;
+ data[0] += g_pVFrame->linesize[0];
+ if (y & 1) {
+ data[1] += g_pVFrame->linesize[1];
+ data[2] += g_pVFrame->linesize[2];
+ }
+ }
+
return WriteFrame(g_pVFrame);
}
--- a/hedgewars/uVideoRec.pas Sun Mar 20 01:16:11 2016 -0400
+++ b/hedgewars/uVideoRec.pas Sun Mar 20 03:08:51 2016 -0400
@@ -58,7 +58,7 @@
filename, desc, soundFile, format, vcodec, acodec: PChar;
width, height, framerateNum, framerateDen, vquality: LongInt): LongInt; cdecl; external AvwrapperLibName;
function AVWrapper_Close: LongInt; cdecl; external AvwrapperLibName;
-function AVWrapper_WriteFrame( pY, pCb, pCr: PByte ): LongInt; cdecl; external AvwrapperLibName;
+function AVWrapper_WriteFrame(rgb: PByte): LongInt; cdecl; external AvwrapperLibName;
type TFrame = record
realTicks: LongWord;
@@ -121,15 +121,6 @@
true) then exit(false);
numPixels:= cScreenWidth*cScreenHeight;
- YCbCr_Planes[0]:= GetMem(numPixels);
- YCbCr_Planes[1]:= GetMem(numPixels div 4);
- YCbCr_Planes[2]:= GetMem(numPixels div 4);
-
- if (YCbCr_Planes[0] = nil) or (YCbCr_Planes[1] = nil) or (YCbCr_Planes[2] = nil) then
- begin
- AddFileLog('Error: Could not allocate memory for video recording (YCbCr buffer).');
- exit(false);
- end;
RGB_Buffer:= GetMem(4*numPixels);
if RGB_Buffer = nil then
@@ -147,9 +138,6 @@
procedure StopVideoRecording;
begin
AddFileLog('StopVideoRecording');
- FreeMem(YCbCr_Planes[0], numPixels);
- FreeMem(YCbCr_Planes[1], numPixels div 4);
- FreeMem(YCbCr_Planes[2], numPixels div 4);
FreeMem(RGB_Buffer, 4*numPixels);
Close(cameraFile);
if AVWrapper_Close() < 0 then
@@ -159,36 +147,13 @@
SendIPC(_S'v'); // inform frontend that we finished
end;
-function pixel(x, y, color: LongInt): LongInt;
-begin
- pixel:= RGB_Buffer[(cScreenHeight-y-1)*cScreenWidth*4 + x*4 + color];
-end;
-
procedure EncodeFrame;
-var x, y, r, g, b: LongInt;
- s: shortstring;
+var s: shortstring;
begin
// read pixels from OpenGL
glReadPixels(0, 0, cScreenWidth, cScreenHeight, GL_RGBA, GL_UNSIGNED_BYTE, RGB_Buffer);
- // convert to YCbCr 4:2:0 format
- // Y
- for y := 0 to cScreenHeight-1 do
- for x := 0 to cScreenWidth-1 do
- YCbCr_Planes[0][y*cScreenWidth + x]:= Byte(16 + ((16828*pixel(x,y,0) + 33038*pixel(x,y,1) + 6416*pixel(x,y,2)) shr 16));
-
- // Cb and Cr
- for y := 0 to cScreenHeight div 2 - 1 do
- for x := 0 to cScreenWidth div 2 - 1 do
- begin
- r:= pixel(2*x,2*y,0) + pixel(2*x+1,2*y,0) + pixel(2*x,2*y+1,0) + pixel(2*x+1,2*y+1,0);
- g:= pixel(2*x,2*y,1) + pixel(2*x+1,2*y,1) + pixel(2*x,2*y+1,1) + pixel(2*x+1,2*y+1,1);
- b:= pixel(2*x,2*y,2) + pixel(2*x+1,2*y,2) + pixel(2*x,2*y+1,2) + pixel(2*x+1,2*y+1,2);
- YCbCr_Planes[1][y*(cScreenWidth div 2) + x]:= Byte(128 + ((-2428*r - 4768*g + 7196*b) shr 16));
- YCbCr_Planes[2][y*(cScreenWidth div 2) + x]:= Byte(128 + (( 7196*r - 6026*g - 1170*b) shr 16));
- end;
-
- if AVWrapper_WriteFrame(YCbCr_Planes[0], YCbCr_Planes[1], YCbCr_Planes[2]) < 0 then
+ if AVWrapper_WriteFrame(RGB_Buffer) < 0 then
halt(-1);
// inform frontend that we have encoded new frame