编译脚本:
#!/bin/bash
NDK_ROOT=/Users/huozhenpeng/Library/Android/sdk/ndk-bundle
PREBUILT=$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
PLATFORM=$NDK_ROOT/platforms/android-9/arch-arm
export PATH=$PATH:$PREBUILT/bin:$PLATFORM/usr/include:
export LDFLAGS="-L$PLATFORM/usr/lib -L$PREBUILT/arm-linux-androideabi/lib -march=armv7-a"
export CFLAGS="-I$PLATFORM/usr/include -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -ffast-math -O2"
export CPPFLAGS="$CFLAGS"
export CFLAGS="$CFLAGS"
export CXXFLAGS="$CFLAGS"
export LDFLAGS="$LDFLAGS"
export AS=$PREBUILT/bin/arm-linux-androideabi-as
export LD=$PREBUILT/bin/arm-linux-androideabi-ld
export CXX="$PREBUILT/bin/arm-linux-androideabi-g++ --sysroot=${PLATFORM}"
export CC="$PREBUILT/bin/arm-linux-androideabi-gcc --sysroot=${PLATFORM} -march=armv7-a"
export NM=$PREBUILT/bin/arm-linux-androideabi-nm
export STRIP=$PREBUILT/bin/arm-linux-androideabi-strip
export RANLIB=$PREBUILT/bin/arm-linux-androideabi-ranlib
export AR=$PREBUILT/bin/arm-linux-androideabi-ar
./configure --host=arm-linux \
--disable-shared \
--disable-frontend \
--enable-static \
--prefix=/Users/huozhenpeng/Desktop/voicevideo/lame-3.99.5/armv7a
make clean
make -j8
make install
编译成功后:
这个armv7a是我新建的目录
我们使用configure的方式来生成makefile文件,然后利用make命令完成编译,make install进行安装
这个makefile文件就是利用configure生成的,configure中最后的命令
make clean
make -j8
make install
都是对这个文件进行操作的
--prefix:指定将编译好的库放在哪个目录下
--host:指定编译好的库最终要运行的平台
CC:指定交叉工具编译链的路径,其实这里就是指定gcc的路径
--CFLAGS:指定编译时所带的参数
--LDFLAGS:指定链接过程中的参数
--disable-shared:通常是GNU标准中关闭动态链接库的选项
--disable-frontend:不编译出LAME的可执行文件
在AndroidStudio中集成LAME库
目录结构:
lamemp3encoder.h
//
// Created by 霍振鹏 on 2018/9/10.
//
#ifndef LAMEPROJECT_LAMEMP3ENCODER_H
#define LAMEPROJECT_LAMEMP3ENCODER_H
#include "../../../../../../Library/Android/sdk/ndk-bundle/platforms/android-21/arch-mips64/usr/include/stdio.h"
extern "C"
{
#include
#include "lame/lame.h"
}
class Mp3Encoder {
private:
FILE *pcmFile;
FILE *mp3File;
lame_t lameClient;
public:
Mp3Encoder();
~Mp3Encoder();
int Init(const char *pcmFilePath, const char *mp3FilePath, int sampleRate, int channels,
int bitRate);
void Encode();
void Destroy();
};
#endif //LAMEPROJECT_LAMEMP3ENCODER_H
lamemp3encoder.cpp
//
// Created by 霍振鹏 on 2018/9/10.
//
#include "lamemp3encoder.h"
Mp3Encoder::Mp3Encoder() {
}
Mp3Encoder::~Mp3Encoder() {
}
int Mp3Encoder::Init(const char *pcmFilePath, const char *mp3FilePath, int sampleRate, int channels,
int bitRate){
int ret = -1;
pcmFile = fopen(pcmFilePath, "rb");
if(pcmFile) {
mp3File = fopen(mp3FilePath, "wb");
if(mp3File) {
lameClient = lame_init();
lame_set_in_samplerate(lameClient, sampleRate);
lame_set_out_samplerate(lameClient, sampleRate);
lame_set_num_channels(lameClient, channels);
lame_set_brate(lameClient, bitRate / 1000);
lame_init_params(lameClient);
ret = 0;
}
}
return ret;
}
void Mp3Encoder::Encode(){
int bufferSize = 1024 * 256;
short* buffer = new short[bufferSize / 2];
short* leftBuffer = new short[bufferSize / 4];
short* rightBuffer = new short[bufferSize / 4];
uint8_t* mp3_buffer = new uint8_t[bufferSize];
int readBufferSize = 0;
while ((readBufferSize = fread(buffer, 2, bufferSize / 2, pcmFile)) > 0) {
for (int i = 0; i < readBufferSize; i++) {
if (i % 2 == 0) {
leftBuffer[i / 2] = buffer[i];
} else {
rightBuffer[i / 2] = buffer[i];
}
}
int wroteSize = lame_encode_buffer(lameClient, (short int *) leftBuffer, (short int *) rightBuffer, readBufferSize / 2, mp3_buffer, bufferSize);
fwrite(mp3_buffer, 1, wroteSize, mp3File);
}
delete[] buffer;
delete[] leftBuffer;
delete[] rightBuffer;
delete[] mp3_buffer;
}
void Mp3Encoder::Destroy(){
if(pcmFile) {
fclose(pcmFile);
}
if(mp3File) {
fclose(mp3File);
lame_close(lameClient);
}
}
MainActivity.java
package com.example.huozhenpeng.lametest;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
String pcmPath = Environment.getExternalStorageDirectory()+"/ffmpeg.pcm";
int audioChannels = 2;
int bitRate = 128 * 1024;
int sampleRate = 44100;
String mp3Path =Environment.getExternalStorageDirectory()+"/lame.mp3";
int ret = init(pcmPath, mp3Path,sampleRate,audioChannels, bitRate);
if(ret >= 0) {
encode();
destroy();
} else {
}
}
});
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native int init(String pcmPath,String mp3Path,int sampleRate,int audioChannels,int bitRate);
public native void encode();
public native void destroy();
}
native-lib.cpp
#include
#include
extern "C"
{
#include "lamemp3encoder.h"
}
Mp3Encoder* encoder=NULL;
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_huozhenpeng_lametest_MainActivity_init(JNIEnv *env, jobject instance,
jstring pcmPath_, jstring mp3Path_,
jint sampleRate, jint audioChannels,
jint bitRate) {
const char *pcmPath = env->GetStringUTFChars(pcmPath_, 0);
const char *mp3Path = env->GetStringUTFChars(mp3Path_, 0);
// TODO
encoder=new Mp3Encoder();
int ret=encoder->Init(pcmPath,mp3Path,sampleRate,audioChannels,bitRate);
env->ReleaseStringUTFChars(pcmPath_, pcmPath);
env->ReleaseStringUTFChars(mp3Path_, mp3Path);
//坑点,忘记写return值了,运行报错
return ret;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_huozhenpeng_lametest_MainActivity_encode(JNIEnv *env, jobject instance) {
// TODO
encoder->Encode();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_huozhenpeng_lametest_MainActivity_destroy(JNIEnv *env, jobject instance) {
// TODO
encoder->Destroy();
}
build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.example.huozhenpeng.lametest"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
abiFilters 'armeabi-v7a'
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
}
CMakeList.txt
cmake_minimum_required(VERSION 3.4.1)
set(distribution_DIR ../../../../libs)
include_directories(libs/include)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp
src/main/cpp/lamemp3encoder.cpp
)
# 坑点,注意路径正确性
add_library(mp3lame STATIC IMPORTED)
set_target_properties(mp3lame
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/armeabi-v7a/libmp3lame.a)
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
target_link_libraries( # Specifies the target library.
native-lib
# 坑点,不要忘记添加这儿
mp3lame
# Links the target library to the log library
# included in the NDK.
${log-lib} )
libs下存放的是上面利用configure编译成的include中的头文件和lib中的静态库(.a)文件
测试: