srs-librtmp pusher(push h264/h265 raw)

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;
}
 
posted @ 2019-03-26 14:53  dong1  阅读(4140)  评论(0编辑  收藏  举报