java调用g726_Android G711(PCMA/PCMU)、G726、PCM音頻轉碼到AAC

Android G711(PCMA/PCMU)、G726、PCM音頻轉碼到AAC

首先先介紹下使用的開源庫,當然還是要感謝開源庫的作者們為我們提供了方便。

采用EasyAACEncoder 此是EasyDarwin開源流媒體服務團隊整理、開發的一款音頻轉碼到AAC的工具庫,目前支持G711a/G711u/G726/PCM等音頻格式的轉碼,跨平台,支持Windows/Linux/arm.

說明

EasyAACEncoder目前支持的音視頻格式:

/* Audio Codec */

enum Law

{

Law_ULaw = 0, /**< U law */

Law_ALaw = 1, /**< A law */

Law_PCM16 = 2, /**< 16 bit uniform PCM values. 原始 pcm 數據 */

Law_G726 = 3 /**< G726 */

};

/* Rate Bits */

enum Rate

{

Rate16kBits=2, /**< 16k bits per second (2 bits per ADPCM sample) */

Rate24kBits=3, /**< 24k bits per second (3 bits per ADPCM sample) */

Rate32kBits=4, /**< 32k bits per second (4 bits per ADPCM sample) */

Rate40kBits=5 /**< 40k bits per second (5 bits per ADPCM sample) */

};

更多信息

回歸正題

具體Android怎么使用該庫呢,有以下步驟:

1.在上面地址下載開源庫解壓

2.把解壓后的開源庫放到項目jni文件夾里

3.去除無用東西,對有錯誤的進行剔除與修正

4.新建個調用c方法的類文件並寫好調用方法

5.新建Android.mk文件與Application.mk文件完成相應配置

6.編輯打包so即可完成

熟練的大神們分分鍾鍾就搞定了,像我這樣不熟悉的還是多多看看資料先寫個小的demo練練手之后在來編譯就簡單多了。

在此過程中第三步與第四步麻煩是最多的。

現在簡單說下

在第三步中要先去掉無用的文件,我直接把非.c源文件與.h頭文件的直接剔除如下圖我的:

a672e06ce320722341da100717d9277b.jpe

該開源庫也采用了libfacc如圖:

5e43cd6d46c65463f6c45252542ce30d.jpe

之后如果仍然會有報錯的文件,找到報錯的所在地再解決,有的需要項目里關聯C/C++ build才可以,有的還需要配置環境,具體網上教程有很多,就不在累贅,找到適合自己的就行。

還有就是c的方法與c++的方法有的地方不一樣的需要格外注意下比如說env。

對四步主要看你的Java層怎么寫方法調用了,然后編譯自動生成即可,或者自己編寫也行。

Java代碼文件方法比如我的:

public class JNIAACEncode {

public static final int Law_ULaw = 0;/**< U law */

public static final int Law_ALaw = 1;/**< A law */

public static final int Law_PCM16 = 2;/**< 16 bit uniform PCM values. 原始 pcm 數據 */

public static final int Law_G726 = 3;/**< G726 */

//首先進行實例化audioCodec為上面聲明的音頻類型

public static native void init(int audioCodec);

//原音頻文件路徑與轉碼后的音頻文件路徑

public static native int encode(String infilename, String outAacname);

static {

System.loadLibrary("AACEncode");

}

}

對應的c代碼為:

JNIEXPORT void JNICALL Java_com_aacencoder_JNIAACEncode_init(JNIEnv *env,jobject obj, jint law) {

InitParam initParam;

initParam.u32AudioSamplerate = 8000;

initParam.ucAudioChannel = 1;

initParam.u32PCMBitSize = 16;

if (Law_ALaw == law) {

initParam.ucAudioCodec = Law_ALaw;

} else if (Law_ULaw == law) {

initParam.ucAudioCodec = Law_ULaw;

} else if (Law_PCM16 == law) {

initParam.ucAudioCodec = Law_PCM16;

} else if (Law_G726 == law) {

initParam.ucAudioCodec = Law_G726;

initParam.g726param.ucRateBits = Rate40kBits;

} else {

LOGE("Java_com_aacencoder_JNIAACEncode_g711Ainit law failure =%d", law);

return;

}

handle = Easy_AACEncoder_Init(initParam);

LOGE("Java_com_aacencoder_JNIAACEncode_g711Ainit env=%p", env);

}

