128 lines
3.1 KiB
C++
128 lines
3.1 KiB
C++
#include "sys/sock.h"
|
|
#include "sys/thread.h"
|
|
#include "sys/system.h"
|
|
#include "sys/sync.hpp"
|
|
#include "aio-connect.h"
|
|
#include "aio-timeout.h"
|
|
#include "aio-rtmp-client.h"
|
|
#include "flv-reader.h"
|
|
#include "flv-proto.h"
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <list>
|
|
|
|
static struct
|
|
{
|
|
int code; // rtmp error code
|
|
const char* file;
|
|
char tcurl[4 * 1024];
|
|
const char* app;
|
|
const char* stream;
|
|
aio_rtmp_client_t* rtmp;
|
|
} s_param;
|
|
|
|
static int STDCALL rtmp_client_push(void* flv)
|
|
{
|
|
int r, type;
|
|
size_t taglen;
|
|
uint32_t timestamp;
|
|
uint32_t clock0 = system_clock();
|
|
void* f = flv_reader_create((const char*)flv);
|
|
|
|
static char packet[2 * 1024 * 1024];
|
|
while (0 == s_param.code && 1 == flv_reader_read(f, &type, ×tamp, &taglen, packet, sizeof(packet)))
|
|
{
|
|
uint32_t t = system_clock();
|
|
if(clock0 + timestamp > t && clock0 + timestamp < t + 3 * 1000)
|
|
system_sleep(clock0 + timestamp - t);
|
|
else if (t + timestamp > t + 3 * 1000)
|
|
t = t - timestamp;
|
|
|
|
while (s_param.rtmp && aio_rtmp_client_get_unsend(s_param.rtmp) > 8 * 1024 * 1024)
|
|
system_sleep(1000); // can't send?
|
|
|
|
switch (type)
|
|
{
|
|
case FLV_TYPE_AUDIO:
|
|
r = aio_rtmp_client_send_audio(s_param.rtmp, packet, taglen, timestamp);
|
|
break;
|
|
|
|
case FLV_TYPE_VIDEO:
|
|
r = aio_rtmp_client_send_video(s_param.rtmp, packet, taglen, timestamp);
|
|
break;
|
|
|
|
case FLV_TYPE_SCRIPT:
|
|
r = aio_rtmp_client_send_script(s_param.rtmp, packet, taglen, timestamp);
|
|
break;
|
|
|
|
default:
|
|
r = 0;
|
|
break;
|
|
}
|
|
|
|
if (0 != r)
|
|
{
|
|
assert(0);
|
|
break; // TODO: handle send failed
|
|
}
|
|
}
|
|
|
|
aio_rtmp_client_destroy(s_param.rtmp);
|
|
flv_reader_destroy(f);
|
|
s_param.file = NULL;
|
|
s_param.rtmp = NULL;
|
|
return 0;
|
|
}
|
|
|
|
static void rtmp_client_publish_onsend(void*, size_t)
|
|
{
|
|
}
|
|
|
|
static void rtmp_client_publish_onready(void*)
|
|
{
|
|
pthread_t thread;
|
|
thread_create(&thread, rtmp_client_push, (void*)s_param.file);
|
|
thread_detach(thread);
|
|
}
|
|
|
|
static void rtmp_client_publish_onerror(void* /*param*/, int code)
|
|
{
|
|
// exit publish thread
|
|
s_param.code = code;
|
|
}
|
|
|
|
static void rtmp_onconnect(void*, int code, socket_t tcp, aio_socket_t aio)
|
|
{
|
|
assert(0 == code);
|
|
|
|
struct aio_rtmp_client_handler_t handler;
|
|
memset(&handler, 0, sizeof(handler));
|
|
handler.onerror = rtmp_client_publish_onerror;
|
|
handler.onready = rtmp_client_publish_onready;
|
|
handler.onsend = rtmp_client_publish_onsend;
|
|
|
|
s_param.code = 0;
|
|
s_param.rtmp = aio_rtmp_client_create(aio, s_param.app, s_param.stream, s_param.tcurl, &handler, NULL);
|
|
assert(0 == aio_rtmp_client_start(s_param.rtmp, 0));
|
|
}
|
|
|
|
// rtmp://video-center.alivecdn.com/live/hello?vhost=your.domain
|
|
// rtmp_publish_aio_test("video-center.alivecdn.com", "live", "hello?vhost=your.domain", local-flv-file-name)
|
|
void rtmp_publish_aio_test(const char* host, const char* app, const char* stream, const char* file)
|
|
{
|
|
s_param.file = file;
|
|
s_param.app = app;
|
|
s_param.stream = stream;
|
|
snprintf(s_param.tcurl, sizeof(s_param.tcurl), "rtmp://%s/%s", host, app); // tcurl
|
|
|
|
aio_socket_init(1);
|
|
aio_connect(host, 1935, 3000, rtmp_onconnect, NULL);
|
|
|
|
while (aio_socket_process(5000) > 0)
|
|
{
|
|
aio_timeout_process();
|
|
}
|
|
|
|
aio_socket_clean();
|
|
}
|