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.

hls-segmenter-mp4.cpp 4.4KB

10 月之前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #if defined(_HAVE_FFMPEG_)
  2. extern "C"
  3. {
  4. #include "libavformat/avformat.h"
  5. }
  6. #include "hls-fmp4.h"
  7. #include "hls-m3u8.h"
  8. #include "hls-param.h"
  9. #include "mov-format.h"
  10. #include "mpeg-ps.h"
  11. #include <assert.h>
  12. static char s_packet[2 * 1024 * 1024];
  13. static void ffmpeg_init()
  14. {
  15. avformat_network_init();
  16. }
  17. static AVFormatContext* ffmpeg_open(const char* url)
  18. {
  19. int r;
  20. AVFormatContext* ic;
  21. AVDictionary* opt = NULL;
  22. ic = avformat_alloc_context();
  23. if (NULL == ic)
  24. {
  25. printf("%s(%s): avformat_alloc_context failed.\n", __FUNCTION__, url);
  26. return NULL;
  27. }
  28. //if (!av_dict_get(ff->opt, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
  29. // av_dict_set(&ff->opt, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
  30. // scan_all_pmts_set = 1;
  31. //}
  32. r = avformat_open_input(&ic, url, NULL, &opt);
  33. if (0 != r)
  34. {
  35. printf("%s: avformat_open_input(%s) => %d\n", __FUNCTION__, url, r);
  36. return NULL;
  37. }
  38. //if (scan_all_pmts_set)
  39. // av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
  40. //ff->ic->probesize = 100 * 1024;
  41. //ff->ic->max_analyze_duration = 5 * AV_TIME_BASE;
  42. /* If not enough info to get the stream parameters, we decode the
  43. first frames to get it. (used in mpeg case for example) */
  44. r = avformat_find_stream_info(ic, NULL/*&opt*/);
  45. if (r < 0) {
  46. printf("%s(%s): could not find codec parameters\n", __FUNCTION__, url);
  47. return NULL;
  48. }
  49. av_dict_free(&opt);
  50. return ic;
  51. }
  52. static int hls_init_segment(hls_fmp4_t* hls, hls_m3u8_t* m3u)
  53. {
  54. int bytes = hls_fmp4_init_segment(hls, s_packet, sizeof(s_packet));
  55. FILE* fp = fopen("hls/0.mp4", "wb");
  56. fwrite(s_packet, 1, bytes, fp);
  57. fclose(fp);
  58. return hls_m3u8_set_x_map(m3u, "hls/0.mp4");
  59. }
  60. static int hls_segment(void* m3u8, const void* data, size_t bytes, int64_t /*pts*/, int64_t dts, int64_t duration)
  61. {
  62. static int i = 0;
  63. static char name[128] = { 0 };
  64. snprintf(name, sizeof(name) - 1, "hls/%d.mp4", ++i);
  65. FILE* fp = fopen(name, "wb");
  66. fwrite(data, 1, bytes, fp);
  67. fclose(fp);
  68. return hls_m3u8_add((hls_m3u8_t*)m3u8, name, dts, duration, 0);
  69. }
  70. void hls_segmenter_fmp4_test(const char* file)
  71. {
  72. ffmpeg_init();
  73. AVPacket pkt;
  74. memset(&pkt, 0, sizeof(pkt));
  75. //av_init_packet(&pkt);
  76. AVFormatContext* ic = ffmpeg_open(file);
  77. hls_m3u8_t* m3u = hls_m3u8_create(0, 7);
  78. hls_fmp4_t* hls = hls_fmp4_create(HLS_DURATION * 1000, hls_segment, m3u);
  79. int track_aac = -1;
  80. int track_264 = -1;
  81. int track_265 = -1;
  82. for (unsigned int i = 0; i < ic->nb_streams; i++)
  83. {
  84. AVStream* st = ic->streams[i];
  85. if (AV_CODEC_ID_AAC == st->codecpar->codec_id)
  86. track_aac = hls_fmp4_add_audio(hls, MOV_OBJECT_AAC, st->codecpar->channels, st->codecpar->bits_per_coded_sample, st->codecpar->sample_rate, st->codecpar->extradata, st->codecpar->extradata_size);
  87. else if (AV_CODEC_ID_H264 == st->codecpar->codec_id)
  88. track_264 = hls_fmp4_add_video(hls, MOV_OBJECT_H264, st->codecpar->width, st->codecpar->height, st->codecpar->extradata, st->codecpar->extradata_size);
  89. else if(AV_CODEC_ID_H265 == st->codecpar->codec_id)
  90. track_265 = hls_fmp4_add_video(hls, MOV_OBJECT_HEVC, st->codecpar->width, st->codecpar->height, st->codecpar->extradata, st->codecpar->extradata_size);
  91. }
  92. // write init segment
  93. hls_init_segment(hls, m3u);
  94. int r = av_read_frame(ic, &pkt);
  95. while (0 == r)
  96. {
  97. AVStream* st = ic->streams[pkt.stream_index];
  98. int64_t pts = (int64_t)(pkt.pts * av_q2d(st->time_base) * 1000);
  99. int64_t dts = (int64_t)(pkt.dts * av_q2d(st->time_base) * 1000);
  100. if (AV_CODEC_ID_AAC == st->codecpar->codec_id)
  101. {
  102. //printf("[A] pts: %08lld, dts: %08lld\n", pts, dts);
  103. hls_fmp4_input(hls, track_aac, pkt.data, pkt.size, pts, dts, 0);
  104. }
  105. else if (AV_CODEC_ID_H264 == st->codecpar->codec_id)
  106. {
  107. //printf("[V] pts: %08lld, dts: %08lld\n", pts, dts);
  108. hls_fmp4_input(hls, track_264, pkt.data, pkt.size, pts, dts, (pkt.flags & AV_PKT_FLAG_KEY) ? MOV_AV_FLAG_KEYFREAME : 0);
  109. }
  110. else if (AV_CODEC_ID_H265 == st->codecpar->codec_id)
  111. {
  112. //printf("[V] pts: %08lld, dts: %08lld\n", pts, dts);
  113. hls_fmp4_input(hls, track_265, pkt.data, pkt.size, pts, dts, (pkt.flags & AV_PKT_FLAG_KEY) ? MOV_AV_FLAG_KEYFREAME : 0);
  114. }
  115. else
  116. {
  117. assert(0);
  118. }
  119. //av_packet_unref(&pkt);
  120. r = av_read_frame(ic, &pkt);
  121. }
  122. avformat_close_input(&ic);
  123. avformat_free_context(ic);
  124. hls_fmp4_destroy(hls);
  125. // write m3u8 file
  126. hls_m3u8_playlist(m3u, 1, s_packet, sizeof(s_packet));
  127. hls_m3u8_destroy(m3u);
  128. FILE* fp = fopen("playlist.m3u8", "wb");
  129. fwrite(s_packet, 1, strlen(s_packet), fp);
  130. fclose(fp);
  131. }
  132. #endif