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.

544 lines
15KB

  1. #include "fmp4-writer.h"
  2. #include "mov-internal.h"
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <assert.h>
  6. #include <errno.h>
  7. #include <time.h>
  8. struct fmp4_writer_t
  9. {
  10. struct mov_t mov;
  11. size_t mdat_size;
  12. int has_moov;
  13. uint32_t frag_interleave;
  14. uint32_t fragment_id; // start from 1
  15. uint32_t sn; // sample sn
  16. };
  17. static int fmp4_write_app(struct mov_t* mov)
  18. {
  19. mov_buffer_w32(&mov->io, 8 + strlen(MOV_APP)); /* size */
  20. mov_buffer_write(&mov->io, "free", 4);
  21. mov_buffer_write(&mov->io, MOV_APP, strlen(MOV_APP));
  22. return 0;
  23. }
  24. static size_t fmp4_write_mvex(struct mov_t* mov)
  25. {
  26. int i;
  27. size_t size;
  28. uint64_t offset;
  29. size = 8 /* Box */;
  30. offset = mov_buffer_tell(&mov->io);
  31. mov_buffer_w32(&mov->io, 0); /* size */
  32. mov_buffer_write(&mov->io, "mvex", 4);
  33. //size += fmp4_write_mehd(mov);
  34. for (i = 0; i < mov->track_count; i++)
  35. {
  36. mov->track = mov->tracks + i;
  37. size += mov_write_trex(mov);
  38. }
  39. //size += mov_write_leva(mov);
  40. mov_write_size(mov, offset, size); /* update size */
  41. return size;
  42. }
  43. static size_t fmp4_write_traf(struct mov_t* mov, uint32_t moof)
  44. {
  45. uint32_t i, start;
  46. size_t size;
  47. uint64_t offset;
  48. struct mov_track_t* track;
  49. size = 8 /* Box */;
  50. offset = mov_buffer_tell(&mov->io);
  51. mov_buffer_w32(&mov->io, 0); /* size */
  52. mov_buffer_write(&mov->io, "traf", 4);
  53. track = mov->track;
  54. track->tfhd.flags = MOV_TFHD_FLAG_DEFAULT_FLAGS /*| MOV_TFHD_FLAG_BASE_DATA_OFFSET*/;
  55. track->tfhd.flags |= MOV_TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX;
  56. // ISO/IEC 23009-1:2014(E) 6.3.4.2 General format type (p93)
  57. // The 'moof' boxes shall use movie-fragment relative addressing for media data that
  58. // does not use external data references, the flag 'default-base-is-moof' shall be set,
  59. // and data-offset shall be used, i.e. base-data-offset-present shall not be used.
  60. //if (mov->flags & MOV_FLAG_SEGMENT)
  61. {
  62. //track->tfhd.flags &= ~MOV_TFHD_FLAG_BASE_DATA_OFFSET;
  63. track->tfhd.flags |= MOV_TFHD_FLAG_DEFAULT_BASE_IS_MOOF;
  64. }
  65. track->tfhd.base_data_offset = mov->moof_offset;
  66. track->tfhd.sample_description_index = 1;
  67. track->tfhd.default_sample_flags = MOV_AUDIO == track->handler_type ? MOV_TREX_FLAG_SAMPLE_DEPENDS_ON_I_PICTURE : (MOV_TREX_FLAG_SAMPLE_IS_NO_SYNC_SAMPLE| MOV_TREX_FLAG_SAMPLE_DEPENDS_ON_NOT_I_PICTURE);
  68. if (track->sample_count > 0)
  69. {
  70. track->tfhd.flags |= MOV_TFHD_FLAG_DEFAULT_DURATION | MOV_TFHD_FLAG_DEFAULT_SIZE;
  71. track->tfhd.default_sample_duration = track->sample_count > 1 ? (uint32_t)(track->samples[1].dts - track->samples[0].dts) : (uint32_t)track->turn_last_duration;
  72. track->tfhd.default_sample_size = track->samples[0].bytes;
  73. }
  74. else
  75. {
  76. track->tfhd.flags |= MOV_TFHD_FLAG_DURATION_IS_EMPTY;
  77. track->tfhd.default_sample_duration = 0; // not set
  78. track->tfhd.default_sample_size = 0; // not set
  79. }
  80. size += mov_write_tfhd(mov);
  81. // ISO/IEC 23009-1:2014(E) 6.3.4.2 General format type (p93)
  82. // Each 'traf' box shall contain a 'tfdt' box.
  83. size += mov_write_tfdt(mov);
  84. for (start = 0, i = 1; i < track->sample_count; i++)
  85. {
  86. if (track->samples[i - 1].offset + track->samples[i - 1].bytes != track->samples[i].offset)
  87. {
  88. size += mov_write_trun(mov, start, i-start, moof);
  89. start = i;
  90. }
  91. }
  92. size += mov_write_trun(mov, start, i-start, moof);
  93. mov_write_size(mov, offset, size); /* update size */
  94. return size;
  95. }
  96. static size_t fmp4_write_moof(struct mov_t* mov, uint32_t fragment, uint32_t moof)
  97. {
  98. int i;
  99. size_t size, j;
  100. uint64_t offset;
  101. uint64_t n;
  102. size = 8 /* Box */;
  103. offset = mov_buffer_tell(&mov->io);
  104. mov_buffer_w32(&mov->io, 0); /* size */
  105. mov_buffer_write(&mov->io, "moof", 4);
  106. size += mov_write_mfhd(mov, fragment);
  107. n = 0;
  108. for (i = 0; i < mov->track_count; i++)
  109. {
  110. mov->track = mov->tracks + i;
  111. // rewrite offset, write only one trun
  112. // 2017/10/17 Dale Curtis SHA-1: a5fd8aa45b11c10613e6e576033a6b5a16b9cbb9 (libavformat/mov.c)
  113. for (j = 0; j < mov->track->sample_count; j++)
  114. {
  115. mov->track->samples[j].offset = n;
  116. n += mov->track->samples[j].bytes;
  117. }
  118. if (mov->track->sample_count > 0)
  119. size += fmp4_write_traf(mov, moof);
  120. }
  121. mov_write_size(mov, offset, size); /* update size */
  122. return size;
  123. }
  124. static size_t fmp4_write_moov(struct mov_t* mov)
  125. {
  126. int i;
  127. size_t size;
  128. uint32_t count;
  129. uint64_t offset;
  130. size = 8 /* Box */;
  131. offset = mov_buffer_tell(&mov->io);
  132. mov_buffer_w32(&mov->io, 0); /* size */
  133. mov_buffer_write(&mov->io, "moov", 4);
  134. size += mov_write_mvhd(mov);
  135. // size += fmp4_write_iods(mov);
  136. for (i = 0; i < mov->track_count; i++)
  137. {
  138. mov->track = mov->tracks + i;
  139. count = mov->track->sample_count;
  140. mov->track->sample_count = 0;
  141. size += mov_write_trak(mov);
  142. mov->track->sample_count = count; // restore sample count
  143. }
  144. size += fmp4_write_mvex(mov);
  145. size += mov_write_udta(mov);
  146. mov_write_size(mov, offset, size); /* update size */
  147. return size;
  148. }
  149. static size_t fmp4_write_sidx(struct mov_t* mov)
  150. {
  151. int i;
  152. for (i = 0; i < mov->track_count; i++)
  153. {
  154. mov->track = mov->tracks + i;
  155. mov_write_sidx(mov, 52 * (uint64_t)(mov->track_count - i - 1)); /* first_offset */
  156. }
  157. return 52 * mov->track_count;
  158. }
  159. static int fmp4_write_mfra(struct mov_t* mov)
  160. {
  161. int i;
  162. uint64_t mfra_offset;
  163. uint64_t mfro_offset;
  164. // mfra
  165. mfra_offset = mov_buffer_tell(&mov->io);
  166. mov_buffer_w32(&mov->io, 0); /* size */
  167. mov_buffer_write(&mov->io, "mfra", 4);
  168. // tfra
  169. for (i = 0; i < mov->track_count; i++)
  170. {
  171. mov->track = mov->tracks + i;
  172. mov_write_tfra(mov);
  173. }
  174. // mfro
  175. mfro_offset = mov_buffer_tell(&mov->io);
  176. mov_buffer_w32(&mov->io, 16); /* size */
  177. mov_buffer_write(&mov->io, "mfro", 4);
  178. mov_buffer_w32(&mov->io, 0); /* version & flags */
  179. mov_buffer_w32(&mov->io, (uint32_t)(mfro_offset - mfra_offset + 16));
  180. mov_write_size(mov, mfra_offset, (size_t)(mfro_offset - mfra_offset + 16));
  181. return (int)(mfro_offset - mfra_offset + 16);
  182. }
  183. static int fmp4_add_fragment_entry(struct mov_track_t* track, uint64_t time, uint64_t offset)
  184. {
  185. if (track->frag_count >= track->frag_capacity)
  186. {
  187. void* p = realloc(track->frags, sizeof(struct mov_fragment_t) * (track->frag_capacity + 64));
  188. if (!p) return -ENOMEM;
  189. track->frags = p;
  190. track->frag_capacity += 64;
  191. }
  192. track->frags[track->frag_count].time = time;
  193. track->frags[track->frag_count].offset = offset;
  194. ++track->frag_count;
  195. return 0;
  196. }
  197. static int fmp4_write_fragment(struct fmp4_writer_t* writer)
  198. {
  199. int i;
  200. size_t n;
  201. size_t refsize;
  202. struct mov_t* mov;
  203. mov = &writer->mov;
  204. if (writer->mdat_size < 1)
  205. return 0; // empty
  206. // write moov
  207. if (!writer->has_moov)
  208. {
  209. // write ftyp/stype
  210. if (mov->flags & MOV_FLAG_SEGMENT)
  211. {
  212. mov_write_styp(mov);
  213. }
  214. else
  215. {
  216. mov_write_ftyp(mov);
  217. fmp4_write_app(mov);
  218. fmp4_write_moov(mov);
  219. }
  220. writer->has_moov = 1;
  221. }
  222. if (mov->flags & MOV_FLAG_SEGMENT)
  223. {
  224. // ISO/IEC 23009-1:2014(E) 6.3.4.2 General format type (p93)
  225. // Each Media Segment may contain one or more 'sidx' boxes.
  226. // If present, the first 'sidx' box shall be placed before any 'moof' box
  227. // and the first Segment Index box shall document the entire Segment.
  228. fmp4_write_sidx(mov);
  229. }
  230. // moof
  231. mov->moof_offset = mov_buffer_tell(&mov->io);
  232. refsize = fmp4_write_moof(mov, ++writer->fragment_id, 0); // start from 1
  233. // rewrite moof with trun data offset
  234. mov_buffer_seek(&mov->io, mov->moof_offset);
  235. fmp4_write_moof(mov, writer->fragment_id, (uint32_t)refsize+8);
  236. refsize += writer->mdat_size + 8/*mdat box*/;
  237. // add mfra entry
  238. for (i = 0; i < mov->track_count; i++)
  239. {
  240. mov->track = mov->tracks + i;
  241. if (mov->track->sample_count > 0 && 0 == (mov->flags & MOV_FLAG_SEGMENT))
  242. fmp4_add_fragment_entry(mov->track, mov->track->samples[0].dts, mov->moof_offset);
  243. // hack: write sidx referenced_size
  244. if (mov->flags & MOV_FLAG_SEGMENT)
  245. mov_write_size(mov, mov->moof_offset - 52 * (uint64_t)(mov->track_count - i) + 40, (0 << 31) | (refsize & 0x7fffffff));
  246. mov->track->offset = 0; // reset
  247. }
  248. // mdat
  249. if (writer->mdat_size + 8 <= UINT32_MAX)
  250. {
  251. mov_buffer_w32(&mov->io, (uint32_t)writer->mdat_size + 8); /* size */
  252. mov_buffer_write(&mov->io, "mdat", 4);
  253. }
  254. else
  255. {
  256. mov_buffer_w32(&mov->io, 1);
  257. mov_buffer_write(&mov->io, "mdat", 4);
  258. mov_buffer_w64(&mov->io, writer->mdat_size + 16);
  259. }
  260. // interleave write samples
  261. n = 0;
  262. while(n < writer->mdat_size)
  263. {
  264. for (i = 0; i < mov->track_count; i++)
  265. {
  266. mov->track = mov->tracks + i;
  267. while (mov->track->offset < mov->track->sample_count && n == mov->track->samples[mov->track->offset].offset)
  268. {
  269. mov_buffer_write(&mov->io, mov->track->samples[mov->track->offset].data, mov->track->samples[mov->track->offset].bytes);
  270. free(mov->track->samples[mov->track->offset].data); // free av packet memory
  271. n += mov->track->samples[mov->track->offset].bytes;
  272. ++mov->track->offset;
  273. }
  274. }
  275. }
  276. // clear track samples(don't free samples memory)
  277. for (i = 0; i < mov->track_count; i++)
  278. {
  279. mov->tracks[i].sample_count = 0;
  280. mov->tracks[i].offset = 0;
  281. }
  282. writer->mdat_size = 0;
  283. return mov_buffer_error(&mov->io);
  284. }
  285. static int fmp4_writer_init(struct mov_t* mov)
  286. {
  287. if (mov->flags & MOV_FLAG_SEGMENT)
  288. {
  289. mov->ftyp.major_brand = MOV_BRAND_MSDH;
  290. mov->ftyp.minor_version = 0;
  291. mov->ftyp.brands_count = 6;
  292. mov->ftyp.compatible_brands[0] = MOV_BRAND_ISOM;
  293. mov->ftyp.compatible_brands[1] = MOV_BRAND_MP42;
  294. mov->ftyp.compatible_brands[2] = MOV_BRAND_MSDH;
  295. mov->ftyp.compatible_brands[3] = MOV_BRAND_MSIX;
  296. mov->ftyp.compatible_brands[4] = MOV_BRAND_ISO5; // default�\base�\is�\moof flag
  297. mov->ftyp.compatible_brands[5] = MOV_BRAND_ISO6; // styp
  298. mov->header = 0;
  299. }
  300. else
  301. {
  302. mov->ftyp.major_brand = MOV_BRAND_ISOM;
  303. mov->ftyp.minor_version = 1;
  304. mov->ftyp.brands_count = 5;
  305. mov->ftyp.compatible_brands[0] = MOV_BRAND_ISOM;
  306. mov->ftyp.compatible_brands[1] = MOV_BRAND_MP42;
  307. mov->ftyp.compatible_brands[2] = MOV_BRAND_AVC1;
  308. mov->ftyp.compatible_brands[3] = MOV_BRAND_DASH;
  309. mov->ftyp.compatible_brands[4] = MOV_BRAND_ISO5; // default�\base�\is�\moof flag
  310. mov->header = 0;
  311. }
  312. return 0;
  313. }
  314. struct fmp4_writer_t* fmp4_writer_create(const struct mov_buffer_t *buffer, void* param, int flags)
  315. {
  316. struct mov_t* mov;
  317. struct fmp4_writer_t* writer;
  318. writer = (struct fmp4_writer_t*)calloc(1, sizeof(struct fmp4_writer_t));
  319. if (NULL == writer)
  320. return NULL;
  321. writer->frag_interleave = 5;
  322. mov = &writer->mov;
  323. mov->flags = flags;
  324. mov->mvhd.next_track_ID = 1;
  325. mov->mvhd.creation_time = time(NULL) + 0x7C25B080; // 1970 based -> 1904 based;
  326. mov->mvhd.modification_time = mov->mvhd.creation_time;
  327. mov->mvhd.timescale = 1000;
  328. mov->mvhd.duration = 0; // placeholder
  329. fmp4_writer_init(mov);
  330. mov->io.param = param;
  331. memcpy(&mov->io.io, buffer, sizeof(mov->io.io));
  332. return writer;
  333. }
  334. void fmp4_writer_destroy(struct fmp4_writer_t* writer)
  335. {
  336. int i;
  337. struct mov_t* mov;
  338. mov = &writer->mov;
  339. fmp4_writer_save_segment(writer);
  340. for (i = 0; i < mov->track_count; i++)
  341. mov_free_track(mov->tracks + i);
  342. if (mov->tracks)
  343. free(mov->tracks);
  344. free(writer);
  345. }
  346. int fmp4_writer_write(struct fmp4_writer_t* writer, int idx, const void* data, size_t bytes, int64_t pts, int64_t dts, int flags)
  347. {
  348. int64_t duration;
  349. struct mov_track_t* track;
  350. struct mov_sample_t* sample;
  351. if (idx < 0 || idx >= (int)writer->mov.track_count)
  352. return -ENOENT;
  353. track = &writer->mov.tracks[idx];
  354. duration = dts > track->last_dts && INT64_MIN != track->last_dts ? dts - track->last_dts : 0;
  355. #if 1
  356. track->turn_last_duration = duration;
  357. #else
  358. track->turn_last_duration = track->turn_last_duration > 0 ? track->turn_last_duration * 7 / 8 + duration / 8 : duration;
  359. #endif
  360. if (MOV_VIDEO == track->handler_type && (flags & MOV_AV_FLAG_KEYFREAME) )
  361. fmp4_write_fragment(writer); // fragment per video keyframe
  362. if (track->sample_count + 1 >= track->sample_offset)
  363. {
  364. void* ptr = realloc(track->samples, sizeof(struct mov_sample_t) * (track->sample_offset + 1024));
  365. if (NULL == ptr) return -ENOMEM;
  366. track->samples = (struct mov_sample_t*)ptr;
  367. track->sample_offset += 1024;
  368. }
  369. pts = pts * track->mdhd.timescale / 1000;
  370. dts = dts * track->mdhd.timescale / 1000;
  371. sample = &track->samples[track->sample_count];
  372. sample->sample_description_index = 1;
  373. sample->bytes = (uint32_t)bytes;
  374. sample->flags = flags;
  375. sample->pts = pts;
  376. sample->dts = dts;
  377. sample->offset = writer->mdat_size;
  378. sample->data = malloc(bytes);
  379. if (NULL == sample->data)
  380. return -ENOMEM;
  381. memcpy(sample->data, data, bytes);
  382. if (INT64_MIN == track->start_dts)
  383. track->start_dts = sample->dts;
  384. writer->mdat_size += bytes; // update media data size
  385. track->sample_count += 1;
  386. track->last_dts = sample->dts;
  387. return mov_buffer_error(&writer->mov.io);
  388. }
  389. int fmp4_writer_add_audio(struct fmp4_writer_t* writer, uint8_t object, int channel_count, int bits_per_sample, int sample_rate, const void* extra_data, size_t extra_data_size)
  390. {
  391. struct mov_t* mov;
  392. struct mov_track_t* track;
  393. mov = &writer->mov;
  394. track = mov_add_track(mov);
  395. if (NULL == track)
  396. return -ENOMEM;
  397. if (0 != mov_add_audio(track, &mov->mvhd, 1000, object, channel_count, bits_per_sample, sample_rate, extra_data, extra_data_size))
  398. return -ENOMEM;
  399. mov->mvhd.next_track_ID++;
  400. return mov->track_count++;
  401. }
  402. int fmp4_writer_add_video(struct fmp4_writer_t* writer, uint8_t object, int width, int height, const void* extra_data, size_t extra_data_size)
  403. {
  404. struct mov_t* mov;
  405. struct mov_track_t* track;
  406. mov = &writer->mov;
  407. track = mov_add_track(mov);
  408. if (NULL == track)
  409. return -ENOMEM;
  410. if (0 != mov_add_video(track, &mov->mvhd, 1000, object, width, height, extra_data, extra_data_size))
  411. return -ENOMEM;
  412. mov->mvhd.next_track_ID++;
  413. return mov->track_count++;
  414. }
  415. int fmp4_writer_add_subtitle(struct fmp4_writer_t* writer, uint8_t object, const void* extra_data, size_t extra_data_size)
  416. {
  417. struct mov_t* mov;
  418. struct mov_track_t* track;
  419. mov = &writer->mov;
  420. track = mov_add_track(mov);
  421. if (NULL == track)
  422. return -ENOMEM;
  423. if (0 != mov_add_subtitle(track, &mov->mvhd, 1000, object, extra_data, extra_data_size))
  424. return -ENOMEM;
  425. mov->mvhd.next_track_ID++;
  426. return mov->track_count++;
  427. }
  428. int fmp4_writer_add_udta(fmp4_writer_t* writer, const void* data, size_t size)
  429. {
  430. writer->mov.udta = data;
  431. writer->mov.udta_size = size;
  432. return 0;
  433. }
  434. int fmp4_writer_save_segment(fmp4_writer_t* writer)
  435. {
  436. int i;
  437. struct mov_t* mov;
  438. mov = &writer->mov;
  439. // flush fragment
  440. fmp4_write_fragment(writer);
  441. // write mfra
  442. if (0 == (mov->flags & MOV_FLAG_SEGMENT))
  443. {
  444. fmp4_write_mfra(mov);
  445. for (i = 0; i < mov->track_count; i++)
  446. mov->tracks[i].frag_count = 0; // don't free frags memory
  447. }
  448. else
  449. {
  450. writer->has_moov = 0; // clear moov flags
  451. }
  452. return mov_buffer_error(&mov->io);
  453. }
  454. int fmp4_writer_init_segment(fmp4_writer_t* writer)
  455. {
  456. struct mov_t* mov;
  457. mov = &writer->mov;
  458. mov_write_ftyp(mov);
  459. fmp4_write_moov(mov);
  460. return mov_buffer_error(&mov->io);
  461. }