Browse code

add Flash Screen Video 2 decoder

Signed-off-by: Ronald S. Bultje <rsbultje@gmail.com>

Kostya Shishkov authored on 2011/07/16 19:02:55
Showing 7 changed files
... ...
@@ -4,6 +4,7 @@ releases are sorted from youngest to oldest.
4 4
 
5 5
 version <next>:
6 6
 - BWF muxer
7
+- Flash Screen Video 2 decoder
7 8
 
8 9
 
9 10
 version 0.7:
... ...
@@ -1270,6 +1270,7 @@ flac_decoder_select="golomb"
1270 1270
 flac_encoder_select="golomb lpc"
1271 1271
 flashsv_decoder_select="zlib"
1272 1272
 flashsv_encoder_select="zlib"
1273
+flashsv2_decoder_select="zlib"
1273 1274
 flv_decoder_select="h263_decoder"
1274 1275
 flv_encoder_select="h263_encoder"
1275 1276
 fraps_decoder_select="huffman"
... ...
@@ -401,6 +401,7 @@ following image formats are supported:
401 401
     @tab experimental lossless codec (fourcc: FFV1)
402 402
 @item Flash Screen Video v1  @tab  X  @tab  X
403 403
     @tab fourcc: FSV1
404
+@item Flash Screen Video v2  @tab     @tab  X
404 405
 @item Flash Video (FLV)      @tab  X  @tab  X
405 406
     @tab Sorenson H.263 used in Flash
406 407
 @item Fraps                  @tab     @tab  X
... ...
@@ -146,6 +146,7 @@ OBJS-$(CONFIG_FLAC_DECODER)            += flacdec.o flacdata.o flac.o
146 146
 OBJS-$(CONFIG_FLAC_ENCODER)            += flacenc.o flacdata.o flac.o
147 147
 OBJS-$(CONFIG_FLASHSV_DECODER)         += flashsv.o
148 148
 OBJS-$(CONFIG_FLASHSV_ENCODER)         += flashsvenc.o
149
+OBJS-$(CONFIG_FLASHSV2_DECODER)        += flashsv.o
149 150
 OBJS-$(CONFIG_FLIC_DECODER)            += flicvideo.o
150 151
 OBJS-$(CONFIG_FOURXM_DECODER)          += 4xm.o
151 152
 OBJS-$(CONFIG_FRAPS_DECODER)           += fraps.o
... ...
@@ -106,6 +106,7 @@ void avcodec_register_all(void)
106 106
     REGISTER_ENCDEC  (FFV1, ffv1);
107 107
     REGISTER_ENCDEC  (FFVHUFF, ffvhuff);
108 108
     REGISTER_ENCDEC  (FLASHSV, flashsv);
109
+    REGISTER_DECODER (FLASHSV2, flashsv2);
109 110
     REGISTER_DECODER (FLIC, flic);
110 111
     REGISTER_ENCDEC  (FLV, flv);
111 112
     REGISTER_DECODER (FOURXM, fourxm);
... ...
@@ -25,6 +25,8 @@
25 25
  * Flash Screen Video decoder
26 26
  * @author Alex Beregszaszi
27 27
  * @author Benjamin Larsson
28
+ * @author Daniel Verkamp
29
+ * @author Konstantin Shishkov
28 30
  *
29 31
  * A description of the bitstream format for Flash Screen Video version 1/2
30 32
  * is part of the SWF File Format Specification (version 10), which can be
... ...
@@ -35,9 +37,17 @@
35 35
 #include <stdlib.h>
36 36
 #include <zlib.h>
37 37
 
38
+#include "libavutil/intreadwrite.h"
38 39
 #include "avcodec.h"
40
+#include "bytestream.h"
39 41
 #include "get_bits.h"
40 42
 
