android - 其他线程上的android mediaCodec.callback
问题描述
我正在尝试将音频文件转换为 byte[] 并且效果很好。我的问题是它适用于 UI 线程,但我想在其他线程上执行;这是我的代码:
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) {
}
}
}
该文档说,如果您在主线程以外的其他线程上启动媒体编解码器,它应该在该线程中工作,但这不会发生(我测试它)。另一个解决方案是使用 hanlder,但我不知道如何!
解决方案
请参阅MediaCodec.setCallback方法。您需要创建并启动 HandlerThread 来处理其他线程中的数据。
private var codecHandlerThread: HandlerThread = HandlerThread(TAG)
codecHandlerThread.start()
然后,Handler
在后台创建HandlerThread.looper
并将其作为第二个参数传递给MediaCodec.setCallback
方法:
val backgroundHandler = Handler(decoderHandlerThread.looper)
mediaCodec.setCallback(yourCallback, backgroundHandler)
推荐阅读
- javascript - 带有json的随机图片库?
- python - 将 pandas DataFrame 的所有列连接到第一列
- awk - 将 AWK 应用于具有模式的多个文件
- android - SSL 握手失败,Android 7.0 支持 secp256r1 曲线
- python - np.savetxt - 向 csv 文件添加一个标题
- c - 关于 C 中的结构和函数
- c# - 使用泛型将带有字符串键的字典转换为带有枚举键的字典
- r - R:解释 boot() 输出
- angular - 如何将 JSON 请求正文的值设置为数组而不是字符串
- wordpress - 使用过滤器更改默认页面标题 wordpress