当前位置:编程学习 > C/C++ >>

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

在这里在研究研究接收消息(Message)的源代码,接收消息最典型的应用就是接收视音频数据了,因为视频和音频分别都属于RTMP协议规范中的一种消息。在这里主要分析接收视音频数据。
 
RTMPdump中完成视音频数据的接收(也可以说是视音频数据的下载)的函数是:RTMP_Read()。
RTMPdump主程序中的Download()函数就是通过调用RTMP_Read()完成数据接收,从而实现下载的。
 
那么我们马上开始吧,首先看看RTMP_Read()函数:
 
[cpp]  
//FLV文件头  
static const char flvHeader[] = { 'F', 'L', 'V', 0x01,  
  0x00,             /* 0x04代表有音频, 0x01代表有视频 */  
  0x00, 0x00, 0x00, 0x09,  
  0x00, 0x00, 0x00, 0x00  
};  
  
#define HEADERBUF   (128*1024)  
int  
RTMP_Read(RTMP *r, char *buf, int size)  
{  
  int nRead = 0, total = 0;  
  
  /* can't continue */  
fail:  
  switch (r->m_read.status) {  
  case RTMP_READ_EOF:  
  case RTMP_READ_COMPLETE:  
    return 0;  
  case RTMP_READ_ERROR:  /* corrupted stream, resume failed */  
    SetSockError(EINVAL);  
    return -1;  
  default:  
    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 += nR
补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,