<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