~ubuntu-branches/ubuntu/quantal/gst-plugins-bad-multiverse0.10/quantal

« back to all changes in this revision

Viewing changes to gst/mve/mvevideodec16.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2007-05-03 19:52:54 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20070503195254-4dovmz251nut3yrt
Tags: 0.10.4+cvs20070502-1
* New CVS snapshot.
* debian/rules,
  debian/build-deps.in:
  + Update build dependencies.
* debian/gstreamer-plugins-bad-multiverse.install:
  + Add x264 plugin.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Interplay MVE Video Decoder (16 bit)
 
3
 * Copyright (C) 2003 the ffmpeg project, Mike Melanson
 
4
 *           (C) 2006 Jens Granseuer
 
5
 *
 
6
 * This library is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU Lesser General Public
 
8
 * License as published by the Free Software Foundation; either
 
9
 * version 2 of the License, or (at your option) any later version.
 
10
 *
 
11
 * This library is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * Lesser General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Lesser General Public
 
17
 * License along with this library; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
19
 *
 
20
 * For more information about the Interplay MVE format, visit:
 
21
 *   http://www.pcisys.net/~melanson/codecs/interplay-mve.txt
 
22
 */
 
23
 
 
24
#include "gstmvedemux.h"
 
25
#include <string.h>
 
26
 
 
27
#define PIXEL(s) GST_READ_UINT16_LE (s)
 
28
 
 
29
#define CHECK_STREAM(l, n) \
 
30
  do { \
 
31
    if (G_UNLIKELY (*(l) < (n))) { \
 
32
      GST_ERROR ("wanted to read %d bytes from stream, %d available", (n), *(l)); \
 
33
      return -1; \
 
34
    } \
 
35
    *(l) -= (n); \
 
36
  } while (0)
 
37
 
 
38
/* copy an 8x8 block from the stream to the frame buffer */
 
39
static int
 
40
ipvideo_copy_block (const GstMveDemuxStream * s, unsigned short *frame,
 
41
    const unsigned short *src, int offset)
 
42
{
 
43
  int i;
 
44
  int frame_offset;
 
45
 
 
46
  frame_offset = frame - (unsigned short *) s->back_buf1 + offset;
 
47
 
 
48
  if (G_UNLIKELY (frame_offset < 0)) {
 
49
    GST_ERROR ("frame offset < 0 (%d)", frame_offset);
 
50
    return -1;
 
51
  } else if (G_UNLIKELY (frame_offset > s->max_block_offset)) {
 
52
    GST_ERROR ("frame offset above limit (%d > %u)",
 
53
        frame_offset, s->max_block_offset);
 
54
    return -1;
 
55
  }
 
56
 
 
57
  for (i = 0; i < 8; ++i) {
 
58
    memcpy (frame, src, 16);
 
59
    frame += s->width;
 
60
    src += s->width;
 
61
  }
 
62
 
 
63
  return 0;
 
64
}
 
65
 
 
66
static int
 
67
ipvideo_decode_0x2 (const GstMveDemuxStream * s, unsigned short *frame,
 
68
    const unsigned char **data, unsigned short *len)
 
69
{
 
70
  unsigned char B;
 
71
  int x, y;
 
72
  int offset;
 
73
 
 
74
  /* copy block from 2 frames ago using a motion vector */
 
75
  CHECK_STREAM (len, 1);
 
76
  B = *(*data)++;
 
77
 
 
78
  if (B < 56) {
 
79
    x = 8 + (B % 7);
 
80
    y = B / 7;
 
81
  } else {
 
82
    x = -14 + ((B - 56) % 29);
 
83
    y = 8 + ((B - 56) / 29);
 
84
  }
 
85
  offset = y * s->width + x;
 
86
 
 
87
  return ipvideo_copy_block (s, frame, frame + offset, offset);
 
88
}
 
89
 
 
90
static int
 
91
ipvideo_decode_0x3 (const GstMveDemuxStream * s, unsigned short *frame,
 
92
    const unsigned char **data, unsigned short *len)
 
