( nv12Data: Uint8ClampedArray, width: number, height: number, yStride: number, fullRange = false, )
| 107 | } |
| 108 | |
| 109 | function convertNv12ToRgbaMainThread( |
| 110 | nv12Data: Uint8ClampedArray, |
| 111 | width: number, |
| 112 | height: number, |
| 113 | yStride: number, |
| 114 | fullRange = false, |
| 115 | ): Uint8ClampedArray { |
| 116 | const rgbaSize = width * height * 4; |
| 117 | if (!mainThreadNv12Buffer || mainThreadNv12BufferSize < rgbaSize) { |
| 118 | mainThreadNv12Buffer = new Uint8ClampedArray(rgbaSize); |
| 119 | mainThreadNv12BufferSize = rgbaSize; |
| 120 | } |
| 121 | const rgba = mainThreadNv12Buffer; |
| 122 | |
| 123 | const ySize = yStride * height; |
| 124 | const yPlane = nv12Data; |
| 125 | const uvPlane = nv12Data.subarray(ySize); |
| 126 | const uvStride = yStride; |
| 127 | |
| 128 | for (let row = 0; row < height; row++) { |
| 129 | const yRowOffset = row * yStride; |
| 130 | const uvRowOffset = (row >> 1) * uvStride; |
| 131 | const rgbaRowOffset = row * width * 4; |
| 132 | |
| 133 | for (let col = 0; col < width; col += 2) { |
| 134 | const uvCol = (col >> 1) * 2; |
| 135 | const u = uvPlane[uvRowOffset + uvCol] - 128; |
| 136 | const v = uvPlane[uvRowOffset + uvCol + 1] - 128; |
| 137 | const d = u; |
| 138 | const e = v; |
| 139 | |
| 140 | const y0 = yPlane[yRowOffset + col]; |
| 141 | let r: number; |
| 142 | let g: number; |
| 143 | let b: number; |
| 144 | if (fullRange) { |
| 145 | r = y0 + ((359 * e + 128) >> 8); |
| 146 | g = y0 - ((88 * d + 183 * e + 128) >> 8); |
| 147 | b = y0 + ((454 * d + 128) >> 8); |
| 148 | } else { |
| 149 | const c0 = 298 * (y0 - 16); |
| 150 | r = (c0 + 409 * e + 128) >> 8; |
| 151 | g = (c0 - 100 * d - 208 * e + 128) >> 8; |
| 152 | b = (c0 + 516 * d + 128) >> 8; |
| 153 | } |
| 154 | |
| 155 | r = r < 0 ? 0 : r > 255 ? 255 : r; |
| 156 | g = g < 0 ? 0 : g > 255 ? 255 : g; |
| 157 | b = b < 0 ? 0 : b > 255 ? 255 : b; |
| 158 | |
| 159 | const rgbaOffset = rgbaRowOffset + col * 4; |
| 160 | rgba[rgbaOffset] = r; |
| 161 | rgba[rgbaOffset + 1] = g; |
| 162 | rgba[rgbaOffset + 2] = b; |
| 163 | rgba[rgbaOffset + 3] = 255; |
| 164 | |
| 165 | const nextCol = col + 1; |
| 166 | if (nextCol < width) { |
no outgoing calls
no test coverage detected