trak.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:15k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. #include "quicktime.h"
  2. int quicktime_trak_init(quicktime_trak_t *trak)
  3. {
  4. quicktime_tkhd_init(&(trak->tkhd));
  5. quicktime_edts_init(&(trak->edts));
  6. quicktime_tref_init(&(trak->tref));
  7. quicktime_mdia_init(&(trak->mdia));
  8. quicktime_hint_udta_init(&(trak->hint_udta));
  9. return 0;
  10. }
  11. int quicktime_trak_init_video(quicktime_t *file, 
  12. quicktime_trak_t *trak, 
  13. int frame_w, 
  14. int frame_h, 
  15. float frame_rate,
  16. int time_scale,
  17. char *compressor)
  18. {
  19. quicktime_tkhd_init_video(file, &(trak->tkhd), frame_w, frame_h);
  20. quicktime_mdia_init_video(file, &(trak->mdia), frame_w, frame_h, 
  21. frame_rate, time_scale, compressor);
  22. quicktime_edts_init_table(&(trak->edts));
  23. return 0;
  24. }
  25. int quicktime_trak_init_audio(quicktime_t *file, 
  26. quicktime_trak_t *trak, 
  27. int channels, 
  28. int sample_rate, 
  29. int bits, 
  30. int sample_size,
  31. int time_scale,
  32. int sample_duration,
  33. char *compressor)
  34. {
  35. quicktime_mdia_init_audio(file, &(trak->mdia), channels, sample_rate, bits,
  36. sample_size, time_scale, sample_duration, compressor);
  37. quicktime_edts_init_table(&(trak->edts));
  38. return 0;
  39. }
  40. int quicktime_trak_init_hint(quicktime_t *file, 
  41. quicktime_trak_t *trak, 
  42. quicktime_trak_t *refTrak,
  43. int maxPktSize,
  44. int time_scale,
  45. int sampleDuration)
  46. {
  47. quicktime_tkhd_init_hint(file, &(trak->tkhd));
  48. quicktime_edts_init_table(&(trak->edts));
  49. quicktime_tref_init_hint(&(trak->tref), refTrak);
  50. quicktime_mdia_init_hint(file, &(trak->mdia), 
  51. refTrak, maxPktSize, time_scale, sampleDuration);
  52. return 0;
  53. }
  54. int quicktime_trak_is_hint(quicktime_trak_t *trak)
  55. {
  56. if (trak->tref.hint.numTracks > 0) {
  57. return 1;
  58. }
  59. return 0;
  60. }
  61. int quicktime_trak_delete(quicktime_trak_t *trak)
  62. {
  63. quicktime_tkhd_delete(&(trak->tkhd));
  64. quicktime_hint_udta_delete(&(trak->hint_udta));
  65. return 0;
  66. }
  67. int quicktime_trak_dump(quicktime_trak_t *trak)
  68. {
  69. printf(" trackn");
  70. quicktime_tkhd_dump(&(trak->tkhd));
  71. quicktime_edts_dump(&(trak->edts));
  72. quicktime_tref_dump(&(trak->tref));
  73. quicktime_mdia_dump(&(trak->mdia));
  74. quicktime_hint_udta_dump(&(trak->hint_udta));
  75. return 0;
  76. }
  77. quicktime_trak_t* quicktime_add_trak(quicktime_moov_t *moov)
  78. {
  79. if(moov->total_tracks < MAXTRACKS)
  80. {
  81. moov->trak[moov->total_tracks] = malloc(sizeof(quicktime_trak_t));
  82. quicktime_trak_init(moov->trak[moov->total_tracks]);
  83. moov->total_tracks++;
  84. }
  85. return moov->trak[moov->total_tracks - 1];
  86. }
  87. quicktime_trak_t* quicktime_find_track_by_id(quicktime_moov_t *moov, int trackId)
  88. {
  89. int i;
  90. for (i = 0; i < moov->total_tracks; i++) {
  91. if (moov->trak[i]->tkhd.track_id == trackId) {
  92. return moov->trak[i];
  93. }
  94. }
  95. return NULL;
  96. }
  97. int quicktime_delete_trak(quicktime_moov_t *moov, quicktime_trak_t *trak)
  98. {
  99. int i, j;
  100. for (i = 0; i < moov->total_tracks; i++) {
  101. if (moov->trak[i] == trak) {
  102. quicktime_trak_delete(trak);
  103. free(trak);
  104. moov->trak[i] = NULL;
  105. for (j = i + 1; j < moov->total_tracks; j++, i++) {
  106. moov->trak[i] = moov->trak[j];
  107. }
  108. moov->trak[j] = NULL;
  109. moov->total_tracks--;
  110. return 0;
  111. }
  112. }
  113. return -1;
  114. }
  115. int quicktime_read_trak(quicktime_t *file, quicktime_trak_t *trak, quicktime_atom_t *trak_atom)
  116. {
  117. quicktime_atom_t leaf_atom;
  118. do
  119. {
  120. quicktime_atom_read_header(file, &leaf_atom);
  121. /* mandatory */
  122. if(quicktime_atom_is(&leaf_atom, "tkhd"))
  123. { quicktime_read_tkhd(file, &(trak->tkhd)); }
  124. else
  125. if(quicktime_atom_is(&leaf_atom, "mdia"))
  126. { quicktime_read_mdia(file, &(trak->mdia), &leaf_atom); }
  127. else
  128. /* optional */
  129. if(quicktime_atom_is(&leaf_atom, "clip"))
  130. { quicktime_atom_skip(file, &leaf_atom); }
  131. else
  132. if(quicktime_atom_is(&leaf_atom, "matt"))
  133. { quicktime_atom_skip(file, &leaf_atom); }
  134. else
  135. if(quicktime_atom_is(&leaf_atom, "edts"))
  136. { quicktime_read_edts(file, &(trak->edts), &leaf_atom); }
  137. else
  138. if(quicktime_atom_is(&leaf_atom, "load"))
  139. { quicktime_atom_skip(file, &leaf_atom); }
  140. else
  141. if(quicktime_atom_is(&leaf_atom, "tref"))
  142. { quicktime_read_tref(file, &(trak->tref), &leaf_atom); }
  143. else
  144. if(quicktime_atom_is(&leaf_atom, "imap"))
  145. { quicktime_atom_skip(file, &leaf_atom); }
  146. else
  147. if(quicktime_atom_is(&leaf_atom, "udta"))
  148. { quicktime_read_hint_udta(file, &(trak->hint_udta), &leaf_atom); }
  149. else
  150. quicktime_atom_skip(file, &leaf_atom);
  151. }while(quicktime_position(file) < trak_atom->end);
  152. return 0;
  153. }
  154. int quicktime_write_trak(quicktime_t *file, quicktime_trak_t *trak, long moov_time_scale)
  155. {
  156. long duration;
  157. long timescale;
  158. quicktime_atom_t atom;
  159. quicktime_atom_write_header(file, &atom, "trak");
  160. quicktime_trak_duration(trak, &duration, &timescale);
  161. /* printf("quicktime_write_trak duration %dn", duration); */
  162. /* get duration in movie's units */
  163. if (timescale) {
  164. trak->tkhd.duration = 
  165. (long)((float)duration / timescale * moov_time_scale);
  166. } else {
  167. trak->tkhd.duration = 0;
  168. }
  169. trak->mdia.mdhd.duration = duration;
  170. trak->mdia.mdhd.time_scale = timescale;
  171. if (trak->mdia.minf.is_hint) {
  172. if (duration && timescale) {
  173. trak->mdia.minf.hmhd.avgbitrate =
  174. (trak->hint_udta.hinf.trpy.numBytes * 8)
  175. / (duration / timescale);
  176. } else {
  177. trak->mdia.minf.hmhd.avgbitrate = 0;
  178. }
  179. }
  180. quicktime_write_tkhd(file, &(trak->tkhd));
  181. quicktime_write_edts(file, &(trak->edts), trak->tkhd.duration);
  182. quicktime_write_tref(file, &(trak->tref));
  183. quicktime_write_mdia(file, &(trak->mdia));
  184. quicktime_write_hint_udta(file, &(trak->hint_udta));
  185. quicktime_atom_write_footer(file, &atom);
  186. return 0;
  187. }
  188. long quicktime_track_end(quicktime_trak_t *trak)
  189. {
  190. /* get the byte endpoint of the track in the file */
  191. long size = 0;
  192. long chunk, chunk_offset, chunk_samples, sample;
  193. quicktime_stsz_t *stsz = &(trak->mdia.minf.stbl.stsz);
  194. quicktime_stsz_table_t *table = stsz->table;
  195. quicktime_stsc_t *stsc = &(trak->mdia.minf.stbl.stsc);
  196. quicktime_stco_t *stco;
  197. /* get the last chunk offset */
  198. /* the chunk offsets contain the HEADER_LENGTH themselves */
  199. stco = &(trak->mdia.minf.stbl.stco);
  200. chunk = stco->total_entries;
  201. size = chunk_offset = stco->table[chunk - 1].offset;
  202. /* get the number of samples in the last chunk */
  203. chunk_samples = stsc->table[stsc->total_entries - 1].samples;
  204. /* get the size of last samples */
  205. #ifdef NOTDEF
  206. if(stsz->sample_size)
  207. {
  208. /* assume audio so calculate the sample size */
  209. size += chunk_samples * stsz->sample_size
  210. * trak->mdia.minf.stbl.stsd.table[0].channels 
  211. * trak->mdia.minf.stbl.stsd.table[0].sample_size / 8;
  212. }
  213. else
  214. {
  215. /* assume video */
  216. #endif
  217. for(sample = stsz->total_entries - chunk_samples; 
  218. sample >= 0 && sample < stsz->total_entries; sample++)
  219. {
  220. size += stsz->table[sample].size;
  221. }
  222. #ifdef NOTDEF
  223. }
  224. #endif
  225. /* for hint tracks */
  226. if (quicktime_trak_is_hint(trak)) {
  227. /* compute maximum packet duration */
  228. if (trak->hint_udta.hinf.maxr.maxBitRate != 0) {
  229. trak->hint_udta.hinf.dmax.milliSecs = 
  230. (trak->hint_udta.hinf.pmax.numBytes * 8) *
  231. ((float)trak->hint_udta.hinf.maxr.granularity /
  232. (float)trak->hint_udta.hinf.maxr.maxBitRate);
  233. }
  234. }
  235. return size;
  236. }
  237. long quicktime_track_samples(quicktime_t *file, quicktime_trak_t *trak)
  238. {
  239. /*printf("file->rd %d file->wr %dn", file->rd, file->wr); */
  240. if(file->wr)
  241. {
  242. /* get the sample count when creating a new file */
  243.   quicktime_stsc_table_t *table = trak->mdia.minf.stbl.stsc.table;
  244. long total_entries = trak->mdia.minf.stbl.stsc.total_entries;
  245. long chunk = trak->mdia.minf.stbl.stco.total_entries;
  246. long sample;
  247. if(chunk)
  248. {
  249. sample = quicktime_sample_of_chunk(trak, chunk);
  250. sample += table[total_entries - 1].samples;
  251. }
  252. else 
  253. sample = 0;
  254. return sample;
  255. }
  256. else
  257. {
  258. /* get the sample count when reading only */
  259. quicktime_stts_t *stts = &(trak->mdia.minf.stbl.stts);
  260. int i;
  261. long total = 0;
  262. for(i = 0; i < stts->total_entries; i++)
  263. {
  264. total += stts->table[i].sample_count;
  265. }
  266. return total;
  267. }
  268. }
  269. long quicktime_sample_of_chunk(quicktime_trak_t *trak, long chunk)
  270. {
  271. quicktime_stsc_table_t *table = trak->mdia.minf.stbl.stsc.table;
  272. long total_entries = trak->mdia.minf.stbl.stsc.total_entries;
  273. long chunk1entry, chunk2entry;
  274. long chunk1, chunk2, chunks, total = 0;
  275. for(chunk1entry = total_entries - 1, chunk2entry = total_entries; 
  276. chunk1entry >= 0; 
  277. chunk1entry--, chunk2entry--)
  278. {
  279. chunk1 = table[chunk1entry].chunk;
  280. if(chunk > chunk1)
  281. {
  282. if(chunk2entry < total_entries)
  283. {
  284. chunk2 = table[chunk2entry].chunk;
  285. if(chunk < chunk2) chunk2 = chunk;
  286. }
  287. else
  288. chunk2 = chunk;
  289. chunks = chunk2 - chunk1;
  290. total += chunks * table[chunk1entry].samples;
  291. }
  292. }
  293. return total;
  294. }
  295. int quicktime_chunk_of_sample(long *chunk_sample, long *chunk, quicktime_trak_t *trak, long sample)
  296. {
  297. quicktime_stsc_table_t *table = NULL;
  298. long total_entries = 0;
  299. long chunk2entry;
  300. long chunk1, chunk2, chunk1samples, range_samples, total = 0;
  301. if (trak == NULL) {
  302. return -1;
  303. }
  304.   table = trak->mdia.minf.stbl.stsc.table;
  305. total_entries = trak->mdia.minf.stbl.stsc.total_entries;
  306. chunk1 = 1;
  307. chunk1samples = 0;
  308. chunk2entry = 0;
  309. do
  310. {
  311. chunk2 = table[chunk2entry].chunk;
  312. *chunk = chunk2 - chunk1;
  313. range_samples = *chunk * chunk1samples;
  314. if(sample < total + range_samples) break;
  315. chunk1samples = table[chunk2entry].samples;
  316. chunk1 = chunk2;
  317. if(chunk2entry < total_entries)
  318. {
  319. chunk2entry++;
  320. total += range_samples;
  321. }
  322. }while(chunk2entry < total_entries);
  323. if(chunk1samples)
  324. *chunk = (sample - total) / chunk1samples + chunk1;
  325. else
  326. *chunk = 1;
  327. *chunk_sample = total + (*chunk - chunk1) * chunk1samples;
  328. return 0;
  329. }
  330. long quicktime_chunk_to_offset(quicktime_trak_t *trak, long chunk)
  331. {
  332. quicktime_stco_table_t *table = NULL;
  333. if (trak == NULL) {
  334. return -1;
  335. }
  336. table = trak->mdia.minf.stbl.stco.table;
  337. if(trak->mdia.minf.stbl.stco.total_entries && chunk > trak->mdia.minf.stbl.stco.total_entries)
  338. return table[trak->mdia.minf.stbl.stco.total_entries - 1].offset;
  339. else
  340. if(trak->mdia.minf.stbl.stco.total_entries)
  341. return table[chunk - 1].offset;
  342. else
  343. return HEADER_LENGTH;
  344. return 0;
  345. }
  346. long quicktime_offset_to_chunk(long *chunk_offset, quicktime_trak_t *trak, long offset)
  347. {
  348. quicktime_stco_table_t *table = trak->mdia.minf.stbl.stco.table;
  349. int i;
  350. for(i = trak->mdia.minf.stbl.stco.total_entries - 1; i >= 0; i--)
  351. {
  352. if(table[i].offset <= offset)
  353. {
  354. *chunk_offset = table[i].offset;
  355. return i + 1;
  356. }
  357. }
  358. *chunk_offset = HEADER_LENGTH;
  359. return 1;
  360. }
  361. long quicktime_sample_range_size(quicktime_trak_t *trak, long chunk_sample, long sample)
  362. {
  363. quicktime_stsz_table_t *table = trak->mdia.minf.stbl.stsz.table;
  364. long i, total;
  365. if(trak->mdia.minf.stbl.stsz.sample_size)
  366. {
  367. /* assume audio */
  368. return quicktime_samples_to_bytes(trak, sample - chunk_sample);
  369. }
  370. else
  371. {
  372. /* probably video */
  373. for(i = chunk_sample, total = 0; i < sample; i++)
  374. {
  375. total += trak->mdia.minf.stbl.stsz.table[i].size;
  376. }
  377. }
  378. return total;
  379. }
  380. long quicktime_sample_to_offset(quicktime_trak_t *trak, long sample)
  381. {
  382. long chunk, chunk_sample, chunk_offset1, chunk_offset2;
  383. if (trak == NULL) {
  384. return -1;
  385. }
  386. quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, sample);
  387. chunk_offset1 = quicktime_chunk_to_offset(trak, chunk);
  388. chunk_offset2 = chunk_offset1 + quicktime_sample_range_size(trak, chunk_sample, sample);
  389. /*printf("quicktime_sample_to_offset chunk %d sample %d chunk_offset %d chunk_sample %d chunk_offset + samples %dn", */
  390. /*  chunk, sample, chunk_offset1, chunk_sample, chunk_offset2); */
  391. return chunk_offset2;
  392. }
  393. long quicktime_offset_to_sample(quicktime_trak_t *trak, long offset)
  394. {
  395. long chunk_offset;
  396. long chunk = quicktime_offset_to_chunk(&chunk_offset, trak, offset);
  397. long chunk_sample = quicktime_sample_of_chunk(trak, chunk);
  398. long sample, sample_offset;
  399. quicktime_stsz_table_t *table = trak->mdia.minf.stbl.stsz.table;
  400. long total_samples = trak->mdia.minf.stbl.stsz.total_entries;
  401. if(trak->mdia.minf.stbl.stsz.sample_size)
  402. {
  403. sample = chunk_sample + (offset - chunk_offset) / 
  404. trak->mdia.minf.stbl.stsz.sample_size;
  405. }
  406. else
  407. for(sample = chunk_sample, sample_offset = chunk_offset; 
  408. sample_offset < offset && sample < total_samples; )
  409. {
  410. sample_offset += table[sample].size;
  411. if(sample_offset < offset) sample++;
  412. }
  413. return sample;
  414. }
  415. int quicktime_update_tables(quicktime_t *file, 
  416. quicktime_trak_t *trak, 
  417. long offset, 
  418. long chunk, 
  419. long sample, 
  420. long samples, 
  421. long sample_size,
  422. long sample_duration,
  423. u_char isSyncSample,
  424. long renderingOffset)
  425. {
  426. if (offset + sample_size > file->mdat.size) {
  427. file->mdat.size = offset + sample_size;
  428. }
  429. quicktime_update_stco(&(trak->mdia.minf.stbl.stco), chunk, offset);
  430. if (sample_size) {
  431. quicktime_update_stsz(&(trak->mdia.minf.stbl.stsz), sample, sample_size);
  432. }
  433. quicktime_update_stsc(&(trak->mdia.minf.stbl.stsc), chunk, samples);
  434. if (sample_duration) {
  435. quicktime_update_stts(&(trak->mdia.minf.stbl.stts), sample_duration);
  436. }
  437. if (isSyncSample) {
  438. quicktime_update_stss(&(trak->mdia.minf.stbl.stss), sample);
  439. }
  440. quicktime_update_ctts(&(trak->mdia.minf.stbl.ctts), renderingOffset);
  441. return 0;
  442. }
  443. int quicktime_trak_duration(quicktime_trak_t *trak, long *duration, long *timescale)
  444. {
  445. quicktime_stts_t *stts = &(trak->mdia.minf.stbl.stts);
  446. int i;
  447. *duration = 0;
  448. /* hint track duration is that of reference track */
  449. if (quicktime_trak_is_hint(trak)) {
  450. #ifdef DEBUG
  451. if ((quicktime_trak_t*)trak->tref.hint.traks[0] == trak) {
  452. printf("quicktime_trak_duration: BUG, self reference loop!!!n");
  453. *duration = 0;
  454. *timescale = 1;
  455. return 0;
  456. }
  457. if ((quicktime_trak_t*)trak->tref.hint.traks[0] == NULL) {
  458. printf("quicktime_trak_duration: BUG, NULL reference!!!n");
  459. *duration = 0;
  460. *timescale = 1;
  461. return 0;
  462. }
  463. #endif /* DEBUG */
  464. return quicktime_trak_duration(
  465. (quicktime_trak_t*)trak->tref.hint.traks[0], duration, timescale);
  466. }
  467. for(i = 0; i < stts->total_entries; i++) {
  468. *duration += stts->table[i].sample_duration * stts->table[i].sample_count;
  469. }
  470. *timescale = trak->mdia.mdhd.time_scale;
  471. return 0;
  472. }
  473. int quicktime_trak_fix_counts(quicktime_t *file, quicktime_trak_t *trak)
  474. {
  475. long samples = quicktime_track_samples(file, trak);
  476. if (trak->mdia.minf.stbl.stts.total_entries == 1) {
  477. trak->mdia.minf.stbl.stts.table[0].sample_count = samples;
  478. }
  479. if(trak->mdia.minf.stbl.stsz.sample_size)
  480. trak->mdia.minf.stbl.stsz.total_entries = samples;
  481. return 0;
  482. }
  483. long quicktime_chunk_samples(quicktime_trak_t *trak, long chunk)
  484. {
  485. long result, current_chunk;
  486. quicktime_stsc_t *stsc = &(trak->mdia.minf.stbl.stsc);
  487. long i = stsc->total_entries - 1;
  488. do
  489. {
  490. current_chunk = stsc->table[i].chunk;
  491. result = stsc->table[i].samples;
  492. i--;
  493. }while(i >= 0 && current_chunk > chunk);
  494. return result;
  495. }
  496. int quicktime_trak_shift_offsets(quicktime_trak_t *trak, long offset)
  497. {
  498. quicktime_stco_t *stco = &(trak->mdia.minf.stbl.stco);
  499. int i;
  500. for(i = 0; i < stco->total_entries; i++)
  501. {
  502. stco->table[i].offset += offset;
  503. }
  504. return 0;
  505. }