Android native层实现MediaCodec编码H264/HEVC

简介: Android平台在上层实现mediacodec的编码,资料泛滥,已经不再是难事,今天给大家介绍下,如何在Android native层实现MediaCodec编码H264/HEVC,网上千篇一律的接口说明,这里不再赘述,本文主要介绍下,一些需要注意的点,权当抛砖引玉,相关设计界面如下:

Android平台在上层实现mediacodec的编码,资料泛滥,已经不再是难事,今天给大家介绍下,如何在Android native层实现MediaCodec编码H264/HEVC,网上千篇一律的接口说明,这里不再赘述,本文主要介绍下,一些需要注意的点,权当抛砖引玉,相关设计界面如下:

c7f3b1fd196142558f88c9b2b238291b.jpg

问题1:有了上层MediaCodec编码方案,为什么还要开发Native层解决方案?


回答:由于我们的数据流向是编码前YV12/NV21/NV12/I420/RGB24/RGBA32/RGB565等数据类型,底层统一处理后,实现H264、HEVC的编码,减少了上下层之间的交互,效率更高,支持的编码前video数据接口设计如下:

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

问题2:Android Native层MediaCodec编码,从什么版本开始支持的,支持什么架构?


回答:从5.0开始,armv8,如果像我们一样,想支持armv7也未尝不可,需要底层动态加载lib so,然后接口再做一层封装即可,设置MediaCodec Native硬编码时,底层需要判断下系统版本,相关设计接口如下:

/**
   * 设置视频硬编码是否使用 Native Media NDK, 默认是不使用, 安卓5.0以下设备不支持
   * @param handle
   * @param is_native: 0表示不使用, 1表示使用, sdk默认是0.
   * @return {0} if successful
   */
  public native int SetNativeMediaNDK(long handle, int is_native);

问题3:看了下MediaCodec的接口,底层接口好像不像上层的那么全,是不是会导致编码效果大打折扣?


回答:MediaCodec的native接口的调用,确实不如上层的那么方便,比如,判断系统是否支持特定编码类型硬编或支持的color format等信息,可以采用上下层结合的形式。


问题4:底层如何判断关键帧?


回答:和上层一样,参考以下代码:

bool is_key_frame = info.flags & AMEDIACODEC_BUFFER_FLAG_KEY_FRAME;

问题5:如何获取codec config?


回答:和上层类似,参考以下代码:

if (info.flags & AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG) {
  config_info.clear();
  config_info.insert(config_info_.end(), output_buffer + info.offset, output_buffer + info.offset + info.size);
}

问题6:创建MediaFormat有什么特别之处吗?


回答:没啥特别之处,设置下如mine_type、width、height,编码码率、fps、关键帧间隔等信息即可。


问题7:编码过程中,比如发生横竖屏切换等,导致分辨率变化怎么办?


回答:重启encoder即可。


问题8:我想比较下到底native层编码效率高,还是上层高?


回答:可以快速写代码尝试,也可私信我,试试我们的,从我们测试来看,由于本身我们上层调用的,也做的非常优异了,native层相对来说,更多地是调用效率的提高,后续扩展更方便。


问题9:Android Native层编码后的数据,可以用在什么场景下?


回答:编码后的H264、HEVC数据,按照协议栈要求,用于需要视频传输的场景都可以,比如RTMP推送、GB28181设备接入,轻量级RTSP服务,甚至私有协议传输都OK。

