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 24 * id RoQ Video common functions based on work by Dr. Tim Ferguson 25 */ 26 27#include <stdint.h> 28#include <string.h> 29#include "roqvideo.h" 30 31static inline void block_copy(unsigned char *out, unsigned char *in, 32 int outstride, int instride, int sz) 33{ 34 int rows = sz; 35 while(rows--) { 36 memcpy(out, in, sz); 37 out += outstride; 38 in += instride; 39 } 40} 41 42void ff_apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell) 43{ 44 unsigned char *bptr; 45 int boffs,stride; 46 47 stride = ri->current_frame->linesize[0]; 48 boffs = y*stride + x; 49 50 bptr = ri->current_frame->data[0] + boffs; 51 bptr[0 ] = cell->y[0]; 52 bptr[1 ] = cell->y[1]; 53 bptr[stride ] = cell->y[2]; 54 bptr[stride+1] = cell->y[3]; 55 56 stride = ri->current_frame->linesize[1]; 57 boffs = y*stride + x; 58 59 bptr = ri->current_frame->data[1] + boffs; 60 bptr[0 ] = 61 bptr[1 ] = 62 bptr[stride ] = 63 bptr[stride+1] = cell->u; 64 65 bptr = ri->current_frame->data[2] + boffs; 66 bptr[0 ] = 67 bptr[1 ] = 68 bptr[stride ] = 69 bptr[stride+1] = cell->v; 70} 71 72void ff_apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell) 73{ 74 unsigned char *bptr; 75 int boffs,stride; 76 77 stride = ri->current_frame->linesize[0]; 78 boffs = y*stride + x; 79 80 bptr = ri->current_frame->data[0] + boffs; 81 bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] = cell->y[0]; 82 bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] = cell->y[1]; 83 bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] = cell->y[2]; 84 bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->y[3]; 85 86 stride = ri->current_frame->linesize[1]; 87 boffs = y*stride + x; 88 89 bptr = ri->current_frame->data[1] + boffs; 90 bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] = 91 bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] = 92 bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] = 93 bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->u; 94 95 bptr = ri->current_frame->data[2] + boffs; 96 bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] = 97 bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] = 98 bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] = 99 bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->v; 100} 101 102 103static inline void apply_motion_generic(RoqContext *ri, int x, int y, int deltax, 104 int deltay, int sz) 105{ 106 int mx, my, cp; 107 108 mx = x + deltax; 109 my = y + deltay; 110 111 /* check MV against frame boundaries */ 112 if ((mx < 0) || (mx > ri->width - sz) || 113 (my < 0) || (my > ri->height - sz)) { 114 av_log(ri->avctx, AV_LOG_ERROR, "motion vector out of bounds: MV = (%d, %d), boundaries = (0, 0, %d, %d)\n", 115 mx, my, ri->width, ri->height); 116 return; 117 } 118 119 if (!ri->last_frame->data[0]) { 120 av_log(ri->avctx, AV_LOG_ERROR, "Invalid decode type. Invalid header?\n"); 121 return; 122 } 123 124 for(cp = 0; cp < 3; cp++) { 125 int outstride = ri->current_frame->linesize[cp]; 126 int instride = ri->last_frame ->linesize[cp]; 127 block_copy(ri->current_frame->data[cp] + y*outstride + x, 128 ri->last_frame->data[cp] + my*instride + mx, 129 outstride, instride, sz); 130 } 131} 132 133 134void ff_apply_motion_4x4(RoqContext *ri, int x, int y, 135 int deltax, int deltay) 136{ 137 apply_motion_generic(ri, x, y, deltax, deltay, 4); 138} 139 140void ff_apply_motion_8x8(RoqContext *ri, int x, int y, 141 int deltax, int deltay) 142{ 143 apply_motion_generic(ri, x, y, deltax, deltay, 8); 144} 145