Browse code

Escape 130 (RPL) decoder

Some fixes provided by Paul B Mahol <onemda@gmail.com>
and Michael Niedermayer <michaelni@gmx.at> and me.

Signed-off-by: Diego Biurrun <diego@biurrun.de>
Signed-off-by: Kostya Shishkov <kostya.shishkov@gmail.com>

Eli Friedman authored on 2011/12/17 05:30:27
Showing 9 changed files
... ...
@@ -19,6 +19,7 @@ version 10:
19 19
 - Matroska muxer can now put the index at the beginning of the file.
20 20
 - avconv -deinterlace option removed, the yadif filter should be used instead
21 21
 - Apple Intermediate Codec decoder
22
+- Escape 130 video decoder
22 23
 
23 24
 
24 25
 version 9:
... ...
@@ -497,6 +497,7 @@ following image formats are supported:
497 497
 @item Electronic Arts TGQ video  @tab     @tab  X
498 498
 @item Electronic Arts TQI video  @tab     @tab  X
499 499
 @item Escape 124             @tab     @tab  X
500
+@item Escape 130             @tab     @tab  X
500 501
 @item FFmpeg video codec #1  @tab  X  @tab  X
501 502
     @tab experimental lossless codec (fourcc: FFV1)
502 503
 @item Flash Screen Video v1  @tab  X  @tab  X
... ...
@@ -163,6 +163,7 @@ OBJS-$(CONFIG_EIGHTBPS_DECODER)        += 8bps.o
163 163
 OBJS-$(CONFIG_EIGHTSVX_EXP_DECODER)    += 8svx.o
164 164
 OBJS-$(CONFIG_EIGHTSVX_FIB_DECODER)    += 8svx.o
165 165
 OBJS-$(CONFIG_ESCAPE124_DECODER)       += escape124.o
166
+OBJS-$(CONFIG_ESCAPE130_DECODER)       += escape130.o
166 167
 OBJS-$(CONFIG_FFV1_DECODER)            += ffv1dec.o ffv1.o
167 168
 OBJS-$(CONFIG_FFV1_ENCODER)            += ffv1enc.o ffv1.o
168 169
 OBJS-$(CONFIG_FFVHUFF_DECODER)         += huffyuv.o huffyuvdec.o
... ...
@@ -136,6 +136,7 @@ void avcodec_register_all(void)
136 136
     REGISTER_DECODER(EIGHTSVX_EXP,      eightsvx_exp);
137 137
     REGISTER_DECODER(EIGHTSVX_FIB,      eightsvx_fib);
138 138
     REGISTER_DECODER(ESCAPE124,         escape124);
139
+    REGISTER_DECODER(ESCAPE130,         escape130);
139 140
     REGISTER_ENCDEC (FFV1,              ffv1);
140 141
     REGISTER_ENCDEC (FFVHUFF,           ffvhuff);
141 142
     REGISTER_ENCDEC (FLASHSV,           flashsv);
... ...
@@ -269,6 +269,7 @@ enum AVCodecID {
269 269
     AV_CODEC_ID_MSS2,
270 270
     AV_CODEC_ID_VP9,
271 271
     AV_CODEC_ID_AIC,
272
+    AV_CODEC_ID_ESCAPE130,
272 273
 
273 274
     /* various PCM "codecs" */
274 275
     AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
... ...
@@ -1214,6 +1214,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
1214 1214
         .long_name = NULL_IF_CONFIG_SMALL("Apple Intermediate Codec"),
1215 1215
         .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
1216 1216
     },
1217
+    {
1218
+        .id        = AV_CODEC_ID_ESCAPE130,
1219
+        .type      = AVMEDIA_TYPE_VIDEO,
1220
+        .name      = "escape130",
1221
+        .long_name = NULL_IF_CONFIG_SMALL("Escape 130"),
1222
+        .props     = AV_CODEC_PROP_LOSSY,
1223
+    },
1217 1224
 
1218 1225
     /* various PCM "codecs" */
