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