Tizen 2.0 Release
[framework/multimedia/gst-plugins-bad0.10.git] / gst / mve / mvevideodec16.c
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 }