hedgewars/avwrapper/avwrapper.c
changeset 11612 b7d5d75469ee
parent 11543 3617c611406b
child 11614 3c959df6638e
--- 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);
 }