~ubuntu-branches/ubuntu/jaunty/xvidcap/jaunty-proposed

« back to all changes in this revision

Viewing changes to ffmpeg/libavcodec/roqvideo.c

  • Committer: Bazaar Package Importer
  • Author(s): Lionel Le Folgoc, Andrew Starr-Bochicchio, Lionel Le Folgoc
  • Date: 2008-12-26 00:10:06 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20081226001006-2040ls9680bd1blt
Tags: 1.1.7-0.2ubuntu1
[ Andrew Starr-Bochicchio ]
* Merge from debian-multimedia (LP: #298547), Ubuntu Changes:
 - For ffmpeg-related build-deps, fix versionized dependencies
   as the ubuntu versioning is different than debian-multimedia's.

[ Lionel Le Folgoc ]
* LP: #311412 is fixed since the 1.1.7~rc1-0.1 revision.
* debian/patches/03_ffmpeg.diff: updated to fix FTBFS due to libswscale API
  change (cherry-pick from Gentoo #234383).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2003 the ffmpeg project
 
2
 * Copyright (C) 2003 Mike Melanson
 
3
 * Copyright (C) 2003 Dr. Tim Ferguson
3
4
 *
4
5
 * This file is part of FFmpeg.
5
6
 *
16
17
 * You should have received a copy of the GNU Lesser General Public
17
18
 * License along with FFmpeg; if not, write to the Free Software
18
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 
 *
20
20
 */
21
21
 
22
22
/**
23
23
 * @file roqvideo.c
24
 
 * Id RoQ Video Decoder by Dr. Tim Ferguson
25
 
 * For more information about the Id RoQ format, visit:
26
 
 *   http://www.csse.monash.edu.au/~timf/
 
24
 * Id RoQ Video common functions based on work by Dr. Tim Ferguson
27
25
 */
28
26
 
29
 
#include <stdio.h>
30
 
#include <stdlib.h>
31
 
#include <string.h>
32
 
#include <unistd.h>
33
 
 
34
 
#include "common.h"
35
27
#include "avcodec.h"
36
 
#include "dsputil.h"
37
 
 
38
 
typedef struct {
39
 
  unsigned char y0, y1, y2, y3, u, v;
40
 
} roq_cell;
41
 
 
42
 
typedef struct {
43
 
  int idx[4];
44
 
} roq_qcell;
45
 
 
46
 
static int uiclip[1024], *uiclp;  /* clipping table */
47
 
#define avg2(a,b) uiclp[(((int)(a)+(int)(b)+1)>>1)]
48
 
#define avg4(a,b,c,d) uiclp[(((int)(a)+(int)(b)+(int)(c)+(int)(d)+2)>>2)]
49
 
 
50
 
typedef struct RoqContext {
51
 
 
52
 
    AVCodecContext *avctx;
53
 
    DSPContext dsp;
54
 
    AVFrame frames[2];
55
 
    AVFrame *last_frame;
56
 
    AVFrame *current_frame;
57
 
    int first_frame;
58
 
    int y_stride;
59
 
    int c_stride;
60
 
 
61
 
    roq_cell cells[256];
62
 
    roq_qcell qcells[256];
63
 
 
64
 
    unsigned char *buf;
65
 
    int size;
66
 
 
67
 
} RoqContext;
68
 
 
69
 
#define RoQ_INFO              0x1001
70
 
#define RoQ_QUAD_CODEBOOK     0x1002
71
 
#define RoQ_QUAD_VQ           0x1011
72
 
#define RoQ_SOUND_MONO        0x1020
73
 
#define RoQ_SOUND_STEREO      0x1021
74
 
 
75
 
#define RoQ_ID_MOT              0x00
76
 
#define RoQ_ID_FCC              0x01
77
 
#define RoQ_ID_SLD              0x02
78
 
#define RoQ_ID_CCC              0x03
79
 
 
80
 
#define get_byte(in_buffer) *(in_buffer++)
81
 
#define get_word(in_buffer) ((unsigned short)(in_buffer += 2, \
82
 
  (in_buffer[-1] << 8 | in_buffer[-2])))
