Reputation:
i am trying to convert audio file to byte[] and it works well. my problem is that it works on UI thread but i want to do it on other Thread; this is my code:
private class DecodeMusic extends Thread {
@RequiresApi(api = Build.VERSION_CODES.M)
public void run() {
playing = true;
sample = musics.get(current_music).getSample();
channel = musics.get(current_music).getChannel();
duration = musics.get(current_music).getDuration();
try {
if (mediaCodec != null) {
mediaCodec.stop();
mediaCodec.release();
mediaCodec = null;
}
if (mediaExtractor != null)
mediaExtractor.release();
musicQueue = new ArrayList<>();
StereoFile stereoFile = musics.get(current_music);
mediaExtractor = new MediaExtractor();
mediaExtractor.setDataSource(stereoFile.getPath());
MediaFormat format = mediaExtractor.getTrackFormat(0);
mediaExtractor.selectTrack(0);
MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
mediaCodec = MediaCodec.createByCodecName(mediaCodecList.findDecoderForFormat(format));
musicQueue = new ArrayList<>(duration * sample);
try {
Looper.prepare();
Handler handler = new Handler();
mediaCodec.setCallback(new MediaCodec.Callback() {
@Override
public void onInputBufferAvailable(@NonNull MediaCodec codec, int index) {
ByteBuffer decoderInputBuffer = codec.getInputBuffer(index);
int size = mediaExtractor.readSampleData(decoderInputBuffer, 0);
if (size < 0) {
codec.queueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
} else {
codec.queueInputBuffer(index, 0, size, mediaExtractor.getSampleTime(), 0);
mediaExtractor.advance();
}
}
@Override
public void onOutputBufferAvailable(@NonNull MediaCodec codec, int index, @NonNull MediaCodec.BufferInfo info) {
byte[] data = new byte[info.size - info.offset];
mediaCodec.getOutputBuffer(index).get(data);
musicQueue.add(data);
mediaCodec.releaseOutputBuffer(index, true);
}
@Override
public void onError(@NonNull MediaCodec codec, @NonNull MediaCodec.CodecException e) {
}
@Override
public void onOutputFormatChanged(@NonNull MediaCodec codec, @NonNull MediaFormat format) {
}
}, handler);
} catch (Exception e) {
e.printStackTrace();
}
mediaCodec.configure(format, null, null, 0);
mediaCodec.start();
} catch (IOException ignored) {
}
}
}
The doc says that if you start mediacodec on other thread than main, it should works in that thread but this doesn't happen(i test it). another solution is using hanlder but i don't know how!
Upvotes: 0
Views: 1394
Reputation: 838
Please, see MediaCodec.setCallback method. You need to create and start HandlerThread to process data in other thread.
private var codecHandlerThread: HandlerThread = HandlerThread(TAG)
codecHandlerThread.start()
Then, create Handler
on background HandlerThread.looper
and pass it as a second argument to MediaCodec.setCallback
method:
val backgroundHandler = Handler(decoderHandlerThread.looper)
mediaCodec.setCallback(yourCallback, backgroundHandler)
Upvotes: 1