首先看MediaRecorder.java內(nèi)的setVideoEncoder方法:

在網(wǎng)站制作、網(wǎng)站建設(shè)中從網(wǎng)站色彩、結(jié)構(gòu)布局、欄目設(shè)置、關(guān)鍵詞群組等細(xì)微處著手,突出企業(yè)的產(chǎn)品/服務(wù)/品牌,幫助企業(yè)鎖定精準(zhǔn)用戶,提高在線咨詢和轉(zhuǎn)化,使成都網(wǎng)站營(yíng)銷成為有效果、有回報(bào)的無錫營(yíng)銷推廣。成都創(chuàng)新互聯(lián)專業(yè)成都網(wǎng)站建設(shè)10多年了,客戶滿意度97.8%,歡迎成都創(chuàng)新互聯(lián)客戶聯(lián)系。
/**
* Sets the video encoder to be used for recording. If this method is not
* called, the output file will not contain an video track. Call this after
* setOutputFormat() and before prepare().
*
* @param video_encoder the video encoder to use.
* @throws IllegalStateException if it is called before
* setOutputFormat() or after prepare()
* @see android.media.MediaRecorder.VideoEncoder
*/
public native void setVideoEncoder(int video_encoder)
throws IllegalStateException;123456789101112
這是一個(gè)native方法,根據(jù)JNI的規(guī)則,我們應(yīng)該去android_media_MediaRecorder.cpp里看這個(gè)方法的實(shí)現(xiàn):
static void
android_media_MediaRecorder_setVideoEncoder(JNIEnv *env, jobject thiz, jint ve)
{
ALOGV("setVideoEncoder(%d)", ve);
if (ve VIDEO_ENCODER_DEFAULT || ve = VIDEO_ENCODER_LIST_END) {
jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid video encoder");
return;
}
spMediaRecorder mr = getMediaRecorder(env, thiz);
process_media_recorder_call(env, mr-setVideoEncoder(ve), "java/lang/RuntimeException", "setVideoEncoder failed.");
}1234567891011
關(guān)鍵是最后的兩句,sp是Android 里的一個(gè)指針,就當(dāng)沒看見~ 所以最后兩句的意思是調(diào)用Native層的MediaRecorder的setVideoEncoder方法。
繼續(xù)去MediaRecorder.cpp里看setVideoEncoder方法:
status_t MediaRecorder::setVideoEncoder(int ve)
{
ALOGV("setVideoEncoder(%d)", ve);
if (mMediaRecorder == NULL) {
ALOGE("media recorder is not initialized yet");
return INVALID_OPERATION;
}
if (!mIsVideoSourceSet) {
ALOGE("try to set the video encoder without setting the video source first");
return INVALID_OPERATION;
}
if (mIsVideoEncoderSet) {
ALOGE("video encoder has already been set");
return INVALID_OPERATION;
}
if (!(mCurrentState MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
ALOGE("setVideoEncoder called in an invalid state(%d)", mCurrentState);
return INVALID_OPERATION;
}
status_t ret = mMediaRecorder-setVideoEncoder(ve);
if (OK != ret) {
ALOGV("setVideoEncoder failed: %d", ret);
mCurrentState = MEDIA_RECORDER_ERROR;
return ret;
}
mIsVideoEncoderSet = true;
return ret;
}1234567891011121314151617181920212223242526272829
這里的mMediaReocorder定義在MediaRecorder.h里:
spIMediaRecorder mMediaRecorder;1
可見其是一個(gè)IMediaRecorder類型的變量,這是一個(gè)接口類型,看一下其接口定義,在IMediaRecorder.h中:
class IMediaRecorder: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaRecorder);
virtual status_t setCamera(const sphardware::ICamera camera,
const spICameraRecordingProxy proxy) = 0;
virtual status_t setPreviewSurface(const spIGraphicBufferProducer surface) = 0;
virtual status_t setVideoSource(int vs) = 0;
virtual status_t setAudioSource(int as) = 0;
virtual status_t setOutputFormat(int of) = 0;
virtual status_t setVideoEncoder(int ve) = 0;
virtual status_t setAudioEncoder(int ae) = 0;
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
virtual status_t setVideoSize(int width, int height) = 0;
virtual status_t setVideoFrameRate(int frames_per_second) = 0;
virtual status_t setParameters(const String8 params) = 0;
virtual status_t setListener(const spIMediaRecorderClient listener) = 0;
virtual status_t setClientName(const String16 clientName) = 0;
virtual status_t prepare() = 0;
virtual status_t getMaxAmplitude(int* max) = 0;
virtual status_t start() = 0;
virtual status_t stop() = 0;
virtual status_t reset() = 0;
virtual status_t pause() = 0;
virtual status_t resume() = 0;
virtual status_t init() = 0;
virtual status_t close() = 0;
virtual status_t release() = 0;
virtual status_t setInputSurface(const spIGraphicBufferConsumer surface) = 0;
virtual spIGraphicBufferProducer querySurfaceMediaSource() = 0;
};
// ----------------------------------------------------------------------------
class BnMediaRecorder: public BnInterfaceIMediaRecorder
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel data,
Parcel* reply,
uint32_t flags = 0);
};12345678910111213141516171819202122232425262728293031323334353637383940414243
吶~關(guān)鍵的步驟來了,在以前我基本就追到這,就算完蛋了,不知道怎么繼續(xù)往下追了,后來看Binder相關(guān)的內(nèi)容,知道了BnInterface的作用,這是Binder中關(guān)鍵的一環(huán),我們這就不展開講了,只要記得,接下來我們要追的是BnMediaRecorder這個(gè)類。
全局搜索一下“: public BnMediaRecorder”,也就是去找它的實(shí)現(xiàn)類,發(fā)現(xiàn)在MediaRecorderClient.h當(dāng)中有如下的定義:
class MediaRecorderClient : public BnMediaRecorder
{
class ServiceDeathNotifier: public IBinder::DeathRecipient
{
public:
ServiceDeathNotifier(
const spIBinder service,
const spIMediaRecorderClient listener,
int which);
virtual ~ServiceDeathNotifier();
virtual void binderDied(const wpIBinder who);
private:
int mWhich;
spIBinder mService;
wpIMediaRecorderClient mListener;
};
public:
virtual status_t setCamera(const sphardware::ICamera camera,
const spICameraRecordingProxy proxy);
virtual status_t setPreviewSurface(const spIGraphicBufferProducer surface);
virtual status_t setVideoSource(int vs);
virtual status_t setAudioSource(int as);
virtual status_t setOutputFormat(int of);
virtual status_t setVideoEncoder(int ve);
virtual status_t setAudioEncoder(int ae);
virtual status_t setOutputFile(int fd, int64_t offset,
int64_t length);
virtual status_t setVideoSize(int width, int height);
virtual status_t setVideoFrameRate(int frames_per_second);
virtual status_t setParameters(const String8 params);
virtual status_t setListener(
const spIMediaRecorderClient listener);
virtual status_t setClientName(const String16 clientName);
virtual status_t prepare();
virtual status_t getMaxAmplitude(int* max);
virtual status_t start();
virtual status_t stop();
virtual status_t reset();
virtual status_t pause();
virtual status_t resume();
virtual status_t init();
virtual status_t close();
virtual status_t release();
virtual status_t dump(int fd, const VectorString16 args);
virtual status_t setInputSurface(const spIGraphicBufferConsumer surface);
virtual spIGraphicBufferProducer querySurfaceMediaSource();
private:
friend class MediaPlayerService; // for accessing private constructor
MediaRecorderClient(
const spMediaPlayerService service,
pid_t pid,
const String16 opPackageName);
virtual ~MediaRecorderClient();
spIBinder::DeathRecipient mCameraDeathListener;
spIBinder::DeathRecipient mCodecDeathListener;
pid_t mPid;
Mutex mLock;
MediaRecorderBase *mRecorder;
spMediaPlayerService mMediaPlayerService;
};123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
那么我們?nèi)ediaRecorderClient.cpp里看看:
status_t MediaRecorderClient::setVideoEncoder(int ve)
{
ALOGV("setVideoEncoder(%d)", ve);
Mutex::Autolock lock(mLock);
if (mRecorder == NULL) {
ALOGE("recorder is not initialized");
return NO_INIT;
}
return mRecorder-setVideoEncoder((video_encoder)ve);
}12345678910
這里的mRecorder 定義在MediaRecorderClient.h當(dāng)中:
MediaRecorderBase *mRecorder;1
來,我們繼續(xù)搜索“: public MediaRecorderBase”,在StagefrightRecorder.h中找到了,那么我們?nèi)tagefrightRecorder.cpp當(dāng)中看看~
status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
ALOGV("setVideoEncoder: %d", ve);
if (ve VIDEO_ENCODER_DEFAULT ||
ve = VIDEO_ENCODER_LIST_END) {
ALOGE("Invalid video encoder: %d", ve);
return BAD_VALUE;
}
mVideoEncoder = ve;
return OK;
}123456789101112
吶,這就算完了~最后我們會(huì)發(fā)現(xiàn)MediaRecorder中的接口實(shí)現(xiàn)基本到最后都會(huì)落在這個(gè)StagefrightRecorder.cpp當(dāng)中。
當(dāng)閱讀Android原生的應(yīng)用層源代碼時(shí),當(dāng)遇到不理解的API時(shí),如果僅憑將API函數(shù)放到google的官方API網(wǎng)頁(yè)中去搜索的話,不一定合適,可以用eclipse先搜到該函數(shù)的定義處,看屬于哪個(gè)類,然后再在google的官方API網(wǎng)頁(yè)中搜該類,然后找到這個(gè)方法,如果該方法還是沒在該類中,那么可以用eclipse找找該方法是不是繼承與其子類,再?gòu)淖宇愔兴阉选?/p>
構(gòu)建開發(fā)環(huán)境
1、 構(gòu)建Android編譯環(huán)境:
Ubuntu11.10-64bit系統(tǒng)、一系列編譯庫(kù)、JDK、Android SDK、Eclipse +ADT。
2、 Android官方原生Android代碼。
3、 源代碼根目錄下:
source build/envsetup.sh
lunch full-eng
make –j4
1、2、3相關(guān)內(nèi)容在都有相關(guān)說明。
4、 編譯Android源碼的同時(shí),可以建立Android源代碼Java工程
(1)將源碼目錄\development\ide\eclipse 中的.classpath復(fù)制到源碼根目錄下。
(2)更改eclipse緩存設(shè)置
在eclipse安裝根目錄下修改eclipse.ini
-Xms128m
-Xmx512m
-XX:MaxPermSize=256m
(3)將 源碼目錄\development\ide\eclipse 中的android-formatting.xml和android.importorder導(dǎo)入eclipse。
android-formatting.xml用來配置eclipse編輯器的代碼風(fēng)格;android.importorder用來配置eclipse的import的順序和結(jié)構(gòu)。
在android源碼中有一個(gè)目錄idegen,是生成ide的project文件,主要是生成intellij的project文件,用source insight閱讀Android源碼,效果非常好。
過程:
效果圖;
在開始編譯idegen模塊前,需要知道需要先全局編譯出out目錄及相關(guān)文件;
在根目錄生成對(duì)應(yīng)的android.ipr、android.iml IEDA工程配置文件;
導(dǎo)入到android studio,打開Android studio,點(diǎn)擊File Open,選擇剛剛生成的android.ipr就好了;
備注:
可以結(jié)合android studio,界面,智能提示都比source insight要好。
當(dāng)我們?cè)趀clipse中開發(fā)android程序的時(shí)候,往往需要看源代碼(可能是出于好奇,可能是讀源碼習(xí)慣),那么如何查看Android源代碼呢? 比如下面這種情況假設(shè)我們想?yún)⒖碅ctivity類的源代碼,按著Ctrl鍵,左擊它,現(xiàn)實(shí)的結(jié)果卻看不到代碼的,提示的信息便是“找不到Activity.class文件”。此時(shí)點(diǎn)擊下面的按鈕,“Change Attached Source…”,選擇android源代碼所在位置,便彈出圖三的對(duì)話框。 第一種是選擇工作目錄,即已經(jīng)存在的android應(yīng)用程序源代碼。 第二種分兩種方式 (1)選擇External File…按鈕,添加Jar格式文件或者zip格式文件路徑; (2)選擇External Floder…按鈕,添加文件夾所在路徑。 下面問題就來了,源代碼在哪里?不能憑空產(chǎn)生阿。 可以通過Android SDK Manager進(jìn)行源代碼下載;(推薦該種方法)
由于工作需要大量修改framework代碼, 在AOSP(Android Open Source Project)源碼上花費(fèi)了不少功夫, Application端和Services端都看和改了不少.
如果只是想看看一些常用類的實(shí)現(xiàn), 在Android包管理器里把源碼下載下來, 隨便一個(gè)IDE配好Source Code的path看就行.
但如果想深入的了解Android系統(tǒng), 那么可以看下我的一些簡(jiǎn)單的總結(jié).
知識(shí)
Java
Java是AOSP的主要語言之一. 沒得說, 必需熟練掌握.
熟練的Android App開發(fā)
Linux
Android基于Linux的, 并且AOSP的推薦編譯環(huán)境是Ubuntu 12.04. 所以熟練的使用并了解Linux這個(gè)系統(tǒng)是必不可少的. 如果你想了解偏底層的代碼, 那么必需了解基本的Linux環(huán)境下的程序開發(fā). 如果再深入到驅(qū)動(dòng)層, 那么Kernel相關(guān)的知識(shí)也要具備.
Make
AOSP使用Make系統(tǒng)進(jìn)行編譯. 了解基本的Makefile編寫會(huì)讓你更清晰了解AOSP這個(gè)龐大的項(xiàng)目是如何構(gòu)建起來的.
Git
AOSP使用git+repo進(jìn)行源碼管理. 這應(yīng)該是程序員必備技能吧.
C++
Android系統(tǒng)的一些性能敏感模塊及第三方庫(kù)是用C++實(shí)現(xiàn)的, 比如: Input系統(tǒng), Chromium項(xiàng)目(WebView的底層實(shí)現(xiàn)).
硬件
流暢的國(guó)際網(wǎng)絡(luò)
AOSP代碼下載需要你擁有一個(gè)流暢的國(guó)際網(wǎng)絡(luò). 如果在下載代碼這一步就失去耐心的話, 那你肯定沒有耐心去看那亂糟糟的AOSP代碼. 另外, 好程序員應(yīng)該都會(huì)需要一個(gè)流暢的Google.
一臺(tái)運(yùn)行Ubuntu 12.04的PC.
如果只是閱讀源碼而不做太多修改的話, 其實(shí)不需要太高的配置.
一臺(tái)Nexus設(shè)備
AOSP項(xiàng)目默認(rèn)只支持Nexus系列設(shè)備. 沒有也沒關(guān)系, 你依然可以讀代碼. 但如果你想在大牛之路走的更遠(yuǎn), 還是改改代碼, 然后刷機(jī)調(diào)試看看吧.
高品質(zhì)USB線
要刷機(jī)時(shí)線壞了, 沒有更窩心的事兒了.
軟件
Ubuntu 12.04
官方推薦, 沒得選.
Oracle Java 1.6
注意不要用OpenJDK. 這是個(gè)坑, 官方文檔雖然有寫, 但還是單獨(dú)提一下.
安裝:
sudo apt-get install python-software-properties
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java6-installer
sudo apt-get install oracle-java6-set-default
Eclipse
估計(jì)會(huì)有不少人吐槽, 為什么要用這個(gè)老古董. 其實(shí)原因很簡(jiǎn)單, 合適. 剛開始搞AOSP時(shí), 為了找到效率最優(yōu)的工具, 我嘗試過Eclipse, IntelliJ IDEA, Vim+Ctags, Sublime Text+Ctags. 最終結(jié)果還是Eclipse. 主要優(yōu)點(diǎn)有:
有語法分析 (快速準(zhǔn)確的類, 方法跳轉(zhuǎn)).
支持C++ (IntelliJ的C++支持做的太慢了).
嵌入了DDMS, View Hierarchy等調(diào)試工具.
為了提高效率, 花5分鐘背下常用快捷鍵非常非常值得.
調(diào)整好你的classpath, 不要導(dǎo)入無用的代碼. 因?yàn)锳OSP項(xiàng)目代碼實(shí)在是太多了. 當(dāng)你還不需要看C++代碼時(shí), 不要為項(xiàng)目添加C++支持, 建索引過程會(huì)讓你崩潰.
Intellij IDEA
開發(fā)App必備. 當(dāng)你要調(diào)試系統(tǒng)的某個(gè)功能是, 常常需要迅速寫出一個(gè)調(diào)試用App, 這個(gè)時(shí)候老舊的Eclipse就不好用了. Itellij IDEA的xml自動(dòng)補(bǔ)全非常給力.
巨人的肩膀
這個(gè)一定要先讀. 項(xiàng)目介紹, 代碼下載, 環(huán)境搭建, 刷機(jī)方法, Eclipse配置都在這里. 這是一切的基礎(chǔ).
這個(gè)其實(shí)是給App開發(fā)者看的. 但是里面也有不少關(guān)于系統(tǒng)機(jī)制的介紹, 值得細(xì)讀.
此老羅非彼老羅. 羅升陽老師的博客非常有營(yíng)養(yǎng), 基本可以作為指引你開始閱讀AOSP源碼的教程. 你可以按照博客的時(shí)間順序一篇篇挑需要的看.但這個(gè)系列的博客有些問題:
早期的博客是基于舊版本的Android;
大量的代碼流程追蹤. 讀文章時(shí)你一定要清楚你在看的東西在整個(gè)系統(tǒng)處于什么樣的位置.
鄧凡平老師也是為Android大牛, 博客同樣很有營(yíng)養(yǎng). 但是不像羅升陽老師的那么系統(tǒng). 更多的是一些技術(shù)點(diǎn)的深入探討.
Android官方Issue列表. 我在開發(fā)過程中發(fā)現(xiàn)過一些奇怪的bug, 最后發(fā)現(xiàn)這里基本都有記錄. 當(dāng)然你可以提一些新的, 有沒有人改就是另外一回事了.
一定要能流暢的使用這個(gè)工具. 大量的相關(guān)知識(shí)是沒有人系統(tǒng)的總結(jié)的, 你需要自己搞定.
其它
代碼組織
AOSP的編譯單元不是和git項(xiàng)目一一對(duì)應(yīng)的, 而是和Android.mk文件一一對(duì)應(yīng)的. 善用mmm命令進(jìn)行模塊編譯將節(jié)省你大量的時(shí)間.
Binder
這是Android最基礎(chǔ)的進(jìn)程間通訊. 在Application和System services之間大量使用. 你不僅要知道AIDL如何使用, 也要知道如何手寫B(tài)inder接口. 這對(duì)你理解Android的Application和System services如何交互有非常重要的作用. Binder如何實(shí)現(xiàn)的倒不必著急看.
HAL
除非你對(duì)硬件特別感興趣或者想去方案公司上班, 否則別花太多時(shí)間在這一層.
CyanogenMod
這是一個(gè)基于AOSP的第三方Rom. 從這個(gè)項(xiàng)目的wiki里你能學(xué)到很多AOSP官方?jīng)]有告訴你的東西. 比如如何支持Nexus以外的設(shè)備.
DIA
這是一個(gè)Linux下畫UML的工具, 能夠幫你梳理看過的代碼.
XDA
這里有最新資訊和最有趣的論壇.
想到了再補(bǔ)充.
文章名稱:閱讀android源碼,源碼閱讀app
地址分享:http://chinadenli.net/article28/dsgpdcp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、網(wǎng)站收錄、全網(wǎng)營(yíng)銷推廣、服務(wù)器托管、標(biāo)簽優(yōu)化、做網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)