捕捉音频的时候怎么从 CMSampleBufferRef 中提取视频中的音频数据

如何从视频中提取音频?选择字号:
选择【影音工具箱-转码】
点击【添加文件】将视频加入到列表中,选择输出“纯音频文件”(如2所示)和设置保存的地址(如3所示)即可。
如果您需要进一步的设置,可点击【参数设置】按钮,在弹出的设置框中选择相关参数即可。QQ影音支持将各种格式转为通用的WMA\MP3格式。
以上信息是否已解决您的问题?当前访客身份:游客 [
当前位置:
发布于 日 12时,
&无详细内容&
代码片段(2)
streamdef.h&~&4KB&&&&
#ifndef _STREAMDEF_H_
#define _STREAMDEF_H_
#define MAX_PS_LENGTH
#define MAX_PES_LENGTH (0xFFFF)
#define MAX_ES_LENGTH
(0x100000)
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#pragma pack (1)
typedef struct RTP_HEADER
#ifdef ORTP_BIGENDIAN
uint16_t version:2;
uint16_t padbit:1;
uint16_t extbit:1;
uint16_t cc:4;
uint16_t markbit:1;
uint16_t paytype:7;
uint16_t cc:4;
uint16_t extbit:1;
uint16_t padbit:1;
uint16_t version:2;
uint16_t paytype:7;
//负载类型
uint16_t markbit:1;
//1表示前面的包为一个解码单元,0表示当前解码单元未结束
uint16_t seq_
uint32_ //时间戳
//循环校验码
//uint32_t csrc[16];
} RTP_header_t;
typedef struct ps_header{
unsigned char pack_start_code[4];
//'0x000001BA'
unsigned char system_clock_reference_base21:2;
unsigned char marker_bit:1;
unsigned char system_clock_reference_base1:3;
unsigned char fix_bit:2;
unsigned char system_clock_reference_base22;
unsigned char system_clock_reference_base31:2;
unsigned char marker_bit1:1;
unsigned char system_clock_reference_base23:5;
unsigned char system_clock_reference_base32;
unsigned char system_clock_reference_extension1:2;
unsigned char marker_bit2:1;
unsigned char system_clock_reference_base33:5; //system_clock_reference_base 33bit
unsigned char marker_bit3:1;
unsigned char system_clock_reference_extension2:7; //system_clock_reference_extension 9bit
unsigned char program_mux_rate1;
unsigned char program_mux_rate2;
unsigned char marker_bit5:1;
unsigned char marker_bit4:1;
unsigned char program_mux_rate3:6;
unsigned char pack_stuffing_length:3;
unsigned char reserved:5;
}ps_header_t;
typedef struct sh_header
unsigned char system_header_start_code[4]; //32
unsigned char header_length[2];
//16 uimsbf
uint32_t marker_bit1:1;
uint32_t rate_bound:22;
//22 uimsbf
uint32_t marker_bit2:1;
uint32_t audio_bound:6;
//6 uimsbf
uint32_t fixed_flag:1;
uint32_t CSPS_flag:1;
uint16_t system_audio_lock_flag:1;
uint16_t system_video_lock_flag:1;
uint16_t marker_bit3:1;
uint16_t video_bound:5;
uint16_t packet_rate_restriction_flag:1; //bslbf
uint16_t reserved_bits:7;
unsigned char reserved[6];
}sh_header_t; //18
typedef struct psm_header{
unsigned char promgram_stream_map_start_code[4];
unsigned char program_stream_map_length[2];
unsigned char program_stream_map_version:5;
unsigned char reserved1:2;
unsigned char current_next_indicator:1;
unsigned char marker_bit:1;
unsigned char reserved2:7;
unsigned char program_stream_info_length[2];
unsigned char elementary_stream_map_length[2];
unsigned char stream_
unsigned char elementary_stream_
unsigned char elementary_stream_info_length[2];
unsigned char CRC_32[4];
unsigned char reserved[16];
}psm_header_t; //36
typedef struct pes_header
unsigned char pes_start_code_prefix[3];
unsigned char stream_
unsigned short PES_packet_
}pes_header_t; //6
typedef struct optional_pes_header{
unsigned char original_or_copy:1;
unsigned char copyright:1;
unsigned char data_alignment_indicator:1;
unsigned char PES_priority:1;
unsigned char PES_scrambling_control:2;
unsigned char fix_bit:2;
unsigned char PES_extension_flag:1;
unsigned char PES_CRC_flag:1;
unsigned char additional_copy_info_flag:1;
unsigned char DSM_trick_mode_flag:1;
unsigned char ES_rate_flag:1;
unsigned char ESCR_flag:1;
unsigned char PTS_DTS_flags:2;
unsigned char PES_header_data_
}optional_pes_header_t;
#pragma pack ()
enum PSStatus
ps_padding, //未知状态
ps_pes_video,
ps_pes_audio
PSPacket.h&~&11KB&&&&
#ifndef _PSUNPACKET_H_
#define _PSUNPACKET_H_
#include "streamdef.h"
#include &tuple&
using namespace std::tr1;
#ifndef AV_RB16
define AV_RB16(x)
((((const unsigned char*)(x))[0] && 8) |
((const unsigned char*)(x))[1])
static inline unsigned __int64 ff_parse_pes_pts(const unsigned char* buf) {
return (unsigned __int64)(*buf & 0x0e) && 29 |
(AV_RB16(buf+1) && 1) && 15 |
AV_RB16(buf+3) && 1;
static unsigned __int64 get_pts(optional_pes_header* option)
if(option-&PTS_DTS_flags != 2 && option-&PTS_DTS_flags != 3 && option-&PTS_DTS_flags != 0)
if((option-&PTS_DTS_flags & 2) == 2)
unsigned char* pts = (unsigned char*)option + sizeof(optional_pes_header);
return ff_parse_pes_pts(pts);
static unsigned __int64 get_dts(optional_pes_header* option)
if(option-&PTS_DTS_flags != 2 && option-&PTS_DTS_flags != 3 && option-&PTS_DTS_flags != 0)
if((option-&PTS_DTS_flags & 3) == 3)
unsigned char* dts = (unsigned char*)option + sizeof(optional_pes_header) + 5;
return ff_parse_pes_pts(dts);
bool inline is_ps_header(ps_header_t* ps)
if(ps-&pack_start_code[0] == 0 && ps-&pack_start_code[1] == 0 && ps-&pack_start_code[2] == 1 && ps-&pack_start_code[3] == 0xBA)
bool inline is_sh_header(sh_header_t* sh)
if(sh-&system_header_start_code[0] == 0 && sh-&system_header_start_code[1] == 0 && sh-&system_header_start_code[2] == 1 && sh-&system_header_start_code[3] == 0xBB)
bool inline is_psm_header(psm_header_t* psm)
if(psm-&promgram_stream_map_start_code[0] == 0 && psm-&promgram_stream_map_start_code[1] == 0 && psm-&promgram_stream_map_start_code[2] == 1 && psm-&promgram_stream_map_start_code[3] == 0xBC)
bool inline is_pes_video_header(pes_header_t* pes)
if(pes-&pes_start_code_prefix[0]==0 && pes-&pes_start_code_prefix[1] == 0 && pes-&pes_start_code_prefix[2] == 1 && pes-&stream_id == 0xE0)
bool inline is_pes_audio_header(pes_header_t* pes)
if(pes-&pes_start_code_prefix[0]==0 && pes-&pes_start_code_prefix[1] == 0 && pes-&pes_start_code_prefix[2] == 1 && pes-&stream_id == 0xC0)
bool inline is_pes_header(pes_header_t* pes)
if(pes-&pes_start_code_prefix[0]==0 && pes-&pes_start_code_prefix[1] == 0 && pes-&pes_start_code_prefix[2] == 1)
if(pes-&stream_id == 0xC0 || pes-&stream_id == 0xE0)
PSStatus inline pes_type(pes_header_t* pes)
if(pes-&pes_start_code_prefix[0]==0 && pes-&pes_start_code_prefix[1] == 0 && pes-&pes_start_code_prefix[2] == 1)
if(pes-&stream_id == 0xC0)
return ps_pes_
else if(pes-&stream_id == 0xE0)
return ps_pes_
return ps_
_1 是否包含数据
_2 下一个PS状态
_3 数据指针
_4 数据长度
typedef std::tr1::tuple&bool, PSStatus, pes_header_t*& pes_
_1 是否包含数据
_2 数据类型
_3 PTS时间戳
_4 DTS时间戳
_5 数据指针
_6 数据长度
typedef std::tr1::tuple&bool, unsigned char, unsigned __int64, unsigned __int64, char*, unsigned int& naked_
class PSPacket
PSPacket()
m_status = ps_
m_nESLength = m_nPESIndicator = m_nPSWrtiePos = m_nPESLength = 0;
void PSWrite(char* pBuffer, unsigned int sz)
if(m_nPSWrtiePos + sz & MAX_PS_LENGTH)
memcpy((m_pPSBuffer + m_nPSWrtiePos), pBuffer, sz);
m_nPSWrtiePos +=
m_status = ps_
m_nESLength = m_nPESIndicator = m_nPSWrtiePos = m_nPESLength = 0;
void RTPWrite(char* pBuffer, unsigned int sz)
char* data = (pBuffer + sizeof(RTP_header_t));
unsigned int length =
sz - sizeof(RTP_header_t);
if(m_nPSWrtiePos + length & MAX_PS_LENGTH)
memcpy((m_pPSBuffer + m_nPSWrtiePos), data, length);
m_nPSWrtiePos +=
m_status = ps_
m_nESLength = m_nPESIndicator = m_nPSWrtiePos = m_nPESLength = 0;
pes_tuple pes_payload()
if(m_status == ps_padding)
for(; m_nPESIndicator&m_nPSWrtieP m_nPESIndicator++)
m_ps = (ps_header_t*)(m_pPSBuffer + m_nPESIndicator);
if(is_ps_header(m_ps))
m_status = ps_
if(m_status == ps_ps)
for(; m_nPESIndicator&m_nPSWrtieP m_nPESIndicator++)
m_sh = (sh_header_t*)(m_pPSBuffer + m_nPESIndicator);
m_pes = (pes_header_t*)(m_pPSBuffer + m_nPESIndicator);
if(is_sh_header(m_sh))
m_status = ps_
else if (is_pes_header(m_pes))
m_status = ps_
if(m_status == ps_sh)
for(; m_nPESIndicator&m_nPSWrtieP m_nPESIndicator++)
m_psm = (psm_header_t*)(m_pPSBuffer + m_nPESIndicator);
m_pes = (pes_header_t*)(m_pPSBuffer + m_nPESIndicator);
if(is_psm_header(m_psm))
m_status = ps_//冲掉s_sh状态
if(is_pes_header(m_pes))
m_status = ps_
if(m_status == ps_psm)
for(; m_nPESIndicator&m_nPSWrtieP m_nPESIndicator++)
m_pes = (pes_header_t*)(m_pPSBuffer + m_nPESIndicator);
if(is_pes_header(m_pes))
m_status = ps_
if(m_status == ps_pes)
//寻找下一个pes 或者 ps
unsigned short PES_packet_length = ntohs(m_pes-&PES_packet_length);
if((m_nPESIndicator + PES_packet_length + sizeof(pes_header_t)) & m_nPSWrtiePos)
char* next = (m_pPSBuffer + m_nPESIndicator + sizeof(pes_header_t) + PES_packet_length);
pes_header_t* pes = (pes_header_t*)
ps_header_t* ps = (ps_header_t*)
m_nPESLength = PES_packet_length + sizeof(pes_header_t);
memcpy(m_pPESBuffer, m_pes, m_nPESLength);
if(is_pes_header(pes) || is_ps_header(ps))
PSStatus status = ps_
if(is_ps_header(ps))
status = m_status = ps_
status = pes_type(pes);
int remain = m_nPSWrtiePos - (next - m_pPSBuffer);
memcpy(m_pPSBuffer, next, remain);
m_nPSWrtiePos = m_nPESIndicator = 0;
m_ps = (ps_header_t*)m_pPSB
m_pes = (pes_header_t*)m_pPSB
return pes_tuple(true, status, (pes_header_t*)m_pPESBuffer);
m_status = ps_
m_nPESIndicator = m_nPSWrtiePos = 0;
return pes_tuple(false, ps_padding, NULL);
naked_tuple naked_payload()
naked_tuple tuple = naked_tuple(false, 0, 0, 0, NULL, 0);
pes_tuple t = pes_payload();
if(! std::tr1::get&0&(t))
PSStatus status = std::tr1::get&1&(t);
pes_header_t* pes = std::tr1::get&2&(t);
optional_pes_header* option = (optional_pes_header*)((char*)pes + sizeof(pes_header_t));
if(option-&PTS_DTS_flags != 2 && option-&PTS_DTS_flags != 3 && option-&PTS_DTS_flags != 0)
unsigned __int64 pts = get_pts(option);
unsigned __int64 dts = get_dts(option);
unsigned char stream_id = pes-&stream_
unsigned short PES_packet_length = ntohs(pes-&PES_packet_length);
char* pESBuffer = ((char*)option + sizeof(optional_pes_header) + option-&PES_header_data_length);
int nESLength = PES_packet_length - (sizeof(optional_pes_header) + option-&PES_header_data_length);
memcpy(m_pESBuffer + m_nESLength, pESBuffer, nESLength);
m_nESLength += nESL
if(stream_id == 0xE0 && (status == ps_ps || status == ps_pes_audio))
tuple = naked_tuple(true, 0xE0, pts, dts, m_pESBuffer, m_nESLength);
m_nESLength = 0;
else if(stream_id == 0xC0)
tuple = naked_tuple(true, 0xC0, pts, dts, m_pESBuffer, m_nESLength);
m_nESLength = 0;
} while (false);
//当前状态
m_pPSBuffer[MAX_PS_LENGTH];
//PS缓冲区
unsigned int
m_nPSWrtieP
//PS写入位置
unsigned int
m_pPESBuffer[MAX_PES_LENGTH]; //PES缓冲区
unsigned int
//PES数据长度
ps_header_t*
sh_header_t*
psm_header_t* m_
//节目流头
pes_header_t* m_
m_pESBuffer[MAX_ES_LENGTH];
unsigned int m_nESL
//裸码流长度
开源中国-程序员在线工具:
相关的代码(60)
不错,找了好久,多谢。
2楼:周年荻 发表于
引用来自“LKai”的评论 不错,找了好久,多谢。 多谢捧场 哈哈哈
3楼:隐形人 发表于
4楼:周年荻 发表于
引用来自“隐形人”的评论PS流是啥Program Stream (节目流),简称PS流
5楼:隐形人 发表于
引用来自“周年荻”的评论引用来自“隐形人”的评论PS流是啥Program Stream (节目流),简称PS流那这数据是从哪儿来的呢
6楼:asdfasdfw 发表于
这个适用于H264吗
7楼:周年荻 发表于
引用来自“asdfasdfw”的评论这个适用于H264吗H264只是PS流的负载部分,这个可以重PS流中提取H264裸码流
8楼:iamcopy 发表于
怎么使用这个代码?我现在从28181中获取到了rtp流但是VLC不能播放,我是想取出其中的视频流,怎么做
9楼:周年荻 发表于
引用来自“iamcopy”的评论怎么使用这个代码?我现在从28181中获取到了rtp流但是VLC不能播放,我是想取出其中的视频流,怎么做new 一个PSPacket对象 ,把rtp数据 调用RTPWrite,ps数据调用PSWrite, 然后循环调用naked_payload()返回视频流,和音频流,直到返回失败,结束循环。
10楼:mboy 发表于
你好,我按照你的方法可以取出视频流,能正常播放,但是有时候会出现视频卡的情况,请问跟什么有关系呢?谢谢
11楼:mboy 发表于
你好,我按照你的方法可以取出视频流,能正常播放,但是有时候会出现视频卡的情况,请问跟什么有关系呢?谢谢
12楼:Keven_M 发表于
引用来自“mboy”的评论 你好,我按照你的方法可以取出视频流,能正常播放,但是有时候会出现视频卡的情况,请问跟什么有关系呢?谢谢 请问你获取到裸流后是如何进行解码并显示的,我用ffmpeg解码出错,请问是否还需要组帧
13楼:Keven_M 发表于
不知道如何使用这个代码,我的28181已经获取到了rtp流,标准的PS封包,一个rtp包调用一次RTPWrite(),随后就调用naked_payload()。是这样的流程吗?如果是这样的话,裸流长度会很长,我的解码不成功,不知道是不是调用的问题,望楼主解答。
14楼:Keven_M 发表于
引用来自“iamcopy”的评论怎么使用这个代码?我现在从28181中获取到了rtp流但是VLC不能播放,我是想取出其中的视频流,怎么做没看懂代码中RTPWrite()方法和RTPWrite()方法是否需要同时使用, 我这边已经拿到了以PS封装的RTP包,如果你已经解析出裸流的话,麻烦告知一下接口使用流程,谢谢
15楼:周年荻 发表于
引用来自“mboy”的评论 你好,我按照你的方法可以取出视频流,能正常播放,但是有时候会出现视频卡的情况,请问跟什么有关系呢?谢谢 丢帧,还是 延迟?
16楼:周年荻 发表于
引用来自“iamcopy”的评论怎么使用这个代码?我现在从28181中获取到了rtp流但是VLC不能播放,我是想取出其中的视频流,怎么做引用来自“Keven_M”的评论没看懂代码中RTPWrite()方法和RTPWrite()方法是否需要同时使用, 我这边已经拿到了以PS封装的RTP包,如果你已经解析出裸流的话,麻烦告知一下接口使用流程,谢谢new 一个PSPacket对象 ,把rtp数据调用RTPWrite,ps数据调用PSWrite, 然后循环调用naked_payload()返回视频流,和音频流,直到返回失败,结束循环。
17楼:阳光天堂 发表于
请问对于aac音频的封装,PSM中的
stream_type填多少?
18楼:mboy 发表于
引用来自“mboy”的评论 你好,我按照你的方法可以取出视频流,能正常播放,但是有时候会出现视频卡的情况,请问跟什么有关系呢?谢谢 引用来自“Keven_M”的评论请问你获取到裸流后是如何进行解码并显示的,我用ffmpeg解码出错,请问是否还需要组帧我不是用ffmpeg去解的,解码这一块直接用的解码库
19楼:mboy 发表于
引用来自“mboy”的评论 你好,我按照你的方法可以取出视频流,能正常播放,但是有时候会出现视频卡的情况,请问跟什么有关系呢?谢谢 引用来自“周年荻”的评论丢帧,还是 延迟?没有丢帧,我现在用的是TCP方式接收数据,我把码率调到4M就会卡了 调小点就不会。另外,播放视频的时候,静止的画面有时候会模糊,类似马赛克那样,但一旦画面动一下就恢复正常了。请问这是啥原因? 还有,我在接收PS流的时候,时间戳应该用RTP头里的那个还是应该用PS流封装的pts? 谢谢楼主解答。
20楼:mboy 发表于
引用来自“Keven_M”的评论不知道如何使用这个代码,我的28181已经获取到了rtp流,标准的PS封包,一个rtp包调用一次RTPWrite(),随后就调用naked_payload()。是这样的流程吗?如果是这样的话,裸流长度会很长,我的解码不成功,不知道是不是调用的问题,望楼主解答。你好,你用28181协议封装RTP视频流用的啥方式?RTP_OVER_UDP 还是RTP_OVER_TCP?
开源从代码分享开始
周年荻的其他代码访问本页面,您的浏览器需要支持JavaScript}

我要回帖

更多关于 音频捕捉过滤器 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信