93
{
 
94
  unsigned char B;
 
95
  int x, y;
 
96
  int offset;
 
97
 
 
98
  /* copy 8x8 block from current frame from an up/left block */
 
99
  CHECK_STREAM (len, 1);
 
100
  B = *(*data)++;
 
101
 
 
102
  if (B < 56) {
 
103
    x = -(8 + (B % 7));
 
104
    y = -(B / 7);
 
105
  } else {
 
106
    x = -(-14 + ((B - 56) % 29));
 
107
    y = -(8 + ((B - 56) / 29));
 
108
  }
 
109
  offset = y * s->width + x;
 
110
 
 
111
  return ipvideo_copy_block (s, frame, frame + offset, offset);
 
112
}
 
113
 
 
114
static int
 
115
ipvideo_decode_0x4 (const GstMveDemuxStream * s, unsigned short *frame,
 
116
    const unsigned char **data, unsigned short *len)
 
117
{
 
118
  int x, y;
 
119
  unsigned char B;
 
120
  int offset;
 
121
 
 
122
  /* copy a block from the previous frame */
 
123
  CHECK_STREAM (len, 1);
 
124
  B = *(*data)++;
 
125
  x = -8 + (B & 0x0F);
 
126
  y = -8 + (B >> 4);
 
127
  offset = y * s->width + x;
 
128
 
 
129
  return ipvideo_copy_block (s, frame, frame +
 
130
      ((unsigned short *) s->back_buf2 - (unsigned short *) s->back_buf1) +
 
131
      offset, offset);
 
132
}
 
133
 
 
134
static int
 
135
ipvideo_decode_0x5 (const GstMveDemuxStream * s, unsigned short *frame,
 
136
    const unsigned char **data, unsigned short *len)
 
137
{
 
138
  signed char x, y;
 
139
  int offset;
 
140
 
 
141
  /* copy a block from the previous frame using an expanded range */
 
142
  CHECK_STREAM (len, 2);
 
143
  x = (signed char) *(*data)++;
 
144
  y = (signed char) *(*data)++;
 
145
  offset = y * s->width + x;
 
146
 
 
147
  return ipvideo_copy_block (s, frame, frame +
 
148
      ((unsigned short *) s->back_buf2 - (unsigned short *) s->back_buf1) +
 
149
      offset, offset);
 
150
}
 
151
 
 
152
static int
 
153
ipvideo_decode_0x7 (const GstMveDemuxStream * s, unsigned short *frame,
 
154
    const unsigned char **data, unsigned short *len)
 
155
{
 
156
  int x, y;
 
157
  unsigned short P0, P1;
 
158
  unsigned int flags;
 
159
  int bitmask;
 
160
 
 
161
  /* 2-color encoding */
 
162
  CHECK_STREAM (len, 4 + 2);
 
163
  P0 = PIXEL (*data);
 
164
  (*data) += 2;
 
165
  P1 = PIXEL (*data);
 
166
  (*data) += 2;
 
167
 
 
168
  if (!(P0 & 0x8000)) {
 
169
 
 
170
    /* need 8 more bytes from the stream */
 
171
    CHECK_STREAM (len, 8 - 2);
 
172
 
 
173
    for (y = 0; y < 8; ++y) {
 
174
      flags = *(*data)++;
 
175
      for (x = 0x01; x <= 0x80; x <<= 1) {
 
176
        if (flags & x)
 
177
          *frame++ = P1;
 
178
        else
 
179
          *frame++ = P0;
 
180
      }
 
181
      frame += s->width - 8;
 
182
    }
 
183
 
 
184
  } else {
 
185
    P0 &= ~0x8000;
 
186
 
 
187
    /* need 2 more bytes from the stream */
 
188
 
 
189
    flags = ((*data)[1] << 8) | (*data)[0];
 
190
    (*data) += 2;
 
191
    bitmask = 0x0001;
 
192
    for (y = 0; y < 8; y += 2) {
 
193
      for (x = 0; x < 8; x += 2, bitmask <<= 1) {
 
194
        if (flags & bitmask) {
 
195
          *(frame + x) = P1;
 
196
          *(frame + x + 1) = P1;
 
197
          *(frame + s->width + x) = P1;
 
198
          *(frame + s->width + x + 1) = P1;
 
199
        } else {
 
200
          *(frame + x) = P0;
 
201
          *(frame + x + 1) = P0;
 
202
          *(frame + s->width + x) = P0;
 
203
          *(frame + s->width + x + 1) = P0;
 
204
        }
 
205
      }
 
206
      frame += s->width * 2;
 
207
    }
 
208
  }
 
209
 
 
210
  return 0;
 
211
}
 
