Android平台GB28181设备接入端对接编码前后音视频源类型浅析

简介: 今天主要对Android平台GB28181设备接入模块支持的接入数据类型,做个简单的汇总:1. 编码前数据(目前支持的有YV12/NV21/NV12/I420/RGB24/RGBA32/RGB565等数据类型),其中,Android平台前后摄像头数据,或者屏幕数据,或者Unity拿到的数据,均属编码前数据;2. 编码后数据(如无人机等264/HEVC数据,或者本地解析的MP4音视频数据);3. 拉取RTSP或RTMP流并接入至GB28181平台(比如其他IPC的RTSP流,可通过Android平台GB28181接入到国标平台)。

前言

今天主要对Android平台GB28181设备接入模块支持的接入数据类型,做个简单的汇总:


  1. 编码前数据(目前支持的有YV12/NV21/NV12/I420/RGB24/RGBA32/RGB565等数据类型),其中,Android平台前后摄像头数据,或者屏幕数据,或者Unity拿到的数据,均属编码前数据;
  2. 编码后数据(如无人机等264/HEVC数据,或者本地解析的MP4音视频数据);
  3. 拉取RTSP或RTMP流并接入至GB28181平台(比如其他IPC的RTSP流,可通过Android平台GB28181接入到国标平台)。

支持的音视频数据类型

编码前音视频数据


编码前音视频数据支持的类型接口如下,除了常规的音视频数据外,我们还设计支持了实时动态水印,比如实时文字水印、图片水印,音频这块,我们实现了混音机制,支持2路混音输入:

/*
 * SmartPublisherJniV2.java
 * SmartPublisherJniV2
 *
 * WebSite: https://daniusdk.com
 * Github: https://github.com/daniulive/SmarterStreaming
 * 
 * Created by DaniuLive on 2015/09/20.
 */