83
 
#define get_long(in_buffer) ((unsigned long)(in_buffer += 4, \
84
 
  (in_buffer[-1] << 24 | in_buffer[-2] << 16 | in_buffer[-3] << 8 | in_buffer[-4])))
85
 
 
86
 
 
87
 
static void apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell)
88
 
{
89
 
    unsigned char *yptr;
90
 
 
91
 
    yptr = ri->current_frame->data[0] + (y * ri->y_stride) + x;
92
 
    *yptr++ = cell->y0;
93
 
    *yptr++ = cell->y1;
94
 
    yptr += (ri->y_stride - 2);
95
 
    *yptr++ = cell->y2;
96
 
    *yptr++ = cell->y3;
97
 
    ri->current_frame->data[1][(y/2) * (ri->c_stride) + x/2] = cell->u;
98
 
    ri->current_frame->data[2][(y/2) * (ri->c_stride) + x/2] = cell->v;
99
 
}
100
 
 
101
 
static void apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell)
102
 
{
103
 
    unsigned long row_inc, c_row_inc;
104
 
    register unsigned char y0, y1, u, v;
105
 
    unsigned char *yptr, *uptr, *vptr;
106
 
 
107
 
    yptr = ri->current_frame->data[0] + (y * ri->y_stride) + x;
108
 
    uptr = ri->current_frame->data[1] + (y/2) * (ri->c_stride) + x/2;
109
 
    vptr = ri->current_frame->data[2] + (y/2) * (ri->c_stride) + x/2;
110
 
 
111
 
    row_inc = ri->y_stride - 4;
112
 
    c_row_inc = (ri->c_stride) - 2;
113
 
    *yptr++ = y0 = cell->y0; *uptr++ = u = cell->u; *vptr++ = v = cell->v;
114
 
    *yptr++ = y0;
115
 
    *yptr++ = y1 = cell->y1; *uptr++ = u; *vptr++ = v;
116
 
    *yptr++ = y1;
117
 
 
118
 
    yptr += row_inc;
119
 
 
120
 
    *yptr++ = y0;
121
 
    *yptr++ = y0;
122
 
    *yptr++ = y1;
123
 
    *yptr++ = y1;
124
 
 
125
 
    yptr += row_inc; uptr += c_row_inc; vptr += c_row_inc;
126
 
 
127
 
    *yptr++ = y0 = cell->y2; *uptr++ = u; *vptr++ = v;
128
 
    *yptr++ = y0;
129
 
    *yptr++ = y1 = cell->y3; *uptr++ = u; *vptr++ = v;
130
 
    *yptr++ = y1;
131
 
 
132
 
    yptr += row_inc;
133
 
 
134
 
    *yptr++ = y0;
135
 
    *yptr++ = y0;
136
 
    *yptr++ = y1;
137
 
    *yptr++ = y1;
138
 
}
139
 
 
140
 
static void apply_motion_4x4(RoqContext *ri, int x, int y, unsigned char mv,
141
 
    signed char mean_x, signed char mean_y)
142
 
