Writing C based wrapper for rtmp stuff which I'll then call using cgo

This commit is contained in:
Saxon Milton 2018-02-13 00:01:19 +10:30
parent bf6b1383c0
commit 0ac9c3d50b
5 changed files with 229 additions and 1 deletions

View File

@ -18,6 +18,7 @@ const (
H264 = 7
AVCNALU = 1
DataHeaderLength = 5
NoTimestampExtension = 0
)
type Header struct {

View File

@ -72,7 +72,7 @@ func (g *flvGenerator) generate() {
TagType: uint8(flv.VideoTagType),
DataSize: uint32(len(videoFrame)) + flv.DataHeaderLength,
Timestamp: g.getNextTimestamp(),
TimestampExtended: 0,
TimestampExtended: flv.NoTimestampExtension,
FrameType: flv.KeyFrameType,
Codec: flv.H264,
PacketType: flv.AVCNALU,

16
rtmp/RTMP.go Normal file
View File

@ -0,0 +1,16 @@
package rtmp
// #include "libRTMPWrapper.h"
import "C"
type rtmpSession struct {
}
type RTMPSession interface {
}
func NewRTMPSession() (session *rtmpSession){
}

211
rtmp/RTMPWrapper.c Normal file
View File

@ -0,0 +1,211 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "rtmp_c/librtmp/rtmp_sys.h"
#include "rtmp_c/librtmp/log.h"
#include "lwlog/lwlog.h"
#define HTON16(x) ((x>>8&0xff)|(x<<8&0xff00))
#define HTON24(x) ((x>>16&0xff)|(x<<16&0xff0000)|(x&0xff00))
#define HTON32(x) ((x>>24&0xff)|(x>>8&0xff00)|\
(x<<8&0xff0000)|(x<<24&0xff000000))
#define HTONTIME(x) ((x>>16&0xff)|(x<<16&0xff0000)|(x&0xff00)|(x&0xff000000))
/*read 1 byte*/
int ReadU8(uint32_t *u8, FILE *fp) {
if (fread(u8, 1, 1, fp) != 1) {
return 0;
}
return 1;
}
/*read 2 byte*/
int ReadU16(uint32_t *u16, FILE *fp) {
if (fread(u16, 2, 1, fp) != 1) {
return 0;
}
*u16 = HTON16(*u16);
return 1;
}
/*read 3 byte*/
int ReadU24(uint32_t *u24, FILE *fp) {
if (fread(u24, 3, 1, fp) != 1) {
return 0;
}
*u24 = HTON24(*u24);
return 1;
}
/*read 4 byte*/
int ReadU32(uint32_t *u32, FILE *fp) {
if (fread(u32, 4, 1, fp) != 1) {
return 0;
}
*u32 = HTON32(*u32);
return 1;
}
/*read 1 byte,and loopback 1 byte at once*/
int PeekU8(uint32_t *u8, FILE *fp) {
if (fread(u8, 1, 1, fp) != 1) {
return 0;
}
fseek(fp, -1, SEEK_CUR);
return 1;
}
/*read 4 byte and convert to time format*/
int ReadTime(uint32_t *utime, FILE *fp) {
if (fread(utime, 4, 1, fp) != 1) {
return 0;
}
*utime = HTONTIME(*utime);
return 1;
}
//Publish using RTMP_Write()
int publish_using_write() {
uint32_t start_time = 0;
uint32_t now_time = 0;
uint32_t pre_frame_time = 0;
uint32_t lasttime = 0;
int b_next_is_key = 0;
char *p_file_buf = NULL;
//read from tag header
uint32_t type = 0;
uint32_t datalength = 0;
uint32_t timestamp = 0;
RTMP *rtmp = NULL;
FILE *fp = NULL;
fp = fopen("../cuc_ieschool.flv", "rb");
if (NULL == fp) {
RTMP_LogPrintf("Open File Error.\n");
return -1;
}
/* set log level */
//RTMP_LogLevel loglvl=RTMP_LOGDEBUG;
//RTMP_LogSetLevel(loglvl);
rtmp = RTMP_Alloc();
RTMP_Init(rtmp);
//set connection timeout,default 30s
rtmp->Link.timeout = 5;
if (!RTMP_SetupURL(rtmp, "rtmp://localhost/live/inrtmp")) {
RTMP_Log(RTMP_LOGERROR, "SetupURL Err\n");
RTMP_Free(rtmp);
return -1;
}
RTMP_EnableWrite(rtmp);
//1hour
RTMP_SetBufferMS(rtmp, 3600 * 1000);
if (!RTMP_Connect(rtmp, NULL)) {
RTMP_Log(RTMP_LOGERROR, "Connect Err\n");
RTMP_Free(rtmp);
return -1;
}
if (!RTMP_ConnectStream(rtmp, 0)) {
RTMP_Log(RTMP_LOGERROR, "ConnectStream Err\n");
RTMP_Close(rtmp);
RTMP_Free(rtmp);
return -1;
}
lwlog_info("Start to send data ...");
//jump over FLV Header
fseek(fp, 9, SEEK_SET);
//jump over previousTagSizen
fseek(fp, 4, SEEK_CUR);
start_time = RTMP_GetTime();
while (1) {
if ((((now_time = RTMP_GetTime()) - start_time)
< (pre_frame_time)) && b_next_is_key) {
//wait for 1 sec if the send process is too fast
//this mechanism is not very good,need some improvement
if (pre_frame_time > lasttime) {
RTMP_LogPrintf("TimeStamp:%8u ms\n", pre_frame_time);
lasttime = pre_frame_time;
}
sleep(1);
continue;
}
//jump over type
fseek(fp, 1, SEEK_CUR);
if (!ReadU24(&datalength, fp)) {
break;
}
if (!ReadTime(&timestamp, fp)) {
break;
}
//jump back
fseek(fp, -8, SEEK_CUR);
p_file_buf = (char *) malloc(11 + datalength + 4);
memset(p_file_buf, 0, 11 + datalength + 4);
if (fread(p_file_buf, 1, 11 + datalength + 4, fp) != (11 + datalength + 4)) {
break;
}
pre_frame_time = timestamp;
if (!RTMP_IsConnected(rtmp)) {
RTMP_Log(RTMP_LOGERROR, "rtmp is not connect\n");
break;
}
if (!RTMP_Write(rtmp, p_file_buf, 11 + datalength + 4)) {
RTMP_Log(RTMP_LOGERROR, "Rtmp Write Error\n");
break;
}
free(p_file_buf);
p_file_buf = NULL;
if (!PeekU8(&type, fp)) {
break;
}
if (0x09 == type) {
if (fseek(fp, 11, SEEK_CUR) != 0) {
break;
}
if (!PeekU8(&type, fp)) {
break;
}
if (type == 0x17) {
b_next_is_key = 1;
} else {
b_next_is_key = 0;
}
fseek(fp, -11, SEEK_CUR);
}
}
RTMP_LogPrintf("\nSend Data Over\n");
if (fp != NULL) {
fclose(fp);
fp = NULL;
}
if (rtmp != NULL) {
RTMP_Close(rtmp);
RTMP_Free(rtmp);
rtmp = NULL;
}
if (p_file_buf != NULL) {
free(p_file_buf);
p_file_buf = NULL;
}
return 0;
}

0
rtmp/RTMPWrapper.h Normal file
View File