yading@10: /* yading@10: * Copyright (C) 2003 Mike Melanson yading@10: * Copyright (C) 2003 Dr. Tim Ferguson yading@10: * yading@10: * This file is part of FFmpeg. yading@10: * yading@10: * FFmpeg is free software; you can redistribute it and/or yading@10: * modify it under the terms of the GNU Lesser General Public yading@10: * License as published by the Free Software Foundation; either yading@10: * version 2.1 of the License, or (at your option) any later version. yading@10: * yading@10: * FFmpeg is distributed in the hope that it will be useful, yading@10: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@10: * Lesser General Public License for more details. yading@10: * yading@10: * You should have received a copy of the GNU Lesser General Public yading@10: * License along with FFmpeg; if not, write to the Free Software yading@10: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@10: */ yading@10: yading@10: /** yading@10: * @file yading@10: * id RoQ Video common functions based on work by Dr. Tim Ferguson yading@10: */ yading@10: yading@10: #include "avcodec.h" yading@10: #include "roqvideo.h" yading@10: yading@10: static inline void block_copy(unsigned char *out, unsigned char *in, yading@10: int outstride, int instride, int sz) yading@10: { yading@10: int rows = sz; yading@10: while(rows--) { yading@10: memcpy(out, in, sz); yading@10: out += outstride; yading@10: in += instride; yading@10: } yading@10: } yading@10: yading@10: void ff_apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell) yading@10: { yading@10: unsigned char *bptr; yading@10: int boffs,stride; yading@10: yading@10: stride = ri->current_frame->linesize[0]; yading@10: boffs = y*stride + x; yading@10: yading@10: bptr = ri->current_frame->data[0] + boffs; yading@10: bptr[0 ] = cell->y[0]; yading@10: bptr[1 ] = cell->y[1]; yading@10: bptr[stride ] = cell->y[2]; yading@10: bptr[stride+1] = cell->y[3]; yading@10: yading@10: stride = ri->current_frame->linesize[1]; yading@10: boffs = y*stride + x; yading@10: yading@10: bptr = ri->current_frame->data[1] + boffs; yading@10: bptr[0 ] = yading@10: bptr[1 ] = yading@10: bptr[stride ] = yading@10: bptr[stride+1] = cell->u; yading@10: yading@10: bptr = ri->current_frame->data[2] + boffs; yading@10: bptr[0 ] = yading@10: bptr[1 ] = yading@10: bptr[stride ] = yading@10: bptr[stride+1] = cell->v; yading@10: } yading@10: yading@10: void ff_apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell) yading@10: { yading@10: unsigned char *bptr; yading@10: int boffs,stride; yading@10: yading@10: stride = ri->current_frame->linesize[0]; yading@10: boffs = y*stride + x; yading@10: yading@10: bptr = ri->current_frame->data[0] + boffs; yading@10: bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] = cell->y[0]; yading@10: bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] = cell->y[1]; yading@10: bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] = cell->y[2]; yading@10: bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->y[3]; yading@10: yading@10: stride = ri->current_frame->linesize[1]; yading@10: boffs = y*stride + x; yading@10: yading@10: bptr = ri->current_frame->data[1] + boffs; yading@10: bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] = yading@10: bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] = yading@10: bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] = yading@10: bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->u; yading@10: yading@10: bptr = ri->current_frame->data[2] + boffs; yading@10: bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] = yading@10: bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] = yading@10: bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] = yading@10: bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->v; yading@10: } yading@10: yading@10: yading@10: static inline void apply_motion_generic(RoqContext *ri, int x, int y, int deltax, yading@10: int deltay, int sz) yading@10: { yading@10: int mx, my, cp; yading@10: yading@10: mx = x + deltax; yading@10: my = y + deltay; yading@10: yading@10: /* check MV against frame boundaries */ yading@10: if ((mx < 0) || (mx > ri->width - sz) || yading@10: (my < 0) || (my > ri->height - sz)) { yading@10: av_log(ri->avctx, AV_LOG_ERROR, "motion vector out of bounds: MV = (%d, %d), boundaries = (0, 0, %d, %d)\n", yading@10: mx, my, ri->width, ri->height); yading@10: return; yading@10: } yading@10: yading@10: if (ri->last_frame->data[0] == NULL) { yading@10: av_log(ri->avctx, AV_LOG_ERROR, "Invalid decode type. Invalid header?\n"); yading@10: return; yading@10: } yading@10: yading@10: for(cp = 0; cp < 3; cp++) { yading@10: int outstride = ri->current_frame->linesize[cp]; yading@10: int instride = ri->last_frame ->linesize[cp]; yading@10: block_copy(ri->current_frame->data[cp] + y*outstride + x, yading@10: ri->last_frame->data[cp] + my*instride + mx, yading@10: outstride, instride, sz); yading@10: } yading@10: } yading@10: yading@10: yading@10: void ff_apply_motion_4x4(RoqContext *ri, int x, int y, yading@10: int deltax, int deltay) yading@10: { yading@10: apply_motion_generic(ri, x, y, deltax, deltay, 4); yading@10: } yading@10: yading@10: void ff_apply_motion_8x8(RoqContext *ri, int x, int y, yading@10: int deltax, int deltay) yading@10: { yading@10: apply_motion_generic(ri, x, y, deltax, deltay, 8); yading@10: }