【关键字】
音频编码、管道模式、createEncoder
【写在前面】
在使用API6开发HarmonyOS应用时,如何将pcm源文件进行编码并写入文件,最后生成aac文件,本文直接附上主要代码开发步骤供大家参考。
【主要功能代码】
import ohos.media.codec.Codec;
import ohos.media.common.BufferInfo;
import ohos.media.common.Format;
import ohos.media.common.Source;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
public class AudioEncoder {
void creatEncoder(){
}
FileOutputStream fileOutputStream = null;
public void encode(){
System.out.println("encode start");
try {
File fd = new File("/data/data/com.example.myapplication/11.aac");
fileOutputStream = new FileOutputStream(fd, true);
} catch (FileNotFoundException e) {
System.out.println("FileNotFoundException");
} finally {
}
final Codec encoder = Codec.createEncoder();
String path = "/data/data/com.example.myapplication/11.pcm";
System.out.println("encoder = " + encoder);
boolean ret = encoder.setSource(new Source(path), null);
System.out.println("setSource ret = " + ret);
Format fmt = new Format();
// format格式中转码率和声道需与pcm相同
fmt.putStringValue(Format.MIME, Format.AUDIO_AAC);
fmt.putIntValue(Format.BIT_RATE, 128000);
fmt.putIntValue(Format.CHANNEL, 2);
fmt.putIntValue(Format.SAMPLE_RATE, 44100);
fmt.putIntValue(Format.FRAME_RATE, 30); // 此设置必须,数值一般为30/60,或自行设置需要数值
boolean b1 = encoder.setSourceFormat(fmt);
System.out.println("setSourceFormat = " + b1);
Codec.ICodecListener listener = new Codec.ICodecListener() {
@Override
public void onReadBuffer(ByteBuffer byteBuffer, BufferInfo bufferInfo, int trackId) {
System.out.println("byteBuffer = " + byteBuffer + "trackId = " + trackId + "bufferinfo = " + bufferInfo.bufferType);
if(bufferInfo.bufferType == 4){
encoder.stop();
encoder.release();
try {
fileOutputStream.close();
} catch (IOException e) {
// 打印异常
System.out.println("IOException");
}
return;
}
writeFile(byteBuffer,bufferInfo,trackId);
}
@Override
public void one rror(int errorCode, int act, int trackId) {
System.out.println( "PlayerCallback one rror errorCode: "+errorCode +", trackId:"+trackId);
}
};
boolean b = encoder.registerCodecListener(listener);
System.out.println("registerCodecListener = " + b);
boolean start = encoder.start();
System.out.println("start = " + start);
}
private void writeFile(ByteBuffer outputBuffer, BufferInfo info, int trackId) {
try {
final byte[] chunk = new byte[info.size+7];
addADTSHeader(chunk,info.size+7);
outputBuffer.get(chunk,7,info.size);
fileOutputStream.write(chunk);
outputBuffer.clear();
} catch (FileNotFoundException e) {
System.out.println("FileNotFoundException");
} catch (IOException e) {
System.out.println("IOException");
} finally {
}
}
/**
* 添加AAC帧文件头
*
* @param packet packet
* @param packetLen packetLen
*/
private void addADTSHeader(byte[] packet, int packetLen) {
int profile = 2; // AAC
int freqIdx = 4; // 44.1kHz
int channelCount = 2;//声道
packet[0] = (byte) 0xFF;
packet[1] = (byte) 0xF9;
packet[2] = (byte) (((profile - 1) << 6) + (freqIdx << 2) + (channelCount >> 2));
packet[3] = (byte) (((channelCount & 3) << 6) + (packetLen >> 11));
packet[4] = (byte) ((packetLen & 0x7FF) >> 3);
packet[5] = (byte) (((packetLen & 7) << 5) + 0x1F);
packet[6] = (byte) 0xFC;
}
}
【说明和注意事项】
1、AAC文件有两种添加头文件方式:ADIF与ADTS,此处使用ADTS方式,ADTS是每一段编码都有一个头部,因此并不能只添加一次,需要在回调中添加头文件;添加头文件保存的aac文件可以直接播放;
2、format中需要设置FRAME_RATE,即fmt.putIntValue(Format.FRAME_RATE, 30);,数值必须大于0,否则可能会编码失败
3、编解码功能建议在子线程中执行,不要在主线程中。
【参考文档】
视频编解码文档:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/media-video-codec-0000000000031749
标签:API6,Java,Format,System,packet,音频文件,println,import,out From: https://www.cnblogs.com/mayism123/p/17648350.html