43
+typedef struct BlockInfo {
44
+    uint8_t *pos;
45
+    int      size;
46
+    int      unp_size;
47
+} BlockInfo;
48
+
41 49
 typedef struct FlashSVContext {
42 50
     AVCodecContext *avctx;
43 51
     AVFrame         frame;
... ...
@@ -46,9 +56,50 @@ typedef struct FlashSVContext {
46 46
     uint8_t        *tmpblock;
47 47
     int             block_size;
48 48
     z_stream        zstream;
49
+    int             ver;
50
+    const uint32_t *pal;
51
+    int             is_keyframe;
52
+    uint8_t        *keyframedata;
53
+    uint8_t        *keyframe;
54
+    BlockInfo      *blocks;
55
+    uint8_t        *deflate_block;
56
+    int             deflate_block_size;
57
+    int             color_depth;
58
+    int             zlibprime_curr, zlibprime_prev;
59
+    int             diff_start, diff_height;
49 60
 } FlashSVContext;
50 61
 
51 62
 
63
+static int decode_hybrid(const uint8_t *sptr, uint8_t *dptr, int dx, int dy,
64
+                         int h, int w, int stride, const uint32_t *pal)
65
+{
66
+    int x, y;
67
+    const uint8_t *orig_src = sptr;
68
+
69
+    for (y = dx+h; y > dx; y--) {
70
+        uint8_t *dst = dptr + (y * stride) + dy * 3;
71
+        for (x = 0; x < w; x++) {
72
+            if (*sptr & 0x80) {
73
+                /* 15-bit color */
74
+                unsigned c = AV_RB16(sptr) & ~0x8000;
75
+                unsigned b =  c        & 0x1F;
76
+                unsigned g = (c >>  5) & 0x1F;
77
+                unsigned r =  c >> 10;
78
+                /* 000aaabb -> aaabbaaa  */
79
+                *dst++ = (b << 3) | (b >> 2);
80
+                *dst++ = (g << 3) | (g >> 2);
81
+                *dst++ = (r << 3) | (r >> 2);
82
+                sptr += 2;
83
+            } else {
84
+                /* palette index */
85
+                uint32_t c = pal[*sptr++];
86
+                bytestream_put_le24(&dst, c);
87
+            }
88
+        }
89
+    }
90
+    return sptr - orig_src;
91
+}
92
+
52 93
 static av_cold int flashsv_decode_init(AVCodecContext *avctx)
53 94
 {
54 95
     FlashSVContext *s = avctx->priv_data;
... ...
@@ -70,9 +121,42 @@ static av_cold int flashsv_decode_init(AVCodecContext *avctx)
70 70
 }
71 71
 
72 72
 
73
+static void flashsv2_prime(FlashSVContext *s, uint8_t *src,
74
+                           int size, int unp_size)
75
+{
76
+    z_stream zs;
77
+
78
+    zs.zalloc = NULL;
79
+    zs.zfree  = NULL;
80
+    zs.opaque = NULL;
81
+
82
+    s->zstream.next_in   = src;
83
+    s->zstream.avail_in  = size;
84
+    s->zstream.next_out  = s->tmpblock;
85
+    s->zstream.avail_out = s->block_size * 3;
86
+    inflate(&s->zstream, Z_SYNC_FLUSH);
87
+
88
+    deflateInit(&zs, 0);
89
+    zs.next_in   = s->tmpblock;
90
+    zs.avail_in  = s->block_size * 3 - s->zstream.avail_out;
91
+    zs.next_out  = s->deflate_block;
92
+    zs.avail_out = s->deflate_block_size;
93
+    deflate(&zs, Z_SYNC_FLUSH);
94
+    deflateEnd(&zs);
95
+
96
+    inflateReset(&s->zstream);
97
+
98
+    s->zstream.next_in   = s->deflate_block;
99
+    s->zstream.avail_in  = s->deflate_block_size - zs.avail_out;
100
+    s->zstream.next_out  = s->tmpblock;
101
+    s->zstream.avail_out = s->block_size * 3;
102
+    inflate(&s->zstream, Z_SYNC_FLUSH);
103
+}
104
+
73 105
 static int flashsv_decode_block(AVCodecContext *avctx, AVPacket *avpkt,
74 106
                                 GetBitContext *gb, int block_size,
75
-                                int width, int height, int x_pos, int y_pos)
107
+                                int width, int height, int x_pos, int y_pos,
108
+                                int blk_idx)
76 109
 {
77 110
     struct FlashSVContext *s = avctx->priv_data;
78 111
     uint8_t *line = s->tmpblock;
... ...
@@ -81,6 +165,10 @@ static int flashsv_decode_block(AVCodecContext *avctx, AVPacket *avpkt,
81 81
     if (ret != Z_OK) {
82 82
         //return -1;
83 83
     }
84
+    if (s->zlibprime_curr || s->zlibprime_prev) {
85
+        flashsv2_prime(s, s->blocks[blk_idx].pos, s->blocks[blk_idx].size,
86
+                       s->blocks[blk_idx].unp_size);
87
+    }
84 88
     s->zstream.next_in   = avpkt->data + get_bits_count(gb) / 8;
85 89
     s->zstream.avail_in  = block_size;
86 90
     s->zstream.next_out  = s->tmpblock;
... ...
@@ -95,19 +183,48 @@ static int flashsv_decode_block(AVCodecContext *avctx, AVPacket *avpkt,
95 95
     if (ret != Z_OK && ret != Z_STREAM_END) {
96 96
         //return -1;
97 97
     }
98
-    /* Flash Screen Video stores the image upside down, so copy
99
-     * lines to destination in reverse order. */
100
-    for (k = 1; k <= height; k++) {
101
-        memcpy(s->frame.data[0] + x_pos * 3 +
102
-               (s->image_height - y_pos - k) * s->frame.linesize[0],
103
-               line, width * 3);
104
-        /* advance source pointer to next line */
105
-        line += width * 3;
98
+
99
+    if (s->is_keyframe) {
100
+        s->blocks[blk_idx].pos      = s->keyframedata + (get_bits_count(gb) / 8);
101
+        s->blocks[blk_idx].size     = block_size;
102
+        s->blocks[blk_idx].unp_size = s->block_size * 3 - s->zstream.avail_out;
103
+    }
104
+    if (!s->color_depth) {
105
+        /* Flash Screen Video stores the image upside down, so copy
106
+         * lines to destination in reverse order. */
107
+        for (k = 1; k <= s->diff_height; k++) {
108
+            memcpy(s->frame.data[0] + x_pos * 3 +
109
+                   (s->image_height - y_pos - s->diff_start - k) * s->frame.linesize[0],
110
+                   line, width * 3);
111
+            /* advance source pointer to next line */
112
+            line += width * 3;
113
+        }
114
+    } else {
115
+        /* hybrid 15-bit/palette mode */
116
+        decode_hybrid(s->tmpblock, s->frame.data[0],
117
+                      s->image_height - (y_pos + 1 + s->diff_start + s->diff_height),
118
+                      x_pos, s->diff_height, width,
119
+                      s->frame.linesize[0], s->pal);
106 120
     }
107 121
     skip_bits_long(gb, 8 * block_size); /* skip the consumed bits */
108 122
     return 0;
109 123
 }
110 124
 
125
+static int calc_deflate_block_size(int tmpblock_size)
126
+{
127
+    z_stream zstream;
128
+    int size;
129
+
130
+    zstream.zalloc = Z_NULL;
131
+    zstream.zfree  = Z_NULL;
132
+    zstream.opaque = Z_NULL;
133
+    if (deflateInit(&zstream, 0) != Z_OK)
134
+        return -1;
135
+    size = deflateBound(&zstream, tmpblock_size);
136
+    deflateEnd(&zstream);
137
+
138
+    return size;
139
+}
111 140
 
112 141
 static int flashsv_decode_frame(AVCodecContext *avctx, void *data,
113 142
                                 int *data_size, AVPacket *avpkt)
... ...
@@ -131,6 +248,18 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data,
131 131
     s->block_height = 16 * (get_bits(&gb,  4) + 1);
132 132
     s->image_height =       get_bits(&gb, 12);
133 133
 
134
+    if (s->ver == 2) {
135
+        skip_bits(&gb, 6);
136
+        if (get_bits1(&gb)) {
137
+            av_log_missing_feature(avctx, "iframe", 1);
138
+            return AVERROR_PATCHWELCOME;
139
+        }
140
+        if (get_bits1(&gb)) {
141
+            av_log_missing_feature(avctx, "custom palette", 1);
142
+            return AVERROR_PATCHWELCOME;
143
+        }
144
+    }
145
+
134 146
     /* calculate number of blocks and size of border (partial) blocks */
135 147
     h_blocks = s->image_width  / s->block_width;
136 148
     h_part   = s->image_width  % s->block_width;
... ...
@@ -140,11 +269,25 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data,
140 140
     /* the block size could change between frames, make sure the buffer
141 141
      * is large enough, if not, get a larger one */
142 142
     if (s->block_size < s->block_width * s->block_height) {
143
-        av_free(s->tmpblock);
144
-        if ((s->tmpblock = av_malloc(3 * s->block_width * s->block_height)) == NULL) {
143
+        int tmpblock_size = 3 * s->block_width * s->block_height;
144
+
145
+        s->tmpblock = av_realloc(s->tmpblock, tmpblock_size);
146
+        if (!s->tmpblock) {
145 147
             av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
146 148
             return AVERROR(ENOMEM);
147 149
         }
150
+        if (s->ver == 2) {
151
+            s->deflate_block_size = calc_deflate_block_size(tmpblock_size);
152
+            if (s->deflate_block_size <= 0) {
153
+                av_log(avctx, AV_LOG_ERROR, "Can't determine deflate buffer size.\n");
154
+                return -1;
155
+            }
156
+            s->deflate_block = av_realloc(s->deflate_block, s->deflate_block_size);
157
+            if (!s->deflate_block) {
158
+                av_log(avctx, AV_LOG_ERROR, "Can't allocate deflate buffer.\n");
159
+                return AVERROR(ENOMEM);
160
+            }
161
+        }
148 162
     }
149 163
     s->block_size = s->block_width * s->block_height;
150 164
 
... ...
@@ -163,6 +306,16 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data,
163 163
         return AVERROR_INVALIDDATA;
164 164
     }
165 165
 
166
+    /* we care for keyframes only in Screen Video v2 */
167
+    s->is_keyframe = (avpkt->flags & AV_PKT_FLAG_KEY) && (s->ver == 2);
168
+    if (s->is_keyframe) {
169
+        s->keyframedata = av_realloc(s->keyframedata, avpkt->size);
170
+        memcpy(s->keyframedata, avpkt->data, avpkt->size);
171
+        s->blocks = av_realloc(s->blocks,
172
+                               (v_blocks + !!v_part) * (h_blocks + !!h_part)
173
+                               * sizeof(s->blocks[0]));
174
+    }
175
+
166 176
     av_dlog(avctx, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n",
167 177
             s->image_width, s->image_height, s->block_width, s->block_height,
168 178
             h_blocks, v_blocks, h_part, v_part);
... ...
@@ -186,25 +339,90 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data,
186 186
         for (i = 0; i < h_blocks + (h_part ? 1 : 0); i++) {
187 187
             int x_pos = i * s->block_width; // horizontal position in frame
188 188
             int cur_blk_width = (i < h_blocks) ? s->block_width : h_part;
189
+            int has_diff = 0;
189 190
 
190 191
             /* get the size of the compressed zlib chunk */
191 192
             int size = get_bits(&gb, 16);
193
+
194
+            s->color_depth    = 0;
195
+            s->zlibprime_curr = 0;
196
+            s->zlibprime_prev = 0;
197
+            s->diff_start     = 0;
198
+            s->diff_height    = cur_blk_height;
199
+
192 200
             if (8 * size > get_bits_left(&gb)) {
193 201
                 avctx->release_buffer(avctx, &s->frame);
194 202
                 s->frame.data[0] = NULL;
195 203
                 return AVERROR_INVALIDDATA;
196 204
             }
197 205
 
206
+            if (s->ver == 2 && size) {
207
+                skip_bits(&gb, 3);
208
+                s->color_depth    = get_bits(&gb, 2);
209
+                has_diff          = get_bits1(&gb);
210
+                s->zlibprime_curr = get_bits1(&gb);
211
+                s->zlibprime_prev = get_bits1(&gb);
212
+
213
+                if (s->color_depth != 0 && s->color_depth != 2) {
214
+                    av_log(avctx, AV_LOG_ERROR,
215
+                           "%dx%d invalid color depth %d\n", i, j, s->color_depth);
216
+                    return -1;
217
+                }
218
+
219
+                if (has_diff) {
220
+                    s->diff_start  = get_bits(&gb, 8);
221
+                    s->diff_height = get_bits(&gb, 8);
222
+                    av_log(avctx, AV_LOG_DEBUG,
223
+                           "%dx%d diff start %d height %d\n",
224
+                           i, j, s->diff_start, s->diff_height);
225
+                    size -= 2;
226
+                }
227
+
228
+                if (s->zlibprime_prev)
229
+                    av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_prev\n", i, j);
230
+
231
+                if (s->zlibprime_curr) {
232
+                    int col = get_bits(&gb, 8);
233
+                    int row = get_bits(&gb, 8);
234
+                    av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_curr %dx%d\n", i, j, col, row);
235
+                    size -= 2;
236
+                    av_log_missing_feature(avctx, "zlibprime_curr", 1);
237
+                    return AVERROR_PATCHWELCOME;
238
+                }
239
+                size--; // account for flags byte
240
+            }
241
+
242
+            if (has_diff) {
243
+                int k;
244
+                int off = (s->image_height - y_pos - 1) * s->frame.linesize[0];
245
+
246
+                for (k = 0; k < cur_blk_height; k++)
247
+                    memcpy(s->frame.data[0] + off - k*s->frame.linesize[0] + x_pos*3,
248
+                           s->keyframe + off - k*s->frame.linesize[0] + x_pos*3,
249
+                           cur_blk_width * 3);
250
+            }
251
+
198 252
             /* skip unchanged blocks, which have size 0 */
199 253
             if (size) {
200 254
                 if (flashsv_decode_block(avctx, avpkt, &gb, size,
201 255
                                          cur_blk_width, cur_blk_height,
202
-                                         x_pos, y_pos))
256
+                                         x_pos, y_pos,
257
+                                         i + j * (h_blocks + !!h_part)))
203 258
                     av_log(avctx, AV_LOG_ERROR,
204 259
                            "error in decompression of block %dx%d\n", i, j);
205 260
             }
206 261
         }
207 262
     }