212
 
 
213
static int
 
214
ipvideo_decode_0x8 (const GstMveDemuxStream * s, unsigned short *frame,
 
215
    const unsigned char **data, unsigned short *len)
 
216
{
 
217
  int x, y;
 
218
  unsigned short P[8];
 
219
  unsigned char B[8];
 
220
  unsigned int flags = 0;
 
221
  unsigned int bitmask = 0;
 
222
  unsigned short P0 = 0, P1 = 0;
 
223
  int lower_half = 0;
 
224
 
 
225
  /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on
 
226
   * either top and bottom or left and right halves */
 
227
  CHECK_STREAM (len, 6 + 10);
 
228
 
 
229
  P[0] = PIXEL (*data);
 
230
  (*data) += 2;
 
231
  P[1] = PIXEL (*data);
 
232
  (*data) += 2;
 
233
  B[0] = *(*data)++;
 
234
  B[1] = *(*data)++;
 
235
 
 
236
  if (!(P[0] & 0x8000)) {
 
237
 
 
238
    /* need 18 more bytes */
 
239
    CHECK_STREAM (len, 18 - 10);
 
240
 
 
241
    P[2] = PIXEL (*data);
 
242
    (*data) += 2;
 
243
    P[3] = PIXEL (*data);
 
244
    (*data) += 2;
 
245
    B[2] = *(*data)++;
 
246
    B[3] = *(*data)++;
 
247
    P[4] = PIXEL (*data);
 
248
    (*data) += 2;
 
249
    P[5] = PIXEL (*data);
 
250
    (*data) += 2;
 
251
    B[4] = *(*data)++;
 
252
    B[5] = *(*data)++;
 
253
    P[6] = PIXEL (*data);
 
254
    (*data) += 2;
 
255
    P[7] = PIXEL (*data);
 
256
    (*data) += 2;
 
257
    B[6] = *(*data)++;
 
258
    B[7] = *(*data)++;
 
259
 
 
260
    flags =
 
261
        ((B[0] & 0xF0) << 4) | ((B[4] & 0xF0) << 8) |
 
262
        ((B[0] & 0x0F)) | ((B[4] & 0x0F) << 4) |
 
263
        ((B[1] & 0xF0) << 20) | ((B[5] & 0xF0) << 24) |
 
264
        ((B[1] & 0x0F) << 16) | ((B[5] & 0x0F) << 20);
 
265
    bitmask = 0x00000001;
 
266
    lower_half = 0;             /* still on top half */
 
267
 
 
268
    for (y = 0; y < 8; ++y) {
 
269
 
 
270
      /* time to reload flags? */
 
271
      if (y == 4) {
 
272
        flags =
 
273
            ((B[2] & 0xF0) << 4) | ((B[6] & 0xF0) << 8) |
 
274
            ((B[2] & 0x0F)) | ((B[6] & 0x0F) << 4) |
 
275
            ((B[3] & 0xF0) << 20) | ((B[7] & 0xF0) << 24) |
 
276
            ((B[3] & 0x0F) << 16) | ((B[7] & 0x0F) << 20);
 
277
        bitmask = 0x00000001;
 
278
        lower_half = 2;
 
279
      }
 
280
 
 
281
      /* get the pixel values ready for this quadrant */
 
282
      P0 = P[lower_half + 0];
 
283
      P1 = P[lower_half + 1];
 
284
 
 
285
      for (x = 0; x < 8; ++x, bitmask <<= 1) {
 
286
        if (x == 4) {
 
287
          P0 = P[lower_half + 4];
 
288
          P1 = P[lower_half + 5];
 
289
        }
 
290
 
 
291
        if (flags & bitmask)
 
292
          *frame++ = P1;
 
293
        else
 
294
          *frame++ = P0;
 
295
      }
 
296
      frame += s->width - 8;
 
297
    }
 
298
 
 
299
  } else {
 
300
    P[0] &= ~0x8000;
 
301
 
 
302
    /* need 10 more bytes */
 
303
    B[2] = *(*data)++;
 
304
    B[3] = *(*data)++;
 
305
    P[2] = PIXEL (*data);
 
306
    (*data) += 2;
 
307
    P[3] = PIXEL (*data);
 
308
    (*data) += 2;
 
309
    B[4] = *(*data)++;
 
310
    B[5] = *(*data)++;
 
311
    B[6] = *(*data)++;
 
312
    B[7] = *(*data)++;
 
313
 
 
314
    if (!(P[2] & 0x8000)) {
 
315
      /* vertical split; left & right halves are 2-color encoded */
 
316
 
 
317
      flags =
 
318
          ((B[0] & 0xF0) << 4) | ((B[4] & 0xF0) << 8) |
 
319
          ((B[0] & 0x0F)) | ((B[4] & 0x0F) << 4) |
 
320
          ((B[1] & 0xF0) << 20) | ((B[5] & 0xF0) << 24) |
 
321
          ((B[1] & 0x0F) << 16) | ((B[5] & 0x0F) << 20);
 
322
      bitmask = 0x00000001;
 
323
 
 
324
      for (y = 0; y < 8; ++y) {
 
325
 
 
326
        /* time to reload flags? */
 
327
        if (y == 4) {
 
328
          flags =
 
329
              ((B[2] & 0xF0) << 4) | ((B[6] & 0xF0) << 8) |
 
330
              ((B[2] & 0x0F)) | ((B[6] & 0x0F) << 4) |
 
331
              ((B[3] & 0xF0) << 20) | ((B[7] & 0xF0) << 24) |
 
332
              ((B[3] & 0x0F) << 16) | ((B[7] & 0x0F) << 20);
 
333
          bitmask = 0x00000001;
 
334
        }
 
335
 
 
336
        /* get the pixel values ready for this half */
 
337
        P0 = P[0];
 
338
        P1 = P[1];
 
339
 
 
340
        for (x = 0; x < 8; ++x, bitmask <<= 1) {
 
341
          if (x == 4) {
 
342
            P0 = P[2];
 
343
            P1 = P[3];
 
344
          }
 
345
 
 
346
          if (flags & bitmask)
 
347
            *frame++ = P1;
 
348
          else
 
349
            *frame++ = P0;
 
350
        }
 
351
        frame += s->width - 8;
 
352
      }
 
353
 
 
354
    } else {
 
355
      /* horizontal split; top & bottom halves are 2-color encoded */
 
356
 
 
357
      P0 = P[0];
 
358
      P1 = P[1];
 
359
 
 
360
      for (y = 0; y < 8; ++y) {
 
361
 
 
362
        flags = B[y];
 
363
        if (y == 4) {
 
364
          P0 = P[2] & ~0x8000;
 
365
          P1 = P[3];
 
366
        }
 
367
 
 
368
        for (bitmask = 0x01; bitmask <= 0x80; bitmask <<= 1) {
 
369
 
 
370
          if (flags & bitmask)
 
371
            *frame++ = P1;
 
372
          else
 
373
            *frame++ = P0;
 
374
        }
 
375
        frame += s->width - 8;
 
376
      }
 
377
    }
 
378
  }
 
379
 
 
380
  return 0;
 
381
}
 
