1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#include <assert.h> 20cabdff1aSopenharmony_ci#include <stdint.h> 21cabdff1aSopenharmony_ci#include <string.h> 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include "config.h" 24cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 25cabdff1aSopenharmony_ci#include "libavutil/attributes.h" 26cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 27cabdff1aSopenharmony_ci#include "avcodec.h" 28cabdff1aSopenharmony_ci#include "me_cmp.h" 29cabdff1aSopenharmony_ci#include "mpegvideoencdsp.h" 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_cistatic int try_8x8basis_c(int16_t rem[64], int16_t weight[64], 32cabdff1aSopenharmony_ci int16_t basis[64], int scale) 33cabdff1aSopenharmony_ci{ 34cabdff1aSopenharmony_ci int i; 35cabdff1aSopenharmony_ci unsigned int sum = 0; 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_ci for (i = 0; i < 8 * 8; i++) { 38cabdff1aSopenharmony_ci int b = rem[i] + ((basis[i] * scale + 39cabdff1aSopenharmony_ci (1 << (BASIS_SHIFT - RECON_SHIFT - 1))) >> 40cabdff1aSopenharmony_ci (BASIS_SHIFT - RECON_SHIFT)); 41cabdff1aSopenharmony_ci int w = weight[i]; 42cabdff1aSopenharmony_ci b >>= RECON_SHIFT; 43cabdff1aSopenharmony_ci av_assert2(-512 < b && b < 512); 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_ci sum += (w * b) * (w * b) >> 4; 46cabdff1aSopenharmony_ci } 47cabdff1aSopenharmony_ci return sum >> 2; 48cabdff1aSopenharmony_ci} 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_cistatic void add_8x8basis_c(int16_t rem[64], int16_t basis[64], int scale) 51cabdff1aSopenharmony_ci{ 52cabdff1aSopenharmony_ci int i; 53cabdff1aSopenharmony_ci 54cabdff1aSopenharmony_ci for (i = 0; i < 8 * 8; i++) 55cabdff1aSopenharmony_ci rem[i] += (basis[i] * scale + 56cabdff1aSopenharmony_ci (1 << (BASIS_SHIFT - RECON_SHIFT - 1))) >> 57cabdff1aSopenharmony_ci (BASIS_SHIFT - RECON_SHIFT); 58cabdff1aSopenharmony_ci} 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_cistatic int pix_sum_c(uint8_t *pix, int line_size) 61cabdff1aSopenharmony_ci{ 62cabdff1aSopenharmony_ci int s = 0, i, j; 63cabdff1aSopenharmony_ci 64cabdff1aSopenharmony_ci for (i = 0; i < 16; i++) { 65cabdff1aSopenharmony_ci for (j = 0; j < 16; j += 8) { 66cabdff1aSopenharmony_ci s += pix[0]; 67cabdff1aSopenharmony_ci s += pix[1]; 68cabdff1aSopenharmony_ci s += pix[2]; 69cabdff1aSopenharmony_ci s += pix[3]; 70cabdff1aSopenharmony_ci s += pix[4]; 71cabdff1aSopenharmony_ci s += pix[5]; 72cabdff1aSopenharmony_ci s += pix[6]; 73cabdff1aSopenharmony_ci s += pix[7]; 74cabdff1aSopenharmony_ci pix += 8; 75cabdff1aSopenharmony_ci } 76cabdff1aSopenharmony_ci pix += line_size - 16; 77cabdff1aSopenharmony_ci } 78cabdff1aSopenharmony_ci return s; 79cabdff1aSopenharmony_ci} 80cabdff1aSopenharmony_ci 81cabdff1aSopenharmony_cistatic int pix_norm1_c(uint8_t *pix, int line_size) 82cabdff1aSopenharmony_ci{ 83cabdff1aSopenharmony_ci int s = 0, i, j; 84cabdff1aSopenharmony_ci const uint32_t *sq = ff_square_tab + 256; 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci for (i = 0; i < 16; i++) { 87cabdff1aSopenharmony_ci for (j = 0; j < 16; j += 8) { 88cabdff1aSopenharmony_ci#if HAVE_FAST_64BIT 89cabdff1aSopenharmony_ci register uint64_t x = *(uint64_t *) pix; 90cabdff1aSopenharmony_ci s += sq[x & 0xff]; 91cabdff1aSopenharmony_ci s += sq[(x >> 8) & 0xff]; 92cabdff1aSopenharmony_ci s += sq[(x >> 16) & 0xff]; 93cabdff1aSopenharmony_ci s += sq[(x >> 24) & 0xff]; 94cabdff1aSopenharmony_ci s += sq[(x >> 32) & 0xff]; 95cabdff1aSopenharmony_ci s += sq[(x >> 40) & 0xff]; 96cabdff1aSopenharmony_ci s += sq[(x >> 48) & 0xff]; 97cabdff1aSopenharmony_ci s += sq[(x >> 56) & 0xff]; 98cabdff1aSopenharmony_ci#else 99cabdff1aSopenharmony_ci register uint32_t x = *(uint32_t *) pix; 100cabdff1aSopenharmony_ci s += sq[x & 0xff]; 101cabdff1aSopenharmony_ci s += sq[(x >> 8) & 0xff]; 102cabdff1aSopenharmony_ci s += sq[(x >> 16) & 0xff]; 103cabdff1aSopenharmony_ci s += sq[(x >> 24) & 0xff]; 104cabdff1aSopenharmony_ci x = *(uint32_t *) (pix + 4); 105cabdff1aSopenharmony_ci s += sq[x & 0xff]; 106cabdff1aSopenharmony_ci s += sq[(x >> 8) & 0xff]; 107cabdff1aSopenharmony_ci s += sq[(x >> 16) & 0xff]; 108cabdff1aSopenharmony_ci s += sq[(x >> 24) & 0xff]; 109cabdff1aSopenharmony_ci#endif 110cabdff1aSopenharmony_ci pix += 8; 111cabdff1aSopenharmony_ci } 112cabdff1aSopenharmony_ci pix += line_size - 16; 113cabdff1aSopenharmony_ci } 114cabdff1aSopenharmony_ci return s; 115cabdff1aSopenharmony_ci} 116cabdff1aSopenharmony_ci 117cabdff1aSopenharmony_ci/* draw the edges of width 'w' of an image of size width, height */ 118cabdff1aSopenharmony_ci// FIXME: Check that this is OK for MPEG-4 interlaced. 119cabdff1aSopenharmony_cistatic void draw_edges_8_c(uint8_t *buf, int wrap, int width, int height, 120cabdff1aSopenharmony_ci int w, int h, int sides) 121cabdff1aSopenharmony_ci{ 122cabdff1aSopenharmony_ci uint8_t *ptr = buf, *last_line; 123cabdff1aSopenharmony_ci int i; 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci /* left and right */ 126cabdff1aSopenharmony_ci for (i = 0; i < height; i++) { 127cabdff1aSopenharmony_ci memset(ptr - w, ptr[0], w); 128cabdff1aSopenharmony_ci memset(ptr + width, ptr[width - 1], w); 129cabdff1aSopenharmony_ci ptr += wrap; 130cabdff1aSopenharmony_ci } 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci /* top and bottom + corners */ 133cabdff1aSopenharmony_ci buf -= w; 134cabdff1aSopenharmony_ci last_line = buf + (height - 1) * wrap; 135cabdff1aSopenharmony_ci if (sides & EDGE_TOP) 136cabdff1aSopenharmony_ci for (i = 0; i < h; i++) 137cabdff1aSopenharmony_ci // top 138cabdff1aSopenharmony_ci memcpy(buf - (i + 1) * wrap, buf, width + w + w); 139cabdff1aSopenharmony_ci if (sides & EDGE_BOTTOM) 140cabdff1aSopenharmony_ci for (i = 0; i < h; i++) 141cabdff1aSopenharmony_ci // bottom 142cabdff1aSopenharmony_ci memcpy(last_line + (i + 1) * wrap, last_line, width + w + w); 143cabdff1aSopenharmony_ci} 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci/* 2x2 -> 1x1 */ 146cabdff1aSopenharmony_cistatic void shrink22(uint8_t *dst, int dst_wrap, 147cabdff1aSopenharmony_ci const uint8_t *src, int src_wrap, 148cabdff1aSopenharmony_ci int width, int height) 149cabdff1aSopenharmony_ci{ 150cabdff1aSopenharmony_ci int w; 151cabdff1aSopenharmony_ci const uint8_t *s1, *s2; 152cabdff1aSopenharmony_ci uint8_t *d; 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_ci for (; height > 0; height--) { 155cabdff1aSopenharmony_ci s1 = src; 156cabdff1aSopenharmony_ci s2 = s1 + src_wrap; 157cabdff1aSopenharmony_ci d = dst; 158cabdff1aSopenharmony_ci for (w = width; w >= 4; w -= 4) { 159cabdff1aSopenharmony_ci d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; 160cabdff1aSopenharmony_ci d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2; 161cabdff1aSopenharmony_ci d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2; 162cabdff1aSopenharmony_ci d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2; 163cabdff1aSopenharmony_ci s1 += 8; 164cabdff1aSopenharmony_ci s2 += 8; 165cabdff1aSopenharmony_ci d += 4; 166cabdff1aSopenharmony_ci } 167cabdff1aSopenharmony_ci for (; w > 0; w--) { 168cabdff1aSopenharmony_ci d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; 169cabdff1aSopenharmony_ci s1 += 2; 170cabdff1aSopenharmony_ci s2 += 2; 171cabdff1aSopenharmony_ci d++; 172cabdff1aSopenharmony_ci } 173cabdff1aSopenharmony_ci src += 2 * src_wrap; 174cabdff1aSopenharmony_ci dst += dst_wrap; 175cabdff1aSopenharmony_ci } 176cabdff1aSopenharmony_ci} 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci/* 4x4 -> 1x1 */ 179cabdff1aSopenharmony_cistatic void shrink44(uint8_t *dst, int dst_wrap, 180cabdff1aSopenharmony_ci const uint8_t *src, int src_wrap, 181cabdff1aSopenharmony_ci int width, int height) 182cabdff1aSopenharmony_ci{ 183cabdff1aSopenharmony_ci int w; 184cabdff1aSopenharmony_ci const uint8_t *s1, *s2, *s3, *s4; 185cabdff1aSopenharmony_ci uint8_t *d; 186cabdff1aSopenharmony_ci 187cabdff1aSopenharmony_ci for (; height > 0; height--) { 188cabdff1aSopenharmony_ci s1 = src; 189cabdff1aSopenharmony_ci s2 = s1 + src_wrap; 190cabdff1aSopenharmony_ci s3 = s2 + src_wrap; 191cabdff1aSopenharmony_ci s4 = s3 + src_wrap; 192cabdff1aSopenharmony_ci d = dst; 193cabdff1aSopenharmony_ci for (w = width; w > 0; w--) { 194cabdff1aSopenharmony_ci d[0] = (s1[0] + s1[1] + s1[2] + s1[3] + 195cabdff1aSopenharmony_ci s2[0] + s2[1] + s2[2] + s2[3] + 196cabdff1aSopenharmony_ci s3[0] + s3[1] + s3[2] + s3[3] + 197cabdff1aSopenharmony_ci s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4; 198cabdff1aSopenharmony_ci s1 += 4; 199cabdff1aSopenharmony_ci s2 += 4; 200cabdff1aSopenharmony_ci s3 += 4; 201cabdff1aSopenharmony_ci s4 += 4; 202cabdff1aSopenharmony_ci d++; 203cabdff1aSopenharmony_ci } 204cabdff1aSopenharmony_ci src += 4 * src_wrap; 205cabdff1aSopenharmony_ci dst += dst_wrap; 206cabdff1aSopenharmony_ci } 207cabdff1aSopenharmony_ci} 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci/* 8x8 -> 1x1 */ 210cabdff1aSopenharmony_cistatic void shrink88(uint8_t *dst, int dst_wrap, 211cabdff1aSopenharmony_ci const uint8_t *src, int src_wrap, 212cabdff1aSopenharmony_ci int width, int height) 213cabdff1aSopenharmony_ci{ 214cabdff1aSopenharmony_ci int w, i; 215cabdff1aSopenharmony_ci 216cabdff1aSopenharmony_ci for (; height > 0; height--) { 217cabdff1aSopenharmony_ci for(w = width;w > 0; w--) { 218cabdff1aSopenharmony_ci int tmp = 0; 219cabdff1aSopenharmony_ci for (i = 0; i < 8; i++) { 220cabdff1aSopenharmony_ci tmp += src[0] + src[1] + src[2] + src[3] + 221cabdff1aSopenharmony_ci src[4] + src[5] + src[6] + src[7]; 222cabdff1aSopenharmony_ci src += src_wrap; 223cabdff1aSopenharmony_ci } 224cabdff1aSopenharmony_ci *(dst++) = (tmp + 32) >> 6; 225cabdff1aSopenharmony_ci src += 8 - 8 * src_wrap; 226cabdff1aSopenharmony_ci } 227cabdff1aSopenharmony_ci src += 8 * src_wrap - 8 * width; 228cabdff1aSopenharmony_ci dst += dst_wrap - width; 229cabdff1aSopenharmony_ci } 230cabdff1aSopenharmony_ci} 231cabdff1aSopenharmony_ci 232cabdff1aSopenharmony_ciav_cold void ff_mpegvideoencdsp_init(MpegvideoEncDSPContext *c, 233cabdff1aSopenharmony_ci AVCodecContext *avctx) 234cabdff1aSopenharmony_ci{ 235cabdff1aSopenharmony_ci c->try_8x8basis = try_8x8basis_c; 236cabdff1aSopenharmony_ci c->add_8x8basis = add_8x8basis_c; 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ci c->shrink[0] = av_image_copy_plane; 239cabdff1aSopenharmony_ci c->shrink[1] = shrink22; 240cabdff1aSopenharmony_ci c->shrink[2] = shrink44; 241cabdff1aSopenharmony_ci c->shrink[3] = shrink88; 242cabdff1aSopenharmony_ci 243cabdff1aSopenharmony_ci c->pix_sum = pix_sum_c; 244cabdff1aSopenharmony_ci c->pix_norm1 = pix_norm1_c; 245cabdff1aSopenharmony_ci 246cabdff1aSopenharmony_ci c->draw_edges = draw_edges_8_c; 247cabdff1aSopenharmony_ci 248cabdff1aSopenharmony_ci#if ARCH_ARM 249cabdff1aSopenharmony_ci ff_mpegvideoencdsp_init_arm(c, avctx); 250cabdff1aSopenharmony_ci#elif ARCH_PPC 251cabdff1aSopenharmony_ci ff_mpegvideoencdsp_init_ppc(c, avctx); 252cabdff1aSopenharmony_ci#elif ARCH_X86 253cabdff1aSopenharmony_ci ff_mpegvideoencdsp_init_x86(c, avctx); 254cabdff1aSopenharmony_ci#elif ARCH_MIPS 255cabdff1aSopenharmony_ci ff_mpegvideoencdsp_init_mips(c, avctx); 256cabdff1aSopenharmony_ci#endif 257cabdff1aSopenharmony_ci} 258