]> git.sesse.net Git - ffmpeg/blob - libavcodec/flashsv.c
avcodec: Constify AVCodecs
[ffmpeg] / libavcodec / flashsv.c
1 /*
2  * Flash Screen Video decoder
3  * Copyright (C) 2004 Alex Beregszaszi
4  * Copyright (C) 2006 Benjamin Larsson
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 /**
24  * @file
25  * Flash Screen Video decoder
26  * @author Alex Beregszaszi
27  * @author Benjamin Larsson
28  * @author Daniel Verkamp
29  * @author Konstantin Shishkov
30  *
31  * A description of the bitstream format for Flash Screen Video version 1/2
32  * is part of the SWF File Format Specification (version 10), which can be
33  * downloaded from http://www.adobe.com/devnet/swf.html.
34  */
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <zlib.h>
39
40 #include "libavutil/intreadwrite.h"
41 #include "avcodec.h"
42 #include "bytestream.h"
43 #include "get_bits.h"
44 #include "internal.h"
45
46 typedef struct BlockInfo {
47     uint8_t *pos;
48     int      size;
49 } BlockInfo;
50
51 typedef struct FlashSVContext {
52     AVCodecContext *avctx;
53     AVFrame        *frame;
54     int             image_width, image_height;
55     int             block_width, block_height;
56     uint8_t        *tmpblock;
57     int             block_size;
58     z_stream        zstream;
59     int             ver;
60     const uint32_t *pal;
61     int             is_keyframe;
62     uint8_t        *keyframedata;
63     uint8_t        *keyframe;
64     BlockInfo      *blocks;
65     uint8_t        *deflate_block;
66     int             deflate_block_size;
67     int             color_depth;
68     int             zlibprime_curr, zlibprime_prev;
69     int             diff_start, diff_height;
70 } FlashSVContext;
71
72 static int decode_hybrid(const uint8_t *sptr, const uint8_t *sptr_end, uint8_t *dptr, int dx, int dy,
73                          int h, int w, int stride, const uint32_t *pal)
74 {
75     int x, y;
76     const uint8_t *orig_src = sptr;
77
78     for (y = dx + h; y > dx; y--) {
79         uint8_t *dst = dptr + (y * stride) + dy * 3;
80         for (x = 0; x < w; x++) {
81             if (sptr >= sptr_end)
82                 return AVERROR_INVALIDDATA;
83             if (*sptr & 0x80) {
84                 /* 15-bit color */
85                 unsigned c = AV_RB16(sptr) & ~0x8000;
86                 unsigned b =  c        & 0x1F;
87                 unsigned g = (c >>  5) & 0x1F;
88                 unsigned r =  c >> 10;
89                 /* 000aaabb -> aaabbaaa  */
90                 *dst++ = (b << 3) | (b >> 2);
91                 *dst++ = (g << 3) | (g >> 2);
92                 *dst++ = (r << 3) | (r >> 2);
93                 sptr += 2;
94             } else {
95                 /* palette index */
96                 uint32_t c = pal[*sptr++];
97                 bytestream_put_le24(&dst, c);
98             }
99         }
100     }
101     return sptr - orig_src;
102 }
103
104 static av_cold int flashsv_decode_end(AVCodecContext *avctx)
105 {
106     FlashSVContext *s = avctx->priv_data;
107     inflateEnd(&s->zstream);
108     /* release the frame if needed */
109     av_frame_free(&s->frame);
110
111     /* free the tmpblock */
112     av_freep(&s->tmpblock);
113
114     return 0;
115 }
116
117 static av_cold int flashsv_decode_init(AVCodecContext *avctx)
118 {
119     FlashSVContext *s = avctx->priv_data;
120     int zret; // Zlib return code
121
122     s->avctx          = avctx;
123     s->zstream.zalloc = Z_NULL;
124     s->zstream.zfree  = Z_NULL;
125     s->zstream.opaque = Z_NULL;
126     zret = inflateInit(&s->zstream);
127     if (zret != Z_OK) {
128         av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
129         return 1;
130     }
131     avctx->pix_fmt = AV_PIX_FMT_BGR24;
132
133     s->frame = av_frame_alloc();
134     if (!s->frame) {
135         return AVERROR(ENOMEM);
136     }
137
138     return 0;
139 }
140
141 static int flashsv2_prime(FlashSVContext *s, uint8_t *src, int size)
142 {
143     z_stream zs;
144     int zret; // Zlib return code
145
146     if (!src)
147         return AVERROR_INVALIDDATA;
148
149     zs.zalloc = NULL;
150     zs.zfree  = NULL;
151     zs.opaque = NULL;
152
153     s->zstream.next_in   = src;
154     s->zstream.avail_in  = size;
155     s->zstream.next_out  = s->tmpblock;
156     s->zstream.avail_out = s->block_size * 3;
157     inflate(&s->zstream, Z_SYNC_FLUSH);
158
159     if (deflateInit(&zs, 0) != Z_OK)
160         return -1;
161     zs.next_in   = s->tmpblock;
162     zs.avail_in  = s->block_size * 3 - s->zstream.avail_out;
163     zs.next_out  = s->deflate_block;
164     zs.avail_out = s->deflate_block_size;
165     deflate(&zs, Z_SYNC_FLUSH);
166     deflateEnd(&zs);
167
168     if ((zret = inflateReset(&s->zstream)) != Z_OK) {
169         av_log(s->avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret);
170         return AVERROR_UNKNOWN;
171     }
172
173     s->zstream.next_in   = s->deflate_block;
174     s->zstream.avail_in  = s->deflate_block_size - zs.avail_out;
175     s->zstream.next_out  = s->tmpblock;
176     s->zstream.avail_out = s->block_size * 3;
177     inflate(&s->zstream, Z_SYNC_FLUSH);
178
179     return 0;
180 }
181
182 static int flashsv_decode_block(AVCodecContext *avctx, const AVPacket *avpkt,
183                                 GetBitContext *gb, int block_size,
184                                 int width, int height, int x_pos, int y_pos,
185                                 int blk_idx)
186 {
187     struct FlashSVContext *s = avctx->priv_data;
188     uint8_t *line = s->tmpblock;
189     int k;
190     int ret = inflateReset(&s->zstream);
191     if (ret != Z_OK) {
192         av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret);
193         return AVERROR_UNKNOWN;
194     }
195     if (s->zlibprime_curr || s->zlibprime_prev) {
196         ret = flashsv2_prime(s,
197                              s->blocks[blk_idx].pos,
198                              s->blocks[blk_idx].size);
199         if (ret < 0)
200             return ret;
201     }
202     s->zstream.next_in   = avpkt->data + get_bits_count(gb) / 8;
203     s->zstream.avail_in  = block_size;
204     s->zstream.next_out  = s->tmpblock;
205     s->zstream.avail_out = s->block_size * 3;
206     ret = inflate(&s->zstream, Z_FINISH);
207     if (ret == Z_DATA_ERROR) {
208         av_log(avctx, AV_LOG_ERROR, "Zlib resync occurred\n");
209         inflateSync(&s->zstream);
210         ret = inflate(&s->zstream, Z_FINISH);
211     }
212
213     if (ret != Z_OK && ret != Z_STREAM_END) {
214         //return -1;
215     }
216
217     if (s->is_keyframe) {
218         s->blocks[blk_idx].pos  = s->keyframedata + (get_bits_count(gb) / 8);
219         s->blocks[blk_idx].size = block_size;
220     }
221
222     y_pos += s->diff_start;
223
224     if (!s->color_depth) {
225         /* Flash Screen Video stores the image upside down, so copy
226          * lines to destination in reverse order. */
227         for (k = 1; k <= s->diff_height; k++) {
228             memcpy(s->frame->data[0] + x_pos * 3 +
229                    (s->image_height - y_pos - k) * s->frame->linesize[0],
230                    line, width * 3);
231             /* advance source pointer to next line */
232             line += width * 3;
233         }
234     } else {
235         /* hybrid 15-bit/palette mode */
236         ret = decode_hybrid(s->tmpblock, s->zstream.next_out,
237                       s->frame->data[0],
238                       s->image_height - (y_pos + 1 + s->diff_height),
239                       x_pos, s->diff_height, width,
240                       s->frame->linesize[0], s->pal);
241         if (ret < 0) {
242             av_log(avctx, AV_LOG_ERROR, "decode_hybrid failed\n");
243             return ret;
244         }
245     }
246     skip_bits_long(gb, 8 * block_size); /* skip the consumed bits */
247     return 0;
248 }
249
250 static int calc_deflate_block_size(int tmpblock_size)
251 {
252     z_stream zstream;
253     int size;
254
255     zstream.zalloc = Z_NULL;
256     zstream.zfree  = Z_NULL;
257     zstream.opaque = Z_NULL;
258     if (deflateInit(&zstream, 0) != Z_OK)
259         return -1;
260     size = deflateBound(&zstream, tmpblock_size);
261     deflateEnd(&zstream);
262
263     return size;
264 }
265
266 static int flashsv_decode_frame(AVCodecContext *avctx, void *data,
267                                 int *got_frame, AVPacket *avpkt)
268 {
269     int buf_size = avpkt->size;
270     FlashSVContext *s = avctx->priv_data;
271     int h_blocks, v_blocks, h_part, v_part, i, j, ret;
272     GetBitContext gb;
273     int last_blockwidth = s->block_width;
274     int last_blockheight= s->block_height;
275
276     /* no supplementary picture */
277     if (buf_size == 0)
278         return 0;
279     if (buf_size < 4)
280         return -1;
281
282     if ((ret = init_get_bits8(&gb, avpkt->data, buf_size)) < 0)
283         return ret;
284
285     /* start to parse the bitstream */
286     s->block_width  = 16 * (get_bits(&gb, 4) + 1);
287     s->image_width  = get_bits(&gb, 12);
288     s->block_height = 16 * (get_bits(&gb, 4) + 1);
289     s->image_height = get_bits(&gb, 12);
290
291     if (   last_blockwidth != s->block_width
292         || last_blockheight!= s->block_height)
293         av_freep(&s->blocks);
294
295     if (s->ver == 2) {
296         skip_bits(&gb, 6);
297         if (get_bits1(&gb)) {
298             avpriv_request_sample(avctx, "iframe");
299             return AVERROR_PATCHWELCOME;
300         }
301         if (get_bits1(&gb)) {
302             avpriv_request_sample(avctx, "Custom palette");
303             return AVERROR_PATCHWELCOME;
304         }
305     }
306
307     /* calculate number of blocks and size of border (partial) blocks */
308     h_blocks = s->image_width  / s->block_width;
309     h_part   = s->image_width  % s->block_width;
310     v_blocks = s->image_height / s->block_height;
311     v_part   = s->image_height % s->block_height;
312
313     /* the block size could change between frames, make sure the buffer
314      * is large enough, if not, get a larger one */
315     if (s->block_size < s->block_width * s->block_height) {
316         int tmpblock_size = 3 * s->block_width * s->block_height, err;
317
318         if ((err = av_reallocp(&s->tmpblock, tmpblock_size)) < 0) {
319             s->block_size = 0;
320             av_log(avctx, AV_LOG_ERROR,
321                    "Cannot allocate decompression buffer.\n");
322             return err;
323         }
324         if (s->ver == 2) {
325             s->deflate_block_size = calc_deflate_block_size(tmpblock_size);
326             if (s->deflate_block_size <= 0) {
327                 av_log(avctx, AV_LOG_ERROR,
328                        "Cannot determine deflate buffer size.\n");
329                 return -1;
330             }
331             if ((err = av_reallocp(&s->deflate_block, s->deflate_block_size)) < 0) {
332                 s->block_size = 0;
333                 av_log(avctx, AV_LOG_ERROR, "Cannot allocate deflate buffer.\n");
334                 return err;
335             }
336         }
337     }
338     s->block_size = s->block_width * s->block_height;
339
340     /* initialize the image size once */
341     if (avctx->width == 0 && avctx->height == 0) {
342         if ((ret = ff_set_dimensions(avctx, s->image_width, s->image_height)) < 0)
343             return ret;
344     }
345
346     /* check for changes of image width and image height */
347     if (avctx->width != s->image_width || avctx->height != s->image_height) {
348         av_log(avctx, AV_LOG_ERROR,
349                "Frame width or height differs from first frame!\n");
350         av_log(avctx, AV_LOG_ERROR, "fh = %d, fv %d  vs  ch = %d, cv = %d\n",
351                avctx->height, avctx->width, s->image_height, s->image_width);
352         return AVERROR_INVALIDDATA;
353     }
354
355     /* we care for keyframes only in Screen Video v2 */
356     s->is_keyframe = (avpkt->flags & AV_PKT_FLAG_KEY) && (s->ver == 2);
357     if (s->is_keyframe) {
358         int err;
359         if ((err = av_reallocp(&s->keyframedata, avpkt->size)) < 0)
360             return err;
361         memcpy(s->keyframedata, avpkt->data, avpkt->size);
362     }
363     if(s->ver == 2 && !s->blocks)
364         s->blocks = av_mallocz((v_blocks + !!v_part) * (h_blocks + !!h_part) *
365                                sizeof(s->blocks[0]));
366
367     ff_dlog(avctx, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n",
368             s->image_width, s->image_height, s->block_width, s->block_height,
369             h_blocks, v_blocks, h_part, v_part);
370
371     if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0)
372         return ret;
373
374     /* loop over all block columns */
375     for (j = 0; j < v_blocks + (v_part ? 1 : 0); j++) {
376
377         int y_pos  = j * s->block_height; // vertical position in frame
378         int cur_blk_height = (j < v_blocks) ? s->block_height : v_part;
379
380         /* loop over all block rows */
381         for (i = 0; i < h_blocks + (h_part ? 1 : 0); i++) {
382             int x_pos = i * s->block_width; // horizontal position in frame
383             int cur_blk_width = (i < h_blocks) ? s->block_width : h_part;
384             int has_diff = 0;
385
386             /* get the size of the compressed zlib chunk */
387             int size = get_bits(&gb, 16);
388
389             s->color_depth    = 0;
390             s->zlibprime_curr = 0;
391             s->zlibprime_prev = 0;
392             s->diff_start     = 0;
393             s->diff_height    = cur_blk_height;
394
395             if (8 * size > get_bits_left(&gb)) {
396                 av_frame_unref(s->frame);
397                 return AVERROR_INVALIDDATA;
398             }
399
400             if (s->ver == 2 && size) {
401                 skip_bits(&gb, 3);
402                 s->color_depth    = get_bits(&gb, 2);
403                 has_diff          = get_bits1(&gb);
404                 s->zlibprime_curr = get_bits1(&gb);
405                 s->zlibprime_prev = get_bits1(&gb);
406
407                 if (s->color_depth != 0 && s->color_depth != 2) {
408                     av_log(avctx, AV_LOG_ERROR,
409                            "%dx%d invalid color depth %d\n",
410                            i, j, s->color_depth);
411                     return AVERROR_INVALIDDATA;
412                 }
413
414                 if (has_diff) {
415                     if (size < 3) {
416                         av_log(avctx, AV_LOG_ERROR, "size too small for diff\n");
417                         return AVERROR_INVALIDDATA;
418                     }
419                     if (!s->keyframe) {
420                         av_log(avctx, AV_LOG_ERROR,
421                                "Inter frame without keyframe\n");
422                         return AVERROR_INVALIDDATA;
423                     }
424                     s->diff_start  = get_bits(&gb, 8);
425                     s->diff_height = get_bits(&gb, 8);
426                     if (s->diff_start + s->diff_height > cur_blk_height) {
427                         av_log(avctx, AV_LOG_ERROR,
428                                "Block parameters invalid: %d + %d > %d\n",
429                                s->diff_start, s->diff_height, cur_blk_height);
430                         return AVERROR_INVALIDDATA;
431                     }
432                     av_log(avctx, AV_LOG_DEBUG,
433                            "%dx%d diff start %d height %d\n",
434                            i, j, s->diff_start, s->diff_height);
435                     size -= 2;
436                 }
437
438                 if (s->zlibprime_prev)
439                     av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_prev\n", i, j);
440
441                 if (s->zlibprime_curr) {
442                     int col = get_bits(&gb, 8);
443                     int row = get_bits(&gb, 8);
444                     av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_curr %dx%d\n",
445                            i, j, col, row);
446                     if (size < 3) {
447                         av_log(avctx, AV_LOG_ERROR, "size too small for zlibprime_curr\n");
448                         return AVERROR_INVALIDDATA;
449                     }
450                     size -= 2;
451                     avpriv_request_sample(avctx, "zlibprime_curr");
452                     return AVERROR_PATCHWELCOME;
453                 }
454                 if (!s->blocks && (s->zlibprime_curr || s->zlibprime_prev)) {
455                     av_log(avctx, AV_LOG_ERROR,
456                            "no data available for zlib priming\n");
457                     return AVERROR_INVALIDDATA;
458                 }
459                 size--; // account for flags byte
460             }
461
462             if (has_diff) {
463                 int k;
464                 int off = (s->image_height - y_pos - 1) * s->frame->linesize[0];
465
466                 for (k = 0; k < cur_blk_height; k++) {
467                     int x = off - k * s->frame->linesize[0] + x_pos * 3;
468                     memcpy(s->frame->data[0] + x, s->keyframe + x,
469                            cur_blk_width * 3);
470                 }
471             }
472
473             /* skip unchanged blocks, which have size 0 */
474             if (size) {
475                 if (flashsv_decode_block(avctx, avpkt, &gb, size,
476                                          cur_blk_width, cur_blk_height,
477                                          x_pos, y_pos,
478                                          i + j * (h_blocks + !!h_part)))
479                     av_log(avctx, AV_LOG_ERROR,
480                            "error in decompression of block %dx%d\n", i, j);
481             }
482         }
483     }
484     if (s->is_keyframe && s->ver == 2) {
485         if (!s->keyframe) {
486             s->keyframe = av_malloc(s->frame->linesize[0] * avctx->height);
487             if (!s->keyframe) {
488                 av_log(avctx, AV_LOG_ERROR, "Cannot allocate image data\n");
489                 return AVERROR(ENOMEM);
490             }
491         }
492         memcpy(s->keyframe, s->frame->data[0],
493                s->frame->linesize[0] * avctx->height);
494     }
495
496     if ((ret = av_frame_ref(data, s->frame)) < 0)
497         return ret;
498
499     *got_frame = 1;
500
501     if ((get_bits_count(&gb) / 8) != buf_size)
502         av_log(avctx, AV_LOG_ERROR, "buffer not fully consumed (%d != %d)\n",
503                buf_size, (get_bits_count(&gb) / 8));
504
505     /* report that the buffer was completely consumed */
506     return buf_size;
507 }
508
509 #if CONFIG_FLASHSV_DECODER
510 const AVCodec ff_flashsv_decoder = {
511     .name           = "flashsv",
512     .long_name      = NULL_IF_CONFIG_SMALL("Flash Screen Video v1"),
513     .type           = AVMEDIA_TYPE_VIDEO,
514     .id             = AV_CODEC_ID_FLASHSV,
515     .priv_data_size = sizeof(FlashSVContext),
516     .init           = flashsv_decode_init,
517     .close          = flashsv_decode_end,
518     .decode         = flashsv_decode_frame,
519     .capabilities   = AV_CODEC_CAP_DR1,
520     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
521     .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE },
522 };
523 #endif /* CONFIG_FLASHSV_DECODER */
524
525 #if CONFIG_FLASHSV2_DECODER
526 static const uint32_t ff_flashsv2_default_palette[128] = {
527     0x000000, 0x333333, 0x666666, 0x999999, 0xCCCCCC, 0xFFFFFF,
528     0x330000, 0x660000, 0x990000, 0xCC0000, 0xFF0000, 0x003300,
529     0x006600, 0x009900, 0x00CC00, 0x00FF00, 0x000033, 0x000066,
530     0x000099, 0x0000CC, 0x0000FF, 0x333300, 0x666600, 0x999900,
531     0xCCCC00, 0xFFFF00, 0x003333, 0x006666, 0x009999, 0x00CCCC,
532     0x00FFFF, 0x330033, 0x660066, 0x990099, 0xCC00CC, 0xFF00FF,
533     0xFFFF33, 0xFFFF66, 0xFFFF99, 0xFFFFCC, 0xFF33FF, 0xFF66FF,
534     0xFF99FF, 0xFFCCFF, 0x33FFFF, 0x66FFFF, 0x99FFFF, 0xCCFFFF,
535     0xCCCC33, 0xCCCC66, 0xCCCC99, 0xCCCCFF, 0xCC33CC, 0xCC66CC,
536     0xCC99CC, 0xCCFFCC, 0x33CCCC, 0x66CCCC, 0x99CCCC, 0xFFCCCC,
537     0x999933, 0x999966, 0x9999CC, 0x9999FF, 0x993399, 0x996699,
538     0x99CC99, 0x99FF99, 0x339999, 0x669999, 0xCC9999, 0xFF9999,
539     0x666633, 0x666699, 0x6666CC, 0x6666FF, 0x663366, 0x669966,
540     0x66CC66, 0x66FF66, 0x336666, 0x996666, 0xCC6666, 0xFF6666,
541     0x333366, 0x333399, 0x3333CC, 0x3333FF, 0x336633, 0x339933,
542     0x33CC33, 0x33FF33, 0x663333, 0x993333, 0xCC3333, 0xFF3333,
543     0x003366, 0x336600, 0x660033, 0x006633, 0x330066, 0x663300,
544     0x336699, 0x669933, 0x993366, 0x339966, 0x663399, 0x996633,
545     0x6699CC, 0x99CC66, 0xCC6699, 0x66CC99, 0x9966CC, 0xCC9966,
546     0x99CCFF, 0xCCFF99, 0xFF99CC, 0x99FFCC, 0xCC99FF, 0xFFCC99,
547     0x111111, 0x222222, 0x444444, 0x555555, 0xAAAAAA, 0xBBBBBB,
548     0xDDDDDD, 0xEEEEEE
549 };
550
551 static av_cold int flashsv2_decode_init(AVCodecContext *avctx)
552 {
553     FlashSVContext *s = avctx->priv_data;
554     int ret;
555
556     ret = flashsv_decode_init(avctx);
557     if (ret < 0)
558         return ret;
559     s->pal = ff_flashsv2_default_palette;
560     s->ver = 2;
561
562     return 0;
563 }
564
565 static av_cold int flashsv2_decode_end(AVCodecContext *avctx)
566 {
567     FlashSVContext *s = avctx->priv_data;
568
569     av_freep(&s->keyframedata);
570     av_freep(&s->blocks);
571     av_freep(&s->keyframe);
572     av_freep(&s->deflate_block);
573     flashsv_decode_end(avctx);
574
575     return 0;
576 }
577
578 const AVCodec ff_flashsv2_decoder = {
579     .name           = "flashsv2",
580     .long_name      = NULL_IF_CONFIG_SMALL("Flash Screen Video v2"),
581     .type           = AVMEDIA_TYPE_VIDEO,
582     .id             = AV_CODEC_ID_FLASHSV2,
583     .priv_data_size = sizeof(FlashSVContext),
584     .init           = flashsv2_decode_init,
585     .close          = flashsv2_decode_end,
586     .decode         = flashsv_decode_frame,
587     .capabilities   = AV_CODEC_CAP_DR1,
588     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
589     .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE },
590 };
591 #endif /* CONFIG_FLASHSV2_DECODER */