/**
    * 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);
    /**
     * 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);
    /**
     * 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);
    /**
     * 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);
    /**
    * 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图像接口
     *
     * @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);
    /**
     * 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);
    /**
    * 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);
    /**
     * 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);
    /*
    *  专门为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);
    /**
     * 启用或者停用视频层, 这个接口必须在StartXXX之后调用.
     *
     * @param index: 层索引, 必须大于0, 注意第0层不能停用
     *
     * @param  is_enable: 是否启用, 0停用, 1启用
     *
     * @return {0} if successful
     */
    public native int EnableLayer(long handle, int index, int is_enable);
    /**
     * 移除视频层, 这个接口必须在StartXXX之后调用.
     *
     * @param index: 层索引, 必须大于0, 注意第0层不能移除
     *
     * @return {0} if successful
     */
    public native int RemoveLayer(long handle, int index);
    /**
     * 投递层RGBA8888图像,如果不需要Aplpha通道的话, 请使用RGBX8888接口, 效率高
     *
     * @param index: 层索引, 必须大于等于0, 注意:如果index是0的话,将忽略Alpha通道
     *
     * @param left: 层叠加的左上角坐标, 对于第0层的话传0
     *
     * @param top: 层叠加的左上角坐标, 对于第0层的话传0
     *
     * @param rgba_plane: rgba 图像数据
     *
     * @param offset: 图像偏移, 这个主要目的是用来做clip的, 一般传0
     *
     * @param row_stride: stride information
     *
     * @param width: width, 必须大于1, 如果是奇数, 将减1
     *
     * @param height: height, 必须大于1, 如果是奇数, 将减1
     *
     * @param  is_vertical_flip: 是否垂直翻转, 0不翻转, 1翻转
     *
     * @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
     *
     * @param  scale_width: 缩放宽,必须是偶数, 0或负数不缩放
     *
     * @param  scale_height: 缩放高, 必须是偶数, 0或负数不缩放
     *
     * @param  scale_filter_mode: 缩放质量, 传0使用默认速度,可选等级范围是:[1,3],值越大缩放质量越好, 但速度越慢
     *
     * @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270, 注意:旋转是在缩放, 垂直/水品反转之后再做, 请留意顺序
     *
     * @return {0} if successful
     */
    public native int PostLayerImageRGBA8888ByteBuffer(long handle, int index, int left, int top,
                                             ByteBuffer rgba_plane, int offset, int row_stride, int width, int height,
                                             int is_vertical_flip,  int is_horizontal_flip,
                                             int scale_width,  int scale_height, int scale_filter_mode,
                                             int rotation_degree);
    /**
     * 投递层RGBA8888图像, 详细说明请参考PostLayerImageRGBA8888ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageRGBA8888ByteArray(long handle, int index, int left, int top,
                                                      byte[] rgba_plane, int offset, int row_stride, int width, int height,
                                                      int is_vertical_flip,  int is_horizontal_flip,
                                                      int scale_width,  int scale_height, int scale_filter_mode,
                                                      int rotation_degree);
    /**
     * 投递层RGBA8888图像, 详细说明请参考PostLayerImageRGBA8888ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageRGBA8888Native(long handle, int index, int left, int top,
                                                   long rgba_plane, int offset, int row_stride, int width, int height,
                                                   int is_vertical_flip,  int is_horizontal_flip,
                                                   int scale_width,  int scale_height, int scale_filter_mode,
                                                   int rotation_degree);
    /**
     * 投递层RGBX8888图像
     *
     * @param index: 层索引, 必须大于等于0
     *
     * @param left: 层叠加的左上角坐标, 对于第0层的话传0
     *
     * @param top: 层叠加的左上角坐标, 对于第0层的话传0
     *
     * @param rgbx_plane: rgbx 图像数据
     *
     * @param offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
     *
     * @param row_stride: stride information
     *
     * @param width: width, 必须大于1, 如果是奇数, 将减1
     *
     * @param height: height, 必须大于1, 如果是奇数, 将减1
     *
     * @param  is_vertical_flip: 是否垂直翻转, 0不翻转, 1翻转
     *
     * @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
     *
     * @param  scale_width: 缩放宽,必须是偶数, 0或负数不缩放
     *
     * @param  scale_height: 缩放高, 必须是偶数, 0或负数不缩放
     *
     * @param  scale_filter_mode: 缩放质量, 传0使用默认速度,可选等级范围是:[1,3],值越大缩放质量越好, 但速度越慢
     *
     * @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270, 注意:旋转是在缩放, 垂直/水品反转之后再做, 请留意顺序
     *
     * @return {0} if successful
     */
    public native int PostLayerImageRGBX8888ByteBuffer(long handle, int index, int left, int top,
                                                       ByteBuffer rgbx_plane, int offset, int row_stride, int width, int height,
                                                       int is_vertical_flip,  int is_horizontal_flip,
                                                       int scale_width,  int scale_height, int scale_filter_mode,
                                                       int rotation_degree);
    /**
     * 投递层RGBX8888图像, 详细说明请参考PostLayerImageRGBX8888ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageRGBX8888ByteArray(long handle, int index, int left, int top,
                                                      byte[] rgbx_plane, int offset, int row_stride, int width, int height,
                                                      int is_vertical_flip,  int is_horizontal_flip,
                                                      int scale_width,  int scale_height, int scale_filter_mode,
                                                      int rotation_degree);
    /**
     * 投递层RGBX8888图像, 详细说明请参考PostLayerImageRGBX8888ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageRGBX8888Native(long handle, int index, int left, int top,
                                                   long rgbx_plane, int offset, int row_stride, int width, int height,
                                                   int is_vertical_flip,  int is_horizontal_flip,
                                                   int scale_width,  int scale_height, int scale_filter_mode,
                                                   int rotation_degree);
    /**
     * 投递层RGB888图像
     *
     * @param index: 层索引, 必须大于等于0
     *
     * @param left: 层叠加的左上角坐标, 对于第0层的话传0
     *
     * @param top: 层叠加的左上角坐标, 对于第0层的话传0
     *
     * @param rgb_plane: rgb888 图像数据
     *
     * @param offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
     *
     * @param row_stride: stride information
     *
     * @param width: width, 必须大于1, 如果是奇数, 将减1
     *
     * @param height: height, 必须大于1, 如果是奇数, 将减1
     *
     * @param  is_vertical_flip: 是否垂直翻转, 0不翻转, 1翻转
     *
     * @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
     *
     * @param  scale_width: 缩放宽,必须是偶数, 0或负数不缩放
     *
     * @param  scale_height: 缩放高, 必须是偶数, 0或负数不缩放
     *
     * @param  scale_filter_mode: 缩放质量, 传0使用默认速度,可选等级范围是:[1,3],值越大缩放质量越好, 但速度越慢
     *
     * @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270, 注意:旋转是在缩放, 垂直/水品反转之后再做, 请留意顺序
     *
     * @return {0} if successful
     */
    public native int PostLayerImageRGB888Native(long handle, int index, int left, int top,
                                                       long rgb_plane, int offset, int row_stride, int width, int height,
                                                       int is_vertical_flip,  int is_horizontal_flip,
                                                       int scale_width,  int scale_height, int scale_filter_mode,
                                                       int rotation_degree);
    /**
     * 投递层NV21图像
     *
     * @param index: 层索引, 必须大于等于0
     *
     * @param left: 层叠加的左上角坐标, 对于第0层的话传0
     *
     * @param top: 层叠加的左上角坐标, 对于第0层的话传0
     *
     * @param y_plane: y平面图像数据
     *
     * @param y_offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
     *
     * @param y_row_stride: stride information
     *
     * @param uv_plane: uv平面图像数据
     *
     * @param uv_offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
     *
     * @param uv_row_stride: stride information
     *
     * @param width: width, 必须大于1, 且必须是偶数
     *
     * @param height: height, 必须大于1, 且必须是偶数
     *
     * @param  is_vertical_flip: 是否垂直翻转, 0不翻转, 1翻转
     *
     * @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
     *
     * @param  scale_width: 缩放宽,必须是偶数, 0或负数不缩放
     *
     * @param  scale_height: 缩放高, 必须是偶数, 0或负数不缩放
     *
     * @param  scale_filter_mode: 缩放质量, 传0使用默认速度,可选等级范围是:[1,3],值越大缩放质量越好, 但速度越慢
     *
     * @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270, 注意:旋转是在缩放, 垂直/水品反转之后再做, 请留意顺序
     *
     * @return {0} if successful
     */
    public native int PostLayerImageNV21ByteBuffer(long handle, int index, int left, int top,
                                                       ByteBuffer y_plane, int y_offset, int y_row_stride,
                                                       ByteBuffer uv_plane, int uv_offset, int uv_row_stride,
                                                       int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                                                       int scale_width,  int scale_height, int scale_filter_mode,
                                                       int rotation_degree);
    /**
     * 投递层NV21图像, 详细说明请参考PostLayerImageNV21ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageNV21ByteArray(long handle, int index, int left, int top,
                                                   byte[] y_plane, int y_offset, int y_row_stride,
                                                   byte[] uv_plane, int uv_offset, int uv_row_stride,
                                                   int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                                                   int scale_width,  int scale_height, int scale_filter_mode,
                                                   int rotation_degree);
    /**
     * 投递层NV12图像, 详细说明请参考PostLayerImageNV21ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageNV12ByteBuffer(long handle, int index, int left, int top,
                                                   ByteBuffer y_plane, int y_offset, int y_row_stride,
                                                   ByteBuffer uv_plane, int uv_offset, int uv_row_stride,
                                                   int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                                                   int scale_width,  int scale_height, int scale_filter_mode,
                                                   int rotation_degree);
    /**
     * 投递层NV12图像, 详细说明请参考PostLayerImageNV21ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageNV12ByteArray(long handle, int index, int left, int top,
                                                  byte[] y_plane, int y_offset, int y_row_stride,
                                                  byte[] uv_plane, int uv_offset, int uv_row_stride,
                                                  int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                                                  int scale_width,  int scale_height, int scale_filter_mode,
                                                  int rotation_degree);
    /**
     * 投递层I420图像
     *
     * @param index: 层索引, 必须大于等于0
     *
     * @param left: 层叠加的左上角坐标, 对于第0层的话传0
     *
     * @param top: 层叠加的左上角坐标, 对于第0层的话传0
     *
     * @param y_plane: y平面图像数据
     *
     * @param y_offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
     *
     * @param y_row_stride: stride information
     *
     * @param u_plane: u平面图像数据
     *
     * @param u_offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
     *
     * @param u_row_stride: stride information
     *                    *
     * @param v_plane: v平面图像数据
     *
     * @param v_offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
     *
     * @param v_row_stride: stride information
     *
     * @param width: width, 必须大于1, 且必须是偶数
     *
     * @param height: height, 必须大于1, 且必须是偶数
     *
     * @param  is_vertical_flip: 是否垂直翻转, 0不翻转, 1翻转
     *
     * @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
     *
     * @param  scale_width: 缩放宽,必须是偶数, 0或负数不缩放
     *
     * @param  scale_height: 缩放高, 必须是偶数, 0或负数不缩放
     *
     * @param  scale_filter_mode: 缩放质量, 传0使用默认速度,可选等级范围是:[1,3],值越大缩放质量越好, 但速度越慢
     *
     * @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270, 注意:旋转是在缩放, 垂直/水品反转之后再做, 请留意顺序
     *
     * @return {0} if successful
     */
    public native int PostLayerImageI420ByteBuffer(long handle, int index, int left, int top,
                                                   ByteBuffer y_plane, int y_offset, int y_row_stride,
                                                   ByteBuffer u_plane, int u_offset, int u_row_stride,
                                                   ByteBuffer v_plane, int v_offset, int v_row_stride,
                                                   int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                                                   int scale_width,  int scale_height, int scale_filter_mode,
                                                   int rotation_degree);
    /**
     * 投递层I420图像, 详细说明请参考PostLayerImageI420ByteBuffer
     *
     * @return {0} if successful
     */
    public native int PostLayerImageI420ByteArray(long handle, int index, int left, int top,
                                                   byte[] y_plane, int y_offset, int y_row_stride,
                                                   byte[] u_plane, int u_offset, int u_row_stride,
                                                   byte[] v_plane, int v_offset, int v_row_stride,
                                                   int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                                                   int scale_width,  int scale_height, int scale_filter_mode,
                                                   int rotation_degree);
    /**
     * 投递层YUV420888图像, 专门为android.media.Image的android.graphics.ImageFormat.YUV_420_888格式提供的接口
     *
     * @param index: 层索引, 必须大于等于0
     *
     * @param left: 层叠加的左上角坐标, 对于第0层的话传0
     *
     * @param top: 层叠加的左上角坐标, 对于第0层的话传0
     *
     * @param y_plane: 对应android.media.Image.Plane[0].getBuffer()
     *
     * @param y_offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
     *
     * @param y_row_stride: 对应android.media.Image.Plane[0].getRowStride()
     *
     * @param u_plane: android.media.Image.Plane[1].getBuffer()
     *
     * @param u_offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
     *
     * @param u_row_stride: android.media.Image.Plane[1].getRowStride()
     *
     * @param v_plane: 对应android.media.Image.Plane[2].getBuffer()
     *
     * @param v_offset: 图像偏移, 这个主要目的是用来做clip的,一般传0
     *
     * @param v_row_stride: 对应android.media.Image.Plane[2].getRowStride()
     *
     * @param uv_pixel_stride: 对应android.media.Image.Plane[1].getPixelStride()
     *
     * @param width: width, 必须大于1, 且必须是偶数
     *
     * @param height: height, 必须大于1, 且必须是偶数
     *
     * @param  is_vertical_flip: 是否垂直翻转, 0不翻转, 1翻转
     *
     * @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
     *
     * @param  scale_width: 缩放宽,必须是偶数, 0或负数不缩放
     *
     * @param  scale_height: 缩放高, 必须是偶数, 0或负数不缩放
     *
     * @param  scale_filter_mode: 缩放质量, 传0使用默认速度,可选等级范围是:[1,3],值越大缩放质量越好, 但速度越慢
     *
     * @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270, 注意:旋转是在缩放, 垂直/水品反转之后再做, 请留意顺序
     *
     * @return {0} if successful
     */
    public native int PostLayerImageYUV420888ByteBuffer(long handle, int index, int left, int top,
                                                         ByteBuffer y_plane, int y_offset, int y_row_stride,
                                                         ByteBuffer u_plane, int u_offset, int u_row_stride,
                                                         ByteBuffer v_plane, int v_offset, int v_row_stride, int uv_pixel_stride,
                                                         int width, int height, int is_vertical_flip,  int is_horizontal_flip,
                                                         int scale_width,  int scale_height, int scale_filter_mode,
                                                         int rotation_degree);
    /**
     * 传递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);
    /**
     * 传递PCM音频数据给SDK, 每10ms音频数据传入一次
     *
     *  @param pcm_float_array: pcm数据
     *  @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 SmartPublisherOnPCMFloatArray(long handle, float[] pcm_float_array, int offset, int len, int sample_rate, int channel, int per_channel_sample_number);
    /**
     * 请参考SmartPublisherOnPCMFloatArray
     */
    public native int SmartPublisherOnPCMFloatNative(long handle, long pcm_float_data, int offset, int len, int sample_rate, int channel, int per_channel_sample_number);
    /**
     * 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);
    /**
     * 传递PCM混音音频数据给SDK, 每10ms音频数据传入一次
     *
     *  @param stream_index: 当前只能传1, 传其他返回错误
     *  @param pcm_float_array: pcm数据
     *  @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 SmartPublisherOnMixPCMFloatArray(long handle, int stream_index, float[] pcm_float_array, int offset, int len, int sample_rate, int channels, int per_channel_sample_number);
    /*
    * 请参考SmartPublisherOnMixPCMFloatArray
     */
    public native int SmartPublisherOnMixPCMFloatNative(long handle, int stream_index, long pcm_float_data, int offset, int len, int sample_rate, int channels, int per_channel_sample_number);

