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++ ,
- 更多C/C++疑问解答:
- 关于c++的cout输出的问题。
- 在学校里学过C和C++,不过学的很一般,现在自学C#,会不会很难?
- 全国计算机二级C语言笔试题
- 已知某树有2个2度结点,3个3度结点,4个4度结点,问有几个叶子结点?
- c++数据结构内部排序问题,整数排序
- 2012九月计算机二级C语言全国题库,,急求急求
- 如果assert只有一个字符串作为参数,是什么意思呢?
- C语言中,哪些运算符具有左结合性,哪些具有右结合性,帮忙总结下,谢谢了!
- 为什么用结构体编写的程序输入是,0输不出来啊~~~
- 将IEEE—754的十六进制转化为十进制浮点类型,用C或C++都行,多谢各位大侠啊,非常感谢!
- 为什么这个程序求不出公式?
- 这个链表倒置的算法请大家分析下
- c语言函数库调用
- C语言unsigned int纠错
- C语言快排求解啊