1. 程式人生 > >Apple公司Darwin流式伺服器原始碼分析

Apple公司Darwin流式伺服器原始碼分析

當前,伴隨著Internet的飛速發展,計算機網路已經進入到每一個普通人的家庭。在這個過程中,一個值得我們關注的現象是:Internet中儲存和傳輸內容的構成已經發生了本質的改變,從傳統的基於文字或少量影象的主頁變為大容量、富資訊量的流式媒體資訊。一份早在1998年提交的研究報告就曾指出,流式媒體統治Internet的潮流是不可抗拒的,該報告估計到2003年,儲存在網路伺服器上的內容超過50%的將是流式媒體資訊。但今天看來,這個估計還是有些保守了。
所謂的流式媒體簡單的講就是指人們通過網路實時的收看多媒體資訊:如音訊流、視訊流等。與流式媒體對應的傳統工作方式是下載+播放模式,即使用者首先下載多媒體檔案,然後再在本地播放,這種方法的一個主要缺點是啟動延遲較大,例如一個30分鐘長的MPEG-I檔案(相當於VCD質量),即使使用1.5Mbps的速率下載,也需要半個小時才能完成,這樣一個漫長的等待時間實在是無法忍受。在窄帶網路環境中,幾乎所有基於Internet的流式媒體產品都有著類似的工作原理:首先需要開發高效的壓縮編碼技術,並通過一套完整有效的傳輸體系將其釋出到使用者的桌面上。目前在流式媒體領域,有三種佔有主導地位的產品,它們分別是Apple公司的Quick Time、Microsoft公司的Media Server以及Real公司的Real System。本文將介紹QuickTime技術及其開放原始碼的Darwin流化伺服器。

1     QuickTime技術介紹
Apple公司近日釋出了QuickTime 5及QuickTime Streaming Server 3(簡稱QTSS)。作為客戶端的QuickTime 5是用於在Internet上對高質量音訊和視訊內容進行建立、播放及提供數字流的軟體,目前QuickTime在全世界的使用量已經超過1億5千萬份。QuickTime Streaming Server 3是Apple基於標準的、開放式原始碼的流式伺服器軟體的新版本,它包括以下新功能:跳讀保護(Skip Protection),一項獲得專利的特性組合,它可以保證Internet上數字流的質量,防止中斷;全新的易於使用、基於Web的介面,使用者可以在本地或遠端進行管理,實現伺服器配置。作為Internet流媒體聯盟(ISMA)的建立者之一,Apple不斷致力於開⒎弦到綾曜嫉牟泛圖際醯ü岣呋ゲ僮饜嶽從嘔沒У氖褂錳逖椋殼癚uickTime已被國際標準組織(ISO)選為MPEG-4的基本檔案格式,可預見Apple將有更多MPEG-4 產品和技術的推出。

QuickTime正迅速成為世界領先的跨平臺多媒體技術,而且是迄今為止唯一的開放式原始碼、基於標準的數字流解決方案。ZDNet在2000年9月對於三種流式媒體伺服器的特徵比較說明了QTSS不僅僅被技術開發者關注,而且可以通過簡單的定製成為成熟強大的產品,評測結果可見表1。
表1  ZDNet對三類產品的評測結果
伺服器模組    QTSS 2.01     Media Server 7       RealServer Basic 7
作業系統支援       Windows NT, 2000; FreeBSD; Linux; Mac OS; Solaris       Windows NT, 2000       Windows NT, 2000