382
 
 
383
static int
 
384
ipvideo_decode_0x9 (const GstMveDemuxStream * s, unsigned short *frame,
 
385
    const unsigned char **data, unsigned short *len)
 
386
{
 
387
  int x, y;
 
388
  unsigned short P[4];
 
389
  unsigned char B[4];
 
390
  unsigned int flags = 0;
 
391
  int shifter = 0;
 
392
  unsigned short pix;
 
393
 
 
394
  /* 4-color encoding */
 
395
  CHECK_STREAM (len, 8 + 4);
 
396
 
 
397
  P[0] = PIXEL (*data);
 
398
  (*data) += 2;
 
399
  P[1] = PIXEL (*data);
 
400
  (*data) += 2;
 
401
  P[2] = PIXEL (*data);
 
402
  (*data) += 2;
 
403
  P[3] = PIXEL (*data);
 
404
  (*data) += 2;
 
405
 
 
406
  if (!(P[0] & 0x8000) && !(P[2] & 0x8000)) {
 
407
 
 
408
    /* 1 of 4 colors for each pixel, need 16 more bytes */
 
409
    CHECK_STREAM (len, 16 - 4);
 
410
 
 
411
    for (y = 0; y < 8; ++y) {
 
412
      /* get the next set of 8 2-bit flags */
 
413
      flags = ((*data)[1] << 8) | (*data)[0];
 
414
      (*data) += 2;
 
415
      for (x = 0, shifter = 0; x < 8; ++x, shifter += 2) {
 
416
        *frame++ = P[(flags >> shifter) & 0x03];
 
417
      }
 
418
      frame += s->width - 8;
 
419
    }
 
420
 
 
421
  } else if (!(P[0] & 0x8000) && (P[2] & 0x8000)) {
 
422
    P[2] &= ~0x8000;
 
423
 
 
424
    /* 1 of 4 colors for each 2x2 block, need 4 more bytes */
 
425
 
 
426
    B[0] = *(*data)++;
 
427
    B[1] = *(*data)++;
 
428
    B[2] = *(*data)++;
 
429
    B[3] = *(*data)++;
 
430
    flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
 
431
    shifter = 0;
 
432
 
 
433
    for (y = 0; y < 8; y += 2) {
 
434
      for (x = 0; x < 8; x += 2, shifter += 2) {
 
435
        pix = P[(flags >> shifter) & 0x03];
 
436
        *(frame + x) = pix;
 
437
        *(frame + x + 1) = pix;
 
438
        *(frame + s->width + x) = pix;
 
439
        *(frame + s->width + x + 1) = pix;
 
440
      }
 
441
      frame += s->width * 2;
 
442
    }
 
443
 
 
444
  } else if ((P[0] & 0x8000) && !(P[2] & 0x8000)) {
 
445
    P[0] &= ~0x8000;
 
446
 
 
447
    /* 1 of 4 colors for each 2x1 block, need 8 more bytes */
 
448
 
 
449
    CHECK_STREAM (len, 8 - 4);
 
450
    for (y = 0; y < 8; ++y) {
 
451
      /* time to reload flags? */
 
452
      if ((y == 0) || (y == 4)) {
 
453
        B[0] = *(*data)++;
 
454
        B[1] = *(*data)++;
 
455
        B[2] = *(*data)++;
 
456
        B[3] = *(*data)++;
 
457
        flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
 
458
        shifter = 0;
 
459
      }
 
460
      for (x = 0; x < 8; x += 2, shifter += 2) {
 
461
        pix = P[(flags >> shifter) & 0x03];
 
462
        *(frame + x) = pix;
 
463
        *(frame + x + 1) = pix;
 
464
      }
 
465
      frame += s->width;
 
466
    }
 
467
 
 
468
  } else {
 
469
    P[0] &= ~0x8000;
 
470
    P[2] &= ~0x8000;
 
471
 
 
472
    /* 1 of 4 colors for each 1x2 block, need 8 more bytes */
 
473
    CHECK_STREAM (len, 8 - 4);
 
474
 
 
475
    for (y = 0; y < 8; y += 2) {
 
476
      /* time to reload flags? */
 
477
      if ((y == 0) || (y == 4)) {
 
478
        B[0] = *(*data)++;
 
479
        B[1] = *(*data)++;
 
480
        B[2] = *(*data)++;
 
481
        B[3] = *(*data)++;
 
482
        flags = (B[3] << 24) | (B[2] << 16) | (B[1] << 8) | B[0];
 
483
        shifter = 0;
 
484
      }
 
485
      for (x = 0; x < 8; ++x, shifter += 2) {
 
486
        pix = P[(flags >> shifter) & 0x03];
 
487
        *(frame + x) = pix;
 
488
        *(frame + s->width + x) = pix;
 
489
      }
 
490
      frame += s->width * 2;
 
491
    }
 
492
  }
 
493
 
 
494
  return 0;
 
495
}
 
