RTMP的回调

本文介绍了一个基于C++和Java实现的直播推流系统。该系统通过JNI调用C++代码进行RTMP推流,并在Java层提供了接口供Android应用使用。实现了连接状态的回调功能。

CMakeLists.txt  中添加相关cpp

GConnectListener

package com.example.glivepush.push;

public interface GConnectListener {
    //
    void onConnecting();

    void onConnectSuccess();

    void onConnectFail(String msg);
}

PushVideo

package com.example.glivepush.push;

import android.text.TextUtils;

public class PushVideo {
    static {
        System.loadLibrary("gpush");
    }

    private GConnectListener gConnectListener;

    public void setgConnectListener(GConnectListener gConnectListener) {
        this.gConnectListener = gConnectListener;
    }

    /********************************************************回调***********************************/
    private void onConnecting() {
        if (gConnectListener != null) {
            gConnectListener.onConnecting();
        }
    }

    private void onConnectSuccess() {
        if (gConnectListener != null) {
            gConnectListener.onConnectSuccess();
        }
    }

    private void onConnectFail(String msg) {
        if (gConnectListener != null) {
            gConnectListener.onConnectFail(msg);
        }
    }
    /********************************************************回调***********************************/

    public void initLivePush(String url) {
        if (!TextUtils.isEmpty(url)) {
            initPush(url);
        }
    }

    private native void initPush(String pushUrl);
}

LivePushActivity

package com.example.glivepush;

import android.os.Bundle;
import android.os.Environment;
import android.se.omapi.SEService;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.example.glivepush.push.GConnectListener;
import com.example.glivepush.push.PushVideo;

public class LivePushActivity extends AppCompatActivity {

    private PushVideo pushVideo;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_live_push);
        pushVideo = new PushVideo();

        /********************************************************回调*******************************/
        pushVideo.setgConnectListener(new GConnectListener() {
            @Override
            public void onConnecting() {
                Log.d("godv", "链接服务器中");
            }

            @Override
            public void onConnectSuccess() {
                Log.d("godv", "链接服务器成功");
            }

            @Override
            public void onConnectFail(String msg) {
                Log.d("godv", msg);
            }
        });

        /********************************************************回调*******************************/
    }

    public void startPush(View view) {
        pushVideo.initLivePush("rtmp://192.168.0.14/myapp/mystream");
    }
}

gpush.cpp

#include <jni.h>
#include <string>

#include "RtmpPush.h"

/********************************************************回调***************************************/
#include "GCallJava.h"

GCallJava *gCallJava = NULL;
JavaVM *javaVm = NULL;
/********************************************************回调***************************************/

RtmpPush *rtmpPush = NULL;
extern "C"
JNIEXPORT void JNICALL
Java_com_example_glivepush_push_PushVideo_initPush(JNIEnv *env, jobject thiz, jstring pushUrl_) {
    // TODO: implement initPush()
    const char *pushUrl = env->GetStringUTFChars(pushUrl_, 0);

    /********************************************************回调***********************************/
    gCallJava = new GCallJava(javaVm, env, &thiz);
    rtmpPush = new RtmpPush(pushUrl, gCallJava);
    /********************************************************回调***********************************/

    rtmpPush->init();

    env->ReleaseStringUTFChars(pushUrl_, pushUrl);
}

/********************************************************回调***************************************/
extern "C"
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env;
    javaVm = vm;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    return JNI_VERSION_1_6;
}

extern "C"
JNIEXPORT void JNICALL
JNI_OnUnload(JavaVM *vm, void *reserved) {
    javaVm = NULL;
}
/********************************************************回调***************************************/

GCallJava.h

#ifndef RTMPSUC_GCALLJAVA_H
#define RTMPSUC_GCALLJAVA_H

#include "jni.h"

#define G_THREAD_MAIN 1
#define G_THREAD_CHILD 2

class GCallJava {

public:
    JNIEnv *jniEnv = NULL;
    JavaVM *javaVm = NULL;

    jobject jobj;
    jmethodID jmid_connecting;
    jmethodID jmid_connectsuccess;
    jmethodID jmid_connectfail;

public:
    GCallJava(JavaVM *javaVm, JNIEnv *jniEnv, jobject *jobj);

