opus android编译,Mac系统opus Android编译集成
一、源码下载
opus官网
源码下载
我这里使用的是1.3.1版本
新建Android module opus
其目录结构如下
将opus源码拷贝至src目录,在src目录下新建Android.mk 与Application.mk
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/celt_sources.mk
include $(LOCAL_PATH)/silk_sources.mk
include $(LOCAL_PATH)/opus_sources.mk
LOCAL_MODULE := opus
# Fixed point sources
SILK_SOURCES += $(SILK_SOURCES_FIXED)
# ARM build
CELT_SOURCES += $(CELT_SOURCES_ARM)
SILK_SOURCES += $(SILK_SOURCES_ARM)
LOCAL_SRC_FILES := \
$(CELT_SOURCES) $(SILK_SOURCES) $(OPUS_SOURCES) $(OPUS_SOURCES_FLOAT)
LOCAL_SRC_FILES += \
logger.c \
jni/encoder_jni.cpp \
jni/decoder_jni.cpp
LOCAL_LDLIBS := -lm -llog
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/silk \
$(LOCAL_PATH)/silk/fixed \
$(LOCAL_PATH)/celt \
$(LOCAL_PATH)/jni
LOCAL_CFLAGS := -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
LOCAL_CFLAGS += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -O3 -fno-math-errno
LOCAL_CPPFLAGS := -DBSD=1
LOCAL_CPPFLAGS += -ffast-math -O3 -funroll-loops
LOCAL_LDLIBS += -llog
LOCAL_LDLIBS += -landroid
LOCAL_CFLAGS += -DNPT_CONFIG_ENABLE_LOGGING
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_ABI := armeabi armeabi-v7a
APP_PLATFORM := android-21
APP_ALLOW_MISSING_DEPS=true
添加编译脚本build.sh
#!/usr/bin/env bash
cd ../src
ndk-build APP_BUILD_SCRIPT=Android.mk NDK_APPLICATION_MK=Application.mk NDK_PROJECT_PATH=.
cd ../build
cp -f ../src/libs/armeabi-v7a/* ../../libs/armeabi-v7a/
编译可得libopus.so
二、jni调用
在java部分添加编解码类
public class Encoder {
public Encoder() {
Opus.getInstance();
}
public int initEncoder(Parameter parameter) {
return _initEncoder(parameter);
}
public int encode(byte[] opus, short[] pcm) {
return _encode(opus, pcm);
}
public int destroyEncoder() {
return _destroyEncoder();
}
private native int _initEncoder(Parameter parameter);
private native int _encode(byte[] opus, short[] pcm);
private native int _destroyEncoder();
}
public class Decoder {
public Decoder() {
Opus.getInstance();
}
public int initDecoder(Parameter parameter) {
return _initDecoder(parameter);
}
public int decode(short[] pcm, byte[] opus) {
return _decode(pcm, opus);
}
public int destroyDecoder() {
return _destroyDecoder();
}
private native int _initDecoder(Parameter parameter);
private native int _decode(short[] pcm, byte[] opus);
private native int _destroyDecoder();
}
添加jni脚本jni.sh,用于生成头文件
#!/usr/bin/env bash
# Mirror
javah -o ../core/src/jni/decoder_jni.h -classpath ../build/intermediates/classes/release/ com.cast.opus.decoder.Decoder
javah -o ../core/src/jni/encoder_jni.h -classpath ../build/intermediates/classes/release/ com.cast.opus.encoder.Encoder
image.png
新建encoder_jni.cpp 与 decoder_jni.cpp分别实现编解码部分的jni调用
encoder_jni.cpp
#include "encoder_jni.h"
#include "logger.h"
#include "opus.h"
#define TAG "encoder-jni"
OpusEncoder *gOpusEnc;
JNIEXPORT jint JNICALL Java_com_cast_opus_encoder_Encoder__1initEncoder
(JNIEnv *env, jobject obj, jobject paraObj) {
int error;
gOpusEnc = opus_encoder_create(48000, 2,
OPUS_APPLICATION_RESTRICTED_LOWDELAY,
&error);
if (gOpusEnc) {
opus_encoder_ctl(gOpusEnc, OPUS_SET_VBR(0));//0:CBR, 1:VBR
opus_encoder_ctl(gOpusEnc, OPUS_SET_VBR_CONSTRAINT(true));
opus_encoder_ctl(gOpusEnc, OPUS_SET_BITRATE(32000));
opus_encoder_ctl(gOpusEnc, OPUS_SET_COMPLEXITY(8));//8 0~10
opus_encoder_ctl(gOpusEnc, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
opus_encoder_ctl(gOpusEnc, OPUS_SET_LSB_DEPTH(16));
opus_encoder_ctl(gOpusEnc, OPUS_SET_DTX(0));
opus_encoder_ctl(gOpusEnc, OPUS_SET_INBAND_FEC(0));
opus_encoder_ctl(gOpusEnc, OPUS_SET_PACKET_LOSS_PERC(0));
}
OpusLogI(TAG,"initEncoder %d ", error);
return error;
}
JNIEXPORT jint JNICALL Java_com_cast_opus_encoder_Encoder__1encode
(JNIEnv *env, jobject obj, jbyteArray opus,jshortArray pcm) {
if (!gOpusEnc || !pcm || !opus) {
OpusLogW(TAG,"encode ignore 1");
return -1;
}
jshort *pcmArray = env->GetShortArrayElements(pcm, 0);
jsize pcmSize = env->GetArrayLength(pcm);
jbyte *opusArray = env->GetByteArrayElements(opus, 0);
jsize opusSize = env->GetArrayLength(opus);
//if (opusSize < 320 || pcmSize <= 0) {
if (opusSize <= 0 || pcmSize <= 0) {
OpusLogW(TAG,"encode ignore 2");
return -1;
}
OpusLogI(TAG,"encode %d %d",pcmSize,opusSize);
//
// int nRet = opus_encode(gOpusEnc, pcmArray, pcmSize, (unsigned char *) opusArray,
// opusSize);
int nRet = opus_encode(gOpusEnc, pcmArray, pcmSize, (unsigned char *) opusArray,
opusSize);
env->ReleaseShortArrayElements(pcm, pcmArray, 0);
env->ReleaseByteArrayElements(opus, opusArray, 0);
OpusLogI(TAG,"encode %d ",nRet);
return nRet;
}
JNIEXPORT jint JNICALL Java_com_cast_opus_encoder_Encoder__1destroyEncoder
(JNIEnv *env, jobject obj) {
OpusLogI(TAG,"destroyEncoder");
if (!gOpusEnc)
return 0;
opus_encoder_destroy(gOpusEnc);
return 0;
}
decoder_jni.cpp
//
// Created by don on 2020/5/20.
//
#include "decoder_jni.h"
#include "logger.h"
#include "opus.h"
#define TAG "decoder-jni"
OpusDecoder *gOpusDec;
JNIEXPORT jint JNICALL Java_com_cast_opus_decoder_Decoder__1initDecoder
(JNIEnv *env, jobject obj, jobject paraObj){
int error;
gOpusDec = opus_decoder_create(48000, 2, &error);
OpusLogI(TAG,"initDecoder %d",error);
return error;
}
JNIEXPORT jint JNICALL Java_com_cast_opus_decoder_Decoder__1decode
(JNIEnv *env, jobject obj, jshortArray pcm,jbyteArray opus){
OpusLogI(TAG,"decode");
if (!gOpusDec || !opus || !pcm)
return -1;
jbyte *opusArray = env->GetByteArrayElements(opus, 0);
jsize opusSize = env->GetArrayLength(opus);
jshort *pcmArray = env->GetShortArrayElements(pcm, 0);
jsize pcmSize = env->GetArrayLength(pcm);
if (opusSize <= 0 || pcmSize <= 0) {
return -1;
}
int nRet = opus_decode(gOpusDec, (unsigned char *) opusArray, opusSize, pcmArray, pcmSize, 0);
env->ReleaseShortArrayElements(pcm, pcmArray, 0);
env->ReleaseByteArrayElements(opus, opusArray, 0);
return nRet;
}
JNIEXPORT jint JNICALL Java_com_cast_opus_decoder_Decoder__1destroyDecoder
(JNIEnv *env, jobject obj){
OpusLogI(TAG,"destroyDecoder");
if (!gOpusDec)
return 0;
opus_decoder_destroy(gOpusDec);
gOpusDec = NULL;
return 0;
}
三、编解码调用
pcm编码为opus
private byte[] encode(short[] buf) {
short[] newShortBuf = new short[1920];
System.arraycopy(buf, 0, newShortBuf, 0, newShortBuf.length);
Logger.i(TAG, "opus---- origin: " + Arrays.toString(newShortBuf));
byte[] opus = new byte[newShortBuf.length / 8];
if (mOpusEncoder == null) {
mOpusEncoder = new Encoder();
mOpusEncoder.initEncoder(null);
}
int result = mOpusEncoder.encode(opus, newShortBuf);
//Logger.i(TAG, "opus---- encode opus: " + Arrays.toString(opus));
byte[] newOpus = new byte[result];
System.arraycopy(opus, 0, newOpus, 0, newOpus.length);
return newOpus;
}
opus解码为pcm
private short[] decode(byte[] buf) {
short[] pcm = new short[1920];
if (mOpusDecoder == null) {
mOpusDecoder = new Decoder();
mOpusDecoder.initDecoder(null);
}
int result = mOpusDecoder.decode(pcm, buf);
Logger.i(TAG, "decode " + result);
short[] newPcm = new short[result];
System.arraycopy(pcm,0,newPcm,0,newPcm.length);
return newPcm;
}
opus android编译,Mac系统opus Android编译集成相关推荐
- imac android studio,MAC系统下Android Studio 实用小技巧 – 站长微资讯
MAC系统下Android Studio 常用快捷键 1 . Cmd + C 复制,Cmd + Shift + C 复制文件路径 2 . Cmd + V 粘贴, Cmd + Shift + V 从剪切 ...
- Q106:Mac系统下安装编译PBRT-V3
Mac和Linux比较类似,所以,"Mac系统下安装编译PBRT-V3"和"Linux系统下安装编译PBRT-V3"是非常相似的. 基于"Q106:L ...
- mac 系统下android源码下载以及使用(总结)
曾经买了本android系统内核分析的书,看了一段看不懂,工作也忙,差不多两年过去了,感觉android水平需要提高一下,就装备把书看看,但是在网上找了一些文章,参考了官方的下载方式,最后都没有很好的 ...
- mac调试android studio,Mac系统下AndroidStudio真机调试
Mac系统下AndroidStudio真机调试. 一.首先将android手机通过USB数据线连接Mac,获取设备的Product ID,这里提供两种获取方式: 打开终端输入:system_profi ...
- mac安装软件管理Android手机,Mac如何管理Android手机:这方式很得体
[PConline 评测]还记得是在8月份锤子的发布会上,除了带来了新的坚果手机外,在系统领域,老罗吐槽安卓系统和 Mac 连接时,传输和管理文件的方极为丑陋,因此他们为Mac用户精心开发了一款名为S ...
- android 4.0系统,全新Android 4.0系统_手机Android频道-中关村在线
与搭载Android 2.3系统的OPPO R807不同,OPPO R817搭载了Android 4.0系统.不过这款手机仍旧舍弃了Android系统的原生界面,因此两款手机在界面上的变化其实并不非常 ...
- android自动获取系统时间,Android获取系统时间的多种方法
Android中获取系统时间有多种方法,可分为Java中Calendar类获取,java.util.date类实现,还有android中Time实现. 现总结如下: 方法一: void getTime ...
- android 判断华为系统版本号,Android获取系统(ROM)类别及版本号
很多时候我们需要知道用户当前使用的是什么系统,甚至是系统的版本号(比如MIUI V7.V8)来进一步处理业务逻辑,比如打开系统权限设置界面. 感谢国内各大Android手机/系统生产商,让我们这些An ...
- Android的mac和BSSID,Android 获取本机的mac和wifi的BSSID(mac)以及其他信息
一上班就开始总结上礼拜写的wifi,先来说说wifi的属性 在Android的官方文档中定义了如下五种状态: WIFI_STATE_DISABLED WIFI 不可用 WIFI_STATE_DIS ...
最新文章
- 《web全栈工程师的自我修养》阅读笔记
- 【VBA编程】15.WorkSheet对象常用属性
- Java 运行时的内存划分
- TSS描述符表的作用
- java redis快速入门_SpringDataRedis快速入门
- 蚂蚁集团网络通信框架 SOFABolt 功能介绍及协议框架解析 | 开源
- 【2013.4.6】微软暑期实习生答案(zz)
- python数据抓取技术与实战训练_师傅带徒弟学Python:项目实战1:网络爬虫与抓取股票数据...
- 【剑指offer】二叉搜索树转双向链表,C++实现
- Microsoft.Office.Interop.Excel 报错
- Java-JVM第一篇认识JVM
- 基于 Spark推荐 系统应用 现 状
- 【java基础】Eclipse Java注释模板设置详解以及版权声明
- 全国计算机b类一级考试试题题库,全国计算机等级考试模拟题:一级B试题(一)...
- Kali欺骗网关攻击Windows10截取数据
- 如何查看win10已激活密钥?查看win10已激活完整密钥的方法!
- 测度空间上的可测函数和性质
- 世界通用闹铃(闹钟铃声)铃声 世界通用闹铃(闹钟铃声)手机铃声...
- 数据智仓功能介绍(一)
- 手机怎么使用涂鸦?分享几个手机视频怎么添加涂鸦的妙招
热门文章
- 031_自己对ArrayList中Iterator的实现
- 056_Object对象方法
- 022_html计算机输出标签
- 去除 计算机里面的百度云管家,WIN7如何彻底清除“百度云管家”图标或残留文件?...
- 工具用途_德普优化使用指南:16个工具的功能及用途(工具文)
- android字符显示流程图,Android应用层View绘制流程与源码分析
- 矩形变弧度角_在上海做下颌角整形这些医生错过后悔都来不及,案例分享
- Java 程序死锁问题原理及解决方案
- c语言87,C语言程序设计87300.doc
- kali linux 的ssh服务器,如何在 Kali Linux 上安装 SSH 服务