MediaCodec硬編碼pcm2aac
MediaCodec
是Android(api>=16)
提供的一個多媒體硬解編碼庫,能實現音視訊的編解碼。
工作原理:其內部有2個佇列,一個是輸入佇列,一個是輸出佇列。輸入佇列負責儲存編
解碼前的原始資料儲存,並輸送給MediaCodec
處理;輸出佇列負責儲存編解碼後
的新資料,可以直接處理或儲存到檔案中。
AAC
的頭部資訊介紹 :https://blog.csdn.net/jay100500/article/details/52955232
//mediacodec
private MediaFormat encoderFormat = null;
private MediaCodec encoder = null;
private FileOutputStream outputStream = null;
private MediaCodec.BufferInfo info = null;
private int perpcmsize = 0;
private byte[] outByteBuffer = null;
private int aacsamplerate = 4;
private double recordTime = 0;
private int audioSamplerate = 0;
private void initMediacodec(int samperate, File outfile)
{
try {
aacsamplerate = getADTSsamplerate(samperate);
//立體聲
encoderFormat = MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC, samperate, 2);
//96kbps fm音質
encoderFormat.setInteger(MediaFormat.KEY_BIT_RATE, 96000);
encoderFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
encoderFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 4096);
encoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_AUDIO_AAC);
info = new MediaCodec.BufferInfo();
if(encoder == null)
{
MyLog.d("craete encoder wrong");
return;
}
recordTime = 0;
encoder.configure(encoderFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
outputStream = new FileOutputStream(outfile);
encoder.start();
} catch (IOException e) {
e.printStackTrace();
}
}
private void encodecPcmToAAc(int size, byte[] buffer)
{
if(buffer != null && encoder != null)
{
//錄音時間 size/ 取樣率*聲道數 * bits/8
recordTime += size * 1.0 / (audioSamplerate * 2 * (16 / 8));
MyLog.d("recordTime = " + recordTime);
//回掉
if(wlOnRecordTimeListener != null)
{
wlOnRecordTimeListener.onRecordTime((int) recordTime);
}
int inputBufferindex = encoder.dequeueInputBuffer(0);
if(inputBufferindex >= 0)
{
ByteBuffer byteBuffer = encoder.getInputBuffers()[inputBufferindex];
byteBuffer.clear();
byteBuffer.put(buffer);
encoder.queueInputBuffer(inputBufferindex, 0, size, 0, 0);
}
int index = encoder.dequeueOutputBuffer(info, 0);
while(index >= 0)
{
try {
perpcmsize = info.size + 7;
outByteBuffer = new byte[perpcmsize];
ByteBuffer byteBuffer = encoder.getOutputBuffers()[index];
byteBuffer.position(info.offset);
byteBuffer.limit(info.offset + info.size);
addADtsHeader(outByteBuffer, perpcmsize, aacsamplerate);
byteBuffer.get(outByteBuffer, 7, info.size);
byteBuffer.position(info.offset);
outputStream.write(outByteBuffer, 0, perpcmsize);
encoder.releaseOutputBuffer(index, false);
index = encoder.dequeueOutputBuffer(info, 0);
outByteBuffer = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void addADtsHeader(byte[] packet, int packetLen, int samplerate)
{
int profile = 2; // AAC LC
int freqIdx = samplerate; // samplerate
int chanCfg = 2; // CPE
packet[0] = (byte) 0xFF; // 0xFFF(12bit) 這裡只取了8位,所以還差4位放到下一個裡面
packet[1] = (byte) 0xF9; // 第一個t位放F
packet[2] = (byte) (((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2));
packet[3] = (byte) (((chanCfg & 3) << 6) + (packetLen >> 11));
packet[4] = (byte) ((packetLen & 0x7FF) >> 3);
packet[5] = (byte) (((packetLen & 7) << 5) + 0x1F);
packet[6] = (byte) 0xFC;
}
private int getADTSsamplerate(int samplerate)
{
int rate = 4;
switch (samplerate)
{
case 96000:
rate = 0;
break;
case 88200:
rate = 1;
break;
case 64000:
rate = 2;
break;
case 48000:
rate = 3;
break;
case 44100:
rate = 4;
break;
case 32000:
rate = 5;
break;
case 24000:
rate = 6;
break;
case 22050:
rate = 7;
break;
case 16000:
rate = 8;
break;
case 12000:
rate = 9;
break;
case 11025:
rate = 10;
break;
case 8000:
rate = 11;
break;
case 7350:
rate = 12;
break;
}
return rate;
}
private void releaseMedicacodec()
{
if(encoder == null)
{
return;
}
try {
recordTime = 0;
outputStream.close();
outputStream = null;
encoder.stop();
encoder.release();
encoder = null;
encoderFormat = null;
info = null;
initmediacodec = false;
MyLog.d("錄製完成...");
} catch (IOException e) {
e.printStackTrace();
}
finally {
if(outputStream != null)
{
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
outputStream = null;
}
}
}
相關文章
- 使用 MediaCodec 在 Android 上進行硬解碼Android
- Android:MediaCodeC硬編碼解碼視訊,並將視訊幀儲存為圖片檔案Android
- Android音視訊(四)MediaCodec編解碼AACAndroid
- 使用MediaCodeC將圖片集編碼為視訊
- Android 音視訊 - MediaCodec 編解碼音視訊Android
- android使用MediaCodec實現非同步視訊編解碼Android非同步
- MediaCodec解碼FFmpeg AvPacket
- 【Codecs系列】硬體編碼器編碼引數分析
- 模板 vs. 硬編碼 HTMLHTML
- 視訊硬編碼(iOS端)iOS
- Android短影片系統硬編碼—實現音影片編碼(三)Android
- Android短影片系統硬編碼—實現音影片編碼(二)Android
- 全網首發:使用安卓MediaCodec Encoder進行編碼時的方向問題安卓
- MediaCodeC解碼視訊指定幀,迅捷、精確
- Android 音視訊錄製硬編碼實現Android
- 漏洞簡析——CWE-259:使用硬編碼的密碼漏洞密碼
- Android安全開發之淺談金鑰硬編碼Android
- 使用java8的方法引用替換硬編碼Java
- MediaCodec 高效解碼得到標準 YUV420P 格式幀
- 硬體編碼相關知識(H264,H265)
- 轉載:iOS音視訊實時採集硬體編碼iOS
- 定時任務不在硬編碼,動態定時刷起來
- 思科產品中存在硬編碼密碼和 Java 反序列化高危漏洞密碼Java
- 軟硬協同:基於倚天的影片雲編碼效能升級
- 別再用硬編碼寫業務流程了,試試這款輕量級流程編排框架框架
- 從 Notification.Name 看 Swift 如何優雅的解決 String 硬編碼Swift
- Android音視訊處理之MediaCodecAndroid
- 編解碼持續升級,「硬」實力鑄就影片雲最優解
- camera開發系列之三 相機資料採集硬編碼h264
- Jan Ozer:高畫質直播互動場景下的硬編碼如何選型?
- Code rant: 從硬編碼到可配置、規則引擎、低程式碼DSL的複雜性時鐘
- C# 類對映的四種方法【解決硬編碼的問題】(工具三)C#
- 超10萬Zyxel防火牆裝置存在硬編碼憑據漏洞,儘快打補丁!防火牆
- 硬剛 lodash 原始碼之路,_.chunk原始碼
- IDEA如何設定編碼格式,字元編碼,全域性編碼和專案編碼格式Idea字元
- 告別硬編碼與埋點長週期, DTM為數字營銷注入新活力
- 開源規則引擎——ice:致力於解決靈活繁複的硬編碼問題
- 熵編碼(四)-算術編碼(二)熵