rtmpdump可以下载rtmp流并保存成flv文件。
如果要对流中的音频或视频单独处理,需要根据flv协议分别提取。
简单修改rtmpdump代码,增加相应功能。
1 提取音频:
rtmpdump程序在Download函数中循环下载:
....
 do
 {
....
nRead = RTMP_Read(rtmp, buffer, bufferSize);
....
}while(!RTMP_ctrlC && nRead > -1 && RTMP_IsConnected(rtmp) && !RTMP_IsTimedout(rtmp));
....

原程序是收到后写文件,生成flv。
现在,在写之前分别提取音视频,提取音频比较简单,直接分析buffer(参考RTMP_Write函数里的方法).
注意的是,rtmpdump里用的是RTMP_Read来接收,注意它的参数。为了方便,也可以直接用RTMP_ReadPacket。后面的视频使用RTMP_ReadPacket来接收并处理。

int RTMP_Write2(RTMP *r, const char *buf, int size)
{
  RTMPPacket *pkt = &r->m_write;
  char *pend, *enc;
  int s2 = size, ret, num;

if (size < 11) {
   /* FLV pkt too small */
   return 0;
 }

if (buf[0] == 'F' && buf[1] == 'L' && buf[2] == 'V')
   {
     buf += 13;
     s2 -= 13;
   }

pkt->m_packetType = *buf++;
 pkt->m_nBodySize = AMF_DecodeInt24(buf);
 buf += 3;
 pkt->m_nTimeStamp = AMF_DecodeInt24(buf);
 buf += 3;
 pkt->m_nTimeStamp |= *buf++ << 24;
 buf += 3;
 s2 -= 11;

if (((pkt->m_packetType == RTMP_PACKET_TYPE_AUDIO
                || pkt->m_packetType == RTMP_PACKET_TYPE_VIDEO) &&
            !pkt->m_nTimeStamp) || pkt->m_packetType == RTMP_PACKET_TYPE_INFO)
   {
     pkt->m_headerType = RTMP_PACKET_SIZE_LARGE;
     if (pkt->m_packetType == RTMP_PACKET_TYPE_INFO)
      pkt->m_nBodySize += 16;
   }
 else
   {
     pkt->m_headerType = RTMP_PACKET_SIZE_MEDIUM;
   }

BYTE outbuf2[640];
int nLen2 = 640;

AVManager::GetInstance()->Decode((BYTE*)(pkt->m_body+1), pkt->m_nBodySize-1, outbuf2, nLen2);
//实际音频内容为pkt->m_body+1,大小是pkt->m_nBodySize-1。这里的声音是speex编码。
为什么跳过第一字节,可以参考:http://bbs.rosoo.net/thread-16488-1-1.html

evt_OnReceivePacket((char*)outbuf2, nLen2);//回调出来

RTMPPacket_Free(pkt);
pkt->m_nBytesRead = 0;


视频处理
可以参考rtmpsrv.c
把nRead = RTMP_Read(rtmp, buffer, bufferSize);改成:

RTMPPacket pc = { 0 }, ps = { 0 };
 bool bFirst = true;
while (RTMP_ReadPacket(rtmp, &pc))
{
if (RTMPPacket_IsReady(&pc))
 {
     if (pc.m_packetType == RTMP_PACKET_TYPE_VIDEO && RTMP_ClientPacket(rtmp, &pc))
    {
        bool bIsKeyFrame = false;
     if (result == 0x17)//I frame
    {
        bIsKeyFrame = true;
    }
    else if (result == 0x27)
    {
        bIsKeyFrame = false;
    }
static unsigned char const start_code[4] = {0x00, 0x00, 0x00, 0x01};
fwrite(start_code, 1, 4, pf );
//int ret = fwrite(pc.m_body + 9, 1, pc.m_nBodySize-9, pf);

if( bFirst) {

//AVCsequence header

//ioBuffer.put(foredata);

//获取sps

int spsnum = data[10]&0x1f;

int number_sps = 11;

int count_sps = 1;

while (count_sps<=spsnum){

int spslen =(data[number_sps]&0x000000FF)<<8 |(data[number_sps+1]&0x000000FF);

number_sps += 2;

fwrite(data+number_sps, 1, spslen, pf );
fwrite(start_code, 1, 4, pf );

//ioBuffer.put(data,number_sps, spslen);
//ioBuffer.put(foredata);

number_sps += spslen;

count_sps ++;

}

//获取pps

int ppsnum = data[number_sps]&0x1f;

int number_pps = number_sps+1;

int count_pps = 1;

while (count_pps<=ppsnum){

int ppslen =(data[number_pps]&0x000000FF)<<8|data[number_pps+1]&0x000000FF;

number_pps += 2;

//ioBuffer.put(data,number_pps,ppslen);

//ioBuffer.put(foredata);

fwrite(data+number_pps, 1, ppslen, pf );
fwrite(start_code, 1, 4, pf );

number_pps += ppslen;

count_pps ++;

}

bFirst =false;

} else {

//AVCNALU

int len =0;

int num =5;

//ioBuffer.put(foredata);

while(num<pc.m_nBodySize) 
{

len =(data[num]&0x000000FF)<<24|(data[num+1]&0x000000FF)<<16|(data[num+2]&0x000000FF)<<8|data[num+3]&0x000000FF;

num = num+4;

//ioBuffer.put(data,num,len);

//ioBuffer.put(foredata);

fwrite(data+num, 1, len, pf );
fwrite(start_code, 1, 4, pf );

num = num + len;

}

}

 

}
}

具体视频分析的见: http://blog.csdn.net/cssmhyl/article/details/8128478

http://blog.chinaunix.net/uid-15063109-id-4273162.html

librtmp接收flv流中提取h264码流:根据多个资料汇总的更多相关文章

  1. [转]【流媒體】H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流

    [流媒體]H264—MP4格式及在MP4文件中提取H264的SPS.PPS及码流 SkySeraph Apr 1st 2012  Email:skyseraph00@163.com 一.MP4格式基本 ...

  2. 从H264码流中获取视频宽高 (SPS帧) 升级篇

    之前写过 <从H264码流中获取视频宽高 (SPS帧)> . 但发现很多局限性,而且有时解出来是错误的. 所以重新去研究了. 用了 官方提供的代码库来解析. 花了点时间,从代码库里单独把解 ...

  3. H264码流中SPS PPS详解<转>

    转载地址:https://zhuanlan.zhihu.com/p/27896239 1 SPS和PPS从何处而来? 2 SPS和PPS中的每个参数起什么作用? 3 如何解析SDP中包含的H.264的 ...

  4. 从H264码流中获取视频宽高 (SPS帧)

    获取.h264视频宽高的方法 花了2个通宵终于搞定.(后面附上完整代码) http://write.blog.csdn.net/postedit/7852406 图像的高和宽在H264的SPS帧中.在 ...

  5. H264码流解析及NALU

    ffmpeg 从mp4上提取H264的nalu http://blog.csdn.net/gavinr/article/details/7183499 639     /* bitstream fil ...

  6. H264码流打包分析

    转自:http://www.360doc.com/content/13/0124/08/9008018_262076786.shtml   SODB 数据比特串-->最原始的编码数据 RBSP ...

  7. H264码流打包分析(精华)

    H264码流打包分析 SODB 数据比特串-->最原始的编码数据 RBSP 原始字节序列载荷-->在SODB的后面填加了结尾比特(RBSP trailing bits 一个bit“1”)若 ...

  8. H264编码原理以及I帧、B和P帧详解, H264码流结构分析

    H264码流结构分析 http://blog.csdn.net/chenchong_219/article/details/37990541 1.码流总体结构: h264的功能分为两层,视频编码层(V ...

  9. RTP协议全解析(H264码流和PS流)

    转自:http://blog.csdn.net/chen495810242/article/details/39207305 写在前面:RTP的解析,网上找了很多资料,但是都不全,所以我力图整理出一个 ...

随机推荐

  1. java程序设计基础篇 复习笔记 第六单元

    第六章 一维数组 1 数组初始化语法 array initializer 2 for each loop 3 off-by-one error 通常是在循环中该使用<的地方使用了<= 4 ...

  2. Solr后台管理界面配置

    配置来源 https://stackoverflow.com/questions/28043957/how-to-set-apache-solr-admin-password 注意:配置用户名密码后 ...

  3. Qt实现简单的单例模式

    单例模式十分的常见也很常用,Boost库中就有单例的泛型实现,Qt中,可以利用原子指针来实现一个单例模式: class SingleTon{ public: static SingleTon & ...

  4. C++复制控制:拷贝构造函数

    一.拷贝构造函数是一种特殊构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用.与默认构造函数一样 ,拷贝构造函数可由编译器隐式调用.拷贝构造函数应用的场合为: (1)根据另一个同类 ...

  5. DRF中两大视图基类APIView/GenericAPIView的介绍

    (1)APIView rest_framework.views.APIView APIView是REST framework提供的所有视图的基类,继承自Django的View父类. APIView与V ...

  6. C++面向对象高级编程(二)基础篇

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 概要 知识点1.重载成员函数 知识点2 . return by value, return by reference 知识点3 重载非成员函数 ...

  7. LINUX中的DNS服务---DNS正向、反向和双向解析

    一.DNS的正向解析 也就是域名解析为IP地址进行访问! 1)vim  /etc/named.conf   ---->  删除forwarders所在行 2)vim  /etc/named.rf ...

  8. free和delete把指针怎么啦?

    别看free和delete的名字恶狠狠的(尤其是delete),它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉. 用调试器跟踪示例7-5,发现指针p被free以后其地址仍然不变(非NULL) ...

  9. C# 读写opc ua服务器,浏览所有节点,读写节点,读历史数据,调用方法,订阅,批量订阅操作

    OPC UA简介 OPC是应用于工业通信的,在windows环境的下一种通讯技术,原有的通信技术难以满足日益复杂的环境,在可扩展性,安全性,跨平台性方面的不足日益明显,所以OPC基金会在几年前提出了面 ...

  10. AspectJ语法

    AspectJ语法 看了很多AOP的文章了,AOP这两年发展的很慢,没有什么新意,现在到处都是SOA,SCA了,不过研究了一下,觉得还是很有帮助的.尤其是增加系统的契约性和模块的独立性来说,很有帮助. ...