Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

139 рядки
2.9KB

  1. #include "mp4-writer.h"
  2. #include "mov-format.h"
  3. #include "aom-av1.h"
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <assert.h>
  8. #define MOV_WRITER_AV1_FMP4 0
  9. extern "C" const struct mov_buffer_t* mov_file_buffer(void);
  10. enum
  11. {
  12. OBU_SEQUENCE_HEADER = 1,
  13. OBU_TEMPORAL_DELIMITER = 2,
  14. OBU_FRAME = 6,
  15. };
  16. static uint8_t s_buffer[2 * 1024 * 1024];
  17. static uint8_t s_extra_data[64 * 1024];
  18. struct mov_av1_test_t
  19. {
  20. mp4_writer_t* mov;
  21. struct aom_av1_t av1;
  22. int track;
  23. int width;
  24. int height;
  25. uint32_t pts, dts;
  26. uint8_t* ptr;
  27. int bytes;
  28. int vcl;
  29. int keyframe;
  30. };
  31. static uint8_t* file_read(const char* file, long* size)
  32. {
  33. FILE* fp = fopen(file, "rb");
  34. if (fp)
  35. {
  36. fseek(fp, 0, SEEK_END);
  37. *size = ftell(fp);
  38. fseek(fp, 0, SEEK_SET);
  39. uint8_t* ptr = (uint8_t*)malloc(*size);
  40. fread(ptr, 1, *size, fp);
  41. fclose(fp);
  42. return ptr;
  43. }
  44. return NULL;
  45. }
  46. static int av1_write(struct mov_av1_test_t* ctx, const void* data, int bytes)
  47. {
  48. if (ctx->track < 0)
  49. {
  50. int r = aom_av1_codec_configuration_record_init(&ctx->av1, data, bytes);
  51. if (ctx->av1.width < 1 || ctx->av1.height < 1)
  52. {
  53. //ctx->ptr = end;
  54. return -2; // waiting for sps/pps
  55. }
  56. int extra_data_size = aom_av1_codec_configuration_record_save(&ctx->av1, s_extra_data, sizeof(s_extra_data));
  57. if (extra_data_size <= 0)
  58. {
  59. // invalid AVCC
  60. assert(0);
  61. return -1;
  62. }
  63. // TODO: waiting for key frame ???
  64. ctx->track = mp4_writer_add_video(ctx->mov, MOV_OBJECT_AV1, ctx->width, ctx->height, s_extra_data, extra_data_size);
  65. if (ctx->track < 0)
  66. return -1;
  67. mp4_writer_init_segment(ctx->mov);
  68. }
  69. mp4_writer_write(ctx->mov, ctx->track, data, bytes, ctx->pts, ctx->pts, ctx->keyframe ? MOV_AV_FLAG_KEYFREAME : 0);
  70. ctx->pts += 40;
  71. ctx->dts += 40;
  72. return 0;
  73. }
  74. static int av1_handler(void* param, const uint8_t* obu, size_t bytes)
  75. {
  76. struct mov_av1_test_t* ctx = (struct mov_av1_test_t*)param;
  77. uint8_t obu_type = (obu[0] >> 3) & 0x0F;
  78. if (ctx->vcl > 0 && OBU_TEMPORAL_DELIMITER == obu_type)
  79. {
  80. int r = av1_write(ctx, ctx->ptr, ctx->bytes);
  81. if (-1 == r)
  82. return 0; // wait for more data
  83. ctx->bytes = 0;
  84. ctx->vcl = 0;
  85. ctx->keyframe = 0;
  86. }
  87. if (OBU_TEMPORAL_DELIMITER == obu_type)
  88. return 0; // ignore
  89. if (OBU_SEQUENCE_HEADER == obu_type)
  90. ctx->keyframe = 1;
  91. if (OBU_FRAME == obu_type)
  92. ++ctx->vcl;
  93. memcpy(ctx->ptr + ctx->bytes, obu, bytes);
  94. ctx->bytes += bytes;
  95. return 0;
  96. }
  97. void mov_writer_av1(const char* obu, int width, int height, const char* mp4)
  98. {
  99. struct mov_av1_test_t ctx;
  100. memset(&ctx, 0, sizeof(ctx));
  101. ctx.track = -1;
  102. ctx.width = width;
  103. ctx.height = height;
  104. ctx.ptr = s_buffer;
  105. long bytes = 0;
  106. uint8_t* ptr = file_read(obu, &bytes);
  107. if (NULL == ptr) return;
  108. FILE* fp = fopen(mp4, "wb+");
  109. ctx.mov = mp4_writer_create(MOV_WRITER_AV1_FMP4, mov_file_buffer(), fp, MOV_FLAG_FASTSTART | MOV_FLAG_SEGMENT);
  110. aom_av1_obu_split(ptr, bytes, av1_handler, &ctx);
  111. mp4_writer_destroy(ctx.mov);
  112. fclose(fp);
  113. free(ptr);
  114. }