{
143
 
    int i, hw, mx, my;
144
 
    unsigned char *pa, *pb;
145
 
 
146
 
    mx = x + 8 - (mv >> 4) - mean_x;
147
 
    my = y + 8 - (mv & 0xf) - mean_y;
148
 
 
149
 
    /* check MV against frame boundaries */
150
 
    if ((mx < 0) || (mx > ri->avctx->width - 4) ||
151
 
        (my < 0) || (my > ri->avctx->height - 4)) {
152
 
        av_log(ri->avctx, AV_LOG_ERROR, "motion vector out of bounds: MV = (%d, %d), boundaries = (0, 0, %d, %d)\n",
153
 
            mx, my, ri->avctx->width, ri->avctx->height);
154
 
        return;
155
 
    }
156
 
 
157
 
    pa = ri->current_frame->data[0] + (y * ri->y_stride) + x;
158
 
    pb = ri->last_frame->data[0] + (my * ri->y_stride) + mx;
159
 
    for(i = 0; i < 4; i++) {
160
 
        pa[0] = pb[0];
161
 
        pa[1] = pb[1];
162
 
        pa[2] = pb[2];
163
 
        pa[3] = pb[3];
164
 
        pa += ri->y_stride;
165
 
        pb += ri->y_stride;
166
 
    }
167
 
 
168
 
    hw = ri->y_stride/2;
169
 
    pa = ri->current_frame->data[1] + (y * ri->y_stride)/4 + x/2;
170
 
    pb = ri->last_frame->data[1] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
171
 
 
172
 
    for(i = 0; i < 2; i++) {
173
 
        switch(((my & 0x01) << 1) | (mx & 0x01)) {
174
 
 
175
 
        case 0:
176
 
            pa[0] = pb[0];
177
 
            pa[1] = pb[1];
178
 
            pa[hw] = pb[hw];
179
 
            pa[hw+1] = pb[hw+1];
180
 
            break;
181
 
 
182
 
        case 1:
183
 
            pa[0] = avg2(pb[0], pb[1]);
184
 
            pa[1] = avg2(pb[1], pb[2]);
185
 
            pa[hw] = avg2(pb[hw], pb[hw+1]);
186
 
            pa[hw+1] = avg2(pb[hw+1], pb[hw+2]);
187
 
            break;
188
 
 
189
 
        case 2:
190
 
            pa[0] = avg2(pb[0], pb[hw]);
191
 
            pa[1] = avg2(pb[1], pb[hw+1]);
192
 
            pa[hw] = avg2(pb[hw], pb[hw*2]);
193
 
            pa[hw+1] = avg2(pb[hw+1], pb[(hw*2)+1]);
194
 
            break;
195
 
 
196
 
        case 3:
197
 
            pa[0] = avg4(pb[0], pb[1], pb[hw], pb[hw+1]);
198
 
            pa[1] = avg4(pb[1], pb[2], pb[hw+1], pb[hw+2]);
199
 
            pa[hw] = avg4(pb[hw], pb[hw+1], pb[hw*2], pb[(hw*2)+1]);
200
 
            pa[hw+1] = avg4(pb[hw+1], pb[hw+2], pb[(hw*2)+1], pb[(hw*2)+1]);
201
 
            break;
202
 
        }
203
 
 
204
 
        pa = ri->current_frame->data[2] + (y * ri->y_stride)/4 + x/2;
205
 
        pb = ri->last_frame->data[2] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
206
 
    }
207
 
}
208
 
 
209
 
static void apply_motion_8x8(RoqContext *ri, int x, int y,
210
 
    unsigned char mv, signed char mean_x, signed char mean_y)
211
 
