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.

331 lines
9.8KB

  1. #include "mov-reader.h"
  2. #include "mov-format.h"
  3. #include "mpeg4-hevc.h"
  4. #include "mpeg4-avc.h"
  5. #include "mpeg4-aac.h"
  6. #include "webm-vpx.h"
  7. #include "aom-av1.h"
  8. #include "rtp-payload.h"
  9. #include "rtp-profile.h"
  10. #include "mpeg-ps.h"
  11. #include "mpeg-ts.h"
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <assert.h>
  16. #include <time.h>
  17. //#define RTP_VIDEO_WITH_PS
  18. #define RTP_LOST_PERCENT 5
  19. extern "C" const struct mov_buffer_t* mov_file_buffer(void);
  20. static uint8_t s_packet[2 * 1024 * 1024];
  21. static uint8_t s_buffer[4 * 1024 * 1024];
  22. static struct mpeg4_hevc_t s_hevc;
  23. static struct mpeg4_avc_t s_avc;
  24. static struct mpeg4_aac_t s_aac;
  25. static struct webm_vpx_t s_vpx;
  26. static struct aom_av1_t s_av1;
  27. struct mov_rtp_test_t;
  28. struct mov_rtp_test_stream_t
  29. {
  30. struct mov_rtp_test_t* ctx;
  31. int av;
  32. int object;
  33. int track;
  34. int psi;
  35. int64_t dts;
  36. void* encoder;
  37. void* decoder;
  38. };
  39. struct mov_rtp_test_t
  40. {
  41. struct mov_rtp_test_stream_t a, v;
  42. struct ps_muxer_t* psenc;
  43. struct ps_demuxer_t* psdec;
  44. };
  45. static unsigned char packet[8 * 1024 * 1024];
  46. static void* rtp_alloc(void* /*param*/, int bytes)
  47. {
  48. static uint8_t buffer[2 * 1024 * 1024 + 4] = { 0, 0, 0, 1, };
  49. assert(bytes <= sizeof(buffer) - 4);
  50. return buffer + 4;
  51. }
  52. static void rtp_free(void* /*param*/, void * /*packet*/)
  53. {
  54. }
  55. static int rtp_encode_packet(void* param, const void *packet, int bytes, uint32_t timestamp, int /*flags*/)
  56. {
  57. struct mov_rtp_test_stream_t* ctx = (struct mov_rtp_test_stream_t*)param;
  58. //int x = rand();
  59. //if( (x % 100) < RTP_LOST_PERCENT )
  60. //{
  61. // printf("======== discard [%s] timestamp: %u ==============\n", ctx->av ? "V" : "A", (unsigned int)timestamp);
  62. // return 0;
  63. //}
  64. int r = rtp_payload_decode_input(ctx->decoder, packet, bytes);
  65. return r >= 0 ? 0 : r;
  66. }
  67. static int rtp_decode_packet(void* param, const void *packet, int bytes, uint32_t timestamp, int flags)
  68. {
  69. struct mov_rtp_test_stream_t* ctx = (struct mov_rtp_test_stream_t*)param;
  70. printf("RTP Decode: [%s] timestamp: %u, bytes: %d\n", ctx->av ? "V" : "A", (unsigned int)timestamp, bytes);
  71. #if defined(RTP_VIDEO_WITH_PS)
  72. if(ctx == &ctx->ctx->v)
  73. {
  74. size_t r = ps_demuxer_input(ctx->ctx->psdec, (const uint8_t*)packet, bytes);
  75. assert(r == bytes);
  76. return r;
  77. }
  78. #endif
  79. return 0;
  80. }
  81. static int rtp_payload_codec_create(struct mov_rtp_test_stream_t* ctx, int payload, const char* encoding, uint16_t seq, uint32_t ssrc)
  82. {
  83. struct rtp_payload_t handler1;
  84. handler1.alloc = rtp_alloc;
  85. handler1.free = rtp_free;
  86. handler1.packet = rtp_decode_packet;
  87. ctx->decoder = rtp_payload_decode_create(payload, encoding, &handler1, ctx);
  88. struct rtp_payload_t handler2;
  89. handler2.alloc = rtp_alloc;
  90. handler2.free = rtp_free;
  91. handler2.packet = rtp_encode_packet;
  92. ctx->encoder = rtp_payload_encode_create(payload, encoding, seq, ssrc, &handler2, ctx);
  93. return 0;
  94. }
  95. inline const char* ftimestamp(uint32_t t, char* buf)
  96. {
  97. sprintf(buf, "%02u:%02u:%02u.%03u", t / 3600000, (t / 60000) % 60, (t / 1000) % 60, t % 1000);
  98. return buf;
  99. }
  100. static void onread(void* param, uint32_t track, const void* buffer, size_t bytes, int64_t pts, int64_t dts, int flags)
  101. {
  102. static char s_pts[64], s_dts[64];
  103. static int64_t v_pts, v_dts;
  104. static int64_t a_pts, a_dts;
  105. struct mov_rtp_test_t* ctx = (struct mov_rtp_test_t*)param;
  106. int n = bytes;
  107. if (ctx->v.track == track)
  108. {
  109. if (MOV_OBJECT_H264 == ctx->v.object)
  110. {
  111. n = h264_mp4toannexb(&s_avc, buffer, bytes, s_packet, sizeof(s_packet));
  112. }
  113. else if (MOV_OBJECT_HEVC == ctx->v.object)
  114. {
  115. n = h265_mp4toannexb(&s_hevc, buffer, bytes, s_packet, sizeof(s_packet));
  116. }
  117. else if (MOV_OBJECT_AV1 == ctx->v.object)
  118. {
  119. n = aom_av1_codec_configuration_record_save(&s_av1, s_packet, sizeof(s_packet));
  120. }
  121. else if (MOV_OBJECT_VP8 == ctx->v.object || MOV_OBJECT_VP9 == ctx->v.object)
  122. {
  123. // nothing to do
  124. }
  125. else
  126. {
  127. assert(0);
  128. }
  129. printf("[V] pts: %s, dts: %s, diff: %03d/%03d, %d%s\n", ftimestamp(pts, s_pts), ftimestamp(dts, s_dts), (int)(pts - v_pts), (int)(dts - v_dts), (int)n, flags ? " [I]" : "");
  130. v_pts = pts;
  131. v_dts = dts;
  132. #if defined(RTP_VIDEO_WITH_PS)
  133. if(MOV_OBJECT_H264 == ctx->v.object || MOV_OBJECT_HEVC == ctx->v.object)
  134. {
  135. ctx->v.dts = dts;
  136. ps_muxer_input(ctx->psenc, ctx->v.psi, (MOV_AV_FLAG_KEYFREAME&flags)?0x0001:0, pts, dts, s_packet, n);
  137. return;
  138. }
  139. #endif
  140. assert(0 == rtp_payload_encode_input(ctx->v.encoder, s_packet, n, (unsigned int)dts));
  141. }
  142. else if (ctx->a.track == track)
  143. {
  144. if (MOV_OBJECT_AAC == ctx->a.object)
  145. {
  146. n = mpeg4_aac_adts_save(&s_aac, bytes, s_packet, sizeof(s_packet));
  147. }
  148. else if(MOV_OBJECT_OPUS == ctx->a.object)
  149. {
  150. assert(0);
  151. }
  152. else
  153. {
  154. assert(0);
  155. }
  156. printf("[A] pts: %s, dts: %s, diff: %03d/%03d, %d\n", ftimestamp(pts, s_pts), ftimestamp(dts, s_dts), (int)(pts - a_pts), (int)(dts - a_dts), (int)n);
  157. a_pts = pts;
  158. a_dts = dts;
  159. assert(0 == rtp_payload_encode_input(ctx->a.encoder, s_packet, n, (unsigned int)dts));
  160. }
  161. else
  162. {
  163. assert(0);
  164. }
  165. }
  166. static void mov_video_info(void* param, uint32_t track, uint8_t object, int /*width*/, int /*height*/, const void* extra, size_t bytes )
  167. {
  168. struct mov_rtp_test_t* ctx = (struct mov_rtp_test_t*)param;
  169. ctx->v.track = track;
  170. ctx->v.object = object;
  171. ctx->v.av = 1;
  172. if (MOV_OBJECT_H264 == object)
  173. {
  174. #if defined(RTP_VIDEO_WITH_PS)
  175. ctx->v.psi = ps_muxer_add_stream(ctx->psenc, PSI_STREAM_H264, NULL, 0);
  176. #else
  177. assert(0 == rtp_payload_codec_create(&ctx->v, 96, "H264", 0, 0));
  178. #endif
  179. assert(bytes == mpeg4_avc_decoder_configuration_record_load((const uint8_t*)extra, bytes, &s_avc));
  180. }
  181. else if (MOV_OBJECT_HEVC == object)
  182. {
  183. #if defined(RTP_VIDEO_WITH_PS)
  184. ctx->v.psi = ps_muxer_add_stream(ctx->psenc, PSI_STREAM_H265, NULL, 0);
  185. #else
  186. assert(0 == rtp_payload_codec_create(&ctx->v, 96, "H265", 0, 0));
  187. #endif
  188. assert(bytes == mpeg4_hevc_decoder_configuration_record_load((const uint8_t*)extra, bytes, &s_hevc));
  189. }
  190. else if (MOV_OBJECT_AV1 == object)
  191. {
  192. assert(0 == rtp_payload_codec_create(&ctx->v, 96, "AV1", 0, 0));
  193. assert(bytes == aom_av1_codec_configuration_record_load((const uint8_t*)extra, bytes, &s_av1));
  194. }
  195. else if (MOV_OBJECT_VP9 == object)
  196. {
  197. assert(0 == rtp_payload_codec_create(&ctx->v, 96, "VP9", 0, 0));
  198. assert(bytes == webm_vpx_codec_configuration_record_load((const uint8_t*)extra, bytes, &s_vpx));
  199. }
  200. else if (MOV_OBJECT_VP8 == object)
  201. {
  202. assert(0 == rtp_payload_codec_create(&ctx->v, 96, "VP8", 0, 0));
  203. assert(bytes == webm_vpx_codec_configuration_record_load((const uint8_t*)extra, bytes, &s_vpx));
  204. }
  205. else
  206. {
  207. assert(0);
  208. }
  209. }
  210. 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)
  211. {
  212. struct mov_rtp_test_t* ctx = (struct mov_rtp_test_t*)param;
  213. ctx->a.track = track;
  214. ctx->a.object = object;
  215. ctx->a.av = 0;
  216. if (MOV_OBJECT_AAC == object)
  217. {
  218. assert(0 == rtp_payload_codec_create(&ctx->a, 97, "MP4A-LATM", 0, 0));
  219. assert(bytes == mpeg4_aac_audio_specific_config_load((const uint8_t*)extra, bytes, &s_aac));
  220. }
  221. else if (MOV_OBJECT_OPUS == object)
  222. {
  223. assert(0 == rtp_payload_codec_create(&ctx->a, 97, "OPUS", 0, 0));
  224. }
  225. else
  226. {
  227. assert(0);
  228. }
  229. }
  230. static void* ps_alloc(void* /*param*/, size_t bytes)
  231. {
  232. static char s_buffer[2 * 1024 * 1024];
  233. assert(bytes <= sizeof(s_buffer));
  234. return s_buffer;
  235. }
  236. static void ps_free(void* /*param*/, void* /*packet*/)
  237. {
  238. return;
  239. }
  240. static int ps_write(void* param, int stream, void* packet, size_t bytes)
  241. {
  242. struct mov_rtp_test_t* ctx = (struct mov_rtp_test_t*)param;
  243. return rtp_payload_encode_input(ctx->v.encoder, packet, bytes, (unsigned int)ctx->v.dts);
  244. }
  245. static int ps_onpacket(void* ps, int stream, int codecid, int flags, int64_t pts, int64_t dts, const void* data, size_t bytes)
  246. {
  247. printf("PS Decode [V] pts: %08lu, dts: %08lu, bytes: %u, %s\n", (unsigned long)pts, (unsigned long)dts, (unsigned int)bytes, flags ? " [I]" : "");
  248. return 0;
  249. }
  250. void mov_rtp_test(const char* mp4)
  251. {
  252. struct mov_rtp_test_t ctx;
  253. memset(&ctx, 0, sizeof(ctx));
  254. ctx.a.ctx = &ctx;
  255. ctx.v.ctx = &ctx;
  256. #if defined(RTP_VIDEO_WITH_PS)
  257. struct ps_muxer_func_t handler;
  258. handler.alloc = ps_alloc;
  259. handler.write = ps_write;
  260. handler.free = ps_free;
  261. ctx.psenc = ps_muxer_create(&handler, &ctx);
  262. ctx.psdec = ps_demuxer_create(ps_onpacket, &ctx);
  263. assert(0 == rtp_payload_codec_create(&ctx.v, 96, "MP2P", 0, 0));
  264. #endif
  265. FILE* fp = fopen(mp4, "rb");
  266. mov_reader_t* mov = mov_reader_create(mov_file_buffer(), fp);
  267. uint64_t duration = mov_reader_getduration(mov);
  268. struct mov_reader_trackinfo_t info = { mov_video_info, mov_audio_info };
  269. mov_reader_getinfo(mov, &info, &ctx);
  270. //srand((int)time(NULL));
  271. while (mov_reader_read(mov, s_buffer, sizeof(s_buffer), onread, &ctx) > 0)
  272. {
  273. }
  274. if(ctx.a.decoder)
  275. rtp_payload_decode_destroy(ctx.a.decoder);
  276. if(ctx.a.encoder)
  277. rtp_payload_encode_destroy(ctx.a.encoder);
  278. if(ctx.v.decoder)
  279. rtp_payload_decode_destroy(ctx.v.decoder);
  280. if(ctx.v.encoder)
  281. rtp_payload_encode_destroy(ctx.v.encoder);
  282. #if defined(RTP_VIDEO_WITH_PS)
  283. ps_demuxer_destroy(ctx.psdec);
  284. ps_muxer_destroy(ctx.psenc);
  285. #endif
  286. mov_reader_destroy(mov);
  287. fclose(fp);
  288. }