-
Notifications
You must be signed in to change notification settings - Fork 168
/
Copy pathBlankAudioDataSource.java
131 lines (105 loc) · 3.88 KB
/
BlankAudioDataSource.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package com.otaliastudios.transcoder.source;
import android.media.MediaFormat;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.otaliastudios.transcoder.engine.TrackType;
import com.otaliastudios.transcoder.postprocessor.DefaultAudioPostProcessor;
import com.otaliastudios.transcoder.postprocessor.PostProcessor;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import static com.otaliastudios.transcoder.internal.MediaFormatConstants.MIMETYPE_AUDIO_RAW;
/**
* A {@link DataSource} that provides a silent audio track of the a specific duration.
* This class can be used to concatenate a DataSources that has a video track only with another
* that has both video and audio track.
*/
public class BlankAudioDataSource implements DataSource {
private final static String TAG = BlankAudioDataSource.class.getSimpleName();
private static final int CHANNEL_COUNT = 2;
private static final int SAMPLE_RATE = 44100;
private static final int BITS_PER_SAMPLE = 16;
private static final int BIT_RATE = CHANNEL_COUNT * SAMPLE_RATE * BITS_PER_SAMPLE;
private static final double SAMPLES_PER_PERIOD = 2048;
private static final double PERIOD_TIME_SECONDS = SAMPLES_PER_PERIOD / SAMPLE_RATE;
private static final long PERIOD_TIME_US = (long) (1000000 * PERIOD_TIME_SECONDS);
private static final int PERIOD_SIZE = (int) (PERIOD_TIME_SECONDS * BIT_RATE / 8);
private final long durationUs;
private final ByteBuffer byteBuffer;
private final MediaFormat audioFormat;
private long currentTimestampUs = 0L;
public BlankAudioDataSource(long durationUs) {
this.durationUs = durationUs;
this.byteBuffer = ByteBuffer.allocateDirect(PERIOD_SIZE).order(ByteOrder.nativeOrder());
this.audioFormat = new MediaFormat();
audioFormat.setString(MediaFormat.KEY_MIME, MIMETYPE_AUDIO_RAW);
audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
audioFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, CHANNEL_COUNT);
audioFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, PERIOD_SIZE);
audioFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, SAMPLE_RATE);
}
private PostProcessor postProcessor = new DefaultAudioPostProcessor();
@Override
public void setPostProcessor(@NonNull PostProcessor postProcessor) {
this.postProcessor = postProcessor;
}
@Override
public PostProcessor getPostProcessor() {
return postProcessor;
}
@Override
public int getOrientation() {
return 0;
}
@Nullable
@Override
public double[] getLocation() {
return null;
}
@Override
public long getDurationUs() {
return durationUs;
}
@Nullable
@Override
public MediaFormat getTrackFormat(@NonNull TrackType type) {
return (type == TrackType.AUDIO) ? audioFormat : null;
}
@Override
public void selectTrack(@NonNull TrackType type) {
// Nothing to do
}
@Override
public long seekTo(long desiredTimestampUs) {
currentTimestampUs = desiredTimestampUs;
return desiredTimestampUs;
}
@Override
public boolean canReadTrack(@NonNull TrackType type) {
return type == TrackType.AUDIO;
}
@Override
public void readTrack(@NonNull Chunk chunk) {
byteBuffer.clear();
chunk.buffer = byteBuffer;
chunk.isKeyFrame = true;
chunk.timestampUs = currentTimestampUs;
chunk.bytes = PERIOD_SIZE;
currentTimestampUs += PERIOD_TIME_US;
}
@Override
public long getReadUs() {
return currentTimestampUs;
}
@Override
public boolean isDrained() {
return currentTimestampUs >= getDurationUs();
}
@Override
public void releaseTrack(@NonNull TrackType type) {
// Nothing to do
}
@Override
public void rewind() {
currentTimestampUs = 0;
}
}