496
 
 
497
static int
 
498
ipvideo_decode_0xa (const GstMveDemuxStream * s, unsigned short *frame,
 
499
    const unsigned char **data, unsigned short *len)
 
500
{
 
501
  int x, y;
 
502
  unsigned short P[16];
 
503
  unsigned char B[16];
 
504
  int flags = 0;
 
505
  int shifter = 0;
 
506
  int index;
 
507
  int split;
 
508
  int lower_half;
 
509
 
 
510
  /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on
 
511
   * either top and bottom or left and right halves */
 
512
  CHECK_STREAM (len, 8 + 24);
 
513
 
 
514
  P[0] = PIXEL (*data);
 
515
  (*data) += 2;
 
516
  P[1] = PIXEL (*data);
 
517
  (*data) += 2;
 
518
  P[2] = PIXEL (*data);
 
519
  (*data) += 2;
 
520
  P[3] = PIXEL (*data);
 
521
  (*data) += 2;
 
522
 
 
523
  if (!(P[0] & 0x8000)) {
 
524
 
 
525
    /* 4-color encoding for each quadrant; need 40 more bytes */
 
526
    CHECK_STREAM (len, 40 - 24);
 
527
 
 
528
    B[0] = *(*data)++;
 
529
    B[1] = *(*data)++;
 
530
    B[2] = *(*data)++;
 
531
    B[3] = *(*data)++;
 
532
    for (y = 4; y < 16; y += 4) {
 
533
      for (x = y; x < y + 4; ++x) {
 
534
        P[x] = PIXEL (*data);
 
535
        (*data) += 2;
 
536
      }
 
537
      for (x = y; x < y + 4; ++x)
 
538
        B[x] = *(*data)++;
 
539
    }
 
540
 
 
541
    for (y = 0; y < 8; ++y) {
 
542
 
 
543
      lower_half = (y >= 4) ? 4 : 0;
 
544
      flags = (B[y + 8] << 8) | B[y];
 
545
 
 
546
      for (x = 0, shifter = 0; x < 8; ++x, shifter += 2) {
 
547
        split = (x >= 4) ? 8 : 0;
 
548
        index = split + lower_half + ((flags >> shifter) & 0x03);
 
549
        *frame++ = P[index];
 
550
      }
 
551
 
 
552
      frame += s->width - 8;
 
553
    }
 
554
 
 
555
  } else {
 
556
    P[0] &= ~0x8000;
 
557
 
 
558
    /* 4-color encoding for either left and right or top and bottom
 
559
     * halves; need 24 more bytes */
 
560
 
 
561
    memcpy (&B[0], *data, 8);
 
562
    (*data) += 8;
 
563
    P[4] = PIXEL (*data);
 
564
    (*data) += 2;
 
565
    P[5] = PIXEL (*data);
 
566
    (*data) += 2;
 
567
    P[6] = PIXEL (*data);
 
568
    (*data) += 2;
 
569
    P[7] = PIXEL (*data);
 
570
    (*data) += 2;
 
571
    memcpy (&B[8], *data, 8);
 
572
    (*data) += 8;
 
573
 
 
574
    if (!(P[4] & 0x8000)) {
 
575
 
 
576
      /* block is divided into left and right halves */
 
577
      for (y = 0; y < 8; ++y) {
 
578
 
 
579
        flags = (B[y + 8] << 8) | B[y];
 
580
        split = 0;
 
581
 
 
582
        for (x = 0, shifter = 0; x < 8; ++x, shifter += 2) {
 
583
          if (x == 4)
 
584
            split = 4;
 
585
          *frame++ = P[split + ((flags >> shifter) & 0x03)];
 
586
        }
 
587
 
 
588
        frame += s->width - 8;
 
589
      }
 
590
 
 
591
    } else {
 
592
      P[4] &= ~0x8000;
 
593
 
 
594
      /* block is divided into top and bottom halves */
 
595
      split = 0;
 
596
      for (y = 0; y < 8; ++y) {
 
597
 
 
598
        flags = (B[y * 2 + 1] << 8) | B[y * 2];
 
599
        if (y == 4)
 
600
          split = 4;
 
601
 
 
602
        for (x = 0, shifter = 0; x < 8; ++x, shifter += 2)
 
603
          *frame++ = P[split + ((flags >> shifter) & 0x03)];
 
604
 
 
605
        frame += s->width - 8;
 
606
      }
 
607
    }
 
608
  }
 
609
 
 
610
  return 0;
 
611
}
 
