RTMPdump(libRTMP) 源代码分析 9 接收消息(Message)(接收视音频数据)

分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.youkuaiyun.com/jiangjunshow

               

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

RTMPdump(libRTMP) 源代码分析系列文章:

RTMPdump 源代码分析 1: main()函数

RTMPDump (libRTMP) 源代码分析2:解析RTMP地址——RTMP_ParseURL()

RTMPdump (libRTMP) 源代码分析3: AMF编码

RTMPdump (libRTMP) 源代码分析4: 连接第一步——握手 (HandShake)

RTMPdump (libRTMP) 源代码分析5: 建立一个流媒体连接  (NetConnection部分)

RTMPdump (libRTMP) 源代码分析6: 建立一个流媒体连接  (NetStream部分 1)

RTMPdump (libRTMP) 源代码分析7: 建立一个流媒体连接  (NetStream部分 2)

RTMPdump (libRTMP) 源代码分析8: 发送消息 (Message)

RTMPdump (libRTMP) 源代码分析9: 接收消息 (Message)  (接收视音频数据)

RTMPdump (libRTMP) 源代码分析10: 处理各种消息 (Message)

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


函数调用结构图

RTMPDump (libRTMP)的整体的函数调用结构图如下图所示。


单击查看大图

详细分析

前一篇文章分析了RTMPdump(libRTMP) 的发送消息(Message)方面的源代码:RTMPdump(libRTMP) 源代码分析 8: 发送消息(Message)

在这里在研究研究接收消息(Message)的源代码,接收消息最典型的应用就是接收视音频数据了,因为视频和音频分别都属于RTMP协议规范中的一种消息。在这里主要分析接收视音频数据。

RTMPdump中完成视音频数据的接收(也可以说是视音频数据的下载)的函数是:RTMP_Read()。

RTMPdump主程序中的Download()函数就是通过调用RTMP_Read()完成数据接收,从而实现下载的。

那么我们马上开始吧,首先看看RTMP_Read()函数:

//FLV文件头static const char flvHeader[] = { 'F', 'L', 'V', 0x010x00,    /* 0x04代表有音频, 0x01代表有视频 */  0x00, 0x00, 0x00, 0x090x00, 0x00, 0x00, 0x00};#define HEADERBUF (128*1024)intRTMP_Read(RTMP *r, char *buf, int size)int nRead = 0, total = 0/* can't continue */fail:  switch (r-&gt;m_read.status) {  case RTMP_READ_EOF:  case RTMP_READ_COMPLETE:    return 0case RTMP_READ_ERROR:  /* corrupted stream, resume failed */    SetSockError(EINVAL);    return -1default:    break;  }  /* first time thru */  if (!(r->m_read.flags & RTMP_READ_HEADER))    {      if (!(r->m_read.flags & RTMP_READ_RESUME)) { //分配内存,指向buf的首部和尾部   char *mybuf = (char *) malloc(HEADERBUF), *end = mybuf + HEADERBUF;   int cnt = 0;   //buf指向同一地址   r->m_read.buf = mybuf;   r->m_read.buflen = HEADERBUF;   //把Flv的首部复制到mybuf指向的内存   //RTMP传递的多媒体数据是“砍头”的FLV文件   memcpy(mybuf, flvHeader, sizeof(flvHeader));   //m_read.buf指针后移flvheader个单位   r->m_read.buf += sizeof(flvHeader);   //buf长度增加flvheader长度   r->m_read.buflen -= sizeof(flvHeader);   //timestamp=0,不是多媒体数据   while (r->m_read.timestamp == 0)     {  //读取一个Packet,到r->m_read.buf  //nRead为读取结果标记       nRead = Read_1_Packet(r, r->m_read.buf, r->m_read.buflen);    //有错误       if (nRead < 0)  {    free(mybuf);    r->m_read.buf = NULL;    r->m_read.buflen = 0;    r->m_read.status = nRead;    goto fail;  }       /* buffer overflow, fix buffer and give up */       if (r->m_read.buf < mybuf || r->m_read.buf > end) {        mybuf = (char *) realloc(mybuf, cnt + nRead);  memcpy(mybuf+cnt, r->m_read.buf, nRead);  r->m_read.buf = mybuf+cnt+nRead;         break;       }    //    //记录读取的字节数       cnt += nRead;    //m_read.buf指针后移nRead个单位       r->m_read.buf += nRead;       r->m_read.buflen -= nRead;    //当dataType=00000101时,即有视频和音频时    //说明有多媒体数据了       if (r->m_read.dataType == 5)         break;     }   //读入数据类型   //注意:mybuf指针位置一直没动   //mybuf[4]中第 6 位表示是否存在音频Tag。第 8 位表示是否存在视频Tag。    mybuf[4] = r->m_read.dataType;   //两个指针之间的差   r->m_read.buflen = r->m_read.buf - mybuf;   r->m_read.buf = mybuf;   //这句很重要!后面memcopy   r->m_read.bufpos = mybuf; }   //flags标明已经读完了文件头      r->m_read.flags |= RTMP_READ_HEADER;    }  if ((r->m_read.flags & RTMP_READ_SEEKING) && r->m_read.buf)    {      /* drop whatever's here */      free(r->m_read.buf);      r->m_read.buf = NULL;      r->m_read.bufpos = NULL;      r->m_read.buflen = 0;    }  /* If there's leftover data buffered, use it up */  if (r->m_read.buf)    {      nRead = r->m_read.buflen;      if (nRead > size) nRead = size;   //m_read.bufpos指向mybuf      memcpy(buf, r->m_read.bufpos, nRead);      r->m_read.buflen -= nRead;      if (!r->m_read.buflen) {   free(r->m_read.buf);   r->m_read.buf = NULL;   r->m_read.bufpos = NULL; }      else {   r->m_read.bufpos += nRead; }      buf += nRead;      total += nRead;      size -= nRead;    }  //接着读  while (size > 0 && (nRead = Read_1_Packet(r, buf, size)) >= 0)    {      if (!nRead) continue;      buf += nRead;      total += nRead;      size -= nRead;      break;    }  if (nRead < 0)    r->m_read.status = nRead;  if (size < 0)    total += size;  return total;}

程序关键的地方都已经注释上了代码,在此就不重复说明了。有一点要提一下:RTMP传送的视音频数据的格式和FLV(FLash Video)格式是一样的,把接收下来的数据直接存入文件就可以了。但是这些视音频数据没有文件头,是
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值