Android平台RTMP推送模块如何对接NV21、YV12、RGB、YUV等编码前数据
前言
我們在對接Android平臺攝像頭或者屏幕采集、編碼打包推送場景的時候,隨著采集設(shè)備的不同,出來的數(shù)據(jù)也是多樣化的,比如NV21、YV12、RGB、YUV等,更有圖像數(shù)據(jù)甚至是翻轉(zhuǎn)或者倒置的,如果上層處理,效率低下,本篇文章主要介紹下常用的編碼前數(shù)據(jù)接口。相關(guān)資料或版本測試,也可聯(lián)系大牛直播SDK(官方)
接口描述
1.?Android設(shè)備前后攝像頭數(shù)據(jù):
Android自帶的camera攝像頭數(shù)據(jù)對接是最基礎(chǔ)的,需要考慮的是攝像頭方向問題,比如橫屏、豎屏、還有部分定制設(shè)備home鍵在左側(cè)的情況,相對來說處理比較簡單,直接上接口,不再贅述。
@Overridepublic void onPreviewFrame(byte[] data, Camera camera) {frameCount++;if (frameCount % 3000 == 0) {Log.i("OnPre", "gc+");System.gc();Log.i("OnPre", "gc-");}if (data == null) {Parameters params = camera.getParameters();Size size = params.getPreviewSize();int bufferSize = (((size.width | 0x1f) + 1) * size.height * ImageFormat.getBitsPerPixel(params.getPreviewFormat())) / 8;camera.addCallbackBuffer(new byte[bufferSize]);} else {if (isRTSPPublisherRunning || isPushingRtmp || isRecording || isPushingRtsp) {libPublisher.SmartPublisherOnCaptureVideoData(publisherHandle, data, data.length, currentCameraType, currentOrigentation);}camera.addCallbackBuffer(data);}}?對應接口定義:
/*** Set live video data(no encoded data).** @param cameraType: CAMERA_FACING_BACK with 0, CAMERA_FACING_FRONT with 1*?* @param curOrg:* PORTRAIT = 1;????//豎屏* LANDSCAPE = 2;????//橫屏 home鍵在右邊的情況* LANDSCAPE_LEFT_HOME_KEY = 3; //橫屏 home鍵在左邊的情況** @return {0} if successful*/public native int SmartPublisherOnCaptureVideoData(long handle, byte[] data, int len, int cameraType, int curOrg);這里有個問題,有的設(shè)備,出來的數(shù)據(jù),可能是旋轉(zhuǎn)或者倒置的,為此,我們提供了NV21的對接接口,以滿足數(shù)據(jù)旋轉(zhuǎn)、水平、垂直翻轉(zhuǎn)訴求。注意:y_stride一般系video_width, uv_strde合到一起也是傳video_width.
/*** NV21數(shù)據(jù)接口** @param data: nv21 data** @param len: data length** @param width: 圖像寬** @param height: 圖像高** @param y_stride: y面步長** @param uv_stride: uv面步長** rotation_degree: 順時針旋轉(zhuǎn), 必須是0, 90, 180, 270** @return {0} if successful*/public native int SmartPublisherOnNV21Data(long handle, byte[] data, int len, int width, int height, int y_stride, int uv_stride, int rotation_degree);/*** NV21數(shù)據(jù)接口** @param data: nv21 data** @param len: data length** @param width: 圖像寬** @param height: 圖像高** @param y_stride: y面步長** @param uv_stride: uv面步長** rotation_degree: 順時針旋轉(zhuǎn), 必須是0, 90, 180, 270** @param is_vertical_flip: 是否垂直翻轉(zhuǎn), 0不翻轉(zhuǎn), 1翻轉(zhuǎn)** @param is_horizontal_flip:是否水平翻轉(zhuǎn), 0不翻轉(zhuǎn), 1翻轉(zhuǎn)** @return {0} if successful*/public native int SmartPublisherOnNV21DataV2(long handle, byte[] data, int len, int width, int height, int y_stride, int uv_stride, int rotation_degree,int is_vertical_flip, int is_horizontal_flip);2. YV12的數(shù)據(jù)接口:
YV12的數(shù)據(jù)接口,主要是用于第三方的設(shè)備對接居多,這個接口的u_stride, v_stride分別是(width+1)/2,如果出來的數(shù)據(jù)需要旋轉(zhuǎn),通過rotation_degree來控制旋轉(zhuǎn)角度即可。
????/*** YV12數(shù)據(jù)接口** @param data: YV12 data** @param width: 圖像寬** @param height: 圖像高** @param y_stride: ?y面步長** @param v_stride: v面步長** @param u_stride: u面步長** rotation_degree: 順時針旋轉(zhuǎn), 必須是0, 90, 180, 270** @return {0} if successful*/public native int SmartPublisherOnYV12Data(long handle, byte[] data, int width, int height, int y_stride, ?int v_stride, int u_stride, int rotation_degree);3. YUV數(shù)據(jù)接口:
支持標準的I420數(shù)據(jù)接口對接,不再贅述:
????/*** Set live video data(no encoded data).** @param data: I420 data*?* @param len: I420 data length*?* @param yStride: y stride*?* @param uStride: u stride*?* @param vStride: v stride** @return {0} if successful*/public native int SmartPublisherOnCaptureVideoI420Data(long handle, ?byte[] data, int len, int yStride, int uStride, int vStride);為了方便對接,我們提供了I420的擴展接口:
/*** 傳I420圖像接口** @param data: I420 data** @param width: 圖像寬** @param height: 圖像高** @param y_stride: y stride** @param u_stride: u stride** @param v_stride: v stride** @return {0} if successful*/public native int SmartPublisherOnCaptureVideoI420DataV2(long handle, byte[] data, int width, int height, int y_stride, int u_stride, int v_stride);4. NV21轉(zhuǎn)I420并旋轉(zhuǎn)接口
這個接口也是主要用于特定的數(shù)據(jù)類型對接,NV21的數(shù)據(jù),直接轉(zhuǎn)I420后,對接即可,接口參數(shù)比較簡單,不再贅述。
/*** NV21轉(zhuǎn)換到I420并旋轉(zhuǎn)** @param src: nv21 data** @param dst: 輸出I420 data** @param width: 圖像寬** @param height: 圖像高** rotation_degree: 順時針旋轉(zhuǎn), 必須是0, 90, 180, 270** @return {0} if successful*/public native int SmartPublisherNV21ToI420Rotate(long handle, byte[] src, int src_y_stride, int src_uv_stride, byte[] dst,int dst_y_stride, int dst_u_stride, int dst_v_stride,int width, int height,int rotation_degree);
5. 支持RGBA數(shù)據(jù)接入(支持裁剪后數(shù)據(jù)接入,主要用于同屏場景):
RGBA的主要用于屏幕共享場景下。
????/*** Set live video data(no encoded data).** @param data: RGBA data*?* @param rowStride: stride information*?* @param width: width*?* @param height: height** @return {0} if successful*/public native int SmartPublisherOnCaptureVideoRGBAData(long handle, ?ByteBuffer data, int rowStride, int width, int height);/*** 投遞裁剪過的RGBA數(shù)據(jù)** @param data: RGBA data** @param rowStride: stride information** @param width: width** @param height: height** @param clipedLeft: 左; ?clipedTop: 上; clipedwidth: 裁剪后的寬; clipedHeight: 裁剪后的高; 確保傳下去裁剪后的寬、高均為偶數(shù)** @return {0} if successful*/public native int SmartPublisherOnCaptureVideoClipedRGBAData(long handle, ?ByteBuffer data, int rowStride, int width, int height, int clipedLeft, int clipedTop, int clipedWidth, int clipedHeight);/*** Set live video data(no encoded data).** @param data: ABGR flip vertical(垂直翻轉(zhuǎn)) data** @param rowStride: stride information** @param width: width** @param height: height** @return {0} if successful*/public native int SmartPublisherOnCaptureVideoABGRFlipVerticalData(long handle, ?ByteBuffer data, int rowStride, int width, int height);6. 支持RGB565數(shù)據(jù)接入(主要用于同屏場景):
RGB565數(shù)據(jù)類型也主要用于屏幕采集這塊。
????/*** Set live video data(no encoded data).** @param data: RGB565 data** @param row_stride: stride information** @param width: width** @param height: height** @return {0} if successful*/public native int SmartPublisherOnCaptureVideoRGB565Data(long handle,ByteBuffer data, int row_stride, int width, int height);7.?支持camera數(shù)據(jù)接入(主要用于camera2接口對接):
? ? 為了更高效率的兼容camera2數(shù)據(jù)采集模式。
/** ?專門為android.media.Image的android.graphics.ImageFormat.YUV_420_888格式提供的接口** @param ?width: 必須是8的倍數(shù)** @param ?height: 必須是8的倍數(shù)** @param ?crop_left: 剪切左上角水平坐標, 一般根據(jù)android.media.Image.getCropRect() 填充** @param ?crop_top: 剪切左上角垂直坐標, 一般根據(jù)android.media.Image.getCropRect() 填充** @param ?crop_width: 必須是8的倍數(shù), 填0將忽略這個參數(shù), 一般根據(jù)android.media.Image.getCropRect() 填充** @param ?crop_height: 必須是8的倍數(shù), 填0將忽略這個參數(shù),一般根據(jù)android.media.Image.getCropRect() 填充** @param y_plane 對應android.media.Image.Plane[0].getBuffer()** @param y_row_stride 對應android.media.Image.Plane[0].getRowStride()** @param u_plane 對應android.media.Image.Plane[1].getBuffer()** @param v_plane 對應android.media.Image.Plane[2].getBuffer()** @param uv_row_stride 對應android.media.Image.Plane[1].getRowStride()** @param uv_pixel_stride 對應android.media.Image.Plane[1].getPixelStride()** @param ?rotation_degree: 順時針旋轉(zhuǎn), 必須是0, 90, 180, 270** @param ?is_vertical_flip: 是否垂直翻轉(zhuǎn), 0不翻轉(zhuǎn), 1翻轉(zhuǎn)** @param ?is_horizontal_flip:是否水平翻轉(zhuǎn), 0不翻轉(zhuǎn), 1翻轉(zhuǎn)** @param ?scale_width: 縮放寬,必須是8的倍數(shù), 0不縮放** @param ?scale_height: 縮放高, 必須是8的倍數(shù), 0不縮放** @param ?scale_filter_mode: 縮放質(zhì)量, 范圍必須是[1,3], 傳0使用默認速度** @return {0} if successful*/public native int SmartPublisherOnImageYUV420888(long handle, int width, int height,int crop_left, int crop_top, int crop_width, int crop_height,ByteBuffer y_plane, int y_row_stride,ByteBuffer u_plane, ByteBuffer v_plane, int uv_row_stride, int uv_pixel_stride,int rotation_degree, int is_vertical_flip, int is_horizontal_flip,int scale_width, int scale_height, int scale_filter_mode);
8. RGB24和RGBA32接口
/*** Set live video data(no encoded data).** @param buffer: RGB24 data** @param length: data length** @param rowStride: stride information** @param width: width** @param height: height** @param is_vertical_flip: 是否垂直翻轉(zhuǎn), 0不翻轉(zhuǎn), 1翻轉(zhuǎn)** @param is_horizontal_flip:是否水平翻轉(zhuǎn), 0不翻轉(zhuǎn), 1翻轉(zhuǎn)** @param rotation_degree: 順時針旋轉(zhuǎn), 必須是0, 90, 180, 270** @param scale_width: 縮放寬,必須是8的倍數(shù), 0不縮放** @param scale_height: 縮放高, 必須是8的倍數(shù), 0不縮放** @param scale_filter_mode: 縮放質(zhì)量, 范圍必須是[1,3], 傳0使用默認質(zhì)量** @return {0} if successful*/public native int SmartPublisherOnCaptureVideoRGB24Data(long handle, long buffer, int length, int rowStride, int width, int height,int is_vertical_flip, int is_horizontal_flip,int rotation_degree,int scale_width, int scale_height, int scale_filter_mode);/*** Set live video data(no encoded data).** @param buffer: RGBA data** @param length: data length** @param rowStride: stride information** @param width: width** @param height: height** @param is_vertical_flip: 是否垂直翻轉(zhuǎn), 0不翻轉(zhuǎn), 1翻轉(zhuǎn)** @param is_horizontal_flip:是否水平翻轉(zhuǎn), 0不翻轉(zhuǎn), 1翻轉(zhuǎn)** @param rotation_degree: 順時針旋轉(zhuǎn), 必須是0, 90, 180, 270** @param scale_width: 縮放寬,必須是8的倍數(shù), 0不縮放** @param scale_height: 縮放高, 必須是8的倍數(shù), 0不縮放** @param scale_filter_mode: 縮放質(zhì)量, 范圍必須是[1,3], 傳0使用默認質(zhì)量** @return {0} if successful*/public native int SmartPublisherOnCaptureVideoRGBA32Data(long handle, long buffer, int length, int rowStride, int width, int height,int is_vertical_flip, int is_horizontal_flip,int rotation_degree,int scale_width, int scale_height, int scale_filter_mode);總結(jié):
以上僅是Android視頻編碼前的數(shù)據(jù)接口分享,感興趣的開發(fā)者可酌情參考。
由此可見,部分公司或開發(fā)者提到,一個Android平臺的RTMP推送模塊只要幾個接口,化繁為簡幾乎是不可能的。
一個好的產(chǎn)品的迭代,必然需要付出很大的精力和代價。
總結(jié)
以上是生活随笔為你收集整理的Android平台RTMP推送模块如何对接NV21、YV12、RGB、YUV等编码前数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Python】强烈建议你学这 3 个
- 下一篇: 本地一站式极速开发AI模型 百度飞桨Ea