一身转战三千里,一剑曾百万师。这篇文章主要讲述如何实现RTMP推送Android Camera2数据相关的知识,希望能为你提供帮助。
Camera2简介
【如何实现RTMP推送Android Camera2数据】在Google 推出android 5.0的时候, Android Camera API 版本升级到了API2(android.hardware.camera2), 之前使用的API1(android.hardware.camera)就被标为 Deprecated 了。
Camera API2相较于API1有很大不同, 并且API2是为了配合HAL3进行使用的, API2有很多API1不支持的特性, 比如:
- 更先进的API架构;
- 可以获取更多的帧(预览/拍照)信息以及手动控制每一帧的参数;
- 对Camera的控制更加完全(比如支持调整focus distance, 剪裁预览/拍照图片);
- 支持更多图片格式(yuv/raw)以及高速连拍等。
文章图片
文章图片
?
这里引用了管道的概念将安卓设备和摄像头之间联通起来,系统向摄像头发送 Capture 请求,而摄像头会返回 CameraMetadata。这一切建立在一个叫作 CameraCaptureSession 的会话中。
下面是 camera2包中的主要类:
文章图片
文章图片
?
其中 CameraManager 是那个站在高处统管所有摄像投设备(CameraDevice)的管理者,而每个 CameraDevice 自己会负责建立 CameraCaptureSession 以及建立 CaptureRequest。
CameraCharacteristics 是 CameraDevice 的属性描述类,非要做个对比的话,那么它与原来的 CameraInfo 有相似性。
Camera2 API调用基础流程:
- 通过context.getSystemService(Context.CAMERA_SERVICE) 获取CameraManager;
- 调用CameraManager .open()方法在回调中得到CameraDevice;
- 通过CameraDevice.createCaptureSession() 在回调中获取CameraCaptureSession;
- 构建CaptureRequest, 有三种模式可选 预览/拍照/录像.;
- 通过 CameraCaptureSession发送CaptureRequest, capture表示只发一次请求, setRepeatingRequest表示不断发送请求;
- 拍照数据可以在ImageReader.OnImageAvailableListener回调中获取, CaptureCallback中则可获取拍照实际的参数和Camera当前状态。
通过OnImageAvailableListenerImpl 获取到原始数据,推送端以大牛直播SDK https://github.com/daniulive/SmarterStreaming/ 的万能推送接口为例,获取数据后,调用SmartPublisherOnImageYUV420888() 完成数据传送,底层进行二次处理后,编码后传输即可。
接口描述:
/*
*专门为android.media.Image的android.graphics.ImageFormat.YUV_420_888格式提供的接口
*
* @paramwidth: 必须是8的倍数
*
* @paramheight: 必须是8的倍数
*
* @paramcrop_left: 剪切左上角水平坐标, 一般根据android.media.Image.getCropRect() 填充
*
* @paramcrop_top: 剪切左上角垂直坐标, 一般根据android.media.Image.getCropRect() 填充
*
* @paramcrop_width: 必须是8的倍数, 填0将忽略这个参数, 一般根据android.media.Image.getCropRect() 填充
*
* @paramcrop_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()
*
* @paramrotation_degree: 顺时针旋转, 必须是0, 90, 180, 270
*
* @paramis_vertical_flip: 是否垂直翻转, 0不翻转, 1翻转
*
* @paramis_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
*
* @paramscale_width: 缩放宽,必须是8的倍数, 0不缩放
*
* @paramscale_height: 缩放高, 必须是8的倍数, 0不缩放
*
* @paramscale_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);
文章图片
private class OnImageAvailableListenerImpl implements ImageReader.OnImageAvailableListener {@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireLatestImage();
if ( image != null )
{
if ( camera2Listener != null )
{
camera2Listener.onCameraImageData(image);
}image.close();
}
}
}
文章图片
@Override
public void onCameraImageData(Image image) {synchronized(this)
{
Rect crop_rect = image.getCropRect();
if(isPushingRtmp || isRTSPPublisherRunning) {
if(libPublisher != null)
{
Image.Plane[] planes = image.getPlanes();
//crop_rect.left, crop_rect.top, crop_rect.width(), crop_rect.height(),
//这里缩放宽高可以填0,使用原视视频宽高都可以的
libPublisher. SmartPublisherOnImageYUV420888(publisherHandle, image.getWidth(), image.getHeight(),
crop_rect.left, crop_rect.top, crop_rect.width(), crop_rect.height(),
planes[0].getBuffer(), planes[0].getRowStride(),
planes[1].getBuffer(), planes[2].getBuffer(), planes[1].getRowStride(), planes[1].getPixelStride(),
displayOrientation, 0, 0,
videoWidth, videoHeight, 1);
}
}
}
}
文章图片
以上就是基础的Android Camera2介绍,和RTMP调用流程,感兴趣的可以自行学习。
推荐阅读
- AppScan扫描教程
- 第一轮铁大树洞APP开发冲刺
- 耗时 2 年,用 8.5 万块乐高积木最牛复刻 Apple Park
- There's more to life than being happy
- 在 Reface.AppStarter 中使用事件总线
- 安卓逆向11.IDA以Debug模式调试APK SO
- PO设计模式在Appium中的应用——框架内容的补充
- unia-app页面声明周期
- RStudio IDE安装详细步骤(图解)