Browse code

initial commit for Quicktime Animation (RLE) video decoder; bit depths 32, 24, and 16 are working; 8bpp is partially working; 4, 2, and 1 bpp are not supported yet

Originally committed as revision 2748 to svn://svn.ffmpeg.org/ffmpeg/trunk

Mike Melanson authored on 2004/02/05 14:22:44
Showing 7 changed files
... ...
@@ -2,6 +2,7 @@ version <next>:
2 2
 - DV encoder, DV muxer
3 3
 - Microsoft RLE video decoder
4 4
 - Microsoft Video-1 decoder
5
+- Apple Animation (RLE) decoder
5 6
 - Apple Graphics (SMC) decoder
6 7
 - Apple Video (RPZA) decoder
7 8
 - Cinepak decoder
... ...
@@ -715,6 +715,7 @@ following image formats are supported:
715 715
 @item Id RoQ                 @tab     @tab  X @tab used in Quake III, Jedi Knight 2, other computer games
716 716
 @item Xan/WC3                @tab     @tab  X @tab used in Wing Commander III .MVE files
717 717
 @item Interplay Video        @tab     @tab  X @tab used in Interplay .MVE files
718
+@item Apple Animation        @tab     @tab  X @tab fourcc: 'rle '
718 719
 @item Apple Graphics         @tab     @tab  X @tab fourcc: 'smc '
719 720
 @item Apple Video            @tab     @tab  X @tab fourcc: rpza
720 721
 @item Cinepak                @tab     @tab  X
... ...
@@ -19,7 +19,7 @@ OBJS= common.o utils.o mem.o allcodecs.o \
19 19
       vp3.o asv1.o 4xm.o cabac.o ffv1.o ra144.o ra288.o vcr1.o cljr.o \
20 20
       roqvideo.o dpcm.o interplayvideo.o xan.o rpza.o cinepak.o msrle.o \
21 21
       msvideo1.o vqavideo.o idcinvideo.o adx.o rational.o faandct.o 8bps.o \
22
-      smc.o parser.o flicvideo.o truemotion1.o vmdav.o lcl.o
22
+      smc.o parser.o flicvideo.o truemotion1.o vmdav.o lcl.o qtrle.o
23 23
 
24 24
 ifeq ($(AMR_NB),yes)
25 25
 ifeq ($(AMR_NB_FIXED),yes)
... ...
@@ -153,6 +153,7 @@ void avcodec_register_all(void)
153 153
     register_avcodec(&roq_dpcm_decoder);
154 154
     register_avcodec(&interplay_dpcm_decoder);
155 155
     register_avcodec(&xan_dpcm_decoder);
156
+    register_avcodec(&qtrle_decoder);
156 157
 #endif /* CONFIG_DECODERS */
157 158
 
158 159
 #ifdef AMR_NB
