分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

=====================================================

最简单的基于libRTMP的示例系列文章列表:

最简单的基于librtmp的示例:接收(RTMP保存为FLV)

最简单的基于librtmp的示例:发布(FLV通过RTMP发布)

最简单的基于librtmp的示例:发布H.264(H.264通过RTMP发布)

=====================================================

本文记录一个基于libRTMP的发布流媒体的程序:Simplest libRTMP Send FLV。该程序可以将本地FLV文件发布到RTMP流媒体服务器。是最简单的基于libRTMP的流媒体发布示例。

流程图

使用librtmp发布RTMP流的可以使用两种API:RTMP_SendPacket()和RTMP_Write()。使用RTMP_SendPacket()发布流的时候的函数执行流程图如下图所示。使用RTMP_Write()发布流的时候的函数执行流程图相差不大。

流程图中关键函数的作用如下所列:

InitSockets():初始化Socket
RTMP_Alloc():为结构体“RTMP”分配内存。
RTMP_Init():初始化结构体“RTMP”中的成员变量。
RTMP_SetupURL():设置输入的RTMP连接的URL。
RTMP_EnableWrite():发布流的时候必须要使用。如果不使用则代表接收流。
RTMP_Connect():建立RTMP连接,创建一个RTMP协议规范中的NetConnection。
RTMP_ConnectStream():创建一个RTMP协议规范中的NetStream。
Delay:发布流过程中的延时,保证按正常播放速度发送数据。
RTMP_SendPacket():发送一个RTMP数据RTMPPacket。
RTMP_Close():关闭RTMP连接。
RTMP_Free():释放结构体“RTMP”。
CleanupSockets():关闭Socket。

源代码

源代码中包含了使用两种API函数RTMP_SendPacket()和RTMP_Write()发布流媒体的源代码,如下所示。