併發流個數    2,000      2,000      25 free/3000 pro
現場直播和廣播    Yes  Yes  Yes
線上廣告支援      Yes  Yes  Yes
PPV/流加密   No / No   Yes / Yes Yes / Yes
分配流能力    No   Yes  Yes
SMIL標準支援     Yes  No   Yes
RTSP標準支援     Yes        No   Yes
多播支援       Yes  Yes  Yes
狀態報告       Yes  Yes  Yes
伺服器日誌    Yes  Yes  Yes
防火牆和代理支援       Yes  Yes  Yes
遠端監控       Yes  Yes  Yes
客戶可以使用QuickTime Player或其他支援QuickTime的應用程式在Windows或Macintosh平臺上接收視訊流,而且QuickTime Player可以從蘋果公司的網站上下載免費使用。如果安裝了QuickTime的外掛,客戶還可以直接通過瀏覽器收看。
客戶希望點播一個節目時,QuickTime Player或外掛將向QTSS傳送請求,指明要點播的節目名。如果該節目存在,QTSS將向客戶傳送相應的視訊流。當客戶希望收看現場直播(或實時廣播)時,它首先從QTSS獲得關於當前頻道的編碼格式、地址等相關資訊,然後再接受該頻道的媒體流。
對於那些希望在Internet上實時流化視訊或音訊資訊的使用者,QTSS伺服器將是一個很好的選擇,通過它可實現多項任務,例如:
建立一個24小時線上的Internet廣播電臺;
現場實況轉播:如公司會議、體育節目等;
建立遠端學習站點:如能夠點播視訊和演講; 
       圖1是一個利用QTSS伺服器建立的現場直播場景。