... ...
@@ -93,6 +93,7 @@ enum CodecID {
93 93
     CODEC_ID_VMDAUDIO,
94 94
     CODEC_ID_MSZH,
95 95
     CODEC_ID_ZLIB,
96
+    CODEC_ID_QTRLE,
96 97
 
97 98
     /* various pcm "codecs" */
98 99
     CODEC_ID_PCM_S16LE,
... ...
@@ -1700,6 +1701,7 @@ extern AVCodec ra_288_decoder;
1700 1700
 extern AVCodec roq_dpcm_decoder;
1701 1701
 extern AVCodec interplay_dpcm_decoder;
1702 1702
 extern AVCodec xan_dpcm_decoder;
1703
+extern AVCodec qtrle_decoder;
1703 1704
 
1704 1705
 /* pcm codecs */
1705 1706
 #define PCM_CODEC(id, name) \
1706 1707
new file mode 100644
... ...
@@ -0,0 +1,537 @@
0
+/*
1
+ * Quicktime Animation (RLE) Video Decoder
2
+ * Copyright (C) 2004 the ffmpeg project
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2 of the License, or (at your option) any later version.
8
+ *
9
+ * This library is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with this library; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
+ *
18
+ */
19
+
20
+/**
21
+ * @file qtrle.c
22
+ * QT RLE Video Decoder by Mike Melanson (melanson@pcisys.net)
23
+ * For more information about the QT RLE format, visit:
24
+ *   http://www.pcisys.net/~melanson/codecs/
25
+ *
26
+ * The QT RLE decoder has seven modes of operation:
27
+ * 1, 2, 4, 8, 16, 24, and 32 bits per pixel. For modes 1, 2, 4, and 8
28
+ * the decoder outputs PAL8 colorspace data. 16-bit data yields RGB24
29
+ * data. 24-bit data is RGB888 and 32-bit data is RGBA32.
30
+ */
31
+
32
+#include <stdio.h>
33
+#include <stdlib.h>
34
+#include <string.h>
35
+#include <unistd.h>
36
+
37
+#include "common.h"
38
+#include "avcodec.h"
39
+#include "dsputil.h"
40
+
41
+typedef struct QtrleContext {
42
+
43
+    AVCodecContext *avctx;
44
+    DSPContext dsp;
45
+    AVFrame frame;
46
+
47
+    unsigned char *buf;
48
+    int size;
49
+
50
+} QtrleContext;
51
+
52
+#define BE_16(x)  ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
53
+
54
+#define CHECK_STREAM_PTR(n) \
55
+  if ((stream_ptr + n) > s->size) { \
56
+    printf ("QT RLE problem: stream_ptr out of bounds (%d >= %d)\n", \
57
+      stream_ptr + n, s->size); \
58
+    return; \
59
+  }
60
+
61
+#define CHECK_PIXEL_PTR(n) \
62
+  if (pixel_ptr + n > pixel_limit) { \
63
+    printf ("QT RLE problem: pixel_ptr >= pixel_limit (%d >= %d)\n", \
64
+      pixel_ptr + n, pixel_limit); \
65
+    return; \
66
+  } \
67
+
68
+static void qtrle_decode_1bpp(QtrleContext *s)
69
+{
70
+}
71
+
72
+static void qtrle_decode_2bpp(QtrleContext *s)
73
+{
74
+}
75
+
76
+static void qtrle_decode_4bpp(QtrleContext *s)
77
+{
78
+}
79
+
80
+static void qtrle_decode_8bpp(QtrleContext *s)
81
+{
82
+    int stream_ptr;
83
+    int header;
84
+    int start_line;
85
+    int lines_to_change;
86
+    signed char rle_code;
87
+    int row_ptr, pixel_ptr;
88
+    int row_inc = s->frame.linesize[0];
89
+    unsigned char pi1, pi2, pi3, pi4;  /* 4 palette indices */
90
+    unsigned char *rgb = s->frame.data[0];
91
+    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
92
+
93
+    /* check if this frame is even supposed to change */
94
+    if (s->size < 8)
95
+        return;
96
+
97
+    /* start after the chunk size */
98
+    stream_ptr = 4;
99
+
100
+    /* fetch the header */
101
+    CHECK_STREAM_PTR(2);
102
+    header = BE_16(&s->buf[stream_ptr]);
103
+    stream_ptr += 2;
104
+
105
+    /* if a header is present, fetch additional decoding parameters */
106
+    if (header & 0x0008) {
107
+        CHECK_STREAM_PTR(8);
108
+        start_line = BE_16(&s->buf[stream_ptr]);
109
+        stream_ptr += 4;
110
+        lines_to_change = BE_16(&s->buf[stream_ptr]);
111
+        stream_ptr += 4;
112
+    } else {
113
+        start_line = 0;
114
+        lines_to_change = s->avctx->height;
115
+    }
116
+
117
+    row_ptr = row_inc * start_line;
118
+    while (lines_to_change--) {
119
+        CHECK_STREAM_PTR(2);
120
+        pixel_ptr = row_ptr + (4 * (s->buf[stream_ptr++] - 1));
121
+
122
+        while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
123
+            if (rle_code == 0) {
124
+                /* there's another skip code in the stream */
125
+                CHECK_STREAM_PTR(1);
126
+                pixel_ptr += (4 * (s->buf[stream_ptr++] - 1));
127
+            } else if (rle_code < 0) {
128
+                /* decode the run length code */
129
+                rle_code = -rle_code;
130
+                /* get the next 4 bytes from the stream, treat them as palette
131
+                 * indices, and output them rle_code times */
132
+                CHECK_STREAM_PTR(4);
133
+                pi1 = s->buf[stream_ptr++];
134
+                pi2 = s->buf[stream_ptr++];
135
+                pi3 = s->buf[stream_ptr++];
136
+                pi4 = s->buf[stream_ptr++];
137
+
138
+                CHECK_PIXEL_PTR(rle_code * 4);
139
+
140
+                while (rle_code--) {
141
+                    rgb[pixel_ptr++] = pi1;
142
+                    rgb[pixel_ptr++] = pi2;
143
+                    rgb[pixel_ptr++] = pi3;
144
+                    rgb[pixel_ptr++] = pi4;
145
+                }
146
+            } else {
147
+                /* copy the same pixel directly to output 4 times */
148
+                rle_code *= 4;
149
+                CHECK_STREAM_PTR(rle_code);
150
+                CHECK_PIXEL_PTR(rle_code);
151
+
152
+                while (rle_code--) {
153
+                    rgb[pixel_ptr++] = s->buf[stream_ptr++];
154
+                }
155
+            }
156
+        }
157
+        row_ptr += row_inc;
158
+    }
159
+}
160
+
161
+static void qtrle_decode_16bpp(QtrleContext *s)
162
+{
163
+    int stream_ptr;
164
+    int header;
165
+    int start_line;
166
+    int lines_to_change;
167
+    signed char rle_code;
168
+    int row_ptr, pixel_ptr;
169
+    int row_inc = s->frame.linesize[0];
170
+    unsigned short rgb16;
171
+    unsigned char *rgb = s->frame.data[0];
172
+    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
173
+
174
+    /* check if this frame is even supposed to change */
175
+    if (s->size < 8)
176
+        return;
177
+
178
+    /* start after the chunk size */
179
+    stream_ptr = 4;
180
+
181
+    /* fetch the header */
182
+    CHECK_STREAM_PTR(2);
183
+    header = BE_16(&s->buf[stream_ptr]);
184
+    stream_ptr += 2;
185
+
186
+    /* if a header is present, fetch additional decoding parameters */
187
+    if (header & 0x0008) {
188
+        CHECK_STREAM_PTR(8);
189
+        start_line = BE_16(&s->buf[stream_ptr]);
190
+        stream_ptr += 4;
191
+        lines_to_change = BE_16(&s->buf[stream_ptr]);
192
+        stream_ptr += 4;
193
+    } else {
194
+        start_line = 0;
195
+        lines_to_change = s->avctx->height;
196
+    }
197
+
198
+    row_ptr = row_inc * start_line;
199
+    while (lines_to_change--) {
200
+        CHECK_STREAM_PTR(2);
201
+        pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 2;
202
+
203
+        while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
204
+            if (rle_code == 0) {
205
+                /* there's another skip code in the stream */
206
+                CHECK_STREAM_PTR(1);
207
+                pixel_ptr += (s->buf[stream_ptr++] - 1) * 2;
208
+            } else if (rle_code < 0) {
209
+                /* decode the run length code */
210
+                rle_code = -rle_code;
211
+                CHECK_STREAM_PTR(2);
212
+                rgb16 = BE_16(&s->buf[stream_ptr]);
213
+                stream_ptr += 2;
214
+
215
+                CHECK_PIXEL_PTR(rle_code * 2);
216
+
217
+                while (rle_code--) {
218
+                    *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
219
+                    pixel_ptr += 2;
220
+                }
221
+            } else {
222
+                CHECK_STREAM_PTR(rle_code * 2);
223
+                CHECK_PIXEL_PTR(rle_code * 2);
224
+
225
+                /* copy pixels directly to output */
226
+                while (rle_code--) {
227
+                    rgb16 = BE_16(&s->buf[stream_ptr]);
228
+                    stream_ptr += 2;
229
+                    *(unsigned short *)(&rgb[pixel_ptr]) = rgb16;
230
+                    pixel_ptr += 2;
231
+                }
232
+            }
233
+        }
234
+        row_ptr += row_inc;
235
+    }
236
+}
237
+
238
+static void qtrle_decode_24bpp(QtrleContext *s)
239
+{
240
+    int stream_ptr;
241
+    int header;
242
+    int start_line;
243
+    int lines_to_change;
244
+    signed char rle_code;
245
+    int row_ptr, pixel_ptr;
246
+    int row_inc = s->frame.linesize[0];
247
+    unsigned char r, g, b;
248
+    unsigned char *rgb = s->frame.data[0];
249
+    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
250
+
251
+    /* check if this frame is even supposed to change */
252
+    if (s->size < 8)
253
+        return;
254
+
255
+    /* start after the chunk size */
256
+    stream_ptr = 4;
257
+
258
+    /* fetch the header */
259
+    CHECK_STREAM_PTR(2);
260
+    header = BE_16(&s->buf[stream_ptr]);
261
+    stream_ptr += 2;
262
+
263
+    /* if a header is present, fetch additional decoding parameters */
264
+    if (header & 0x0008) {
265
+        CHECK_STREAM_PTR(8);
266
+        start_line = BE_16(&s->buf[stream_ptr]);
267
+        stream_ptr += 4;
268
+        lines_to_change = BE_16(&s->buf[stream_ptr]);
269
+        stream_ptr += 4;
270
+    } else {
271
+        start_line = 0;
272
+        lines_to_change = s->avctx->height;
273
+    }
274
+
275
+    row_ptr = row_inc * start_line;
276
+    while (lines_to_change--) {
277
+        CHECK_STREAM_PTR(2);
278
+        pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 3;
279
+
280
+        while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
281
+            if (rle_code == 0) {
282
+                /* there's another skip code in the stream */
283
+                CHECK_STREAM_PTR(1);
284
+                pixel_ptr += (s->buf[stream_ptr++] - 1) * 3;
285
+            } else if (rle_code < 0) {
286
+                /* decode the run length code */
287
+                rle_code = -rle_code;
288
+                CHECK_STREAM_PTR(3);
289
+                r = s->buf[stream_ptr++];
290
+                g = s->buf[stream_ptr++];
291
+                b = s->buf[stream_ptr++];
292
+
293
+                CHECK_PIXEL_PTR(rle_code * 3);
294
+
295
+                while (rle_code--) {
296
+                    rgb[pixel_ptr++] = r;
297
+                    rgb[pixel_ptr++] = g;
298
+                    rgb[pixel_ptr++] = b;
299
+                }
300
+            } else {
301
+                CHECK_STREAM_PTR(rle_code * 3);
302
+                CHECK_PIXEL_PTR(rle_code * 3);
303
+
304
+                /* copy pixels directly to output */
305
+                while (rle_code--) {
306
+                    rgb[pixel_ptr++] = s->buf[stream_ptr++];
307
+                    rgb[pixel_ptr++] = s->buf[stream_ptr++];
308
+                    rgb[pixel_ptr++] = s->buf[stream_ptr++];
309
+                }
310
+            }
311
+        }
312
+        row_ptr += row_inc;
313
+    }
314
+}
315
+
316
+static void qtrle_decode_32bpp(QtrleContext *s)
317
+{
318
+    int stream_ptr;
319
+    int header;
320
+    int start_line;
321
+    int lines_to_change;
322
+    signed char rle_code;
323
+    int row_ptr, pixel_ptr;
324
+    int row_inc = s->frame.linesize[0];
325
+    unsigned char r, g, b;
326
+    unsigned int argb;
327
+    unsigned char *rgb = s->frame.data[0];
328
+    int pixel_limit = s->frame.linesize[0] * s->avctx->height;
329
+
330
+    /* check if this frame is even supposed to change */
331
+    if (s->size < 8)
332
+        return;
333
+
334
+    /* start after the chunk size */
335
+    stream_ptr = 4;
336
+
337
+    /* fetch the header */
338
+    CHECK_STREAM_PTR(2);
339
+    header = BE_16(&s->buf[stream_ptr]);
340
+    stream_ptr += 2;
341
+
342
+    /* if a header is present, fetch additional decoding parameters */
343
+    if (header & 0x0008) {
344
+        CHECK_STREAM_PTR(8);
345
+        start_line = BE_16(&s->buf[stream_ptr]);
346
+        stream_ptr += 4;
347
+        lines_to_change = BE_16(&s->buf[stream_ptr]);
348
+        stream_ptr += 4;
349
+    } else {
350
+        start_line = 0;
351
+        lines_to_change = s->avctx->height;
352
+    }
353
+
354
+    row_ptr = row_inc * start_line;
355
+    while (lines_to_change--) {
356
+        CHECK_STREAM_PTR(2);
357
+        pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 4;
358
+
359
+        while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
360
+            if (rle_code == 0) {
361
+                /* there's another skip code in the stream */
362
+                CHECK_STREAM_PTR(1);
363
+                pixel_ptr += (s->buf[stream_ptr++] - 1) * 4;
364
+            } else if (rle_code < 0) {
365
+                /* decode the run length code */
366
+                rle_code = -rle_code;
367
+                CHECK_STREAM_PTR(4);
368
+                stream_ptr++;  /* skip the alpha (?) byte */
369
+                r = s->buf[stream_ptr++];
370
+                g = s->buf[stream_ptr++];
371
+                b = s->buf[stream_ptr++];
372
+                argb = (r << 16) | (g << 8) | (b << 0);
373
+
374
+                CHECK_PIXEL_PTR(rle_code * 4);
375
+
376
+                while (rle_code--) {
377
+                    *(unsigned int *)(&rgb[pixel_ptr]) = argb;
378
+                    pixel_ptr += 4;
379
+                }
380
+            } else {
381
+                CHECK_STREAM_PTR(rle_code * 4);
382
+                CHECK_PIXEL_PTR(rle_code * 4);
383
+
384
+                /* copy pixels directly to output */
385
+                while (rle_code--) {
386
+                    stream_ptr++;  /* skip the alpha (?) byte */
387
+                    r = s->buf[stream_ptr++];
388
+                    g = s->buf[stream_ptr++];
389
+                    b = s->buf[stream_ptr++];
390
+                    argb = (r << 16) | (g << 8) | (b << 0);
391
+                    *(unsigned int *)(&rgb[pixel_ptr]) = argb;
392
+                    pixel_ptr += 4;
393
+                }
394
+            }
395
+        }
396
+        row_ptr += row_inc;
397
+    }
398
+}
399
+
400
+static int qtrle_decode_init(AVCodecContext *avctx)
401
+{
402
+    QtrleContext *s = (QtrleContext *)avctx->priv_data;
403
+
404
+    s->avctx = avctx;
405
+    switch (avctx->bits_per_sample) {
406
+    case 1:
407
+    case 2:
408
+    case 4:
409
+    case 8:
410
+    case 33:
411
+    case 34:
412
+    case 36:
413
+    case 40:
414
+        avctx->pix_fmt = PIX_FMT_PAL8;
415
+        break;
416
+
417
+    case 16:
418
+        avctx->pix_fmt = PIX_FMT_RGB555;
419
+        break;
420
+
421
+    case 24:
422
+        avctx->pix_fmt = PIX_FMT_RGB24;
423
+        break;
424
+
425
+    case 32:
426
+        avctx->pix_fmt = PIX_FMT_RGBA32;
427
+        break;
428
+
429
+    default:
430
+        printf ("QT RLE: Unsupported colorspace: %d bits/sample?\n",
431
+            avctx->bits_per_sample);
432
+        break;
433
+    }
434
+    avctx->has_b_frames = 0;
435
+    dsputil_init(&s->dsp, avctx);
436
+
437
+    s->frame.data[0] = NULL;
438
+
439
+    return 0;
440
+}
441
+
442
+static int qtrle_decode_frame(AVCodecContext *avctx,
443
+                              void *data, int *data_size,
444
+                              uint8_t *buf, int buf_size)
445
+{
446
+    QtrleContext *s = (QtrleContext *)avctx->priv_data;
447
+
448
+    /* no supplementary picture */
449
+    if (buf_size == 0)
450
+        return 0;
451
+
452
+    s->buf = buf;
453
+    s->size = buf_size;
454
+
455
+    s->frame.reference = 1;
456
+    s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
457
+                            FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
458
+    if (avctx->reget_buffer(avctx, &s->frame)) {
459
+        printf ("reget_buffer() failed\n");
460
+        return -1;
461
+    }
462
+
463
+    switch (avctx->bits_per_sample) {
464
+    case 1:
465
+    case 33:
466
+        qtrle_decode_1bpp(s);
467
+        break;
468
+
469
+    case 2:
470
+    case 34:
471
+        qtrle_decode_2bpp(s);
472
+        break;
473
+
474
+    case 4:
475
+    case 36:
476
+        qtrle_decode_4bpp(s);
477
+        break;
478
+
479
+    case 8:
480
+    case 40:
481
+        qtrle_decode_8bpp(s);
482
+        /* make the palette available on the way out */
483
+        memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
484
+        if (s->avctx->palctrl->palette_changed) {
485
+            s->frame.palette_has_changed = 1;
486
+            s->avctx->palctrl->palette_changed = 0;
487
+        }
488
+        break;
489
+
490
+    case 16:
491
+        qtrle_decode_16bpp(s);
492
+        break;
493
+
494
+    case 24:
495
+        qtrle_decode_24bpp(s);
496
+        break;
497
+
498
+    case 32:
499
+        qtrle_decode_32bpp(s);
500
+        break;
501
+
502
+    default:
503
+        printf ("QT RLE: Unsupported colorspace: %d bits/sample?\n",
504
+            avctx->bits_per_sample);
505
+        break;
506
+    }
507
+
508
+    *data_size = sizeof(AVFrame);
509
+    *(AVFrame*)data = s->frame;
510
+
511
+    /* always report that the buffer was completely consumed */
512
+    return buf_size;
513
+}
514
+
515
+static int qtrle_decode_end(AVCodecContext *avctx)
516
+{
517
+    QtrleContext *s = (QtrleContext *)avctx->priv_data;
518
+
519
+    if (s->frame.data[0])
520
+        avctx->release_buffer(avctx, &s->frame);
521
+
522
+    return 0;
523
+}
524
+
525
+AVCodec qtrle_decoder = {
526
+    "qtrle",
527
+    CODEC_TYPE_VIDEO,
528
+    CODEC_ID_QTRLE,
529
+    sizeof(QtrleContext),
530
+    qtrle_decode_init,
531
+    NULL,
532
+    qtrle_decode_end,
533
+    qtrle_decode_frame,
534
+    CODEC_CAP_DR1,
535
+};
536
+
... ...
@@ -105,6 +105,7 @@ static const CodecTag mov_video_tags[] = {
105 105
     { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') }, /* Cinepak */
106 106
     { CODEC_ID_8BPS, MKTAG('8', 'B', 'P', 'S') }, /* Planar RGB (8BPS) */
107 107
     { CODEC_ID_SMC, MKTAG('s', 'm', 'c', ' ') }, /* Apple Graphics (SMC) */
108
+    { CODEC_ID_QTRLE, MKTAG('r', 'l', 'e', ' ') }, /* Apple Animation (RLE) */
108 109
     { CODEC_ID_NONE, 0 },
109 110
 };
110 111