/* * FFv1 codec * * Copyright (c) 2024 Lynne * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ ivec4 load_components(ivec2 pos) { if (planar_rgb == 0) return ivec4(imageLoad(src[0], pos)); ivec4 pix; for (int i = 0; i < (3 + transparency); i++) pix[i] = int(imageLoad(src[i], pos)[0]); /* Swizzle out the difference */ if (bits > 8 && bits < 16 && transparency == 0) return pix.bgra; return pix.brga; } void bypass_sample(ivec2 pos) { imageStore(dst[0], pos, load_components(pos)); } void bypass_block(in SliceContext sc) { ivec2 start = ivec2(gl_LocalInvocationID) + sc.slice_pos; ivec2 end = sc.slice_pos + sc.slice_dim; for (uint y = start.y; y < end.y; y += gl_WorkGroupSize.y) for (uint x = start.x; x < end.x; x += gl_WorkGroupSize.x) bypass_sample(ivec2(x, y)); } void transform_sample(ivec2 pos, ivec2 rct_coef) { ivec4 pix = load_components(pos); pix.b -= pix.g; pix.r -= pix.g; pix.g += (pix.r*rct_coef.x + pix.b*rct_coef.y) >> 2; pix.b += offset; pix.r += offset; imageStore(dst[0], pos, pix); } void transform_block(in SliceContext sc) { const ivec2 rct_coef = sc.slice_rct_coef; const ivec2 start = ivec2(gl_LocalInvocationID) + sc.slice_pos; const ivec2 end = sc.slice_pos + sc.slice_dim; for (uint y = start.y; y < end.y; y += gl_WorkGroupSize.y) for (uint x = start.x; x < end.x; x += gl_WorkGroupSize.x) transform_sample(ivec2(x, y), rct_coef); } void main() { const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x; if (slice_ctx[slice_idx].slice_coding_mode == 1) bypass_block(slice_ctx[slice_idx]); else transform_block(slice_ctx[slice_idx]); }