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