612
 
 
613
static int
 
614
ipvideo_decode_0xb (const GstMveDemuxStream * s, unsigned short *frame,
 
615
    const unsigned char **data, unsigned short *len)
 
616
{
 
617
  int x, y;
 
618
 
 
619
  /* 64-color encoding (each pixel in block is a different color) */
 
620
  CHECK_STREAM (len, 128);
 
621
 
 
622
  for (y = 0; y < 8; ++y) {
 
623
    for (x = 0; x < 8; ++x) {
 
624
      *frame++ = PIXEL (*data);
 
625
      (*data) += 2;
 
626
    }
 
627
    frame += s->width - 8;
 
628
  }
 
629
 
 
630
  return 0;
 
631
}
 
632
 
 
633
static int
 
634
ipvideo_decode_0xc (const GstMveDemuxStream * s, unsigned short *frame,
 
635
    const unsigned char **data, unsigned short *len)
 
636
{
 
637
  int x, y;
 
638
  unsigned short pix;
 
639
 
 
640
  /* 16-color block encoding: each 2x2 block is a different color */
 
641
  CHECK_STREAM (len, 32);
 
642
 
 
643
  for (y = 0; y < 8; y += 2) {
 
644
    for (x = 0; x < 8; x += 2) {
 
645
      pix = PIXEL (*data);
 
646
      (*data) += 2;
 
647
      *(frame + x) = pix;
 
648
      *(frame + x + 1) = pix;
 
649
      *(frame + s->width + x) = pix;
 
650
      *(frame + s->width + x + 1) = pix;
 
651
    }
 
652
    frame += s->width * 2;
 
653
  }
 
654
 
 
655
  return 0;
 
656
}
 