轉碼方法為:

JNIEXPORT jint JNICALL Java_com_aacencoder_JNIAACEncode_encode(JNIEnv *env,

jobject obj, jstring jinfilename, jstring joutAacname) {

char *infilename = jstringTostr(env, jinfilename); //類型進行轉換

char *outAacname = jstringTostr(env, joutAacname); //類型進行轉換

LOGE("inFilename = %s", infilename);

LOGE("outAacname = %s", outAacname);

//1.打開 wav,MP3文件

// FILE* fwav = fopen(cwav, "rb");

// FILE* fmp3 = fopen(cmp3, "wb");

// char* infilename = "g711.g711a"; //標准

// char* outAacname = "g711.aac";

FILE* fpIn = fopen(infilename, "rb");

if (NULL == fpIn) {

printf("%s:[%d] open %s file failed\n", __FUNCTION__, __LINE__,

infilename);

return -1;

}

FILE* fpOut = fopen(outAacname, "wb");

if (NULL == fpOut) {

printf("%s:[%d] open %s file failed\n", __FUNCTION__, __LINE__,

outAacname);

return -1;

}

int gBytesRead = 0;

int bG711ABufferSize = 500;

int bAACBufferSize = 4 * bG711ABufferSize; //提供足夠大的緩沖區

unsigned char *pbG711ABuffer = (unsigned char *) malloc(

bG711ABufferSize * sizeof(unsigned char));

unsigned char *pbAACBuffer = (unsigned char*) malloc(

bAACBufferSize * sizeof(unsigned char));

unsigned int out_len = 0;

while ((gBytesRead = fread(pbG711ABuffer, 1, bG711ABufferSize, fpIn)) > 0) {

if (Easy_AACEncoder_Encode(handle, pbG711ABuffer, gBytesRead,

pbAACBuffer, &out_len) > 0) {

fwrite(pbAACBuffer, 1, out_len, fpOut);

}

}

Easy_AACEncoder_Release(handle);

free(pbG711ABuffer);

free(pbAACBuffer);

fclose(fpIn);

fclose(fpOut);

return 0;

}

上面方法別忘了引入頭文件:

#include

#include

#include

#include

#include "EasyAACEncoderAPI.h"

#include "com_aacencoder_JNIAACEncode.h"

#include

#define LOG_TAG "VIDEO_AAC"

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)

#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

把這些搞定基本完成80%啦,又可以愉快玩耍了。

下面要進行第五步了那就是編寫配置文件:

這配置文件很簡單,大家應該都會就不多說了,只不過要提醒下LOCAL_SRC_FILES列出所有文件要注意c文件與cpp文件區別。

如下我的:

LOCAL_PATH := $(call my-dir)

#生成so動態庫

include $(CLEAR_VARS)

LOCAL_MODULE := AACEncode

LOCAL_SRC_FILES := \

./libfaac/aacquant.c \

./libfaac/backpred.c \

./libfaac/bitstream.c \

./libfaac/channels.c \

./libfaac/fft.c \

./libfaac/filtbank.c \

./libfaac/frame.c \

./libfaac/huffman.c\

./libfaac/ltp.c \

./libfaac/midside.c \

./libfaac/psychkni.c \

./libfaac/tns.c \

./libfaac/util.c \

./libfaac/kiss_fft/kiss_fft.c \

./libfaac/kiss_fft/kiss_fftr.c \

audio_buffer.cpp EasyAACEncoder.cpp EasyAACEncoderAPI.cpp g711.cpp G711AToPcm.cpp g726.cpp G726ToPcm.cpp IDecodeToPcm.cpp PcmToAac.cpp AACEncoder.c

LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY)

然后編譯運行即可生成so庫啦啦啦~

在libs文件里就能找到的~

本人使用的還Eclipse工具編譯,由於Android Studio支持不是很好也比較麻煩。

就簡單的說這些吧,提醒下對於第三步與第四步問題估計比較多,有問題那就多多去谷歌,問題會解決的!

GitHub源代碼

點擊CSDN下載

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值