/** * Simplest Librtmp Send FLV * * 雷霄骅,张晖 * leixiaohua1020@126.com * zhanghuicuc@gmail.com * 中国传媒大学/数字电视技术 * Communication University of China / Digital TV Technology * http://blog.csdn.net/leixiaohua1020 * * 本程序用于将FLV格式的视音频文件使用RTMP推送至RTMP流媒体服务器。 * This program can send local flv file to net server as a rtmp live stream. */ #include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdint.h>#ifndef WIN32#include <unistd.h>#endif  #include "librtmp/rtmp_sys.h"#include "librtmp/log.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;} int InitSockets(){         WORD version;         WSADATA wsaData;         version=MAKEWORD(2,2);         return (WSAStartup(version, &wsaData) == 0);} void CleanupSockets(){         WSACleanup();} //Publish using RTMP_SendPacket()int publish_using_packet(){         RTMP *rtmp=NULL;                                    RTMPPacket *packet=NULL;         uint32_t start_time=0;         uint32_t now_time=0;         //the timestamp of the previous frame         long pre_frame_time=0;         long lasttime=0;         int bNextIsKey=1;         uint32_t preTagsize=0;                 //packet attributes         uint32_t type=0;                                 uint32_t datalength=0;                    uint32_t timestamp=0;                    uint32_t streamid=0;                                  FILE*fp=NULL;         fp=fopen("cuc_ieschool.flv","rb");         if (!fp){                   RTMP_LogPrintf("Open File Error.\n");                   CleanupSockets();                   return -1;         }          /* set log level */         //RTMP_LogLevel loglvl=RTMP_LOGDEBUG;         //RTMP_LogSetLevel(loglvl);                           if (!InitSockets()){                   RTMP_LogPrintf("Init Socket Err\n");                   return -1;         }          rtmp=RTMP_Alloc();         RTMP_Init(rtmp);         //set connection timeout,default 30s         rtmp->Link.timeout=5;                               if(!RTMP_SetupURL(rtmp,"rtmp://localhost/publishlive/livestream"))         {                   RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n");                   RTMP_Free(rtmp);                   CleanupSockets();                   return -1;         }                 //if unable,the AMF command would be 'play' instead of 'publish'         RTMP_EnableWrite(rtmp);                      if (!RTMP_Connect(rtmp,NULL)){                   RTMP_Log(RTMP_LOGERROR,"Connect Err\n");                   RTMP_Free(rtmp);                   CleanupSockets();                   return -1;         }                 if (!RTMP_ConnectStream(rtmp,0)){                   RTMP_Log(RTMP_LOGERROR,"ConnectStream Err\n");                   RTMP_Close(rtmp);                   RTMP_Free(rtmp);                   CleanupSockets();                   return -1;         }          packet=(RTMPPacket*)malloc(sizeof(RTMPPacket));         RTMPPacket_Alloc(packet,1024*64);         RTMPPacket_Reset(packet);          packet->m_hasAbsTimestamp = 0;                 packet->m_nChannel = 0x04;         packet->m_nInfoField2 = rtmp->m_stream_id;          RTMP_LogPrintf("Start to send data ...\n");                 //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)) && bNextIsKey){                                    //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:%8lu ms\n",pre_frame_time);                                     lasttime=pre_frame_time;                            }                            Sleep(1000);                            continue;                   }                                     //not quite the same as FLV spec                   if(!ReadU8(&type,fp))                                 break;                   if(!ReadU24(&datalength,fp))                            break;                   if(!ReadTime(×tamp,fp))                            break;                   if(!ReadU24(&streamid,fp))                            break;                    if (type!=0x08&&type!=0x09){                            //jump over non_audio and non_video frame,                            //jump over next previousTagSizen at the same time                            fseek(fp,datalength+4,SEEK_CUR);                            continue;                   }                                     if(fread(packet->m_body,1,datalength,fp)!=datalength)                            break;                    packet->m_headerType = RTMP_PACKET_SIZE_LARGE;                   packet->m_nTimeStamp = timestamp;                   packet->m_packetType = type;                   packet->m_nBodySize  = datalength;                   pre_frame_time=timestamp;                    if (!RTMP_IsConnected(rtmp)){                            RTMP_Log(RTMP_LOGERROR,"rtmp is not connect\n");                            break;                   }                   if (!RTMP_SendPacket(rtmp,packet,0)){                            RTMP_Log(RTMP_LOGERROR,"Send Error\n");                            break;                   }                    if(!ReadU32(&preTagsize,fp))                            break;                                              if(!PeekU8(&type,fp))                            break;                   if(type==0x09){                            if(fseek(fp,11,SEEK_CUR)!=0)                                     break;                            if(!PeekU8(&type,fp)){                                     break;                            }                            if(type==0x17)                                     bNextIsKey=1;                            else                                     bNextIsKey=0;                             fseek(fp,-11,SEEK_CUR);                   }         }                         RTMP_LogPrintf("\nSend Data Over\n");                 if(fp)                   fclose(fp);          if (rtmp!=NULL){                   RTMP_Close(rtmp);                           RTMP_Free(rtmp);                    rtmp=NULL;         }         if (packet!=NULL){                   RTMPPacket_Free(packet);                       free(packet);                   packet=NULL;         }          CleanupSockets();         return 0;} //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 bNextIsKey=0;         char* pFileBuf=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 (!fp){                   RTMP_LogPrintf("Open File Error.\n");                   CleanupSockets();                   return -1;         }          /* set log level */         //RTMP_LogLevel loglvl=RTMP_LOGDEBUG;         //RTMP_LogSetLevel(loglvl);                           if (!InitSockets()){                  RTMP_LogPrintf("Init Socket Err\n");                   return -1;         }          rtmp=RTMP_Alloc();         RTMP_Init(rtmp);         //set connection timeout,default 30s         rtmp->Link.timeout=5;                               if(!RTMP_SetupURL(rtmp,"rtmp://localhost/publishlive/livestream"))         {                   RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n");                   RTMP_Free(rtmp);                   CleanupSockets();                   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);                   CleanupSockets();                   return -1;         }                 if (!RTMP_ConnectStream(rtmp,0)){                   RTMP_Log(RTMP_LOGERROR,"ConnectStream Err\n");                   RTMP_Close(rtmp);                   RTMP_Free(rtmp);                   CleanupSockets();                   return -1;         }          printf("Start to send data ...\n");                 //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)) && bNextIsKey){                                    //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:%8lu ms\n",pre_frame_time);                                     lasttime=pre_frame_time;                            }                            Sleep(1000);                            continue;                   }                                     //jump over type                   fseek(fp,1,SEEK_CUR);                      if(!ReadU24(&datalength,fp))                            break;                   if(!ReadTime(×tamp,fp))                            break;                   //jump back                   fseek(fp,-8,SEEK_CUR);                                       pFileBuf=(char*)malloc(11+datalength+4);                   memset(pFileBuf,0,11+datalength+4);                   if(fread(pFileBuf,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,pFileBuf,11+datalength+4)){                            RTMP_Log(RTMP_LOGERROR,"Rtmp Write Error\n");                            break;                   }                                     free(pFileBuf);                   pFileBuf=NULL;                    if(!PeekU8(&type,fp))                            break;                   if(type==0x09){                            if(fseek(fp,11,SEEK_CUR)!=0)                                     break;                            if(!PeekU8(&type,fp)){                                     break;                            }                            if(type==0x17)                                     bNextIsKey=1;                            else                                     bNextIsKey=0;                            fseek(fp,-11,SEEK_CUR);                   }         }          RTMP_LogPrintf("\nSend Data Over\n");                 if(fp)                   fclose(fp);          if (rtmp!=NULL){                   RTMP_Close(rtmp);                           RTMP_Free(rtmp);                   rtmp=NULL;         }          if(pFileBuf){                   free(pFileBuf);                   pFileBuf=NULL;         }          CleanupSockets();         return 0;} int main(int argc, char* argv[]){         //2 Methods:         publish_using_packet();         //publish_using_write();         return 0;}