657
 
 
658
static int
 
659
ipvideo_decode_0xd (const GstMveDemuxStream * s, unsigned short *frame,
 
660
    const unsigned char **data, unsigned short *len)
 
661
{
 
662
  int x, y;
 
663
  unsigned short P[4];
 
664
  unsigned char index = 0;
 
665
 
 
666
  /* 4-color block encoding: each 4x4 block is a different color */
 
667
  CHECK_STREAM (len, 8);
 
668
 
 
669
  P[0] = PIXEL (*data);
 
670
  (*data) += 2;
 
671
  P[1] = PIXEL (*data);
 
672
  (*data) += 2;
 
673
  P[2] = PIXEL (*data);
 
674
  (*data) += 2;
 
675
  P[3] = PIXEL (*data);
 
676
  (*data) += 2;
 
677
 
 
678
  for (y = 0; y < 8; ++y) {
 
679
    if (y < 4)
 
680
      index = 0;
 
681
    else
 
682
      index = 2;
 
683
 
 
684
    for (x = 0; x < 8; ++x) {
 
685
      if (x == 4)
 
686
        ++index;
 
687
      *frame++ = P[index];
 
688
    }
 
689
    frame += s->width - 8;
 
690
  }
 
691
 
 
692
  return 0;
 
693
}
 
694
 
 
695
static int
 
696
ipvideo_decode_0xe (const GstMveDemuxStream * s, unsigned short *frame,
 
697
    const unsigned char **data, unsigned short *len)
 
698
{
 
699
  int x, y;
 
700
  unsigned short pix;
 
701
 
 
702
  /* 1-color encoding: the whole block is 1 solid color */
 
703
  CHECK_STREAM (len, 2);
 
704
 
 
705
  pix = PIXEL (*data);
 
706
  (*data) += 2;
 
707
 
 
708
  for (y = 0; y < 8; ++y) {
 
709
    for (x = 0; x < 8; ++x) {
 
710
      *frame++ = pix;
 
711
    }
 
712
    frame += s->width - 8;
 
713
  }
 
714
 
 
715
  return 0;
 
716
}
 
717
 
 
718
static int
 
719
ipvideo_decode_0xf (const GstMveDemuxStream * s, unsigned short *frame,
 
720
    const unsigned char **data, unsigned short *len)
 
721
{
 
722
  int x, y;
 
723
  unsigned short P[2];
 
724
 
 
725
  /* dithered encoding */
 
726
  CHECK_STREAM (len, 4);
 
727
 
 
728
  P[0] = PIXEL (*data);
 
729
  (*data) += 2;
 
730
  P[1] = PIXEL (*data);
 
731
  (*data) += 2;
 
732
 
 
733
  for (y = 0; y < 8; ++y) {
 
734
    for (x = 0; x < 4; ++x) {
 
735
      *frame++ = P[y & 1];
 
736
      *frame++ = P[(y & 1) ^ 1];
 
737
    }
 
738
    frame += s->width - 8;
 
739
  }
 
740
 
 
741
  return 0;
 
742
}
 
743
 
 
744
int
 