2     Darwin流化伺服器介紹
Darwin Streaming Server(簡稱DSS)是QuickTime Streaming Server開放式原始碼的版本,同時支援FreeBSD、Linux、Solaris、Windows NT和Windows 2000等多個作業系統,是當前所有同類產品中支援平臺最多的一個。DSS的原始碼和相關文件可從以下站點獲得:http://www.apple.com
DSS原始碼完全採用標準C++語言寫成,程式設計風格非常優秀,每個C++類都對應著一對和類同名的.h/.cpp檔案。但是由於大量採用了面向物件的概念,如繼承、多型等等;而且原始檔和類相當多,所以不太容易講清楚。因此,讀者最好事先把程式碼完整的過濾一兩遍,再配合本文,就能看得更清楚點。
整個伺服器包括多個子系統,分別存放在獨立的工程內,如圖2所示。
其中,最為重要的是基礎功能類庫(CommonUtilitiesLib)和流化伺服器(StreamingServer)兩個工程,前者是整個系統的通用程式碼工具箱,包括了執行緒管理、資料結構、網路和文字分析等多個功能模組。DSS和其他相關的工具使用基礎功能類庫工程中定義的功能類實現以下三個目標:
(1)抽象出系統中相同或類似的功能,用於降低程式碼的冗餘度;
(2)封裝基本功能,簡化高層編碼的複雜度;
(3)隔離開作業系統平臺相關的程式碼。
而流化伺服器工程中包含了DSS對多個國際標準的實現,是整個伺服器的主工程。在本文中,我們將重點分析這兩個工程中的核心程式碼和模組。另外,我們還將簡單介紹利用DSS提供的開發介面(Module)擴充套件和定製伺服器的方法。
DSS實現了四種IETF制定的國際標準,分別是:實時流傳輸協議RTSP(Real-time Streaming Protocol, RFC 2326)、實時傳輸協議(RTP Real-time Transfer Protocol,RFC 1889)、實時傳輸控制協議RTCP(Real-time Transport Control Protocol,RFC 1889)、會話描述協議SDP(Session Description Protocol,RFC 2327)。這四個標準是開發所有流式媒體產品都必須掌握的,因此在對相關程式碼進行分析和二次開發之前,希望讀者瞭解上述四種協議的基本思想,上述協議樣本可從以下網站獲得:http://www.ietf.org
3     基礎功能類庫(Common Utilities)
3.1   OS類
Darwin Streaming Server支援包括Windows,Linux以及Solaris在內的多種作業系統平臺。我們知道,Windows和Unix(或Unix-like)作業系統之間無論從核心還是程式設計介面上都有著本質的區別,即使是Linux和Solaris,在程式設計介面上也大為不同。為此,DSS開發了多個用於處理時間、臨界區、訊號量、事件、互斥量和執行緒等作業系統相關的類,這些類為上層提供了統一的使用介面,但在內部卻需要針對不同的作業系統採用不同的方法實現。表2羅列出了DSS中的主要OS類和資料結構。
表2  DSS中的主要OS類和資料結構
類(資料結構)名       主要功能
OS   平臺相關的功能類,如記憶體分配、時間等
OSCond  狀態變數的基本功能和操作
OSMutex 互斥量的基本功能和操作
OSThread       執行緒類
OSFileSource  簡單檔案類
OSQueue 佇列類
OSHashTable  雜湊表類
OSHeap   堆類
OSRef     參考引用類
3.1.1       OSMutex/OSCond Class
在有多個執行緒併發執行的環境中,能同步不同執行緒的活動是很重要的,DSS開發了OSMutex和OSCond兩個類用以封裝不同作業系統對執行緒同步支援的差異。
我們首先分析OSMutex類,這個類定義了廣義互斥量的基本操作,類定義如下:
class OSMutex
{
1     public:
2            OSMutex();         //建構函式
3            ~OSMutex();              //解構函式
4            inline void Lock();              //加鎖
5            inline void Unlock();    //解鎖
6            inline Bool16 TryLock();     //非同步鎖,無論是否成功立即返回
7     private:
8     #ifdef __Win32__
9            CRITICAL_SECTION fMutex;  //臨界區
10           DWORD        fHolder;                     //擁有臨界區的執行緒id
11           UInt32           fHolderCount;             //進入臨界區執行緒數
              //其他略…
}
在Windows平臺上,OSMutex類是通過臨界區(CRITICAL_SECTION)來實現的,第10行定義了臨界區變數fMutex。類例項化時建構函式呼叫InitializeCriticalSection(&fMutex)初始化臨界區變數,對應的在解構函式中呼叫DeleteCriticalSection(&fMutex)清除。
Lock()函式用於對互斥量加鎖,它呼叫私有方法RecursiveLock實現:
void        OSMutex::RecursiveLock()
{
       // 當前執行緒已經擁有互斥量,只需增加引用計數
1     if (OSThread::GetCurrentThreadID() == fHolder)
2     {
3            fHolderCount++;  //增加引用計數
4            return;
5     }
6     #ifdef __Win32__
7            ::EnterCriticalSection(&fMutex); //申請進入臨界區
8     #else
9            (void)pthread_mutex_lock(&fMutex);
10    #endif
11    Assert(fHolder == 0);
12    fHolder = OSThread::GetCurrentThreadID();    //更新臨界區擁有者標誌
13    fHolderCount++;  
14    Assert(fHolderCount == 1);
}
       第1行檢測如果當前執行緒已經擁有互斥量,就只需將內部計數fHolderCount加1,以便紀錄正在使用互斥量的方法數。如果當前執行緒還沒有得到互斥量,第7行呼叫EnterCriticalSection()函式申請進入臨界區;如果當前已經有其他執行緒進入臨界區,該函式就會阻塞,使得當前執行緒進入睡眠狀態,直到佔用臨界區的執行緒呼叫LeaveCriticalSection(&fMutex)離開臨界區後才可能被喚醒。一旦執行緒進入臨界區後,它將首先更新臨界區持有者標誌(第12行),同時將臨界區引用計數加1。
       注意到另外一個函式TryLock(),該函式也是用於為互斥量加鎖,但與Lock()不同的是,TryLock()函式為使用者提供了非同步呼叫互斥量的功能,這是因為它呼叫::TryEnterCriticalSection(&fMutex)函式申請進入緩衝區:如果臨界區沒有被任何執行緒擁有,該函式將臨界區的訪問區給予呼叫的執行緒,並返回TRUE,否則它將立刻返回FALSE。TryEnterCriticalSection()和EnterCriticalSection()函式的本質區別在於前者從不掛起執行緒。
