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

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

前言

我们在对接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推送模块只要几个接口,化繁为简几乎是不可能的。


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

相关文章
|
8天前
|
消息中间件 网络协议 Java
Android 开发中实现数据传递:广播和Handler
Android 开发中实现数据传递:广播和Handler
13 1
|
8天前
|
Android开发
Android MediaTek 平台增加UART接口的红外模块支持,支持NEC红外遥控
Android MediaTek 平台增加UART接口的红外模块支持,支持NEC红外遥控
11 0
|
8天前
|
Android开发
Android 支持 ap6236 wifi 模块补丁
Android 支持 ap6236 wifi 模块补丁
11 0
|
8天前
|
Android开发
Android RIL 动态切换 4G 模块适配
Android RIL 动态切换 4G 模块适配
14 0
|
15天前
|
Android开发 开发者
Android网络和数据交互: 请解释Android中的AsyncTask的作用。
Android's AsyncTask simplifies asynchronous tasks for brief background work, bridging UI and worker threads. It involves execute() for starting tasks, doInBackground() for background execution, publishProgress() for progress updates, and onPostExecute() for returning results to the main thread.
11 0
|
15天前
|
网络协议 安全 API
Android网络和数据交互: 什么是HTTP和HTTPS?在Android中如何进行网络请求?
HTTP和HTTPS是网络数据传输协议,HTTP基于TCP/IP,简单快速,HTTPS则是加密的HTTP,确保数据安全。在Android中,过去常用HttpURLConnection和HttpClient,但HttpClient自Android 6.0起被移除。现在推荐使用支持TLS、流式上传下载、超时配置等特性的HttpsURLConnection进行网络请求。
11 0
|
22天前
|
JSON 安全 Java
Android网络部分-----网络数据请求、解析
Android网络部分-----网络数据请求、解析
Android网络部分-----网络数据请求、解析
|
28天前
|
XML Java Android开发
Android每点击一次按钮就添加一条数据
Android每点击一次按钮就添加一条数据
24 1
|
2月前
|
Android开发
Android 数据传递的几种方式,HttpLoggingInterceptor消息拦截器
Android 数据传递的几种方式,HttpLoggingInterceptor消息拦截器
20 6
|
数据采集 传感器 编解码
【Android RTMP】音频数据采集编码 ( FAAC 编码器编码 AAC 音频解码信息 | 封装 RTMP 音频数据头 | 设置 AAC 音频数据类型 | 封装 RTMP 数据包 )
【Android RTMP】音频数据采集编码 ( FAAC 编码器编码 AAC 音频解码信息 | 封装 RTMP 音频数据头 | 设置 AAC 音频数据类型 | 封装 RTMP 数据包 )
202 0