编码后音视频数据

像前文所说,如无人机等264/HEVC数据,或者本地解析的MP4音视频数据,均可通过实时流的形式,接入到GB28181平台,设计接口如下:

/**
     * 设置编码后视频数据(H.264)
     *
     * @param codec_id, H.264对应 1
     *
     * @param data 编码后的video数据
     *
     * @param size data length
     *
     * @param is_key_frame 是否I帧, if with key frame, please set 1, otherwise, set 0.
     *
     * @param timestamp video timestamp
     *
     * @param pts Presentation Time Stamp, 显示时间戳
     *
     * @return {0} if successful
     */
    public native int SmartPublisherPostVideoEncodedData(long handle, int codec_id, ByteBuffer data, int size, int is_key_frame, long timestamp, long pts);
    /**
     * 设置编码后视频数据(H.264)
     *
     * @param codec_id, H.264对应 1
     *
     * @param data 编码后的video数据
     *
     *@param offset data的偏移
     *
     * @param size data length
     *
     * @param is_key_frame 是否I帧, if with key frame, please set 1, otherwise, set 0.
     *
     * @param timestamp video timestamp
     *
     * @param pts Presentation Time Stamp, 显示时间戳
     *
     * @return {0} if successful
     */
    public native int SmartPublisherPostVideoEncodedDataV2(long handle, int codec_id,
                                                           ByteBuffer data, int offset, int size,
                                                           int is_key_frame, long timestamp, long pts,
                                                           byte[] sps, int sps_len,
                                                           byte[] pps, int pps_len);
    /**
     * 设置编码后视频数据(H.264),如需录制编码后的数据,用此接口,且设置实际宽高
     *
     * @param codec_id, H.264对应 1
     *
     * @param data 编码后的video数据
     *
     *@param offset data的偏移
     *
     * @param size data length
     *
     * @param is_key_frame 是否I帧, if with key frame, please set 1, otherwise, set 0.
     *
     * @param timestamp video timestamp
     *
     * @param pts Presentation Time Stamp, 显示时间戳
     *
     * @param width, height: 编码后视频宽高
     *
     * @return {0} if successful
     */
    public native int SmartPublisherPostVideoEncodedDataV3(long handle, int codec_id,
                                                           ByteBuffer data, int offset, int size,
                                                           int is_key_frame, long timestamp, long pts,
                                                           byte[] sps, int sps_len,
                                                           byte[] pps, int pps_len,
                                                           int width, int height);
    /**
     * 设置音频数据(AAC/PCMA/PCMU/SPEEX)
     *
     * @param codec_id:
     *
     *  NT_MEDIA_CODEC_ID_AUDIO_BASE = 0x10000,
     *   NT_MEDIA_CODEC_ID_PCMA = NT_MEDIA_CODEC_ID_AUDIO_BASE,
     *   NT_MEDIA_CODEC_ID_PCMU,
     *   NT_MEDIA_CODEC_ID_AAC,
     *   NT_MEDIA_CODEC_ID_SPEEX,
     *   NT_MEDIA_CODEC_ID_SPEEX_NB,
     *   NT_MEDIA_CODEC_ID_SPEEX_WB,
     *   NT_MEDIA_CODEC_ID_SPEEX_UWB,
     *
     * @param data audio数据
     *
     * @param size data length
     *
     * @param is_key_frame 是否I帧, if with key frame, please set 1, otherwise, set 0, audio忽略
     *
     * @param timestamp video timestamp
     *
     * @param parameter_info 用于AAC special config信息填充
     *
     * @param parameter_info_size parameter info size
     *
     * @return {0} if successful
     */
    public native int SmartPublisherPostAudioEncodedData(long handle, int codec_id, ByteBuffer data, int size, int is_key_frame, long timestamp,ByteBuffer parameter_info, int parameter_info_size);
    /**
     * 设置音频数据(AAC/PCMA/PCMU/SPEEX)
     *
     * @param codec_id:
     *
     *  NT_MEDIA_CODEC_ID_AUDIO_BASE = 0x10000,
     *   NT_MEDIA_CODEC_ID_PCMA = NT_MEDIA_CODEC_ID_AUDIO_BASE,
     *   NT_MEDIA_CODEC_ID_PCMU,
     *   NT_MEDIA_CODEC_ID_AAC,
     *   NT_MEDIA_CODEC_ID_SPEEX,
     *   NT_MEDIA_CODEC_ID_SPEEX_NB,
     *   NT_MEDIA_CODEC_ID_SPEEX_WB,
     *   NT_MEDIA_CODEC_ID_SPEEX_UWB,
     *
     * @param data audio数据
     *
     * @param offset data的偏移
     *
     * @param size data length
     *
     * @param is_key_frame 是否I帧, if with key frame, please set 1, otherwise, set 0, audio忽略
     *
     * @param timestamp video timestamp
     *
     * @param parameter_info 用于AAC special config信息填充
     *
     * @param parameter_info_size parameter info size
     *
     * @return {0} if successful
     */
    public native int SmartPublisherPostAudioEncodedDataV2(long handle, int codec_id,
                                                           ByteBuffer data, int offset, int size,
                                                           int is_key_frame, long timestamp,
                                                           byte[] parameter_info, int parameter_info_size);
    /**
     * 设置音频数据(AAC/PCMA/PCMU/SPEEX)
     *
     * @param codec_id:
     *
     *  NT_MEDIA_CODEC_ID_AUDIO_BASE = 0x10000,
     *   NT_MEDIA_CODEC_ID_PCMA = NT_MEDIA_CODEC_ID_AUDIO_BASE,
     *   NT_MEDIA_CODEC_ID_PCMU,
     *   NT_MEDIA_CODEC_ID_AAC,
     *   NT_MEDIA_CODEC_ID_SPEEX,
     *   NT_MEDIA_CODEC_ID_SPEEX_NB,
     *   NT_MEDIA_CODEC_ID_SPEEX_WB,
     *   NT_MEDIA_CODEC_ID_SPEEX_UWB,
     *
     * @param data audio数据
     *
     * @param offset data的偏移
     *
     * @param size data length
     *
     * @param is_key_frame 是否I帧, if with key frame, please set 1, otherwise, set 0, audio忽略
     *
     * @param timestamp video timestamp
     *
     * @param parameter_info 用于AAC special config信息填充
     *
     * @param parameter_info_size parameter info size
     *
     * @param sample_rate 采样率,如果需要录像的话必须传正确的值
     *
     *@param channels 通道数, 如果需要录像的话必须传正确的值, 一般是1或者2
     *
     * @return {0} if successful
     */
    public native int SmartPublisherPostAudioEncodedDataV3(long handle, int codec_id,
                                                           ByteBuffer data, int offset, int size,
                                                           int is_key_frame, long timestamp,
                                                           byte[] parameter_info, int parameter_info_size,
                                                           int sample_rate, int channels);

