1 . Java Передать строковые данные в JNI : При запуске push-стриминга , Java слой будет RTMP Адрес push передается JNI ;
2 . jstring Преобразование типа в char* тип : Воля Java Преобразовать строку в C нить ;
// получать Rtmp Отправить адрес потока
// Должен pushPathFromJava Ссылка — это локальная ссылка, Оно будет недействительным, если оно выходит за рамки.
// Локальные ссылки не могут охватывать метод , Звонок через нить
const char* pushPathFromJava = env->GetStringUTFChars(path, 0);
3 . Обработка локальной ссылочной переменной : Преобразованный const char* pushPathFromJava нить — локальная ссылочная переменная , Невозможно пересекать процессы , Использование в разных областях , Последующие операции push используются в отдельных потоках. , Поэтому Волянить данные существования необходимо хранить в куче памяти. ;
// получатьадресдлина, плюс '\0' длина
char * pushPathNative = new char[strlen(pushPathFromJava) + 1];
// копировать pushPathFromJava перегружать память pushPathNative середина
// Локальные ссылки не могут охватывать метод , Звонок через нить, Здесь вам нужно существоватьсередина, используя адрес Должена.
// Поэтому необходимо Воля Долженместная ссылкакопироватьперегружать памятьсередина, Затем передали соответствующему нитьсередина.
strcpy(pushPathNative, pushPathFromJava);
4 . Освободить локальную ссылку : JNI локальные ссылочные переменные в , Отпустите сразу после использования ;
// освобождение от Java слойполучатьизнить
// Освободить локальную ссылку
env->ReleaseStringUTFChars(path, pushPathFromJava);
1 . Независимый толчок нити : RTMP Операцию push необходимо выполнить в отдельном потоке. , Операции, связанные с сетью, требуют много времени. , существовать Android середина Необходимыйсуществоватьнитьсерединаосуществлять ;
2 . нить ID заявление : Нужно импортировать #include <pthread.h>
Сумка , Только тогда ты сможешь использовать нить ,Первыйзаявлениенить ID, pthread_t тип ;
/**
* Начать продвигать поток работы нить нить ID
*/
pthread_t startRtmpPushPid;
3 . создаватьиосуществлятьнить : создаватьиосуществлятьнить , существоватьнитьсерединаосуществлять startRtmpPush метод ,входящий pushPathNative нитьпараметр ;
// создаватьнить
pthread_create(&startRtmpPushPid, 0, startRtmpPush, pushPathNative);
4 . нитьметод : Определение нитметод , И параметры, и возвращаемые значения void* тип , существоватьстартовая позицияполучатьвходящийизпараметр ;
void* startRtmpPush (void* args){
// 0. получать Rtmp Отправить адрес потока
char* pushPath = static_cast<char *>(args);
// ...
}
создавать RTMP объект , Если создатель потерпит неудачу , Просто остановите весь метод push-потока ;
// 1. создавать RTMP объект, Подать заявку на память
rtmp = RTMP_Alloc();
if (!rtmp) {
__android_log_print(ANDROID_LOG_INFO, "RTMP", "Применять RTMP Память подвела");
break;
}
инициализация RTMP объект , и установите тайм-аут ;
// 2. инициализация RTMP
RTMP_Init(rtmp);
// настройка таймаута 5 Второй
rtmp->Link.timeout = 5;
Установите адрес push-уведомления RTMP. Если настройка не удалась, выйдите из операции push напрямую;
Адрес Java слой передан в JNI изнить, Это локальная ссылочная переменная, когда она впервые получена. , Воляитскопировать в кучу памятисередина , Только тогда можносуществоватьтолкатьпотокнитьсерединаиспользовать ;
// 3. настраивать RTMP Отправить адрес потокового сервера
int ret = RTMP_SetupURL(rtmp, pushPath);
if (!ret) {
__android_log_print(ANDROID_LOG_INFO, "RTMP", "настраивать RTMP Отправить адрес потокового сервера %s неудача", pushPath);
break;
}
Включить запись RTMP;
// 4. давать возможность RTMP функция записи
RTMP_EnableWrite(rtmp);
соединять RTMP сервер , Если соединение не удалось , прямойпокидать Долженметод ;
// 5. соединять RTMP сервер
ret = RTMP_Connect(rtmp, 0);
if (!ret) {
__android_log_print(ANDROID_LOG_INFO, "RTMP", "соединять RTMP сервер %s неудача", pushPath);
break;
}
соединять RTMP поток , Если соединение не удалось ,покидатьметод ;
// 6. соединять RTMP поток
ret = RTMP_ConnectStream(rtmp, 0);
if (!ret) {
__android_log_print(ANDROID_LOG_INFO, "RTMP", "соединять RTMP поток %s неудача", pushPath);
break;
}
Воля RTMP данные Сумкаотправлятьприезжатьсерверсередина ;
// 7. Воля RTMP данные Сумкаотправлятьприезжатьсерверсередина
ret = RTMP_SendPacket(rtmp, packet, 1);
толкатьпоток После окончания , близко с RTMP серверсоединять , Освободить ресурсы ;
// 8. Нажмите поток, чтобы закончить, близко с RTMP серверсоединять, Освободить ресурсы
if(rtmp){
RTMP_Close(rtmp);
RTMP_Free(rtmp);
}
RTMPDump отправить код потока :
/**
* Запустить удаленно RTMP серверPush data
*/
extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_rtmp_LivePusher_native_1startRtmpPush(JNIEnv *env, jobject thiz,
jstring path) {
if(isStartRtmpPush){
// Предотвратить многократный вызов Долженметода, Если он был вызван ранее, Тогда заблокируйте этот звонок
return;
}
// Выполнив его один раз, Немедленно отметьте выполненный статус, Не в следующий разосуществлять Долженметод Понятно
isStartRtmpPush = TRUE;
// получать Rtmp Отправить адрес потока
// Должен pushPathFromJava Ссылка — это локальная ссылка, Оно будет недействительным, если оно выходит за рамки.
// Локальные ссылки не могут охватывать метод , Звонок через нить
const char* pushPathFromJava = env->GetStringUTFChars(path, 0);
// получатьадресдлина, плюс '\0' длина
char * pushPathNative = new char[strlen(pushPathFromJava) + 1];
// копировать pushPathFromJava перегружать память pushPathNative середина
// Локальные ссылки не могут охватывать метод , Звонок через нить, Здесь вам нужно существоватьсередина, используя адрес Должена.
// Поэтому необходимо Воля Долженместная ссылкакопироватьперегружать памятьсередина, Затем передали соответствующему нитьсередина.
strcpy(pushPathNative, pushPathFromJava);
// создаватьнить
pthread_create(&startRtmpPushPid, 0, startRtmpPush, pushPathNative);
// освобождение от Java слойполучатьизнить
// Освободить локальную ссылку
env->ReleaseStringUTFChars(path, pushPathFromJava);
}
/**
* Начни продвигать миссию по потоку нить
* В основном звоню RTMPDump Сделайте толчок
* @param args
* @return
*/
void* startRtmpPush (void* args){
// 0. получать Rtmp Отправить адрес потока
char* pushPath = static_cast<char *>(args);
// rtmp толкатель потока
RTMP* rtmp = 0;
// rtmp толкатьпотокданные Сумка RTMPPacket *packet = 0;
/*
Воля подталкивает поток выполнения основного контента, чтобы обеспечить существование do while циклсередина
существовать После ошибки, в любое время break выйти из цикла, Выполните следующее Освободить код ресурса
Это может быть гарантировано, существуют Наконец-то ресурсы Воля освобождены, Избегайте утечек памяти
Избегайте неудачного выполнения, прямой return, В результате ресурсы не освобождаются.
*/
do {
// 1. создавать RTMP объект, Подать заявку на память
rtmp = RTMP_Alloc();
if (!rtmp) {
__android_log_print(ANDROID_LOG_INFO, "RTMP", "Применять RTMP Память подвела");
break;
}
// 2. инициализация RTMP
RTMP_Init(rtmp);
// настройка таймаута 5 Второй
rtmp->Link.timeout = 5;
// 3. настраивать RTMP Отправить адрес потокового сервера
int ret = RTMP_SetupURL(rtmp, pushPath);
if (!ret) {
__android_log_print(ANDROID_LOG_INFO, "RTMP", "настраивать RTMP Отправить адрес потокового сервера %s неудача", pushPath);
break;
}
// 4. давать возможность RTMP функция записи
RTMP_EnableWrite(rtmp);
// 5. соединять RTMP сервер
ret = RTMP_Connect(rtmp, 0);
if (!ret) {
__android_log_print(ANDROID_LOG_INFO, "RTMP", "соединять RTMP сервер %s неудача", pushPath);
break;
}
// 6. соединять RTMP поток
ret = RTMP_ConnectStream(rtmp, 0);
if (!ret) {
__android_log_print(ANDROID_LOG_INFO, "RTMP", "соединять RTMP поток %s неудача", pushPath);
break;
}
// Приготовьтесь отправить данные, связанные с потоком, Например, нить очереди безопасности
readyForPush = TRUE;
// Запись времени начала push-потока
pushStartTime = RTMP_GetTime();
// нитьSecurity Queue начинает работать
packets.setWork(1);
while (isStartRtmpPush) {
// Из нить очереди безопасности середина
// Достаньте побитую Сумку RTMP данные Сумка packets.pop(packet);
// Убедитесь, что вы в данный момент нажимаете поток
if (!isStartRtmpPush) {
break;
}
// Убедитесь, что пустые не вынуты. RTMP данные Сумка if (!packet) {
continue;
}
// настраиватьпрямая трансляцияизпоток ID
packet->m_nInfoField2 = rtmp->m_stream_id;
// 7. Воля RTMP данные Сумкаотправлятьприезжатьсерверсередина
ret = RTMP_SendPacket(rtmp, packet, 1);
// RTMP После использования данных Сумка, выпускать Долженданные Сумка if (packet) {
RTMPPacket_Free(packet);
delete packet;
packet = 0;
}
if (!ret) {
__android_log_print(ANDROID_LOG_INFO, "RTMP", "RTMP Ошибка отправки потока данных "Сумка данных");
break;
}
}
}while (0);
// Поверхностная часть является отделочной частью, Освободить ресурсы
// 8. Нажмите поток, чтобы закончить, близко с RTMP серверсоединять, Освободить ресурсы
if(rtmp){
RTMP_Close(rtmp);
RTMP_Free(rtmp);
}
// толкатьпотокданные Сумка освободить очередь безопасности
// предотвращатьсерединаспособпокидатьв результате нет Освободить ресурсы, вызывая утечки памяти
if (packet) {
RTMPPacket_Free(packet);
delete packet;
packet = 0;
}
// выпускать Отправить адрес потока
if(pushPath){
delete pushPath;
pushPath = 0;
}
return 0;
}