1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Copyright (c) 2015 Henrik Gramner 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * This file is part of FFmpeg. 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or modify 7cabdff1aSopenharmony_ci * it under the terms of the GNU General Public License as published by 8cabdff1aSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 9cabdff1aSopenharmony_ci * (at your option) any later version. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14cabdff1aSopenharmony_ci * GNU General Public License for more details. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * You should have received a copy of the GNU General Public License along 17cabdff1aSopenharmony_ci * with FFmpeg; if not, write to the Free Software Foundation, Inc., 18cabdff1aSopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19cabdff1aSopenharmony_ci */ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include <string.h> 22cabdff1aSopenharmony_ci#include "checkasm.h" 23cabdff1aSopenharmony_ci#include "libavcodec/avcodec.h" 24cabdff1aSopenharmony_ci#include "libavcodec/h264pred.h" 25cabdff1aSopenharmony_ci#include "libavutil/common.h" 26cabdff1aSopenharmony_ci#include "libavutil/internal.h" 27cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 28cabdff1aSopenharmony_ci#include "libavutil/mem_internal.h" 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_cistatic const int codec_ids[4] = { AV_CODEC_ID_H264, AV_CODEC_ID_VP8, AV_CODEC_ID_RV40, AV_CODEC_ID_SVQ3 }; 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_cistatic const char * const pred4x4_modes[4][15] = { 33cabdff1aSopenharmony_ci { /* H.264 */ 34cabdff1aSopenharmony_ci [VERT_PRED ] = "vertical", 35cabdff1aSopenharmony_ci [HOR_PRED ] = "horizontal", 36cabdff1aSopenharmony_ci [DC_PRED ] = "dc", 37cabdff1aSopenharmony_ci [DIAG_DOWN_LEFT_PRED ] = "down_left", 38cabdff1aSopenharmony_ci [DIAG_DOWN_RIGHT_PRED] = "down_right", 39cabdff1aSopenharmony_ci [VERT_RIGHT_PRED ] = "vertical_right", 40cabdff1aSopenharmony_ci [HOR_DOWN_PRED ] = "horizontal_right", 41cabdff1aSopenharmony_ci [VERT_LEFT_PRED ] = "vertical_left", 42cabdff1aSopenharmony_ci [HOR_UP_PRED ] = "horizontal_up", 43cabdff1aSopenharmony_ci [LEFT_DC_PRED ] = "left_dc", 44cabdff1aSopenharmony_ci [TOP_DC_PRED ] = "top_dc", 45cabdff1aSopenharmony_ci [DC_128_PRED ] = "dc_128", 46cabdff1aSopenharmony_ci }, 47cabdff1aSopenharmony_ci { /* VP8 */ 48cabdff1aSopenharmony_ci [VERT_PRED ] = "vertical_vp8", 49cabdff1aSopenharmony_ci [HOR_PRED ] = "horizontal_vp8", 50cabdff1aSopenharmony_ci [VERT_LEFT_PRED] = "vertical_left_vp8", 51cabdff1aSopenharmony_ci [TM_VP8_PRED ] = "tm_vp8", 52cabdff1aSopenharmony_ci [DC_127_PRED ] = "dc_127_vp8", 53cabdff1aSopenharmony_ci [DC_129_PRED ] = "dc_129_vp8", 54cabdff1aSopenharmony_ci }, 55cabdff1aSopenharmony_ci { /* RV40 */ 56cabdff1aSopenharmony_ci [DIAG_DOWN_LEFT_PRED ] = "down_left_rv40", 57cabdff1aSopenharmony_ci [VERT_LEFT_PRED ] = "vertical_left_rv40", 58cabdff1aSopenharmony_ci [HOR_UP_PRED ] = "horizontal_up_rv40", 59cabdff1aSopenharmony_ci [DIAG_DOWN_LEFT_PRED_RV40_NODOWN] = "down_left_nodown_rv40", 60cabdff1aSopenharmony_ci [HOR_UP_PRED_RV40_NODOWN ] = "horizontal_up_nodown_rv40", 61cabdff1aSopenharmony_ci [VERT_LEFT_PRED_RV40_NODOWN ] = "vertical_left_nodown_rv40", 62cabdff1aSopenharmony_ci }, 63cabdff1aSopenharmony_ci { /* SVQ3 */ 64cabdff1aSopenharmony_ci [DIAG_DOWN_LEFT_PRED] = "down_left_svq3", 65cabdff1aSopenharmony_ci }, 66cabdff1aSopenharmony_ci}; 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_cistatic const char * const pred8x8_modes[4][11] = { 69cabdff1aSopenharmony_ci { /* H.264 */ 70cabdff1aSopenharmony_ci [DC_PRED8x8 ] = "dc", 71cabdff1aSopenharmony_ci [HOR_PRED8x8 ] = "horizontal", 72cabdff1aSopenharmony_ci [VERT_PRED8x8 ] = "vertical", 73cabdff1aSopenharmony_ci [PLANE_PRED8x8 ] = "plane", 74cabdff1aSopenharmony_ci [LEFT_DC_PRED8x8 ] = "left_dc", 75cabdff1aSopenharmony_ci [TOP_DC_PRED8x8 ] = "top_dc", 76cabdff1aSopenharmony_ci [DC_128_PRED8x8 ] = "dc_128", 77cabdff1aSopenharmony_ci [ALZHEIMER_DC_L0T_PRED8x8] = "mad_cow_dc_l0t", 78cabdff1aSopenharmony_ci [ALZHEIMER_DC_0LT_PRED8x8] = "mad_cow_dc_0lt", 79cabdff1aSopenharmony_ci [ALZHEIMER_DC_L00_PRED8x8] = "mad_cow_dc_l00", 80cabdff1aSopenharmony_ci [ALZHEIMER_DC_0L0_PRED8x8] = "mad_cow_dc_0l0", 81cabdff1aSopenharmony_ci }, 82cabdff1aSopenharmony_ci { /* VP8 */ 83cabdff1aSopenharmony_ci [PLANE_PRED8x8 ] = "tm_vp8", 84cabdff1aSopenharmony_ci [DC_127_PRED8x8] = "dc_127_vp8", 85cabdff1aSopenharmony_ci [DC_129_PRED8x8] = "dc_129_vp8", 86cabdff1aSopenharmony_ci }, 87cabdff1aSopenharmony_ci { /* RV40 */ 88cabdff1aSopenharmony_ci [DC_PRED8x8 ] = "dc_rv40", 89cabdff1aSopenharmony_ci [LEFT_DC_PRED8x8] = "left_dc_rv40", 90cabdff1aSopenharmony_ci [TOP_DC_PRED8x8 ] = "top_dc_rv40", 91cabdff1aSopenharmony_ci }, 92cabdff1aSopenharmony_ci /* nothing for SVQ3 */ 93cabdff1aSopenharmony_ci}; 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_cistatic const char * const pred16x16_modes[4][9] = { 96cabdff1aSopenharmony_ci { /* H.264 */ 97cabdff1aSopenharmony_ci [DC_PRED8x8 ] = "dc", 98cabdff1aSopenharmony_ci [HOR_PRED8x8 ] = "horizontal", 99cabdff1aSopenharmony_ci [VERT_PRED8x8 ] = "vertical", 100cabdff1aSopenharmony_ci [PLANE_PRED8x8 ] = "plane", 101cabdff1aSopenharmony_ci [LEFT_DC_PRED8x8] = "left_dc", 102cabdff1aSopenharmony_ci [TOP_DC_PRED8x8 ] = "top_dc", 103cabdff1aSopenharmony_ci [DC_128_PRED8x8 ] = "dc_128", 104cabdff1aSopenharmony_ci }, 105cabdff1aSopenharmony_ci { /* VP8 */ 106cabdff1aSopenharmony_ci [PLANE_PRED8x8 ] = "tm_vp8", 107cabdff1aSopenharmony_ci [DC_127_PRED8x8] = "dc_127_vp8", 108cabdff1aSopenharmony_ci [DC_129_PRED8x8] = "dc_129_vp8", 109cabdff1aSopenharmony_ci }, 110cabdff1aSopenharmony_ci { /* RV40 */ 111cabdff1aSopenharmony_ci [PLANE_PRED8x8] = "plane_rv40", 112cabdff1aSopenharmony_ci }, 113cabdff1aSopenharmony_ci { /* SVQ3 */ 114cabdff1aSopenharmony_ci [PLANE_PRED8x8] = "plane_svq3", 115cabdff1aSopenharmony_ci }, 116cabdff1aSopenharmony_ci}; 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_cistatic const uint32_t pixel_mask[3] = { 0xffffffff, 0x01ff01ff, 0x03ff03ff }; 119cabdff1aSopenharmony_ci 120cabdff1aSopenharmony_ci#define SIZEOF_PIXEL ((bit_depth + 7) / 8) 121cabdff1aSopenharmony_ci#define BUF_SIZE (3 * 16 * 17) 122cabdff1aSopenharmony_ci 123cabdff1aSopenharmony_ci#define check_pred_func(func, name, mode_name) \ 124cabdff1aSopenharmony_ci (mode_name && ((codec_ids[codec] == AV_CODEC_ID_H264) ? \ 125cabdff1aSopenharmony_ci check_func(func, "pred%s_%s_%d", name, mode_name, bit_depth) : \ 126cabdff1aSopenharmony_ci check_func(func, "pred%s_%s", name, mode_name))) 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_ci#define randomize_buffers() \ 129cabdff1aSopenharmony_ci do { \ 130cabdff1aSopenharmony_ci uint32_t mask = pixel_mask[bit_depth - 8]; \ 131cabdff1aSopenharmony_ci int i; \ 132cabdff1aSopenharmony_ci for (i = 0; i < BUF_SIZE; i += 4) { \ 133cabdff1aSopenharmony_ci uint32_t r = rnd() & mask; \ 134cabdff1aSopenharmony_ci AV_WN32A(buf0 + i, r); \ 135cabdff1aSopenharmony_ci AV_WN32A(buf1 + i, r); \ 136cabdff1aSopenharmony_ci } \ 137cabdff1aSopenharmony_ci } while (0) 138cabdff1aSopenharmony_ci 139cabdff1aSopenharmony_ci#define src0 (buf0 + 4 * 16) /* Offset to allow room for top and left */ 140cabdff1aSopenharmony_ci#define src1 (buf1 + 4 * 16) 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_cistatic void check_pred4x4(H264PredContext *h, uint8_t *buf0, uint8_t *buf1, 143cabdff1aSopenharmony_ci int codec, int chroma_format, int bit_depth) 144cabdff1aSopenharmony_ci{ 145cabdff1aSopenharmony_ci if (chroma_format == 1) { 146cabdff1aSopenharmony_ci uint8_t *topright = buf0 + 2*16; 147cabdff1aSopenharmony_ci int pred_mode; 148cabdff1aSopenharmony_ci declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *src, const uint8_t *topright, ptrdiff_t stride); 149cabdff1aSopenharmony_ci 150cabdff1aSopenharmony_ci for (pred_mode = 0; pred_mode < 15; pred_mode++) { 151cabdff1aSopenharmony_ci if (check_pred_func(h->pred4x4[pred_mode], "4x4", pred4x4_modes[codec][pred_mode])) { 152cabdff1aSopenharmony_ci randomize_buffers(); 153cabdff1aSopenharmony_ci call_ref(src0, topright, 12*SIZEOF_PIXEL); 154cabdff1aSopenharmony_ci call_new(src1, topright, 12*SIZEOF_PIXEL); 155cabdff1aSopenharmony_ci if (memcmp(buf0, buf1, BUF_SIZE)) 156cabdff1aSopenharmony_ci fail(); 157cabdff1aSopenharmony_ci bench_new(src1, topright, 12*SIZEOF_PIXEL); 158cabdff1aSopenharmony_ci } 159cabdff1aSopenharmony_ci } 160cabdff1aSopenharmony_ci } 161cabdff1aSopenharmony_ci} 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_cistatic void check_pred8x8(H264PredContext *h, uint8_t *buf0, uint8_t *buf1, 164cabdff1aSopenharmony_ci int codec, int chroma_format, int bit_depth) 165cabdff1aSopenharmony_ci{ 166cabdff1aSopenharmony_ci int pred_mode; 167cabdff1aSopenharmony_ci declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *src, ptrdiff_t stride); 168cabdff1aSopenharmony_ci 169cabdff1aSopenharmony_ci for (pred_mode = 0; pred_mode < 11; pred_mode++) { 170cabdff1aSopenharmony_ci if (check_pred_func(h->pred8x8[pred_mode], (chroma_format == 2) ? "8x16" : "8x8", 171cabdff1aSopenharmony_ci pred8x8_modes[codec][pred_mode])) { 172cabdff1aSopenharmony_ci randomize_buffers(); 173cabdff1aSopenharmony_ci call_ref(src0, 24*SIZEOF_PIXEL); 174cabdff1aSopenharmony_ci call_new(src1, 24*SIZEOF_PIXEL); 175cabdff1aSopenharmony_ci if (memcmp(buf0, buf1, BUF_SIZE)) 176cabdff1aSopenharmony_ci fail(); 177cabdff1aSopenharmony_ci bench_new(src1, 24*SIZEOF_PIXEL); 178cabdff1aSopenharmony_ci } 179cabdff1aSopenharmony_ci } 180cabdff1aSopenharmony_ci} 181cabdff1aSopenharmony_ci 182cabdff1aSopenharmony_cistatic void check_pred16x16(H264PredContext *h, uint8_t *buf0, uint8_t *buf1, 183cabdff1aSopenharmony_ci int codec, int chroma_format, int bit_depth) 184cabdff1aSopenharmony_ci{ 185cabdff1aSopenharmony_ci if (chroma_format == 1) { 186cabdff1aSopenharmony_ci int pred_mode; 187cabdff1aSopenharmony_ci declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *src, ptrdiff_t stride); 188cabdff1aSopenharmony_ci 189cabdff1aSopenharmony_ci for (pred_mode = 0; pred_mode < 9; pred_mode++) { 190cabdff1aSopenharmony_ci if (check_pred_func(h->pred16x16[pred_mode], "16x16", pred16x16_modes[codec][pred_mode])) { 191cabdff1aSopenharmony_ci randomize_buffers(); 192cabdff1aSopenharmony_ci call_ref(src0, 48); 193cabdff1aSopenharmony_ci call_new(src1, 48); 194cabdff1aSopenharmony_ci if (memcmp(buf0, buf1, BUF_SIZE)) 195cabdff1aSopenharmony_ci fail(); 196cabdff1aSopenharmony_ci bench_new(src1, 48); 197cabdff1aSopenharmony_ci } 198cabdff1aSopenharmony_ci } 199cabdff1aSopenharmony_ci } 200cabdff1aSopenharmony_ci} 201cabdff1aSopenharmony_ci 202cabdff1aSopenharmony_cistatic void check_pred8x8l(H264PredContext *h, uint8_t *buf0, uint8_t *buf1, 203cabdff1aSopenharmony_ci int codec, int chroma_format, int bit_depth) 204cabdff1aSopenharmony_ci{ 205cabdff1aSopenharmony_ci if (chroma_format == 1 && codec_ids[codec] == AV_CODEC_ID_H264) { 206cabdff1aSopenharmony_ci int pred_mode; 207cabdff1aSopenharmony_ci declare_func_emms(AV_CPU_FLAG_MMXEXT, void, uint8_t *src, int topleft, int topright, ptrdiff_t stride); 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci for (pred_mode = 0; pred_mode < 12; pred_mode++) { 210cabdff1aSopenharmony_ci if (check_pred_func(h->pred8x8l[pred_mode], "8x8l", pred4x4_modes[codec][pred_mode])) { 211cabdff1aSopenharmony_ci int neighbors; 212cabdff1aSopenharmony_ci for (neighbors = 0; neighbors <= 0xc000; neighbors += 0x4000) { 213cabdff1aSopenharmony_ci int has_topleft = neighbors & 0x8000; 214cabdff1aSopenharmony_ci int has_topright = neighbors & 0x4000; 215cabdff1aSopenharmony_ci 216cabdff1aSopenharmony_ci if ((pred_mode == DIAG_DOWN_RIGHT_PRED || pred_mode == VERT_RIGHT_PRED) && !has_topleft) 217cabdff1aSopenharmony_ci continue; /* Those aren't allowed according to the spec */ 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci randomize_buffers(); 220cabdff1aSopenharmony_ci call_ref(src0, has_topleft, has_topright, 24*SIZEOF_PIXEL); 221cabdff1aSopenharmony_ci call_new(src1, has_topleft, has_topright, 24*SIZEOF_PIXEL); 222cabdff1aSopenharmony_ci if (memcmp(buf0, buf1, BUF_SIZE)) 223cabdff1aSopenharmony_ci fail(); 224cabdff1aSopenharmony_ci bench_new(src1, has_topleft, has_topright, 24*SIZEOF_PIXEL); 225cabdff1aSopenharmony_ci } 226cabdff1aSopenharmony_ci } 227cabdff1aSopenharmony_ci } 228cabdff1aSopenharmony_ci } 229cabdff1aSopenharmony_ci} 230cabdff1aSopenharmony_ci 231cabdff1aSopenharmony_ci/* TODO: Add tests for H.264 lossless H/V prediction */ 232cabdff1aSopenharmony_ci 233cabdff1aSopenharmony_civoid checkasm_check_h264pred(void) 234cabdff1aSopenharmony_ci{ 235cabdff1aSopenharmony_ci static const struct { 236cabdff1aSopenharmony_ci void (*func)(H264PredContext*, uint8_t*, uint8_t*, int, int, int); 237cabdff1aSopenharmony_ci const char *name; 238cabdff1aSopenharmony_ci } tests[] = { 239cabdff1aSopenharmony_ci { check_pred4x4, "pred4x4" }, 240cabdff1aSopenharmony_ci { check_pred8x8, "pred8x8" }, 241cabdff1aSopenharmony_ci { check_pred16x16, "pred16x16" }, 242cabdff1aSopenharmony_ci { check_pred8x8l, "pred8x8l" }, 243cabdff1aSopenharmony_ci }; 244cabdff1aSopenharmony_ci 245cabdff1aSopenharmony_ci LOCAL_ALIGNED_16(uint8_t, buf0, [BUF_SIZE]); 246cabdff1aSopenharmony_ci LOCAL_ALIGNED_16(uint8_t, buf1, [BUF_SIZE]); 247cabdff1aSopenharmony_ci H264PredContext h; 248cabdff1aSopenharmony_ci int test, codec, chroma_format, bit_depth; 249cabdff1aSopenharmony_ci 250cabdff1aSopenharmony_ci for (test = 0; test < FF_ARRAY_ELEMS(tests); test++) { 251cabdff1aSopenharmony_ci for (codec = 0; codec < 4; codec++) { 252cabdff1aSopenharmony_ci int codec_id = codec_ids[codec]; 253cabdff1aSopenharmony_ci for (bit_depth = 8; bit_depth <= (codec_id == AV_CODEC_ID_H264 ? 10 : 8); bit_depth++) 254cabdff1aSopenharmony_ci for (chroma_format = 1; chroma_format <= (codec_id == AV_CODEC_ID_H264 ? 2 : 1); chroma_format++) { 255cabdff1aSopenharmony_ci ff_h264_pred_init(&h, codec_id, bit_depth, chroma_format); 256cabdff1aSopenharmony_ci tests[test].func(&h, buf0, buf1, codec, chroma_format, bit_depth); 257cabdff1aSopenharmony_ci } 258cabdff1aSopenharmony_ci } 259cabdff1aSopenharmony_ci report("%s", tests[test].name); 260cabdff1aSopenharmony_ci } 261cabdff1aSopenharmony_ci} 262