1. 程式人生 > 實用技巧 >安卓平臺RTMP推流或輕量級RTSP服務(攝像頭或同屏)編碼前資料接入型別總結

安卓平臺RTMP推流或輕量級RTSP服務(攝像頭或同屏)編碼前資料接入型別總結

很多開發者在做Android平臺RTMP推流或輕量級RTSP服務(攝像頭或同屏)時,總感覺介面不夠用,以大牛直播SDK為例 (Github) 我們來總結下,我們常規需要支援的編碼前音視訊資料有哪些型別:

1. Android攝像頭前後camera通過OnPreviewFrame()回撥的資料介面:

    @Override
    public 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);

2. 部分定製裝置,只支援YV12的資料:

/**
* YV12資料介面
*
* @param data: YV12 data
*
* @param width: 影象寬
*
* @param height: 影象高
*
* @param y_stride: y面步長
*
* @param v_stride: v面步長
*
* @param u_stride: u面步長
*
* rotation_degree: 順時針旋轉, 必須是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. 支援NV21資料介面:

nv21資料介面,除了用於常規的camera資料接入外,部分定製攝像頭出來的資料發生翻轉,這個介面也支援。

/**
* NV21資料介面
*
* @param data: nv21 data
*
* @param len: data length
*
* @param width: 影象寬
*
* @param height: 影象高
*
* @param y_stride: y面步長
*
* @param uv_stride: uv面步長
*
* rotation_degree: 順時針旋轉, 必須是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資料介面
*
* @param data: nv21 data
*
* @param len: data length
*
* @param width: 影象寬
*
* @param height: 影象高
*
* @param y_stride: y面步長
*
* @param uv_stride: uv面步長
*
* rotation_degree: 順時針旋轉, 必須是0, 90, 180, 270
*
* @param is_vertical_flip: 是否垂直翻轉, 0不翻轉, 1翻轉
*
* @param is_horizontal_flip:是否水平翻轉, 0不翻轉, 1翻轉
*
* @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);

4. 支援YUV資料接入:

/**
* 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);


5. 支援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資料
*
* @param data: RGBA data
*
* @param rowStride: stride information
*
* @param width: width
*
* @param height: height
*
* @param clipedLeft: 左; clipedTop: 上; clipedwidth: 裁剪後的寬; clipedHeight: 裁剪後的高; 確保傳下去裁剪後的寬、高均為偶數
*
* @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(垂直翻轉) 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資料接入(主要用於同屏場景):

/**
* 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資料接入(主要用於camera2介面對接):

/*
* 專門為android.media.Image的android.graphics.ImageFormat.YUV_420_888格式提供的介面
*
* @param width: 必須是8的倍數
*
* @param height: 必須是8的倍數
*
* @param crop_left: 剪下左上角水平座標, 一般根據android.media.Image.getCropRect() 填充
*
* @param crop_top: 剪下左上角垂直座標, 一般根據android.media.Image.getCropRect() 填充
*
* @param crop_width: 必須是8的倍數, 填0將忽略這個引數, 一般根據android.media.Image.getCropRect() 填充
*
* @param crop_height: 必須是8的倍數, 填0將忽略這個引數,一般根據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: 順時針旋轉, 必須是0, 90, 180, 270
*
* @param is_vertical_flip: 是否垂直翻轉, 0不翻轉, 1翻轉
*
* @param is_horizontal_flip:是否水平翻轉, 0不翻轉, 1翻轉
*
* @param scale_width: 縮放寬,必須是8的倍數, 0不縮放
*
* @param scale_height: 縮放高, 必須是8的倍數, 0不縮放
*
* @param scale_filter_mode: 縮放質量, 範圍必須是[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.支援PCM資料接入:

/**
* 傳遞PCM音訊資料給SDK, 每10ms音訊資料傳入一次
*
* @param pcmdata: pcm資料, 需要使用ByteBuffer.allocateDirect分配, ByteBuffer.isDirect()是true的才行.
* @param size: pcm資料大小
* @param sample_rate: 取樣率,當前只支援{44100, 8000, 16000, 24000, 32000, 48000}, 推薦44100
* @param channel: 通道, 當前通道支援單通道(1)和雙通道(2),推薦單通道(1)
* @param per_channel_sample_number: 這個請傳入的是 sample_rate/100
*/
public native int SmartPublisherOnPCMData(long handle, ByteBuffer pcmdata, int size, int sample_rate, int channel, int per_channel_sample_number);


