Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 564ecb0

Browse files
committed
Fix BlankAudioDataSource
1 parent d82bcfc commit 564ecb0

File tree

12 files changed

+58
-21
lines changed

12 files changed

+58
-21
lines changed

‎lib/src/main/java/com/otaliastudios/transcoder/internal/audio/conversions.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@ internal fun bytesToUs(
1515
return MICROSECONDS_PER_SECOND * bytes / byteRate // usec
1616
}
1717

18+
internal fun bitRate(sampleRate: Int, channels: Int): Int {
19+
val byteRate = channels * sampleRate * BYTES_PER_SAMPLE_PER_CHANNEL
20+
return byteRate * 8
21+
}
22+
23+
internal fun samplesToBytes(samples: Int, channels: Int): Int {
24+
val bytesPerSample = BYTES_PER_SAMPLE_PER_CHANNEL * channels
25+
return samples * bytesPerSample
26+
}
27+
1828
internal fun usToBytes(us: Long, sampleRate: Int, channels: Int): Int {
1929
val byteRatePerChannel = sampleRate * BYTES_PER_SAMPLE_PER_CHANNEL
2030
val byteRate = byteRatePerChannel * channels

‎lib/src/main/java/com/otaliastudios/transcoder/internal/codec/Decoder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ internal class Decoder(
5757
override fun enqueue(data: ReaderData) {
5858
val (chunk, id) = data
5959
val flag = if (chunk.keyframe) BUFFER_FLAG_SYNC_FRAME else 0
60-
codec.queueInputBuffer(id, 0, chunk.bytes, chunk.timeUs, flag)
60+
codec.queueInputBuffer(id, chunk.buffer.position(), chunk.buffer.remaining(), chunk.timeUs, flag)
6161
dropper.input(chunk.timeUs, chunk.render)
6262
}
6363

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@ import com.otaliastudios.transcoder.internal.pipeline.Step
77
import java.nio.ByteBuffer
88
import java.nio.ByteOrder
99

10-
internal class ReaderWriterBridge(private val format: MediaFormat)
10+
internal class Bridge(private val format: MediaFormat)
1111
: Step<ReaderData, ReaderChannel, WriterData, WriterChannel>, ReaderChannel {
1212

1313
private val bufferSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE)
1414
private val buffer = ByteBuffer.allocateDirect(bufferSize).order(ByteOrder.nativeOrder())
1515
override val channel = this
1616

1717
override fun buffer(): Pair<ByteBuffer, Int> {
18+
buffer.clear()
1819
return buffer to 0
1920
}
2021

‎lib/src/main/java/com/otaliastudios/transcoder/internal/data/Reader.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ internal class Reader(
3737
override fun step(state: State.Ok<Unit>, fresh: Boolean): State<ReaderData> {
3838
return if (source.isDrained) {
3939
nextBufferOrWait { byteBuffer, id ->
40-
// TODO we might have to clear the chunk fields
40+
byteBuffer.limit(0)
4141
chunk.buffer = byteBuffer
42+
chunk.keyframe = false
43+
chunk.render = true
4244
State.Eos(ReaderData(chunk, id))
4345
}
4446
} else if (!source.canReadTrack(track)) {

‎lib/src/main/java/com/otaliastudios/transcoder/internal/data/Writer.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ import com.otaliastudios.transcoder.internal.pipeline.Step
99
import com.otaliastudios.transcoder.sink.DataSink
1010
import java.nio.ByteBuffer
1111

12-
internal data class WriterData(val buffer: ByteBuffer, val timeUs: Long, val flags: Int, val release: () -> Unit)
12+
internal data class WriterData(
13+
val buffer: ByteBuffer,
14+
val timeUs: Long,
15+
val flags: Int,
16+
val release: () -> Unit
17+
)
1318

1419
internal interface WriterChannel : Channel {
1520
fun handleFormat(format: MediaFormat)

‎lib/src/main/java/com/otaliastudios/transcoder/internal/media/MediaFormatProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,8 @@ private void feedOnce(@NonNull TrackType type,
157157
chunk.buffer = buffers.getInputBuffer(result);
158158
source.readTrack(chunk);
159159
decoder.queueInputBuffer(result,
160-
0,
161-
chunk.bytes,
160+
chunk.buffer.position(),
161+
chunk.buffer.remaining(),
162162
chunk.timeUs,
163163
chunk.keyframe ? MediaCodec.BUFFER_FLAG_SYNC_FRAME : 0);
164164
}

‎lib/src/main/java/com/otaliastudios/transcoder/internal/pipeline/Step.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.otaliastudios.transcoder.internal.pipeline
22

3+
// TODO this could be Any
34
internal interface Channel {
45
companion object : Channel
56
}

‎lib/src/main/java/com/otaliastudios/transcoder/internal/pipeline/pipelines.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ internal fun PassThroughPipeline(
2828
) = Pipeline.build("PassThrough($track)") {
2929
Reader(source, track) +
3030
ReaderTimer(track, interpolator) +
31-
ReaderWriterBridge(source.getTrackFormat(track)!!) +
31+
Bridge(source.getTrackFormat(track)!!) +
3232
Writer(sink, track)
3333
}
3434

‎lib/src/main/java/com/otaliastudios/transcoder/internal/video/FrameDrawer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
* NOTE: By default, the Surface will be using a BufferQueue in asynchronous mode, so we
2727
* can potentially drop frames.
2828
*/
29-
public class FrameDrawer {
29+
class FrameDrawer {
3030
private static final Logger LOG = new Logger("FrameDrawer");
3131

3232
private static final long NEW_IMAGE_TIMEOUT_MILLIS = 10000;

‎lib/src/main/java/com/otaliastudios/transcoder/source/BlankAudioDataSource.java

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
import java.nio.ByteBuffer;
1111
import java.nio.ByteOrder;
1212

13+
import static com.otaliastudios.transcoder.internal.audio.ConversionsKt.bitRate;
14+
import static com.otaliastudios.transcoder.internal.audio.ConversionsKt.bytesToUs;
15+
import static com.otaliastudios.transcoder.internal.audio.ConversionsKt.samplesToBytes;
1316
import static com.otaliastudios.transcoder.internal.media.MediaFormatConstants.MIMETYPE_AUDIO_RAW;
1417

1518
/**
@@ -21,12 +24,8 @@ public class BlankAudioDataSource implements DataSource {
2124

2225
private static final int CHANNEL_COUNT = 2;
2326
private static final int SAMPLE_RATE = 44100;
24-
private static final int BITS_PER_SAMPLE = 16;
25-
private static final int BIT_RATE = CHANNEL_COUNT * SAMPLE_RATE * BITS_PER_SAMPLE;
26-
private static final double SAMPLES_PER_PERIOD = 2048;
27-
private static final double PERIOD_TIME_SECONDS = SAMPLES_PER_PERIOD / SAMPLE_RATE;
28-
private static final long PERIOD_TIME_US = (long) (1000000 * PERIOD_TIME_SECONDS);
29-
private static final int PERIOD_SIZE = (int) (PERIOD_TIME_SECONDS * BIT_RATE / 8);
27+
// "period" = our MediaFormat.KEY_MAX_INPUT_SIZE
28+
private static final int PERIOD_SIZE = samplesToBytes(2048, CHANNEL_COUNT);
3029

3130
private final long durationUs;
3231

@@ -44,7 +43,7 @@ public void initialize() {
4443
byteBuffer = ByteBuffer.allocateDirect(PERIOD_SIZE).order(ByteOrder.nativeOrder());
4544
audioFormat = new MediaFormat();
4645
audioFormat.setString(MediaFormat.KEY_MIME, MIMETYPE_AUDIO_RAW);
47-
audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
46+
audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate(SAMPLE_RATE, CHANNEL_COUNT));
4847
audioFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, CHANNEL_COUNT);
4948
audioFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, PERIOD_SIZE);
5049
audioFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, SAMPLE_RATE);
@@ -108,14 +107,21 @@ public boolean canReadTrack(@NonNull TrackType type) {
108107

109108
@Override
110109
public void readTrack(@NonNull Chunk chunk) {
110+
// Could fill the chunk with a while loop in case it's bigger than our buffer,
111+
// but let's respect our MediaFormat.KEY_MAX_INPUT_SIZE
112+
int position = chunk.buffer.position();
113+
int bytes = Math.min(chunk.buffer.remaining(), PERIOD_SIZE);
114+
111115
byteBuffer.clear();
112-
chunk.buffer = byteBuffer;
116+
byteBuffer.limit(bytes);
117+
chunk.buffer.put(byteBuffer);
118+
chunk.buffer.position(position);
119+
chunk.buffer.limit(position + bytes);
120+
113121
chunk.keyframe = true;
114122
chunk.timeUs = positionUs;
115-
chunk.bytes = PERIOD_SIZE;
116123
chunk.render = true;
117-
118-
positionUs += PERIOD_TIME_US;
124+
positionUs += bytesToUs(bytes, SAMPLE_RATE, CHANNEL_COUNT);
119125
}
120126

121127
@Override

‎lib/src/main/java/com/otaliastudios/transcoder/source/DataSource.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ class Chunk {
130130
public ByteBuffer buffer;
131131
public boolean keyframe;
132132
public long timeUs;
133-
public int bytes;
134133
public boolean render;
135134
}
136135
}

‎lib/src/main/java/com/otaliastudios/transcoder/source/DefaultDataSource.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,20 @@ public boolean canReadTrack(@NonNull TrackType type) {
162162
@Override
163163
public void readTrack(@NonNull Chunk chunk) {
164164
int index = mExtractor.getSampleTrackIndex();
165-
chunk.bytes = mExtractor.readSampleData(chunk.buffer, 0);
165+
166+
int position = chunk.buffer.position();
167+
int limit = chunk.buffer.limit();
168+
int read = mExtractor.readSampleData(chunk.buffer, position);
169+
if (read < 0) {
170+
throw new IllegalStateException("No samples available! Forgot to call " +
171+
"canReadTrack / isDrained?");
172+
} else if (position + read > limit) {
173+
throw new IllegalStateException("MediaExtractor is not respecting the buffer limit. " +
174+
"This might cause other issues down the pipeline.");
175+
}
176+
chunk.buffer.limit(position + read);
177+
chunk.buffer.position(position);
178+
166179
chunk.keyframe = (mExtractor.getSampleFlags() & MediaExtractor.SAMPLE_FLAG_SYNC) != 0;
167180
chunk.timeUs = mExtractor.getSampleTime();
168181
chunk.render = chunk.timeUs < mDontRenderRangeStart || chunk.timeUs >= mDontRenderRangeEnd;

0 commit comments

Comments
 (0)