运行结果

程序运行后,会将“cuc_ieschool.flv”文件以直播流的形式发布到“rtmp://localhost/publishlive/livestream”的URL。修改文件名称和RTMP的URL可以实现将任意flv文件发布到任意RTMP的URL。

下载

Simplest LibRTMP Example

项目主页

SourceForge:https://sourceforge.net/projects/simplestlibrtmpexample/

Github:https://github.com/leixiaohua1020/simplest_librtmp_example

开源中国:http://git.oschina.net/leixiaohua1020/simplest_librtmp_example

CSDN下载: http://download.csdn.net/detail/leixiaohua1020/8291757
 
本工程包含了LibRTMP的使用示例,包含如下子工程:
simplest_librtmp_receive: 接收RTMP流媒体并在本地保存成FLV格式的文件。
simplest_librtmp_send_flv: 将FLV格式的视音频文件使用RTMP推送至RTMP流媒体服务器。
simplest_librtmp_send264: 将内存中的H.264数据推送至RTMP流媒体服务器。

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

你好! 这是你第一次使用 **Markdown编辑器** 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

新的改变

我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:

  1. 全新的界面设计 ,将会带来全新的写作体验;
  2. 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
  3. 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
  4. 全新的 KaTeX数学公式 语法;
  5. 增加了支持甘特图的mermaid语法1 功能;
  6. 增加了 多屏幕编辑 Markdown文章功能;
  7. 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
  8. 增加了 检查列表 功能。

功能快捷键

撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G

合理的创建标题,有助于目录的生成

直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。

如何改变文本的样式

强调文本 强调文本

加粗文本 加粗文本

标记文本

删除文本

引用文本

H2O is是液体。

210 运算结果是 1024.

插入链接与图片

链接: link.

图片:

带尺寸的图片:

当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

如何插入一段漂亮的代码片

去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block var foo = 'bar'; 

生成一个适合你的列表

  • 项目

    • 项目

      • 项目
  1. 项目1
  2. 项目2
  3. 项目3
  • 计划任务
  • 完成任务

创建一个表格

一个简单的表格是这么创建的:

项目 Value
电脑 $1600
手机 $12
导管 $1

设定内容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列 第二列 第三列
第一列文本居中 第二列文本居右 第三列文本居左

SmartyPants

SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:

TYPE ASCII HTML
Single backticks 'Isn't this fun?' ‘Isn’t this fun?’
Quotes "Isn't this fun?" “Isn’t this fun?”
Dashes -- is en-dash, --- is em-dash – is en-dash, — is em-dash

创建一个自定义列表

Markdown
Text-to- HTML conversion tool
Authors
John
Luke

如何创建一个注脚

一个具有注脚的文本。2

注释也是必不可少的

Markdown将文本转换为 HTML

KaTeX数学公式

您可以使用渲染LaTeX数学表达式 KaTeX:

Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n−1)!∀n∈N 是通过欧拉积分

Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t &ThinSpace; . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=∫0∞​tz−1e−tdt.

你可以找到更多关于的信息 LaTeX 数学表达式here.

新的甘特图功能,丰富你的文章

ganttdateFormat  YYYY-MM-DDtitle Adding GANTT diagram functionality to mermaidsection 现有任务已完成               :done,    des1, 2014-01-06,2014-01-08进行中               :active,  des2, 2014-01-09, 3d计划一               :         des3, after des2, 5d计划二               :         des4, after des3, 5d
  • 关于 甘特图 语法,参考 这儿,

UML 图表

可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图::

张三 李四 王五 你好!李四, 最近怎么样? 你最近怎么样,王五? 我很好,谢谢! 我很好,谢谢! 李四想了很长时间, 文字太长了 不适合放在一行. 打量着王五... 很好... 王五, 你怎么样? 张三 李四 王五

这将产生一个流程图。:

链接
长方形
圆角长方形
菱形
  • 关于 Mermaid 语法,参考 这儿,

