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接入到国标平台。

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

这里简单的说一下具体的实现,其实和之前我们做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;@Overridepublic 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_;}@Overridepublic 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;@Overridepublic 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数据接入,基本上可以复用之前的设计。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/552974.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

搜狗高速浏览器怎么设置页面字体 设置方法介绍

搜狗高速浏览器是由搜狗公司开发的一款浏览器应用&#xff0c;我们在使用电脑或者手机等设备时都是离不开浏览器应用的&#xff0c;并且在很多浏览器中有的功能都是可以根据用户的使用习惯和喜好来设置的&#xff0c;就比如页面字体&#xff0c;所以小编今天就来跟大家分享一下…

C++学习之-析构函数必须为虚函数吗?

今天讨论个比较有意思的话题&#xff1a;析构函数是不是必须要为虚函数&#xff1f; 先说答案&#xff1a; 析构函数可以是虚函数&#xff0c;也可以不是虚函数。 再说原因&#xff1a; 析构函数为虚函数的情况&#xff1a;继承 当父类指针释放子类对象时&#xff0c;如果…

如何实现RTMP或RTSP播放端回调YUV/RGB数据?

今天某乎收到个问题推荐&#xff0c;如何实现RTSP回调YUV数据&#xff0c;用于二次处理&#xff1f; 正好前些年我们做RTSP和RTMP直播播放的时候&#xff0c;实现过相关的需求&#xff0c;本文就以Android为例&#xff0c;大概说说具体实现吧。 先说回调yuv或rgb这块意义吧&a…

Win7系统打印机删除不掉的解决方法

在Win7系统下&#xff0c;如果想要把安装的打印机删除&#xff0c;通常会在设备和打印机里删除打印机图标&#xff0c;但是一些用户反馈&#xff0c;用户在删除了打印机之后&#xff0c;只要一刷新打印机又会重新出现&#xff0c;感觉是删除不了&#xff0c;那么Win7系统打印机…

GB/T28181-2016传输要求和Android平台设备接入技术实现

相关协议规范 GB/T28181-2016公共安全视频监控联网系统 信息传输、交换、控制技术要求相关的传输要求如下&#xff1a; 5.1 网络传输协议要求 联网系统网络层应支持IP协议,传输层应支持 TCP和 UDP协议。 5.2 媒体传输协议要求 视音频流在基于IP的网络上传输时应支持 RTP/R…

无法打开Win11系统小组件怎么办

Win11操作系统也推出一段时间了&#xff0c;不少小伙都有下载体验&#xff0c;Win11与之前的Win10比较起来改动非常大&#xff0c;小组件是Win11系统中全新添加的功能&#xff0c;他类似于Win10最新的加入的兴趣模块&#xff0c;但是有朋友遇到了小组件无法打开的情况这是怎么回…

GB28181控制、传输流程和协议接口之注册|注销和技术实现

注册和注销基本要求 SIP客户端、网关、SIP设备、联网系统等 SIP代理(SIP UA)使用IETFRFC3261中定义的方法 15 GB/T28181—2016Register进行注册和注销。 注册和注销时应进行认证&#xff0c;认证方式应支持数字摘要认证方式&#xff0c;高安全级别的宜支持数字证书的认证方式&…

Edge浏览器网页怎么收藏 Edge浏览器网页收藏图文教程

Edge浏览器是微软最新推出的网页浏览工具。而现在有很多Edge浏览器新用户可能对它不是很了解&#xff0c;在使用过程中会出现小问题。今天小编就为大家解答Edge浏览器网页怎么收藏&#xff0c;一起来看教程吧! Edge浏览器网页收藏图文教程 一、怎么收藏网页? 1、打开Edge浏…

GB28181状态信息报送解读及Android端国标设备接入技术实现

今天主要聊聊GB/T28181状态信息报送这块&#xff0c;先回顾下协议规范相关细节&#xff0c;然后再针对代码实现&#xff0c;做个简单的说明。 状态消息报送基本要求 当源设备(包括网关、SIP设备、SIP客户端或联网系统)发现工作异常时,应立即向本 SIP监控域 的SIP服务器发送状…

IE浏览器怎么设置兼容性 添加兼容站点方法