相关文章
|
7月前
|
开发工具 Android开发 开发者
Android如何回调编码后的音视频数据
有开发者提到,在RTMP推送端的基础上,希望能回调编码后的音视频数据,便于开发者对接第三方系统,如GB28181.
|
7月前
|
编解码 Android开发 数据安全/隐私保护
Android平台外部编码数据(H264/H265/AAC/PCMA/PCMU)实时预览播放技术实现
好多开发者可能疑惑,外部数据实时预览播放,到底有什么用? 是的,一般场景是用不到的,我们在开发这块前几年已经开发了非常稳定的RTMP、RTSP直播播放模块,不过也遇到这样的场景,部分设备输出编码后(视频:H.264/H.265,音频:AAC/PCMA/PCMU)的数据,比如无人机或部分智能硬件设备,回调出来的H.264/H.265数据,除了想转推到RTMP、轻量级RTSP服务或GB28181外,还需要本地预览甚至对数据做二次处理(视频分析、实时水印字符叠加等,然后二次编码),基于这样的场景诉求,我们开发了Android平台外部编码数据实时预览播放模块。
|
8月前
|
编解码 开发工具 Android开发
Android平台如何实现第三方模块编码后(H.264/H.265/AAC/PCMA/PCMU)数据实时预览播放
Android平台如何实现第三方模块编码后(H.264/H.265/AAC/PCMA/PCMU)数据实时预览播放
|
7月前
|
编解码 Android开发 开发者
Android平台GB28181设备接入模块如何实现实时视频和本地录像双码流编码
我们在做Android平台GB28181设备接入模块的时候,遇到这样的场景,比如执法记录仪或智慧工地等场景下,由于GB28181设备接入模块,注册到国标平台后,平时只是心跳保持,或还有实时位置订阅,查看视频的时候,是按需看,而且有时候,网络环境并不是太好,所以,催生了这样一个诉求:部分开发者希望能本地录像的时候,录制高分辨率(比如1920*1080),国标平台侧发起实时视频查看请求的时候,上传低分辨率(如1280*720)数据,有点类似于IPC的主码流和子码流。
|
7月前
|
编解码 Android开发 数据安全/隐私保护
Android平台如何实现外部编码后(H.264/H.265)数据实时预览播放
我们在对接开发者的时候,遇到这样的诉求:除了正常的RTMP、RTSP直播播放外,有些硬件设备输出编码后(H.264/H.265)的数据,比如无人机或类似硬件产品,回调出来的H.264/H.265数据,除了正常转推到RTMP、轻量级RTSP服务或GB28181外,还需要本地预览甚至重新对数据做二次处理,基于这样的场景诉求,我们开发了外部编码后数据实时预览播放模块。
|
7月前
|
编解码 监控 网络协议
Android平台GB28181设备接入侧(编码前|编码后|RTSP|RTMP)支持功能浅析
在之前,我有写过Android平台GB28181设备接入模块的好多blog,包括参数设置、功能支持与扩展等,以数据接入为例,支持的数据类型涉及编码前、编码后或直接流数据(RTSP或RTMP流)。可用于如智能监控、智慧零售、智慧教育、远程办公、生产运输、智慧交通、车载或执法记录仪等场景。
118 0
|
7月前
|
编解码 Android开发 数据安全/隐私保护
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接入到国标平台)。
|
7月前
|
数据采集 编解码 开发工具
Android平台RTMP推送模块如何对接NV21、YV12、RGB、YUV等编码前数据
我们在对接Android平台摄像头或者屏幕采集、编码打包推送场景的时候,随着采集设备的不同,出来的数据也是多样化的,比如NV21、YV12、RGB、YUV等,更有图像数据甚至是翻转或者倒置的,如果上层处理,效率低下,本篇文章主要介绍下常用的编码前数据接口。相关资料或版本测试,也可联系大牛直播SDK(官方)
|
7月前
|
开发工具 Android开发 开发者
Android平台RTMP推流或轻量级RTSP服务(摄像头或同屏)编码前数据接入类型总结
很多开发者在做Android平台RTMP推流或轻量级RTSP服务(摄像头或同屏)时,总感觉接口不够用,以大牛直播SDK为例 (Github) 我们来总结下,我们常规需要支持的编码前音视频数据有哪些类型:
|
8月前
|
编解码 前端开发 Android开发
Android平台GB28181设备接入模块之按需编码和双码流编码
Android平台GB28181设备接入模块之按需编码和双码流编码