1/* 2 * Copyright (C) 2003 Mike Melanson 3 * Copyright (C) 2003 Dr. Tim Ferguson 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file libavcodec/roqvideo.c 24 * id RoQ Video common functions based on work by Dr. Tim Ferguson 25 */ 26 27#include "avcodec.h" 28#include "roqvideo.h" 29 30static inline void block_copy(unsigned char *out, unsigned char *in, 31 int outstride, int instride, int sz) 32{ 33 int rows = sz; 34 while(rows--) { 35 memcpy(out, in, sz); 36 out += outstride; 37 in += instride; 38 } 39} 40 41void ff_apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell) 42{ 43 unsigned char *bptr; 44 int boffs,stride; 45 46 stride = ri->current_frame->linesize[0]; 47 boffs = y*stride + x; 48 49 bptr = ri->current_frame->data[0] + boffs; 50 bptr[0 ] = cell->y[0]; 51 bptr[1 ] = cell->y[1]; 52 bptr[stride ] = cell->y[2]; 53 bptr[stride+1] = cell->y[3]; 54 55 stride = ri->current_frame->linesize[1]; 56 boffs = y*stride + x; 57 58 bptr = ri->current_frame->data[1] + boffs; 59 bptr[0 ] = 60 bptr[1 ] = 61 bptr[stride ] = 62 bptr[stride+1] = cell->u; 63 64 bptr = ri->current_frame->data[2] + boffs; 65 bptr[0 ] = 66 bptr[1 ] = 67 bptr[stride ] = 68 bptr[stride+1] = cell->v; 69} 70 71void ff_apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell) 72{ 73 unsigned char *bptr; 74 int boffs,stride; 75 76 stride = ri->current_frame->linesize[0]; 77 boffs = y*stride + x; 78 79 bptr = ri->current_frame->data[0] + boffs; 80 bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] = cell->y[0]; 81 bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] = cell->y[1]; 82 bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] = cell->y[2]; 83 bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->y[3]; 84 85 stride = ri->current_frame->linesize[1]; 86 boffs = y*stride + x; 87 88 bptr = ri->current_frame->data[1] + boffs; 89 bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] = 90 bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] = 91 bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] = 92 bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->u; 93 94 bptr = ri->current_frame->data[2] + boffs; 95 bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] = 96 bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] = 97 bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] = 98 bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->v; 99} 100 101 102static inline void apply_motion_generic(RoqContext *ri, int x, int y, int deltax, 103 int deltay, int sz) 104{ 105 int mx, my, cp; 106 107 mx = x + deltax; 108 my = y + deltay; 109 110 /* check MV against frame boundaries */ 111 if ((mx < 0) || (mx > ri->width - sz) || 112 (my < 0) || (my > ri->height - sz)) { 113 av_log(ri->avctx, AV_LOG_ERROR, "motion vector out of bounds: MV = (%d, %d), boundaries = (0, 0, %d, %d)\n", 114 mx, my, ri->width, ri->height); 115 return; 116 } 117 118 for(cp = 0; cp < 3; cp++) { 119 int outstride = ri->current_frame->linesize[cp]; 120 int instride = ri->last_frame ->linesize[cp]; 121 block_copy(ri->current_frame->data[cp] + y*outstride + x, 122 ri->last_frame->data[cp] + my*instride + mx, 123 outstride, instride, sz); 124 } 125} 126 127 128void ff_apply_motion_4x4(RoqContext *ri, int x, int y, 129 int deltax, int deltay) 130{ 131 apply_motion_generic(ri, x, y, deltax, deltay, 4); 132} 133 134void ff_apply_motion_8x8(RoqContext *ri, int x, int y, 135 int deltax, int deltay) 136{ 137 apply_motion_generic(ri, x, y, deltax, deltay, 8); 138} 139