欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 运维知识 > Android >内容正文

Android

EasyDarwin开源音频解码项目EasyAudioDecoder:EasyPlayer Android音频解码库(第二部分,封装解码器接口)...

发布时间:2025/5/22 Android 60 豆豆
生活随笔 收集整理的这篇文章主要介绍了 EasyDarwin开源音频解码项目EasyAudioDecoder:EasyPlayer Android音频解码库(第二部分,封装解码器接口)... 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

上一节我们讲了如何基于ffmpeg-Android工程编译安卓上的支持音频的ffmpeg静态库:http://blog.csdn.net/xiejiashu/article/details/52524099,这篇文章我们将介绍如何封装安卓的解码器。

首先,为了能让我们的app调用调用,我们需要定义一套Java的native接口,解码器主要有三个接口:

  • create 创建解码器,参数分别为: 
    • codec:音频编码格式,参考EasyTypes.h里面的EASY_SDK_AUDIO_CODEC_*宏定义;
    • sample_rate:采样率,通常为8000、44000等等;
    • channels:通道数,1、2分别表示单通道、双通道;
    • sample_bit:采样精度,通常为16bit; 
      返回解码器句柄,即后续接口里面用到的handle
  • decode 解码,参数为: 
    • handle :解码器句柄
    • buffer:要解码的buffer(编码后的音频数据)
    • offset:编码数据在buffer里的起始位置
    • length:编码数据的长度
    • pcm:解码后的pcm数据
    • outLen 长度至少为1的int数组,如果解码成功,那outLen[0]被置为pcm的数据长度
  • close 关闭解码器,参数为解码器的句柄。关闭后句柄无效,应该置为0.
package org.easydarwin.audio;/*** Created by John on 2016/3/18.*/ public class AudioCodec {static {System.loadLibrary("AudioCodecer");}public static native int create(int codec, int sample_rate, int channels, int sample_bit);public static native int decode(int handle, byte[] buffer, int offset, int length, byte[] pcm, int[] outLen);public static native void close(int handle); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

接下来我们要实现相应的native接口,头文件可通过调用javah命令(这里不再详述)来生成。以AAC解码来说明,create代码片段如下:

// 创建获取解码器AVCodec *pCodec = avcodec_find_decoder(AV_CODEC_ID_AAC);if (pCodec == NULL){LOGI("find aac decoder error");printf("find aac decoder error\r\n");return 0;}// 创建解码Context并open解码器pCodecCtx = avcodec_alloc_context3(pCodec);pCodecCtx->channels = channels;pCodecCtx->sample_rate = sample_rate;pCodecCtx->bit_rate = bit_rate;if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0){printf("open codec error\r\n");return 0;}// 分配内存,存放解码后的数据pFrame = av_frame_alloc();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

decode:

// 源码流赋值packet.size = length;packet.data = buffer;int got_frame = 0;// 解码、数据拷贝while (pkt_pos < nLen){// pkt_pos = 0;int got_frame = 0;src_len = avcodec_decode_audio4(pAACD->pCodecCtx, pAACD->pFrame, &got_frame, &packet);if (src_len < 0){return -3;}data_len += src_lenif (got_frame){memcpy(pAACD->pFrame, pAACD->audio_buf, len);dst_len += len;}pkt_pos += src_len;packet.data = pData + pkt_pos;packet.size = nLen - pkt_pos;}if (NULL != outLen) *outLen = dst_len;// 释放av_free_packet(&packet);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

close:

av_frame_free(&pFrame);avcodec_close(pComponent->pCodecCtx);avcodec_free_context(&pCodecCtx);
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

对于其它格式的音频算法,只要在avcodec_find_decoder时传入不同的算法ID即可。

接下来,我们需要使用NDK编译出ANDROID上可以使用的动态库,为此我们需要编辑Android.mk文件,其内容如下:

# Copyright (C) 2009 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # LOCAL_PATH:= $(call my-dir) SRC_ROOT_PATH := $(call my-dir) LOCAL_INCLUDE := $(LOCAL_PATH)/aacdec/include # 加载预编译的静态库 include $(CLEAR_VARS) LOCAL_MODULE := libavcodec LOCAL_SRC_FILES := $(LOCAL_PATH)/aacdec/lib/libavcodec.a include $(PREBUILT_STATIC_LIBRARY)include $(CLEAR_VARS) LOCAL_MODULE := libavdevice LOCAL_SRC_FILES := $(LOCAL_PATH)/aacdec/lib/libavdevice.a include $(PREBUILT_STATIC_LIBRARY)include $(CLEAR_VARS) LOCAL_MODULE := libavfilter LOCAL_SRC_FILES := $(LOCAL_PATH)/aacdec/lib/libavfilter.a include $(PREBUILT_STATIC_LIBRARY)include $(CLEAR_VARS) LOCAL_MODULE := libavformat LOCAL_SRC_FILES := $(LOCAL_PATH)/aacdec/lib/libavformat.a include $(PREBUILT_STATIC_LIBRARY)include $(CLEAR_VARS) LOCAL_MODULE := libavutil LOCAL_SRC_FILES := $(LOCAL_PATH)/aacdec/lib/libavutil.a include $(PREBUILT_STATIC_LIBRARY)include $(CLEAR_VARS) LOCAL_MODULE := libswresample LOCAL_SRC_FILES := $(LOCAL_PATH)/aacdec/lib/libswresample.a include $(PREBUILT_STATIC_LIBRARY)include $(CLEAR_VARS) LOCAL_MODULE := libswscale LOCAL_SRC_FILES := $(LOCAL_PATH)/aacdec/lib/libswscale.a include $(PREBUILT_STATIC_LIBRARY)include $(CLEAR_VARS)LOCAL_C_INCLUDES += $(LOCAL_PATH) LOCAL_C_INCLUDES += $(LOCAL_INCLUDE)PROJECT_FILES := $(wildcard $(SRC_ROOT_PATH)/*.cpp) PROJECT_FILES += $(wildcard $(SRC_ROOT_PATH)/*.c) PROJECT_FILES += $(wildcard $(SRC_ROOT_PATH)/aacdec/*.cpp)$(warning $(PROJECT_FILES)) PROJECT_FILES := $(PROJECT_FILES:$(LOCAL_PATH)/%=%) $(warning $(PROJECT_FILES)) LOCAL_SRC_FILES := $(PROJECT_FILES)LOCAL_CFLAGS := -D__unix__ -DANDROID_OS -D__arm__ -D__STDC_CONSTANT_MACROSLOCAL_MODULE := AudioCodecerLOCAL_LDLIBS += -L$(LOCAL_PATH)/aacdec/lib -lavcodec -lswscale -lswresample -lavutil -lavformat -lavfilter -lavdevice -llog -lzCFLAGS += -mfpu=neonLOCAL_STATIC_LIBRARIES := libavcodec libswscale libswresample libavutil libavformat libavfilter libavdeviceinclude $(BUILD_SHARED_LIBRARY)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

我们这里需要把之前编译出来的静态库链接起来,生成一个动态库。其中,静态库lib文件和头文件分别放在/aacdec/lib/ 和 /aacdec/include/ 下。

接下来,cd到jni目录,执行ndk-build,如果顺利的话,我们要的动态库文件就会生成。

整个项目源码见Github

转载于:https://www.cnblogs.com/babosa/p/5904606.html

总结

以上是生活随笔为你收集整理的EasyDarwin开源音频解码项目EasyAudioDecoder:EasyPlayer Android音频解码库(第二部分,封装解码器接口)...的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。