流式播放的資料來源來自ISource 介面對象,可以來自於網路,記憶體或者檔案。流式媒體有兩種內容:一種是格式化的媒體,該媒體包含了頭,編碼規範和未經處理資料的起始位置,例如.mp3 或者 .wav 的檔案;另一種是未經處理資料,其編解碼方法由使用者單獨提供。流式播放需要一個ISource的具體實現,由應用建立 ISource 介面, 並保持在IMedia 介面的整個生命週期內有效。下面是一個簡單的例子,對一個wav檔案實現流式播放。
static void MyApp_SetupSource(MyApp * pme){
AEEMediaDataEx md;
IFileMgr *pfm; ISourceUtil *psu;
// 步驟#1: 建立IMedia PCM 對象,處於 IDLE 狀態
ISHELL_CreateInstance(pme->e.m_pIShell,AEECLSID_MEDIAPCM,(void**)&pme->m_pIMedia);
// 步驟#2: 建立具體ISource對象
ISHELL_CreateInstance(pme->e.m_pIShell, AEECLSID_FILEMGR, (void **)&pfm))
pme->m_pFile = IFILEMGR_OpenFile(pfm, "sample.wav", _OFM_READ);
IFILEMGR_Release(pfm);
ISHELL_CreateInstance(pme->e.m_pIShell, AEECLSID_SOURCEUTIL, (void **)&psu))
ISOURCEUTIL_SourceFromAStream(psu, (IAStream*)pme->m_pFile, &pme->m_pISource);
ISOURCEUTIL_Release(psu);
// 步驟 #3: 以ISource 初始化AEEMediaDataEx
md.clsData = MMD_ISOURCE;
md.pData = (void *)pme->m_pISource;
md.dwSize = 0;
md.dwStructSize = sizeof(md); // AEEMediaDataEx 資料結構的大小
md.dwCaps = 0;.
md.bRaw = FALSE; // 是否是未經處理資料? FALSE代表不是
md.dwBufferSize = 0; // 內部的緩衝大小, 0 代表使用預設值.
md.pSpec = NULL; // 只對未經處理資料格式有限
md.dwSpecSize = 0; //只對未經處理資料格式有限
// 步驟#4: 設定媒體資料,IMedia 對象處於 READY狀態
IMEDIA_SetMediaDataEx(pme->m_pIMedia, &md, 1);
}
對於未經處理資料的流式播放,由於沒有媒體播放的終止符,需要在播放中準確的調用IMEDIA_Stop()。在AEEMediaDataEx 資料結構中,需要將bRaw 設為TRUE,將pSpec 設為指定的編解碼方法。
流媒體播放就是資料來源來自網路的流式播放,採用串流的方式,不需要使用者將多媒體資料全部下載,而是採取邊下載邊播放的方式, 僅僅將最初的一些資料先下載到本地緩衝區,只要資料積累到可以連續播放的要求後就開始播放,後面的資料會根據請求不斷進入本地緩衝區,從而使播放片斷形成一個完整的資料流,如最常用的網路電視PPLIVE 就是採用這種技術。由於無線網路的限制,移動流媒體一般採用單播的播放方式,每個接收端與流媒體伺服器建立起一對一的串連關係,每個使用者單獨向伺服器發出資料請求,並由伺服器向該使用者發送單獨的資料拷貝。
由於目前的API不支援對H. 264 或者MPEG- 4/ H. 263 格式的介面,因此需要移植相應的解碼器到BREW平台上。移植主要使用BREW的介面來替代解碼器中的C 語言函數,並用整數計算或定點計算代替浮點運算,尤其需要解決的是H.264 和Xvid 參考來源程式所使用的棧空間超過BREW手機的限制問題(如將數組改為動態分配記憶體,將全域的數組改為函數域中),最終將視訊框架解碼為位元影像顯示在手機螢幕上。手機播放視頻流的一個重要問題是解決音視頻的同步。伺服器端傳送的資料包中包含了音頻和視頻的播放期間,這樣可以採取以音頻播放時間為基準,校正視頻播放. 假設ha 是當前音訊播放時間, hv是當前視訊框架的播放時間. 如果hv < ha ,表示視頻滯後於音頻,則丟棄此幀,立刻轉向下一幀的解碼;如果hv > ha ,表示視頻超前於音頻,則此幀暫時不顯示,等待音頻播放hv - ha 的時間後再顯示.