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
block_copy(unsigned char * out,unsigned char * in,int outstride,int instride,int sz)31 static 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
ff_apply_vector_2x2(RoqContext * ri,int x,int y,roq_cell * cell)42 void 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
ff_apply_vector_4x4(RoqContext * ri,int x,int y,roq_cell * cell)72 void 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
apply_motion_generic(RoqContext * ri,int x,int y,int deltax,int deltay,int sz)103 static 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
ff_apply_motion_4x4(RoqContext * ri,int x,int y,int deltax,int deltay)134 void 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
ff_apply_motion_8x8(RoqContext * ri,int x,int y,int deltax,int deltay)140 void 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