直播推流RTMP

<uses-permission android:name="android.permission.INTERNET" />
<activity android:name=".LivePushActivity" />

CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_CRYPTO")
add_library(
        gpush
        SHARED
        gpush.cpp
        GQueue.cpp
        RtmpPush.cpp
        librtmp/amf.c
        librtmp/hashswf.c
        librtmp/log.c
        librtmp/parseurl.c
        librtmp/rtmp.c

        native-lib.cpp
        RecordBuffer.cpp
)

find_library(
        log-lib
        log
)


target_link_libraries(
        gpush
        OpenSLES
        ${log-lib}
)

MainActivity

public void livePush(View view) {
        Intent intent = new Intent(this, LivePushActivity.class);
        startActivity(intent);
    }

LivePushActivity

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

PushVideo

package com.example.glivepush.push;

import android.text.TextUtils;

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

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

    private native void initPush(String pushUrl);
}

gpush.cpp

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

#include "RtmpPush.h"

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);

    rtmpPush = new RtmpPush(pushUrl);
    rtmpPush->init();

    env->ReleaseStringUTFChars(pushUrl_, pushUrl);
}

队列

#ifndef RTMPSUC_GQUEUE_H
#define RTMPSUC_GQUEUE_H

#include "queue"
#include "pthread.h"
#include "AndroidLog.h"

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

class GQueue {
public:
    std::queue<RTMPPacket *> queuePacket;
    //线程锁
    pthread_mutex_t mutexPacket;
    //条件变量
    pthread_cond_t condPacket;

public:
    GQueue();

    ~GQueue();

    int putRtmpPacket(RTMPPacket *packet);

    RTMPPacket *getRtmpPacket();

    void clearQueue();

    void notifyQueue();
};


#endif //RTMPSUC_GQUEUE_H

GQueue.cpp

#include "GQueue.h"

GQueue::GQueue() {
    //初始化
    pthread_mutex_init(&mutexPacket, NULL);
    pthread_cond_init(&condPacket, NULL);
}

GQueue::~GQueue() {
    clearQueue();
    //销毁线程锁
    pthread_mutex_destroy(&mutexPacket);
    //销毁条件变量
    pthread_cond_destroy(&condPacket);
}

int GQueue::putRtmpPacket(RTMPPacket *packet) {
    pthread_mutex_lock(&mutexPacket);
    queuePacket.push(packet);
    //通知
    pthread_cond_signal(&condPacket);
    pthread_mutex_unlock(&mutexPacket);
    return 0;
}

RTMPPacket *GQueue::getRtmpPacket() {
    pthread_mutex_lock(&mutexPacket);
    RTMPPacket *p = NULL;
    if (!queuePacket.empty()) {
        p = queuePacket.front();
        queuePacket.pop();
    } else {
        pthread_cond_wait(&condPacket, &mutexPacket);
    }
    pthread_mutex_unlock(&mutexPacket);
    return p;
}

void GQueue::clearQueue() {
    pthread_mutex_lock(&mutexPacket);
    while (true) {
        if (queuePacket.empty()) {
            break;
        }
        RTMPPacket *p = queuePacket.front();
        queuePacket.pop();
        RTMPPacket_Free(p);
        p = NULL;
    }
    pthread_mutex_unlock(&mutexPacket);
}

void GQueue::notifyQueue() {
    pthread_mutex_lock(&mutexPacket);
    pthread_cond_signal(&condPacket);
    pthread_mutex_unlock(&mutexPacket);
}

RtmpPush.h

#ifndef RTMPSUC_RTMPPUSH_H
#define RTMPSUC_RTMPPUSH_H

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

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

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

    pthread_t push_thread;
public:
    RtmpPush(const char *url);

    ~RtmpPush();

    void init();

};


#endif //RTMPSUC_RTMPPUSH_H

RtmpPush.cpp

#include "RtmpPush.h"

RtmpPush::RtmpPush(const char *url) {
    this->url = static_cast<char *>(malloc(512));
    strcpy(this->url, url);
    this->queue = new GQueue();
}

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

void *callBackPush(void *data) {
    RtmpPush *rtmpPush = static_cast<RtmpPush *>(data);
    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);
        goto end;
    }
    if (!RTMP_ConnectStream(rtmpPush->rtmp, 0)) {   //链接流  0失败
        LOGE("can not connect the stream of the service");
        goto end;
    }
    LOGD("connect success start push stream");
    //推流


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

void RtmpPush::init() {
    pthread_create(&push_thread, NULL, callBackPush, this);
}


AndroidLog.h

#pragma once
#ifndef RTMPSUC_ANDROIDLOG_H
#define RTMPSUC_ANDROIDLOG_H

#include <android/log.h>

#define LOG_SHOW true

#define LOGD(FORMAT,...) __android_log_print(ANDROID_LOG_DEBUG,"godv",FORMAT,##__VA_ARGS__);
#define LOGE(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR,"godv",FORMAT,##__VA_ARGS__);

#endif //RTMPSUC_ANDROIDLOG_H

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值