FLowchart流程图

我们依旧会支持flowchart的流程图:

  • 关于 Flowchart流程图 语法,参考 这儿.

导出与导入

导出

如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。

导入

如果你想加载一篇你写过的.md文件或者.html文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。


  1. mermaid语法说明 ↩︎

  2. 注脚的解释 ↩︎

最简单的基于librtmp的示例 发布(FLV通过RTMP发布)相关推荐

  1. 最简单的基于librtmp的示例:接收(RTMP保存为FLV)

    https://blog.csdn.net/leixiaohua1020/article/details/42104893 https://blog.csdn.net/u013470102/artic ...

  2. 最简单的基于librtmp的示例:发布H.264(H.264通过RTMP发布)

    ===================================================== 最简单的基于libRTMP的示例系列文章列表: 最简单的基于librtmp的示例:接收(RT ...

  3. 最简单的基于DirectShow的示例:获取Filter信息

    ===================================================== 最简单的基于DirectShow的示例文章列表: 最简单的基于DirectShow的示例:视 ...

  4. 最简单的基于DirectShow的示例:视频播放器自定义版

    ===================================================== 最简单的基于DirectShow的示例文章列表: 最简单的基于DirectShow的示例:视 ...

  5. 最简单的基于DirectShow的示例:视频播放器图形界面版

    ===================================================== 最简单的基于DirectShow的示例文章列表: 最简单的基于DirectShow的示例:视 ...

  6. 最简单的基于DirectShow的示例:视频播放器

    ===================================================== 最简单的基于DirectShow的示例文章列表: 最简单的基于DirectShow的示例:视 ...

  7. 最简单的基于 DirectShow 的视频播放器

    源程序下载链接:https://download.csdn.net/download/bmjhappy/11250669 50行代码实现的一个最简单的基于 DirectShow 的视频播放器 本文介绍 ...

  8. 转:最简单的基于 DirectShow 的视频播放器

    50行代码实现的一个最简单的基于 DirectShow 的视频播放器 本文介绍一个最简单的基于 DirectShow 的视频播放器.该播放器对于初学者来说是十分有用的,它包含了使用 DirectSho ...

  9. 通过Dapr实现一个简单的基于.net的微服务电商系统(四)——一步一步教你如何撸Dapr之订阅发布...

    之前的章节我们介绍了如何通过dapr发起一个服务调用,相信看过前几章的小伙伴已经对dapr有一个基本的了解了,今天我们来聊一聊dapr的另外一个功能--订阅发布 目录: 一.通过Dapr实现一个简单的 ...

最新文章

  1. Eclipse轻松玩转SmartFramework
  2. 外链对网站SEO优化起什么作用?
  3. Java程序员从阿里、京东、美团面试回来,这些面试题你会吗?
  4. hdu1285 拓扑序
  5. SpringBoot集成JPA
  6. C/C++学习之路_九:文件操作
  7. c#操作XML文件 1614260503
  8. 保持函数依赖的模式分解可以减轻或解决什么_为什么我更喜欢函数式编程?
  9. VS2010链接SQLsever2008数据库时出现[DBNETLIB][ConnectionOpen (Connect()).]SQL Server 不存在或拒
  10. java 消费者模式 多线程_[Java并发-24-并发设计模式] 生产者-消费者模式,并发提高效率...
  11. Java笔记(1):final关键字
  12. docker设置不同网络和迁移到指定网络
  13. php底部导航栏,微信小程序之底部导航栏目开发(附代码)
  14. 厉害了!机器视觉在农业中的应用
  15. 怎么样把书上的字很快的弄成电子版,哈哈,我也会了
  16. 谈用户裂变,社群裂变的重要性
  17. 升级至android 5.0,OPPO X9007 升级到Android5.0 Color2.1(root版) 详细纪实
  18. 初中英语语法(008)-动词不定式
  19. 《狂人日记》 解读|读后感
  20. 你认为vscode和visual studio哪个好?

热门文章

  1. 文本翻译免费软件-word免费翻译软件
  2. EXTEND RRT
  3. Android AIDL(接口定义语言)简单理解和基本使用方法
  4. Springboot配置undertow容器
  5. 【朝夕教育】2023年04月 WPF运动控制平台-002.运动控制平台知识点学习
  6. 计算机视觉顶级会议和期刊(中英文全称)
  7. 2021年全球及中国独角兽企业发展分析:中国有3家企业进入全球前十[图]
  8. 【随笔】2018年10月之家庭篇
  9. java实现mysql备份_Java实现MySQL数据库备份
  10. 入门createjs———EaselJS模块基本介绍