接著分析OSCond類,該類定義了狀態變數(Condition Variable)的基本操作,類定義如下:
class OSCond 
{
1     public:
2            OSCond();   //建構函式
3            ~OSCond(); //解構函式

4            inline void      Signal();       //傳信函式
5            inline void      Wait(OSMutex* inMutex, SInt32 inTimeoutInMilSecs = 0);   
//等待傳信函式
6            inline void       Broadcast(); //廣播傳信函式
7     private:
8     #ifdef __Win32__
9            HANDLE                     fCondition;   //事件控制代碼
10           UInt32                         fWaitCount;  //等待傳信使用者數
//其他略…
       }
       雖然同是用於執行緒同步,但OSCond類與OSMutex大不相同,後者用來控制對關鍵資料的訪問,而前者則通過發訊號表示某一操作已經完成。在Windows平臺中,OSCond是通過事件(event)來實現的;建構函式呼叫CreateEvent()函式初始化事件控制代碼fCondition,而解構函式則呼叫CloseHandle()關閉控制代碼。
       OSCond的使用流程是這樣的:執行緒呼叫Wait(OSMutex* inMutex, SInt32 inTimeoutInMilSecs = 0)函式等待某個事件的發生,其中inTimeoutInMilSecs是最長等待時間,0代表無限長。Wait()函式內部呼叫了WaitForSingleObject (fCondition, theTimeout)函式,該函式告訴系統執行緒在等待由事件控制代碼fCondition標識的核心物件變為有訊號,引數theTimeout告訴系統執行緒最長願意等待多少毫秒。如果指定的核心物件在規定時間內沒有變為有訊號,系統就會喚醒該執行緒,讓它繼續執行。而函式Signal()正是用來使事件控制代碼fCondition有訊號的。Signal()函式內部實現很簡單,只是簡單呼叫SetEvent函式將事件控制代碼設定為有訊號狀態。
       使用OSCond的過程中存在一種需求,就是希望通知所有正在等待的使用者事件已經完成,而Signal()函式每次只能通知一個使用者,因此又開發了另外一個廣播傳信函式如下:
inline void OSCond::Broadcast()
{     //提示:本函式相當迴圈呼叫Signal()函式
1     #ifdef __Win32__
2     UInt32 waitCount = fWaitCount;       //等待傳信的使用者數
3     for (UInt32 x = 0; x ; x++)        //迴圈為每個使用者傳信
4     {
5            BOOL theErr = ::SetEvent(fCondition);             //設定事件控制代碼為有訊號狀態
6            Assert(theErr == TRUE);
7     }
//此處略…
       }
       Broadcast首先統計所有等待傳信的使用者數(第2行),然後用一個迴圈為每個使用者傳信(第3~7)行。這種程式設計方法雖然不是很優雅(elegant),但是由於Windows平臺上不支援廣播傳信功能(Linux和Solaris均支援),也只好如此。
3.1.2       OSThread Class
OSThread是DSS中最重要的類之一,它封裝並且定義了使用執行緒的方式,因此需要重點討論。OSThread類的定義如下:
class OSThread
{
1     public:
       // 必須在使用其他OSThread函式前呼叫該初始化函式
2     static void              Initialize();

3     OSThread(); //建構函式
4     virtual                                 ~OSThread();      //解構函式

       //子類繼承該純虛擬函式完成自己的工作
5     virtual     void                     Entry() = 0;  

6     void                     Start(); //啟動執行緒
7     void                     Join();  //等待執行緒執行完成後刪除
8     void                     Detach();     //使執行緒處於fDetached狀態
9     static void              ThreadYield();     //Windows平臺不用
10    static void              Sleep(UInt32 inMsec); //讓執行緒睡眠
       …
11    private:
       //標識執行緒的狀態
12    Bool16 fStopRequested:1;
13    Bool16 fRunning:1;
14    Bool16 fCancelThrown:1;
15    Bool16 fDetached:1;
16    Bool16 fJoined:1;
       …
17    static void              CallEntry(OSThread* thread);//呼叫子類過載的虛擬函式
18    #ifdef __Win32__
//使用_beginghreadex建立執行緒時的標準入口函式
19    static unsigned int WINAPI _Entry(LPVOID inThread); 
20    #else
21    static void*    _Entry(void* inThread); //unix下的入口函式
22    #endif
}
OSThread封裝了執行緒的基本功能,一個OSThread的例項代表一個執行緒。使用者通過繼承OSThread,並且過載其中的純虛擬函式Entry(第5行),從而將自己的任務交給該執行緒執行。OSThread內部執行機制比較複雜,為此我們用圖3所示的流程來描述其執行過程。
      另外,OSThread對於執行緒的狀態定義了一套完整的控制方法。當用戶呼叫start()函式後,按照上圖,最終將呼叫CallEntry()函式,而該函式在呼叫Entry()之前將執行緒設定為執行狀態(thread->fRunning = true),當Entry()函式執行完後再設為非執行狀態;在執行過程中,使用者可以通過StopAndWaitForThread()、join()、Detach()以及ThrowStopRequest()等函式改變執行緒其他狀態變數。
