Simple Live System Using SRS
https://www.cnblogs.com/dong1/p/5100792.html
1、h264推送规则看文档描述如下
/**
For the example file:
http://winlinvip.github.io/srs.release/3rdparty/720p.h264.raw
The data sequence is:
// SPS
000000016742802995A014016E40
// PPS
0000000168CE3880
// IFrame
0000000165B8041014C038008B0D0D3A071.....
// PFrame
0000000141E02041F8CDDC562BBDEFAD2F.....
User can send the SPS+PPS, then each frame:
// SPS+PPS
srs_h264_write_raw_frames('000000016742802995A014016E400000000168CE3880', size, dts, pts)
// IFrame
srs_h264_write_raw_frames('0000000165B8041014C038008B0D0D3A071......', size, dts, pts)
// PFrame
srs_h264_write_raw_frames('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts)
User also can send one by one:
// SPS
srs_h264_write_raw_frames('000000016742802995A014016E4', size, dts, pts)
// PPS
srs_h264_write_raw_frames('00000000168CE3880', size, dts, pts)
// IFrame
srs_h264_write_raw_frames('0000000165B8041014C038008B0D0D3A071......', size, dts, pts)
// PFrame
srs_h264_write_raw_frames('0000000141E02041F8CDDC562BBDEFAD2F......', size, dts, pts)
*/
我们设备的数据sps+pps+i是合成一帧的,直接按 (sps+pps+i合成一帧) + p*n 来推送也是可行了,只是报了个pps重复错误,不影响。
/**
# Example to use srs-librtmp
# see: https://github.com/ossrs/srs/wiki/v2_CN_SrsLibrtmp
gcc example.c srs_librtmp.cpp -g -O0 -lstdc++ -o example
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "srs_librtmp.h"
static off_t file_size;
char* get_data_frame(char* raw_file)
{
int raw_fd = open(raw_file, O_RDONLY);
if (raw_fd < 0) {
srs_human_trace("open h264 raw file %s failed.", raw_file);
return NULL;
}
file_size = lseek(raw_fd, 0, SEEK_END);
if (file_size <= 0) {
srs_human_trace("h264 raw file %s empty.", raw_file);
return NULL;
}
//srs_human_trace("read entirely h264 raw file, size=%dKB", (int)(file_size / 1024));
char*h264_raw = (char*)malloc(file_size);
if (!h264_raw) {
srs_human_trace("alloc raw buffer failed for file %s.", raw_file);
return NULL;
}
lseek(raw_fd, 0, SEEK_SET);
ssize_t nb_read = 0;
if ((nb_read = read(raw_fd, h264_raw, file_size)) != file_size) {
srs_human_trace("buffer %s failed, expect=%dKB, actual=%dKB.",
raw_file, (int)(file_size / 1024), (int)(nb_read / 1024));
return NULL;
}
close(raw_fd);
return h264_raw;
}
int main(int argc, char** argv)
{
printf("Example for srs-librtmp\n");
printf("SRS(ossrs) client librtmp library.\n");
printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision());
// connect rtmp context
const char* rtmp_url = "rtmp://127.0.0.1:1935/live/livestream";
srs_rtmp_t rtmp = srs_rtmp_create(rtmp_url);
if (srs_rtmp_handshake(rtmp) != 0) {
srs_human_trace("simple handshake failed.");
goto rtmp_destroy;
}
srs_human_trace("simple handshake success");
if (srs_rtmp_connect_app(rtmp) != 0) {
srs_human_trace("connect vhost/app failed.");
goto rtmp_destroy;
}
srs_human_trace("connect vhost/app success");
if (srs_rtmp_publish_stream(rtmp) != 0) {
srs_human_trace("publish stream failed.");
goto rtmp_destroy;
}
srs_human_trace("publish stream success");
int n = 0;
int dts = 0;
int pts = 0;
double fps = 25;
while(1){
char str[32];
sprintf(str,"./h264_nalu_frame/test%d.264",n);
char* h264_raw = get_data_frame(str);
if(h264_raw != NULL){
// send out the h264 packet over RTMP
int ret = srs_h264_write_raw_frames(rtmp, h264_raw, file_size, dts, pts);
if (ret != 0) {
if (srs_h264_is_dvbsp_error(ret)) {
srs_human_trace("ignore drop video error, code=%d", ret);
} else if (srs_h264_is_duplicated_sps_error(ret)) {
srs_human_trace("ignore duplicated sps, code=%d", ret);
} else if (srs_h264_is_duplicated_pps_error(ret)) {
srs_human_trace("ignore duplicated pps, code=%d", ret);
} else {
srs_human_trace("send h264 raw data failed. ret=%d", ret);
goto rtmp_destroy;
}
}
}
else break;
dts += 1000 / fps;
pts = dts;
usleep(40 * 1000);
free(h264_raw);
if(++n > 31) n=0;
}
rtmp_destroy:
srs_rtmp_destroy(rtmp);
return 0;
}
https://files.cnblogs.com/files/dong1/srs-librtmp_demo.zip
2、推送多路rtmp流 ,还是一帧一帧的发送
/**
# Example to use srs-librtmp
# see: https://github.com/ossrs/srs/wiki/v2_CN_SrsLibrtmp
gcc example.c srs_librtmp.cpp -g -O0 -lstdc++ -o example
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "srs_librtmp.h"
#include "threadpool.h"
#define THREAD 32
#define QUEUE 256
#define THREAD_POOL_EN (0)
static off_t file_size;
pthread_mutex_t lock;
char* get_data_frame(char* raw_file)
{
int raw_fd = open(raw_file, O_RDONLY);
if (raw_fd < 0) {
srs_human_trace("open h264 raw file %s failed.", raw_file);
return NULL;
}
file_size = lseek(raw_fd, 0, SEEK_END);
if (file_size <= 0) {
srs_human_trace("h264 raw file %s empty.", raw_file);
return NULL;
}
//srs_human_trace("read entirely h264 raw file, size=%dKB", (int)(file_size / 1024));
char*h264_raw = (char*)malloc(file_size);
if (!h264_raw) {
srs_human_trace("alloc raw buffer failed for file %s.", raw_file);
return NULL;
}
lseek(raw_fd, 0, SEEK_SET);
ssize_t nb_read = 0;
if ((nb_read = read(raw_fd, h264_raw, file_size)) != file_size) {
srs_human_trace("buffer %s failed, expect=%dKB, actual=%dKB.",
raw_file, (int)(file_size / 1024), (int)(nb_read / 1024));
return NULL;
}
close(raw_fd);
return h264_raw;
}
#if THREAD_POOL_EN
void sink_task(void *arg)
#else
void* sink_task(void *arg)
#endif
{
int num = *(int*)arg;
printf("Example for srs-librtmp\n");
printf("SRS(ossrs) client librtmp library.\n");
printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision());
int n = 0;
int dts = 0;
int pts = 0;
double fps = 25;
// connect rtmp context
const char* rtmp_url = "rtmp://127.0.0.1:1935/live/livestream";
char url[32]={0};
sprintf(url,"%s%d",rtmp_url,num);
printf("%s\n",url);
srs_rtmp_t rtmp = srs_rtmp_create(url);
if (srs_rtmp_handshake(rtmp) != 0) {
srs_human_trace("simple handshake failed.");
goto rtmp_destroy;
}
srs_human_trace("simple handshake success");
if (srs_rtmp_connect_app(rtmp) != 0) {
srs_human_trace("connect vhost/app failed.");
goto rtmp_destroy;
}
srs_human_trace("connect vhost/app success");
if (srs_rtmp_publish_stream(rtmp) != 0) {
srs_human_trace("publish stream failed.");
goto rtmp_destroy;
}
srs_human_trace("publish stream success");
while(1){
char str[32];
sprintf(str,"./h264_nalu_frame/test%d.264",n);
pthread_mutex_lock(&lock);
char* h264_raw = get_data_frame(str);
pthread_mutex_unlock(&lock);
if(h264_raw != NULL){
// send out the h264 packet over RTMP
int ret = srs_h264_write_raw_frames(rtmp, h264_raw, file_size, dts, pts);
if (ret != 0) {
if (srs_h264_is_dvbsp_error(ret)) {
srs_human_trace("ignore drop video error, code=%d", ret);
} else if (srs_h264_is_duplicated_sps_error(ret)) {
srs_human_trace("ignore duplicated sps, code=%d", ret);
} else if (srs_h264_is_duplicated_pps_error(ret)) {
srs_human_trace("ignore duplicated pps, code=%d", ret);
} else {
srs_human_trace("send h264 raw data failed. ret=%d", ret);
goto rtmp_destroy;
}
}
}
else break;
dts += 1000 / fps;
pts = dts;
usleep(40 * 1000);
free(h264_raw);
if(++n > 31) n=0;
}
rtmp_destroy:
srs_rtmp_destroy(rtmp);
}
void source_task(void *arg){
}
void* signal_task(void *arg) {
threadpool_t *pool;
assert((pool = threadpool_create(THREAD, QUEUE, 0)) != NULL);
fprintf(stderr, "Pool started with %d threads and "
"queue size of %d\n", THREAD, QUEUE);
pthread_mutex_init(&lock, NULL);
#if THREAD_POOL_EN
if(threadpool_add(pool, &source_task, NULL, 0) == 0) {
}
int num = 0;
if(threadpool_add(pool, &sink_task, &num, 0) == 0) {
}
int num1 = 1;
if(threadpool_add(pool, &sink_task, &num1, 0) == 0) {
}
int num2 = 2;
if(threadpool_add(pool, &sink_task, &num2, 0) == 0) {
}
#else
pthread_t rtmp_id,rtmp_id1,rtmp_id2;
int num = 0;
int ret = pthread_create(&rtmp_id,NULL,sink_task, &num);
if(ret!=0)
{
printf("Create pthread error!\n");
}
int num1 = 1;
ret = pthread_create(&rtmp_id1,NULL,sink_task, &num1);
if(ret!=0)
{
printf("Create pthread error!\n");
}
int num2 = 2;
ret = pthread_create(&rtmp_id2,NULL,sink_task, &num2);
if(ret!=0)
{
printf("Create pthread error!\n");
}
#endif
while(1)
{
sleep(1);
}
assert(threadpool_destroy(pool, 0) == 0);
}
int main(int argc, char** argv)
{
pthread_t signal_id;
int ret = pthread_create(&signal_id,NULL,signal_task, NULL);
if(ret!=0)
{
return -1;
}
while(1)
{
sleep(1);
}
return 0;
}
https://files.cnblogs.com/files/dong1/srs-librtmp_multiple.zip
3. 推送h265, 需要在srs里添加hevc支持
参考
### SRS v4.x support hevc(h.265) RTMP streaming #1721
rtmp推送h265
https://blog.csdn.net/qq_44895902/article/details/106030403
将网友的例子稍微改一下, 跟上面一样一帧一帧的发送.
/**
# Example to use srs-librtmp
# see: https://github.com/ossrs/srs/wiki/v2_CN_SrsLibrtmp
gcc example.c srs_librtmp.cpp -g -O0 -lstdc++ -o example
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "srs_librtmp.h"
static off_t file_size;
char* get_data_frame(char* raw_file)
{
int raw_fd = open(raw_file, O_RDONLY);
if (raw_fd < 0) {
srs_human_trace("open h265 raw file %s failed.", raw_file);
return NULL;
}
file_size = lseek(raw_fd, 0, SEEK_END);
if (file_size <= 0) {
srs_human_trace("h265 raw file %s empty.", raw_file);
return NULL;
}
srs_human_trace("read entirely h265 raw file, size=%dKB", (int)(file_size / 1024));
char*h265_raw = (char*)malloc(file_size);
if (!h265_raw) {
srs_human_trace("alloc raw buffer failed for file %s.", raw_file);
return NULL;
}
lseek(raw_fd, 0, SEEK_SET);
ssize_t nb_read = 0;
if ((nb_read = read(raw_fd, h265_raw, file_size)) != file_size) {
srs_human_trace("buffer %s failed, expect=%dKB, actual=%dKB.",
raw_file, (int)(file_size / 1024), (int)(nb_read / 1024));
return NULL;
}
close(raw_fd);
return h265_raw;
}
int main(int argc, char** argv)
{
printf("Example for srs-librtmp\n");
printf("SRS(ossrs) client librtmp library.\n");
printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision());
// connect rtmp context
const char* rtmp_url = "rtmp://127.0.0.1:1935/live/livestream";
srs_rtmp_t rtmp = srs_rtmp_create(rtmp_url);
if (srs_rtmp_handshake(rtmp) != 0) {
srs_human_trace("simple handshake failed.");
goto rtmp_destroy;
}
srs_human_trace("simple handshake success");
if (srs_rtmp_connect_app(rtmp) != 0) {
srs_human_trace("connect vhost/app failed.");
goto rtmp_destroy;
}
srs_human_trace("connect vhost/app success");
if (srs_rtmp_publish_stream(rtmp) != 0) {
srs_human_trace("publish stream failed.");
goto rtmp_destroy;
}
srs_human_trace("publish stream success");
int n = 0;
int dts = 0;
int pts = 0;
double fps = 25;
while(1){
char str[32];
sprintf(str,"./h265_nalu_frame/test%d.265",n);
char* h265_raw = get_data_frame(str);
if(h265_raw != NULL){
// send out the h265 packet over RTMP
int ret = srs_h265_write_raw_frames(rtmp, h265_raw, file_size, dts, pts);
if (ret != 0) {
if (srs_h265_is_dvbsp_error(ret)) {
srs_human_trace("ignore drop video error, code=%d", ret);
} else if (srs_h265_is_duplicated_sps_error(ret)) {
srs_human_trace("ignore duplicated sps, code=%d", ret);
} else if (srs_h265_is_duplicated_pps_error(ret)) {
srs_human_trace("ignore duplicated pps, code=%d", ret);
} else {
srs_human_trace("send h265 raw data failed. ret=%d", ret);
goto rtmp_destroy;
}
}
}
else break;
dts += 1000 / fps;
pts = dts;
usleep(40 * 1000);
free(h265_raw);
if(++n > 204) n=0;
}
rtmp_destroy:
srs_rtmp_destroy(rtmp);
return 0;
}