如何实现RTMP推送Android Camera2数据

简介: 在Google 推出Android 5.0的时候, Android Camera API 版本升级到了API2(android.hardware.camera2), 之前使用的API1(android.hardware.camera)就被标为 Deprecated 了。

Camera2简介

在Google 推出Android 5.0的时候, Android Camera API 版本升级到了API2(android.hardware.camera2), 之前使用的API1(android.hardware.camera)就被标为 Deprecated 了。


Camera API2相较于API1有很大不同, 并且API2是为了配合HAL3进行使用的, API2有很多API1不支持的特性, 比如:

  1. 更先进的API架构;
  2. 可以获取更多的帧(预览/拍照)信息以及手动控制每一帧的参数;
  3. 对Camera的控制更加完全(比如支持调整focus distance, 剪裁预览/拍照图片);
  4. 支持更多图片格式(yuv/raw)以及高速连拍等。


在API架构方面, Camera2和之前的Camera有很大区别, APP和底层Camera之前可以想象成用管道方式连接, 如下图:


aHR0cHM6Ly93aWtpLmppa2V4dWV5dWFuLmNvbS9wcm9qZWN0L2FuZHJvaWQtYWN0dWFsLWNvbWJhdC1za2lsbHMvaW1hZ2VzLzMzLTEucG5n.png

这里引用了管道的概念将安卓设备和摄像头之间联通起来,系统向摄像头发送 Capture 请求,而摄像头会返回 CameraMetadata。这一切建立在一个叫作 CameraCaptureSession 的会话中。


下面是 camera2包中的主要类:

aHR0cHM6Ly93aWtpLmppa2V4dWV5dWFuLmNvbS9wcm9qZWN0L2FuZHJvaWQtYWN0dWFsLWNvbWJhdC1za2lsbHMvaW1hZ2VzLzMzLTIucG5n.png

其中 CameraManager 是那个站在高处统管所有摄像投设备(CameraDevice)的管理者,而每个 CameraDevice 自己会负责建立 CameraCaptureSession 以及建立 CaptureRequest。


CameraCharacteristics 是 CameraDevice 的属性描述类,非要做个对比的话,那么它与原来的 CameraInfo 有相似性。

Camera2 API调用基础流程:

  1. 通过context.getSystemService(Context.CAMERA_SERVICE) 获取CameraManager;
  2. 调用CameraManager .open()方法在回调中得到CameraDevice;
  3. 通过CameraDevice.createCaptureSession() 在回调中获取CameraCaptureSession;
  4. 构建CaptureRequest, 有三种模式可选 预览/拍照/录像.;
  5. 通过 CameraCaptureSession发送CaptureRequest, capture表示只发一次请求, setRepeatingRequest表示不断发送请求;
  6. 拍照数据可以在ImageReader.OnImageAvailableListener回调中获取, CaptureCallback中则可获取拍照实际的参数和Camera当前状态。

获取数据后对接RTMP推送:

通过OnImageAvailableListenerImpl 获取到原始数据,推送端以大牛直播SDK https://github.com/daniulive/SmarterStreaming/ 的万能推送接口为例,获取数据后,调用SmartPublisherOnImageYUV420888() 完成数据传送,底层进行二次处理后,编码后传输即可。