745
ipvideo_decode_frame16 (const GstMveDemuxStream * s, const unsigned char *data,
 
746
    unsigned short len)
 
747
{
 
748
  int rc = 0;
 
749
  int x, y, xx, yy;
 
750
  int index = 0;
 
751
  unsigned short offset;
 
752
  unsigned char opcode;
 
753
  unsigned short *frame;
 
754
  const unsigned char *data2;
 
755
  unsigned short len2;
 
756
 
 
757
  CHECK_STREAM (&len, 2);
 
758
 
 
759
  offset = (data[1] << 8) | data[0];
 
760
  data2 = data + offset;
 
761
  len2 = len - offset + 2;
 
762
  data += 2;
 
763
 
 
764
  frame = (unsigned short *) s->back_buf1;
 
765
 
 
766
  /* decoding is done in 8x8 blocks */
 
767
  xx = s->width >> 3;
 
768
  yy = s->height >> 3;
 
769
 
 
770
  for (y = 0; y < yy; ++y) {
 
771
    for (x = 0; x < xx; ++x) {
 
772
      /* decoding map contains 4 bits of information per 8x8 block */
 
773
      /* bottom nibble first, then top nibble */
 
774
      if (index & 1)
 
775
        opcode = s->code_map[index >> 1] >> 4;
 
776
      else
 
777
        opcode = s->code_map[index >> 1] & 0x0F;
 
778
      ++index;
 
779
 
 
780
      /* GST_DEBUG ("block @ (%3d, %3d): encoding 0x%X, data ptr @ %p",
 
781
         x, y, opcode, data); */
 
782
 
 
783
      switch (opcode) {
 
784
        case 0x0:
 
785
          /* copy a block from the previous frame */
 
786
          rc = ipvideo_copy_block (s, frame, frame +
 
787
              ((unsigned short *) s->back_buf2 -
 
788
                  (unsigned short *) s->back_buf1), 0);
 
789
          break;
 
790
        case 0x1:
 
791
          /* copy block from 2 frames ago; since we switched the back
 
792
           * buffers we don't actually have to do anything here */
 
793
          break;
 
794
        case 0x2:
 
795
          rc = ipvideo_decode_0x2 (s, frame, &data2, &len2);
 
796
          break;
 
797
        case 0x3:
 
798
          rc = ipvideo_decode_0x3 (s, frame, &data2, &len2);
 
799
          break;
 
800
        case 0x4:
 
801
          rc = ipvideo_decode_0x4 (s, frame, &data2, &len2);
 
802
          break;
 
803
        case 0x5:
 
804
          rc = ipvideo_decode_0x5 (s, frame, &data, &len);
 
805
          break;
 
806
        case 0x6:
 
807
          /* mystery opcode? skip multiple blocks? */
 
808
          GST_WARNING ("encountered unsupported opcode 0x6");
 
809
          rc = -1;
 
810
          break;
 
811
        case 0x7:
 
812
          rc = ipvideo_decode_0x7 (s, frame, &data, &len);
 
813
          break;
 
814
        case 0x8:
 
815
          rc = ipvideo_decode_0x8 (s, frame, &data, &len);
 
816
          break;
 
817
        case 0x9:
 
818
          rc = ipvideo_decode_0x9 (s, frame, &data, &len);
 
819
          break;
 
820
        case 0xa:
 
821
          rc = ipvideo_decode_0xa (s, frame, &data, &len);
 
822
          break;
 
823
        case 0xb:
 
824
          rc = ipvideo_decode_0xb (s, frame, &data, &len);
 
825
          break;
 
826
        case 0xc:
 
827
          rc = ipvideo_decode_0xc (s, frame, &data, &len);
 
828
          break;
 
829
        case 0xd:
 
830
          rc = ipvideo_decode_0xd (s, frame, &data, &len);
 
831
          break;
 
832
        case 0xe:
 
833
          rc = ipvideo_decode_0xe (s, frame, &data, &len);
 
834
          break;
 
835
        case 0xf:
 
836
          rc = ipvideo_decode_0xf (s, frame, &data, &len);
 
837
          break;
 
838
      }
 
839
 
 
840
      if (rc != 0)
 
841
        return rc;
 
842
 
 
843
      frame += 8;
 
844
    }
 
845
    frame += 7 * s->width;
 
846
  }
 
847
 
 
848
  return 0;
 
849
}