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.

161 lines
3.6KB

  1. #include "mp4-writer.h"
  2. #include "mov-format.h"
  3. #include "mpeg4-hevc.h"
  4. #include "mpeg4-avc.h"
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <assert.h>
  9. #define MOV_WRITER_H265_FMP4 0
  10. extern "C" const struct mov_buffer_t* mov_file_buffer(void);
  11. #define H265_NAL(v) ((v >> 1) & 0x3F)
  12. static uint8_t s_buffer[2 * 1024 * 1024];
  13. static uint8_t s_extra_data[64 * 1024];
  14. struct mov_h265_test_t
  15. {
  16. mp4_writer_t* mov;
  17. struct mpeg4_hevc_t hevc;
  18. int track;
  19. int width;
  20. int height;
  21. uint32_t pts, dts;
  22. const uint8_t* ptr;
  23. uint8_t buf[1024 * 64];
  24. int bytes;
  25. int vcl;
  26. };
  27. static uint8_t* file_read(const char* file, long* size)
  28. {
  29. FILE* fp = fopen(file, "rb");
  30. if (fp)
  31. {
  32. fseek(fp, 0, SEEK_END);
  33. *size = ftell(fp);
  34. fseek(fp, 0, SEEK_SET);
  35. uint8_t* ptr = (uint8_t*)malloc(*size);
  36. fread(ptr, 1, *size, fp);
  37. fclose(fp);
  38. return ptr;
  39. }
  40. return NULL;
  41. }
  42. static int h265_write(struct mov_h265_test_t* ctx, const void* data, int bytes)
  43. {
  44. int vcl = 0;
  45. int update = 0;
  46. int n = h265_annexbtomp4(&ctx->hevc, data, bytes, s_buffer, sizeof(s_buffer), &vcl, &update);
  47. if (ctx->track < 0)
  48. {
  49. if (ctx->hevc.numOfArrays < 1)
  50. {
  51. //ctx->ptr = end;
  52. return -2; // waiting for vps/sps/pps
  53. }
  54. int extra_data_size = mpeg4_hevc_decoder_configuration_record_save(&ctx->hevc, s_extra_data, sizeof(s_extra_data));
  55. if (extra_data_size <= 0)
  56. {
  57. // invalid HVCC
  58. assert(0);
  59. return -1;
  60. }
  61. // TODO: waiting for key frame ???
  62. ctx->track = mp4_writer_add_video(ctx->mov, MOV_OBJECT_HEVC, ctx->width, ctx->height, s_extra_data, extra_data_size);
  63. if (ctx->track < 0)
  64. return -1;
  65. mp4_writer_init_segment(ctx->mov);
  66. }
  67. mp4_writer_write(ctx->mov, ctx->track, s_buffer, n, ctx->pts, ctx->pts, 1 == vcl ? MOV_AV_FLAG_KEYFREAME : 0);
  68. ctx->pts += 40;
  69. ctx->dts += 40;
  70. return 0;
  71. }
  72. static void h265_handler(void* param, const uint8_t* nalu, size_t bytes)
  73. {
  74. static int i = 0;
  75. static int j = 0;
  76. static uint8_t startcode[] = {0x00, 0x00, 0x00, 0x01};
  77. struct mov_h265_test_t* ctx = (struct mov_h265_test_t*)param;
  78. assert(ctx->ptr < nalu);
  79. const uint8_t* ptr = nalu - 3;
  80. // const uint8_t* end = (const uint8_t*)nalu + bytes;
  81. uint8_t nalutype = (nalu[0] >> 1) & 0x3f;
  82. if (ctx->vcl > 0 && h265_is_new_access_unit((const uint8_t*)nalu, bytes))
  83. {
  84. //int r = h265_write(ctx, ctx->ptr, ptr - ctx->ptr);
  85. int r = h265_write(ctx, ctx->buf, ctx->bytes);
  86. if (-1 == r)
  87. return; // wait for more data
  88. if ((j++) % 25 == 0)
  89. i = (i + 1) % ctx->vcl;
  90. ctx->bytes = 0;
  91. printf("\n");
  92. ctx->ptr = ptr;
  93. ctx->vcl = 0;
  94. }
  95. if (nalutype <= 31)
  96. {
  97. ++ctx->vcl;
  98. if (1 == ctx->vcl || ctx->vcl == i)
  99. {
  100. printf("ctx->vcl: %d ", ctx->vcl);
  101. memcpy(ctx->buf + ctx->bytes, startcode, sizeof(startcode));
  102. ctx->bytes += sizeof(startcode);
  103. memcpy(ctx->buf + ctx->bytes, nalu, bytes);
  104. ctx->bytes += bytes;
  105. }
  106. }
  107. else
  108. {
  109. memcpy(ctx->buf + ctx->bytes, startcode, sizeof(startcode));
  110. ctx->bytes += sizeof(startcode);
  111. memcpy(ctx->buf + ctx->bytes, nalu, bytes);
  112. ctx->bytes += bytes;
  113. }
  114. }
  115. void mov_writer_h265(const char* h265, int width, int height, const char* mp4)
  116. {
  117. struct mov_h265_test_t ctx;
  118. memset(&ctx, 0, sizeof(ctx));
  119. ctx.track = -1;
  120. ctx.width = width;
  121. ctx.height = height;
  122. ctx.bytes = 0;
  123. long bytes = 0;
  124. uint8_t* ptr = file_read(h265, &bytes);
  125. if (NULL == ptr) return;
  126. ctx.ptr = ptr;
  127. FILE* fp = fopen(mp4, "wb+");
  128. ctx.mov = mp4_writer_create(MOV_WRITER_H265_FMP4, mov_file_buffer(), fp, MOV_FLAG_FASTSTART | MOV_FLAG_SEGMENT);
  129. mpeg4_h264_annexb_nalu(ptr, bytes, h265_handler, &ctx);
  130. mp4_writer_destroy(ctx.mov);
  131. fclose(fp);
  132. free(ptr);
  133. }