{
212
 
    int mx, my, i, j, hw;
213
 
    unsigned char *pa, *pb;
214
 
 
215
 
    mx = x + 8 - (mv >> 4) - mean_x;
216
 
    my = y + 8 - (mv & 0xf) - mean_y;
217
 
 
218
 
    /* check MV against frame boundaries */
219
 
    if ((mx < 0) || (mx > ri->avctx->width - 8) ||
220
 
        (my < 0) || (my > ri->avctx->height - 8)) {
221
 
        av_log(ri->avctx, AV_LOG_ERROR, "motion vector out of bounds: MV = (%d, %d), boundaries = (0, 0, %d, %d)\n",
222
 
            mx, my, ri->avctx->width, ri->avctx->height);
223
 
        return;
224
 
    }
225
 
 
226
 
    pa = ri->current_frame->data[0] + (y * ri->y_stride) + x;
227
 
    pb = ri->last_frame->data[0] + (my * ri->y_stride) + mx;
228
 
    for(i = 0; i < 8; i++) {
229
 
        pa[0] = pb[0];
230
 
        pa[1] = pb[1];
231
 
        pa[2] = pb[2];
232
 
        pa[3] = pb[3];
233
 
        pa[4] = pb[4];
234
 
        pa[5] = pb[5];
235
 
        pa[6] = pb[6];
236
 
        pa[7] = pb[7];
237
 
        pa += ri->y_stride;
238
 
        pb += ri->y_stride;
239
 
    }
240
 
 
241
 
    hw = ri->c_stride;
242
 
    pa = ri->current_frame->data[1] + (y * ri->y_stride)/4 + x/2;
243
 
    pb = ri->last_frame->data[1] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
244
 
    for(j = 0; j < 2; j++) {
245
 
        for(i = 0; i < 4; i++) {
246
 
            switch(((my & 0x01) << 1) | (mx & 0x01)) {
247
 
 
248
 
            case 0:
249
 
                pa[0] = pb[0];
250
 
                pa[1] = pb[1];
251
 
                pa[2] = pb[2];
252
 
                pa[3] = pb[3];
253
 
                break;
254
 
 
255
 
            case 1:
256
 
                pa[0] = avg2(pb[0], pb[1]);
257
 
                pa[1] = avg2(pb[1], pb[2]);
258
 
                pa[2] = avg2(pb[2], pb[3]);
259
 
                pa[3] = avg2(pb[3], pb[4]);
260
 
                break;
261
 
 
262
 
            case 2:
263
 
                pa[0] = avg2(pb[0], pb[hw]);
264
 
                pa[1] = avg2(pb[1], pb[hw+1]);
265
 
                pa[2] = avg2(pb[2], pb[hw+2]);
266
 
                pa[3] = avg2(pb[3], pb[hw+3]);
267
 
                break;
268
 
 
269
 
            case 3:
270
 
                pa[0] = avg4(pb[0], pb[1], pb[hw], pb[hw+1]);
271
 
                pa[1] = avg4(pb[1], pb[2], pb[hw+1], pb[hw+2]);
272
 
                pa[2] = avg4(pb[2], pb[3], pb[hw+2], pb[hw+3]);
273
 
                pa[3] = avg4(pb[3], pb[4], pb[hw+3], pb[hw+4]);
274
 
                break;
275
 
            }
276
 
            pa += ri->c_stride;
277
 
            pb += ri->c_stride;
278
 
        }
279
 
 
280
 
        pa = ri->current_frame->data[2] + (y * ri->y_stride)/4 + x/2;
281
 
        pb = ri->last_frame->data[2] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
282
 
    }
283
 
}
284
 
 
285
 
static void roqvideo_decode_frame(RoqContext *ri)
286
 
{
287
 
    unsigned int chunk_id = 0, chunk_arg = 0;
288
 
    unsigned long chunk_size = 0;
289
 
    int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1;
290
 
    int vqid, bpos, xpos, ypos, xp, yp, x, y;
291
 
    int frame_stats[2][4] = {{0},{0}};
292
 
    roq_qcell *qcell;
293
 
    unsigned char *buf = ri->buf;
294
 
    unsigned char *buf_end = ri->buf + ri->size;
295
 
 
296
 
    while (buf < buf_end) {
297
 
        chunk_id = get_word(buf);
298
 
        chunk_size = get_long(buf);
299
 
        chunk_arg = get_word(buf);
300
 
 
301
 
        if(chunk_id == RoQ_QUAD_VQ)
302
 
            break;
303
 
        if(chunk_id == RoQ_QUAD_CODEBOOK) {
304
 
            if((nv1 = chunk_arg >> 8) == 0)
305
 
                nv1 = 256;
306
 
            if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size)
307
 
                nv2 = 256;
308
 
            for(i = 0; i < nv1; i++) {
309
 
                ri->cells[i].y0 = get_byte(buf);
310
 
                ri->cells[i].y1 = get_byte(buf);
311
 
                ri->cells[i].y2 = get_byte(buf);
312
 
                ri->cells[i].y3 = get_byte(buf);
313
 
                ri->cells[i].u = get_byte(buf);
314
 
                ri->cells[i].v = get_byte(buf);
315
 
            }
316
 
            for(i = 0; i < nv2; i++)
317
 
                for(j = 0; j < 4; j++)
318
 
                    ri->qcells[i].idx[j] = get_byte(buf);
319
 
        }
320
 
    }
