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.

810 lines
21KB

  1. /*
  2. * This file is part of FFmpeg.
  3. *
  4. * FFmpeg is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * FFmpeg is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with FFmpeg; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include <string.h>
  19. #include "config.h"
  20. #include "libavutil/avassert.h"
  21. #include "libavutil/buffer.h"
  22. #include "libavutil/common.h"
  23. #include "cbs.h"
  24. #include "cbs_internal.h"
  25. static const CodedBitstreamType *cbs_type_table[] = {
  26. #if CONFIG_CBS_AV1
  27. &ff_cbs_type_av1,
  28. #endif
  29. #if CONFIG_CBS_H264
  30. &ff_cbs_type_h264,
  31. #endif
  32. #if CONFIG_CBS_H265
  33. &ff_cbs_type_h265,
  34. #endif
  35. #if CONFIG_CBS_JPEG
  36. &ff_cbs_type_jpeg,
  37. #endif
  38. #if CONFIG_CBS_MPEG2
  39. &ff_cbs_type_mpeg2,
  40. #endif
  41. #if CONFIG_CBS_VP9
  42. &ff_cbs_type_vp9,
  43. #endif
  44. };
  45. const enum AVCodecID ff_cbs_all_codec_ids[] = {
  46. #if CONFIG_CBS_AV1
  47. AV_CODEC_ID_AV1,
  48. #endif
  49. #if CONFIG_CBS_H264
  50. AV_CODEC_ID_H264,
  51. #endif
  52. #if CONFIG_CBS_H265
  53. AV_CODEC_ID_H265,
  54. #endif
  55. #if CONFIG_CBS_JPEG
  56. AV_CODEC_ID_MJPEG,
  57. #endif
  58. #if CONFIG_CBS_MPEG2
  59. AV_CODEC_ID_MPEG2VIDEO,
  60. #endif
  61. #if CONFIG_CBS_VP9
  62. AV_CODEC_ID_VP9,
  63. #endif
  64. AV_CODEC_ID_NONE
  65. };
  66. int ff_cbs_init(CodedBitstreamContext **ctx_ptr,
  67. enum AVCodecID codec_id, void *log_ctx)
  68. {
  69. CodedBitstreamContext *ctx;
  70. const CodedBitstreamType *type;
  71. int i;
  72. type = NULL;
  73. for (i = 0; i < FF_ARRAY_ELEMS(cbs_type_table); i++) {
  74. if (cbs_type_table[i]->codec_id == codec_id) {
  75. type = cbs_type_table[i];
  76. break;
  77. }
  78. }
  79. if (!type)
  80. return AVERROR(EINVAL);
  81. ctx = av_mallocz(sizeof(*ctx));
  82. if (!ctx)
  83. return AVERROR(ENOMEM);
  84. ctx->log_ctx = log_ctx;
  85. ctx->codec = type;
  86. if (type->priv_data_size) {
  87. ctx->priv_data = av_mallocz(ctx->codec->priv_data_size);
  88. if (!ctx->priv_data) {
  89. av_freep(&ctx);
  90. return AVERROR(ENOMEM);
  91. }
  92. }
  93. ctx->decompose_unit_types = NULL;
  94. ctx->trace_enable = 0;
  95. ctx->trace_level = AV_LOG_TRACE;
  96. *ctx_ptr = ctx;
  97. return 0;
  98. }
  99. void ff_cbs_close(CodedBitstreamContext **ctx_ptr)
  100. {
  101. CodedBitstreamContext *ctx = *ctx_ptr;
  102. if (!ctx)
  103. return;
  104. if (ctx->codec && ctx->codec->close)
  105. ctx->codec->close(ctx);
  106. av_freep(&ctx->write_buffer);
  107. av_freep(&ctx->priv_data);
  108. av_freep(ctx_ptr);
  109. }
  110. static void cbs_unit_uninit(CodedBitstreamContext *ctx,
  111. CodedBitstreamUnit *unit)
  112. {
  113. av_buffer_unref(&unit->content_ref);
  114. unit->content = NULL;
  115. av_buffer_unref(&unit->data_ref);
  116. unit->data = NULL;
  117. unit->data_size = 0;
  118. unit->data_bit_padding = 0;
  119. }
  120. void ff_cbs_fragment_reset(CodedBitstreamContext *ctx,
  121. CodedBitstreamFragment *frag)
  122. {
  123. int i;
  124. for (i = 0; i < frag->nb_units; i++)
  125. cbs_unit_uninit(ctx, &frag->units[i]);
  126. frag->nb_units = 0;
  127. av_buffer_unref(&frag->data_ref);
  128. frag->data = NULL;
  129. frag->data_size = 0;
  130. frag->data_bit_padding = 0;
  131. }
  132. void ff_cbs_fragment_free(CodedBitstreamContext *ctx,
  133. CodedBitstreamFragment *frag)
  134. {
  135. ff_cbs_fragment_reset(ctx, frag);
  136. av_freep(&frag->units);
  137. frag->nb_units_allocated = 0;
  138. }
  139. static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
  140. CodedBitstreamFragment *frag)
  141. {
  142. int err, i, j;
  143. for (i = 0; i < frag->nb_units; i++) {
  144. CodedBitstreamUnit *unit = &frag->units[i];
  145. if (ctx->decompose_unit_types) {
  146. for (j = 0; j < ctx->nb_decompose_unit_types; j++) {
  147. if (ctx->decompose_unit_types[j] == unit->type)
  148. break;
  149. }
  150. if (j >= ctx->nb_decompose_unit_types)
  151. continue;
  152. }
  153. av_buffer_unref(&unit->content_ref);
  154. unit->content = NULL;
  155. av_assert0(unit->data && unit->data_ref);
  156. err = ctx->codec->read_unit(ctx, unit);
  157. if (err == AVERROR(ENOSYS)) {
  158. av_log(ctx->log_ctx, AV_LOG_VERBOSE,
  159. "Decomposition unimplemented for unit %d "
  160. "(type %"PRIu32").\n", i, unit->type);
  161. } else if (err < 0) {
  162. av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d "
  163. "(type %"PRIu32").\n", i, unit->type);
  164. return err;
  165. }
  166. }
  167. return 0;
  168. }
  169. static int cbs_fill_fragment_data(CodedBitstreamContext *ctx,
  170. CodedBitstreamFragment *frag,
  171. const uint8_t *data, size_t size)
  172. {
  173. av_assert0(!frag->data && !frag->data_ref);
  174. frag->data_ref =
  175. av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
  176. if (!frag->data_ref)
  177. return AVERROR(ENOMEM);
  178. frag->data = frag->data_ref->data;
  179. frag->data_size = size;
  180. memcpy(frag->data, data, size);
  181. memset(frag->data + size, 0,
  182. AV_INPUT_BUFFER_PADDING_SIZE);
  183. return 0;
  184. }
  185. int ff_cbs_read_extradata(CodedBitstreamContext *ctx,
  186. CodedBitstreamFragment *frag,
  187. const AVCodecParameters *par)
  188. {
  189. int err;
  190. err = cbs_fill_fragment_data(ctx, frag, par->extradata,
  191. par->extradata_size);
  192. if (err < 0)
  193. return err;
  194. err = ctx->codec->split_fragment(ctx, frag, 1);
  195. if (err < 0)
  196. return err;
  197. return cbs_read_fragment_content(ctx, frag);
  198. }
  199. int ff_cbs_read_packet(CodedBitstreamContext *ctx,
  200. CodedBitstreamFragment *frag,
  201. const AVPacket *pkt)
  202. {
  203. int err;
  204. if (pkt->buf) {
  205. frag->data_ref = av_buffer_ref(pkt->buf);
  206. if (!frag->data_ref)
  207. return AVERROR(ENOMEM);
  208. frag->data = pkt->data;
  209. frag->data_size = pkt->size;
  210. } else {
  211. err = cbs_fill_fragment_data(ctx, frag, pkt->data, pkt->size);
  212. if (err < 0)
  213. return err;
  214. }
  215. err = ctx->codec->split_fragment(ctx, frag, 0);
  216. if (err < 0)
  217. return err;
  218. return cbs_read_fragment_content(ctx, frag);
  219. }
  220. int ff_cbs_read(CodedBitstreamContext *ctx,
  221. CodedBitstreamFragment *frag,
  222. const uint8_t *data, size_t size)
  223. {
  224. int err;
  225. err = cbs_fill_fragment_data(ctx, frag, data, size);
  226. if (err < 0)
  227. return err;
  228. err = ctx->codec->split_fragment(ctx, frag, 0);
  229. if (err < 0)
  230. return err;
  231. return cbs_read_fragment_content(ctx, frag);
  232. }
  233. static int cbs_write_unit_data(CodedBitstreamContext *ctx,
  234. CodedBitstreamUnit *unit)
  235. {
  236. PutBitContext pbc;
  237. int ret;
  238. if (!ctx->write_buffer) {
  239. // Initial write buffer size is 1MB.
  240. ctx->write_buffer_size = 1024 * 1024;
  241. reallocate_and_try_again:
  242. ret = av_reallocp(&ctx->write_buffer, ctx->write_buffer_size);
  243. if (ret < 0) {
  244. av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a "
  245. "sufficiently large write buffer (last attempt "
  246. "%"SIZE_SPECIFIER" bytes).\n", ctx->write_buffer_size);
  247. return ret;
  248. }
  249. }
  250. init_put_bits(&pbc, ctx->write_buffer, ctx->write_buffer_size);
  251. ret = ctx->codec->write_unit(ctx, unit, &pbc);
  252. if (ret < 0) {
  253. if (ret == AVERROR(ENOSPC)) {
  254. // Overflow.
  255. ctx->write_buffer_size *= 2;
  256. goto reallocate_and_try_again;
  257. }
  258. // Write failed for some other reason.
  259. return ret;
  260. }
  261. // Overflow but we didn't notice.
  262. av_assert0(put_bits_count(&pbc) <= 8 * ctx->write_buffer_size);
  263. if (put_bits_count(&pbc) % 8)
  264. unit->data_bit_padding = 8 - put_bits_count(&pbc) % 8;
  265. else
  266. unit->data_bit_padding = 0;
  267. flush_put_bits(&pbc);
  268. ret = ff_cbs_alloc_unit_data(ctx, unit, put_bits_count(&pbc) / 8);
  269. if (ret < 0)
  270. return ret;
  271. memcpy(unit->data, ctx->write_buffer, unit->data_size);
  272. return 0;
  273. }
  274. int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
  275. CodedBitstreamFragment *frag)
  276. {
  277. int err, i;
  278. for (i = 0; i < frag->nb_units; i++) {
  279. CodedBitstreamUnit *unit = &frag->units[i];
  280. if (!unit->content)
  281. continue;
  282. av_buffer_unref(&unit->data_ref);
  283. unit->data = NULL;
  284. err = cbs_write_unit_data(ctx, unit);
  285. if (err < 0) {
  286. av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d "
  287. "(type %"PRIu32").\n", i, unit->type);
  288. return err;
  289. }
  290. av_assert0(unit->data && unit->data_ref);
  291. }
  292. av_buffer_unref(&frag->data_ref);
  293. frag->data = NULL;
  294. err = ctx->codec->assemble_fragment(ctx, frag);
  295. if (err < 0) {
  296. av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to assemble fragment.\n");
  297. return err;
  298. }
  299. av_assert0(frag->data && frag->data_ref);
  300. return 0;
  301. }
  302. int ff_cbs_write_extradata(CodedBitstreamContext *ctx,
  303. AVCodecParameters *par,
  304. CodedBitstreamFragment *frag)
  305. {
  306. int err;
  307. err = ff_cbs_write_fragment_data(ctx, frag);
  308. if (err < 0)
  309. return err;
  310. av_freep(&par->extradata);
  311. par->extradata = av_malloc(frag->data_size +
  312. AV_INPUT_BUFFER_PADDING_SIZE);
  313. if (!par->extradata)
  314. return AVERROR(ENOMEM);
  315. memcpy(par->extradata, frag->data, frag->data_size);
  316. memset(par->extradata + frag->data_size, 0,
  317. AV_INPUT_BUFFER_PADDING_SIZE);
  318. par->extradata_size = frag->data_size;
  319. return 0;
  320. }
  321. int ff_cbs_write_packet(CodedBitstreamContext *ctx,
  322. AVPacket *pkt,
  323. CodedBitstreamFragment *frag)
  324. {
  325. AVBufferRef *buf;
  326. int err;
  327. err = ff_cbs_write_fragment_data(ctx, frag);
  328. if (err < 0)
  329. return err;
  330. buf = av_buffer_ref(frag->data_ref);
  331. if (!buf)
  332. return AVERROR(ENOMEM);
  333. av_buffer_unref(&pkt->buf);
  334. pkt->buf = buf;
  335. pkt->data = frag->data;
  336. pkt->size = frag->data_size;
  337. return 0;
  338. }
  339. void ff_cbs_trace_header(CodedBitstreamContext *ctx,
  340. const char *name)
  341. {
  342. if (!ctx->trace_enable)
  343. return;
  344. av_log(ctx->log_ctx, ctx->trace_level, "%s\n", name);
  345. }
  346. void ff_cbs_trace_syntax_element(CodedBitstreamContext *ctx, int position,
  347. const char *str, const int *subscripts,
  348. const char *bits, int64_t value)
  349. {
  350. char name[256];
  351. size_t name_len, bits_len;
  352. int pad, subs, i, j, k, n;
  353. if (!ctx->trace_enable)
  354. return;
  355. av_assert0(value >= INT_MIN && value <= UINT32_MAX);
  356. subs = subscripts ? subscripts[0] : 0;
  357. n = 0;
  358. for (i = j = 0; str[i];) {
  359. if (str[i] == '[') {
  360. if (n < subs) {
  361. ++n;
  362. k = snprintf(name + j, sizeof(name) - j, "[%d", subscripts[n]);
  363. av_assert0(k > 0 && j + k < sizeof(name));
  364. j += k;
  365. for (++i; str[i] && str[i] != ']'; i++);
  366. av_assert0(str[i] == ']');
  367. } else {
  368. while (str[i] && str[i] != ']')
  369. name[j++] = str[i++];
  370. av_assert0(str[i] == ']');
  371. }
  372. } else {
  373. av_assert0(j + 1 < sizeof(name));
  374. name[j++] = str[i++];
  375. }
  376. }
  377. av_assert0(j + 1 < sizeof(name));
  378. name[j] = 0;
  379. av_assert0(n == subs);
  380. name_len = strlen(name);
  381. bits_len = strlen(bits);
  382. if (name_len + bits_len > 60)
  383. pad = bits_len + 2;
  384. else
  385. pad = 61 - name_len;
  386. av_log(ctx->log_ctx, ctx->trace_level, "%-10d %s%*s = %"PRId64"\n",
  387. position, name, pad, bits, value);
  388. }
  389. int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, GetBitContext *gbc,
  390. int width, const char *name,
  391. const int *subscripts, uint32_t *write_to,
  392. uint32_t range_min, uint32_t range_max)
  393. {
  394. uint32_t value;
  395. int position;
  396. av_assert0(width > 0 && width <= 32);
  397. if (get_bits_left(gbc) < width) {
  398. av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at "
  399. "%s: bitstream ended.\n", name);
  400. return AVERROR_INVALIDDATA;
  401. }
  402. if (ctx->trace_enable)
  403. position = get_bits_count(gbc);
  404. value = get_bits_long(gbc, width);
  405. if (ctx->trace_enable) {
  406. char bits[33];
  407. int i;
  408. for (i = 0; i < width; i++)
  409. bits[i] = value >> (width - i - 1) & 1 ? '1' : '0';
  410. bits[i] = 0;
  411. ff_cbs_trace_syntax_element(ctx, position, name, subscripts,
  412. bits, value);
  413. }
  414. if (value < range_min || value > range_max) {
  415. av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
  416. "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
  417. name, value, range_min, range_max);
  418. return AVERROR_INVALIDDATA;
  419. }
  420. *write_to = value;
  421. return 0;
  422. }
  423. int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
  424. int width, const char *name,
  425. const int *subscripts, uint32_t value,
  426. uint32_t range_min, uint32_t range_max)
  427. {
  428. av_assert0(width > 0 && width <= 32);
  429. if (value < range_min || value > range_max) {
  430. av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
  431. "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
  432. name, value, range_min, range_max);
  433. return AVERROR_INVALIDDATA;
  434. }
  435. if (put_bits_left(pbc) < width)
  436. return AVERROR(ENOSPC);
  437. if (ctx->trace_enable) {
  438. char bits[33];
  439. int i;
  440. for (i = 0; i < width; i++)
  441. bits[i] = value >> (width - i - 1) & 1 ? '1' : '0';
  442. bits[i] = 0;
  443. ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc),
  444. name, subscripts, bits, value);
  445. }
  446. if (width < 32)
  447. put_bits(pbc, width, value);
  448. else
  449. put_bits32(pbc, value);
  450. return 0;
  451. }
  452. int ff_cbs_read_signed(CodedBitstreamContext *ctx, GetBitContext *gbc,
  453. int width, const char *name,
  454. const int *subscripts, int32_t *write_to,
  455. int32_t range_min, int32_t range_max)
  456. {
  457. int32_t value;
  458. int position;
  459. av_assert0(width > 0 && width <= 32);
  460. if (get_bits_left(gbc) < width) {
  461. av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at "
  462. "%s: bitstream ended.\n", name);
  463. return AVERROR_INVALIDDATA;
  464. }
  465. if (ctx->trace_enable)
  466. position = get_bits_count(gbc);
  467. value = get_sbits_long(gbc, width);
  468. if (ctx->trace_enable) {
  469. char bits[33];
  470. int i;
  471. for (i = 0; i < width; i++)
  472. bits[i] = value & (1U << (width - i - 1)) ? '1' : '0';
  473. bits[i] = 0;
  474. ff_cbs_trace_syntax_element(ctx, position, name, subscripts,
  475. bits, value);
  476. }
  477. if (value < range_min || value > range_max) {
  478. av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
  479. "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n",
  480. name, value, range_min, range_max);
  481. return AVERROR_INVALIDDATA;
  482. }
  483. *write_to = value;
  484. return 0;
  485. }
  486. int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc,
  487. int width, const char *name,
  488. const int *subscripts, int32_t value,
  489. int32_t range_min, int32_t range_max)
  490. {
  491. av_assert0(width > 0 && width <= 32);
  492. if (value < range_min || value > range_max) {
  493. av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
  494. "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n",
  495. name, value, range_min, range_max);
  496. return AVERROR_INVALIDDATA;
  497. }
  498. if (put_bits_left(pbc) < width)
  499. return AVERROR(ENOSPC);
  500. if (ctx->trace_enable) {
  501. char bits[33];
  502. int i;
  503. for (i = 0; i < width; i++)
  504. bits[i] = value & (1U << (width - i - 1)) ? '1' : '0';
  505. bits[i] = 0;
  506. ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc),
  507. name, subscripts, bits, value);
  508. }
  509. if (width < 32)
  510. put_sbits(pbc, width, value);
  511. else
  512. put_bits32(pbc, value);
  513. return 0;
  514. }
  515. int ff_cbs_alloc_unit_content(CodedBitstreamContext *ctx,
  516. CodedBitstreamUnit *unit,
  517. size_t size,
  518. void (*free)(void *opaque, uint8_t *data))
  519. {
  520. av_assert0(!unit->content && !unit->content_ref);
  521. unit->content = av_mallocz(size);
  522. if (!unit->content)
  523. return AVERROR(ENOMEM);
  524. unit->content_ref = av_buffer_create(unit->content, size,
  525. free, ctx, 0);
  526. if (!unit->content_ref) {
  527. av_freep(&unit->content);
  528. return AVERROR(ENOMEM);
  529. }
  530. return 0;
  531. }
  532. int ff_cbs_alloc_unit_data(CodedBitstreamContext *ctx,
  533. CodedBitstreamUnit *unit,
  534. size_t size)
  535. {
  536. av_assert0(!unit->data && !unit->data_ref);
  537. unit->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
  538. if (!unit->data_ref)
  539. return AVERROR(ENOMEM);
  540. unit->data = unit->data_ref->data;
  541. unit->data_size = size;
  542. memset(unit->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
  543. return 0;
  544. }
  545. static int cbs_insert_unit(CodedBitstreamContext *ctx,
  546. CodedBitstreamFragment *frag,
  547. int position)
  548. {
  549. CodedBitstreamUnit *units;
  550. if (frag->nb_units < frag->nb_units_allocated) {
  551. units = frag->units;
  552. if (position < frag->nb_units)
  553. memmove(units + position + 1, units + position,
  554. (frag->nb_units - position) * sizeof(*units));
  555. } else {
  556. units = av_malloc_array(frag->nb_units + 1, sizeof(*units));
  557. if (!units)
  558. return AVERROR(ENOMEM);
  559. ++frag->nb_units_allocated;
  560. if (position > 0)
  561. memcpy(units, frag->units, position * sizeof(*units));
  562. if (position < frag->nb_units)
  563. memcpy(units + position + 1, frag->units + position,
  564. (frag->nb_units - position) * sizeof(*units));
  565. }
  566. memset(units + position, 0, sizeof(*units));
  567. if (units != frag->units) {
  568. av_free(frag->units);
  569. frag->units = units;
  570. }
  571. ++frag->nb_units;
  572. return 0;
  573. }
  574. int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
  575. CodedBitstreamFragment *frag,
  576. int position,
  577. CodedBitstreamUnitType type,
  578. void *content,
  579. AVBufferRef *content_buf)
  580. {
  581. CodedBitstreamUnit *unit;
  582. AVBufferRef *content_ref;
  583. int err;
  584. if (position == -1)
  585. position = frag->nb_units;
  586. av_assert0(position >= 0 && position <= frag->nb_units);
  587. if (content_buf) {
  588. content_ref = av_buffer_ref(content_buf);
  589. if (!content_ref)
  590. return AVERROR(ENOMEM);
  591. } else {
  592. content_ref = NULL;
  593. }
  594. err = cbs_insert_unit(ctx, frag, position);
  595. if (err < 0) {
  596. av_buffer_unref(&content_ref);
  597. return err;
  598. }
  599. unit = &frag->units[position];
  600. unit->type = type;
  601. unit->content = content;
  602. unit->content_ref = content_ref;
  603. return 0;
  604. }
  605. int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx,
  606. CodedBitstreamFragment *frag,
  607. int position,
  608. CodedBitstreamUnitType type,
  609. uint8_t *data, size_t data_size,
  610. AVBufferRef *data_buf)
  611. {
  612. CodedBitstreamUnit *unit;
  613. AVBufferRef *data_ref;
  614. int err;
  615. if (position == -1)
  616. position = frag->nb_units;
  617. av_assert0(position >= 0 && position <= frag->nb_units);
  618. if (data_buf)
  619. data_ref = av_buffer_ref(data_buf);
  620. else
  621. data_ref = av_buffer_create(data, data_size, NULL, NULL, 0);
  622. if (!data_ref)
  623. return AVERROR(ENOMEM);
  624. err = cbs_insert_unit(ctx, frag, position);
  625. if (err < 0) {
  626. av_buffer_unref(&data_ref);
  627. return err;
  628. }
  629. unit = &frag->units[position];
  630. unit->type = type;
  631. unit->data = data;
  632. unit->data_size = data_size;
  633. unit->data_ref = data_ref;
  634. return 0;
  635. }
  636. void ff_cbs_delete_unit(CodedBitstreamContext *ctx,
  637. CodedBitstreamFragment *frag,
  638. int position)
  639. {
  640. av_assert0(0 <= position && position < frag->nb_units
  641. && "Unit to be deleted not in fragment.");
  642. cbs_unit_uninit(ctx, &frag->units[position]);
  643. --frag->nb_units;
  644. if (frag->nb_units > 0)
  645. memmove(frag->units + position,
  646. frag->units + position + 1,
  647. (frag->nb_units - position) * sizeof(*frag->units));
  648. }