/**
* 傳遞PCM音訊資料給SDK, 每10ms音訊資料傳入一次
*
* @param pcmdata: pcm資料, 需要使用ByteBuffer.allocateDirect分配, ByteBuffer.isDirect()是true的才行.
* @param offset: pcmdata的偏移
* @param size: pcm資料大小
* @param sample_rate: 取樣率,當前只支援{44100, 8000, 16000, 24000, 32000, 48000}, 推薦44100
* @param channel: 通道, 當前通道支援單通道(1)和雙通道(2),推薦單通道(1)
* @param per_channel_sample_number: 這個請傳入的是 sample_rate/100
*/
public native int SmartPublisherOnPCMDataV2(long handle, ByteBuffer pcmdata, int offset, int size, int sample_rate, int channel, int per_channel_sample_number);


/**
* 傳遞PCM音訊資料給SDK, 每10ms音訊資料傳入一次
*
* @param pcm_short_array: pcm資料, short是native endian order
* @param offset: 陣列偏移
* @param len: 陣列項數
* @param sample_rate: 取樣率,當前只支援{44100, 8000, 16000, 24000, 32000, 48000}, 推薦44100
* @param channel: 通道, 當前通道支援單通道(1)和雙通道(2),推薦單通道(1)
* @param per_channel_sample_number: 這個請傳入的是 sample_rate/100
*/
public native int SmartPublisherOnPCMShortArray(long handle, short[] pcm_short_array, int offset, int len, int sample_rate, int channel, int per_channel_sample_number);

9.支援遠端PCM資料接入和混音後PCM資料接入(主要用於一對一互動):

/**
* Set far end pcm data
*
* @param pcmdata : 16bit pcm data
* @param sampleRate: audio sample rate
* @param channel: auido channel
* @param per_channel_sample_number: per channel sample numbers
* @param is_low_latency: if with 0, it is not low_latency, if with 1, it is low_latency
* @return {0} if successful
*/
public native int SmartPublisherOnFarEndPCMData(long handle, ByteBuffer pcmdata, int sampleRate, int channel, int per_channel_sample_number, int is_low_latency);


/**
* 傳遞PCM混音音訊資料給SDK, 每10ms音訊資料傳入一次
*
* @param stream_index: 當前只能傳1, 傳其他返回錯誤
* @param pcm_data: pcm資料, 需要使用ByteBuffer.allocateDirect分配, ByteBuffer.isDirect()是true的才行.
* @param offset: pcmdata的偏移
* @param size: pcm資料大小
* @param sample_rate: 取樣率,當前只支援{44100, 8000, 16000, 24000, 32000, 48000}
* @param channels: 通道, 當前通道支援單通道(1)和雙通道(2)
* @param per_channel_sample_number: 這個請傳入的是 sample_rate/100
*/
public native int SmartPublisherOnMixPCMData(long handle, int stream_index, ByteBuffer pcm_data, int offset, int size, int sample_rate, int channels, int per_channel_sample_number);


/**
* 傳遞PCM混音音訊資料給SDK, 每10ms音訊資料傳入一次
*
* @param stream_index: 當前只能傳1, 傳其他返回錯誤
* @param pcm_short_array: pcm資料, short是native endian order
* @param offset: 陣列偏移
* @param len: 陣列項數
* @param sample_rate: 取樣率,當前只支援{44100, 8000, 16000, 24000, 32000, 48000}
* @param channels: 通道, 當前通道支援單通道(1)和雙通道(2)
* @param per_channel_sample_number: 這個請傳入的是 sample_rate/100
*/
public native int SmartPublisherOnMixPCMShortArray(long handle, int stream_index, short[] pcm_short_array, int offset, int len, int sample_rate, int channels, int per_channel_sample_number);

總結:

以上只是編碼前資料介面,一個產品如果想做的足夠通用,需要對接的太多了,你覺得呢?