我正在使用MediaCodec
将.wav
文件转换为.amr
。我使用以下代码进行输入并获取编码缓冲区。我得到编码的文件,但它没有播放,我的输入是正确的,因为我能够在Audacity中播放该文件。我在android API测试中使用EncodeDecodeTest.java
。任何指向潜在问题的指标都表示赞赏。
MediaCodec codec = MediaCodec.createByCodecName(componentName);
try {
codec.configure(
format,
null /* surface */,
null /* crypto */,
MediaCodec.CONFIGURE_FLAG_ENCODE);
} catch (IllegalStateException e) {
AppLog.logString("codec '" + componentName + "' failed configuration.");
// assertTrue("codec '" + componentName + "' failed configuration.", false);
}
codec.start();
ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();
int numBytesSubmitted = 0;
boolean doneSubmittingInput = false;
int numBytesDequeued = 0;
while (true) {
int index =0 ;
if (!doneSubmittingInput) {
index = codec.dequeueInputBuffer(kTimeoutUs /* timeoutUs */);
if (index != MediaCodec.INFO_TRY_AGAIN_LATER) {
if (numBytesSubmitted >= filesize ){
codec.queueInputBuffer(
index,
0 /* offset */,
0 /* size */,
0 /* timeUs */,
MediaCodec.BUFFER_FLAG_END_OF_STREAM);
if (VERBOSE) {
AppLog.logString("queued input EOS.");
}
doneSubmittingInput = true;
} else {
int inputsize = 0;
int size = 0;
if ((filesize - numBytesSubmitted) > codecInputBuffers[index]
.limit()) {
inputsize = codecInputBuffers[index].limit();
} else
inputsize = (int) (filesize - numBytesSubmitted);
size = queueInputBuffer(codec,
codecInputBuffers, index, in, inputsize);
numBytesSubmitted += size;
/*if (VERBOSE) {
AppLog.logString("queued " + size + " bytes of input data.");
}*/
}
}else
AppLog.logString("MediaCodec.INFO_TRY_AGAIN_LATER.");
}
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
index = codec.dequeueOutputBuffer(info, kTimeoutUs /* timeoutUs */);
if (index == MediaCodec.INFO_TRY_AGAIN_LATER) {
} else if (index == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
AppLog.logString("INFO_OUTPUT_FORMAT_CHANGED");
MediaFormat fmt = codec.getOutputFormat();
AppLog.logString(fmt.getString(MediaFormat.KEY_MIME));
} else if (index == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
codecOutputBuffers = codec.getOutputBuffers();
} else {
dequeueOutputBuffer(codec, codecOutputBuffers, index, info, fos);
numBytesDequeued += info.size;
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
if (VERBOSE) {
AppLog.logString("dequeued output EOS.");
}
break;
}
if (VERBOSE) {
AppLog.logString("dequeued " + info.size + " bytes of output data.");
}
}
}
if (VERBOSE) {
AppLog.logString("queued a total of " + numBytesSubmitted + "bytes, "
+ "dequeued " + numBytesDequeued + " bytes.");
}
codec.release();
codec = null;
queueInputBuffer
和dequeueOutputBuffer
的实施方式如下:
private int queueInputBuffer(
MediaCodec codec, ByteBuffer[] inputBuffers, int index, FileInputStream in, int size) {
ByteBuffer buffer = inputBuffers[index];
buffer.clear();
// int size = buffer.limit();
AppLog.logString("Size is :" + size);
byte[] data = new byte[size];
try {
in.read(data,0,size);
} catch (IOException e) {
e.printStackTrace();
}
buffer.put(data);
buffer.flip();
codec.queueInputBuffer(index, 0 /* offset */, size, 0 /* timeUs */, MediaCodec.BUFFER_FLAG_SYNC_FRAME);
return size;
}
private void dequeueOutputBuffer(
MediaCodec codec, ByteBuffer[] outputBuffers,
int index, MediaCodec.BufferInfo info, FileOutputStream fos) {
byte[] data= new byte[info.size];
ByteBuffer out = outputBuffers[index];
out.get(data);
try {
fos.write(data);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
codec.releaseOutputBuffer(index, false /* render */);
}