3.1.3       OSHashTable/OSQueue/OSHeap/OSRef Class
DSS定義了幾個通用的較為複雜的資料結構,它們都以類的方式封裝。這些資料結構不但貫穿於DSS的所有原始碼,而且由於其封裝的十分好,讀者可以在看懂原始碼的基礎上很容易的將它們從DSS的工程中抽取出來,構建自己的基礎類庫,為將來的開發工作打下良好的基礎。另外,對這些基礎資料結構原始碼的研究將提高我們對於面向物件技術的掌握和領會。
       最主要的資料結構有四種:雜湊表(OSHashTable)、佇列(OSQueue)、堆(OSHeap)和物件引用表(OSRef)。前三種是我們在程式設計中大量使用的資料結構,而物件引用表則是類似於COM/DCOM元件程式設計中IUNKOWN介面功能的資料結構,它首先為每個物件建立了一個字串形式的ID,以便於通過這個ID找到物件(類似於QueryInterface);另外OSRef類還為每個物件例項建立了引用計數,只有一個物件不再被任何人引用,才可能被釋放(類似於AddRef和Release)。
       鑑於這幾個類在結構上有相似之處,下面我們將分析OSHashTable的原始碼,以便能夠幫助讀者更好的理解其他幾個類。OSHashTable的程式碼如下:
       template
       class OSHashTable {
       /*提示:OSHashTable被設計成為一個類模版,兩個輸入引數分別為:class T:實際的物件類;class K:用於為class T計算雜湊表鍵值的功能類。*/
1     public:
2     OSHashTable( UInt32 size )   //建構函式,入參是雜湊表中物件的最大個數
3     {
4            fHashTable = new ( T*[size] );   //申請分配size個雜湊物件class T的空間
5            Assert( fHashTable );
6            memset( fHashTable, 0, sizeof(T*) * size );      //初始化
7            fSize = size;
/*下面的程式碼決定用哪種方式為雜湊表的鍵值計算索引;
如果雜湊表的大小不是2的冪,只好採用對fSize求餘的方法;
否則可以直接用掩碼的方式,這種方式相對速度更快*/
8            fMask = fSize - 1;
9            if ((fMask & fSize) != 0)             //fSize不是2的冪
10                  fMask = 0;
11           fNumEntries = 0; //當前物件數
12    }
13    ~OSHashTable()     //解構函式
14    {
15           delete [] fHashTable;   //釋放空間
16    }
//下面介紹向雜湊表中新增一個class T物件的原始碼
17    void Add( T* entry ) {
18           Assert( entry->fNextHashEntry == NULL );
                     /*利用功能類class K,計算class T物件的雜湊鍵值,其計算方法由使用者在class K中定義*/
       19           K key( entry );     
20           UInt32 theIndex = ComputeIndex( key.GetHashKey() );//利用鍵值計算索引
21           entry->fNextHashEntry = fHashTable[ theIndex ]; //在新加物件中儲存索引值
22           fHashTable[ theIndex ] = entry; //將該物件插入到索引指定的位置
23           fNumEntries++;   /
24    }
//下面介紹從雜湊表中刪除一個class T物件的原始碼
25    void Remove( T* entry )
26    {
//首先從雜湊表中找到待刪除的物件
//1、計算雜湊鍵值和其對應的物件索引
27           key( entry );        
28           UInt32 theIndex = ComputeIndex( key.GetHashKey() );   
29           T* elem = fHashTable[ theIndex ];
30           T* last = NULL;
/*2、通過物件索引查詢物件,如果不是要找的物件,接著找下一個,直到找到為止。這是因為,存放的時候就是按照這種模式計算索引的。*/
31           while (elem && elem != entry) { 

相關推薦

Apple公司Darwin伺服器原始碼分析

當前,伴隨著Internet的飛速發展,計算機網路已經進入到每一個普通人的家庭。在這個過程中,一個值得我們關注的現象是:Internet中儲存和傳輸內容的構成已經發生了本質的改變,從傳統的基於文字或少量影象的主頁變為大容量、富資訊量的流式媒體資訊。一份早在1998年提交的

SRS(simple-rtmp-server)媒體伺服器原始碼分析--系統啟動

SRS(simple-rtmp-server)流媒體伺服器原始碼分析--系統啟動 一、前言        小卒最近看SRS原始碼,隨手寫下部落格,其一為了整理思路,其二也是為日後翻看方便。如果不足之處,請指教!

輕量級日誌計算分析plog+(zabbix+grafana)

python 流日誌分析 plog plog是一個用python寫的流式計算分析框架,適用於輕量級流式數據的分析場景,大數據場景下大家自然想到使用spark等方案。 拿當前的業務場景看,需要對機器上nginx的流日誌進行狀態碼、響應時間、QPS的實時分析,通過zabbix展現

Spring 宣告事務原始碼分析

Spring 的宣告式事務實現方式主要有2種,一種為通過使用Spring的< tx:advice >定義事務通知與AOP相關配置實現,另為一種通過@Transactional實現事務管理實現,個人認為本質上其實都一樣,就是用定義的註解或者配置資訊將目

三分鐘了解實時大數據分析

最大 想要 工作流 曲線 產生 blog 加速 當前 統計分析 三分鐘了解實時流式大數據分析 大家好,今天為大家介紹華為雲實時流計算服務CS,希望通過本次分享,大家能對華為雲實時流計算服務的服務能力和業務場景有所了解。我們先了解一下實時流計算背景。下面列舉的是流數據普遍產生

計算】Twitter Storm原始碼分析之Nimbus/Supervisor本地目錄結構

  我們知道,storm叢集裡面工作機器分為兩種一種是nimbus, 一種是supervisor, 他們通過zookeeper來進行互動,nimbus通過zookeeper來發布一些指令,supervisor去讀zookeeper來執行這些指令,具體nimbus和supe

計算】Twitter Storm原始碼分析之ZooKeeper中的目錄結構

作者: xumingming | 可以轉載, 但必須以超連結形式標明文章原始出處和作者資訊及版權宣告   我們知道Twitter Storm的所有的狀態資訊都是儲存在Zookeeper裡面,nimbus通過在zookeeper上面寫狀態資訊來分配任務,supervisor

Flume NG原始碼分析(三)使用Event介面表示資料

Flume NG有4個主要的元件: Event表示在Flume各個Agent之間傳遞的資料流 Source表示從外部源接收Event資料流,然後傳遞給Channel Channel表示對從Source傳遞的Event資料流的臨時儲存 Sink表示從Channel中接收儲存的Event

Spark ML線上學習模型初步構建分析-Spark商業ML實戰

本套技術專欄是作者(秦凱新)平時工作的總結和昇華,通過從真實商業環境抽取案例進行總結和分享,並給出商業應用的調優建議和叢集環境容量規劃等內容,請持續關注本套部落格。版權宣告:禁止轉載,歡迎學習。QQ郵箱地址:[email protected],如有任何商業交流,可隨時聯絡。

Netty原始碼分析:1.4伺服器啟動流程

第一章節是主要是伺服器啟動的程式碼分析。章節目錄有: |———1.1初始化NioEventLoopGroup |———1.2初始化NioEventLoop |———1.3初始化NioServerSocketChannel |———1.4伺服器啟動流程 為什麼先從初始化開

bootstrap_柵格系統_響應工具_原始碼分析

-----------------------------------------------------------------------------margin 為負 ​使盒子重疊 ​等高 等高佈局 雙飛翼佈局 ​盒子往一邊 推 或者 拉 ---------------------

計算形態下的大數據分析

信息 電子商務 新特性 少量數據 這一 mapreduce 適用於 right 日常 1 介 紹 1.1 流式計算介紹 流式大數據計算主要有以下特征: 1)實時性。流式大數據不僅是實時產生的,也是要求實時給出反饋結果。系統要有快速響應能力,在短時間內體現出數據的價值,

計算形態下的大資料分析

1 介 紹 1.1 流式計算介紹 流式大資料計算主要有以下特徵: 1)實時性。流式大資料不僅是實時產生的,也是要求實時給出反饋結果。系統要有快速響應能力,在短時間內體現出資料的價值,超過有效時間後資料的價值就會迅速降低。 2)突發性。資料的流入速率和順序並不確定,甚至會有較大的差異。這要求系統要有較高

