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.

275 lines
9.3KB

  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-profile.h"
  9. #include "rtsp-muxer.h"
  10. #include "sockutil.h"
  11. #include "sys/system.h"
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <assert.h>
  16. #include <time.h>
  17. #define IP "127.0.0.1"
  18. #define SOCKET_STORAGE_TO_ADDR(storage) (const struct sockaddr*)(storage), socket_addr_len((const struct sockaddr*)(storage))
  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 rtp_streaming_test_t;
  28. struct rtp_streaming_test_stream_t
  29. {
  30. struct rtp_streaming_test_t* ctx;
  31. int av;
  32. int object;
  33. int track;
  34. int psi;
  35. int64_t dts;
  36. int mid;
  37. struct rtsp_muxer_t* rtp;
  38. socket_t udp[2];
  39. struct sockaddr_storage addr[2];
  40. };
  41. struct rtp_streaming_test_t
  42. {
  43. struct rtp_streaming_test_stream_t a, v;
  44. uint64_t clock;
  45. };
  46. static int rtp_encode_packet(void* param, int pid, const void* packet, int bytes, uint32_t timestamp, int /*flags*/)
  47. {
  48. static uint8_t rtcp[1500];
  49. struct rtp_streaming_test_stream_t* ctx = (struct rtp_streaming_test_stream_t*)param;
  50. assert(bytes == socket_sendto(ctx->udp[0], packet, bytes, 0, SOCKET_STORAGE_TO_ADDR(&ctx->addr[0])));
  51. int r = rtsp_muxer_rtcp(ctx->rtp, ctx->mid, rtcp, sizeof(rtcp));
  52. if (r > 0)
  53. {
  54. assert(r == socket_sendto(ctx->udp[1], rtcp, r, 0, SOCKET_STORAGE_TO_ADDR(&ctx->addr[1])));
  55. }
  56. return 0;
  57. }
  58. static inline const char* ftimestamp(int64_t timestamp, char* buf)
  59. {
  60. uint32_t t = (uint32_t)timestamp;
  61. sprintf(buf, "%02u:%02u:%02u.%03u", t / 3600000, (t / 60000) % 60, (t / 1000) % 60, t % 1000);
  62. return buf;
  63. }
  64. static void onread(void* param, uint32_t track, const void* buffer, size_t bytes, int64_t pts, int64_t dts, int flags)
  65. {
  66. static char s_pts[64], s_dts[64];
  67. static int64_t v_pts, v_dts;
  68. static int64_t a_pts, a_dts;
  69. struct rtp_streaming_test_t* ctx = (struct rtp_streaming_test_t*)param;
  70. uint64_t clock = system_clock();
  71. if (clock - ctx->clock + 5 < dts)
  72. system_sleep(dts - (clock - ctx->clock + 5));
  73. if (ctx->v.track == track)
  74. {
  75. if (MOV_OBJECT_H264 == ctx->v.object)
  76. {
  77. bytes = h264_mp4toannexb(&s_avc, buffer, bytes, s_packet, sizeof(s_packet));
  78. buffer = s_packet;
  79. }
  80. else if (MOV_OBJECT_HEVC == ctx->v.object)
  81. {
  82. bytes = h265_mp4toannexb(&s_hevc, buffer, bytes, s_packet, sizeof(s_packet));
  83. buffer = s_packet;
  84. }
  85. else if (MOV_OBJECT_AV1 == ctx->v.object)
  86. {
  87. //n = aom_av1_codec_configuration_record_save(&s_av1, s_packet, sizeof(s_packet));
  88. }
  89. else if (MOV_OBJECT_VP9 == ctx->v.object || MOV_OBJECT_VP8 == ctx->v.object)
  90. {
  91. //n = aom_av1_codec_configuration_record_save(&s_av1, s_packet, sizeof(s_packet));
  92. }
  93. else
  94. {
  95. assert(0);
  96. }
  97. 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)bytes, flags ? " [I]" : "");
  98. v_pts = pts;
  99. v_dts = dts;
  100. assert(0 == rtsp_muxer_input(ctx->v.rtp, ctx->v.mid, pts, dts, buffer, bytes, 0));
  101. }
  102. else if (ctx->a.track == track)
  103. {
  104. if (MOV_OBJECT_AAC == ctx->a.object)
  105. {
  106. bytes = mpeg4_aac_adts_save(&s_aac, bytes, s_packet, sizeof(s_packet));
  107. buffer = s_packet;
  108. }
  109. else if (MOV_OBJECT_OPUS == ctx->a.object)
  110. {
  111. }
  112. else
  113. {
  114. assert(0);
  115. }
  116. 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)bytes);
  117. a_pts = pts;
  118. a_dts = dts;
  119. assert(0 == rtsp_muxer_input(ctx->a.rtp, ctx->a.mid, pts, dts, buffer, bytes, 0));
  120. }
  121. else
  122. {
  123. assert(0);
  124. }
  125. }
  126. static void mov_video_info(void* param, uint32_t track, uint8_t object, int /*width*/, int /*height*/, const void* extra, size_t bytes)
  127. {
  128. struct rtp_streaming_test_t* ctx = (struct rtp_streaming_test_t*)param;
  129. ctx->v.track = track;
  130. ctx->v.object = object;
  131. ctx->v.av = 1;
  132. ctx->v.udp[0] = socket_udp_bind_ipv4(NULL, 0);
  133. ctx->v.udp[1] = socket_udp_bind_ipv4(NULL, 0);
  134. assert(0 == socket_addr_from(&ctx->v.addr[0], NULL, IP, 8004));
  135. assert(0 == socket_addr_from(&ctx->v.addr[1], NULL, IP, 8005));
  136. ctx->v.rtp = rtsp_muxer_create(rtp_encode_packet, &ctx->v);
  137. if (MOV_OBJECT_H264 == object)
  138. {
  139. assert(bytes == mpeg4_avc_decoder_configuration_record_load((const uint8_t*)extra, bytes, &s_avc));
  140. int pid = rtsp_muxer_add_payload(ctx->v.rtp, "RTP/AVP", 90000, 126, "H264", 0, 0, 0, extra, bytes);
  141. ctx->v.mid = rtsp_muxer_add_media(ctx->v.rtp, pid, RTP_PAYLOAD_H264, extra, bytes);
  142. }
  143. else if (MOV_OBJECT_HEVC == object)
  144. {
  145. assert(bytes == mpeg4_hevc_decoder_configuration_record_load((const uint8_t*)extra, bytes, &s_hevc));
  146. int pid = rtsp_muxer_add_payload(ctx->v.rtp, "RTP/AVP", 90000, RTP_PAYLOAD_H265, "H265", 0, 0, 0, extra, bytes);
  147. ctx->v.mid = rtsp_muxer_add_media(ctx->v.rtp, pid, RTP_PAYLOAD_H265, extra, bytes);
  148. }
  149. else if (MOV_OBJECT_AV1 == object)
  150. {
  151. assert(bytes == aom_av1_codec_configuration_record_load((const uint8_t*)extra, bytes, &s_av1));
  152. int pid = rtsp_muxer_add_payload(ctx->v.rtp, "RTP/AVP", 90000, RTP_PAYLOAD_AV1X, "AV1X", 0, 0, 0, extra, bytes);
  153. ctx->v.mid = rtsp_muxer_add_media(ctx->v.rtp, pid, RTP_PAYLOAD_AV1X, extra, bytes);
  154. }
  155. else if (MOV_OBJECT_VP9 == object)
  156. {
  157. assert(bytes == webm_vpx_codec_configuration_record_load((const uint8_t*)extra, bytes, &s_vpx));
  158. int pid = rtsp_muxer_add_payload(ctx->v.rtp, "RTP/AVP", 90000, RTP_PAYLOAD_VP9, "VP9", 0, 0, 0, extra, bytes);
  159. ctx->v.mid = rtsp_muxer_add_media(ctx->v.rtp, pid, RTP_PAYLOAD_VP9, extra, bytes);
  160. }
  161. else if (MOV_OBJECT_VP8 == object)
  162. {
  163. assert(bytes == webm_vpx_codec_configuration_record_load((const uint8_t*)extra, bytes, &s_vpx));
  164. int pid = rtsp_muxer_add_payload(ctx->v.rtp, "RTP/AVP", 90000, 100, "VP8", 0, 0, 0, extra, bytes);
  165. ctx->v.mid = rtsp_muxer_add_media(ctx->v.rtp, pid, RTP_PAYLOAD_VP8, extra, bytes);
  166. }
  167. else
  168. {
  169. assert(0);
  170. }
  171. }
  172. 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)
  173. {
  174. struct rtp_streaming_test_t* ctx = (struct rtp_streaming_test_t*)param;
  175. ctx->a.track = track;
  176. ctx->a.object = object;
  177. ctx->a.av = 0;
  178. ctx->a.udp[0] = socket_udp_bind_ipv4(NULL, 0);
  179. ctx->a.udp[1] = socket_udp_bind_ipv4(NULL, 0);
  180. assert(0 == socket_addr_from(&ctx->a.addr[0], NULL, IP, 5002));
  181. assert(0 == socket_addr_from(&ctx->a.addr[1], NULL, IP, 5003));
  182. ctx->a.rtp = rtsp_muxer_create(rtp_encode_packet, &ctx->a);
  183. if (MOV_OBJECT_AAC == object)
  184. {
  185. assert(bytes == mpeg4_aac_audio_specific_config_load((const uint8_t*)extra, bytes, &s_aac));
  186. int pid = rtsp_muxer_add_payload(ctx->a.rtp, "RTP/AVP", sample_rate, RTP_PAYLOAD_LATM, "MP4A-LATM", 0, 0, 0, extra, bytes);
  187. ctx->a.mid = rtsp_muxer_add_media(ctx->a.rtp, pid, RTP_PAYLOAD_LATM, extra, bytes);
  188. }
  189. else if (MOV_OBJECT_OPUS == object)
  190. {
  191. assert(48000 == sample_rate);
  192. int pid = rtsp_muxer_add_payload(ctx->a.rtp, "RTP/AVP", sample_rate, 111, "OPUS", 0, 0, 0, extra, bytes);
  193. ctx->a.mid = rtsp_muxer_add_media(ctx->a.rtp, pid, RTP_PAYLOAD_OPUS, extra, bytes);
  194. }
  195. else
  196. {
  197. assert(0);
  198. }
  199. }
  200. void rtp_streaming_test(const char* mp4)
  201. {
  202. struct rtp_streaming_test_t ctx;
  203. memset(&ctx, 0, sizeof(ctx));
  204. ctx.a.ctx = &ctx;
  205. ctx.v.ctx = &ctx;
  206. FILE* fp = fopen(mp4, "rb");
  207. mov_reader_t* mov = mov_reader_create(mov_file_buffer(), fp);
  208. uint64_t duration = mov_reader_getduration(mov);
  209. struct mov_reader_trackinfo_t info = { mov_video_info, mov_audio_info };
  210. mov_reader_getinfo(mov, &info, &ctx);
  211. ctx.clock = system_clock();
  212. while (mov_reader_read(mov, s_buffer, sizeof(s_buffer), onread, &ctx) > 0)
  213. {
  214. int n = 0;
  215. socket_t udp[4];
  216. if (ctx.v.udp[0] && socket_invalid != ctx.v.udp[0])
  217. {
  218. udp[n] = ctx.v.udp[0];
  219. udp[n++] = ctx.v.udp[1];
  220. }
  221. if (ctx.a.udp[0] && socket_invalid != ctx.a.udp[0])
  222. {
  223. udp[n] = ctx.a.udp[0];
  224. udp[n++] = ctx.a.udp[1];
  225. }
  226. socklen_t addrlen;
  227. struct sockaddr_storage addr;
  228. int64_t flags = socket_poll_readv(0, n, udp);
  229. for (int i = 0; i < 4; i++)
  230. {
  231. // discard rtcp
  232. if (flags & (1LL << i))
  233. {
  234. socket_recvfrom(udp[i], s_buffer, sizeof(s_buffer), 0, (struct sockaddr*)&addr, &addrlen);
  235. }
  236. }
  237. }
  238. if (ctx.a.rtp)
  239. rtsp_muxer_destroy(ctx.a.rtp);
  240. if (ctx.v.rtp)
  241. rtsp_muxer_destroy(ctx.v.rtp);
  242. mov_reader_destroy(mov);
  243. fclose(fp);
  244. }