Windows远程桌面实现之五(FFMPEG实现桌面屏幕RTSP( 三 )


int= 8 +++ 2 + 1;
c-> = ;
c-> = (byte*)();
int i = 0;
byte* body = (byte*)c->;
//H264 AVCC 格式的头,用来存储 SPS,PPS
body[i++] = 0x01;
body[i++] = [1];
body[i++] = [2];
body[i++] = [3];
body[i++] = 0xff;
SPS
body[i++] = 0xe1;
body[i++] = ( >> 8) & 0xff;
body[i++] =& 0xff;
(&body[i], , );
i += ;
/// PPS
body[i++] = 0x01;
body[i++] = ( >> 8) & 0xff;
body[i++] = () & 0xff;
(&body[i], , );
i += ;
对于AAC音频编码的字段,则按照如下方式:
假设声道数是,采样率序号是,
AAC编码方式(比如是LC,HEv1,HEv2等)是,这些参数都可以从 带有ADTS头的AAC编码数据里边解析出来 。
至于如何解析,可稍后查看我发布到CSDN或上的源代码 。
// audio, ADTS头转换为MPEG-4
c = ->codec; ///是创建的音频流
c-> = 2;
c-> = (byte*)(2);
byte dsi[2];
dsi[0] = ((+1) > 1);
dsi[1] = ((dex & 1) );//是创建的视频流
接下来的就是同步的问题了 。
我们推流的是桌面屏幕和是电脑内部声音,这跟一般的一直在动的视频不大一样 。
有可能长时间,电脑屏幕都没任何变化;很长时间,电脑都不发一声响声 。
一般采用同步方法基本如下三种:
1,以视频为准,就是让视频以恒定的速度,比如30帧每秒,音频根据视频速度来定位 。
2,以音频为准,让音频以恒定速度,比如每秒48000的采样率,视频根据音频来定位 。
3,以外部的某个时钟为准来同步 。
除第三个办法不知道该怎么操作外,1, 2都比较好理解 。
如果按照1 的办法,显然不大现实,因此只好采用第2种办法,让音频以恒定速度传输 。
既然是让音频以恒定速度传输,也就是时时刻刻都有数据帧,而电脑内部可能很长时间都没有发声 。
也就是没声音数据 。这个时候,我们就得造假了,在这段时间内,我们就得连续不断的制造静音帧 。
以AAC编码为例,AAC编码的每个的大小是固定为1024,
比如是双声道,16位采样,则每次都需要输入固定 1024*2*2=4096字节大小的数据,才能编码出一帧AAC的数据 。
也就是我们造假,每次都输入4096大小的空白数据(就是全是0)让它编码出一帧静音AAC帧 。
我们再来计算每一帧AAC数据播放的持续时间 。
假设还是双声道,16位采样 。
假设每秒48000的采样率,则每秒可以制造2*2*48000字节 = 字节 的PCM原始声音数据 。每帧AAC是4096字节,我们做除法 。
4096/ = 0.0213秒=21.3毫秒 。
在48000采样率的情况下,每帧AAC数据的播放持续时间大约是21毫秒 。
也就是我们每隔21毫秒就要制造一个静音AAC帧推送出去,这样在没有外部声音的情况下,才能保证声音的持续不断 。
在平台,可以使用 函数来达到精确定时 。
如下伪代码:
( 30 , 10, , ()this,
| S | ON);
///
void(UINT uID, UINT uMsg,,dw1,dw2){
cur = (); ///
int= 4;
Lock();
step = ()1024 * 1000 * 1000 / ; // us,每个AAC压缩帧播放的时间
last = max( cur - *step,+ step );
///
pkt; (&pkt, 0, (pkt));
pkt.type = ;
pkt.data = http://www.kingceram.com/post/; ///已经编码好的AAC静音帧
pkt. = ;
pkt. = NULL;
/
while (last