Android短影片系統硬編碼—實現音影片編碼(二)
影片編碼例項
短影片系統影片的編碼和上篇文章的短影片系統音訊的編碼也大同小異。攝像頭的資料回撥時間並不是確定的,就算你設定了攝像頭FPS
範圍為
30-30
幀,它也不會每秒就一定給你
30
幀資料。
Android
攝像頭的資料回撥,受光線的影響非常嚴重,這是由
HAL
層的
3A
演算法決定的,你可以將自動曝光補償、自動白平光等等給關掉,這樣你才有可能得到穩定的幀率。
而我們錄製並編碼影片的時候,肯定是希望得到一個固定幀率的短影片系統影片。所以在短影片系統影片錄製並進行編碼的過程中,需要自己想些法子,讓幀率固定下來。最簡單也是最有效的做法就是,按照固定時間編碼,如果沒有新的攝像頭資料回撥來就用上一幀的資料。
參考程式碼如下:
private String mime="video/avc"; // 編碼的 MIME
private int rate=256000; // 波特率, 256kb
private int frameRate=24; // 幀率, 24 幀
private int frameInterval=1; // 關鍵幀一秒一關鍵幀
// 和音訊編碼一樣,設定編碼格式,獲取編碼器例項
MediaFormat format=MediaFormat.createVideoFormat(mime,width,height);
format.setInteger(MediaFormat.KEY_BIT_RATE,rate);
format.setInteger(MediaFormat.KEY_FRAME_RATE,frameRate);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,frameInterval);
// 這裡需要注意,為了簡單這裡是寫了個固定的 ColorFormat
// 實際上,並不是所有的手機都支援 COLOR_FormatYUV420Planar 顏色空間
// 所以正確的做法應該是,獲取當前裝置支援的顏色空間,並從中選取
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
mEnc=MediaCodec.createEncoderByType(mime);
mEnc.configure(format,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE);
// 同樣,準備好了後,開始編碼器
mEnc.start();
// 編碼器正確開始後,在子執行緒中迴圈編碼,固定位元速率的話,就是一個迴圈加上執行緒休眠的時間固定
// 流程和音訊編碼一樣,取出空盒子,往空盒子裡面加原料,放回盒子到原處 ,
// 盒子中原料被加工,取出盒子,從盒子裡面取出成品,放回盒子到原處
int index=mEnc.dequeueInputBuffer(-1);
if(index>=0){
if(hasNewData){
if(yuv==null){
yuv=new byte[width*height*3/2];
}
// 把傳入的 rgba 資料轉成 yuv 的資料,轉換在網上也是一大堆,不夠下面還是一起貼上吧
rgbaToYuv(data,width,height,yuv);
}
ByteBuffer buffer=getInputBuffer(index);
buffer.clear();
buffer.put(yuv);
// 把盒子和原料一起放回到傳送帶上原來的位置
mEnc.queueInputBuffer(index,0,yuv.length,timeStep,0);
}
MediaCodec.BufferInfo mInfo=new MediaCodec.BufferInfo();
// 嘗試取出加工好的資料,和音訊編碼一樣, do while 和 while 都行,覺得怎麼好怎麼寫
int outIndex=mEnc.dequeueOutputBuffer(mInfo,0);
while (outIndex>=0){
ByteBuffer outBuf=getOutputBuffer(outIndex);
byte[] temp=new byte[mInfo.size];
outBuf.get(temp);
if(mInfo.flags==MediaCodec.BUFFER_FLAG_CODEC_CONFIG){
// 把編碼資訊儲存下來,關鍵幀上要用
mHeadInfo=new byte[temp.length];
mHeadInfo=temp;
}else if(mInfo.flags%8==MediaCodec.BUFFER_FLAG_KEY_FRAME){
// 關鍵幀比普通幀是多了個幀頭的,儲存了編碼的資訊
byte[] keyframe = new byte[temp.length + mHeadInfo.length];
System.arraycopy(mHeadInfo, 0, keyframe, 0, mHeadInfo.length);
System.arraycopy(temp, 0, keyframe, mHeadInfo.length, temp.length);
Log.e(TAG,"other->"+mInfo.flags);
// 寫入檔案
fos.write(keyframe,0,keyframe.length);
}else if(mInfo.flags==MediaCodec.BUFFER_FLAG_END_OF_STREAM){
// 結束的時候應該傳送結束訊號,在這裡處理
}else{
// 寫入檔案
fos.write(temp,0,temp.length);
}
mEnc.releaseOutputBuffer(outIndex,false);
outIndex=mEnc.dequeueOutputBuffer(mInfo,0);
}
// 資料的來源, GL 處理好後, readpix 出來的 RGBA 資料喂進來,
public void feedData(final byte[] data, final long timeStep){
hasNewData=true;
nowFeedData=data;
nowTimeStep=timeStep;
}
//RGBA 轉 YUV 的方法,這是最簡單粗暴的方式,在使用的時候,一般不會選擇在 Java 層,用這種方式做轉換
private void rgbaToYuv(byte[] rgba,int width,int height,byte[] yuv){
final int frameSize = width * height;
int yIndex = 0;
int uIndex = frameSize;
int vIndex = frameSize + frameSize/4;
int R, G, B, Y, U, V;
int index = 0;
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
index = j * width + i;
if(rgba[index*4]>127||rgba[index*4]<-128){
Log.e("color","-->"+rgba[index*4]);
}
R = rgba[index*4]&0xFF;
G = rgba[index*4+1]&0xFF;
B = rgba[index*4+2]&0xFF;
Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
yuv[yIndex++] = (byte) ((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
if (j % 2 == 0 && index % 2 == 0) {
yuv[uIndex++] = (byte) ((U < 0) ? 0 : ((U > 255) ? 255 : U));
yuv[vIndex++] = (byte) ((V < 0) ? 0 : ((V > 255) ? 255 : V));
}
}
}
}
對於短影片系統其他格式的音訊影片編解碼也大同小異了,只要MediaCodec
支援就好。
————————————————
宣告:宣告:本文由雲豹科技轉發自CSDN
【
湖廣午王
】部落格,如有侵權請聯絡作者刪除
原文連結:https://blog.csdn.net/junzia/article/details/54018671
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70002045/viewspace-2779320/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Android短影片系統硬編碼—實現音影片編碼(三)Android
- 短影片電商系統,編寫延遲訊息實現程式碼
- Android 音視訊錄製硬編碼實現Android
- 短影片程式原始碼,如何實現短影片的熱門頁面原始碼
- Android音訊實時傳輸與播放(三):AMR硬編碼與硬解碼Android音訊
- 秘樂短影片原始碼系統開發搭建原始碼
- C++實現RTMP協議傳送H.264編碼及AAC編碼的直播軟體開發音影片C++協議
- 短影片APP系統原始碼,定製開發功能APP原始碼
- 六點概括短影片系統原始碼的實用功能機制原始碼
- 陪玩系統原始碼實現音訊編碼的相關步驟原始碼音訊
- Media Encoder 2022 for Mac(AME音影片編碼工具)Mac
- 夢幻自主研發android安卓和IOS蘋果系統短影片原始碼Android安卓iOS蘋果原始碼
- Python音影片編輯庫:moviepyPython
- 阿里雲影片雲正式支援AV1編碼格式 為影片編碼服務降本提效阿里
- 短影片系統原始碼——“潮流”標籤之下蘊藏哪些實用功能原始碼
- 影片轉碼編輯工具Compressor for MacMac
- 一文搞懂影片編解碼原理
- iOS/Android 影片編輯SDKiOSAndroid
- 短影片商城系統,session和cookie實現登入SessionCookie
- 影片直播系統原始碼,非同步處理實現程式碼分析原始碼非同步
- 短影片整套原始碼,如何實現冪等性校驗?原始碼
- Android 音視訊開發 視訊編碼,音訊編碼格式Android音訊
- 短影片社交平臺開發,短影片直播帶貨,成品原始碼二次開發原始碼
- C++語言的音影片開發應用模式(採集、編碼、解碼...)C++模式
- QLab Pro for Mac(現場表演類實時音影片編輯工具)Mac
- 移動端短影片SDK,企業級影片編輯解決方案
- 短影片軟體系統開發:選擇開源原始碼原始碼
- 短影片直播系統,Android卡片式輪播Android
- pygame播放影片並實現音影片同步GAM
- H.265 & HEVC 影片編碼 All In One
- 短影片直播功能開發定製短影片系統功能需求無加密加密
- 轉載:iOS音視訊實時採集硬體編碼iOS
- 兔子短影片直播(卷軸)系統技術開發(原始碼搭建)原始碼
- 如何提高還在用window系統的編碼硬效率
- Filmage Editor for Mac(專業音影片編輯工具)Mac
- 短影片直播APP原生開發直播系統無加密搭建定製短影片APP加密
- 短影片app開發,短影片系統發展的收益方式是什麼?APP
- 音影片編解碼技術在直播平臺中是如何運用的?