    ~GCallJava();

    void onConnecting(int type);

    void onConnectSuccess();

    void onConnectFail(char *msg);
};

#endif //RTMPSUC_GCALLJAVA_H

GCallJava.cpp

#include "GCallJava.h"

GCallJava::GCallJava(JavaVM *javaVm, JNIEnv *jniEnv, jobject *jobj) {
    this->javaVm = javaVm;
    this->jniEnv = jniEnv;
    this->jobj = jniEnv->NewGlobalRef(*jobj);

    jclass jlz = jniEnv->GetObjectClass(this->jobj);

    jmid_connecting = jniEnv->GetMethodID(jlz, "onConnecting", "()V");
    jmid_connectsuccess = jniEnv->GetMethodID(jlz, "onConnectSuccess", "()V");
    jmid_connectfail = jniEnv->GetMethodID(jlz, "onConnectFail", "(Ljava/lang/String;)V");
}

GCallJava::~GCallJava() {
    jniEnv->DeleteGlobalRef(jobj);
    javaVm = NULL;
    jniEnv = NULL;
}

void GCallJava::onConnecting(int type) {
    if (type == G_THREAD_CHILD) {
        JNIEnv *jniEnv;
        if (javaVm->AttachCurrentThread(&jniEnv, 0) != JNI_OK) {
            return;
        }
        jniEnv->CallVoidMethod(jobj, jmid_connecting);
        javaVm->DetachCurrentThread();

    } else {
        jniEnv->CallVoidMethod(jobj, jmid_connecting);
    }
}

void GCallJava::onConnectSuccess() {
    JNIEnv *jniEnv;
    if (javaVm->AttachCurrentThread(&jniEnv, 0) != JNI_OK) {
        return;
    }
    jniEnv->CallVoidMethod(jobj, jmid_connectsuccess);
    javaVm->DetachCurrentThread();
}

void GCallJava::onConnectFail(char *msg) {
    JNIEnv *jniEnv;
    if (javaVm->AttachCurrentThread(&jniEnv, 0) != JNI_OK) {
        return;
    }
    jstring jmsg = jniEnv->NewStringUTF(msg);
    jniEnv->CallVoidMethod(jobj, jmid_connectfail, jmsg);
    jniEnv->DeleteLocalRef(jmsg);
    javaVm->DetachCurrentThread();

}

RtmpPush.h 

#ifndef RTMPSUC_RTMPPUSH_H
#define RTMPSUC_RTMPPUSH_H

#include <malloc.h>
#include <cstring>
#include "GQueue.h"
#include "pthread.h"

/********************************************************回调***************************************/
#include "GCallJava.h"
/********************************************************回调***************************************/

extern "C" {
#include "librtmp/rtmp.h"
};

class RtmpPush {
public:
    RTMP *rtmp = NULL;
    char *url = NULL;
    GQueue *queue = NULL;

    pthread_t push_thread;

    /********************************************************回调***********************************/
    GCallJava *gCallJava = NULL;
    /********************************************************回调***********************************/

public:

    /********************************************************回调***********************************/
    RtmpPush(const char *url, GCallJava *gCallJava);
    /********************************************************回调***********************************/

    ~RtmpPush();

    void init();

};

#endif //RTMPSUC_RTMPPUSH_H

RtmpPush.cpp

#include "RtmpPush.h"

/********************************************************回调***************************************/
RtmpPush::RtmpPush(const char *url, GCallJava *gCallJava) {
    this->url = static_cast<char *>(malloc(512));
    strcpy(this->url, url);
    this->queue = new GQueue();

    this->gCallJava = gCallJava;
}

/********************************************************回调***************************************/

RtmpPush::~RtmpPush() {
    queue->notifyQueue();
    queue->clearQueue();
    free(url);
}