IE浏览器是我们工作和生活中应用最广泛的浏览器&#xff0c;其安全、便捷是它的特点之一。不过这个浏览器在浏览部分网页的时候&#xff0c;会出现图片不刷新的情况&#xff0c;今天小编就带来了解决方法&#xff0c;告诉大家IE浏览器怎么设置兼容性。 1、首先点击IE浏览器右上…

GB28181设备接入端如何实现校时?

在探讨这个问题之前&#xff0c;我们先看看GB/T28181-2016官方文档怎么说的&#xff0c;9.10.1章节校时基本要求提到&#xff1a; 联网内设备支持基于SIP方式或 NTP方式的网络校时功能&#xff0c;标准时间为北京时间。 SIP方式校时见本节具体描述&#xff1b;NTP(见IETFRFC2…

Win7运行窗口的打开方法

Win7系统中运行窗口可谓是最常用的功能之一&#xff0c;可以帮助我们快速执行程序&#xff0c;在系统有问题时经常运用其协助解决。有用户问到运行窗口在哪?如何打开?找不到怎么办?其实方法不难&#xff0c;下面小编就跟大家详细介绍一下Win7运行窗口的打开方法。 Win7运行…

如何在Unity下采集音视频实现轻量级RTSP服务(类似于IPC)

好多开发者在做虚拟仿真、VR教育等场景的时候&#xff0c;遇到个问题&#xff0c;想把头显里面的画面在内网环境下低延迟的同步出来&#xff0c;又不想单独部署流媒体服务器。为此&#xff0c;我们在Unity下&#xff0c;添加了轻量级RTSP服务模块&#xff0c;通过头显端启动个轻…

【Datawhale 大模型基础】第十一章 环境影响

第十一章 环境影响 This blog is based on datawhale files and a paper. The initial consideration revolves around the potential positive or negative direct impact on the environment. Other transformative technological advancements, like the metaverse, are li…

Win7笔记本如何调整屏幕亮度

长期使用电脑的时候会因为视觉疲劳感觉屏幕亮度过高&#xff0c;需要对其调整来缓解。PC用户方法很简单&#xff0c;只需在显示器上点击按钮进行调整即可&#xff0c;那么Win7笔记本如何调整屏幕亮度?其实Win7系统本身有考虑到这个问题&#xff0c;在系统中有专门针对此问题的…

Android GB28181接入端实时位置订阅和上报之-如何获取当前经纬度

我们在做Android平台GB28181的时候&#xff0c;其中实时位置(MobilePosition)订阅和上报这块&#xff0c;涉及到实时经纬度的获取&#xff0c;特别是执法记录、车载系统的那个等场景&#xff0c;几乎就是标配。 今天主要是分享一段实时获取位置的代码&#xff1a; /** Camera…

Win7系统防火墙设置不了怎么办

防火墙是Windows系统中一项重要的防护措施&#xff0c;可以帮助你的电脑阻挡病毒和恶意软件&#xff0c;确保系统安全。近来有用户反馈win7系统的防火墙无法设置&#xff0c;Win7系统防火墙设置不了怎么办?无法设置说明系统设置被更改&#xff0c;防火墙功能应该是被禁用了&am…

如何实现Android平台GB28181设备对接Camera2数据

技术背景 在写如何实现Android平台GB28181设备对接Camera2数据说明之前&#xff0c;我在前两年的blog就有针对camera2的RTMP直播推送模块做过技术分享&#xff1a; 在Google 推出Android 5.0的时候, Android Camera API 版本升级到了API2(android.hardware.camera2), 之前使用…

Win7性能信息和工具在哪打开

在Win7系统中&#xff0c;有一个性能信息和工具&#xff0c;我们可以通过这个功能中的高级工具&#xff0c;查看到关于系统的关键信息&#xff0c;全面了解系统的运行状况&#xff0c;不过&#xff0c;对于不熟悉电脑的用户来讲&#xff0c;可能连性能信息和工具在哪都不清楚&a…

Android平台实现mp4文件实时推送RTMP|轻量级RTSP服务|GB28181平台

好多开发者有这样的诉求&#xff0c;想把本地录制的MP4文件&#xff0c;以实时流数据的形式&#xff0c;推送到RTMP服务器&#xff0c;注入轻量级RTSP服务&#xff0c;或者对接到GB28181平台&#xff0c;这块前几年我们就有对接。 本次以MediaExtractor为例&#xff0c;先利用…