自定义采集和渲染

最近更新时间:2021-05-11 18:33:58

定制推流画面

iOS 平台

研发实力不俗的客户,会有自定义图像处理的需求(例如堆加字幕),同时又希望复用 RTMP SDK 的整体流程,如果是这样,您可以按照如下攻略进行定制。

  1. 设置视频处理回调
    设置 TXLivePushvideoProcessDelegate 代理点,即可实现对视频画面的定制。

    @protocol TXVideoCustomProcessDelegate

    /**
    * 在OpenGL线程中回调,在这里可以进行采集图像的二次处理
    * @param textureId 纹理 ID
    * @param width 纹理的宽度
    * @param height 纹理的高度
    * @return 返回给 SDK 的纹理
    * 说明:SDK回调出来的纹理类型是 GL_TEXTURE_2D,接口返回给SDK的纹理类型也必须是 GL_TEXTURE_2D
    */

    -(GLuint)onPreProcessTexture:(GLuint)texture width:(CGFloat)width height:(CGFloat)height;

    /**
    * 在OpenGL线程中回调,可以在这里释放创建的OpenGL资源
    */

    -(void)onTextureDestoryed;

    @end

  2. 在回调函数中对视频数据进行加工
    实现 TXVideoCustomProcessDelegate 的 onPreProcessTexture 函数,以实现对视频画面的自定义处理。textureId 指定的纹理是一块类型为 GLES20.GL_TEXTURE_2D 的纹理。

    对于 texture 数据的操作,需要一定的 OpenGL 基础知识,另外计算量不宜太大,因为 onPreProcessTexture 的调用频率跟 FPS 相同,过于繁重的处理很容易造成 GPU 过热。

Android 平台

研发实力不俗的客户,会有自定义图像处理的需求(例如堆加字幕),同时又希望复用 RTMP SDK 的整体流程,如果是这样,您可以按照如下攻略进行定制。

  1. 设置视频处理回调
    设置 TXLivePushsetVideoProcessListener 自定义视频回调,即可实现对视频画面的定制。

    public interface VideoCustomProcessListener {
        /**
        * 在 OpenGL 线程中回调,在这里可以进行采集图像的二次处理
        *
        * @param textureId 纹理 ID
        * @param width     纹理的宽度
        * @param height    纹理的高度
        * @return 返回给 SDK 的纹理 ID,如果不做任何处理,返回传入的纹理 ID 即可
        * <p>
        * 说明:SDK 回调出来的纹理类型是 GLES20.GL_TEXTURE_2D,接口返回给 SDK 的纹理类型也必须是 GLES20.GL_TEXTURE_2D
        */
        int onTextureCustomProcess(int textureId, int width, int height);
    
        /**
         * 增值版回调人脸坐标
        *
        * @param points 归一化人脸坐标,每两个值表示某点 P 的 X,Y 值。值域[0.f,1.f]
        */
        void onDetectFacePoints(float[] points);
    
        /**
        * 在 OpenGL 线程中回调,可以在这里释放创建的 OpenGL 资源
        */
        void onTextureDestoryed();
    }

  2. 在回调函数中对视频数据进行加工
    实现 VideoCustomProcessListener 的 onTextureCustomProcess 函数,以实现对视频画面的自定义处理。textureId 指定的纹理是一块类型为 GLES20.GL_TEXTURE_2D 的纹理。

    对于 texture 数据的操作,需要一定的 OpenGL 基础知识,另外计算量不宜太大,因为 onTextureCustomProcess 的调用频率跟 FPS 相同,过于繁重的处理很容易造成 GPU 过热。

定制播放数据

iOS 平台

  1. 设置 TXLivePlayer 的 TXVideoCustomProcessDelegate 属性
    @interface TXLivePlayer : NSObject
    // 设置之后,Player 的每帧画面都会经过 onPlayerPixelBuffer
    @property(nonatomic, weak) id videoProcessDelegate;
  2. 通过 onPlayerPixelBuffer 回调捕获 Player 的图像数据。
    如果当前 Player 是硬解码模式,pixelBuffer 的图像格式是 NV12,如果当前 Player 是软解码模式,pixelBuffer 的图像格式是 i420
    onPlayerPixelBuffer 返回值为 YES 时, SDK 不会继续做图像渲染,这种方式可以解决 OpenGL 线程冲突的问题。
    @protocol TXVideoCustomProcessDelegate
    @optional

    /**
    * 视频渲染对象回调
    * @prarm pixelBuffer 渲染图像
    * @return 返回YES则SDK不再显示;返回NO则SDK渲染模块继续渲染
    * 说明:渲染图像的数据类型为config中设置的renderPixelFormatType
    */

    -(BOOL)onPlayerPixelBuffer:(CVPixelBufferRef)pixelBuffer;
    @end

Android 平台

  1. 设置 TXLivePlayer 的 ITXLivePlayVideoRenderListener 接口
    public class TXLivePlayer {
    /**
    * 设置视频渲染纹理回调
    *
    * @param listener 自定义渲染纹理回调
    * @param glContext OpenGL 上下文,如果您的渲染模块使用 (javax.microedition.khronos.egl.*) 定义的 OpenGL 接口,请填 javax.microedition.khronos.egl.EGLContext 类型的对象
    * 如果您的渲染模块使用 (android.opengl.*) 定义的 OpenGL 接口,请填 android.opengl.EGLContext 类型的对象。
    * 如果填 null 表示使用 SDK 内部默认的 javax.microedition.khronos.egl.EGLContext 环境
    * @return 0:成功;-1:glContext 类型非法。
    */

    public int setVideoRenderListener(final ITXLivePlayVideoRenderListener listener, Object glContext) {}
    }
  2. 通过 onRenderVideoFrame 回调捕获 Player 的图像数据
    static public class TXLiteAVTexture
    {
    public int textureId; // 视频纹理 ID
    public int width; // 视频宽度
    public int height; // 视频高度
    public Object eglContext; // javax.microedition.khronos.egl.EGLContext 或 android.opengl.EGLContext 定义的 OpenGL Context
    }

    public interface ITXLivePlayVideoRenderListener {
    /**
    * 解码器解出一帧数据回调一次
    *
    * @param texture 视频纹理
    */

    void onRenderVideoFrame(TXLiteAVTexture texture);
    }
目录