263
+    if (s->is_keyframe && s->ver == 2) {
264
+        if (!s->keyframe) {
265
+            s->keyframe = av_malloc(s->frame.linesize[0] * avctx->height);
266
+            if (!s->keyframe) {
267
+                av_log(avctx, AV_LOG_ERROR, "Cannot allocate image data\n");
268
+                return AVERROR(ENOMEM);
269
+            }
270
+        }
271
+        memcpy(s->keyframe, s->frame.data[0], s->frame.linesize[0] * avctx->height);
272
+    }
208 273
 
209 274
     *data_size = sizeof(AVFrame);
210 275
     *(AVFrame*)data = s->frame;
... ...
@@ -233,6 +451,7 @@ static av_cold int flashsv_decode_end(AVCodecContext *avctx)
233 233
 }
234 234
 
235 235
 
236
+#if CONFIG_FLASHSV_DECODER
236 237
 AVCodec ff_flashsv_decoder = {
237 238
     .name           = "flashsv",
238 239
     .type           = AVMEDIA_TYPE_VIDEO,
... ...
@@ -245,3 +464,67 @@ AVCodec ff_flashsv_decoder = {
245 245
     .pix_fmts       = (const enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_NONE},
246 246
     .long_name      = NULL_IF_CONFIG_SMALL("Flash Screen Video v1"),
247 247
 };
248
+#endif /* CONFIG_FLASHSV_DECODER */
249
+
250
+#if CONFIG_FLASHSV2_DECODER
251
+static const uint32_t ff_flashsv2_default_palette[128] = {
252
+    0x000000, 0x333333, 0x666666, 0x999999, 0xCCCCCC, 0xFFFFFF,
253
+    0x330000, 0x660000, 0x990000, 0xCC0000, 0xFF0000, 0x003300,
254
+    0x006600, 0x009900, 0x00CC00, 0x00FF00, 0x000033, 0x000066,
255
+    0x000099, 0x0000CC, 0x0000FF, 0x333300, 0x666600, 0x999900,
256
+    0xCCCC00, 0xFFFF00, 0x003333, 0x006666, 0x009999, 0x00CCCC,
257
+    0x00FFFF, 0x330033, 0x660066, 0x990099, 0xCC00CC, 0xFF00FF,
258
+    0xFFFF33, 0xFFFF66, 0xFFFF99, 0xFFFFCC, 0xFF33FF, 0xFF66FF,
259
+    0xFF99FF, 0xFFCCFF, 0x33FFFF, 0x66FFFF, 0x99FFFF, 0xCCFFFF,
260
+    0xCCCC33, 0xCCCC66, 0xCCCC99, 0xCCCCFF, 0xCC33CC, 0xCC66CC,
261
+    0xCC99CC, 0xCCFFCC, 0x33CCCC, 0x66CCCC, 0x99CCCC, 0xFFCCCC,
262
+    0x999933, 0x999966, 0x9999CC, 0x9999FF, 0x993399, 0x996699,
263
+    0x99CC99, 0x99FF99, 0x339999, 0x669999, 0xCC9999, 0xFF9999,
264
+    0x666633, 0x666699, 0x6666CC, 0x6666FF, 0x663366, 0x669966,
265
+    0x66CC66, 0x66FF66, 0x336666, 0x996666, 0xCC6666, 0xFF6666,
266
+    0x333366, 0x333399, 0x3333CC, 0x3333FF, 0x336633, 0x339933,
267
+    0x33CC33, 0x33FF33, 0x663333, 0x993333, 0xCC3333, 0xFF3333,
268
+    0x003366, 0x336600, 0x660033, 0x006633, 0x330066, 0x663300,
269
+    0x336699, 0x669933, 0x993366, 0x339966, 0x663399, 0x996633,
270
+    0x6699CC, 0x99CC66, 0xCC6699, 0x66CC99, 0x9966CC, 0xCC9966,
271
+    0x99CCFF, 0xCCFF99, 0xFF99CC, 0x99FFCC, 0xCC99FF, 0xFFCC99,
272
+    0x111111, 0x222222, 0x444444, 0x555555, 0xAAAAAA, 0xBBBBBB,
273
+    0xDDDDDD, 0xEEEEEE
274
+};
275
+
276
+static av_cold int flashsv2_decode_init(AVCodecContext *avctx)
277
+{
278
+    FlashSVContext *s = avctx->priv_data;
279
+    flashsv_decode_init(avctx);
280
+    s->pal = ff_flashsv2_default_palette;
281
+    s->ver = 2;
282
+
283
+    return 0;
284
+}
285
+
286
+static av_cold int flashsv2_decode_end(AVCodecContext *avctx)
287
+{
288
+    FlashSVContext *s = avctx->priv_data;
289
+
290
+    av_freep(&s->keyframedata);
291
+    av_freep(&s->blocks);
292
+    av_freep(&s->keyframe);
293
+    av_freep(&s->deflate_block);
294
+    flashsv_decode_end(avctx);
295
+
296
+    return 0;
297
+}
298
+
299
+AVCodec ff_flashsv2_decoder = {
300
+    .name           = "flashsv2",
301
+    .type           = AVMEDIA_TYPE_VIDEO,
302
+    .id             = CODEC_ID_FLASHSV2,
303
+    .priv_data_size = sizeof(FlashSVContext),
304
+    .init           = flashsv2_decode_init,
305
+    .close          = flashsv2_decode_end,
306
+    .decode         = flashsv_decode_frame,
307
+    .capabilities   = CODEC_CAP_DR1,
308
+    .pix_fmts       = (const enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_NONE},
309
+    .long_name      = NULL_IF_CONFIG_SMALL("Flash Screen Video v2"),
310
+};
311
+#endif /* CONFIG_FLASHSV2_DECODER */
... ...
@@ -21,7 +21,7 @@
21 21
 #define AVCODEC_VERSION_H
22 22
 
23 23
 #define LIBAVCODEC_VERSION_MAJOR 53
24
-#define LIBAVCODEC_VERSION_MINOR  6
24
+#define LIBAVCODEC_VERSION_MINOR  7
25 25
 #define LIBAVCODEC_VERSION_MICRO  0
26 26
 
27 27
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \