25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
4.5KB

  1. #include "mpeg-ps.h"
  2. #include "mpeg-ts.h"
  3. #include "mov-reader.h"
  4. #include "mov-format.h"
  5. #include "mpeg4-aac.h"
  6. #include "mpeg4-avc.h"
  7. #include "mpeg4-hevc.h"
  8. #include <assert.h>
  9. #include <string.h>
  10. #include <stdio.h>
  11. #include <map>
  12. extern "C" const struct mov_buffer_t* mov_file_buffer(void);
  13. static uint8_t s_packet[2 * 1024 * 1024];
  14. static uint8_t s_buffer[4 * 1024 * 1024];
  15. struct mpeg_ts_multi_program_test_t
  16. {
  17. int count;
  18. struct
  19. {
  20. int pn;
  21. int track;
  22. int stream;
  23. uint8_t object;
  24. union
  25. {
  26. mpeg4_avc_t avc;
  27. mpeg4_hevc_t hevc;
  28. } v;
  29. union
  30. {
  31. mpeg4_aac_t aac;
  32. } a;
  33. } pn[4];
  34. void* ts;
  35. };
  36. static void* ts_alloc(void* /*param*/, size_t bytes)
  37. {
  38. static char s_buffer[188];
  39. assert(bytes <= sizeof(s_buffer));
  40. return s_buffer;
  41. }
  42. static void ts_free(void* /*param*/, void* /*packet*/)
  43. {
  44. return;
  45. }
  46. static int ts_write(void* param, const void* packet, size_t bytes)
  47. {
  48. return 1 == fwrite(packet, bytes, 1, (FILE*)param) ? 0 : ferror((FILE*)param);
  49. }
  50. static void onread(void* param, uint32_t track, const void* data, size_t bytes, int64_t pts, int64_t dts, int flags)
  51. {
  52. mpeg_ts_multi_program_test_t* ctx = (mpeg_ts_multi_program_test_t*)param;
  53. for (int i = 0; i < ctx->count; i++)
  54. {
  55. if (ctx->pn[i].track == track)
  56. {
  57. if (MOV_OBJECT_H264 == ctx->pn[i].object)
  58. {
  59. bytes = h264_mp4toannexb(&ctx->pn[i].v.avc, data, bytes, s_packet, sizeof(s_packet));
  60. data = s_packet;
  61. }
  62. else if (MOV_OBJECT_HEVC == ctx->pn[i].object)
  63. {
  64. bytes = h265_mp4toannexb(&ctx->pn[i].v.hevc, data, bytes, s_packet, sizeof(s_packet));
  65. data = s_packet;
  66. }
  67. else if (MOV_OBJECT_AAC == ctx->pn[i].object)
  68. {
  69. int n = mpeg4_aac_adts_save(&ctx->pn[i].a.aac, bytes, s_packet, sizeof(s_packet));
  70. memcpy(s_packet + n, data, bytes);
  71. data = s_packet;
  72. bytes += n;
  73. }
  74. assert(0 == mpeg_ts_write(ctx->ts, ctx->pn[i].stream, (flags & MOV_AV_FLAG_KEYFREAME) ? 1 : 0, pts * 90, dts * 90, data, bytes));
  75. return;
  76. }
  77. }
  78. }
  79. static void mov_video_info(void* param, uint32_t track, uint8_t object, int /*width*/, int /*height*/, const void* extra, size_t bytes)
  80. {
  81. assert(MOV_OBJECT_H264 == object || MOV_OBJECT_HEVC == object);
  82. mpeg_ts_multi_program_test_t* ctx = (mpeg_ts_multi_program_test_t*)param;
  83. ctx->pn[ctx->count].pn = ctx->count + 1;
  84. ctx->pn[ctx->count].track = track;
  85. ctx->pn[ctx->count].object = object;
  86. assert(0 == mpeg_ts_add_program(ctx->ts, ctx->pn[ctx->count].pn, NULL, 0));
  87. switch (object)
  88. {
  89. case MOV_OBJECT_H264:
  90. assert(mpeg4_avc_decoder_configuration_record_load((const uint8_t*)extra, bytes, &ctx->pn[ctx->count].v.avc) > 0);
  91. ctx->pn[ctx->count].stream = mpeg_ts_add_program_stream(ctx->ts, ctx->pn[ctx->count].pn, PSI_STREAM_H264, NULL, 0);
  92. break;
  93. case MOV_OBJECT_HEVC:
  94. assert(mpeg4_hevc_decoder_configuration_record_load((const uint8_t*)extra, bytes, &ctx->pn[ctx->count].v.hevc) > 0);
  95. ctx->pn[ctx->count].stream = mpeg_ts_add_program_stream(ctx->ts, ctx->pn[ctx->count].pn, PSI_STREAM_H265, NULL, 0);
  96. break;
  97. default:
  98. assert(0);
  99. }
  100. ctx->count++;
  101. }
  102. static void mov_audio_info(void* param, uint32_t track, uint8_t object, int channel_count, int /*bit_per_sample*/, int sample_rate, const void* extra, size_t bytes)
  103. {
  104. assert(MOV_OBJECT_AAC == object || MOV_OBJECT_OPUS == object);
  105. mpeg_ts_multi_program_test_t* ctx = (mpeg_ts_multi_program_test_t*)param;
  106. ctx->pn[ctx->count].pn = ctx->count + 1;
  107. ctx->pn[ctx->count].track = track;
  108. ctx->pn[ctx->count].object = object;
  109. assert(0 == mpeg_ts_add_program(ctx->ts, ctx->pn[ctx->count].pn, NULL, 0));
  110. assert(mpeg4_aac_audio_specific_config_load((const uint8_t*)extra, bytes, &ctx->pn[ctx->count].a.aac) > 0);
  111. ctx->pn[ctx->count].stream = mpeg_ts_add_program_stream(ctx->ts, ctx->pn[ctx->count].pn, MOV_OBJECT_AAC == object ? PSI_STREAM_AAC : PSI_STREAM_AUDIO_OPUS, NULL, 0);
  112. ctx->count++;
  113. }
  114. void mpeg_ts_multi_program_test(const char* mp4)
  115. {
  116. struct mpeg_ts_multi_program_test_t ctx;
  117. memset(&ctx, 0, sizeof(ctx));
  118. char output[256] = { 0 };
  119. snprintf(output, sizeof(output) - 1, "%s.ts", mp4);
  120. struct mpeg_ts_func_t tshandler;
  121. tshandler.alloc = ts_alloc;
  122. tshandler.write = ts_write;
  123. tshandler.free = ts_free;
  124. FILE* fp = fopen(output, "wb");
  125. ctx.ts = mpeg_ts_create(&tshandler, fp);
  126. FILE* rfp = fopen(mp4, "rb");
  127. mov_reader_t* mov = mov_reader_create(mov_file_buffer(), rfp);
  128. struct mov_reader_trackinfo_t info = { mov_video_info, mov_audio_info };
  129. mov_reader_getinfo(mov, &info, &ctx);
  130. while (mov_reader_read(mov, s_buffer, sizeof(s_buffer), onread, &ctx) > 0)
  131. {
  132. }
  133. mov_reader_destroy(mov);
  134. mpeg_ts_destroy(ctx.ts);
  135. fclose(rfp);
  136. fclose(fp);
  137. }