321
 
 
322
 
    bpos = xpos = ypos = 0;
323
 
    while(bpos < chunk_size) {
324
 
        for (yp = ypos; yp < ypos + 16; yp += 8)
325
 
            for (xp = xpos; xp < xpos + 16; xp += 8) {
326
 
                if (vqflg_pos < 0) {
327
 
                    vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8);
328
 
                    vqflg_pos = 7;
329
 
                }
330
 
                vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
331
 
                frame_stats[0][vqid]++;
332
 
                vqflg_pos--;
333
 
 
334
 
                switch(vqid) {
335
 
                case RoQ_ID_MOT:
336
 
                    apply_motion_8x8(ri, xp, yp, 0, 8, 8);
337
 
                    break;
338
 
                case RoQ_ID_FCC:
339
 
                    apply_motion_8x8(ri, xp, yp, buf[bpos++], chunk_arg >> 8,
340
 
                        chunk_arg & 0xff);
341
 
                    break;
342
 
                case RoQ_ID_SLD:
343
 
                    qcell = ri->qcells + buf[bpos++];
344
 
                    apply_vector_4x4(ri, xp, yp, ri->cells + qcell->idx[0]);
345
 
                    apply_vector_4x4(ri, xp+4, yp, ri->cells + qcell->idx[1]);
346
 
                    apply_vector_4x4(ri, xp, yp+4, ri->cells + qcell->idx[2]);
347
 
                    apply_vector_4x4(ri, xp+4, yp+4, ri->cells + qcell->idx[3]);
348
 
                    break;
349
 
                case RoQ_ID_CCC:
350
 
                    for (k = 0; k < 4; k++) {
351
 
                        x = xp; y = yp;
352
 
                        if(k & 0x01) x += 4;
353
 
                        if(k & 0x02) y += 4;
354
 
 
355
 
                        if (vqflg_pos < 0) {
356
 
                            vqflg = buf[bpos++];
357
 
                            vqflg |= (buf[bpos++] << 8);
358
 
                            vqflg_pos = 7;
359
 
                        }
360
 
                        vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
361
 
                        frame_stats[1][vqid]++;
362
 
                        vqflg_pos--;
363
 
                        switch(vqid) {
364
 
                        case RoQ_ID_MOT:
365
 
                            apply_motion_4x4(ri, x, y, 0, 8, 8);
366
 
                            break;
367
 
                        case RoQ_ID_FCC:
368
 
                            apply_motion_4x4(ri, x, y, buf[bpos++],
369
 
                                chunk_arg >> 8, chunk_arg & 0xff);
370
 
                            break;
371
 
                        case RoQ_ID_SLD:
372
 
                            qcell = ri->qcells + buf[bpos++];
373
 
                            apply_vector_2x2(ri, x, y, ri->cells + qcell->idx[0]);
374
 
                            apply_vector_2x2(ri, x+2, y, ri->cells + qcell->idx[1]);
375
 
                            apply_vector_2x2(ri, x, y+2, ri->cells + qcell->idx[2]);
376
 
                            apply_vector_2x2(ri, x+2, y+2, ri->cells + qcell->idx[3]);
377
 
                            break;
378
 
                        case RoQ_ID_CCC:
379
 
                            apply_vector_2x2(ri, x, y, ri->cells + buf[bpos]);
380
 
                            apply_vector_2x2(ri, x+2, y, ri->cells + buf[bpos+1]);
381
 
                            apply_vector_2x2(ri, x, y+2, ri->cells + buf[bpos+2]);
382
 
                            apply_vector_2x2(ri, x+2, y+2, ri->cells + buf[bpos+3]);
383
 
                            bpos += 4;
384
 
                            break;
385
 
                        }
386
 
                    }
387
 
                    break;
388
 
                default:
389
 
                    av_log(ri->avctx, AV_LOG_ERROR, "Unknown vq code: %d\n", vqid);
390
 
            }
391
 
        }
