diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 96913344..75ba98d7 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -11,6 +11,7 @@
+
diff --git a/.idea/runConfigurations/deployLocal.xml b/.idea/runConfigurations/deployLocal.xml
index f7ebf23b..ca2317c2 100644
--- a/.idea/runConfigurations/deployLocal.xml
+++ b/.idea/runConfigurations/deployLocal.xml
@@ -10,7 +10,7 @@
diff --git a/README.md b/README.md
index d6580bbb..eb9401df 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@ Android codecs available on the device. Works on API 21+.
```kotlin
// build.gradle.kts
dependencies {
- implementation("com.otaliastudios:transcoder:0.11.0")
+ implementation("io.deepmedia.community:transcoder-android:0.11.1")
}
```
diff --git a/docs/changelog.mdx b/docs/changelog.mdx
index 9fa981c8..a3fac8df 100644
--- a/docs/changelog.mdx
+++ b/docs/changelog.mdx
@@ -8,6 +8,12 @@ New versions are released through GitHub, so the reference page is the [GitHub R
## 0.11.X
+### 0.11.1
+
+- Fix: add unbounded queue for drifted tracks during initialization, thanks to [@jumperson](https://github.com/jumperson) ([#166](https://github.com/deepmedia/Transcoder/pull/166))
+
+[Compare 0.11.0...0.11.1](https://github.com/deepmedia/Transcoder/compare/v0.11.0...v0.11.1).
+
### 0.11.0
This release focuses on stability and performance, fixing old bugs that were making the library unstable and unreliable.
diff --git a/lib-legacy/build.gradle.kts b/lib-legacy/build.gradle.kts
index a62e9b07..aae3c91c 100644
--- a/lib-legacy/build.gradle.kts
+++ b/lib-legacy/build.gradle.kts
@@ -28,7 +28,7 @@ deployer {
projectInfo {
groupId = "com.otaliastudios"
artifactId = "transcoder"
- release.version = "0.11.0" // change :lib and README
+ release.version = "0.11.1" // change :lib and README
description = "Accelerated video compression and transcoding on Android using MediaCodec APIs (no FFMPEG/LGPL licensing issues). Supports cropping to any dimension, concatenation, audio processing and much more."
url = "https://opensource.deepmedia.io/transcoder"
scm.fromGithub("deepmedia", "Transcoder")
diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts
index 74dcfcc8..7770af4e 100644
--- a/lib/build.gradle.kts
+++ b/lib/build.gradle.kts
@@ -63,7 +63,7 @@ deployer {
projectInfo {
groupId = "io.deepmedia.community"
artifactId = "transcoder-android"
- release.version = "0.11.0" // change :lib-legacy and README
+ release.version = "0.11.1" // change :lib-legacy and README
description = "Accelerated video compression and transcoding on Android using MediaCodec APIs (no FFMPEG/LGPL licensing issues). Supports cropping to any dimension, concatenation, audio processing and much more."
url = "https://opensource.deepmedia.io/transcoder"
scm.fromGithub("deepmedia", "Transcoder")
diff --git a/lib/src/androidTest/assets/issue_180/party.mp4 b/lib/src/androidTest/assets/issue_180/party.mp4
new file mode 100644
index 00000000..a8c03b6f
Binary files /dev/null and b/lib/src/androidTest/assets/issue_180/party.mp4 differ
diff --git a/lib/src/androidTest/java/com/otaliastudios/transcoder/integration/IssuesTests.kt b/lib/src/androidTest/java/com/otaliastudios/transcoder/integration/IssuesTests.kt
index 6d127813..0cc3ffa9 100644
--- a/lib/src/androidTest/java/com/otaliastudios/transcoder/integration/IssuesTests.kt
+++ b/lib/src/androidTest/java/com/otaliastudios/transcoder/integration/IssuesTests.kt
@@ -11,6 +11,7 @@ import com.otaliastudios.transcoder.TranscoderOptions
import com.otaliastudios.transcoder.common.TrackType
import com.otaliastudios.transcoder.internal.utils.Logger
import com.otaliastudios.transcoder.source.AssetFileDescriptorDataSource
+import com.otaliastudios.transcoder.source.BlankAudioDataSource
import com.otaliastudios.transcoder.source.ClipDataSource
import com.otaliastudios.transcoder.source.FileDescriptorDataSource
import com.otaliastudios.transcoder.strategy.DefaultVideoStrategy
@@ -119,4 +120,19 @@ class IssuesTests {
}
Unit
}
+
+ @Test(timeout = 16000)
+ fun issue180() = with(Helper(180)) {
+ transcode {
+ val vds = input("party.mp4")
+ val duration = run {
+ vds.initialize()
+ vds.durationUs.also { vds.deinitialize() }
+ }
+ check(duration > 0L) { "Invalid duration: $duration" }
+ addDataSource(TrackType.VIDEO, vds)
+ addDataSource(TrackType.AUDIO, BlankAudioDataSource(duration))
+ }
+ Unit
+ }
}
\ No newline at end of file
diff --git a/lib/src/main/java/com/otaliastudios/transcoder/sink/DefaultDataSink.java b/lib/src/main/java/com/otaliastudios/transcoder/sink/DefaultDataSink.java
index 93333027..5d8d2ed1 100644
--- a/lib/src/main/java/com/otaliastudios/transcoder/sink/DefaultDataSink.java
+++ b/lib/src/main/java/com/otaliastudios/transcoder/sink/DefaultDataSink.java
@@ -39,13 +39,17 @@ public class DefaultDataSink implements DataSink {
*/
private static class QueuedSample {
private final TrackType mType;
+ private ByteBuffer mByteBuffer;
+
private final int mSize;
private final long mTimeUs;
private final int mFlags;
private QueuedSample(@NonNull TrackType type,
+ @NonNull ByteBuffer byteBuffer,
@NonNull MediaCodec.BufferInfo bufferInfo) {
mType = type;
+ mByteBuffer = byteBuffer;
mSize = bufferInfo.size;
mTimeUs = bufferInfo.presentationTimeUs;
mFlags = bufferInfo.flags;
@@ -54,14 +58,9 @@ private QueuedSample(@NonNull TrackType type,
private final static Logger LOG = new Logger("DefaultDataSink");
- // We must be able to handle potentially big buffers (e.g. first keyframe) in the queue.
- // Got crashes with 152kb - let's use 256kb. TODO use a dynamic queue instead
- private final static int BUFFER_SIZE = 256 * 1024;
-
private boolean mMuxerStarted = false;
private final MediaMuxer mMuxer;
private final List mQueue = new ArrayList<>();
- private ByteBuffer mQueueBuffer;
private final MutableTrackMap mStatus = mutableTrackMapOf(null);
private final MutableTrackMap mLastFormat = mutableTrackMapOf(null);
private final MutableTrackMap mMuxerIndex = mutableTrackMapOf(null);
@@ -181,19 +180,14 @@ public void writeTrack(@NonNull TrackType type, @NonNull ByteBuffer byteBuffer,
private void enqueue(@NonNull TrackType type,
@NonNull ByteBuffer buffer,
@NonNull MediaCodec.BufferInfo bufferInfo) {
- if (mQueueBuffer == null) {
- mQueueBuffer = ByteBuffer.allocateDirect(BUFFER_SIZE).order(ByteOrder.nativeOrder());
- }
LOG.v("enqueue(" + type + "): offset=" + bufferInfo.offset
+ "\trealOffset=" + buffer.position()
+ "\tsize=" + bufferInfo.size
- + "\trealSize=" + buffer.remaining()
- + "\tavailable=" + mQueueBuffer.remaining()
- + "\ttotal=" + BUFFER_SIZE);
- buffer.limit(bufferInfo.offset + bufferInfo.size);
- buffer.position(bufferInfo.offset);
- mQueueBuffer.put(buffer);
- mQueue.add(new QueuedSample(type, bufferInfo));
+ + "\trealSize=" + buffer.remaining());
+
+ ByteBuffer byteBuffer = ByteBuffer.allocateDirect(bufferInfo.size).order(ByteOrder.nativeOrder());
+ byteBuffer.put(buffer);
+ mQueue.add(new QueuedSample(type, byteBuffer, bufferInfo));
}
/**
@@ -202,19 +196,16 @@ private void enqueue(@NonNull TrackType type,
*/
private void drainQueue() {
if (mQueue.isEmpty()) return;
- mQueueBuffer.flip();
LOG.i("Output format determined, writing pending data into the muxer. "
- + "samples:" + mQueue.size() + " "
- + "bytes:" + mQueueBuffer.limit());
+ + "samples:" + mQueue.size());
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
- int offset = 0;
for (QueuedSample sample : mQueue) {
- bufferInfo.set(offset, sample.mSize, sample.mTimeUs, sample.mFlags);
- writeTrack(sample.mType, mQueueBuffer, bufferInfo);
- offset += sample.mSize;
+ bufferInfo.set(0, sample.mSize, sample.mTimeUs, sample.mFlags);
+ sample.mByteBuffer.position(0);
+ writeTrack(sample.mType, sample.mByteBuffer, bufferInfo);
+ sample.mByteBuffer = null;
}
mQueue.clear();
- mQueueBuffer = null;
}
@Override