[英]Use MediaCodec for H264 streaming
我目前正在嘗試將Android用作Skype端點。 在這個階段,我需要將視頻編碼為H.264(因為它是Skype支持的唯一格式)並將其封裝在RTP中以使流式傳輸工作。
顯然, MediaRecorder
由於各種原因並不適合這種情況。 一個是因為它在完成后添加了MP4或3GP標頭。 另一個原因是為了將延遲降至最低,硬件加速可能會派上用場。 這就是為什么我想利用最近對該框架的低級添加,即MediaCodec
, MediaExtractor
等。
目前,我計划如下工作。 相機將其視頻寫入緩沖區。 MediaCodec使用H264對視頻進行編碼,並將結果寫入另一個緩沖區。 該緩沖區由RTP封裝器讀取,該封裝器將流數據發送到服務器。 這是我的第一個問題:這個計划聽起來對你有用嗎?
現在我已經陷入第一步了。 由於互聯網上關於使用相機的所有文檔都使用了MediaRecorder
,因此在編碼之前我找不到將原始數據存儲到緩沖區的方法。 addCallbackBuffer適合這個嗎? 任何人都有一個例子的鏈接?
接下來,我找不到很多關於MediaCodec的文檔(因為它相當新)。 有固定教程的人嗎?
最后:關於RTP庫的任何建議?
非常感謝提前!
UPDATE
我終於能夠從h264幀創建適當的RTP包。 這是你必須記住的(實際上很簡單):
編碼器確實為每個幀創建NAL標頭。 但它將每個幀作為h264 字節流返回。 這意味着每個幀以三個0字節和一個1字節開始。 您所要做的就是刪除那些開始前綴,並將幀放入RTP數據包(或使用FU-As將其拆分)。
現在回答你的問題:
在編碼之前,我找不到將原始數據存儲到緩沖區的方法。 addCallbackBuffer適合這個嗎?
您應該使用camera.setPreviewCallback(...),並將每個幀添加到編碼器。
我找不到很多關於MediaCodec的文檔(因為它相當新)。 有固定教程的人嗎?
這應該是關於MediaCodec如何工作的一個很好的介紹。 http://dpsm.wordpress.com/2012/07/28/android-mediacodec-decoded/
最后:關於RTP庫的任何建議?
我正在使用jlibrtp來完成工作。
我對MediaCodec或MediaExtractor一無所知,但我對MediaRecorder非常熟悉,並成功實現了基於SpyDroid的RTSP服務器,該服務器捕獲MediaRecorder的H264 / AMRNB輸出。 基本思想是代碼創建一個本地套接字對,並使用MediaRecorder的setOutputFile將輸出寫入該對中的一個套接字。 然后,程序從另一個套接字讀取視頻或音頻流,將其解析為數據包,然后將每個數據包包裝成一個或多個通過UDP發送的RTP數據包。
MediaRecorder確實在它完成后添加了MOOV標頭,但如果你以RTP格式提供H264視頻,這不是問題。 基本上,視頻流的開頭有一個“mdat”標題。 它有4個字節作為標題的長度,后跟4個字節“mdat”。 讀取長度以找出標頭的長度,驗證它是mdat標頭,然后跳過其余的標頭數據。 從那里開始,您將獲得一個NAL單元流,其單位長度為4個字節。 小型NAL單元可以在單個RTP數據包中發送,較大的單元可以分解為FU數據包。 對於RTSP,您還需要提供描述流的SDP標頭。 SpyDroid通過將非常短的電影寫入文件來計算SDP標頭中的信息,然后讀取此文件以從末尾提取MOOV標頭。 我的應用程序總是使用相同的大小,格式和比特率,所以我只提供一個靜態字符串:
public static final String SDP_STRING =
"m=video 5006 RTP/AVP 96\n"
+ "b=RR:0\n"
+ "a=rtpmap:96 H264/90000\n"
+ "a=fmtp:96 packetization-mode=1;profile-level-id=428028;sprop-parameter-sets=Z0KAKJWgKA9E,aM48gA==;\n"
+ "a=control:trackID=0\n"
+ "m=audio 5004 RTP/AVP 96\n"
+ "b=AS:128\n"
+ "b=RR:0\n"
+ "a=rtpmap:96 AMR/8000\n"
+ "a=fmtp:96 octet-align=1;\n"
+ "a=control:trackID=1\n";
這是我的標題為640x480x10fps,H264視頻,具有8000/16/1 AMRNB音頻。
有一點我可以警告你:如果你正在使用MediaRecorder,你的預覽回調永遠不會被調用。 這僅適用於相機模式,而不適用於錄制視頻時。 在錄制視頻時,我無法找到以非壓縮格式訪問預覽圖像的任何方法。
我強烈建議查看SpyDroid的代碼。 這需要一些挖掘,但我打賭你想要的就是在那里。
您的計划絕對可行。 您可以注冊一個Camera.PreviewCallback,它將獲取圖片數據並將其放入MediaCodec。 您讀取輸出並將其作為RTP發送。 一般情況下這很容易,但是在不同的設備上存在各種缺陷,如無證的顏色空間和不同的MediaCodec行為,但它絕對是可能的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.