diff -r b53c3134d55a -r b7d5d75469ee hedgewars/avwrapper/avwrapper.c --- 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); }