Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

pirms 10 mēnešiem
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #include "hls-fmp4.h"
  2. #include "hls-param.h"
  3. #include "mov-format.h"
  4. #include "fmp4-writer.h"
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <assert.h>
  8. #include <errno.h>
  9. #define N_SEGMENT (1 * 1024 * 1024)
  10. #define N_FILESIZE (100 * 1024 * 1024) // 100M
  11. #define VMAX(a, b) ((a) > (b) ? (a) : (b))
  12. struct hls_fmp4_t
  13. {
  14. fmp4_writer_t* mp4;
  15. uint8_t* ptr;
  16. size_t bytes;
  17. size_t capacity;
  18. size_t offset;
  19. size_t maxsize; // max bytes per mp4 file
  20. int64_t duration; // user setting segment duration
  21. int64_t dts_last; // last packet dts
  22. int64_t dts; // segment first dts
  23. int64_t pts; // segment first pts
  24. int video_track;
  25. int audio_only_flag;// don't have video stream in segment
  26. hls_fmp4_handler handler;
  27. void* param;
  28. };
  29. static int mov_buffer_read(void* param, void* data, uint64_t bytes)
  30. {
  31. struct hls_fmp4_t* fmp4;
  32. fmp4 = (struct hls_fmp4_t*)param;
  33. if (fmp4->offset + bytes > fmp4->bytes)
  34. return -E2BIG;
  35. memcpy(data, fmp4->ptr + fmp4->offset, (size_t)bytes);
  36. return 0;
  37. }
  38. static int mov_buffer_write(void* param, const void* data, uint64_t bytes)
  39. {
  40. void* ptr;
  41. size_t capacity;
  42. struct hls_fmp4_t* fmp4;
  43. fmp4 = (struct hls_fmp4_t*)param;
  44. if (fmp4->offset + bytes > fmp4->maxsize)
  45. return -E2BIG;
  46. if (fmp4->offset + (size_t)bytes > fmp4->capacity)
  47. {
  48. capacity = fmp4->offset + (size_t)bytes + N_SEGMENT;
  49. capacity = capacity > fmp4->maxsize ? fmp4->maxsize : capacity;
  50. ptr = realloc(fmp4->ptr, capacity);
  51. if (NULL == ptr)
  52. return -ENOMEM;
  53. fmp4->ptr = ptr;
  54. fmp4->capacity = capacity;
  55. }
  56. memcpy(fmp4->ptr + fmp4->offset, data, (size_t)bytes);
  57. fmp4->offset += (size_t)bytes;
  58. if(fmp4->offset > fmp4->bytes)
  59. fmp4->bytes = fmp4->offset;
  60. return 0;
  61. }
  62. static int mov_buffer_seek(void* param, int64_t offset)
  63. {
  64. struct hls_fmp4_t* fmp4;
  65. fmp4 = (struct hls_fmp4_t*)param;
  66. if ((offset >= 0 ? offset : -offset) >= fmp4->maxsize)
  67. return -E2BIG;
  68. fmp4->offset = (size_t)(offset >= 0 ? offset : fmp4->maxsize+offset);
  69. return 0;
  70. }
  71. static int64_t mov_buffer_tell(void* param)
  72. {
  73. return (int64_t)((struct hls_fmp4_t*)param)->offset;
  74. }
  75. static struct mov_buffer_t s_io = {
  76. mov_buffer_read,
  77. mov_buffer_write,
  78. mov_buffer_seek,
  79. mov_buffer_tell,
  80. };
  81. struct hls_fmp4_t* hls_fmp4_create(int64_t duration, hls_fmp4_handler handler, void* param)
  82. {
  83. int flags;
  84. struct hls_fmp4_t* hls;
  85. hls = (struct hls_fmp4_t*)calloc(1, sizeof(*hls));
  86. if (NULL == hls)
  87. return NULL;
  88. hls->video_track = -1;
  89. hls->maxsize = N_FILESIZE;
  90. hls->dts = hls->pts = PTS_NO_VALUE;
  91. hls->dts_last = PTS_NO_VALUE;
  92. hls->duration = duration;
  93. hls->handler = handler;
  94. hls->param = param;
  95. flags = 0;
  96. //flags |= MOV_FLAG_FASTSTART;
  97. flags |= MOV_FLAG_SEGMENT;
  98. hls->mp4 = fmp4_writer_create(&s_io, hls, flags);
  99. if (NULL == hls->mp4)
  100. {
  101. free(hls);
  102. return NULL;
  103. }
  104. return hls;
  105. }
  106. void hls_fmp4_destroy(struct hls_fmp4_t* hls)
  107. {
  108. if (hls->mp4)
  109. {
  110. fmp4_writer_destroy(hls->mp4);
  111. hls->mp4 = NULL;
  112. }
  113. if (hls->ptr)
  114. {
  115. free(hls->ptr);
  116. hls->ptr = NULL;
  117. }
  118. free(hls);
  119. }
  120. int hls_fmp4_add_audio(hls_fmp4_t* hls, uint8_t object, int channel_count, int bits_per_sample, int sample_rate, const void* extra_data, size_t extra_data_size)
  121. {
  122. return fmp4_writer_add_audio(hls->mp4, object, channel_count, bits_per_sample, sample_rate, extra_data, extra_data_size);
  123. }
  124. int hls_fmp4_add_video(hls_fmp4_t* hls, uint8_t object, int width, int height, const void* extra_data, size_t extra_data_size)
  125. {
  126. hls->video_track = fmp4_writer_add_video(hls->mp4, object, width, height, extra_data, extra_data_size);
  127. return hls->video_track;
  128. }
  129. int hls_fmp4_input(struct hls_fmp4_t* hls, int track, const void* data, size_t bytes, int64_t pts, int64_t dts, int flags)
  130. {
  131. int r, segment;
  132. int force_new_segment;
  133. int64_t duration;
  134. assert(dts < hls->dts_last + hls->duration || PTS_NO_VALUE == hls->dts_last);
  135. // PTS/DTS rewind
  136. force_new_segment = 0;
  137. if (dts + hls->duration < hls->dts_last || NULL == data || 0 == bytes)
  138. force_new_segment = 1;
  139. if ((MOV_AV_FLAG_KEYFREAME & flags) && (dts - hls->dts >= hls->duration || 0 == hls->duration))
  140. {
  141. segment = 1;
  142. }
  143. else if (hls->audio_only_flag && dts - hls->dts >= hls->duration)
  144. {
  145. // audio only file
  146. segment = 1;
  147. }
  148. else
  149. {
  150. segment = 0;
  151. }
  152. if (PTS_NO_VALUE == hls->dts_last || segment || force_new_segment)
  153. {
  154. if (PTS_NO_VALUE != hls->dts_last)
  155. {
  156. // save and create new segment
  157. r = fmp4_writer_save_segment(hls->mp4);
  158. if (0 == r)
  159. {
  160. duration = ((force_new_segment || dts > hls->dts_last + 100) ? hls->dts_last : dts) - hls->dts;
  161. r = hls->handler(hls->param, hls->ptr, hls->bytes, hls->pts, hls->dts, duration);
  162. }
  163. if (0 != r) return r;
  164. }
  165. hls->pts = pts;
  166. hls->dts = dts;
  167. hls->audio_only_flag = 1;
  168. hls->offset = 0;
  169. hls->bytes = 0;
  170. }
  171. if (NULL == data || 0 == bytes)
  172. return 0;
  173. if (hls->audio_only_flag && track == hls->video_track)
  174. hls->audio_only_flag = 0; // clear audio only flag
  175. hls->dts_last = dts;
  176. return fmp4_writer_write(hls->mp4, track, data, bytes, pts, dts, flags);
  177. }
  178. int hls_fmp4_init_segment(hls_fmp4_t* hls, void* data, size_t bytes)
  179. {
  180. int r;
  181. uint8_t* ptr;
  182. size_t len;
  183. size_t capacity;
  184. size_t offset;
  185. size_t maxsize;
  186. // save
  187. ptr = hls->ptr;
  188. len = hls->bytes;
  189. offset = hls->offset;
  190. capacity = hls->capacity;
  191. maxsize = hls->maxsize;
  192. hls->ptr = (uint8_t*)data;
  193. hls->bytes = 0;
  194. hls->offset = 0;
  195. hls->capacity = bytes;
  196. hls->maxsize = bytes;
  197. r = fmp4_writer_init_segment(hls->mp4);
  198. r = 0 == r ? (int)hls->bytes : -1;
  199. // restore
  200. hls->ptr = ptr;
  201. hls->bytes = len;
  202. hls->offset = offset;
  203. hls->capacity = capacity;
  204. hls->maxsize = maxsize;
  205. return r;
  206. }