/*-*- 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 "dsp/mpeg/video.h" #include "libc/log/check.h" forceinline void plm_video_process_macroblock(plm_video_t *self, uint8_t *restrict d, uint8_t *restrict s, int motion_h, int motion_v, bool interpolate, unsigned BW) { unsigned si, di, max_address; int y, x, dest_scan, source_scan, dw, hp, vp, odd_h, odd_v; dw = self->mb_width * BW; hp = motion_h >> 1; vp = motion_v >> 1; odd_h = (motion_h & 1) == 1; odd_v = (motion_v & 1) == 1; si = ((self->mb_row * BW) + vp) * dw + (self->mb_col * BW) + hp; di = (self->mb_row * dw + self->mb_col) * BW; max_address = (dw * (self->mb_height * BW - BW + 1) - BW); if (si > max_address || di > max_address) return; d += di; s += si; switch (((interpolate << 2) | (odd_h << 1) | (odd_v)) & 7) { case 0: dest_scan = dw - BW; source_scan = dw - BW; for (y = 0; y < BW; y++) { for (x = 0; x < BW; x++) { *d++ = *s++; } s += source_scan; d += dest_scan; } break; case 1: dest_scan = dw - BW; source_scan = dw - BW; for (y = 0; y < BW; y++) { for (x = 0; x < BW; x++) { *d++ = (s[0] + s[dw] + 1) >> 1; s++; } s += source_scan; d += dest_scan; } break; case 2: dest_scan = dw - BW; source_scan = dw - BW; for (y = 0; y < BW; y++) { for (x = 0; x < BW; x++) { *d++ = (s[0] + s[1] + 1) >> 1; s++; } s += source_scan; d += dest_scan; } break; case 3: dest_scan = dw - BW; source_scan = dw - BW; for (y = 0; y < BW; y++) { for (x = 0; x < BW; x++) { *d++ = (s[0] + s[1] + s[dw] + s[dw + 1] + 2) >> 2; s++; } s += source_scan; d += dest_scan; } break; case 4: dest_scan = dw - BW; source_scan = dw - BW; for (y = 0; y < BW; y++) { for (x = 0; x < BW; x++) { d[0] = (d[0] + (s[0]) + 1) >> 1; d++; s++; } s += source_scan; d += dest_scan; } break; case 5: dest_scan = dw - BW; source_scan = dw - BW; for (y = 0; y < BW; y++) { for (x = 0; x < BW; x++) { d[0] = (d[0] + ((s[0] + s[dw] + 1) >> 1) + 1) >> 1; d++; s++; } s += source_scan; d += dest_scan; } break; case 6: dest_scan = dw - BW; source_scan = dw - BW; for (y = 0; y < BW; y++) { for (x = 0; x < BW; x++) { d[0] = (d[0] + ((s[0] + s[1] + 1) >> 1) + 1) >> 1; d++; s++; } s += source_scan; d += dest_scan; } break; case 7: dest_scan = dw - BW; source_scan = dw - BW; for (y = 0; y < BW; y++) { for (x = 0; x < BW; x++) { d[0] = (d[0] + ((s[0] + s[1] + s[dw] + s[dw + 1] + 2) >> 2) + 1) >> 1; d++; s++; } s += source_scan; d += dest_scan; } break; default: break; } } void plm_video_process_macroblock_8(plm_video_t *self, uint8_t *restrict d, uint8_t *restrict s, int motion_h, int motion_v, bool interpolate) { DCHECK_ALIGNED(8, d); DCHECK_ALIGNED(8, s); plm_video_process_macroblock(self, d, s, motion_h, motion_v, interpolate, 8); } void plm_video_process_macroblock_16(plm_video_t *self, uint8_t *restrict d, uint8_t *restrict s, int motion_h, int motion_v, bool interpolate) { DCHECK_ALIGNED(16, d); DCHECK_ALIGNED(16, s); plm_video_process_macroblock(self, d, s, motion_h, motion_v, interpolate, 16); }