有什麼方法可以使用標準的Android SDK將PCM wav文件重新編碼爲另一種編碼?將Wav文件重新編碼爲AAC LC,AMR WB/NB
我可以看到,可以直接從麥克風錄製成這些格式,但我正在寫的應用程序必須先在PCM中錄製。 由於許可限制,ffmpeg不是可用選項。
我現在對Jelly Bean有以下代碼,但輸出不可被任何媒體播放器讀取。
從AOSP怯場代碼似乎暗示一個MPEG4容器
profile.nSampleRate = sampleRate;
profile.nBitRate = bitRate;
profile.nAudioBandWidth = 0;
profile.nFrameLength = 0;
profile.nAACtools = OMX_AUDIO_AACToolAll;
profile.nAACERtools = OMX_AUDIO_AACERNone;
profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
但是從機器人代碼輸出不可讀。
根據需要,輸入wav文件是32khz,16位帶符號單聲道。
public void doConvert(View v)
{
new AsyncTask<Void, Void, Void>()
{
@Override
protected Void doInBackground(Void... params)
{
try
{
int codecCount = MediaCodecList.getCodecCount();
for (int i=0; i < codecCount; i++)
{
MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
Logger.getLogger(MainActivity.class.getSimpleName()).log(Level.INFO, info.getName());
for (String type : info.getSupportedTypes())
{
Logger.getLogger(MainActivity.class.getSimpleName()).log(Level.INFO, type);
}
}
File inputFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Media/Report-test5.wav");
FileInputStream fis = new FileInputStream(inputFile);
fis.skip(44);//remove wav header
File outputFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Media/out.mp4");
if (outputFile.exists()) outputFile.delete();
FileOutputStream fos = new FileOutputStream(outputFile);
MediaCodec codec = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat outputFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", 32000, 1);
outputFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
//outputFormat.setInteger(MediaFormat.KEY_CHANNEL_MASK, AudioFormat.CHANNEL_OUT_MONO);
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, 48000);
//outputFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 64000);
double durationInMs = (inputFile.length()/64.0)*1000.0;
outputFormat.setLong(MediaFormat.KEY_DURATION, (long)durationInMs);
//Logger.getLogger(MainActivity.class.getSimpleName()).log(Level.INFO, codec.getOutputFormat().toString());
codec.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
codec.start();
ByteBuffer[] inputBuffers = codec.getInputBuffers();
ByteBuffer[] outputBuffer = codec.getOutputBuffers();
boolean hasMoreData = true;
MediaCodec.BufferInfo outBuffInfo = new BufferInfo();
byte readBuffer[] = new byte[64000];
byte writeBuffer[] = new byte[64000];
do
{
int nextBuffer = codec.dequeueInputBuffer(1000);
logger.log(Level.INFO,"nextInputBuffer = "+nextBuffer);
if (nextBuffer >= 0)
{
ByteBuffer inBuf = inputBuffers[nextBuffer];
inBuf.clear();
int bytesRead = fis.read(readBuffer,0, inBuf.capacity());
logger.log(Level.INFO,"Read = "+bytesRead);
if (bytesRead < inBuf.capacity())
{
hasMoreData = false;
}
inBuf.put(readBuffer, 0, bytesRead);
codec.queueInputBuffer(nextBuffer, 0, bytesRead, 0, hasMoreData?0:MediaCodec.BUFFER_FLAG_END_OF_STREAM);
}
int outputBufferIndex = codec.dequeueOutputBuffer(outBuffInfo, 1000);
logger.log(Level.INFO,"nextOutputBuffer = "+outputBufferIndex);
logger.log(Level.INFO,"outBuffInfo offset = "+outBuffInfo.offset);
logger.log(Level.INFO,"outBuffInfo size = "+outBuffInfo.size);
logger.log(Level.INFO,"outBuffInfo flags = "+outBuffInfo.flags);
//while (outputBufferIndex > -1)
//{
outputBuffer[outputBufferIndex].position(outBuffInfo.offset);
outputBuffer[outputBufferIndex].get(writeBuffer,0,outBuffInfo.size);
fos.write(writeBuffer,0, outBuffInfo.size);
logger.log(Level.INFO,"Writing = "+outBuffInfo.size+" bytes");
outputBuffer[outputBufferIndex].clear();
codec.releaseOutputBuffer(outputBufferIndex, false);
if (outBuffInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM)
{
codec.flush();
codec.stop();
codec.release();
break;
}
//outputBufferIndex = codec.dequeueOutputBuffer(outBuffInfo, 1000);
//logger.log(Level.INFO,"nextOutputBuffer = "+outputBufferIndex);
//}
} while (outBuffInfo.flags != MediaCodec.BUFFER_FLAG_END_OF_STREAM);
fis.close();
fos.flush();
fos.close();
}
catch (Exception e)
{
Logger.getLogger(MainActivity.class.getSimpleName()).log(Level.INFO, "Codec Error",e);
}
logger.log(Level.INFO,"Done");
return null;
}
}.execute();
}
你讓你的AAC文件可讀?你能分享嗎?...? – 2013-02-14 11:44:57
不幸的是,我確定我錯過了一些標題信息,但發現什麼是相當難以捉摸的。 – 2013-02-20 05:43:24