我正在使用Android中的一个媒体编解码器类(Jelly Bean)将PCM格式编码为AAC。该文件已编码,但没有音乐播放器能够播放该文件。我在网上找不到任何工作代码或适当的文档。
这是我的代码:
public void doConvert()
{
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()+"/Download/Ghajini27_Mono_8Khz.wav");
//File inputFile = new File( sampleFD.get);
Log.e("File", String.valueOf(inputFile.length()));
FileInputStream fis = new FileInputStream(inputFile);
fis.skip(44);//remove wav header
File outputFile = new File( Environment.getExternalStorageDirectory().getAbsolutePath()+"/Download/out.m4a");
if ( outputFile.exists()) outputFile.delete();
FileOutputStream fos = new FileOutputStream(outputFile);
//BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(outputFile));
MediaCodec codec = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat outputFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", 22050, 1);
outputFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
// outputFormat.setInteger(MediaFormat.KEY_CHANNEL_MASK, AudioFormat.CHANNEL_CONFIGURATION_MONO);
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, 22050 );
outputFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
//outputFormat.setLong(MediaFormat.KEY_MAX_INPUT_SIZE, inputFile.length());
double durationInMs = (inputFile.length()/16000)*1000;
Log.e("duration",String.valueOf((long)durationInMs));
outputFormat.setLong(MediaFormat.KEY_DURATION, (long)durationInMs );
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[48000];
byte writeBuffer[] = new byte[48000];
do
{
int nextBuffer = codec.dequeueInputBuffer(5000);
Log.e("NextBuffer","nextInputBuffer = "+nextBuffer);
if ( nextBuffer >= 0 )
{
ByteBuffer inBuf = inputBuffers[nextBuffer];
inBuf.clear();
int bytesRead = fis.read( readBuffer,0, inBuf.capacity() );
Log.e("bytesread","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, 3000);
/* 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();
}
你需要一个容器。将MediaCodec的编码输出发送到MediaMuxer。使用mp4作为容器类型。不需要使用@Andy--S发布的神秘代码。
只需确保为最终文件提供一个扩展名。m4a而不是mp4。MP4扩展用于视频。
有关MediaMuxer的详细信息,请参阅:https://developer.android.com/reference/android/media/MediaMuxer#writeSampleData(int,java.nio.ByteBuffer,android.media.MediaCodec.BufferInfo)
有一个AndroidAAC库https://github.com/timsu/android-aac-enc
尝试通过这个库传递您的缓冲区。这可能会有所帮助。
你需要为它选择一个容器。我更喜欢ADT。
将有效载荷数据复制到一个足以容纳您的容器的区域中,只需添加您的位即可。因此,在互联网上搜索我的解决方案后,我将一些片段放在适当的位置
方法“fillInADTSHeader”
profile =( configParams[0]>>3 )&0x1f;
frequency_index = (this.configParams[0]&0x7) <<1 | (this.configParams[1]>>7) &0x1;
channel_config = (this.configParams[1]>>3) &0xf;
int finallength = encoded_length + 7;
ENCodedByteArray[0] = (byte) 0xff;
ENCodedByteArray[1] = (byte) 0xf1;
ENCodedByteArray[2] = (byte) ( ((profile - 1) << 6) + (frequency_index << 2) +(channel_config >> 2));
ENCodedByteArray[3] = (byte) (((channel_config & 0x3) << 6) + (finallength >> 11));
ENCodedByteArray[4] = (byte)( (finallength & 0x7ff) >> 3);
ENCodedByteArray[5] = (byte) (((finallength & 7) << 5) + 0x1f) ;
ENCodedByteArray[6] = (byte) 0xfc;
使用类似
byte chunkADTS[]=new byte[info.size + 7];
fillInADTSHeader(chunkADTS,info.size);
outputBuffers[bR].get(chunkADTS,7,info.size);
buffer.pushData(chunkADTS);
应该在shoutcast等中播放...
我正在修改一个Android框架示例,将MediaCodec生成的基本AAC流打包成一个独立的。mp4文件。我使用的是一个实例,其中包含一个由实例生成的AAC曲目。 然而,我总是最终得到一个错误消息调用:
我正在使用MediaCodec将PCM数据转换为AAC,并使用MediaMuxer将此aac数据存储到m4a文件中。没有视频。 该文件会生成,甚至会播放。但是没有声音。如果我将aac文件导入Audacity,它不会显示任何数据。音频的长度甚至是预期的时间。我知道数据正在被编码,尽管我不确定这些数据是否被正确编码。 对pcm数据进行编码: 我已经浏览了大量示例,我所做的一切似乎都是正确的。如果我在o
我正在尝试使用Android上的MediaCodec API来解码AAC流。(它是原始AAC。)我尝试使用MediaFormat.createAudioFormat()来创建要传递给MediaCodec.configure()的格式对象,但我在使用AAC(音频/mp4a-latm)时一直出错。(不过它适用于MP3(音频/mpeg)...) 最后,我为一个AAC文件创建了一个MediaExtract
我正在尝试使用使用编解码器对一些音频流进行编码。为此,我使用了google cts ExtractEncodeMust的这个实现。 对于某些aac文件,它会在编码某些帧后抛出。更准确地说,它会在第1030行抛出异常,。 我正在配置如下: 我完全不知道如何解决这个问题。任何形式的帮助都将不胜感激。 带有一些日志的堆栈跟踪: 设备:小米POCO x3 操作系统:Android10 导致溢出的示例文件信
问题很简单,但我没有任何线索来解决它: 我编写一行代码来在我的Nexus 4(Android 4.4.2)上创建AAC编码器 保存在“codec”中的返回值不为空,但我在Logcat中收到一条红色错误消息: 我还尝试了另一条线: 并得到相同的错误结果。 在使用MediaCodec之前,我是否错过了任何初始化步骤?我在官方文档中没有找到有关此的任何信息。 有人遇到过这个问题吗? 实际上,我正在尝试将
我正在尝试使用android AudioRecord和MediaCodec对aac音频进行编码。我创建了一个非常类似于(使用Android MediaCodec从相机编码H.264)的编码器类。使用此类,我创建了一个AudioRecord实例,并告诉它将其byte[]数据读出到AudioEncoder(audioEncoder.offerEncoder(Data))。 这是我的音频记录设置 我成功