拉取RTSP或RTMP流并接入至GB28181平台

这块我在之前的blog有专门提过,比如其他IPC的RTSP流,可通过Android平台GB28181接入到国标平台。

07a47f6d585f443292b7f25ac932e9da.jpg

这张图很好的展示了这块,当然如果做的更精细的话,还可以把语音对讲和语音广播的也挪过来。


这里简单的说一下具体的实现,其实和之前我们做RTSP转RTMP推送一样,无非就是把RTSP或者RTMP流数据拉下来,然后回调编码后的数据到上层,上层根据GB28181数据格式要求,实现PS打包,然后通过对接GB28181平台信令和数据交互,实时推过去即可。


其中,拉流实现如下:

private boolean StartPull()
  {
    if ( isPulling )
      return false;
    if (!OpenPullHandle())
      return false;
    libPlayer.SmartPlayerSetAudioDataCallback(playerHandle, new PlayerAudioDataCallback());
    libPlayer.SmartPlayerSetVideoDataCallback(playerHandle, new PlayerVideoDataCallback());
    int is_pull_trans_code  = 1;
    libPlayer.SmartPlayerSetPullStreamAudioTranscodeAAC(playerHandle, is_pull_trans_code);
    int startRet = libPlayer.SmartPlayerStartPullStream(playerHandle);
    if (startRet != 0) {
      Log.e(TAG, "Failed to start pull stream!");
      if(!isPlaying && !isRecording && isPushing && !isRTSPPublisherRunning)
      {
        libPlayer.SmartPlayerClose(playerHandle);
        playerHandle = 0;
      }
      return false;
    }
    isPulling = true;
    return true;
  }
  private void StopPull()
  {
    if ( !isPulling )
      return;
    libPlayer.SmartPlayerStopPullStream(playerHandle);
    if ( !isPlaying && !isRecording && !isPushing && !isRTSPPublisherRunning)
    {
      libPlayer.SmartPlayerClose(playerHandle);
      playerHandle = 0;
    }
    isPulling = false;
  }