void *callBackPush(void *data) {
    RtmpPush *rtmpPush = static_cast<RtmpPush *>(data);

    /********************************************************子线程回调******************************/
    rtmpPush->gCallJava->onConnecting(G_THREAD_CHILD);
    /********************************************************回调***********************************/

    rtmpPush->rtmp = RTMP_Alloc();    //分配空间
    RTMP_Init(rtmpPush->rtmp);        //初始化
    rtmpPush->rtmp->Link.timeout = 10;   //设置超时时间
    rtmpPush->rtmp->Link.lFlags |= RTMP_LF_LIVE;  //追加直播
    RTMP_SetupURL(rtmpPush->rtmp, rtmpPush->url);    //设置推流URL
    RTMP_EnableWrite(rtmpPush->rtmp);    //设置可写状态
    if (!RTMP_Connect(rtmpPush->rtmp, NULL)) {    //链接服务器  0失败
//        LOGE("can not connect the url %s", rtmpPush->url);

        /********************************************************子线程回调**************************/
        rtmpPush->gCallJava->onConnectFail("can not connect the url");
        /*************************************************************回调**************************/

        goto end;
    }
    if (!RTMP_ConnectStream(rtmpPush->rtmp, 0)) {   //链接流  0失败
        /********************************************************子线程回调**************************/
        rtmpPush->gCallJava->onConnectFail("can not connect the stream of the service");
        /********************************************************回调*******************************/
        goto end;
    }
    //推流

    /********************************************************子线程回调******************************/
    rtmpPush->gCallJava->onConnectSuccess();
    /********************************************************回调***********************************/

    end:
    RTMP_Close(rtmpPush->rtmp);
    RTMP_Free(rtmpPush->rtmp);
    rtmpPush->rtmp = NULL;
    pthread_exit(&rtmpPush->push_thread);
}

void RtmpPush::init() {

    /***************************************************主线程回调***********************************/
    //gCallJava->onConnecting(G_THREAD_MAIN);
    /********************************************************回调***********************************/

    pthread_create(&push_thread, NULL, callBackPush, this);
}

 

在使用 Docker 部署 Oryx 时,配置回调地址通常涉及对 Oryx 的配置文件进行修改,或者在运行容器时通过环境变量传递相关参数。Oryx 是一个基于 WebRTC 和 RTMP 的实时音视频流媒体解决方案,支持多种高级功能,如自动 HTTPS、身份验证、DVR、转发增强等。对于回调地址的配置,通常用于身份验证、事件通知或自定义业务逻辑的集成。 在 Docker 部署中,可以通过以下方式进行回调地址的配置: 1. **通过配置文件设置** Oryx 的配置文件通常为 `config.json` 或 `application.yml`,具体取决于部署方式和版本。可以在配置文件中找到与回调相关的配置项,并设置回调地址。例如: ```json { "callback": { "auth": "https://your-callback-server/auth", "event": "https://your-callback-server/event" } } ``` 将配置文件挂载到 Docker 容器中,确保容器启动时读取到该配置。 2. **通过环境变量设置** 在运行 Docker 容器时,可以通过 `-e` 参数设置环境变量来覆盖默认配置。例如: ```bash docker run -d \ -e ORYX_CALLBACK_AUTH=https://your-callback-server/auth \ -e ORYX_CALLBACK_EVENT=https://your-callback-server/event \ -p 1935:1935 -p 80:80 \ oryx/oryx:latest ``` 这种方式适用于需要动态配置回调地址的场景,特别是在不同的部署环境中使用不同的回调服务。 3. **回调地址的业务逻辑处理** 回调地址指向的服务需要能够处理 Oryx 发送的 HTTP 请求。通常,Oryx 会在特定事件发生时(如流开始、流结束、鉴权请求)向回调地址发送 POST 请求。开发者需要根据 Oryx 的回调协议实现相应的处理逻辑。例如: ```python from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/auth', methods=['POST']) def auth(): data = request.json stream_key = data.get('streamKey') # 实现鉴权逻辑 if stream_key == 'valid_key': return jsonify({"code": 200, "message": "OK"}) else: return jsonify({"code": 401, "message": "Unauthorized"}), 401 if __name__ == '__main__': app.run(host='0.0.0.0', port=80) ``` 4. **网络与安全配置** 确保回调地址所在的服务器可以通过公网或内网访问,并且防火墙或安全组规则允许 Oryx 所在的 Docker 容器访问回调地址的端口。此外,建议启用 HTTPS 并配置有效的 SSL 证书以保证通信安全。 Oryx 提供了丰富的功能,包括对回调机制的支持,使得开发者可以灵活地将其集成到现有的业务系统中 [^2]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值