接口描述:

  /*
  *  专门为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);
    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调用流程,感兴趣的可以自行学习。

相关文章
|
26天前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
105 4
|
4月前
|
开发工具 Android开发 开发者
Android平台如何不推RTMP|不发布RTSP流|不实时录像|不回传GB28181数据时实时快照?
本文介绍了一种在Android平台上实现实时截图快照的方法,尤其适用于无需依赖系统接口的情况,如在RTMP推送、RTSP服务或GB28181设备接入等场景下进行截图。通过底层模块(libSmartPublisher.so)实现了截图功能,封装了`SnapShotImpl.java`类来管理截图流程。此外,提供了关键代码片段展示初始化SDK实例、执行截图、以及在Activity销毁时释放资源的过程。此方案还考虑到了快照数据的灵活处理需求,符合GB/T28181-2022的技术规范。对于寻求更灵活快照机制的开发者来说,这是一个值得参考的设计思路。
|
2月前
|
存储 大数据 数据库
Android经典面试题之Intent传递数据大小为什么限制是1M?
在 Android 中,使用 Intent 传递数据时存在约 1MB 的大小限制,这是由于 Binder 机制的事务缓冲区限制、Intent 的设计初衷以及内存消耗和性能问题所致。推荐使用文件存储、SharedPreferences、数据库存储或 ContentProvider 等方式传递大数据。
88 0
|
3月前
|
Web App开发 网络协议 Android开发
Android平台一对一音视频通话方案大比拼:WebRTC VS RTMP VS RTSP,谁才是王者?
【9月更文挑战第4天】本文详细对比了在Android平台上实现一对一音视频通话时常用的WebRTC、RTMP及RTSP三种技术方案。从技术原理、性能表现与开发难度等方面进行了深入分析,并提供了示例代码。WebRTC适合追求低延迟和高质量的场景,但开发成本较高;RTMP和RTSP则在简化开发流程的同时仍能保持较好的传输效果,适用于不同需求的应用场景。
187 1
|
3月前
|
安全 API 开发工具
Android平台RTMP推送|轻量级RTSP服务如何实现麦克风|扬声器声音采集切换
Android平台扬声器播放声音的采集,在无纸化同屏等场景下,意义很大,早期低版本的Android设备,是没法直接采集扬声器audio的(从Android 10开始支持),所以,如果需要采集扬声器audio,需要先做系统版本判断,添加相应的权限。
|
3月前
|
编解码 开发工具 Android开发
Android平台实现屏幕录制(屏幕投影)|音频播放采集|麦克风采集并推送RTMP或轻量级RTSP服务
Android平台屏幕采集、音频播放声音采集、麦克风采集编码打包推送到RTMP和轻量级RTSP服务的相关技术实现,做成高稳定低延迟的同屏系统,还需要有配套好的RTMP、RTSP直播播放器
|
4月前
|
JSON Java Android开发
Android 开发者必备秘籍:轻松攻克 JSON 格式数据解析难题,让你的应用更出色!
【8月更文挑战第18天】在Android开发中,解析JSON数据至关重要。JSON以其简洁和易读成为首选的数据交换格式。开发者可通过多种途径解析JSON,如使用内置的`JSONObject`和`JSONArray`类直接操作数据,或借助Google提供的Gson库将JSON自动映射为Java对象。无论哪种方法,正确解析JSON都是实现高效应用的关键,能帮助开发者处理网络请求返回的数据,并将其展示给用户,从而提升应用的功能性和用户体验。
110 1
|
4月前
|
编解码 网络协议 开发工具
Android平台如何实现多路低延迟RTSP|RTMP播放?
本文档详细介绍了大牛直播SDK在Android平台上实现RTSP与RTMP流媒体播放及录像功能的技术细节。早在2015年,SDK的第一版就已经支持了多实例播放,并且通过简单的实例封装就能轻松实现。文档中提供了代码示例,展示了如何开启播放、停止播放以及开始和停止录像等功能。此外,SDK还提供了丰富的配置选项,例如设置录像目录、文件大小限制、转码选项等。总结部分列出了该SDK的关键特性,包括但不限于高稳定性和低延迟的播放能力、多实例支持、事件回调、硬解码支持、网络状态监控以及复杂的网络环境处理等。这些功能使得SDK能够应对各种应用场景,特别是在对延迟和稳定性有极高要求的情况下表现优异。
103 5
|
4月前
|
图形学 Android开发 iOS开发
穿越数字洪流,揭秘Unity3d中的视频魔法!Windows、Android和iOS如何征服RTSP与RTMP的终极指南!
【8月更文挑战第15天】在数字媒体的海洋中,实时视频流是连接世界的桥梁。对于那些渴望在Unity3d中搭建这座桥梁的开发者来说,本文将揭示如何在Windows、Android和iOS平台上征服RTSP与RTMP的秘密。我们将深入探讨这两种协议的特性,以及在不同平台上实现流畅播放的技巧。无论你是追求稳定性的RTSP拥趸,还是低延迟的RTMP忠实粉丝,这里都有你需要的答案。让我们一起穿越数字洪流,探索Unity3d中视频魔法的世界吧!
75 2
|
4月前
|
编解码 网络协议 vr&ar
Android平台下VR头显如何低延迟播放4K以上超高分辨率RTSP|RTMP流
这段内容讲述了VR头显中实现高分辨率视频播放的技术背景与实现方法,并强调了其重要性。高分辨率对于提升VR体验至关重要,它能提供更清晰的画面、增强沉浸感、补偿透镜放大效应,并维持宽广视场角下的图像质量。文中提到的大牛直播SDK具备极低的延迟(200-400ms),支持多种协议与格式,并具有丰富的功能特性,如多实例播放、事件回调、视频及音频格式支持等。此外,提供了基于Unity的播放器示例代码,展示了如何配置播放参数并开始播放。最后,作者指出此类技术在远程控制、虚拟仿真等应用场景中的重要意义。