拉到的音视频数据,投递到GB28181接入模块即可:

class PlayerAudioDataCallback implements NTAudioDataCallback
  {
    private int audio_buffer_size = 0;
    private int param_info_size = 0;
    private ByteBuffer audio_buffer_ = null;
    private ByteBuffer parameter_info_ = null;
    @Override
    public ByteBuffer getAudioByteBuffer(int size)
    {
      //Log.i("getAudioByteBuffer", "size: " + size);
      if( size < 1 )
      {
        return null;
      }
      if ( size <= audio_buffer_size && audio_buffer_ != null )
      {
        return audio_buffer_;
      }
      audio_buffer_size = size + 512;
      audio_buffer_size = (audio_buffer_size+0xf) & (~0xf);
      audio_buffer_ = ByteBuffer.allocateDirect(audio_buffer_size);
      // Log.i("getAudioByteBuffer", "size: " + size + " buffer_size:" + audio_buffer_size);
      return audio_buffer_;
    }
    @Override
    public ByteBuffer getAudioParameterInfo(int size)
    {
      //Log.i("getAudioParameterInfo", "size: " + size);
      if(size < 1)
      {
        return null;
      }
      if ( size <= param_info_size &&  parameter_info_ != null )
      {
        return  parameter_info_;
      }
      param_info_size = size + 32;
      param_info_size = (param_info_size+0xf) & (~0xf);
      parameter_info_ = ByteBuffer.allocateDirect(param_info_size);
      //Log.i("getAudioParameterInfo", "size: " + size + " buffer_size:" + param_info_size);
      return parameter_info_;
    }
    public void onAudioDataCallback(int ret, int audio_codec_id, int sample_size, int is_key_frame, long timestamp, int sample_rate, int channel, int parameter_info_size, long reserve)
    {
      //Log.i("onAudioDataCallback", "ret: " + ret + ", audio_codec_id: " + audio_codec_id + ", sample_size: " + sample_size + ", timestamp: " + timestamp +
      //    ",sample_rate:" + sample_rate);
      if ( audio_buffer_ == null)
        return;
      audio_buffer_.rewind();
      if ( ret == 0 && (isPushing || isRTSPPublisherRunning || isGB28181StreamRunning)) {
        libPublisher.SmartPublisherPostAudioEncodedData(publisherHandle, audio_codec_id, audio_buffer_, sample_size, is_key_frame, timestamp, parameter_info_, parameter_info_size);
      }
      // test
        /*
        byte[] test_buffer = new byte[16];
        pcm_buffer_.get(test_buffer);
        Log.i(TAG, "onGetPcmFrame data:" + bytesToHexString(test_buffer));
        */
    }
  }
  class PlayerVideoDataCallback implements NTVideoDataCallback
  {
    private int video_buffer_size = 0;
    private ByteBuffer video_buffer_ = null;
    @Override
    public ByteBuffer getVideoByteBuffer(int size)
    {
      //Log.i("getVideoByteBuffer", "size: " + size);
      if( size < 1 )
      {
        return null;
      }
      if ( size <= video_buffer_size &&  video_buffer_ != null )
      {
        return  video_buffer_;
      }
      video_buffer_size = size + 1024;
      video_buffer_size = (video_buffer_size+0xf) & (~0xf);
      video_buffer_ = ByteBuffer.allocateDirect(video_buffer_size);
      // Log.i("getVideoByteBuffer", "size: " + size + " buffer_size:" + video_buffer_size);
      return video_buffer_;
    }
    public void onVideoDataCallback(int ret, int video_codec_id, int sample_size, int is_key_frame, long timestamp, int width, int height, long presentation_timestamp)
    {
      //Log.i("onVideoDataCallback", "ret: " + ret + ", video_codec_id: " + video_codec_id + ", sample_size: " + sample_size + ", is_key_frame: "+ is_key_frame +  ", timestamp: " + timestamp +
      //    ",presentation_timestamp:" + presentation_timestamp);
      if ( video_buffer_ == null)
        return;
      video_buffer_.rewind();
      if ( ret == 0 &&  (isPushing || isRTSPPublisherRunning || isGB28181StreamRunning) ) {
        libPublisher.SmartPublisherPostVideoEncodedData(publisherHandle, video_codec_id, video_buffer_, sample_size, is_key_frame, timestamp, presentation_timestamp);
      }
    }
  }

