1/* 2 * This file is part of FFmpeg. 3 * 4 * FFmpeg is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * FFmpeg is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with FFmpeg; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19#include <assert.h> 20#include <stdint.h> 21#include <string.h> 22 23#include "config.h" 24#include "libavutil/avassert.h" 25#include "libavutil/attributes.h" 26#include "libavutil/imgutils.h" 27#include "avcodec.h" 28#include "dsputil.h" 29#include "imgconvert.h" 30#include "mpegvideoencdsp.h" 31 32static int try_8x8basis_c(int16_t rem[64], int16_t weight[64], 33 int16_t basis[64], int scale) 34{ 35 int i; 36 unsigned int sum = 0; 37 38 for (i = 0; i < 8 * 8; i++) { 39 int b = rem[i] + ((basis[i] * scale + 40 (1 << (BASIS_SHIFT - RECON_SHIFT - 1))) >> 41 (BASIS_SHIFT - RECON_SHIFT)); 42 int w = weight[i]; 43 b >>= RECON_SHIFT; 44 av_assert2(-512 < b && b < 512); 45 46 sum += (w * b) * (w * b) >> 4; 47 } 48 return sum >> 2; 49} 50 51static void add_8x8basis_c(int16_t rem[64], int16_t basis[64], int scale) 52{ 53 int i; 54 55 for (i = 0; i < 8 * 8; i++) 56 rem[i] += (basis[i] * scale + 57 (1 << (BASIS_SHIFT - RECON_SHIFT - 1))) >> 58 (BASIS_SHIFT - RECON_SHIFT); 59} 60 61static int pix_sum_c(uint8_t *pix, int line_size) 62{ 63 int s = 0, i, j; 64 65 for (i = 0; i < 16; i++) { 66 for (j = 0; j < 16; j += 8) { 67 s += pix[0]; 68 s += pix[1]; 69 s += pix[2]; 70 s += pix[3]; 71 s += pix[4]; 72 s += pix[5]; 73 s += pix[6]; 74 s += pix[7]; 75 pix += 8; 76 } 77 pix += line_size - 16; 78 } 79 return s; 80} 81 82static int pix_norm1_c(uint8_t *pix, int line_size) 83{ 84 int s = 0, i, j; 85 uint32_t *sq = ff_square_tab + 256; 86 87 for (i = 0; i < 16; i++) { 88 for (j = 0; j < 16; j += 8) { 89#if 0 90 s += sq[pix[0]]; 91 s += sq[pix[1]]; 92 s += sq[pix[2]]; 93 s += sq[pix[3]]; 94 s += sq[pix[4]]; 95 s += sq[pix[5]]; 96 s += sq[pix[6]]; 97 s += sq[pix[7]]; 98#else 99#if HAVE_FAST_64BIT 100 register uint64_t x = *(uint64_t *) pix; 101 s += sq[x & 0xff]; 102 s += sq[(x >> 8) & 0xff]; 103 s += sq[(x >> 16) & 0xff]; 104 s += sq[(x >> 24) & 0xff]; 105 s += sq[(x >> 32) & 0xff]; 106 s += sq[(x >> 40) & 0xff]; 107 s += sq[(x >> 48) & 0xff]; 108 s += sq[(x >> 56) & 0xff]; 109#else 110 register uint32_t x = *(uint32_t *) pix; 111 s += sq[x & 0xff]; 112 s += sq[(x >> 8) & 0xff]; 113 s += sq[(x >> 16) & 0xff]; 114 s += sq[(x >> 24) & 0xff]; 115 x = *(uint32_t *) (pix + 4); 116 s += sq[x & 0xff]; 117 s += sq[(x >> 8) & 0xff]; 118 s += sq[(x >> 16) & 0xff]; 119 s += sq[(x >> 24) & 0xff]; 120#endif 121#endif 122 pix += 8; 123 } 124 pix += line_size - 16; 125 } 126 return s; 127} 128 129/* draw the edges of width 'w' of an image of size width, height */ 130// FIXME: Check that this is OK for MPEG-4 interlaced. 131static void draw_edges_8_c(uint8_t *buf, int wrap, int width, int height, 132 int w, int h, int sides) 133{ 134 uint8_t *ptr = buf, *last_line; 135 int i; 136 137 /* left and right */ 138 for (i = 0; i < height; i++) { 139 memset(ptr - w, ptr[0], w); 140 memset(ptr + width, ptr[width - 1], w); 141 ptr += wrap; 142 } 143 144 /* top and bottom + corners */ 145 buf -= w; 146 last_line = buf + (height - 1) * wrap; 147 if (sides & EDGE_TOP) 148 for (i = 0; i < h; i++) 149 // top 150 memcpy(buf - (i + 1) * wrap, buf, width + w + w); 151 if (sides & EDGE_BOTTOM) 152 for (i = 0; i < h; i++) 153 // bottom 154 memcpy(last_line + (i + 1) * wrap, last_line, width + w + w); 155} 156 157av_cold void ff_mpegvideoencdsp_init(MpegvideoEncDSPContext *c, 158 AVCodecContext *avctx) 159{ 160 c->try_8x8basis = try_8x8basis_c; 161 c->add_8x8basis = add_8x8basis_c; 162 163 c->shrink[0] = av_image_copy_plane; 164 c->shrink[1] = ff_shrink22; 165 c->shrink[2] = ff_shrink44; 166 c->shrink[3] = ff_shrink88; 167 168 c->pix_sum = pix_sum_c; 169 c->pix_norm1 = pix_norm1_c; 170 171 c->draw_edges = draw_edges_8_c; 172 173 if (ARCH_ARM) 174 ff_mpegvideoencdsp_init_arm(c, avctx); 175 if (ARCH_PPC) 176 ff_mpegvideoencdsp_init_ppc(c, avctx); 177 if (ARCH_X86) 178 ff_mpegvideoencdsp_init_x86(c, avctx); 179} 180