package com.foxx.androidcast.media;

/*********************************************************************
 * RgbToNv21.java
 * Created at: Sat 16 May 2026 18:50:36 +0200
 * Updated at: Wed 20 May 2026 15:17:13 +0200 by Anton Afanasyeu <a.afanasieff@gmail.com>
 * Commit: 5d8e82d2e60a21fff3138d2a394ee4e8b4c6dcb8
 * class RgbToNv21
 * Contributors:
 *    - Anton Afanasyeu <a.afanasieff@gmail.com> (2 commits, 59 lines)
 *    - Cursor Agent (project assistant)
 * Digest: SHA256	40a855caf25776c7d70981d056f0463ed62523d4d1fcb9427af1a1f566cd1da5
**********************************************************************/
import android.graphics.Bitmap;

/** ARGB bitmap to NV21 for YUV420 encoder input. */
public final class RgbToNv21 {
    private RgbToNv21() {}

    public static byte[] fromBitmap(Bitmap bitmap) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int[] argb = new int[width * height];
        bitmap.getPixels(argb, 0, width, 0, 0, width, height);
        return fromArgb(argb, width, height);
    }

    public static byte[] fromArgb(int[] argb, int width, int height) {
        int frameSize = width * height;
        int ySize = frameSize;
        int uvSize = frameSize / 2;
        byte[] nv21 = new byte[ySize + uvSize];
        int yIndex = 0;
        int uvIndex = ySize;
        for (int j = 0; j < height; j++) {
            for (int i = 0; i < width; i++) {
                int color = argb[j * width + i];
                int r = (color >> 16) & 0xff;
                int g = (color >> 8) & 0xff;
                int b = color & 0xff;
                int y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16;
                int u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
                int v = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;
                nv21[yIndex++] = (byte) clamp(y);
                if ((j & 1) == 0 && (i & 1) == 0) {
                    nv21[uvIndex++] = (byte) clamp(v);
                    nv21[uvIndex++] = (byte) clamp(u);
                }
            }
        }
        return nv21;
    }

    private static int clamp(int v) {
        if (v < 0) {
            return 0;
        }
        if (v > 255) {
            return 255;
        }
        return v;
    }
}
