這個系列的文章將會研究最純粹的Android直播的實現(xiàn),而且不是用現(xiàn)在的集成SDK來達到直播的技術實現(xiàn),而是從一個比較底層的直播實現(xiàn)來探討這個技術,這樣子對于直播技術的實現(xiàn),現(xiàn)成的一些直播框架等都有一個比較好的理解。
現(xiàn)在的一些視頻文件都是經過編碼–>封裝得到的,比如說一個mp4的視頻文件mp4就是它的封裝格式,h.264就是它的編碼格式(h.264是現(xiàn)在最廣泛的編碼格式了絕大部分的視頻文件都是用它來進行編碼的),那么我們的一個視頻的播放就會是下面的流程了:
mp4文件–>h.264文件(解封裝后生成)–>yuv文件(解碼后生成)
yuv就是比較原始的視頻文件了,它是非常的大的,和h.264文件相比,可以達到1:100就是說10M大小的h.264文件解碼后生成的yuv文件會達到100多M。所以我們的視頻文件都會經過一個編碼的過程。
那么反過來,我們生成一個視頻文件的時候也就會經過:
yuv文件(h.264編碼)–>h.264文件(mp4封裝)–>mp4文件
比如說我們Android默認的Camera的預覽數(shù)據就是一種yuv的數(shù)據來的,所以我們從Camera里面獲取的yuv數(shù)據,然后經過一個h.264的編碼,然后就可以進行封裝或者傳輸了。
那么直播的這個過程就有可能會是下面那樣了:
這系列的文章主要就會研究Android端的直播和看直播的技術,直播并不單單只有RTMP一種協(xié)議,還有RTP這些協(xié)議等,RTMP比較常用,它使用的封裝格式是FLV的,用的網絡協(xié)議是TCP,RTP用的封裝格式是mpegts,用的網絡協(xié)議是UDP。這里就會使用RTMP這種協(xié)議。
在那個圖片里面可以看到,在推流前,主要做的就是完成一個視頻文件的生成了yuv–>h.264,在Camera獲取到的yuv數(shù)據里面,其實我們還可以加上養(yǎng)顏啊,特效疊加這些功能,然后再進行編碼。也可以對聲音進行處理,比如說娃娃音這些。
注意:聲音是在視頻封裝的時候才加上去的,解封裝的時候是會把圖像數(shù)據和音頻數(shù)據分開的
要注意的是編碼格式和封裝格式是有很多種的,這個系列文章并不會詳細的研究這個,只會在需要的時候講解這些知識,所以如果想詳細知道這些編碼和封裝的知識的,可以先去Google一下。下面我們就要進入我們這篇文章的實戰(zhàn)了,首先就是平臺、工具的介紹:
Windows7
MinGW
AndroidStudio 2.2
NDK(r13b)
FFmpeg 3.4
libx264
因為我是在Windows平臺下進行編譯的,所以就需要MinGW了,MinGW的安裝一定要安裝msys,不然就沒辦法進行編譯了。
在開發(fā)過程中,推薦使用AndroidStudio2.2以上的版本,因為2.2之后,對NDK的支持有了很大的提升,比如說:不需要自己javah來生成native方法對應的C方法了,AS會幫我們自動生成,這個功能就很值得使用了,當然還有其他強大的NDK支持。
我使用的NDK的版本是r13b,最好使用比較新版本的NDK,因為AndroidStudio都使用到2.2了
在直播的流程中,可以看到我們需要對視頻進行編碼,封裝等操作,那么進行這些操作的話,我們需要FFmpeg這個庫來完成,F(xiàn)Fmpeg對音視頻的處理是非常的強大的。這樣說吧,常見的播放器,QQ影音,暴風影音啊,都是使用FFmpeg來進行核心的解碼,編碼等操作的,格式工廠
這些轉換軟件也是,而且現(xiàn)在的一些集成的直播方案,絕大部分也是對FFmpeg進行了包裝。所以在這個系列中,就會使用FFmpeg來還原最純粹的直播技術,這樣就可以知道現(xiàn)在打包好的直播技術是怎樣實現(xiàn)的。PS:FFmpeg的讀法是: F F mpeg 而不是一個一個字母的讀
libx264是一個h.264的編碼器,在使用FFmpeg的AV_CODEC_ID_H264編碼器進行編碼的時候,我們就需要使用到這個庫了,所以編碼FFmpeg的時候,我們會把libx264加進去。
默認Android開發(fā)環(huán)境已經配置好,NDK環(huán)境弄好,安裝完成MinGW之后,我們再把FFmpeg和libx264下載下來就可以了,然后解壓好。
然后我們修改一下里面的configure文件,讓我們編譯出來的文件不會帶有奇怪的名字,不被Android識別。只要把
SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'LIB_INSTALL_EXTRA_CMD='$$(RANLIB) '$(LIBDIR)/$(LIBNAME)''SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'
1
2
3
4
修改成
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)' LIB_INSTALL_EXTRA_CMD='$$(RANLIB)'$(LIBDIR)/$(LIBNAME)'' SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)' SLIB_INSTALL_LINKS='$(SLIBNAME)'
1
2
3
4
修改完成之后,我們就要在當前目錄新建一個.sh文件,就是shell腳本
#!/bin/bash NDK=E:/Programs/android-ndk-r13bSYSROOT=$NDK/platforms/android-19/arch-arm/TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64function build_one { ./configure \ --prefix=$PREFIX \ --enable-asm \ --enable-neon \ --enable-static \ --enable-small \ --disable-shared \ --disable-ffmpeg \ --disable-ffplay \ --disable-ffprobe \ --disable-ffserver \ --disable-avdevice \ --disable-doc \ --disable-symver \ --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \ --target-os=linux \ --arch=arm \ --cpu=armv7-a \ --enable-cross-compile \ --sysroot=$SYSROOT \ --extra-cflags='-fPIC -DANDROID -mfpu=neon -mfloat-abi=softfp -I$NDK/platforms/android-19/arch-arm/usr/include' \ --extra-ldflags='$ADDI_LDFLAGS' make clean make make install } CPU=arm PREFIX=$(pwd)/android/$CPU ADDI_CFLAGS='-marm' build_one
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
在這個腳本前面,配置了三個變量,都是指定好NDK的一些工具,目錄的,要注意的是在:SYSROOT里面,我編譯的platform是android-19的,因為NDK對platform有時會有一些影響的,做過深入的NDK開發(fā)的同學應該清楚,所以這個要看具體的需要進行更改什么的。
–enable-asm 開啟匯編
–enable-neon 針對armv7-a平臺的專屬指令集進行的優(yōu)化,可以讓編碼效率提升
–enable-small 可以盡量的縮小編譯出來的庫大小,比如我沒打開它,編譯出來的.a有80多M,開啟后就只有57M左右
–disable-ffmpeg 不要ffmpeg這個工具,ffmpeg是一個命令行工具,非常強大,在官網也可以看到,但我們通過代碼開發(fā),就不需要它了
–disable-ffplay –disable-ffprobe –disable-ffserver 這些都是不需要的工具,當然也可以編譯出來看看
–disable-avdevice 這個庫是用來操作一些硬件設備的,如攝像頭這些,但Android中感覺不需要它,也可以編譯出來試試能不能使用在Android上
–disable-symver 禁用 symbol versioning
PREFIX=(pwd)/android/CPU 指定編譯成功的庫所在的目錄,這個配置是:當前目錄下的android目錄下的指定的cpu平臺目錄下
–enable-static –disable-shared這兩個是看編譯出來的庫是靜態(tài)庫(.a)還是動態(tài)庫(.so),如果要編譯成動態(tài)庫就–enable-shared –disable-static?;蛘邇蓚€都編譯出來。
動態(tài)庫就是只要Android設備里面有公開這個so,那APP就可以使用,就是只要一次安裝,其他APP就可以使用了
但APP打包進去的so都是在當前APP的私有目錄下的,不能被其他APP使用的,所以動態(tài)庫的優(yōu)勢就沒有了,
而且就暴露了它的缺點,就是so非常大的時候,就會形成Apk包非常大
靜態(tài)庫就是會把需要的代碼打包到自己的so里面,所以這樣子就可以解決動態(tài)庫上面的那個缺點
所以這里我們編譯出來的是靜態(tài)庫,因為編譯出來的庫有50多M,所以使用靜態(tài)庫的方式,可以使打包出來的apk最小化
其他的配置都是比較通俗易懂的了,就不多做解釋了。上面那個腳本編譯出來的就是一個完整功能的FFmpeg庫了,我們就可以打開MinGW的msys了
打開msys.bat,然后cd到FFmpeg的根目錄,執(zhí)行./build_script.sh ,就是執(zhí)行我們上面寫的腳本
要打開一個盤:如打開E盤,cd /e 就可以了。
運行那個腳本就會進行一個編譯的了,編譯過程中,有時可以什么反應都沒有,千萬不要以為沒有運行,停止它,因為編譯是比較耗時的,編譯個20分鐘是很正常的,電腦性能好的,會快點,差的可能半小時都正常,要確定有沒有在編譯,可以查看一下cpu的使用率就可以了。
經過一段時間的編譯,我們就可以在腳本里面定義的那個目錄里面看到編譯成功的庫了。在當前目錄下就會有一個android的目錄,點進里面后,就會看到編譯成功的庫了
可以看到有7個庫左右。可能版本不一樣或配置不一樣會有不一樣的庫,一般用到的會是libavcodec libavfilter libavformat libavutil libswscale這些。
這些庫的功能都是非常齊全的,包含了大量的編解碼器等,但有時我們并不需要那么多功能,這樣就可以通過禁用一些功能來達到精簡一些庫的大小了
如:不需要解碼器 –disable-decoders就可以在上面的那個編譯腳本里面加上這個配置。如果只需要某個解碼器就可以指定–disable-decoders –enable-decoder=h264 這樣就是先禁用解碼器,然后指定一個解碼器,就是只需要h264的解碼器了
所以就可能通過上面那個文件達到精簡庫的大小了,如下面那個精簡的腳本:
#!/bin/bash NDK=E:/Programs/android-ndk-r13bSYSROOT=$NDK/platforms/android-19/arch-arm/TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64function build_one { ./configure \ --prefix=$PREFIX \ --enable-asm \ --enable-neon \ --enable-static \ --enable-small \ --disable-shared \ --disable-doc \ --disable-ffmpeg \ --disable-ffplay \ --disable-ffprobe \ --disable-ffserver \ --disable-avdevice \ --disable-symver \ --disable-muxers \ --enable-muxer=mov \ --enable-muxer=mp4 \ --enable-muxer=avi \ --disable-decoders \ --enable-decoder=aac \ --enable-decoder=h264 \ --enable-decoder=mpeg4 \ --disable-demuxers \ --enable-demuxer=h264 \ --enable-demuxer=avi \ --disable-parsers \ --enable-parser=aac \ --enable-parser=h264 \ --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \ --target-os=linux \ --arch=arm \ --cpu=armv7-a \ --enable-cross-compile \ --sysroot=$SYSROOT \ --extra-cflags='-fPIC -DANDROID -mfpu=neon -mfloat-abi=softfp -I$NDK/platforms/android-19/arch-arm/usr/include' \ --extra-ldflags='$ADDI_LDFLAGS' make clean make make install } CPU=arm PREFIX=$(pwd)/android/$CPU ADDI_CFLAGS='-marm' build_one
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
這樣就可以大大的縮小庫的大小了
那么,接下來就要編譯包含了libx264的FFmpeg庫了,首先,我們要先編譯libx264,我們先在msys里面cd到libx264的目錄下面,然后再新建一個shell腳本:
#!/bin/bash NDK=E:/Programs/android-ndk-r13bSYSROOT=$NDK/platforms/android-19/arch-arm/TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64function build_one { ./configure \ --prefix=$PREFIX \ --enable-static \ --enable-pic \ --disable-asm \ --disable-cli \ --host=arm-linux \ --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \ --sysroot=$SYSROOT make clean make make install }PREFIX=$(pwd)/android-lib/build_one
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
配置基本上是差不多的,其實這些配置都是可以在configure文件里面找到的,大家可以看看。這里,我們也是編譯成靜態(tài)庫。
編譯成功后,我們就會在當前目錄下的android-lib目錄里面看到編譯的結果。
那么我們就要把android-lib整個目錄拷貝到FFmpeg的根目錄下面了,然后就準備編譯FFmpeg
其實也很簡單,只需要把上面的編譯文件添加一些東西就行了
#!/bin/bash NDK=E:/Programs/android-ndk-r13bSYSROOT=$NDK/platforms/android-19/arch-arm/TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64EXTRA_LIB=E:/Programs/FFmpeg-3.2.4/android-libfunction build_one { ./configure \ --prefix=$PREFIX \ --enable-asm \ --enable-neon \ --enable-static \ --enable-small \ --enable-libx264 \ --enable-gpl \ --enable-encoder=libx264 \ --disable-shared \ --disable-doc \ --disable-ffmpeg \ --disable-ffplay \ --disable-ffprobe \ --disable-ffserver \ --disable-avdevice \ --disable-symver \ --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \ --target-os=linux \ --arch=arm \ --cpu=armv7-a \ --enable-cross-compile \ --sysroot=$SYSROOT \ --extra-cflags='-I$EXTRA_LIB/include -fPIC -DANDROID -mfpu=neon -mfloat-abi=softfp -I$NDK/platforms/android-19/arch-arm/usr/include' \ --extra-ldflags='-L$EXTRA_LIB/lib -lx264 $ADDI_LDFLAGS' make clean make make install } CPU=arm PREFIX=$(pwd)/android/x264_lib/$CPU ADDI_CFLAGS='-marm' build_one
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
EXTRA_LIB 指定剛剛編譯的libx264的目錄
–enable-libx264 –enable-gpl 就是把libx264啟用,兩個都需要加
–extra-cflags –extra-ldflags需要指定編譯libx264所生成的頭文件的lib文件
這樣子,我們就可以編譯一個帶有l(wèi)ibx264編碼器的FFmpeg庫了
首先,新建一個新的AndroidStudio項目
在新建項目的時候,最好不要勾選*Include C++ Support,因為它默認是采用cmake編譯的,所以對于我們想到ndk_build的話就要修改配置了,所以最好不要勾選,除非你用cmake。
新建項目完成之后呢,我們就把視圖選成project,然后再在main目錄下新建一個cpp的目錄
新建cpp目錄完成后,就可以把Android.mk和Application.mk文件給拷貝或新建到這個目錄里面了,然后再新建一個c的源文件
注意:這里新建的文件是.c的源文件,為什么不要新建.cpp的源文件,
是因為使用.cpp的源文件的時候,會編譯不通過,因為FFmpeg是一個純c語言的項目
也有可能是我的項目配置的問題,所以這里我是新建.c的文件
有找到原因或解決方法的也可以告訴我
我在.cpp 里面使用 extern “C” 也是會編譯不通過的
做完這些之后,就可以配置Gradle了,在main目錄上右鍵
要注意,這里我們要選擇的是ndk_build,除非用想使用的是cmake,選完這個之后,就再把我們上面添加的Android.mk文件指定到下面的那個Project Path里面去。確定完成后,Gradle就會自動添加一些編譯一次的。這樣子,這個項目就可以成為一個NDK的項目了
接下來,就要把我們剛剛編譯成功的FFmpeg,libx264的庫,頭文件,都拷貝到cpp這個目錄下
然后就要編寫Android.mk文件了
LOCAL_PATH := $(call my-dir)# prepare libXinclude $(CLEAR_VARS)TARGET_ARCH_ABI := armeabi-v7aLOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/includeLOCAL_MODULE := avcodecLOCAL_SRC_FILES := libavcodec.ainclude $(PREBUILT_STATIC_LIBRARY)# prepare libXinclude $(CLEAR_VARS)TARGET_ARCH_ABI := armeabi-v7aLOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/includeLOCAL_MODULE := avfilterLOCAL_SRC_FILES := libavfilter.ainclude $(PREBUILT_STATIC_LIBRARY)# prepare libXinclude $(CLEAR_VARS)TARGET_ARCH_ABI := armeabi-v7aLOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/includeLOCAL_MODULE := avformatLOCAL_SRC_FILES := libavformat.ainclude $(PREBUILT_STATIC_LIBRARY)# prepare libXinclude $(CLEAR_VARS)TARGET_ARCH_ABI := armeabi-v7aLOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/includeLOCAL_MODULE := avutilLOCAL_SRC_FILES := libavutil.ainclude $(PREBUILT_STATIC_LIBRARY)# prepare libXinclude $(CLEAR_VARS)TARGET_ARCH_ABI := armeabi-v7aLOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/includeLOCAL_MODULE := postprocLOCAL_SRC_FILES := libpostproc.ainclude $(PREBUILT_STATIC_LIBRARY)# prepare libXinclude $(CLEAR_VARS)TARGET_ARCH_ABI := armeabi-v7aLOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/includeLOCAL_MODULE := swresampleLOCAL_SRC_FILES := libswresample.ainclude $(PREBUILT_STATIC_LIBRARY)# prepare libXinclude $(CLEAR_VARS)TARGET_ARCH_ABI := armeabi-v7aLOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/includeLOCAL_MODULE := swscaleLOCAL_SRC_FILES := libswscale.ainclude $(PREBUILT_STATIC_LIBRARY)# prepare libXinclude $(CLEAR_VARS)TARGET_ARCH_ABI := armeabi-v7aLOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/includeLOCAL_MODULE := x264LOCAL_SRC_FILES := libx264.ainclude $(PREBUILT_STATIC_LIBRARY)include $(CLEAR_VARS)TARGET_ARCH_ABI := armeabi-v7aLOCAL_MODULE := live_jniLOCAL_SRC_FILES := live_jni.cLOCAL_C_INCLUDES += $(LOCAL_PATH)/includeLOCAL_CFLAGS := -D__STDC_CONSTANT_MACROS -Wno-sign-compare -Wno-switch -Wno-pointer-sign -DHAVE_NEON=1 -mfpu=neon -mfloat-abi=softfp -fPIC -DANDROIDLOCAL_STATIC_LIBRARIES := avfilter avformat avcodec postproc swresample swscale avutil x264LOCAL_LDLIBS := -L$(NDK_ROOT)/platforms/$(APP_PLATFORM)/arch-arm/usr/lib -L$(LOCAL_PATH) -llog -ljnigraphics -lz -ldlinclude $(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
80
81
這個Android.mk有些不要必須的,之些踩坑可能就會寫得有些重復。所以看需要各位進行調整
TARGET_ARCH_ABI := armeabi-v7a
最好指定一下平臺,有時候ndk prebuild的時候,有可能會編譯全平臺,就會出現(xiàn)找不到對應的庫的問題的了
LOCAL_STATIC_LIBRARIES := avfilter avformat avcodec postproc swresample swscale avutil x264
這個是非常重要的,后面的那些庫的順序是有講究的,如果順序有問題,有可能會報找不到鏈接的問題
因為FFmpeg每個版本都可能不一樣的,所以想要知道這個的順序,可以去FFmpeg目錄下的Makefile文件看看
# $(FFLIBS-yes) needs to be in linking orderFFLIBS-$(CONFIG_AVDEVICE) += avdeviceFFLIBS-$(CONFIG_AVFILTER) += avfilterFFLIBS-$(CONFIG_AVFORMAT) += avformatFFLIBS-$(CONFIG_AVCODEC) += avcodecFFLIBS-$(CONFIG_AVRESAMPLE) += avresampleFFLIBS-$(CONFIG_POSTPROC) += postprocFFLIBS-$(CONFIG_SWRESAMPLE) += swresampleFFLIBS-$(CONFIG_SWSCALE) += swscale
1
2
3
4
5
6
7
8
9
Android.mk文件寫好了之后,我們就寫一下Application.mk文件了
APP_STL := gnustl_staticAPP_LDFLAGS := -latomicAPP_ABI := armeabi-v7aAPP_PLATFORM := android-19
1
2
3
4
APP_LDFLAGS
這個最好指定一下 不然可能報 undefined reference to '__atomic_fetch_add_4 error
編寫完成Application.mk后,我們最好還是去配置一下app的build.gradle
externalNativeBuild { ndkBuild { arguments 'NDK_APPLICATION_MK=src/main/cpp/Application.mk' cppFlags '-frtti', '-fexceptions' abiFilters 'armeabi-v7a' } }
1
2
3
4
5
6
7
到現(xiàn)在,我們的整個配置就可以完成了?,F(xiàn)在就可以回到MainActivity里面,然后添加一個native方法,然后在方法上Alt+Enter,這樣子就會有提示,然后Enter讓它生成native方法對應的c方法就可以了
但是,第一次生成對應的native方法的時候,可能會有點問題的
它會新建一個jni的目錄,里面新建一個c文件,生成在里面了,我們只要把這個生成的方法,拷貝到我們自己新建的c文件里面,就可以自動建立關聯(lián)了,這樣,以后再自動生成的方法都會在我們新建的那個文件里面了。然后,我們把jni這個目錄刪掉就行了。
按照Android的官方文檔顯示,Application.mk是不需要自己指定的,它會自動的添加進去的(要和Android.mk同一路徑)
這樣子,我們就可以寫我們的FFmpeg的代碼了
#include <jni.h>#include 'libavcodec/avcodec.h'JNIEXPORT jstring JNICALLJava_com_xiaoxiao_live_MainActivity_helloFromFFmpeg(JNIEnv *env, jobject instance) { // TODO char info[10000] = {0}; sprintf(info, '%s\n', avcodec_configuration()); return (*env)->NewStringUTF(env, info);}
1
2
3
4
5
6
7
8
9
10
11
12
13
然后在MainActivity里面把so加載進去就可以了
寫完這個之后,我們就可以把我們的項目運行起來了
得到這個結果就說明我們的FFmpeg編譯是成功的,而且我們也可以在Android上面使用了
而且從上面看到,我們打包出來的so是非常的小的,這樣就可以大大減少我們apk包的大小了
提示:如果修改了Android.mk 或build.gradle文件,建議執(zhí)行一下下面的操作
到這里,我們的編譯和運行就已經完成了,那么接下來,我們就要處理Android的Camera了,以及完成編碼,推流等操作了。
聯(lián)系客服