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.
- 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音频解码库(第二部分,封装解码器接口)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS - Quartz 2D 画板绘制
- 下一篇: 编程常见处理逻辑