diff --git a/lib/src/main/java/com/otaliastudios/transcoder/internal/thumbnails/DefaultThumbnailsEngine.kt b/lib/src/main/java/com/otaliastudios/transcoder/internal/thumbnails/DefaultThumbnailsEngine.kt index f71457d3..123748ac 100644 --- a/lib/src/main/java/com/otaliastudios/transcoder/internal/thumbnails/DefaultThumbnailsEngine.kt +++ b/lib/src/main/java/com/otaliastudios/transcoder/internal/thumbnails/DefaultThumbnailsEngine.kt @@ -84,8 +84,8 @@ class DefaultThumbnailsEngine( override fun requestKeyFrameTimestamps(): Long { return source.requestKeyFrameTimestamps() } - override fun getKeyFrameTimestampsUs(): ArrayList { - return source.keyFrameTimestampsUs + override fun getKeyFrameTimestamps(): ArrayList { + return source.keyFrameTimestamps } override fun isDrained(): Boolean { @@ -118,13 +118,8 @@ class DefaultThumbnailsEngine( val threshold = stubs.firstOrNull()?.request?.threshold() ?: 0L val nextKeyFrameIndex = source.search(requested) - val nextKeyFrameUs = - if (nextKeyFrameIndex == -1) Long.MAX_VALUE else source.keyFrameTimestampsUs[nextKeyFrameIndex] - val previousKeyFrameUs = - source.keyFrameTimestampsUs[ - if (nextKeyFrameIndex > 0) - nextKeyFrameIndex - 1 else (source.keyFrameTimestampsUs.size - 1) - ] + val nextKeyFrameUs = source.keyFrameAt(nextKeyFrameIndex) { Long.MAX_VALUE } + val previousKeyFrameUs = source.keyFrameAt(nextKeyFrameIndex - 1) { source.lastKeyFrame() } log.i( "seek: current ${source.positionUs}," + @@ -170,18 +165,26 @@ class DefaultThumbnailsEngine( private lateinit var progress: (Thumbnail) -> Unit + private fun DataSource.lastKeyFrame(): Long { + return keyFrameAt(keyFrameTimestamps.size - 1) + } + + private inline fun DataSource.keyFrameAt(index: Int, defaultValue: ((Int)-> Long) = {_ -> -1}): Long { + return keyFrameTimestamps.getOrElse(index, defaultValue) + } + private fun DataSource.search(timestampUs: Long): Int { - if (keyFrameTimestampsUs.isEmpty()) + if (keyFrameTimestamps.isEmpty()) requestKeyFrameTimestamps() - val searchIndex = keyFrameTimestampsUs.binarySearch(timestampUs) + val searchIndex = keyFrameTimestamps.binarySearch(timestampUs) val nextKeyFrameIndex = when { searchIndex >= 0 -> searchIndex searchIndex < 0 -> { val index = -searchIndex - 1 when { - index >= keyFrameTimestampsUs.size -> { + index >= keyFrameTimestamps.size -> { val ts = requestKeyFrameTimestamps() if (ts == -1L) { -1 @@ -189,7 +192,7 @@ class DefaultThumbnailsEngine( search(timestampUs) } } - index < keyFrameTimestampsUs.size -> index + index < keyFrameTimestamps.size -> index else -> { -1 // will never reach here. kotlin is stupid } diff --git a/lib/src/main/java/com/otaliastudios/transcoder/source/DataSource.java b/lib/src/main/java/com/otaliastudios/transcoder/source/DataSource.java index c6e2efe7..ab469fec 100644 --- a/lib/src/main/java/com/otaliastudios/transcoder/source/DataSource.java +++ b/lib/src/main/java/com/otaliastudios/transcoder/source/DataSource.java @@ -114,9 +114,10 @@ public interface DataSource { default long requestKeyFrameTimestamps() { return -1;} - default ArrayList getKeyFrameTimestampsUs() { + default ArrayList getKeyFrameTimestamps() { return new ArrayList<>(); } + /** * Rewinds this source, moving it to its default state. * To be used again, tracks will be selected again. diff --git a/lib/src/main/java/com/otaliastudios/transcoder/source/DefaultDataSource.java b/lib/src/main/java/com/otaliastudios/transcoder/source/DefaultDataSource.java index 3faf7422..7e7c1beb 100644 --- a/lib/src/main/java/com/otaliastudios/transcoder/source/DefaultDataSource.java +++ b/lib/src/main/java/com/otaliastudios/transcoder/source/DefaultDataSource.java @@ -45,7 +45,7 @@ public abstract class DefaultDataSource implements DataSource { private long mDontRenderRangeStart = -1L; private long mDontRenderRangeEnd = -1L; - private final ArrayList keyFrameTsUs = new ArrayList<>(); + private final ArrayList keyFrameTimestamps = new ArrayList<>(); @Override public void initialize() { LOG.i("initialize(): initializing..."); @@ -92,8 +92,8 @@ public void initialize() { } @Override - public ArrayList getKeyFrameTimestampsUs() { - return keyFrameTsUs; + public ArrayList getKeyFrameTimestamps() { + return keyFrameTimestamps; } private Boolean lastKeyFrame = false; @@ -101,15 +101,15 @@ public ArrayList getKeyFrameTimestampsUs() { public long requestKeyFrameTimestamps() { if(lastKeyFrame) return -1L; - if(keyFrameTsUs.size() > 0) { - mExtractor.seekTo(keyFrameTsUs.get(keyFrameTsUs.size() - 1) + 10001L, MediaExtractor.SEEK_TO_NEXT_SYNC); + if(keyFrameTimestamps.size() > 0) { + mExtractor.seekTo(keyFrameTimestamps.get(keyFrameTimestamps.size() - 1) + 10001L, MediaExtractor.SEEK_TO_NEXT_SYNC); } long sampleTime = mExtractor.getSampleTime(); - if (sampleTime == -1 || (keyFrameTsUs.size() > 0 && sampleTime == keyFrameTsUs.get(keyFrameTsUs.size() - 1))) { + if (sampleTime == -1 || (keyFrameTimestamps.size() > 0 && sampleTime == keyFrameTimestamps.get(keyFrameTimestamps.size() - 1))) { lastKeyFrame = true; - mExtractor.seekTo(keyFrameTsUs.get(keyFrameTsUs.size() - 1) + 10001L, MediaExtractor.SEEK_TO_PREVIOUS_SYNC); + mExtractor.seekTo(keyFrameTimestamps.get(keyFrameTimestamps.size() - 1) + 10001L, MediaExtractor.SEEK_TO_PREVIOUS_SYNC); return -1; } LOG.i("keyFrameStartTime:" + sampleTime); @@ -119,17 +119,17 @@ public long requestKeyFrameTimestamps() { int prefetchCount = 100; while (sampleTime >= 0L && sampleTime != lastSampleTime && count < prefetchCount) { if ((mExtractor.getSampleFlags() & MediaExtractor.SAMPLE_FLAG_SYNC) > 0) { - if (!keyFrameTsUs.isEmpty() && sampleTime <= keyFrameTsUs.get(keyFrameTsUs.size() - 1)) { - Collections.sort(keyFrameTsUs); + if (!keyFrameTimestamps.isEmpty() && sampleTime <= keyFrameTimestamps.get(keyFrameTimestamps.size() - 1)) { + Collections.sort(keyFrameTimestamps); } - keyFrameTsUs.add(sampleTime); + keyFrameTimestamps.add(sampleTime); } mExtractor.seekTo(sampleTime + 10001L, MediaExtractor.SEEK_TO_NEXT_SYNC); lastSampleTime = sampleTime; sampleTime = mExtractor.getSampleTime(); count++; } - LOG.i("keyFrameStopCount:" + keyFrameTsUs); + LOG.i("keyFrameStopCount:" + keyFrameTimestamps); return sampleTime; }