Loading media/libstagefright/MPEG4Extractor.cpp +71 −27 Original line number Original line Diff line number Diff line Loading @@ -463,6 +463,66 @@ sp<MetaData> MPEG4Extractor::getTrackMetaData( return NULL; return NULL; } } int64_t duration; int32_t samplerate; if (track->has_elst && mHeaderTimescale != 0 && track->meta->findInt64(kKeyDuration, &duration) && track->meta->findInt32(kKeySampleRate, &samplerate)) { track->has_elst = false; if (track->elst_segment_duration > INT64_MAX) { goto editlistoverflow; } int64_t segment_duration = track->elst_segment_duration; int64_t media_time = track->elst_media_time; int64_t halfscale = mHeaderTimescale / 2; int64_t delay; // delay = ((media_time * samplerate) + halfscale) / mHeaderTimescale; if (__builtin_mul_overflow(media_time, samplerate, &delay) || __builtin_add_overflow(delay, halfscale, &delay) || (delay /= mHeaderTimescale, false) || delay > INT32_MAX || delay < INT32_MIN) { goto editlistoverflow; } track->meta->setInt32(kKeyEncoderDelay, delay); int64_t scaled_duration; // scaled_duration = ((duration * mHeaderTimescale) + 500000) / 1000000; if (__builtin_mul_overflow(duration, mHeaderTimescale, &scaled_duration) || __builtin_add_overflow(scaled_duration, 500000, &scaled_duration)) { goto editlistoverflow; } scaled_duration /= 1000000; int64_t segment_end; int64_t padding; if (__builtin_add_overflow(segment_duration, media_time, &segment_end) || __builtin_sub_overflow(scaled_duration, segment_end, &padding)) { goto editlistoverflow; } if (padding < 0) { // track duration from media header (which is what kKeyDuration is) might // be slightly shorter than the segment duration, which would make the // padding negative. Clamp to zero. padding = 0; } int64_t paddingsamples; // paddingsamples = ((padding * samplerate) + halfscale) / mHeaderTimescale; if (__builtin_mul_overflow(padding, samplerate, &paddingsamples) || __builtin_add_overflow(paddingsamples, halfscale, &paddingsamples) || (paddingsamples /= mHeaderTimescale, false) || paddingsamples > INT32_MAX) { goto editlistoverflow; } track->meta->setInt32(kKeyEncoderPadding, paddingsamples); } editlistoverflow: if ((flags & kIncludeExtensiveMetaData) if ((flags & kIncludeExtensiveMetaData) && !track->includes_expensive_metadata) { && !track->includes_expensive_metadata) { track->includes_expensive_metadata = true; track->includes_expensive_metadata = true; Loading Loading @@ -989,6 +1049,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { track->skipTrack = false; track->skipTrack = false; track->timescale = 0; track->timescale = 0; track->meta->setCString(kKeyMIMEType, "application/octet-stream"); track->meta->setCString(kKeyMIMEType, "application/octet-stream"); track->has_elst = false; } } off64_t stop_offset = *offset + chunk_size; off64_t stop_offset = *offset + chunk_size; Loading Loading @@ -1055,6 +1116,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { { { *offset += chunk_size; *offset += chunk_size; if (!mLastTrack) { return ERROR_MALFORMED; } // See 14496-12 8.6.6 // See 14496-12 8.6.6 uint8_t version; uint8_t version; if (mDataSource->readAt(data_offset, &version, 1) < 1) { if (mDataSource->readAt(data_offset, &version, 1) < 1) { Loading @@ -1069,8 +1134,6 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { if (entry_count != 1) { if (entry_count != 1) { // we only support a single entry at the moment, for gapless playback // we only support a single entry at the moment, for gapless playback ALOGW("ignoring edit list with %d entries", entry_count); ALOGW("ignoring edit list with %d entries", entry_count); } else if (mHeaderTimescale == 0) { ALOGW("ignoring edit list because timescale is 0"); } else { } else { off64_t entriesoffset = data_offset + 8; off64_t entriesoffset = data_offset + 8; uint64_t segment_duration; uint64_t segment_duration; Loading @@ -1094,31 +1157,12 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { return ERROR_IO; return ERROR_IO; } } uint64_t halfscale = mHeaderTimescale / 2; // save these for later, because the elst atom might precede segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale; // the atoms that actually gives us the duration and sample rate media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale; // needed to calculate the padding and delay values mLastTrack->has_elst = true; int64_t duration; mLastTrack->elst_media_time = media_time; int32_t samplerate; mLastTrack->elst_segment_duration = segment_duration; if (!mLastTrack) { return ERROR_MALFORMED; } if (mLastTrack->meta->findInt64(kKeyDuration, &duration) && mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) { int64_t delay = (media_time * samplerate + 500000) / 1000000; mLastTrack->meta->setInt32(kKeyEncoderDelay, delay); int64_t paddingus = duration - (int64_t)(segment_duration + media_time); if (paddingus < 0) { // track duration from media header (which is what kKeyDuration is) might // be slightly shorter than the segment duration, which would make the // padding negative. Clamp to zero. paddingus = 0; } int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000; mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples); } } } break; break; } } Loading media/libstagefright/include/MPEG4Extractor.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -82,6 +82,9 @@ private: sp<SampleTable> sampleTable; sp<SampleTable> sampleTable; bool includes_expensive_metadata; bool includes_expensive_metadata; bool skipTrack; bool skipTrack; bool has_elst; int64_t elst_media_time; uint64_t elst_segment_duration; }; }; Vector<SidxEntry> mSidxEntries; Vector<SidxEntry> mSidxEntries; Loading Loading
media/libstagefright/MPEG4Extractor.cpp +71 −27 Original line number Original line Diff line number Diff line Loading @@ -463,6 +463,66 @@ sp<MetaData> MPEG4Extractor::getTrackMetaData( return NULL; return NULL; } } int64_t duration; int32_t samplerate; if (track->has_elst && mHeaderTimescale != 0 && track->meta->findInt64(kKeyDuration, &duration) && track->meta->findInt32(kKeySampleRate, &samplerate)) { track->has_elst = false; if (track->elst_segment_duration > INT64_MAX) { goto editlistoverflow; } int64_t segment_duration = track->elst_segment_duration; int64_t media_time = track->elst_media_time; int64_t halfscale = mHeaderTimescale / 2; int64_t delay; // delay = ((media_time * samplerate) + halfscale) / mHeaderTimescale; if (__builtin_mul_overflow(media_time, samplerate, &delay) || __builtin_add_overflow(delay, halfscale, &delay) || (delay /= mHeaderTimescale, false) || delay > INT32_MAX || delay < INT32_MIN) { goto editlistoverflow; } track->meta->setInt32(kKeyEncoderDelay, delay); int64_t scaled_duration; // scaled_duration = ((duration * mHeaderTimescale) + 500000) / 1000000; if (__builtin_mul_overflow(duration, mHeaderTimescale, &scaled_duration) || __builtin_add_overflow(scaled_duration, 500000, &scaled_duration)) { goto editlistoverflow; } scaled_duration /= 1000000; int64_t segment_end; int64_t padding; if (__builtin_add_overflow(segment_duration, media_time, &segment_end) || __builtin_sub_overflow(scaled_duration, segment_end, &padding)) { goto editlistoverflow; } if (padding < 0) { // track duration from media header (which is what kKeyDuration is) might // be slightly shorter than the segment duration, which would make the // padding negative. Clamp to zero. padding = 0; } int64_t paddingsamples; // paddingsamples = ((padding * samplerate) + halfscale) / mHeaderTimescale; if (__builtin_mul_overflow(padding, samplerate, &paddingsamples) || __builtin_add_overflow(paddingsamples, halfscale, &paddingsamples) || (paddingsamples /= mHeaderTimescale, false) || paddingsamples > INT32_MAX) { goto editlistoverflow; } track->meta->setInt32(kKeyEncoderPadding, paddingsamples); } editlistoverflow: if ((flags & kIncludeExtensiveMetaData) if ((flags & kIncludeExtensiveMetaData) && !track->includes_expensive_metadata) { && !track->includes_expensive_metadata) { track->includes_expensive_metadata = true; track->includes_expensive_metadata = true; Loading Loading @@ -989,6 +1049,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { track->skipTrack = false; track->skipTrack = false; track->timescale = 0; track->timescale = 0; track->meta->setCString(kKeyMIMEType, "application/octet-stream"); track->meta->setCString(kKeyMIMEType, "application/octet-stream"); track->has_elst = false; } } off64_t stop_offset = *offset + chunk_size; off64_t stop_offset = *offset + chunk_size; Loading Loading @@ -1055,6 +1116,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { { { *offset += chunk_size; *offset += chunk_size; if (!mLastTrack) { return ERROR_MALFORMED; } // See 14496-12 8.6.6 // See 14496-12 8.6.6 uint8_t version; uint8_t version; if (mDataSource->readAt(data_offset, &version, 1) < 1) { if (mDataSource->readAt(data_offset, &version, 1) < 1) { Loading @@ -1069,8 +1134,6 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { if (entry_count != 1) { if (entry_count != 1) { // we only support a single entry at the moment, for gapless playback // we only support a single entry at the moment, for gapless playback ALOGW("ignoring edit list with %d entries", entry_count); ALOGW("ignoring edit list with %d entries", entry_count); } else if (mHeaderTimescale == 0) { ALOGW("ignoring edit list because timescale is 0"); } else { } else { off64_t entriesoffset = data_offset + 8; off64_t entriesoffset = data_offset + 8; uint64_t segment_duration; uint64_t segment_duration; Loading @@ -1094,31 +1157,12 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { return ERROR_IO; return ERROR_IO; } } uint64_t halfscale = mHeaderTimescale / 2; // save these for later, because the elst atom might precede segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale; // the atoms that actually gives us the duration and sample rate media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale; // needed to calculate the padding and delay values mLastTrack->has_elst = true; int64_t duration; mLastTrack->elst_media_time = media_time; int32_t samplerate; mLastTrack->elst_segment_duration = segment_duration; if (!mLastTrack) { return ERROR_MALFORMED; } if (mLastTrack->meta->findInt64(kKeyDuration, &duration) && mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) { int64_t delay = (media_time * samplerate + 500000) / 1000000; mLastTrack->meta->setInt32(kKeyEncoderDelay, delay); int64_t paddingus = duration - (int64_t)(segment_duration + media_time); if (paddingus < 0) { // track duration from media header (which is what kKeyDuration is) might // be slightly shorter than the segment duration, which would make the // padding negative. Clamp to zero. paddingus = 0; } int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000; mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples); } } } break; break; } } Loading
media/libstagefright/include/MPEG4Extractor.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -82,6 +82,9 @@ private: sp<SampleTable> sampleTable; sp<SampleTable> sampleTable; bool includes_expensive_metadata; bool includes_expensive_metadata; bool skipTrack; bool skipTrack; bool has_elst; int64_t elst_media_time; uint64_t elst_segment_duration; }; }; Vector<SidxEntry> mSidxEntries; Vector<SidxEntry> mSidxEntries; Loading