trak.c
上传用户:luping1608
上传日期:2007-01-06
资源大小:38k
文件大小:11k
源码类别:

多媒体

开发平台:

Unix_Linux

  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_mdia_init(&(trak->mdia));
  7. return 0;
  8. }
  9. int quicktime_trak_init_video(quicktime_t *file, 
  10. quicktime_trak_t *trak, 
  11. int frame_w, 
  12. int frame_h, 
  13. float frame_rate,
  14. char *compressor)
  15. {
  16. quicktime_tkhd_init_video(file, &(trak->tkhd), frame_w, frame_h);
  17. quicktime_mdia_init_video(file, &(trak->mdia), frame_w, frame_h, frame_rate, compressor);
  18. quicktime_edts_init_table(&(trak->edts));
  19. return 0;
  20. }
  21. int quicktime_trak_init_audio(quicktime_t *file, 
  22. quicktime_trak_t *trak, 
  23. int channels, 
  24. int sample_rate, 
  25. int bits, 
  26. char *compressor)
  27. {
  28. quicktime_mdia_init_audio(file, &(trak->mdia), channels, sample_rate, bits, compressor);
  29. quicktime_edts_init_table(&(trak->edts));
  30. return 0;
  31. }
  32. int quicktime_trak_delete(quicktime_trak_t *trak)
  33. {
  34. quicktime_tkhd_delete(&(trak->tkhd));
  35. return 0;
  36. }
  37. int quicktime_trak_dump(quicktime_trak_t *trak)
  38. {
  39. printf(" trackn");
  40. quicktime_tkhd_dump(&(trak->tkhd));
  41. quicktime_edts_dump(&(trak->edts));
  42. quicktime_mdia_dump(&(trak->mdia));
  43. return 0;
  44. }
  45. quicktime_trak_t* quicktime_add_trak(quicktime_moov_t *moov)
  46. {
  47. if(moov->total_tracks < MAXTRACKS)
  48. {
  49. moov->trak[moov->total_tracks] = malloc(sizeof(quicktime_trak_t));
  50. quicktime_trak_init(moov->trak[moov->total_tracks]);
  51. moov->total_tracks++;
  52. }
  53. return moov->trak[moov->total_tracks - 1];
  54. }
  55. int quicktime_delete_trak(quicktime_moov_t *moov)
  56. {
  57. if(moov->total_tracks)
  58. {
  59. moov->total_tracks--;
  60. quicktime_trak_delete(moov->trak[moov->total_tracks]);
  61. free(moov->trak[moov->total_tracks]);
  62. }
  63. return 0;
  64. }
  65. int quicktime_read_trak(quicktime_t *file, quicktime_trak_t *trak, quicktime_atom_t *trak_atom)
  66. {
  67. quicktime_atom_t leaf_atom;
  68. do
  69. {
  70. quicktime_atom_read_header(file->stream, &leaf_atom);
  71. // mandatory
  72. if(quicktime_atom_is(&leaf_atom, "tkhd"))
  73. { quicktime_read_tkhd(file, &(trak->tkhd)); }
  74. else
  75. if(quicktime_atom_is(&leaf_atom, "mdia"))
  76. { quicktime_read_mdia(file, &(trak->mdia), &leaf_atom); }
  77. else
  78. // optional
  79. if(quicktime_atom_is(&leaf_atom, "clip"))
  80. { quicktime_atom_skip(file, &leaf_atom); }
  81. else
  82. if(quicktime_atom_is(&leaf_atom, "matt"))
  83. { quicktime_atom_skip(file, &leaf_atom); }
  84. else
  85. if(quicktime_atom_is(&leaf_atom, "edts"))
  86. { quicktime_read_edts(file, &(trak->edts), &leaf_atom); }
  87. else
  88. if(quicktime_atom_is(&leaf_atom, "load"))
  89. { quicktime_atom_skip(file, &leaf_atom); }
  90. else
  91. if(quicktime_atom_is(&leaf_atom, "tref"))
  92. { quicktime_atom_skip(file, &leaf_atom); }
  93. else
  94. if(quicktime_atom_is(&leaf_atom, "imap"))
  95. { quicktime_atom_skip(file, &leaf_atom); }
  96. else
  97. if(quicktime_atom_is(&leaf_atom, "udta"))
  98. { quicktime_atom_skip(file, &leaf_atom); }
  99. else
  100. quicktime_atom_skip(file, &leaf_atom);
  101. }while(quicktime_position(file) < trak_atom->end);
  102. return 0;
  103. }
  104. int quicktime_write_trak(quicktime_t *file, quicktime_trak_t *trak, long moov_time_scale)
  105. {
  106. long duration;
  107. long timescale;
  108. quicktime_atom_t atom;
  109. quicktime_atom_write_header(file, &atom, "trak");
  110. quicktime_trak_duration(trak, &duration, &timescale);
  111. //printf("quicktime_write_trak duration %dn", duration);
  112. // get duration in movie's units
  113. trak->tkhd.duration = (long)((float)duration / timescale * moov_time_scale);
  114. trak->mdia.mdhd.duration = duration;
  115. trak->mdia.mdhd.time_scale = timescale;
  116. quicktime_write_tkhd(file, &(trak->tkhd));
  117. quicktime_write_edts(file, &(trak->edts), trak->tkhd.duration);
  118. quicktime_write_mdia(file, &(trak->mdia));
  119. quicktime_atom_write_footer(file, &atom);
  120. return 0;
  121. }
  122. long quicktime_track_end(quicktime_trak_t *trak)
  123. {
  124. // get the byte endpoint of the track in the file
  125. long size = 0;
  126. long chunk, chunk_offset, chunk_samples, sample;
  127. quicktime_stsz_t *stsz = &(trak->mdia.minf.stbl.stsz);
  128. quicktime_stsz_table_t *table = stsz->table;
  129. quicktime_stsc_t *stsc = &(trak->mdia.minf.stbl.stsc);
  130. quicktime_stco_t *stco;
  131. // get the last chunk offset
  132. // the chunk offsets contain the HEADER_LENGTH themselves
  133. stco = &(trak->mdia.minf.stbl.stco);
  134. chunk = stco->total_entries;
  135. size = chunk_offset = stco->table[chunk - 1].offset;
  136. // get the number of samples in the last chunk
  137. chunk_samples = stsc->table[stsc->total_entries - 1].samples;
  138. // get the size of last samples
  139. if(stsz->sample_size)
  140. {
  141. // assume audio so calculate the sample size
  142. size += chunk_samples * stsz->sample_size
  143. * trak->mdia.minf.stbl.stsd.table[0].channels 
  144. * trak->mdia.minf.stbl.stsd.table[0].sample_size / 8;
  145. }
  146. else
  147. {
  148. // assume video
  149. for(sample = stsz->total_entries - chunk_samples; 
  150. sample < stsz->total_entries; sample++)
  151. {
  152. size += stsz->table[sample].size;
  153. }
  154. }
  155. return size;
  156. }
  157. long quicktime_track_samples(quicktime_t *file, quicktime_trak_t *trak)
  158. {
  159. //printf("file->rd %d file->wr %dn", file->rd, file->wr);
  160. if(file->wr)
  161. {
  162. // get the sample count when creating a new file
  163.   quicktime_stsc_table_t *table = trak->mdia.minf.stbl.stsc.table;
  164. long total_entries = trak->mdia.minf.stbl.stsc.total_entries;
  165. long chunk = trak->mdia.minf.stbl.stco.total_entries;
  166. long sample;
  167. if(chunk)
  168. {
  169. sample = quicktime_sample_of_chunk(trak, chunk);
  170. sample += table[total_entries - 1].samples;
  171. }
  172. else 
  173. sample = 0;
  174. return sample;
  175. }
  176. else
  177. {
  178. // get the sample count when reading only
  179. quicktime_stts_t *stts = &(trak->mdia.minf.stbl.stts);
  180. int i;
  181. long total = 0;
  182. for(i = 0; i < stts->total_entries; i++)
  183. {
  184. total += stts->table[i].sample_count;
  185. }
  186. return total;
  187. }
  188. }
  189. long quicktime_sample_of_chunk(quicktime_trak_t *trak, long chunk)
  190. {
  191. quicktime_stsc_table_t *table = trak->mdia.minf.stbl.stsc.table;
  192. long total_entries = trak->mdia.minf.stbl.stsc.total_entries;
  193. long chunk1entry, chunk2entry;
  194. long chunk1, chunk2, chunks, total = 0;
  195. for(chunk1entry = total_entries - 1, chunk2entry = total_entries; 
  196. chunk1entry >= 0; 
  197. chunk1entry--, chunk2entry--)
  198. {
  199. chunk1 = table[chunk1entry].chunk;
  200. if(chunk > chunk1)
  201. {
  202. if(chunk2entry < total_entries)
  203. {
  204. chunk2 = table[chunk2entry].chunk;
  205. if(chunk < chunk2) chunk2 = chunk;
  206. }
  207. else
  208. chunk2 = chunk;
  209. chunks = chunk2 - chunk1;
  210. total += chunks * table[chunk1entry].samples;
  211. }
  212. }
  213. return total;
  214. }
  215. int quicktime_chunk_of_sample(long *chunk_sample, long *chunk, quicktime_trak_t *trak, long sample)
  216. {
  217. quicktime_stsc_table_t *table = trak->mdia.minf.stbl.stsc.table;
  218. long total_entries = trak->mdia.minf.stbl.stsc.total_entries;
  219. long chunk2entry;
  220. long chunk1, chunk2, chunk1samples, range_samples, total = 0;
  221. chunk1 = 1;
  222. chunk1samples = 0;
  223. chunk2entry = 0;
  224. do
  225. {
  226. chunk2 = table[chunk2entry].chunk;
  227. *chunk = chunk2 - chunk1;
  228. range_samples = *chunk * chunk1samples;
  229. if(sample < total + range_samples) break;
  230. chunk1samples = table[chunk2entry].samples;
  231. chunk1 = chunk2;
  232. if(chunk2entry < total_entries)
  233. {
  234. chunk2entry++;
  235. total += range_samples;
  236. }
  237. }while(chunk2entry < total_entries);
  238. if(chunk1samples)
  239. *chunk = (sample - total) / chunk1samples + chunk1;
  240. else
  241. *chunk = 1;
  242. *chunk_sample = total + (*chunk - chunk1) * chunk1samples;
  243. return 0;
  244. }
  245. long quicktime_chunk_to_offset(quicktime_trak_t *trak, long chunk)
  246. {
  247. quicktime_stco_table_t *table = trak->mdia.minf.stbl.stco.table;
  248. if(trak->mdia.minf.stbl.stco.total_entries && chunk > trak->mdia.minf.stbl.stco.total_entries)
  249. return table[trak->mdia.minf.stbl.stco.total_entries - 1].offset;
  250. else
  251. if(trak->mdia.minf.stbl.stco.total_entries)
  252. return table[chunk - 1].offset;
  253. else
  254. return HEADER_LENGTH;
  255. return 0;
  256. }
  257. long quicktime_offset_to_chunk(long *chunk_offset, quicktime_trak_t *trak, long offset)
  258. {
  259. quicktime_stco_table_t *table = trak->mdia.minf.stbl.stco.table;
  260. int i;
  261. for(i = trak->mdia.minf.stbl.stco.total_entries - 1; i >= 0; i--)
  262. {
  263. if(table[i].offset <= offset)
  264. {
  265. *chunk_offset = table[i].offset;
  266. return i + 1;
  267. }
  268. }
  269. *chunk_offset = HEADER_LENGTH;
  270. return 1;
  271. }
  272. long quicktime_sample_range_size(quicktime_trak_t *trak, long chunk_sample, long sample)
  273. {
  274. quicktime_stsz_table_t *table = trak->mdia.minf.stbl.stsz.table;
  275. long i, total;
  276. if(trak->mdia.minf.stbl.stsz.sample_size)
  277. {
  278. // assume audio
  279. return quicktime_samples_to_bytes(trak, sample - chunk_sample);
  280. //  return (sample - chunk_sample) * trak->mdia.minf.stbl.stsz.sample_size 
  281. //  * trak->mdia.minf.stbl.stsd.table[0].channels 
  282. //  * trak->mdia.minf.stbl.stsd.table[0].sample_size / 8;
  283. }
  284. else
  285. {
  286. // probably video
  287. for(i = chunk_sample, total = 0; i < sample; i++)
  288. {
  289. total += trak->mdia.minf.stbl.stsz.table[i].size;
  290. }
  291. }
  292. return total;
  293. }
  294. long quicktime_sample_to_offset(quicktime_trak_t *trak, long sample)
  295. {
  296. long chunk, chunk_sample, chunk_offset1, chunk_offset2;
  297. quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, sample);
  298. chunk_offset1 = quicktime_chunk_to_offset(trak, chunk);
  299. chunk_offset2 = chunk_offset1 + quicktime_sample_range_size(trak, chunk_sample, sample);
  300. //printf("quicktime_sample_to_offset chunk %d sample %d chunk_offset %d chunk_sample %d chunk_offset + samples %dn",
  301. //  chunk, sample, chunk_offset1, chunk_sample, chunk_offset2);
  302. return chunk_offset2;
  303. }
  304. long quicktime_offset_to_sample(quicktime_trak_t *trak, long offset)
  305. {
  306. long chunk_offset;
  307. long chunk = quicktime_offset_to_chunk(&chunk_offset, trak, offset);
  308. long chunk_sample = quicktime_sample_of_chunk(trak, chunk);
  309. long sample, sample_offset;
  310. quicktime_stsz_table_t *table = trak->mdia.minf.stbl.stsz.table;
  311. long total_samples = trak->mdia.minf.stbl.stsz.total_entries;
  312. if(trak->mdia.minf.stbl.stsz.sample_size)
  313. {
  314. sample = chunk_sample + (offset - chunk_offset) / 
  315. trak->mdia.minf.stbl.stsz.sample_size;
  316. }
  317. else
  318. for(sample = chunk_sample, sample_offset = chunk_offset; 
  319. sample_offset < offset && sample < total_samples; )
  320. {
  321. sample_offset += table[sample].size;
  322. if(sample_offset < offset) sample++;
  323. }
  324. return sample;
  325. }
  326. int quicktime_update_tables(quicktime_trak_t *trak, 
  327. long offset, 
  328. long chunk, 
  329. long sample, 
  330. long samples, 
  331. long sample_size)
  332. {
  333. quicktime_update_stco(&(trak->mdia.minf.stbl.stco), chunk, offset);
  334. if(sample_size) quicktime_update_stsz(&(trak->mdia.minf.stbl.stsz), sample, sample_size);
  335. quicktime_update_stsc(&(trak->mdia.minf.stbl.stsc), chunk, samples);
  336. return 0;
  337. }
  338. int quicktime_trak_duration(quicktime_trak_t *trak, long *duration, long *timescale)
  339. {
  340. quicktime_stts_t *stts = &(trak->mdia.minf.stbl.stts);
  341. int i;
  342. *duration = 0;
  343. for(i = 0; i < stts->total_entries; i++)
  344. {
  345. *duration += stts->table[i].sample_duration * stts->table[i].sample_count;
  346. }
  347. *timescale = trak->mdia.mdhd.time_scale;
  348. return 0;
  349. }
  350. int quicktime_trak_fix_counts(quicktime_t *file, quicktime_trak_t *trak)
  351. {
  352. long samples = quicktime_track_samples(file, trak);
  353. trak->mdia.minf.stbl.stts.table[0].sample_count = samples;
  354. if(trak->mdia.minf.stbl.stsz.sample_size)
  355. trak->mdia.minf.stbl.stsz.total_entries = samples;
  356. return 0;
  357. }
  358. long quicktime_chunk_samples(quicktime_trak_t *trak, long chunk)
  359. {
  360. long result, current_chunk;
  361. quicktime_stsc_t *stsc = &(trak->mdia.minf.stbl.stsc);
  362. long i = stsc->total_entries - 1;
  363. do
  364. {
  365. current_chunk = stsc->table[i].chunk;
  366. result = stsc->table[i].samples;
  367. i--;
  368. }while(i >= 0 && current_chunk > chunk);
  369. return result;
  370. }
  371. int quicktime_trak_shift_offsets(quicktime_trak_t *trak, long offset)
  372. {
  373. quicktime_stco_t *stco = &(trak->mdia.minf.stbl.stco);
  374. int i;
  375. for(i = 0; i < stco->total_entries; i++)
  376. {
  377. stco->table[i].offset += offset;
  378. }
  379. return 0;
  380. }