Skip to content

Instantly share code, notes, and snippets.

@MartijnBraam
Created January 11, 2024 12:16
Show Gist options
  • Save MartijnBraam/9dde585614b916199427063c18f6afa8 to your computer and use it in GitHub Desktop.
Save MartijnBraam/9dde585614b916199427063c18f6afa8 to your computer and use it in GitHub Desktop.
bmd
/*
Copyright 2021 - 2022, Martijn Braam and the OpenAtem contributors
SPDX-License-Identifier: LGPL-3.0-only
*/
#include <stdint.h>
#include <malloc.h>
#define PY_SSIZE_T_CLEAN
#define RLE_HEADER 0xFEFEFEFEFEFEFEFE
const double bt709_coeff_r = 0.2126;
const double bt709_coeff_g = 0.7152;
const double bt709_coeff_b = 0.0722;
const double bt709_coeff_ri = 1.0 - bt709_coeff_r;
const double bt709_coeff_bi = 1.0 - bt709_coeff_b;
const double bt709_coeff_bg = bt709_coeff_b / bt709_coeff_g;
const double bt709_coeff_rg = bt709_coeff_r / bt709_coeff_g;
const int y_offset = 16 << 8;
const int y_range = 219;
const int cr_offset = 128 << 8;
const int cr_range = 224;
const int cr_middle = 224 / 2;
const double bt709_ri_range = bt709_coeff_ri / cr_middle;
const double bt709_bi_range = bt709_coeff_bi / cr_middle;
unsigned short
clamp(unsigned short v, unsigned short min, unsigned short max)
{
const short t = v < min ? min : v;
return t > max ? max : t;
}
int
main()
{
unsigned int width = 2;
unsigned int height = 1;
int data_length = 8;
unsigned char *buffer = (unsigned char *) malloc(8);
buffer[0] = 0xFF; // R
buffer[1] = 0x00; // G
buffer[2] = 0x00; // B
buffer[3] = 0xFF; // A
buffer[4] = 0xFF; // R
buffer[5] = 0x00; // G
buffer[6] = 0x00; // B
buffer[7] = 0xFF; // A
char *outbuffer = (char *) malloc(data_length);
char *writepointer = outbuffer;
int pixel_size = 8;
for (int i = 0; i < data_length; i += pixel_size) {
// Convert RGBA 8888 to 10-bit BT.709 Y'CbCrA
float r1 = (float) buffer[0] / 255;
float g1 = (float) buffer[1] / 255;
float b1 = (float) buffer[2] / 255;
float r2 = (float) buffer[4] / 255;
float g2 = (float) buffer[5] / 255;
float b2 = (float) buffer[6] / 255;
printf("INPUT:\n");
printf(" 1 = %f %f %f\n", r1, g1, b1);
printf(" 2 = %f %f %f\n", r2, g2, b2);
printf(" R = %f %f %f\n", 1.0f, 0.0f, 0.0f);
float y1 = (0.2126 * r1) + (0.7152 * g1) + (0.0722 * b1);
float y2 = (0.2126 * r2) + (0.7152 * g2) + (0.0722 * b2);
float cb = (b2 - y2) / 1.8556;
float cr = (r2 - y2) / 1.5748;
printf("YCbCr:\n");
printf(" 1 = %f %f %f\n", y1, cb, cr);
printf(" 2 = %f %f %f\n", y2, cb, cr);
printf(" R = %f %f %f\n", 0.212600f, -0.114572f, 0.5f);
unsigned short a10a = ((buffer[3] << 2) * 219 / 255) + (15 << 2) + 1;
unsigned short a10b = ((buffer[7] << 2) * 219 / 255) + (15 << 2) + 1;
unsigned short y10a = clamp((unsigned short) (y1 * 876) + 64, 64, 940);
unsigned short y10b = clamp((unsigned short) (y2 * 876) + 64, 64, 940);
unsigned short cb10 = clamp((unsigned short) (cb * 896) + 512, 44, 960);
unsigned short cr10 = clamp((unsigned short) (cr * 896) + 512, 44, 960);
printf("Integers:\n");
printf(" 1 = %d %d %d %d\n", y10a, cb10, cr10, a10a);
printf(" 2 = %d %d %d %d\n", y10b, cb10, cr10, a10b);
printf(" R = %d %d %d %d\n", 250, 410, 960, 937);
writepointer[0] = (unsigned char) (a10a >> 4);
writepointer[1] = (unsigned char) (((a10a & 0x0f) << 4) | (cb10 >> 6));
writepointer[2] = (unsigned char) (((cb10 & 0x3f) << 2) | (y10a >> 8));
writepointer[3] = (unsigned char) (y10a & 0xff);
writepointer[4] = (unsigned char) (a10b >> 4);
writepointer[5] = (unsigned char) (((a10b & 0x0f) << 4) | (cr10 >> 6));
writepointer[6] = (unsigned char) (((cr10 & 0x3f) << 2) | (y10b >> 8));
writepointer[7] = (unsigned char) (y10b & 0xff);
printf("Packed:\n");
printf(" %X %X %X %X %X %X %X %X\n",
writepointer[0] & 0xFF, writepointer[1] & 0xFF, writepointer[2] & 0xFF, writepointer[3] & 0xFF,
writepointer[4] & 0xFF, writepointer[5] & 0xFF, writepointer[6] & 0xFF, writepointer[7] & 0xFF);
printf(" 3A 96 68 FA 3A 9F 0 FA\n");
writepointer += pixel_size;
buffer += pixel_size;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment