zl程序教程

您现在的位置是:首页 >  APP

当前栏目

Android平台RTMP推送模块如何对接NV21、YV12、RGB、YUV等编码前数据

2023-03-14 22:38:07 时间

前言

我们在对接Android平台摄像头或者屏幕采集、编码打包推送场景的时候,随着采集设备的不同,出来的数据也是多样化的,比如NV21、YV12、RGB、YUV等,更有图像数据甚至是翻转或者倒置的,如果上层处理,效率低下,本篇文章主要介绍下常用的编码前数据接口。相关资料或版本测试,也可联系大牛直播SDK(官方

接口描述

1. Android设备前后摄像头数据:

Android自带的camera摄像头数据对接是最基础的,需要考虑的是摄像头方向问题,比如横屏、竖屏、还有部分定制设备home键在左侧的情况,相对来说处理比较简单,直接上接口,不再赘述。

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

这里有个问题,有的设备,出来的数据,可能是旋转或者倒置的,为此,我们提供了NV21的对接接口,以满足数据旋转、水平、垂直翻转诉求。注意:y_stride一般系video_width, uv_strde合到一起也是传video_width.

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

2. YV12的数据接口:

YV12的数据接口,主要是用于第三方的设备对接居多,这个接口的u_stride, v_stride分别是(width+1)/2,如果出来的数据需要旋转,通过rotation_degree来控制旋转角度即可。

    /**
     * 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. YUV数据接口:

支持标准的I420数据接口对接,不再赘述:

    /**
    * 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转I420并旋转接口

这个接口也是主要用于特定的数据类型对接,NV21的数据,直接转I420后,对接即可,接口参数比较简单,不再赘述。

	/**
	 * NV21转换到I420并旋转
	 *
	 * @param src: nv21 data
	 *
	 * @param dst: 输出I420 data
	 *
	 * @param width: 图像宽
	 *
	 * @param height: 图像高
	 *
	 * rotation_degree: 顺时针旋转, 必须是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数据接入(支持裁剪后数据接入,主要用于同屏场景):

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数据接入(主要用于同屏场景):

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接口对接): 为了更高效率的兼容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. 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: 是否垂直翻转, 0不翻转, 1翻转
	 *
	 * @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
	 *
	 * @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270
	 *
	 * @param  scale_width: 缩放宽,必须是8的倍数, 0不缩放
	 *
	 * @param  scale_height: 缩放高, 必须是8的倍数, 0不缩放
	 *
	 * @param  scale_filter_mode: 缩放质量, 范围必须是[1,3], 传0使用默认质量
	 *
	 * @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: 是否垂直翻转, 0不翻转, 1翻转
	 *
	 * @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
	 *
	 * @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270
	 *
	 * @param  scale_width: 缩放宽,必须是8的倍数, 0不缩放
	 *
	 * @param  scale_height: 缩放高, 必须是8的倍数, 0不缩放
	 *
	 * @param  scale_filter_mode: 缩放质量, 范围必须是[1,3], 传0使用默认质量
	 *
	 * @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);

总结:

以上仅是Android视频编码前的数据接口分享,感兴趣的开发者可酌情参考。

由此可见,部分公司或开发者提到,一个Android平台的RTMP推送模块只要几个接口,化繁为简几乎是不可能的。

一个好的产品的迭代,必然需要付出很大的精力和代价。