总结

通过以上描述,大家可以看到,GB/T 28181音视频数据源接入,无非就是上述类型,有RTSP或RTMP音视频开发经验的开发者来说,实现GB28181数据接入,基本上可以复用之前的设计。

相关实践学习
基于Hologres轻量实时的高性能OLAP分析
本教程基于GitHub Archive公开数据集,通过DataWorks将GitHub中的项⽬、行为等20多种事件类型数据实时采集至Hologres进行分析,同时使用DataV内置模板,快速搭建实时可视化数据大屏,从开发者、项⽬、编程语⾔等多个维度了解GitHub实时数据变化情况。
阿里云实时数仓实战 - 用户行为数仓搭建
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3&nbsp;)前置知识要求:熟练掌握 SQL 语法熟悉 Linux 命令,对 Hadoop 大数据体系有一定的了解 &nbsp; 课程大纲 第一章&nbsp;了解数据仓库概念 初步了解数据仓库是干什么的 第二章&nbsp;按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章&nbsp;数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章&nbsp;采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章&nbsp;用户行为数据仓库 严格按照企业的标准开发 第六章&nbsp;搭建业务数仓理论基础和对表的分类同步 第七章&nbsp;业务数仓的搭建&nbsp; 业务行为数仓效果图&nbsp;&nbsp;
相关文章
|
9月前
|
监控 Android开发 数据安全/隐私保护
批量发送短信的平台,安卓群发短信工具插件脚本,批量群发短信软件【autojs版】
这个Auto.js脚本实现了完整的批量短信发送功能,包含联系人管理、短信内容编辑、发送状态监控等功能
|
存储 编解码 监控
Android平台GB28181执法记录仪技术方案与实现
本文介绍了大牛直播SDK的SmartGBD在执法记录仪场景中的应用。GB28181协议作为视频监控联网的国家标准,为设备互联互通提供规范。SmartGBD专为Android平台设计,支持音视频采集、编码与传输,具备自适应算法和多功能扩展优势。文章分析了执法记录仪的需求,如实时音视频传输、设备管理及数据安全,并详细阐述了基于SmartGBD的技术实现方案,包括环境准备、SDK集成、设备注册、音视频处理及功能扩展等步骤。最后展望了SmartGBD在未来智慧物联领域的广阔应用前景。
781 13
|
存储 编解码 开发工具
Android平台毫秒级低延迟HTTP-FLV直播播放器技术探究与实现
本文详细探讨了在Android平台上实现HTTP-FLV播放器的过程。首先介绍了FLV格式的基础,包括文件头和标签结构。接着分析了HTTP-FLV传输原理,通过分块传输实现流畅播放。然后重点讲解了播放器的实现步骤,涵盖网络请求、数据解析、音视频解码与渲染,以及播放控制功能的设计。文章还讨论了性能优化和网络异常处理的方法,并总结了HTTP-FLV播放器的技术价值,尤其是在特定场景下的应用意义。
694 11
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
IDE 开发工具 Android开发
移动应用开发之旅:探索Android和iOS平台
在这篇文章中,我们将深入探讨移动应用开发的两个主要平台——Android和iOS。我们将了解它们的操作系统、开发环境和工具,并通过代码示例展示如何在这两个平台上创建一个简单的“Hello World”应用。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和技巧,帮助你更好地理解和掌握移动应用开发。
374 17
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
422 3
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
770 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
存储 编解码 Android开发
【Android FFMPEG 开发】FFMPEG 读取音视频流中的数据到 AVPacket ( 初始化 AVPacket 数据 | 读取 AVPacket )
【Android FFMPEG 开发】FFMPEG 读取音视频流中的数据到 AVPacket ( 初始化 AVPacket 数据 | 读取 AVPacket )
363 0
|
Android开发
【Android FFMPEG 开发】FFMPEG 初始化 ( 网络初始化 | 打开音视频 | 查找音视频流 )
【Android FFMPEG 开发】FFMPEG 初始化 ( 网络初始化 | 打开音视频 | 查找音视频流 )
527 0

热门文章

最新文章