home *** CD-ROM | disk | FTP | other *** search
/ Geek 6 / Geek-006.iso / linux / video / xmovie-1.5.3.tar.gz / xmovie-1.5.3.tar / xmovie-1.5.3 / quicktime / trak.c < prev    next >
C/C++ Source or Header  |  2000-11-29  |  12KB  |  457 lines

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