📄 image.c
字号:
/***************************************************************************
*
* XVID MPEG-4 VIDEO CODEC
* - Image management functions -
*
* Copyright(C) 2001-2003 Peter Ross <pross@xvid.org>
*
* This program is free software ; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id$
*
****************************************************************************/
#include <stdlib.h>
#include <string.h> /* memcpy, memset */
#include <math.h>
#include "../portab.h"
#include "../global.h" /* XVID_CSP_XXX's */
#include "../xvid.h" /* XVID_CSP_XXX's */
#include "image.h"
#include "colorspace.h"
#include "interpolate8x8.h"
#include "reduced.h"
#include "../utils/mem_align.h"
#include "font.h" /* XXX: remove later */
#define SAFETY 64
#define EDGE_SIZE2 (EDGE_SIZE/2)
//////////////////////////////////////////////////
void Init_MDMA(unsigned char * x_ptr, int x_stride, unsigned char * y_ptr,
unsigned char * u_ptr, unsigned char * v_ptr, int y_stride,
int uv_stride, int width, int height, int vflip);
//////////////////////////////////////////////////
int32_t
image_create(IMAGE * image,
uint32_t edged_width,
uint32_t edged_height)
{
const uint32_t edged_width2 = edged_width / 2;
const uint32_t edged_height2 = edged_height / 2;
image->y =
xvid_malloc(edged_width * (edged_height + 1) + SAFETY, CACHE_LINE);
if (image->y == NULL) {
return -1;
}
memset(image->y, 0, edged_width * (edged_height + 1) + SAFETY);
image->u = xvid_malloc(edged_width2 * edged_height2 + SAFETY, CACHE_LINE);
if (image->u == NULL) {
xvid_free(image->y);
image->y = NULL;
return -1;
}
memset(image->u, 0, edged_width2 * edged_height2 + SAFETY);
image->v = xvid_malloc(edged_width2 * edged_height2 + SAFETY, CACHE_LINE);
if (image->v == NULL) {
xvid_free(image->u);
image->u = NULL;
xvid_free(image->y);
image->y = NULL;
return -1;
}
memset(image->v, 0, edged_width2 * edged_height2 + SAFETY);
image->y += EDGE_SIZE * edged_width + EDGE_SIZE;
image->u += EDGE_SIZE2 * edged_width2 + EDGE_SIZE2;
image->v += EDGE_SIZE2 * edged_width2 + EDGE_SIZE2;
return 0;
}
void
image_destroy(IMAGE * image,
uint32_t edged_width,
uint32_t edged_height)
{
const uint32_t edged_width2 = edged_width / 2;
if (image->y) {
xvid_free(image->y - (EDGE_SIZE * edged_width + EDGE_SIZE));
image->y = NULL;
}
if (image->u) {
xvid_free(image->u - (EDGE_SIZE2 * edged_width2 + EDGE_SIZE2));
image->u = NULL;
}
if (image->v) {
xvid_free(image->v - (EDGE_SIZE2 * edged_width2 + EDGE_SIZE2));
image->v = NULL;
}
}
void
image_swap(IMAGE * image1,
IMAGE * image2)
{
SWAP(uint8_t*, image1->y, image2->y);
SWAP(uint8_t*, image1->u, image2->u);
SWAP(uint8_t*, image1->v, image2->v);
}
void
image_copy(IMAGE * image1,
IMAGE * image2,
uint32_t edged_width,
uint32_t height)
{
memcpy(image1->y, image2->y, edged_width * height);
memcpy(image1->u, image2->u, edged_width * height / 4);
memcpy(image1->v, image2->v, edged_width * height / 4);
}
/* setedges bug was fixed in this BS version */
#define SETEDGES_BUG_BEFORE 18
void
image_setedges(IMAGE * image,
uint32_t edged_width,
uint32_t edged_height,
uint32_t width,
uint32_t height,
int bs_version)
{
const uint32_t edged_width2 = edged_width / 2;
uint32_t width2;
uint32_t i;
uint8_t *dst;
uint8_t *src;
dst = image->y - (EDGE_SIZE + EDGE_SIZE * edged_width);
src = image->y;
/* According to the Standard Clause 7.6.4, padding is done starting at 16
* pixel width and height multiples. This was not respected in old xvids */
if (bs_version == 0 || bs_version >= SETEDGES_BUG_BEFORE) {
width = (width+15)&~15;
height = (height+15)&~15;
}
width2 = width/2;
for (i = 0; i < EDGE_SIZE; i++) {
memset(dst, *src, EDGE_SIZE);
memcpy(dst + EDGE_SIZE, src, width);
memset(dst + edged_width - EDGE_SIZE, *(src + width - 1),
EDGE_SIZE);
dst += edged_width;
}
for (i = 0; i < height; i++) {
memset(dst, *src, EDGE_SIZE);
memset(dst + edged_width - EDGE_SIZE, src[width - 1], EDGE_SIZE);
dst += edged_width;
src += edged_width;
}
src -= edged_width;
for (i = 0; i < EDGE_SIZE; i++) {
memset(dst, *src, EDGE_SIZE);
memcpy(dst + EDGE_SIZE, src, width);
memset(dst + edged_width - EDGE_SIZE, *(src + width - 1),
EDGE_SIZE);
dst += edged_width;
}
/* U */
dst = image->u - (EDGE_SIZE2 + EDGE_SIZE2 * edged_width2);
src = image->u;
for (i = 0; i < EDGE_SIZE2; i++) {
memset(dst, *src, EDGE_SIZE2);
memcpy(dst + EDGE_SIZE2, src, width2);
memset(dst + edged_width2 - EDGE_SIZE2, *(src + width2 - 1),
EDGE_SIZE2);
dst += edged_width2;
}
for (i = 0; i < height / 2; i++) {
memset(dst, *src, EDGE_SIZE2);
memset(dst + edged_width2 - EDGE_SIZE2, src[width2 - 1], EDGE_SIZE2);
dst += edged_width2;
src += edged_width2;
}
src -= edged_width2;
for (i = 0; i < EDGE_SIZE2; i++) {
memset(dst, *src, EDGE_SIZE2);
memcpy(dst + EDGE_SIZE2, src, width2);
memset(dst + edged_width2 - EDGE_SIZE2, *(src + width2 - 1),
EDGE_SIZE2);
dst += edged_width2;
}
/* V */
dst = image->v - (EDGE_SIZE2 + EDGE_SIZE2 * edged_width2);
src = image->v;
for (i = 0; i < EDGE_SIZE2; i++) {
memset(dst, *src, EDGE_SIZE2);
memcpy(dst + EDGE_SIZE2, src, width2);
memset(dst + edged_width2 - EDGE_SIZE2, *(src + width2 - 1),
EDGE_SIZE2);
dst += edged_width2;
}
for (i = 0; i < height / 2; i++) {
memset(dst, *src, EDGE_SIZE2);
memset(dst + edged_width2 - EDGE_SIZE2, src[width2 - 1], EDGE_SIZE2);
dst += edged_width2;
src += edged_width2;
}
src -= edged_width2;
for (i = 0; i < EDGE_SIZE2; i++) {
memset(dst, *src, EDGE_SIZE2);
memcpy(dst + EDGE_SIZE2, src, width2);
memset(dst + edged_width2 - EDGE_SIZE2, *(src + width2 - 1),
EDGE_SIZE2);
dst += edged_width2;
}
}
/* bframe encoding requires image-based u,v interpolation */
void
image_interpolate(const IMAGE * refn,
IMAGE * refh,
IMAGE * refv,
IMAGE * refhv,
uint32_t edged_width,
uint32_t edged_height,
uint32_t quarterpel,
uint32_t rounding)
{
#if 0
const uint32_t offset = EDGE_SIZE2 * (edged_width + 1); /* we only interpolate half of the edge area */
const uint32_t stride_add = 7 * edged_width;
#if 0
const uint32_t edged_width2 = edged_width / 2;
const uint32_t edged_height2 = edged_height / 2;
const uint32_t offset2 = EDGE_SIZE2 * (edged_width2 + 1);
const uint32_t
2 = 7 * edged_width2;
#endif
uint8_t *n_ptr, *h_ptr, *v_ptr, *hv_ptr;
uint32_t x, y;
n_ptr = refn->y;
h_ptr = refh->y;
v_ptr = refv->y;
n_ptr -= offset;
h_ptr -= offset;
v_ptr -= offset;
/* Note we initialize the hv pointer later, as we can optimize code a bit
* doing it down to up in quarterpel and up to down in halfpel */
if(quarterpel) {
for (y = 0; y < (edged_height - EDGE_SIZE); y += 8) {
for (x = 0; x < (edged_width - EDGE_SIZE); x += 8) {
interpolate8x8_6tap_lowpass_h(h_ptr, n_ptr, edged_width, rounding);
interpolate8x8_6tap_lowpass_v(v_ptr, n_ptr, edged_width, rounding);
n_ptr += 8;
h_ptr += 8;
v_ptr += 8;
}
n_ptr += EDGE_SIZE;
h_ptr += EDGE_SIZE;
v_ptr += EDGE_SIZE;
h_ptr += stride_add;
v_ptr += stride_add;
n_ptr += stride_add;
}
h_ptr = refh->y + (edged_height - EDGE_SIZE - EDGE_SIZE2)*edged_width - EDGE_SIZE2;
hv_ptr = refhv->y + (edged_height - EDGE_SIZE - EDGE_SIZE2)*edged_width - EDGE_SIZE2;
for (y = 0; y < (edged_height - EDGE_SIZE); y = y + 8) {
hv_ptr -= stride_add;
h_ptr -= stride_add;
hv_ptr -= EDGE_SIZE;
h_ptr -= EDGE_SIZE;
for (x = 0; x < (edged_width - EDGE_SIZE); x = x + 8) {
hv_ptr -= 8;
h_ptr -= 8;
interpolate8x8_6tap_lowpass_v(hv_ptr, h_ptr, edged_width, rounding);
}
}
} else {
hv_ptr = refhv->y;
hv_ptr -= offset;
for (y = 0; y < (edged_height - EDGE_SIZE); y += 8) {
for (x = 0; x < (edged_width - EDGE_SIZE); x += 8) {
interpolate8x8_halfpel_h(h_ptr, n_ptr, edged_width, rounding);
interpolate8x8_halfpel_v(v_ptr, n_ptr, edged_width, rounding);
interpolate8x8_halfpel_hv(hv_ptr, n_ptr, edged_width, rounding);
n_ptr += 8;
h_ptr += 8;
v_ptr += 8;
hv_ptr += 8;
}
h_ptr += EDGE_SIZE;
v_ptr += EDGE_SIZE;
hv_ptr += EDGE_SIZE;
n_ptr += EDGE_SIZE;
h_ptr += stride_add;
v_ptr += stride_add;
hv_ptr += stride_add;
n_ptr += stride_add;
}
}
#else
const uint32_t offset = EDGE_SIZE2 * (edged_width + 1); /* we only interpolate half of the edge area */
const uint32_t stride_add = 7 * edged_width;
uint8_t *n_ptr, *h_ptr, *v_ptr, *hv_ptr;
uint32_t x, y;
n_ptr = refn->y;
h_ptr = refh->y;
v_ptr = refv->y;
//n_ptr -= offset;
//h_ptr -= offset;
//v_ptr -= offset;
hv_ptr = refhv->y;
//hv_ptr -= offset;
_fullinterpolate(n_ptr,h_ptr,v_ptr,hv_ptr,edged_width-EDGE_SIZE*2,edged_height-EDGE_SIZE*2,edged_width);
#endif
/*
#ifdef BFRAMES
n_ptr = refn->u;
h_ptr = refh->u;
v_ptr = refv->u;
hv_ptr = refhv->u;
n_ptr -= offset2;
h_ptr -= offset2;
v_ptr -= offset2;
hv_ptr -= offset2;
for (y = 0; y < edged_height2; y += 8) {
for (x = 0; x < edged_width2; x += 8) {
interpolate8x8_halfpel_h(h_ptr, n_ptr, edged_width2, rounding);
interpolate8x8_halfpel_v(v_ptr, n_ptr, edged_width2, rounding);
interpolate8x8_halfpel_hv(hv_ptr, n_ptr, edged_width2, rounding);
n_ptr += 8;
h_ptr += 8;
v_ptr += 8;
hv_ptr += 8;
}
h_ptr += stride_add2;
v_ptr += stride_add2;
hv_ptr += stride_add2;
n_ptr += stride_add2;
}
n_ptr = refn->v;
h_ptr = refh->v;
v_ptr = refv->v;
hv_ptr = refhv->v;
n_ptr -= offset2;
h_ptr -= offset2;
v_ptr -= offset2;
hv_ptr -= offset2;
for (y = 0; y < edged_height2; y = y + 8) {
for (x = 0; x < edged_width2; x = x + 8) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -