/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│ │vi: set et ft=c ts=4 sw=4 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ │ PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer │ │ Dominic Szablewski - https://phoboslab.org │ │ │ │ The MIT License(MIT) │ │ Copyright(c) 2019 Dominic Szablewski │ │ │ │ Permission is hereby granted, free of charge, to any person obtaining │ │ a copy of this software and associated documentation files(the │ │ "Software"), to deal in the Software without restriction, including │ │ without limitation the rights to use, copy, modify, merge, publish, │ │ distribute, sublicense, and / or sell copies of the Software, and to │ │ permit persons to whom the Software is furnished to do so, subject to │ │ the following conditions: │ │ │ │ The above copyright notice and this permission notice shall be │ │ included in all copies or substantial portions of the Software. │ │ │ │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND │ │ NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE │ │ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN │ │ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN │ │ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE │ │ SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "dsp/mpeg/mpeg.h" #include "libc/macros.h" asm(".ident\t\"\\n\\n\ PL_MPEG (MIT License)\\n\ Copyright(c) 2019 Dominic Szablewski\\n\ https://phoboslab.org\""); asm(".include \"libc/disclaimer.inc\""); /** * @see YCbCr2RGB() in tool/viz/lib/ycbcr2rgb.c */ void plm_frame_to_rgb(plm_frame_t *frame, uint8_t *rgb) { // Chroma values are the same for each block of 4 pixels, so we proccess // 2 lines at a time, 2 neighboring pixels each. int w = frame->y.width, w2 = w >> 1; int y_index1 = 0, y_index2 = w, y_next_2_lines = w + (w - frame->width); int c_index = 0, c_next_line = w2 - (frame->width >> 1); int rgb_index1 = 0, rgb_index2 = frame->width * 3, rgb_next_2_lines = frame->width * 3; int cols = frame->width >> 1, rows = frame->height >> 1; int ccb, ccr, r, g, b; uint8_t *y = frame->y.data, *cb = frame->cb.data, *cr = frame->cr.data; for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { ccb = cb[c_index]; ccr = cr[c_index]; c_index++; r = (ccr + ((ccr * 103) >> 8)) - 179; g = ((ccb * 88) >> 8) - 44 + ((ccr * 183) >> 8) - 91; b = (ccb + ((ccb * 198) >> 8)) - 227; // Line 1 int y1 = y[y_index1++]; int y2 = y[y_index1++]; rgb[rgb_index1 + 0] = MAX(0, MIN(255, y1 + r)); rgb[rgb_index1 + 1] = MAX(0, MIN(255, y1 - g)); rgb[rgb_index1 + 2] = MAX(0, MIN(255, y1 + b)); rgb[rgb_index1 + 3] = MAX(0, MIN(255, y2 + r)); rgb[rgb_index1 + 4] = MAX(0, MIN(255, y2 - g)); rgb[rgb_index1 + 5] = MAX(0, MIN(255, y2 + b)); rgb_index1 += 6; // Line 2 int y3 = y[y_index2++]; int y4 = y[y_index2++]; rgb[rgb_index2 + 0] = MAX(0, MIN(255, y3 + r)); rgb[rgb_index2 + 1] = MAX(0, MIN(255, y3 - g)); rgb[rgb_index2 + 2] = MAX(0, MIN(255, y3 + b)); rgb[rgb_index2 + 3] = MAX(0, MIN(255, y4 + r)); rgb[rgb_index2 + 4] = MAX(0, MIN(255, y4 - g)); rgb[rgb_index2 + 5] = MAX(0, MIN(255, y4 + b)); rgb_index2 += 6; } y_index1 += y_next_2_lines; y_index2 += y_next_2_lines; rgb_index1 += rgb_next_2_lines; rgb_index2 += rgb_next_2_lines; c_index += c_next_line; } }