srs-librtmp pusher(push h264 raw)
Simple Live System Using SRS
https://www.cnblogs.com/dong1/p/5100792.html
1、上面是推送文件,改成推送缓存
封装了三个函数
int srs_librtmp_connect(srs_rtmp_t rtmp);
int srs_librtmp_push(srs_rtmp_t rtmp, char* h264_raw, off_t file_size, double fps);
int srs_librtmp_close(srs_rtmp_t rtmp);
- /*
- The MIT License (MIT)
- Copyright (c) 2013-2015 SRS(ossrs)
- Permission is hereby granted, free of charge, to any person obtaining a copy of
- this software and associated documentation files (the "Software"), to deal in
- the Software without restriction, including without limitation the rights to
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- the Software, and to permit persons to whom the Software is furnished to do so,
- subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
- /**
- gcc srs_h264_raw_publish.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_h264_raw_publish
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- // for open h264 raw file.
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include "srs_librtmp.h"
- static off_t file_size;
- int read_h264_frame(char* data, int size, char** pp, int* pnb_start_code, int fps,
- char** frame, int* frame_size, int* dts, int* pts)
- {
- char* p = *pp;
- // @remark, for this demo, to publish h264 raw file to SRS,
- // we search the h264 frame from the buffer which cached the h264 data.
- // please get h264 raw data from device, it always a encoded frame.
- if (!srs_h264_startswith_annexb(p, size - (p - data), pnb_start_code)) {
- srs_human_trace("h264 raw data invalid.");
- return -;
- }
- // @see srs_write_h264_raw_frames
- // each frame prefixed h.264 annexb header, by N[00] 00 00 01, where N>=0,
- // for instance, frame = header(00 00 00 01) + payload(67 42 80 29 95 A0 14 01 6E 40)
- *frame = p;
- p += *pnb_start_code;
- for (;p < data + size; p++) {
- if (srs_h264_startswith_annexb(p, size - (p - data), NULL)) {
- break;
- }
- }
- *pp = p;
- *frame_size = p - *frame;
- if (*frame_size <= ) {
- srs_human_trace("h264 raw data invalid.");
- return -;
- }
- // @remark, please get the dts and pts from device,
- // we assume there is no B frame, and the fps can guess the fps and dts,
- // while the dts and pts must read from encode lib or device.
- *dts += / fps;
- *pts = *dts;
- return ;
- }
- int srs_librtmp_connect(srs_rtmp_t rtmp)
- {
- if (srs_rtmp_handshake(rtmp) != ) {
- srs_human_trace("simple handshake failed.");
- return -;
- }
- srs_human_trace("simple handshake success");
- if (srs_rtmp_connect_app(rtmp) != ) {
- srs_human_trace("connect vhost/app failed.");
- return -;
- }
- srs_human_trace("connect vhost/app success");
- if (srs_rtmp_publish_stream(rtmp) != ) {
- srs_human_trace("publish stream failed.");
- return -;
- }
- srs_human_trace("publish stream success");
- return ;
- }
- char* get_data_frame(void)
- {
- const char* raw_file = "./720p.h264.raw";
- // open file
- int raw_fd = open(raw_file, O_RDONLY);
- if (raw_fd < ) {
- srs_human_trace("open h264 raw file %s failed.", raw_file);
- return NULL;
- }
- file_size = lseek(raw_fd, , SEEK_END);
- if (file_size <= ) {
- 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, , SEEK_SET);
- ssize_t nb_read = ;
- 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 / ), (int)(nb_read / ));
- return NULL;
- }
- close(raw_fd);
- return h264_raw;
- }
- int srs_librtmp_push(srs_rtmp_t rtmp, char* h264_raw, off_t file_size, double fps)
- {
- int dts = ;
- int pts = ;
- // @remark, to decode the file.
- char* p = h264_raw;
- int count = ;
- //while(1){
- for (; p < h264_raw + file_size;) {
- // @remark, read a frame from file buffer.
- char* data = NULL;
- int size = ;
- int nb_start_code = ;
- if (read_h264_frame(h264_raw, (int)file_size, &p, &nb_start_code, fps, &data, &size, &dts, &pts) < ) {
- srs_human_trace("read a frame from file buffer failed.");
- return -;
- }
- // send out the h264 packet over RTMP
- int ret = srs_h264_write_raw_frames(rtmp, data, size, dts, pts);
- if (ret != ) {
- 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);
- return -;
- }
- }
- // 5bits, 7.3.1 NAL unit syntax,
- // H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
- // 7: SPS, 8: PPS, 5: I Frame, 1: P Frame, 9: AUD, 6: SEI
- u_int8_t nut = (char)data[nb_start_code] & 0x1f;
- srs_human_trace("sent packet: type=%s, time=%d, size=%d, fps=%.2f, b[%d]=%#x(%s)",
- srs_human_flv_tag_type2string(SRS_RTMP_TYPE_VIDEO), dts, size, fps, nb_start_code, (char)data[nb_start_code],
- (nut == ? "SPS":(nut == ? "PPS":(nut == ? "I":(nut == ? "P":(nut == ? "AUD":(nut == ? "SEI":"Unknown")))))));
- // @remark, when use encode device, it not need to sleep.
- if (count++ == ) {
- usleep( * * count / fps);
- count = ;
- }
- }
- srs_human_trace("h264 raw data completed");
- p = h264_raw;
- //}
- return ;
- }
- int srs_librtmp_close(srs_rtmp_t rtmp)
- {
- srs_rtmp_destroy(rtmp);
- return ;
- }
- int main(int argc, char** argv)
- {
- printf("publish raw h.264 as rtmp stream to server like FMLE/FFMPEG/Encoder\n");
- printf("SRS(ossrs) client librtmp library.\n");
- printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision());
- const char* rtmp_url = "rtmp://127.0.0.1:1935/live/livestream";
- srs_rtmp_t rtmp = srs_rtmp_create(rtmp_url);
- srs_librtmp_connect(rtmp);
- double fps = ;
- char* h264_raw = get_data_frame();
- while(){
- srs_librtmp_push(rtmp,h264_raw,file_size,fps);
- }
- srs_librtmp_close(rtmp);
- free(h264_raw);
- return ;
- }
gcc srs_h264_raw_publish.c -I $(pwd)/srs-librtmp/include ./srs-librtmp/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_h264_raw_publish
./srs_h264_raw_publish
2、上面是为了省事,直接一堆缓存让read_h264_frame去解出h264数据nalu,再推送,基本没什么实用价值。
正儿八经做了个demo,一帧一帧推送数据
https://files.cnblogs.com/files/dong1/srs-librtmp_pusher_demo.zip
直接srs-librtmp.c源码参与编译的demo
https://files.cnblogs.com/files/dong1/srs-librtmp_demo.zip
3、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 < ) {
- srs_human_trace("open h264 raw file %s failed.", raw_file);
- return NULL;
- }
- file_size = lseek(raw_fd, , SEEK_END);
- if (file_size <= ) {
- 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, , SEEK_SET);
- ssize_t nb_read = ;
- 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 / ), (int)(nb_read / ));
- 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) != ) {
- srs_human_trace("simple handshake failed.");
- goto rtmp_destroy;
- }
- srs_human_trace("simple handshake success");
- if (srs_rtmp_connect_app(rtmp) != ) {
- srs_human_trace("connect vhost/app failed.");
- goto rtmp_destroy;
- }
- srs_human_trace("connect vhost/app success");
- if (srs_rtmp_publish_stream(rtmp) != ) {
- srs_human_trace("publish stream failed.");
- goto rtmp_destroy;
- }
- srs_human_trace("publish stream success");
- int n = ;
- int dts = ;
- int pts = ;
- double fps = ;
- while(){
- char str[];
- 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 != ) {
- 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 += / fps;
- pts = dts;
- usleep( * );
- free(h264_raw);
- if(++n > ) n=;
- }
- rtmp_destroy:
- srs_rtmp_destroy(rtmp);
- return ;
- }
https://files.cnblogs.com/files/dong1/srs-librtmp_single.zip
4、推送多路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 < ) {
- srs_human_trace("open h264 raw file %s failed.", raw_file);
- return NULL;
- }
- file_size = lseek(raw_fd, , SEEK_END);
- if (file_size <= ) {
- 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, , SEEK_SET);
- ssize_t nb_read = ;
- 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 / ), (int)(nb_read / ));
- 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 = ;
- int dts = ;
- int pts = ;
- double fps = ;
- // connect rtmp context
- const char* rtmp_url = "rtmp://127.0.0.1:1935/live/livestream";
- char url[]={};
- sprintf(url,"%s%d",rtmp_url,num);
- printf("%s\n",url);
- srs_rtmp_t rtmp = srs_rtmp_create(url);
- if (srs_rtmp_handshake(rtmp) != ) {
- srs_human_trace("simple handshake failed.");
- goto rtmp_destroy;
- }
- srs_human_trace("simple handshake success");
- if (srs_rtmp_connect_app(rtmp) != ) {
- srs_human_trace("connect vhost/app failed.");
- goto rtmp_destroy;
- }
- srs_human_trace("connect vhost/app success");
- if (srs_rtmp_publish_stream(rtmp) != ) {
- srs_human_trace("publish stream failed.");
- goto rtmp_destroy;
- }
- srs_human_trace("publish stream success");
- while(){
- char str[];
- 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 != ) {
- 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 += / fps;
- pts = dts;
- usleep( * );
- free(h264_raw);
- if(++n > ) n=;
- }
- 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, )) != 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, ) == ) {
- }
- int num = ;
- if(threadpool_add(pool, &sink_task, &num, ) == ) {
- }
- int num1 = ;
- if(threadpool_add(pool, &sink_task, &num1, ) == ) {
- }
- int num2 = ;
- if(threadpool_add(pool, &sink_task, &num2, ) == ) {
- }
- #else
- pthread_t rtmp_id,rtmp_id1,rtmp_id2;
- int num = ;
- int ret = pthread_create(&rtmp_id,NULL,sink_task, &num);
- if(ret!=)
- {
- printf("Create pthread error!\n");
- }
- int num1 = ;
- ret = pthread_create(&rtmp_id1,NULL,sink_task, &num1);
- if(ret!=)
- {
- printf("Create pthread error!\n");
- }
- int num2 = ;
- ret = pthread_create(&rtmp_id2,NULL,sink_task, &num2);
- if(ret!=)
- {
- printf("Create pthread error!\n");
- }
- #endif
- while()
- {
- sleep();
- }
- assert(threadpool_destroy(pool, ) == );
- }
- int main(int argc, char** argv)
- {
- pthread_t signal_id;
- int ret = pthread_create(&signal_id,NULL,signal_task, NULL);
- if(ret!=)
- {
- return -;
- }
- while()
- {
- sleep();
- }
- return ;
- }
https://files.cnblogs.com/files/dong1/srs-librtmp_multiple.zip
end
srs-librtmp pusher(push h264 raw)的更多相关文章
- srs(srs-librtmp推送h264原始数据)
1.下载最新srs源码 https://github.com/ossrs/srs/releases 2.编译(进入~/srs-2.0-r4/trunk目录) ./configure --with-li ...
- Push h.264 rawdata to rtmp server
Push h.264 rawdata to rtmp server /* The MIT License (MIT) Copyright (c) 2013-2015 SRS(ossrs) Permis ...
- 海康摄像机使用GB28181接入SRS服务器的搭建步骤---源码安装的方式
下载代码 地址:https://github.com/ossrs/srs-gb28181 https://github.com/ossrs/srs-gb28181.git 注意:使用的是含有gb281 ...
- docker push 实现过程
这一篇文章分析一下docker push的过程:docker push是将本地的镜像上传到registry service的过程: 根据前几篇文章,可以知道客户端的命令是在api/client/pus ...
- RTP协议全解析(H264码流和PS流)
转自:http://blog.csdn.net/chen495810242/article/details/39207305 写在前面:RTP的解析,网上找了很多资料,但是都不全,所以我力图整理出一个 ...
- (转)RTP协议全解(H264码流和PS流)
写在前面:RTP的解析,网上找了很多资料,但是都不全,所以我力图整理出一个比较全面的解析, 其中借鉴了很多文章,我都列在了文章最后,在此表示感谢. 互联网的发展离不开大家的无私奉献,我决定从我做起,希 ...
- RTP协议全解(H264码流和PS流)
写在前面:RTP的解析,网上找了很多资料,但是都不全,所以我力图整理出一个比较全面的解析, 其中借鉴了很多文章,我都列在了文章最后,在此表示感谢. 互联网的发展离不开大家的无私奉献,我决定从我做起,希 ...
- H264 NALU 使用PS封装 RTP发送
最近由于项目平台需求,要将H264 NALU封装为PS再用RTP发送,PS封装按照ISO DEC-13818-1标准.一个PS包包含PS Header, PES Header, PS system h ...
- RTP Payload Format for H264 Video
基础传输结构 rtp中对于h264数据的存储分为两层,分别是 VCL: video coding layer 视频编码层 这是h264中block, macro block 以及 slice级别的定义 ...
随机推荐
- BP算法演示
本文转载自https://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/ Background Backpropaga ...
- 二、angular7的基础知识学习
<p> hello works </p> <div *ngIf="isShow">我是测试内容</div> <p> &l ...
- Sign on Fence(连续的长为W的一段中最小的数字的最大值)
题目链接:http://codeforces.com/problemset/problem/484/E 题意:给你个n,n个木板都有高度,宽度都为1 ,给你两个数[l,r]和一个w,求在[l,r]区间 ...
- IE等浏览器兼容问题解决方案
<meta http-equiv="X-UA-Compatible" content="IE=100" /> 在<head>标签中添加.
- leetcode-mid-array-5. Longest Palindromic Substring
mycode 12.51% class Solution(object): def longestPalindrome(self, s): """ :type s: ...
- 邻近双线性插值图像缩放的Python实现
最近在查找有关图像缩放之类的算法,因工作中需要用到诸如此类的图像处理算法就在网上了解了一下相关算法,以及其原理,并用Python实现,且亲自验证过,在次与大家分享. 声明:本文代码示例针对的是plan ...
- 关于linux中移动目录和到指定目录和移动目录中的数据到指定目录
#这里表示将目录node-v12.13.1-linux-x64移动到/usr/local/中重命名为node,所以node目录可以不存在[root@alone ~]# mv node-v12.13.1 ...
- PHP图片处理
开启GD扩展(php_gd2.dll) 创建画布 画布:一种资源型数据,可以操作的图像资源. 创建新画布(新建) ImageCreate(宽,高);创建基于调色板的画布. imageCreateTru ...
- 阿里云ipv6安全组匹配所有ip的方法
IPv4和IPv6通信彼此独立.您需要为ECS实例单独配置IPv6安全组规则. 操作步骤 登录ECS控制台. 在左侧导航栏,单击网络和安全 > 安全组. 找到目标安全组,然后单击配置规则. 单击 ...
- mysql 添加外键报错:
1.报错信息 Cannot add or update a child row: a foreign key constraint fails 2.原因分析 [1]字段的数据类型 父表: 子表: 以上 ...