1219 1226
     {
1220 1227
new file mode 100644
... ...
@@ -0,0 +1,356 @@
0
+/*
1
+ * Escape 130 video decoder
2
+ * Copyright (C) 2008 Eli Friedman (eli.friedman <at> gmail.com)
3
+ *
4
+ * This file is part of Libav.
5
+ *
6
+ * Libav 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.1 of the License, or (at your option) any later version.
10
+ *
11
+ * Libav 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 Libav; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+#include "libavutil/attributes.h"
22
+#include "libavutil/mem.h"
23
+#include "avcodec.h"
24
+#define BITSTREAM_READER_LE
25
+#include "get_bits.h"
26
+#include "internal.h"
27
+
28
+typedef struct Escape130Context {
29
+    uint8_t *old_y_avg;
30
+
31
+    uint8_t *new_y, *old_y;
32
+    uint8_t *new_u, *old_u;
33
+    uint8_t *new_v, *old_v;
34
+
35
+    uint8_t *buf1, *buf2;
36
+    int     linesize[3];
37
+} Escape130Context;
38
+
39
+static const uint8_t offset_table[] = { 2, 4, 10, 20 };
40
+static const int8_t sign_table[64][4] = {
41
+    {  0,  0,  0,  0 },
42
+    { -1,  1,  0,  0 },
43
+    {  1, -1,  0,  0 },
44
+    { -1,  0,  1,  0 },
45
+    { -1,  1,  1,  0 },
46
+    {  0, -1,  1,  0 },
47
+    {  1, -1,  1,  0 },
48
+    { -1, -1,  1,  0 },
49
+    {  1,  0, -1,  0 },
50
+    {  0,  1, -1,  0 },
51
+    {  1,  1, -1,  0 },
52
+    { -1,  1, -1,  0 },
53
+    {  1, -1, -1,  0 },
54
+    { -1,  0,  0,  1 },
55
+    { -1,  1,  0,  1 },
56
+    {  0, -1,  0,  1 },
57
+
58
+    {  0,  0,  0,  0 },
59
+    {  1, -1,  0,  1 },
60
+    { -1, -1,  0,  1 },
61
+    { -1,  0,  1,  1 },
62
+    { -1,  1,  1,  1 },
63
+    {  0, -1,  1,  1 },
64
+    {  1, -1,  1,  1 },
65
+    { -1, -1,  1,  1 },
66
+    {  0,  0, -1,  1 },
67
+    {  1,  0, -1,  1 },
68
+    { -1,  0, -1,  1 },
69
+    {  0,  1, -1,  1 },
70
+    {  1,  1, -1,  1 },
71
+    { -1,  1, -1,  1 },
72
+    {  0, -1, -1,  1 },
73
+    {  1, -1, -1,  1 },
74
+
75
+    {  0,  0,  0,  0 },
76
+    { -1, -1, -1,  1 },
77
+    {  1,  0,  0, -1 },
78
+    {  0,  1,  0, -1 },
79
+    {  1,  1,  0, -1 },
80
+    { -1,  1,  0, -1 },
81
+    {  1, -1,  0, -1 },
82
+    {  0,  0,  1, -1 },
83
+    {  1,  0,  1, -1 },
84
+    { -1,  0,  1, -1 },
85
+    {  0,  1,  1, -1 },
86
+    {  1,  1,  1, -1 },
87
+    { -1,  1,  1, -1 },
88
+    {  0, -1,  1, -1 },
89
+    {  1, -1,  1, -1 },
90
+    { -1, -1,  1, -1 },
91
+
92
+    {  0,  0,  0,  0 },
93
+    {  1,  0, -1, -1 },
94
+    {  0,  1, -1, -1 },
95
+    {  1,  1, -1, -1 },
96
+    { -1,  1, -1, -1 },
97
+    {  1, -1, -1, -1 }
98
+};
99
+
100
+static const int8_t luma_adjust[] = { -4, -3, -2, -1, 1, 2, 3, 4 };
101
+
102
+static const int8_t chroma_adjust[2][8] = {
103
+    { 1, 1, 0, -1, -1, -1,  0,  1 },
104
+    { 0, 1, 1,  1,  0, -1, -1, -1 }
105
+};
106
+
107
+const uint8_t chroma_vals[] = {
108
+     20,  28,  36,  44,  52,  60,  68,  76,
109
+     84,  92, 100, 106, 112, 116, 120, 124,
110
+    128, 132, 136, 140, 144, 150, 156, 164,
111
+    172, 180, 188, 196, 204, 212, 220, 228
112
+};
113
+
114
+static av_cold int escape130_decode_init(AVCodecContext *avctx)
115
+{
116
+    Escape130Context *s = avctx->priv_data;
117
+    avctx->pix_fmt = PIX_FMT_YUV420P;
118
+
119
+    if ((avctx->width & 1) || (avctx->height & 1)) {
120
+        av_log(avctx, AV_LOG_ERROR,
121
+               "Dimensions should be a multiple of two.\n");
122
+        return AVERROR_INVALIDDATA;
123
+    }
124
+
125
+    s->old_y_avg = av_malloc(avctx->width * avctx->height / 4);
126
+    s->buf1      = av_malloc(avctx->width * avctx->height * 3 / 2);
127
+    s->buf2      = av_malloc(avctx->width * avctx->height * 3 / 2);
128
+    if (!s->old_y_avg || !s->buf1 || !s->buf2) {
129
+        av_freep(&s->old_y_avg);
130
+        av_freep(&s->buf1);
131
+        av_freep(&s->buf2);
132
+        av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
133
+        return AVERROR(ENOMEM);
134
+    }
135
+
136
+    s->linesize[0] = avctx->width;
137
+    s->linesize[1] =
138
+    s->linesize[2] = avctx->width / 2;
139
+
140
+    s->new_y = s->buf1;
141
+    s->new_u = s->new_y + avctx->width * avctx->height;
142
+    s->new_v = s->new_u + avctx->width * avctx->height / 4;
143
+    s->old_y = s->buf2;
144
+    s->old_u = s->old_y + avctx->width * avctx->height;
145
+    s->old_v = s->old_u + avctx->width * avctx->height / 4;
146
+    memset(s->old_y, 0,    avctx->width * avctx->height);
147
+    memset(s->old_u, 0x10, avctx->width * avctx->height / 4);
148
+    memset(s->old_v, 0x10, avctx->width * avctx->height / 4);
149
+
150
+    return 0;
151
+}
152
+
153
+static av_cold int escape130_decode_close(AVCodecContext *avctx)
154
+{
155
+    Escape130Context *s = avctx->priv_data;
156
+
157
+    av_freep(&s->old_y_avg);
158
+    av_freep(&s->buf1);
159
+    av_freep(&s->buf2);
160
+
161
+    return 0;
162
+}
163
+
164
+static int decode_skip_count(GetBitContext* gb)
165
+{
166
+    int value;
167
+
168
+    value = get_bits1(gb);
169
+    if (value)
170
+        return 0;
171
+
172
+    value = get_bits(gb, 3);
173
+    if (value)
174
+        return value;
175
+
176
+    value = get_bits(gb, 8);
177
+    if (value)
178
+        return value + 7;
179
+
180
+    value = get_bits(gb, 15);
181
+    if (value)
182
+        return value + 262;
183
+
184
+    return -1;
185
+}
186
+
187
+static int escape130_decode_frame(AVCodecContext *avctx, void *data,
188
+                                  int *got_frame, AVPacket *avpkt)
189
+{
190
+    const uint8_t *buf  = avpkt->data;
191
+    int buf_size        = avpkt->size;
192
+    Escape130Context *s = avctx->priv_data;
193
+    AVFrame *pic        = data;
194
+    GetBitContext gb;
195
+    int ret;
196
+
197
+    uint8_t *old_y, *old_cb, *old_cr,
198
+            *new_y, *new_cb, *new_cr;
199
+    uint8_t *dstY, *dstU, *dstV;
200
+    unsigned old_y_stride, old_cb_stride, old_cr_stride,
201
+             new_y_stride, new_cb_stride, new_cr_stride;
202
+    unsigned total_blocks = avctx->width * avctx->height / 4,
203
+             block_index, block_x = 0;
204
+    unsigned y[4] = { 0 }, cb = 0x10, cr = 0x10;
205
+    int skip = -1, y_avg = 0, i, j;
206
+    uint8_t *ya = s->old_y_avg;
207
+
208
+    // first 16 bytes are header; no useful information in here
209
+    if (buf_size <= 16) {
210
+        av_log(avctx, AV_LOG_ERROR, "Insufficient frame data\n");
211
+        return AVERROR_INVALIDDATA;
212
+    }
213
+
214
+    if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
215
+        return ret;
216
+
217
+    init_get_bits(&gb, buf + 16, (buf_size - 16) * 8);
218
+
219
+    new_y  = s->new_y;
220
+    new_cb = s->new_u;
221
+    new_cr = s->new_v;
222
+    new_y_stride  = s->linesize[0];
223
+    new_cb_stride = s->linesize[1];
224
+    new_cr_stride = s->linesize[2];
225
+    old_y  = s->old_y;
226
+    old_cb = s->old_u;
227
+    old_cr = s->old_v;
228
+    old_y_stride  = s->linesize[0];
229
+    old_cb_stride = s->linesize[1];
230
+    old_cr_stride = s->linesize[2];
231
+
232
+    for (block_index = 0; block_index < total_blocks; block_index++) {
233
+        // Note that this call will make us skip the rest of the blocks
234
+        // if the frame ends prematurely.
235
+        if (skip == -1)
236
+            skip = decode_skip_count(&gb);
237
+        if (skip == -1) {
238
+            av_log(avctx, AV_LOG_ERROR, "Error decoding skip value\n");
239
+            return AVERROR_INVALIDDATA;
240
+        }
241
+
242
+        if (skip) {
243
+            y[0] = old_y[0];
244
+            y[1] = old_y[1];
245
+            y[2] = old_y[old_y_stride];
246
+            y[3] = old_y[old_y_stride + 1];
247
+            y_avg = ya[0];
248
+            cb = old_cb[0];
249
+            cr = old_cr[0];
250
+        } else {
251
+            if (get_bits1(&gb)) {
252
+                unsigned sign_selector       = get_bits(&gb, 6);
253
+                unsigned difference_selector = get_bits(&gb, 2);
254
+                y_avg = 2 * get_bits(&gb, 5);
255
+                for (i = 0; i < 4; i++) {
256
+                    y[i] = av_clip(y_avg + offset_table[difference_selector] *
257
+                                   sign_table[sign_selector][i], 0, 63);
258
+                }
259
+            } else if (get_bits1(&gb)) {
260
+                if (get_bits1(&gb)) {
261
+                    y_avg = get_bits(&gb, 6);
262
+                } else {
263
+                    unsigned adjust_index = get_bits(&gb, 3);
264
+                    y_avg = (y_avg + luma_adjust[adjust_index]) & 63;
265
+                }
266
+                for (i = 0; i < 4; i++)
267
+                    y[i] = y_avg;
268
+            }
269
+
270
+            if (get_bits1(&gb)) {
271
+                if (get_bits1(&gb)) {
272
+                    cb = get_bits(&gb, 5);
273
+                    cr = get_bits(&gb, 5);
274
+                } else {
275
+                    unsigned adjust_index = get_bits(&gb, 3);
276
+                    cb = (cb + chroma_adjust[0][adjust_index]) & 31;
277
+                    cr = (cr + chroma_adjust[1][adjust_index]) & 31;
278
+                }
279
+            }
280
+        }
281
+        *ya++ = y_avg;
282
+
283
+        new_y[0]                = y[0];
284
+        new_y[1]                = y[1];
285
+        new_y[new_y_stride]     = y[2];
286
+        new_y[new_y_stride + 1] = y[3];
287
+        *new_cb = cb;
288
+        *new_cr = cr;
289
+
290
+        old_y += 2;
291
+        old_cb++;
292
+        old_cr++;
293
+        new_y += 2;
294
+        new_cb++;
295
+        new_cr++;
296
+        block_x++;
297
+        if (block_x * 2 == avctx->width) {
298
+            block_x = 0;
299
+            old_y  += old_y_stride * 2  - avctx->width;
300
+            old_cb += old_cb_stride     - avctx->width / 2;
301
+            old_cr += old_cr_stride     - avctx->width / 2;
302
+            new_y  += new_y_stride * 2  - avctx->width;
303
+            new_cb += new_cb_stride     - avctx->width / 2;
304
+            new_cr += new_cr_stride     - avctx->width / 2;
305
+        }
306
+
307
+        skip--;
308
+    }
309
+
310
+    new_y  = s->new_y;
311
+    new_cb = s->new_u;
312
+    new_cr = s->new_v;
313
+    dstY   = pic->data[0];
314
+    dstU   = pic->data[1];
315
+    dstV   = pic->data[2];
316
+    for (j = 0; j < avctx->height; j++) {
317
+        for (i = 0; i < avctx->width; i++)
318
+            dstY[i] = new_y[i] << 2;
319
+        dstY  += pic->linesize[0];
320
+        new_y += new_y_stride;
321
+    }
322
+    for (j = 0; j < avctx->height / 2; j++) {
323
+        for (i = 0; i < avctx->width / 2; i++) {
324
+            dstU[i] = chroma_vals[new_cb[i]];
325
+            dstV[i] = chroma_vals[new_cr[i]];
326
+        }
327
+        dstU   += pic->linesize[1];
328
+        dstV   += pic->linesize[2];
329
+        new_cb += new_cb_stride;
330
+        new_cr += new_cr_stride;
331
+    }
332
+
333
+    av_dlog(avctx, "Frame data: provided %d bytes, used %d bytes\n",
334
+            buf_size, get_bits_count(&gb) >> 3);
335
+
336
+    FFSWAP(uint8_t*, s->old_y, s->new_y);
337
+    FFSWAP(uint8_t*, s->old_u, s->new_u);
338
+    FFSWAP(uint8_t*, s->old_v, s->new_v);
339
+
340
+    *got_frame = 1;
341
+
342
+    return buf_size;
343
+}
344
+
345
+AVCodec ff_escape130_decoder = {
346
+    .name           = "escape130",
347
+    .type           = AVMEDIA_TYPE_VIDEO,
348
+    .id             = AV_CODEC_ID_ESCAPE130,
349
+    .priv_data_size = sizeof(Escape130Context),
350
+    .init           = escape130_decode_init,
351
+    .close          = escape130_decode_close,
352
+    .decode         = escape130_decode_frame,
353
+    .capabilities   = CODEC_CAP_DR1,
354
+    .long_name      = NULL_IF_CONFIG_SMALL("Escape 130"),
355
+};
... ...
@@ -27,7 +27,7 @@
27 27
  */
28 28
 
29 29
 #define LIBAVCODEC_VERSION_MAJOR 55
30
-#define LIBAVCODEC_VERSION_MINOR  5
30
+#define LIBAVCODEC_VERSION_MINOR  6
31 31
 #define LIBAVCODEC_VERSION_MICRO  0
32 32
 
33 33
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
... ...
@@ -164,11 +164,9 @@ static int rpl_read_header(AVFormatContext *s)
164 164
             // The header is wrong here, at least sometimes
165 165
             vst->codec->bits_per_coded_sample = 16;
166 166
             break;
167
-#if 0
168 167
         case 130:
169 168
             vst->codec->codec_id = AV_CODEC_ID_ESCAPE130;
170 169
             break;
171
-#endif
172 170
         default:
173 171
             av_log(s, AV_LOG_WARNING,
174 172
                    "RPL video format %i not supported yet!\n",