You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

632 lines
22KB

  1. /*
  2. * FM Screen Capture Codec decoder
  3. *
  4. * Copyright (c) 2017 Paul B Mahol
  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. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include "avcodec.h"
  26. #include "bytestream.h"
  27. #include "internal.h"
  28. #define BLOCK_HEIGHT 112u
  29. #define BLOCK_WIDTH 84u
  30. typedef struct InterBlock {
  31. int w, h;
  32. int size;
  33. int xor;
  34. } InterBlock;
  35. typedef struct FMVCContext {
  36. GetByteContext gb;
  37. PutByteContext pb;
  38. uint8_t *buffer;
  39. size_t buffer_size;
  40. uint8_t *pbuffer;
  41. size_t pbuffer_size;
  42. int stride;
  43. int bpp;
  44. int yb, xb;
  45. InterBlock *blocks;
  46. int nb_blocks;
  47. } FMVCContext;
  48. static int decode_type2(GetByteContext *gb, PutByteContext *pb)
  49. {
  50. unsigned repeat = 0, first = 1, opcode;
  51. int i, len, pos;
  52. while (bytestream2_get_bytes_left(gb) > 0) {
  53. GetByteContext gbc;
  54. while (bytestream2_get_bytes_left(gb) > 0) {
  55. if (first) {
  56. first = 0;
  57. if (bytestream2_peek_byte(gb) > 17) {
  58. len = bytestream2_get_byte(gb) - 17;
  59. if (len < 4) {
  60. do {
  61. bytestream2_put_byte(pb, bytestream2_get_byte(gb));
  62. --len;
  63. } while (len);
  64. opcode = bytestream2_peek_byte(gb);
  65. continue;
  66. } else {
  67. do {
  68. bytestream2_put_byte(pb, bytestream2_get_byte(gb));
  69. --len;
  70. } while (len);
  71. opcode = bytestream2_peek_byte(gb);
  72. if (opcode < 0x10) {
  73. bytestream2_skip(gb, 1);
  74. pos = - (opcode >> 2) - 4 * bytestream2_get_byte(gb) - 2049;
  75. bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
  76. bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
  77. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  78. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  79. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  80. len = opcode & 3;
  81. if (!len) {
  82. repeat = 1;
  83. } else {
  84. do {
  85. bytestream2_put_byte(pb, bytestream2_get_byte(gb));
  86. --len;
  87. } while (len);
  88. opcode = bytestream2_peek_byte(gb);
  89. }
  90. continue;
  91. }
  92. }
  93. repeat = 0;
  94. }
  95. repeat = 1;
  96. }
  97. if (repeat) {
  98. repeat = 0;
  99. opcode = bytestream2_peek_byte(gb);
  100. if (opcode < 0x10) {
  101. bytestream2_skip(gb, 1);
  102. if (!opcode) {
  103. if (!bytestream2_peek_byte(gb)) {
  104. do {
  105. bytestream2_skip(gb, 1);
  106. opcode += 255;
  107. } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
  108. }
  109. opcode += bytestream2_get_byte(gb) + 15;
  110. }
  111. bytestream2_put_le32(pb, bytestream2_get_le32(gb));
  112. for (i = opcode - 1; i > 0; --i)
  113. bytestream2_put_byte(pb, bytestream2_get_byte(gb));
  114. opcode = bytestream2_peek_byte(gb);
  115. if (opcode < 0x10) {
  116. bytestream2_skip(gb, 1);
  117. pos = - (opcode >> 2) - 4 * bytestream2_get_byte(gb) - 2049;
  118. bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
  119. bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
  120. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  121. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  122. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  123. len = opcode & 3;
  124. if (!len) {
  125. repeat = 1;
  126. } else {
  127. do {
  128. bytestream2_put_byte(pb, bytestream2_get_byte(gb));
  129. --len;
  130. } while (len);
  131. opcode = bytestream2_peek_byte(gb);
  132. }
  133. continue;
  134. }
  135. }
  136. }
  137. if (opcode >= 0x40) {
  138. bytestream2_skip(gb, 1);
  139. pos = - ((opcode >> 2) & 7) - 1 - 8 * bytestream2_get_byte(gb);
  140. len = (opcode >> 5) - 1;
  141. bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
  142. bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
  143. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  144. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  145. do {
  146. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  147. --len;
  148. } while (len);
  149. len = opcode & 3;
  150. if (!len) {
  151. repeat = 1;
  152. } else {
  153. do {
  154. bytestream2_put_byte(pb, bytestream2_get_byte(gb));
  155. --len;
  156. } while (len);
  157. opcode = bytestream2_peek_byte(gb);
  158. }
  159. continue;
  160. } else if (opcode < 0x20) {
  161. break;
  162. }
  163. len = opcode & 0x1F;
  164. bytestream2_skip(gb, 1);
  165. if (!len) {
  166. if (!bytestream2_peek_byte(gb)) {
  167. do {
  168. bytestream2_skip(gb, 1);
  169. len += 255;
  170. } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
  171. }
  172. len += bytestream2_get_byte(gb) + 31;
  173. }
  174. i = bytestream2_get_le16(gb);
  175. pos = - (i >> 2) - 1;
  176. bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
  177. bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
  178. if (len < 6 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
  179. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  180. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  181. do {
  182. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  183. --len;
  184. } while (len);
  185. } else {
  186. bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
  187. for (len = len - 2; len; --len)
  188. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  189. }
  190. len = i & 3;
  191. if (!len) {
  192. repeat = 1;
  193. } else {
  194. do {
  195. bytestream2_put_byte(pb, bytestream2_get_byte(gb));
  196. --len;
  197. } while (len);
  198. opcode = bytestream2_peek_byte(gb);
  199. }
  200. }
  201. bytestream2_skip(gb, 1);
  202. if (opcode < 0x10) {
  203. pos = -(opcode >> 2) - 1 - 4 * bytestream2_get_byte(gb);
  204. bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
  205. bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
  206. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  207. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  208. len = opcode & 3;
  209. if (!len) {
  210. repeat = 1;
  211. } else {
  212. do {
  213. bytestream2_put_byte(pb, bytestream2_get_byte(gb));
  214. --len;
  215. } while (len);
  216. opcode = bytestream2_peek_byte(gb);
  217. }
  218. continue;
  219. }
  220. len = opcode & 7;
  221. if (!len) {
  222. if (!bytestream2_peek_byte(gb)) {
  223. do {
  224. bytestream2_skip(gb, 1);
  225. len += 255;
  226. } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
  227. }
  228. len += bytestream2_get_byte(gb) + 7;
  229. }
  230. i = bytestream2_get_le16(gb);
  231. pos = bytestream2_tell_p(pb) - 2048 * (opcode & 8);
  232. pos = pos - (i >> 2);
  233. if (pos == bytestream2_tell_p(pb))
  234. break;
  235. pos = pos - 0x4000;
  236. bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
  237. bytestream2_seek(&gbc, pos, SEEK_SET);
  238. if (len < 6 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
  239. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  240. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  241. do {
  242. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  243. --len;
  244. } while (len);
  245. } else {
  246. bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
  247. for (len = len - 2; len; --len)
  248. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  249. }
  250. len = i & 3;
  251. if (!len) {
  252. repeat = 1;
  253. } else {
  254. do {
  255. bytestream2_put_byte(pb, bytestream2_get_byte(gb));
  256. --len;
  257. } while (len);
  258. opcode = bytestream2_peek_byte(gb);
  259. }
  260. }
  261. return 0;
  262. }
  263. static int decode_type1(GetByteContext *gb, PutByteContext *pb)
  264. {
  265. unsigned opcode, len;
  266. int high = 0;
  267. int i, pos;
  268. while (bytestream2_get_bytes_left(gb) > 0) {
  269. GetByteContext gbc;
  270. while (bytestream2_get_bytes_left(gb) > 0) {
  271. while (bytestream2_get_bytes_left(gb) > 0) {
  272. opcode = bytestream2_get_byte(gb);
  273. high = opcode >= 0x20;
  274. if (high)
  275. break;
  276. if (opcode)
  277. break;
  278. opcode = bytestream2_get_byte(gb);
  279. if (opcode < 0xF8) {
  280. opcode = opcode + 32;
  281. break;
  282. }
  283. i = opcode - 0xF8;
  284. if (i) {
  285. len = 256;
  286. do {
  287. len *= 2;
  288. --i;
  289. } while (i);
  290. } else {
  291. len = 280;
  292. }
  293. do {
  294. bytestream2_put_le32(pb, bytestream2_get_le32(gb));
  295. bytestream2_put_le32(pb, bytestream2_get_le32(gb));
  296. len -= 8;
  297. } while (len && bytestream2_get_bytes_left(gb) > 0);
  298. }
  299. if (!high) {
  300. do {
  301. bytestream2_put_byte(pb, bytestream2_get_byte(gb));
  302. --opcode;
  303. } while (opcode && bytestream2_get_bytes_left(gb) > 0);
  304. while (bytestream2_get_bytes_left(gb) > 0) {
  305. GetByteContext gbc;
  306. opcode = bytestream2_get_byte(gb);
  307. if (opcode >= 0x20)
  308. break;
  309. bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
  310. pos = -(opcode | 32 * bytestream2_get_byte(gb)) - 1;
  311. bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
  312. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  313. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  314. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  315. bytestream2_put_byte(pb, bytestream2_get_byte(gb));
  316. }
  317. }
  318. high = 0;
  319. if (opcode < 0x40)
  320. break;
  321. bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
  322. pos = (-((opcode & 0x1F) | 32 * bytestream2_get_byte(gb)) - 1);
  323. bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
  324. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  325. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  326. len = (opcode >> 5) - 1;
  327. do {
  328. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  329. --len;
  330. } while (len && bytestream2_get_bytes_left(&gbc) > 0);
  331. }
  332. len = opcode & 0x1F;
  333. if (!len) {
  334. if (!bytestream2_peek_byte(gb)) {
  335. do {
  336. bytestream2_skip(gb, 1);
  337. len += 255;
  338. } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
  339. }
  340. len += bytestream2_get_byte(gb) + 31;
  341. }
  342. pos = -bytestream2_get_byte(gb);
  343. bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
  344. bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos - (bytestream2_get_byte(gb) << 8), SEEK_SET);
  345. if (bytestream2_tell_p(pb) == bytestream2_tell(&gbc))
  346. break;
  347. if (len < 5 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
  348. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  349. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  350. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  351. do {
  352. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  353. --len;
  354. } while (len && bytestream2_get_bytes_left(&gbc) > 0);
  355. } else {
  356. bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
  357. len--;
  358. do {
  359. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  360. len--;
  361. } while (len && bytestream2_get_bytes_left(&gbc) > 0);
  362. }
  363. }
  364. return 0;
  365. }
  366. static int decode_frame(AVCodecContext *avctx,
  367. void *data, int *got_frame,
  368. AVPacket *avpkt)
  369. {
  370. FMVCContext *s = avctx->priv_data;
  371. GetByteContext *gb = &s->gb;
  372. PutByteContext *pb = &s->pb;
  373. AVFrame *frame = data;
  374. int ret, y, x;
  375. if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
  376. return ret;
  377. bytestream2_init(gb, avpkt->data, avpkt->size);
  378. bytestream2_skip(gb, 2);
  379. frame->key_frame = !!bytestream2_get_le16(gb);
  380. frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
  381. if (frame->key_frame) {
  382. const uint8_t *src;
  383. int type, size;
  384. uint8_t *dst;
  385. type = bytestream2_get_le16(gb);
  386. size = bytestream2_get_le16(gb);
  387. if (size > bytestream2_get_bytes_left(gb))
  388. return AVERROR_INVALIDDATA;
  389. bytestream2_init_writer(pb, s->buffer, s->buffer_size);
  390. if (type == 1) {
  391. decode_type1(gb, pb);
  392. } else if (type == 2){
  393. decode_type2(gb, pb);
  394. } else {
  395. avpriv_report_missing_feature(avctx, "compression %d", type);
  396. return AVERROR_PATCHWELCOME;
  397. }
  398. src = s->buffer;
  399. dst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
  400. for (y = 0; y < avctx->height; y++) {
  401. memcpy(dst, src, avctx->width * s->bpp);
  402. dst -= frame->linesize[0];
  403. src += s->stride * 4;
  404. }
  405. } else {
  406. int block, nb_blocks, type, k, l;
  407. uint8_t *ssrc, *ddst;
  408. const uint32_t *src;
  409. uint32_t *dst;
  410. for (block = 0; block < s->nb_blocks; block++)
  411. s->blocks[block].xor = 0;
  412. nb_blocks = bytestream2_get_le16(gb);
  413. if (nb_blocks > s->nb_blocks)
  414. return AVERROR_INVALIDDATA;
  415. bytestream2_init_writer(pb, s->pbuffer, s->pbuffer_size);
  416. type = bytestream2_get_le16(gb);
  417. for (block = 0; block < nb_blocks; block++) {
  418. int size, offset, start = 0;
  419. offset = bytestream2_get_le16(gb);
  420. if (offset > s->nb_blocks)
  421. return AVERROR_INVALIDDATA;
  422. size = bytestream2_get_le16(gb);
  423. if (size > bytestream2_get_bytes_left(gb))
  424. return AVERROR_INVALIDDATA;
  425. start = bytestream2_tell_p(pb);
  426. if (type == 1) {
  427. decode_type1(gb, pb);
  428. } else if (type == 2){
  429. decode_type2(gb, pb);
  430. } else {
  431. avpriv_report_missing_feature(avctx, "compression %d", type);
  432. return AVERROR_PATCHWELCOME;
  433. }
  434. if (s->blocks[offset].size * 4 != bytestream2_tell_p(pb) - start)
  435. return AVERROR_INVALIDDATA;
  436. s->blocks[offset].xor = 1;
  437. }
  438. src = (const uint32_t *)s->pbuffer;
  439. dst = (uint32_t *)s->buffer;
  440. for (block = 0, y = 0; y < s->yb; y++) {
  441. int block_h = s->blocks[block].h;
  442. uint32_t *rect = dst;
  443. for (x = 0; x < s->xb; x++) {
  444. int block_w = s->blocks[block].w;
  445. uint32_t *row = dst;
  446. block_h = s->blocks[block].h;
  447. if (s->blocks[block].xor) {
  448. for (k = 0; k < block_h; k++) {
  449. uint32_t *column = dst;
  450. for (l = 0; l < block_w; l++) {
  451. *dst++ ^= *src++;
  452. }
  453. dst = &column[s->stride];
  454. }
  455. }
  456. dst = &row[block_w];
  457. ++block;
  458. }
  459. dst = &rect[block_h * s->stride];
  460. }
  461. ssrc = s->buffer;
  462. ddst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
  463. for (y = 0; y < avctx->height; y++) {
  464. memcpy(ddst, ssrc, avctx->width * s->bpp);
  465. ddst -= frame->linesize[0];
  466. ssrc += s->stride * 4;
  467. }
  468. }
  469. *got_frame = 1;
  470. return avpkt->size;
  471. }
  472. static av_cold int decode_init(AVCodecContext *avctx)
  473. {
  474. FMVCContext *s = avctx->priv_data;
  475. int i, j, m, block = 0, h = BLOCK_HEIGHT, w = BLOCK_WIDTH;
  476. switch (avctx->bits_per_coded_sample) {
  477. case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
  478. case 24: avctx->pix_fmt = AV_PIX_FMT_BGR24; break;
  479. case 32: avctx->pix_fmt = AV_PIX_FMT_BGRA; break;
  480. default:
  481. av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", avctx->bits_per_coded_sample);
  482. return AVERROR_INVALIDDATA;
  483. }
  484. s->stride = (avctx->width * avctx->bits_per_coded_sample + 31) / 32;
  485. s->xb = s->stride / BLOCK_WIDTH;
  486. m = s->stride % BLOCK_WIDTH;
  487. if (m) {
  488. if (m < 37) {
  489. w = m + BLOCK_WIDTH;
  490. } else {
  491. w = m;
  492. s->xb++;
  493. }
  494. }
  495. s->yb = avctx->height / BLOCK_HEIGHT;
  496. m = avctx->height % BLOCK_HEIGHT;
  497. if (m) {
  498. if (m < 49) {
  499. h = m + BLOCK_HEIGHT;
  500. } else {
  501. h = m;
  502. s->yb++;
  503. }
  504. }
  505. s->nb_blocks = s->xb * s->yb;
  506. s->blocks = av_calloc(s->nb_blocks, sizeof(*s->blocks));
  507. if (!s->blocks)
  508. return AVERROR(ENOMEM);
  509. for (i = 0; i < s->yb; i++) {
  510. for (j = 0; j < s->xb; j++) {
  511. if (i != (s->yb - 1) || j != (s->xb - 1)) {
  512. if (i == s->yb - 1) {
  513. s->blocks[block].w = BLOCK_WIDTH;
  514. s->blocks[block].h = h;
  515. s->blocks[block].size = BLOCK_WIDTH * h;
  516. } else if (j == s->xb - 1) {
  517. s->blocks[block].w = w;
  518. s->blocks[block].h = BLOCK_HEIGHT;
  519. s->blocks[block].size = BLOCK_HEIGHT * w;
  520. } else {
  521. s->blocks[block].w = BLOCK_WIDTH;
  522. s->blocks[block].h = BLOCK_HEIGHT;
  523. s->blocks[block].size = BLOCK_WIDTH * BLOCK_HEIGHT;
  524. }
  525. } else {
  526. s->blocks[block].w = w;
  527. s->blocks[block].h = h;
  528. s->blocks[block].size = w * h;
  529. }
  530. block++;
  531. }
  532. }
  533. s->bpp = avctx->bits_per_coded_sample >> 3;
  534. s->buffer_size = avctx->width * avctx->height * 4;
  535. s->pbuffer_size = avctx->width * avctx->height * 4;
  536. s->buffer = av_malloc(s->buffer_size);
  537. s->pbuffer = av_malloc(s->pbuffer_size);
  538. if (!s->buffer || !s->pbuffer)
  539. return AVERROR(ENOMEM);
  540. return 0;
  541. }
  542. static av_cold int decode_close(AVCodecContext *avctx)
  543. {
  544. FMVCContext *s = avctx->priv_data;
  545. av_freep(&s->buffer);
  546. av_freep(&s->pbuffer);
  547. av_freep(&s->blocks);
  548. return 0;
  549. }
  550. AVCodec ff_fmvc_decoder = {
  551. .name = "fmvc",
  552. .long_name = NULL_IF_CONFIG_SMALL("FM Screen Capture Codec"),
  553. .type = AVMEDIA_TYPE_VIDEO,
  554. .id = AV_CODEC_ID_FMVC,
  555. .priv_data_size = sizeof(FMVCContext),
  556. .init = decode_init,
  557. .close = decode_close,
  558. .decode = decode_frame,
  559. .capabilities = AV_CODEC_CAP_DR1,
  560. .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
  561. FF_CODEC_CAP_INIT_CLEANUP,
  562. };