"Fossies" - the Fresh Open Source Software Archive

Member "quicktime4linux-2.3/trak.c" (9 Jan 2007, 16766 Bytes) of package /linux/privat/old/quicktime4linux-2.3-src.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #include "funcprotos.h"
    2 #include "quicktime.h"
    3 
    4 
    5 
    6 
    7 int quicktime_trak_init(quicktime_trak_t *trak)
    8 {
    9     quicktime_tkhd_init(&(trak->tkhd));
   10     quicktime_edts_init(&(trak->edts));
   11     quicktime_mdia_init(&(trak->mdia));
   12     return 0;
   13 }
   14 
   15 int quicktime_trak_init_video(quicktime_t *file, 
   16                             quicktime_trak_t *trak, 
   17                             int frame_w, 
   18                             int frame_h, 
   19                             float frame_rate,
   20                             char *compressor)
   21 {
   22 
   23     quicktime_tkhd_init_video(file, 
   24         &(trak->tkhd), 
   25         frame_w, 
   26         frame_h);
   27     quicktime_mdia_init_video(file, 
   28         &(trak->mdia), 
   29         frame_w, 
   30         frame_h, 
   31         frame_rate, 
   32         compressor);
   33     quicktime_edts_init_table(&(trak->edts));
   34 
   35     return 0;
   36 }
   37 
   38 int quicktime_trak_init_audio(quicktime_t *file, 
   39                             quicktime_trak_t *trak, 
   40                             int channels, 
   41                             int sample_rate, 
   42                             int bits, 
   43                             char *compressor)
   44 {
   45     quicktime_mdia_init_audio(file, &(trak->mdia), 
   46         channels, 
   47         sample_rate, 
   48         bits, 
   49         compressor);
   50     quicktime_edts_init_table(&(trak->edts));
   51     return 0;
   52 }
   53 
   54 int quicktime_trak_delete(quicktime_trak_t *trak)
   55 {
   56     quicktime_mdia_delete(&(trak->mdia));
   57     quicktime_edts_delete(&(trak->edts));
   58     quicktime_tkhd_delete(&(trak->tkhd));
   59     return 0;
   60 }
   61 
   62 
   63 int quicktime_trak_dump(quicktime_trak_t *trak)
   64 {
   65     printf(" track\n");
   66     quicktime_tkhd_dump(&(trak->tkhd));
   67     quicktime_edts_dump(&(trak->edts));
   68     quicktime_mdia_dump(&(trak->mdia));
   69 
   70     return 0;
   71 }
   72 
   73 // Used when reading a file
   74 quicktime_trak_t* quicktime_add_trak(quicktime_t *file)
   75 {
   76     quicktime_moov_t *moov = &(file->moov);
   77     if(moov->total_tracks < MAXTRACKS)
   78     {
   79         moov->trak[moov->total_tracks] = calloc(1, sizeof(quicktime_trak_t));
   80         quicktime_trak_init(moov->trak[moov->total_tracks]);
   81         moov->total_tracks++;
   82     }
   83     return moov->trak[moov->total_tracks - 1];
   84 }
   85 
   86 int quicktime_delete_trak(quicktime_moov_t *moov)
   87 {
   88     if(moov->total_tracks)
   89     {
   90         moov->total_tracks--;
   91         quicktime_trak_delete(moov->trak[moov->total_tracks]);
   92         free(moov->trak[moov->total_tracks]);
   93     }
   94     return 0;
   95 }
   96 
   97 
   98 int quicktime_read_trak(quicktime_t *file, quicktime_trak_t *trak, quicktime_atom_t *trak_atom)
   99 {
  100     quicktime_atom_t leaf_atom;
  101 
  102     do
  103     {
  104         quicktime_atom_read_header(file, &leaf_atom);
  105 
  106 //printf("quicktime_read_trak %llx %llx\n", quicktime_position(file), quicktime_ftell(file));
  107 /* mandatory */
  108         if(quicktime_atom_is(&leaf_atom, "tkhd"))
  109             { quicktime_read_tkhd(file, &(trak->tkhd)); }
  110         else
  111         if(quicktime_atom_is(&leaf_atom, "mdia"))
  112             { quicktime_read_mdia(file, &(trak->mdia), &leaf_atom); }
  113         else
  114 /* optional */
  115         if(quicktime_atom_is(&leaf_atom, "clip"))
  116             { quicktime_atom_skip(file, &leaf_atom); }
  117         else
  118         if(quicktime_atom_is(&leaf_atom, "matt"))
  119             { quicktime_atom_skip(file, &leaf_atom); }
  120         else
  121         if(quicktime_atom_is(&leaf_atom, "edts"))
  122             { quicktime_read_edts(file, &(trak->edts), &leaf_atom); }
  123         else
  124         if(quicktime_atom_is(&leaf_atom, "load"))
  125             { quicktime_atom_skip(file, &leaf_atom); }
  126         else
  127         if(quicktime_atom_is(&leaf_atom, "tref"))
  128             { quicktime_atom_skip(file, &leaf_atom); }
  129         else
  130         if(quicktime_atom_is(&leaf_atom, "imap"))
  131             { quicktime_atom_skip(file, &leaf_atom); }
  132         else
  133         if(quicktime_atom_is(&leaf_atom, "udta"))
  134             { quicktime_atom_skip(file, &leaf_atom); }
  135         else
  136             quicktime_atom_skip(file, &leaf_atom);
  137 //printf("quicktime_read_trak %llx %llx\n", quicktime_position(file), leaf_atom.end);
  138     }while(quicktime_position(file) < trak_atom->end);
  139 
  140     return 0;
  141 }
  142 
  143 int quicktime_write_trak(quicktime_t *file, 
  144     quicktime_trak_t *trak, 
  145     long moov_time_scale)
  146 {
  147     long duration;
  148     long timescale;
  149     quicktime_atom_t atom;
  150     quicktime_atom_write_header(file, &atom, "trak");
  151     quicktime_trak_duration(trak, &duration, &timescale);
  152 
  153 /*printf("quicktime_write_trak duration %d\n", duration); */
  154 /* get duration in movie's units */
  155     trak->tkhd.duration = (long)((float)duration / timescale * moov_time_scale);
  156     trak->mdia.mdhd.duration = duration;
  157     trak->mdia.mdhd.time_scale = timescale;
  158 
  159     quicktime_write_tkhd(file, &(trak->tkhd));
  160     quicktime_write_edts(file, &(trak->edts), trak->tkhd.duration);
  161     quicktime_write_mdia(file, &(trak->mdia));
  162 
  163     quicktime_atom_write_footer(file, &atom);
  164 
  165     return 0;
  166 }
  167 
  168 int64_t quicktime_track_end(quicktime_trak_t *trak)
  169 {
  170 /* get the byte endpoint of the track in the file */
  171     int64_t size = 0;
  172     int64_t chunk, chunk_offset, chunk_samples, sample;
  173     quicktime_stsz_t *stsz = &(trak->mdia.minf.stbl.stsz);
  174     quicktime_stsz_table_t *table = stsz->table;
  175     quicktime_stsc_t *stsc = &(trak->mdia.minf.stbl.stsc);
  176     quicktime_stco_t *stco;
  177 
  178 /* get the last chunk offset */
  179 /* the chunk offsets contain the HEADER_LENGTH themselves */
  180     stco = &(trak->mdia.minf.stbl.stco);
  181     chunk = stco->total_entries;
  182     size = chunk_offset = stco->table[chunk - 1].offset;
  183 
  184 /* get the number of samples in the last chunk */
  185     chunk_samples = stsc->table[stsc->total_entries - 1].samples;
  186 
  187 /* get the size of last samples */
  188     if(stsz->sample_size)
  189     {
  190 /* assume audio so calculate the sample size */
  191         size += chunk_samples * stsz->sample_size
  192             * trak->mdia.minf.stbl.stsd.table[0].channels 
  193             * trak->mdia.minf.stbl.stsd.table[0].sample_size / 8;
  194     }
  195     else
  196     {
  197 /* assume video */
  198         for(sample = stsz->total_entries - chunk_samples; 
  199             sample < stsz->total_entries; sample++)
  200         {
  201             size += stsz->table[sample].size;
  202         }
  203     }
  204 
  205     return size;
  206 }
  207 
  208 long quicktime_track_samples(quicktime_t *file, quicktime_trak_t *trak)
  209 {
  210 /*printf("file->rd %d file->wr %d\n", file->rd, file->wr); */
  211     if(file->wr)
  212     {
  213 /* get the sample count when creating a new file */
  214         quicktime_stsc_table_t *table = trak->mdia.minf.stbl.stsc.table;
  215         long total_entries = trak->mdia.minf.stbl.stsc.total_entries;
  216         long chunk = trak->mdia.minf.stbl.stco.total_entries;
  217         long sample;
  218 
  219         if(chunk)
  220         {
  221             sample = quicktime_sample_of_chunk(trak, chunk);
  222             sample += table[total_entries - 1].samples;
  223         }
  224         else 
  225             sample = 0;
  226 
  227         return sample;
  228     }
  229     else
  230     {
  231 /* get the sample count when reading only */
  232         quicktime_stts_t *stts = &(trak->mdia.minf.stbl.stts);
  233         int64_t total = 0;
  234         int i;
  235 
  236         if(trak->mdia.minf.is_audio)
  237         {
  238 
  239 // Get total sample duration
  240             for(i = 0; i < stts->total_entries; i++)
  241             {
  242                 total += stts->table[i].sample_count *
  243                     stts->table[i].sample_duration;
  244             }
  245 
  246             return total;
  247         }
  248         else
  249         if(trak->mdia.minf.is_video)
  250         {
  251 /* Get total number of samples */
  252             for(i = 0; i < stts->total_entries; i++)
  253             {
  254                 total += stts->table[i].sample_count;
  255             }
  256             return total;
  257         }
  258         return total;
  259     }
  260 }
  261 
  262 long quicktime_sample_of_chunk(quicktime_trak_t *trak, long chunk)
  263 {
  264     quicktime_stsc_table_t *table = trak->mdia.minf.stbl.stsc.table;
  265     long total_entries = trak->mdia.minf.stbl.stsc.total_entries;
  266     long chunk1entry, chunk2entry;
  267     long chunk1, chunk2, chunks, total = 0;
  268 
  269     for(chunk1entry = total_entries - 1, chunk2entry = total_entries; 
  270         chunk1entry >= 0; 
  271         chunk1entry--, chunk2entry--)
  272     {
  273         chunk1 = table[chunk1entry].chunk;
  274 
  275         if(chunk > chunk1)
  276         {
  277             if(chunk2entry < total_entries)
  278             {
  279                 chunk2 = table[chunk2entry].chunk;
  280 
  281                 if(chunk < chunk2) chunk2 = chunk;
  282             }
  283             else
  284                 chunk2 = chunk;
  285 
  286             chunks = chunk2 - chunk1;
  287 
  288             total += chunks * table[chunk1entry].samples;
  289         }
  290     }
  291 
  292     return total;
  293 }
  294 
  295 // For AVI
  296 int quicktime_avg_chunk_samples(quicktime_t *file, quicktime_trak_t *trak)
  297 {
  298     int i, chunk = trak->mdia.minf.stbl.stco.total_entries - 1;
  299     long total_samples;
  300 
  301     if(chunk >= 0)
  302     {
  303         total_samples = quicktime_sample_of_chunk(trak, chunk);
  304         return total_samples / (chunk + 1);
  305     }
  306     else
  307     {
  308         total_samples = quicktime_track_samples(file, trak);
  309         return total_samples;
  310     }
  311 }
  312 
  313 int quicktime_chunk_of_sample(int64_t *chunk_sample, 
  314     int64_t *chunk, 
  315     quicktime_trak_t *trak, 
  316     int64_t sample)
  317 {
  318     quicktime_stsc_table_t *table = trak->mdia.minf.stbl.stsc.table;
  319     long total_entries = trak->mdia.minf.stbl.stsc.total_entries;
  320     long chunk2entry;
  321     long chunk1, chunk2, chunk1samples, range_samples, total = 0;
  322 
  323     chunk1 = 1;
  324     chunk1samples = 0;
  325     chunk2entry = 0;
  326 
  327     if(!total_entries)
  328     {
  329         *chunk_sample = 0;
  330         *chunk = 0;
  331         return 0;
  332     }
  333 
  334     do
  335     {
  336         chunk2 = table[chunk2entry].chunk;
  337         *chunk = chunk2 - chunk1;
  338         range_samples = *chunk * chunk1samples;
  339 
  340         if(sample < total + range_samples) break;
  341 
  342         chunk1samples = table[chunk2entry].samples;
  343 //printf("quicktime_chunk_of_sample chunk1samples=%lld\n", chunk1samples);
  344         chunk1 = chunk2;
  345 
  346         if(chunk2entry < total_entries)
  347         {
  348             chunk2entry++;
  349             total += range_samples;
  350         }
  351     }while(chunk2entry < total_entries);
  352 //printf("quicktime_chunk_of_sample chunk1samples=%lld sample=%lld total=%lld chunk1=%lld\n",
  353 //chunk1samples, sample, total, chunk1);
  354 
  355     if(chunk1samples)
  356         *chunk = (sample - total) / chunk1samples + chunk1;
  357     else
  358         *chunk = 1;
  359 
  360     *chunk_sample = total + (*chunk - chunk1) * chunk1samples;
  361     return 0;
  362 }
  363 
  364 int64_t quicktime_chunk_to_offset(quicktime_t *file, quicktime_trak_t *trak, long chunk)
  365 {
  366     quicktime_stco_table_t *table = trak->mdia.minf.stbl.stco.table;
  367     int64_t result = 0;
  368 
  369     if(trak->mdia.minf.stbl.stco.total_entries && 
  370         chunk > trak->mdia.minf.stbl.stco.total_entries)
  371         result = table[trak->mdia.minf.stbl.stco.total_entries - 1].offset;
  372     else
  373     if(trak->mdia.minf.stbl.stco.total_entries)
  374         result = table[chunk - 1].offset;
  375     else
  376         result = HEADER_LENGTH * 2;
  377 
  378 // Skip chunk header for AVI.  Skip it here instead of in read_chunk because some
  379 // codecs can't use read_chunk
  380     if(file->use_avi)
  381     {
  382 //printf("quicktime_chunk_to_offset 1 %llx %llx\n", result, file->mdat.atom.start);
  383         result += 8 + file->mdat.atom.start;
  384     }
  385     return result;
  386 }
  387 
  388 long quicktime_offset_to_chunk(int64_t *chunk_offset, 
  389     quicktime_trak_t *trak, 
  390     int64_t offset)
  391 {
  392     quicktime_stco_table_t *table = trak->mdia.minf.stbl.stco.table;
  393     int i;
  394 
  395     for(i = trak->mdia.minf.stbl.stco.total_entries - 1; i >= 0; i--)
  396     {
  397         if(table[i].offset <= offset)
  398         {
  399             *chunk_offset = table[i].offset;
  400             return i + 1;
  401         }
  402     }
  403     *chunk_offset = HEADER_LENGTH * 2;
  404     return 1;
  405 }
  406 
  407 int quicktime_chunk_bytes(quicktime_t *file, 
  408     int64_t *chunk_offset,
  409     int chunk, 
  410     quicktime_trak_t *trak)
  411 {
  412     int result;
  413     *chunk_offset = quicktime_chunk_to_offset(file, trak, chunk);
  414     quicktime_set_position(file, *chunk_offset - 4);
  415     result = quicktime_read_int32_le(file);
  416     return result;
  417 }
  418 
  419 int64_t quicktime_sample_range_size(quicktime_trak_t *trak, 
  420     long chunk_sample, 
  421     long sample)
  422 {
  423     quicktime_stsz_table_t *table = trak->mdia.minf.stbl.stsz.table;
  424     int64_t i, total;
  425 
  426     if(trak->mdia.minf.stbl.stsz.sample_size)
  427     {
  428 /* assume audio */
  429         return quicktime_samples_to_bytes(trak, sample - chunk_sample);
  430     }
  431     else
  432     {
  433 /* video or vbr audio */
  434         for(i = chunk_sample, total = 0; 
  435             i < sample && i < trak->mdia.minf.stbl.stsz.total_entries; 
  436             i++)
  437         {
  438             total += trak->mdia.minf.stbl.stsz.table[i].size;
  439         }
  440     }
  441     return total;
  442 }
  443 
  444 int64_t quicktime_sample_to_offset(quicktime_t *file, 
  445     quicktime_trak_t *trak, 
  446     long sample)
  447 {
  448     int64_t chunk, chunk_sample, chunk_offset1, chunk_offset2;
  449 
  450     quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, sample);
  451     chunk_offset1 = quicktime_chunk_to_offset(file, trak, chunk);
  452     chunk_offset2 = chunk_offset1 + 
  453         quicktime_sample_range_size(trak, chunk_sample, sample);
  454     return chunk_offset2;
  455 }
  456 
  457 long quicktime_offset_to_sample(quicktime_trak_t *trak, int64_t offset)
  458 {
  459     int64_t chunk_offset;
  460     int64_t chunk = quicktime_offset_to_chunk(&chunk_offset, trak, offset);
  461     int64_t chunk_sample = quicktime_sample_of_chunk(trak, chunk);
  462     int64_t sample, sample_offset;
  463     quicktime_stsz_table_t *table = trak->mdia.minf.stbl.stsz.table;
  464     int64_t total_samples = trak->mdia.minf.stbl.stsz.total_entries;
  465 
  466     if(trak->mdia.minf.stbl.stsz.sample_size)
  467     {
  468         sample = chunk_sample + (offset - chunk_offset) / 
  469             trak->mdia.minf.stbl.stsz.sample_size;
  470     }
  471     else
  472     for(sample = chunk_sample, sample_offset = chunk_offset; 
  473         sample_offset < offset && sample < total_samples; )
  474     {
  475         sample_offset += table[sample].size;
  476         if(sample_offset < offset) sample++;
  477     }
  478     
  479     return sample;
  480 }
  481 
  482 void quicktime_write_chunk_header(quicktime_t *file, 
  483     quicktime_trak_t *trak, 
  484     quicktime_atom_t *chunk)
  485 {
  486     if(file->use_avi)
  487     {
  488 /* Get tag from first riff strl */
  489         quicktime_riff_t *first_riff = file->riff[0];
  490         quicktime_hdrl_t *hdrl = &first_riff->hdrl;
  491         quicktime_strl_t *strl = hdrl->strl[trak->tkhd.track_id - 1];
  492         char *tag = strl->tag;
  493 
  494 /* Create new RIFF object at 1 Gig mark */
  495         quicktime_riff_t *riff = file->riff[file->total_riffs - 1];
  496         if(quicktime_position(file) - riff->atom.start > 0x40000000)
  497         {
  498             quicktime_finalize_riff(file, riff);
  499             quicktime_init_riff(file);
  500         }
  501 
  502         
  503 
  504 /* Write AVI header */
  505         quicktime_atom_write_header(file, chunk, tag);
  506     }
  507     else
  508     {
  509         chunk->start = quicktime_position(file);
  510     }
  511 }
  512 
  513 void quicktime_write_chunk_footer(quicktime_t *file, 
  514     quicktime_trak_t *trak,
  515     int current_chunk,
  516     quicktime_atom_t *chunk, 
  517     int samples)
  518 {
  519     int64_t offset = chunk->start;
  520     int sample_size = quicktime_position(file) - offset;
  521 
  522 
  523 // Write AVI footer
  524     if(file->use_avi)
  525     {
  526         quicktime_atom_write_footer(file, chunk);
  527 
  528 // Save version 1 index entry for first RIFF only
  529         if(file->total_riffs < 2)
  530         {
  531             quicktime_update_idx1table(file, 
  532                 trak, 
  533                 offset, 
  534                 sample_size);
  535         }
  536 
  537 // Save partial index entry
  538         quicktime_update_ixtable(file, 
  539             trak, 
  540             offset, 
  541             sample_size);
  542     }
  543 
  544     if(offset + sample_size > file->mdat.atom.size)
  545         file->mdat.atom.size = offset + sample_size;
  546 
  547     quicktime_update_stco(&(trak->mdia.minf.stbl.stco), 
  548         current_chunk, 
  549         offset);
  550 
  551     if(trak->mdia.minf.is_video)
  552         quicktime_update_stsz(&(trak->mdia.minf.stbl.stsz), 
  553         current_chunk - 1, 
  554         sample_size);
  555 
  556     quicktime_update_stsc(&(trak->mdia.minf.stbl.stsc), 
  557         current_chunk, 
  558         samples);
  559 }
  560 
  561 int quicktime_write_vbr_frame(quicktime_t *file, 
  562     int track,
  563     char *data,
  564     int data_size,
  565     int samples)
  566 {
  567     quicktime_audio_map_t *track_map = &(file->atracks[track]);
  568     quicktime_trak_t *trak = track_map->track;
  569     quicktime_atom_t chunk_atom;
  570     int result = 0;
  571 
  572 
  573     quicktime_write_chunk_header(file, trak, &chunk_atom);
  574     result = !quicktime_write_data(file, data, data_size);
  575     int64_t offset = chunk_atom.start;
  576 
  577 // AVI case
  578     if(file->use_avi)
  579     {
  580         quicktime_atom_write_footer(file, &chunk_atom);
  581 // Save version 1 index entry for first RIFF only
  582         if(file->total_riffs < 2)
  583         {
  584             quicktime_update_idx1table(file, 
  585                 trak, 
  586                 offset, 
  587                 data_size);
  588         }
  589 
  590 // Save version 2 index entry
  591         quicktime_update_ixtable(file, 
  592             trak, 
  593             offset, 
  594             data_size);
  595     }
  596 
  597 // Update MDAT size
  598     if(offset + data_size > file->mdat.atom.size)
  599         file->mdat.atom.size = offset + data_size;
  600 
  601 // Update time to sample table
  602     quicktime_stts_append_audio(file, 
  603         &(trak->mdia.minf.stbl.stts), 
  604         samples);
  605 
  606     int64_t total_chunks = quicktime_stts_total_samples(file,
  607         &(trak->mdia.minf.stbl.stts));
  608     quicktime_update_stco(&(trak->mdia.minf.stbl.stco), 
  609         total_chunks, 
  610         offset);
  611     quicktime_update_stsc(&(trak->mdia.minf.stbl.stsc), 
  612         total_chunks, 
  613         1);
  614     quicktime_update_stsz(&(trak->mdia.minf.stbl.stsz), 
  615         total_chunks - 1, 
  616         data_size);
  617 
  618 
  619     return result;
  620 }
  621 
  622 
  623 
  624 /**
  625  * This is used for writing the header
  626  **/
  627 int quicktime_trak_duration(quicktime_trak_t *trak, 
  628     long *duration, 
  629     long *timescale)
  630 {
  631     quicktime_stts_t *stts = &(trak->mdia.minf.stbl.stts);
  632     int i;
  633     *duration = 0;
  634 
  635     for(i = 0; i < stts->total_entries; i++)
  636     {
  637         *duration += stts->table[i].sample_duration * 
  638             stts->table[i].sample_count;
  639     }
  640 
  641     *timescale = trak->mdia.mdhd.time_scale;
  642     return 0;
  643 }
  644 
  645 int quicktime_trak_fix_counts(quicktime_t *file, quicktime_trak_t *trak)
  646 {
  647     long samples = quicktime_track_samples(file, trak);
  648 
  649     if(!trak->mdia.minf.stbl.stts.is_vbr)
  650     {
  651         trak->mdia.minf.stbl.stts.table[0].sample_count = samples;
  652 
  653         if(!trak->mdia.minf.stbl.stsz.total_entries)
  654         {
  655             trak->mdia.minf.stbl.stsz.sample_size = 1;
  656             trak->mdia.minf.stbl.stsz.total_entries = samples;
  657         }
  658     }
  659     return 0;
  660 }
  661 
  662 long quicktime_chunk_samples(quicktime_trak_t *trak, long chunk)
  663 {
  664     long result, current_chunk;
  665     quicktime_stsc_t *stsc = &(trak->mdia.minf.stbl.stsc);
  666     long i = stsc->total_entries - 1;
  667 
  668     do
  669     {
  670         current_chunk = stsc->table[i].chunk;
  671         result = stsc->table[i].samples;
  672         i--;
  673     }while(i >= 0 && current_chunk > chunk);
  674 
  675     return result;
  676 }
  677 
  678 int quicktime_trak_shift_offsets(quicktime_trak_t *trak, int64_t offset)
  679 {
  680     quicktime_stco_t *stco = &(trak->mdia.minf.stbl.stco);
  681     int i;
  682 
  683     for(i = 0; i < stco->total_entries; i++)
  684     {
  685         stco->table[i].offset += offset;
  686     }
  687     return 0;
  688 }
  689 
  690 char* quicktime_compressor(quicktime_trak_t *track)
  691 {
  692     return track->mdia.minf.stbl.stsd.table[0].format;
  693 }
  694 
  695 
  696 int quicktime_sample_duration(quicktime_trak_t *trak)
  697 {
  698     quicktime_stts_t *stts = &trak->mdia.minf.stbl.stts;
  699     int i;
  700     int max_count = 0;
  701     int result = 1;
  702     for(i = 0; i < stts->total_entries; i++)
  703     {
  704         quicktime_stts_table_t *table = &stts->table[i];
  705         if(table->sample_count > max_count)
  706         {
  707             max_count = table->sample_count;
  708             result = table->sample_duration;
  709         }
  710     }
  711     return result;
  712 }
  713 
  714