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.

637 lines
22KB

  1. /*
  2. * FM Screen Capture Codec decoder
  3. *
  4. * Copyright (c) 2017 Paul B Mahol
  5. *
  6. * This file is part of Libav.
  7. *
  8. * Libav 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. * Libav 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 Libav; 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. ptrdiff_t stride;
  43. int bpp;
  44. int yb, xb;
  45. InterBlock *blocks;
  46. unsigned 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 += 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, void *data,
  363. int *got_frame, AVPacket *avpkt)
  364. {
  365. FMVCContext *s = avctx->priv_data;
  366. GetByteContext *gb = &s->gb;
  367. PutByteContext *pb = &s->pb;
  368. AVFrame *frame = data;
  369. int ret, y, x;
  370. if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
  371. return ret;
  372. bytestream2_init(gb, avpkt->data, avpkt->size);
  373. bytestream2_skip(gb, 2);
  374. frame->key_frame = !!bytestream2_get_le16(gb);
  375. frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
  376. if (frame->key_frame) {
  377. const uint8_t *src;
  378. unsigned type, size;
  379. uint8_t *dst;
  380. type = bytestream2_get_le16(gb);
  381. size = bytestream2_get_le16(gb);
  382. if (size > bytestream2_get_bytes_left(gb))
  383. return AVERROR_INVALIDDATA;
  384. bytestream2_init_writer(pb, s->buffer, s->buffer_size);
  385. if (type == 1) {
  386. decode_type1(gb, pb);
  387. } else if (type == 2){
  388. decode_type2(gb, pb);
  389. } else {
  390. avpriv_report_missing_feature(avctx, "Compression type %d", type);
  391. return AVERROR_PATCHWELCOME;
  392. }
  393. src = s->buffer;
  394. dst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
  395. for (y = 0; y < avctx->height; y++) {
  396. memcpy(dst, src, avctx->width * s->bpp);
  397. dst -= frame->linesize[0];
  398. src += avctx->width * s->bpp;
  399. }
  400. } else {
  401. unsigned block, nb_blocks;
  402. int type, k, l;
  403. uint8_t *ssrc, *ddst;
  404. const uint32_t *src;
  405. uint32_t *dst;
  406. for (block = 0; block < s->nb_blocks; block++)
  407. s->blocks[block].xor = 0;
  408. nb_blocks = bytestream2_get_le16(gb);
  409. if (nb_blocks > s->nb_blocks)
  410. return AVERROR_INVALIDDATA;
  411. bytestream2_init_writer(pb, s->pbuffer, s->pbuffer_size);
  412. type = bytestream2_get_le16(gb);
  413. for (block = 0; block < nb_blocks; block++) {
  414. unsigned size, offset;
  415. int start = 0;
  416. offset = bytestream2_get_le16(gb);
  417. if (offset > s->nb_blocks)
  418. return AVERROR_INVALIDDATA;
  419. size = bytestream2_get_le16(gb);
  420. if (size > bytestream2_get_bytes_left(gb))
  421. return AVERROR_INVALIDDATA;
  422. start = bytestream2_tell_p(pb);
  423. if (type == 1) {
  424. decode_type1(gb, pb);
  425. } else if (type == 2){
  426. decode_type2(gb, pb);
  427. } else {
  428. avpriv_report_missing_feature(avctx, "Compression type %d", type);
  429. return AVERROR_PATCHWELCOME;
  430. }
  431. if (s->blocks[offset].size * 4 != bytestream2_tell_p(pb) - start)
  432. return AVERROR_INVALIDDATA;
  433. s->blocks[offset].xor = 1;
  434. }
  435. src = (const uint32_t *)s->pbuffer;
  436. dst = (uint32_t *)s->buffer;
  437. for (block = 0, y = 0; y < s->yb; y++) {
  438. int block_h = s->blocks[block].h;
  439. uint32_t *rect = dst;
  440. for (x = 0; x < s->xb; x++) {
  441. int block_w = s->blocks[block].w;
  442. uint32_t *row = dst;
  443. block_h = s->blocks[block].h;
  444. if (s->blocks[block].xor) {
  445. for (k = 0; k < block_h; k++) {
  446. uint32_t *column = dst;
  447. for (l = 0; l < block_w; l++)
  448. *dst++ ^= *src++;
  449. dst = &column[s->stride];
  450. }
  451. }
  452. dst = &row[block_w];
  453. ++block;
  454. }
  455. dst = &rect[block_h * s->stride];
  456. }
  457. ssrc = s->buffer;
  458. ddst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
  459. for (y = 0; y < avctx->height; y++) {
  460. memcpy(ddst, ssrc, avctx->width * s->bpp);
  461. ddst -= frame->linesize[0];
  462. ssrc += avctx->width * s->bpp;
  463. }
  464. }
  465. *got_frame = 1;
  466. return avpkt->size;
  467. }
  468. static av_cold int decode_init(AVCodecContext *avctx)
  469. {
  470. FMVCContext *s = avctx->priv_data;
  471. int i, j, m, block = 0, h = BLOCK_HEIGHT, w = BLOCK_WIDTH;
  472. switch (avctx->bits_per_coded_sample) {
  473. case 16:
  474. avctx->pix_fmt = AV_PIX_FMT_RGB555;
  475. break;
  476. case 24:
  477. avctx->pix_fmt = AV_PIX_FMT_BGR24;
  478. break;
  479. case 32:
  480. avctx->pix_fmt = AV_PIX_FMT_BGRA;
  481. break;
  482. default:
  483. av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n",
  484. avctx->bits_per_coded_sample);
  485. return AVERROR_INVALIDDATA;
  486. }
  487. s->stride = (avctx->width * avctx->bits_per_coded_sample + 31) / 32;
  488. s->xb = s->stride / BLOCK_WIDTH;
  489. m = s->stride % BLOCK_WIDTH;
  490. if (m) {
  491. if (m < 37) {
  492. w = m + BLOCK_WIDTH;
  493. } else {
  494. w = m;
  495. s->xb++;
  496. }
  497. }
  498. s->yb = avctx->height / BLOCK_HEIGHT;
  499. m = avctx->height % BLOCK_HEIGHT;
  500. if (m) {
  501. if (m < 49) {
  502. h = m + BLOCK_HEIGHT;
  503. } else {
  504. h = m;
  505. s->yb++;
  506. }
  507. }
  508. s->nb_blocks = s->xb * s->yb;
  509. if (!s->nb_blocks)
  510. return AVERROR_INVALIDDATA;
  511. s->blocks = av_mallocz(s->nb_blocks * sizeof(*s->blocks));
  512. if (!s->blocks)
  513. return AVERROR(ENOMEM);
  514. for (i = 0; i < s->yb; i++) {
  515. for (j = 0; j < s->xb; j++) {
  516. if (i != (s->yb - 1) || j != (s->xb - 1)) {
  517. if (i == s->yb - 1) {
  518. s->blocks[block].w = BLOCK_WIDTH;
  519. s->blocks[block].h = h;
  520. s->blocks[block].size = BLOCK_WIDTH * h;
  521. } else if (j == s->xb - 1) {
  522. s->blocks[block].w = w;
  523. s->blocks[block].h = BLOCK_HEIGHT;
  524. s->blocks[block].size = BLOCK_HEIGHT * w;
  525. } else {
  526. s->blocks[block].w = BLOCK_WIDTH;
  527. s->blocks[block].h = BLOCK_HEIGHT;
  528. s->blocks[block].size = BLOCK_WIDTH * BLOCK_HEIGHT;
  529. }
  530. } else {
  531. s->blocks[block].w = w;
  532. s->blocks[block].h = h;
  533. s->blocks[block].size = w * h;
  534. }
  535. block++;
  536. }
  537. }
  538. s->bpp = avctx->bits_per_coded_sample >> 3;
  539. s->buffer_size = avctx->width * avctx->height * 4;
  540. s->pbuffer_size = avctx->width * avctx->height * 4;
  541. s->buffer = av_malloc(s->buffer_size);
  542. s->pbuffer = av_malloc(s->pbuffer_size);
  543. if (!s->buffer || !s->pbuffer)
  544. return AVERROR(ENOMEM);
  545. return 0;
  546. }
  547. static av_cold int decode_close(AVCodecContext *avctx)
  548. {
  549. FMVCContext *s = avctx->priv_data;
  550. av_freep(&s->buffer);
  551. av_freep(&s->pbuffer);
  552. av_freep(&s->blocks);
  553. return 0;
  554. }
  555. AVCodec ff_fmvc_decoder = {
  556. .name = "fmvc",
  557. .long_name = NULL_IF_CONFIG_SMALL("FM Screen Capture Codec"),
  558. .type = AVMEDIA_TYPE_VIDEO,
  559. .id = AV_CODEC_ID_FMVC,
  560. .priv_data_size = sizeof(FMVCContext),
  561. .init = decode_init,
  562. .close = decode_close,
  563. .decode = decode_frame,
  564. .capabilities = AV_CODEC_CAP_DR1,
  565. .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
  566. FF_CODEC_CAP_INIT_CLEANUP,
  567. };