EasyDarwin媒體伺服器啟動函式StartServer程式碼分析

在前面部落格中分析EasyDarwin字典類QTSS_Dictionary時瞭解到相關QTSS_DictionaryMap,QTSSAttrInfoDict等屬性內容,其初始化分配記憶體是在伺服器啟動的時候。 正好回過來分析伺服器的初始化啟動函式QTSS_ServerSta

vlc原始碼分析(五) 媒體的音視訊同步

轉載地址:https://www.cnblogs.com/jiayayao/p/6890882.html vlc播放流媒體時實現音視訊同步,簡單來說就是傳送方傳送的RTP包帶有時間戳,接收方根據此時間戳不斷校正本地時鐘,播放音視訊時根據本地時鐘進行同步播放。首先了解兩個概念

Vue provide/inject 部分原始碼分析 實現響應資料更新

下面是我自己曾經遇到 一個問題,直接以自己QA的形式來寫吧 官網給出例項,說本身是不支援資料響應式的, 但是可以傳入響應式資料,那麼provide,inject就可以實現響應式。我這裡理解應該沒錯哈,有不對的地方請指出。 我自己寫的demo,做了如下更改 parent 頁面: export def

Android 彈出佈局之Dialog原始碼分析

文章目錄 關於 Dialog的基本使用,可以看之前寫的一片文章 Android 彈出式佈局之Dialog的使用 官方不是不建議直接使用Dialog的,而我們工作中一般是使用AlertDialog或者DialogFragment實現彈框功能

Open vSwitch(OvS)原始碼分析之工作流程(flow表查詢)

前面分析了Open vSwitch幾部分原始碼,對於Open vSwitch也有了個大概的理解,今天要分析的程式碼將是整個Open vSwitch的重中之重。整個Open vSwitch的核心程式碼在datapath檔案中;而datapath檔案中的核心程式碼又在ovs_dp_process_re

android佈局、待辦事項應用、貝塞爾曲線、MVP+Rxjava+Retrofit、藝術圖片應用等原始碼

Android精選原始碼 android模仿淘寶首頁效果原始碼 一款藝術圖片應用,採用T-MVVM打造 Android MVP + RxJava + Retrofit專案 android流式佈局實現熱門標籤效果 android仿淘寶客戶端商品詳

Java BAT大型公司面試必考技能視訊教程之HashMap原始碼分析與實現

視訊通過以下四個方面介紹了HASHMAP的內容 一、 什麼是HashMap Hash雜湊將一個任意的長度通過某種演算法(Hash函式演算法)轉換成一個固定的值。 MAP:地圖 x,y 儲存 總結:通過HASH出來的值,然後通過值定位到這個MAP,然後value儲存到這個M