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.

634 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 = 0;
  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 = 0, 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. } else {
  352. bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
  353. len--;
  354. }
  355. do {
  356. bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
  357. len--;
  358. } while (len && bytestream2_get_bytes_left(&gbc) > 0);
  359. }
  360. return 0;
  361. }
  362. static int decode_frame(AVCodecContext *avctx,
  363. void *data, int *got_frame,
  364. AVPacket *avpkt)
  365. {
  366. FMVCContext *s = avctx->priv_data;
  367. GetByteContext *gb = &s->gb;
  368. PutByteContext *pb = &s->pb;
  369. AVFrame *frame = data;
  370. int ret, y, x;
  371. if (avpkt->size < 8)
  372. return AVERROR_INVALIDDATA;
  373. if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
  374. return ret;
  375. bytestream2_init(gb, avpkt->data, avpkt->size);
  376. bytestream2_skip(gb, 2);
  377. frame->key_frame = !!bytestream2_get_le16(gb);
  378. frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
  379. if (frame->key_frame) {
  380. const uint8_t *src;
  381. int type, size;
  382. uint8_t *dst;
  383. type = bytestream2_get_le16(gb);
  384. size = bytestream2_get_le16(gb);
  385. if (size > bytestream2_get_bytes_left(gb))
  386. return AVERROR_INVALIDDATA;
  387. bytestream2_init_writer(pb, s->buffer, s->buffer_size);
  388. if (type == 1) {
  389. decode_type1(gb, pb);
  390. } else if (type == 2){
  391. decode_type2(gb, pb);
  392. } else {
  393. avpriv_report_missing_feature(avctx, "compression %d", type);
  394. return AVERROR_PATCHWELCOME;
  395. }
  396. src = s->buffer;
  397. dst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
  398. for (y = 0; y < avctx->height; y++) {
  399. memcpy(dst, src, avctx->width * s->bpp);
  400. dst -= frame->linesize[0];
  401. src += s->stride * 4;
  402. }
  403. } else {
  404. int block, nb_blocks, type, k, l;
  405. uint8_t *ssrc, *ddst;
  406. const uint32_t *src;
  407. uint32_t *dst;
  408. for (block = 0; block < s->nb_blocks; block++)
  409. s->blocks[block].xor = 0;
  410. nb_blocks = bytestream2_get_le16(gb);
  411. if (nb_blocks > s->nb_blocks)
  412. return AVERROR_INVALIDDATA;
  413. bytestream2_init_writer(pb, s->pbuffer, s->pbuffer_size);
  414. type = bytestream2_get_le16(gb);
  415. for (block = 0; block < nb_blocks; block++) {
  416. int size, offset, start = 0;
  417. offset = bytestream2_get_le16(gb);
  418. if (offset >= s->nb_blocks)
  419. return AVERROR_INVALIDDATA;
  420. size = bytestream2_get_le16(gb);
  421. if (size > bytestream2_get_bytes_left(gb))
  422. return AVERROR_INVALIDDATA;
  423. start = bytestream2_tell_p(pb);
  424. if (type == 1) {
  425. decode_type1(gb, pb);
  426. } else if (type == 2){
  427. decode_type2(gb, pb);
  428. } else {
  429. avpriv_report_missing_feature(avctx, "compression %d", type);
  430. return AVERROR_PATCHWELCOME;
  431. }
  432. if (s->blocks[offset].size * 4 != bytestream2_tell_p(pb) - start)
  433. return AVERROR_INVALIDDATA;
  434. s->blocks[offset].xor = 1;
  435. }
  436. src = (const uint32_t *)s->pbuffer;
  437. dst = (uint32_t *)s->buffer;
  438. for (block = 0, y = 0; y < s->yb; y++) {
  439. int block_h = s->blocks[block].h;
  440. uint32_t *rect = dst;
  441. for (x = 0; x < s->xb; x++) {
  442. int block_w = s->blocks[block].w;
  443. uint32_t *row = dst;
  444. block_h = s->blocks[block].h;
  445. if (s->blocks[block].xor) {
  446. for (k = 0; k < block_h; k++) {
  447. uint32_t *column = dst;
  448. for (l = 0; l < block_w; l++) {
  449. *dst++ ^= *src++;
  450. }
  451. dst = &column[s->stride];
  452. }
  453. }
  454. dst = &row[block_w];
  455. ++block;
  456. }
  457. dst = &rect[block_h * s->stride];
  458. }
  459. ssrc = s->buffer;
  460. ddst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
  461. for (y = 0; y < avctx->height; y++) {
  462. memcpy(ddst, ssrc, avctx->width * s->bpp);
  463. ddst -= frame->linesize[0];
  464. ssrc += s->stride * 4;
  465. }
  466. }
  467. *got_frame = 1;
  468. return avpkt->size;
  469. }
  470. static av_cold int decode_init(AVCodecContext *avctx)
  471. {
  472. FMVCContext *s = avctx->priv_data;
  473. int i, j, m, block = 0, h = BLOCK_HEIGHT, w = BLOCK_WIDTH;
  474. switch (avctx->bits_per_coded_sample) {
  475. case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
  476. case 24: avctx->pix_fmt = AV_PIX_FMT_BGR24; break;
  477. case 32: avctx->pix_fmt = AV_PIX_FMT_BGRA; break;
  478. default:
  479. av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", avctx->bits_per_coded_sample);
  480. return AVERROR_INVALIDDATA;
  481. }
  482. s->stride = (avctx->width * avctx->bits_per_coded_sample + 31) / 32;
  483. s->xb = s->stride / BLOCK_WIDTH;
  484. m = s->stride % BLOCK_WIDTH;
  485. if (m) {
  486. if (m < 37) {
  487. w = m + BLOCK_WIDTH;
  488. } else {
  489. w = m;
  490. s->xb++;
  491. }
  492. }
  493. s->yb = avctx->height / BLOCK_HEIGHT;
  494. m = avctx->height % BLOCK_HEIGHT;
  495. if (m) {
  496. if (m < 49) {
  497. h = m + BLOCK_HEIGHT;
  498. } else {
  499. h = m;
  500. s->yb++;
  501. }
  502. }
  503. s->nb_blocks = s->xb * s->yb;
  504. if (!s->nb_blocks)
  505. return AVERROR_INVALIDDATA;
  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_mallocz(s->buffer_size);
  537. s->pbuffer = av_mallocz(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. };