From: Torsten J. <t....@gm...> - 2014-02-01 14:32:27
|
# HG changeset patch # User Torsten Jager <t....@gm...> # Date 1391265125 -3600 # Node ID 7dff43b2bd39ca45c92aa925c1883924dca707d0 # Branch default # Parent 04c2280fd10763cb019c829ab9a4e9fa697eec9b demux_qt: rewrite trak builder. Eliminate 5 temporary tables. Fix compressed CBR audio (a52). Add lots of table size guards. Optimize. diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c --- a/src/demuxers/demux_qt.c +++ b/src/demuxers/demux_qt.c @@ -20,6 +20,9 @@ * Quicktime File Demuxer by Mike Melanson (mel...@pc...) * based on a Quicktime parsing experiment entitled 'lazyqt' * + * Atom finder, trak builder rewrite, multiaudio and ISO fragment + * media file support by Torsten Jager (t....@gm...) + * * Ideally, more documentation is forthcoming, but in the meantime: * functional flow: * create_qt_info @@ -207,11 +210,6 @@ } sample_to_chunk_table_t; typedef struct { - unsigned int count; - unsigned int duration; -} time_to_sample_table_t; - -typedef struct { char *url; int64_t data_rate; int qtim_version; @@ -308,16 +306,17 @@ /* chunk offsets */ unsigned int chunk_offset_count; - int64_t *chunk_offset_table; + unsigned char *chunk_offset_table32; + unsigned char *chunk_offset_table64; /* sample sizes */ unsigned int sample_size; unsigned int sample_size_count; - unsigned int *sample_size_table; + unsigned char *sample_size_table; /* sync samples, a.k.a., keyframes */ unsigned int sync_sample_count; - unsigned int *sync_sample_table; + unsigned char *sync_sample_table; /* sample to chunk table */ unsigned int sample_to_chunk_count; @@ -325,11 +324,11 @@ /* time to sample table */ unsigned int time_to_sample_count; - time_to_sample_table_t *time_to_sample_table; + unsigned char *time_to_sample_table; /* pts to dts timeoffset to sample table */ unsigned int timeoffs_to_sample_count; - time_to_sample_table_t *timeoffs_to_sample_table; + unsigned char *timeoffs_to_sample_table; /* what to add to output buffer type */ int audio_index; @@ -690,14 +689,7 @@ for (i = 0; i < info->trak_count; i++) { free(info->traks[i].frames); free(info->traks[i].edit_list_table); - free(info->traks[i].chunk_offset_table); - /* this pointer might have been set to -1 as a special case */ - if (info->traks[i].sample_size_table != (void *)-1) - free(info->traks[i].sample_size_table); - free(info->traks[i].sync_sample_table); free(info->traks[i].sample_to_chunk_table); - free(info->traks[i].time_to_sample_table); - free(info->traks[i].timeoffs_to_sample_table); free(info->traks[i].decoder_config); for (j = 0; j < info->traks[i].stsd_atoms_count; j++) { if (info->traks[i].type == MEDIA_AUDIO) { @@ -949,11 +941,12 @@ trak->edit_list_count = 0; trak->edit_list_table = NULL; trak->chunk_offset_count = 0; - trak->chunk_offset_table = NULL; + trak->chunk_offset_table32 = NULL; + trak->chunk_offset_table64 = NULL; trak->sample_size = 0; trak->sample_size_count = 0; trak->sample_size_table = NULL; - trak->sync_sample_table = 0; + trak->sync_sample_count = 0; trak->sync_sample_table = NULL; trak->sample_to_chunk_count = 0; trak->sample_to_chunk_table = NULL; @@ -1448,25 +1441,14 @@ if (atomsize >= 20) { trak->sample_size = _X_BE_32(&atom[12]); trak->sample_size_count = _X_BE_32(&atom[16]); + if (trak->sample_size_count > (atomsize - 20) / 4) + trak->sample_size_count = (atomsize - 20) / 4; debug_atom_load (" qt stsz atom (sample size atom): sample size = %d, %d entries\n", trak->sample_size, trak->sample_size_count); - /* allocate space and load table only if sample size is 0 */ + /* load table only if sample size is 0 */ /* there may be 0 items + moof fragments later */ - if (trak->sample_size == 0) { - trak->sample_size_table = calloc (trak->sample_size_count + 1, sizeof (trak->sample_size_table[0])); - if (!trak->sample_size_table) { - last_error = QT_NO_MEMORY; - goto free_trak; - } - /* load the sample size table */ - for (j = 0; j < trak->sample_size_count; j++) { - trak->sample_size_table[j] = _X_BE_32(&atom[20 + j * 4]); - debug_atom_load (" sample size %d: %d\n", j, trak->sample_size_table[j]); - } - } else - /* set the pointer to non-NULL to indicate that the atom type has - * already been seen for this trak atom */ - trak->sample_size_table = (void *)-1; + if (trak->sample_size == 0) + trak->sample_size_table = atom + 20; } atom = atoms[7]; /* STSS_ATOM */ @@ -1477,17 +1459,7 @@ trak->sync_sample_count = (atomsize - 16) / 4; debug_atom_load (" qt stss atom (sample sync atom): %d sync samples\n", trak->sync_sample_count); - trak->sync_sample_table = calloc (trak->sync_sample_count + 1, sizeof (trak->sync_sample_table[0])); - if (!trak->sync_sample_table) { - last_error = QT_NO_MEMORY; [... 247 lines omitted ...] - current_offset += - trak->sample_size_table[frame_counter]; + if (size_left) { + size_value = _X_BE_32 (s); s += 4; + size_left--; } + frame->offset = offset_value; + frame->size = size_value; + offset_value += size_value; /* if there is no stss (sample sync) table, make all of the frames * keyframes; otherwise, clear the keyframe bits for now */ if (trak->sync_sample_table) - trak->frames[frame_counter].keyframe = 0; + frame->keyframe = 0; else - trak->frames[frame_counter].keyframe = 1; + frame->keyframe = 1; /* figure out the pts situation */ - trak->frames[frame_counter].pts = current_pts; - current_pts += - trak->time_to_sample_table[pts_index].duration; - pts_index_countdown--; - /* time to refresh countdown? */ - if (!pts_index_countdown) { - pts_index++; - pts_index_countdown = - trak->time_to_sample_table[pts_index].count; + if (duration_left && !duration_countdown) { + duration_countdown = _X_BE_32 (p); p += 4; + duration_value = _X_BE_32 (p); p += 4; + duration_left--; } + frame->pts = pts_value; + pts_value += duration_value; + duration_countdown--; /* offset pts for reordered video */ - if (ptsoffs_index < trak->timeoffs_to_sample_count) { + if (ptsoffs_left && !ptsoffs_countdown) { + unsigned int v; + ptsoffs_countdown = _X_BE_32 (q); q += 4; + v = _X_BE_32 (q); q += 4; /* TJ. this is 32 bit signed. All casts necessary for my gcc 4.5.0 */ - int i = trak->timeoffs_to_sample_table[ptsoffs_index].duration; - if ((sizeof (int) > 4) && (i & 0x80000000)) - i |= ~0xffffffffL; - trak->frames[frame_counter].ptsoffs = (int)90000 * i / (int)trak->timescale; - ptsoffs_index_countdown--; - /* time to refresh countdown? */ - if (!ptsoffs_index_countdown) { - ptsoffs_index++; - ptsoffs_index_countdown = - trak->timeoffs_to_sample_table[ptsoffs_index].count; - } - } else - trak->frames[frame_counter].ptsoffs = 0; + ptsoffs_value = v; + if ((sizeof (int) > 4) && (ptsoffs_value & 0x80000000)) + ptsoffs_value |= ~0xffffffffL; + ptsoffs_value *= (int)90000; + ptsoffs_value /= (int)trak->timescale; + ptsoffs_left--; + } + frame->ptsoffs = ptsoffs_value; + ptsoffs_countdown--; samples_per_chunk--; - frame_counter++; + frame++; } } } + /* was the last chunk incomplete? */ + if (trak->sample_size_count && (trak->sample_size_count < trak->frame_count)) + trak->frame_count = trak->sample_size_count; + /* fill in the keyframe information */ - if (trak->sync_sample_table) { - for (i = 0; i < trak->sync_sample_count; i++) - trak->frames[trak->sync_sample_table[i] - 1].keyframe = 1; + p = trak->sync_sample_table; + for (i = 0; i < trak->sync_sample_count; i++) { + unsigned int fr = _X_BE_32 (p) - 1; p += 4; + if (fr < trak->frame_count) + trak->frames[fr].keyframe = 1; } /* initialize edit list considerations */ @@ -2008,11 +1960,26 @@ } /* fill in the rest of the information for the audio samples */ - for (i = 0; i < trak->frame_count; i++) { - trak->frames[i].offset = trak->chunk_offset_table[i]; - trak->frames[i].keyframe = 0; - if (trak->type != MEDIA_AUDIO) - trak->frames[i].pts = 0; + n = trak->frame_count < trak->chunk_offset_count ? + trak->frame_count : trak->chunk_offset_count; + if (trak->chunk_offset_table32) { + p = trak->chunk_offset_table32; + for (i = 0; i < n; i++) + trak->frames[i].offset = _X_BE_32 (p), p += 4; + } else if (trak->chunk_offset_table64) { + p = trak->chunk_offset_table64; + for (i = 0; i < n; i++) + trak->frames[i].offset = _X_BE_64 (p), p += 8; + } + if (trak->type != MEDIA_AUDIO) { + for (i = 0; i < trak->frame_count; i++) { + trak->frames[i].pts = 0; + trak->frames[i].ptsoffs = 0; + trak->frames[i].keyframe = 0; + } + } else { + for (i = 0; i < trak->frame_count; i++) + trak->frames[i].keyframe = 0; } } @@ -3537,3 +3504,4 @@ { PLUGIN_DEMUX, 27, "quicktime", XINE_VERSION_CODE, &demux_info_qt, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; + |