392
 
 
393
 
        xpos += 16;
394
 
        if (xpos >= ri->avctx->width) {
395
 
            xpos -= ri->avctx->width;
396
 
            ypos += 16;
397
 
        }
398
 
        if(ypos >= ri->avctx->height)
399
 
            break;
400
 
    }
401
 
}
402
 
 
403
 
 
404
 
static int roq_decode_init(AVCodecContext *avctx)
405
 
{
406
 
    RoqContext *s = avctx->priv_data;
407
 
    int i;
408
 
 
409
 
    s->avctx = avctx;
410
 
    s->first_frame = 1;
411
 
    s->last_frame    = &s->frames[0];
412
 
    s->current_frame = &s->frames[1];
413
 
    avctx->pix_fmt = PIX_FMT_YUV420P;
414
 
    avctx->has_b_frames = 0;
415
 
    dsputil_init(&s->dsp, avctx);
416
 
 
417
 
    uiclp = uiclip+512;
418
 
    for(i = -512; i < 512; i++)
419
 
        uiclp[i] = (i < 0 ? 0 : (i > 255 ? 255 : i));
420
 
 
421
 
    return 0;
422
 
}
423
 
 
424
 
static int roq_decode_frame(AVCodecContext *avctx,
425
 
                            void *data, int *data_size,
426
 
                            uint8_t *buf, int buf_size)
427
 
{
428
 
    RoqContext *s = avctx->priv_data;
429
 
 
430
 
    if (avctx->get_buffer(avctx, s->current_frame)) {
431
 
        av_log(avctx, AV_LOG_ERROR, "  RoQ: get_buffer() failed\n");
432
 
        return -1;
433
 
    }
434
 
    s->y_stride = s->current_frame->linesize[0];
435
 
    s->c_stride = s->current_frame->linesize[1];
436
 
 
437
 
    s->buf = buf;
438
 
    s->size = buf_size;
439
 
    roqvideo_decode_frame(s);
440
 
 
441
 
    /* release the last frame if it is allocated */
442
 
    if (s->first_frame)
443
 
        s->first_frame = 0;
444
 
    else
445
 
        avctx->release_buffer(avctx, s->last_frame);
446
 
 
447
 
    *data_size = sizeof(AVFrame);
448
 
    *(AVFrame*)data = *s->current_frame;
449
 
 
450
 
    /* shuffle frames */
451
 
    FFSWAP(AVFrame *, s->current_frame, s->last_frame);
452
 
 
453
 
    return buf_size;
454
 
}
455
 
 
456
 
static int roq_decode_end(AVCodecContext *avctx)
457
 
{
458
 
    RoqContext *s = avctx->priv_data;
459
 
 
460
 
    /* release the last frame */
461
 
    if (s->last_frame->data[0])
462
 
        avctx->release_buffer(avctx, s->last_frame);
463
 
 
464
 
    return 0;
465
 
}
466
 
 
467
 
AVCodec roq_decoder = {
468
 
    "roqvideo",
469
 
    CODEC_TYPE_VIDEO,
470
 
    CODEC_ID_ROQ,
471
 
    sizeof(RoqContext),
472
 
    roq_decode_init,
473
 
    NULL,
474
 
    roq_decode_end,
475
 
    roq_decode_frame,
476
 
    CODEC_CAP_DR1,
477
 
};
 
28
#include "roqvideo.h"
 
29
 
 
30
static 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
 
 
41
void 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
 
 
71
void 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
 
 
102
static 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
 
 
128
void 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
 
 
134
void 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
}