Android音视频学习第5章:视频直播实现之推送音频篇
来源:互联网 发布:n卡优化守望先锋 编辑:程序博客网 时间:2024/05/16 07:06
音频推送流程
1.音视频参数设置
2.开始推流
3.音频视频采集
4.进行编码(生产者)
5.RTMP推流(消费者)
/**
* 音频编码器配置
*/
setAudioOptions{
audio_encode_handle = faacEncOpen(sampleRateInHz,numChannels,&nInputSamples,&nMaxOutputBytes); if(!audio_encode_handle){ LOGE("音频编码器打开失败"); return; } //设置音频编码参数 faacEncHandle faacEncConfigurationPtr p_config = faacEncGetCurrentConfiguration(audio_encode_handle); p_config->mpegVersion = MPEG4; p_config->allowMidside = 1; p_config->aacObjectType = LOW; p_config->outputFormat = 0; //输出是否包含ADTS头 p_config->useTns = 1; //时域噪音控制,大概就是消爆音 p_config->useLfe = 0;// p_config->inputFormat = FAAC_INPUT_16BIT; p_config->quantqual = 100; p_config->bandWidth = 0; //频宽 p_config->shortctl = SHORTCTL_NORMAL; if(!faacEncSetConfiguration(audio_encode_handle,p_config)){ LOGE("%s","音频编码器配置失败.."); throwNativeError(env,INIT_FAILED); return; } LOGI("%s","音频编码器配置成功");
}
/**
* 对音频采样数据进行AAC编码
*/
fireAudio{
int *pcmbuf; unsigned char *bitbuf; jbyte* b_buffer = (*env)->GetByteArrayElements(env, buffer, 0); pcmbuf = (short*) malloc(nInputSamples * sizeof(int)); bitbuf = (unsigned char*) malloc(nMaxOutputBytes * sizeof(unsigned char)); int nByteCount = 0; unsigned int nBufferSize = (unsigned int) len / 2; unsigned short* buf = (unsigned short*) b_buffer; while (nByteCount < nBufferSize) { int audioLength = nInputSamples; if ((nByteCount + nInputSamples) >= nBufferSize) { audioLength = nBufferSize - nByteCount; } int i; for (i = 0; i < audioLength; i++) {//每次从实时的pcm音频队列中读出量化位数为8的pcm数据。 int s = ((int16_t *) buf + nByteCount)[i]; pcmbuf[i] = s << 8;//用8个二进制位来表示一个采样量化点(模数转换) } nByteCount += nInputSamples; //利用FAAC进行编码,pcmbuf为转换后的pcm流数据,audioLength为调用faacEncOpen时得到的输入采样数,bitbuf为编码后的数据buff,nMaxOutputBytes为调用faacEncOpen时得到的最大输出字节数 int byteslen = faacEncEncode(audio_encode_handle, pcmbuf, audioLength, bitbuf, nMaxOutputBytes); if (byteslen < 1) { continue; } add_aac_body(bitbuf, byteslen);//从bitbuf中得到编码后的aac数据流,放到数据队列 } (*env)->ReleaseByteArrayElements(env, buffer, b_buffer, NULL); if (bitbuf) free(bitbuf); if (pcmbuf) free(pcmbuf);
}
AAC header结构(2个字节)
1、SoundFormat,4bit
0 = Linear PCM, platform endian
1 = ADPCM
2 = MP3
3 = Linear PCM, little endian
4 = Nellymoser 16 kHz mono
5 = Nellymoser 8 kHz mono
6 = Nellymoser
7 = G.711 A-law logarithmic PCM
8 = G.711 mu-law logarithmic PCM
9 = reserved
10 = AAC
11 = Speex
14 = MP3 8 kHz
15 = Device-specific sound
2、SoundRate,2bit,抽样频率
0 = 5.5 kHz
1 = 11 kHz
2 = 22 kHz
3 = 44 kHz
对于AAC音频来说,总是0x11,即44khz.
3、SoundSize,1bit,音频的位数。
0 = 8-bit samples
1 = 16-bit samples
AAC总是为0x01,16位。
4、SoundType,1bit,声道
0 = Mono sound
1 = Stereo sound
5、AACPacketType,8bit。
这个字段来表示AACAUDIODATA的类型:0 = AAC sequence header,1 = AAC raw。第一个音频包用0,后面的都用1。
body[0] = 0xAF表示采用44100HZ 16bit stereo的AAC,指每秒钟有 44100 次采样, 采样数据用16位(2字节)记录,双声道(立体声)。
音频文件的格式决定了其声音的品质,日常生活中电话、收音机等均为模拟音频信号,即不存在采样频率和采样位数的概念,可以这样比较一下:
44KHz,16bit的声音称作:CD音质;
22KHz、16Bit的声音效果近似于立体声(FM Stereo)广播,称作:广播音质;
11kHz、8Bit的声音,称作:电话音质。
/**
* 添加AAC rtmp packet
*/
add_aac_body{
int body_size = 2 + len; RTMPPacket *packet = malloc(sizeof(RTMPPacket)); //RTMPPacket初始化 RTMPPacket_Alloc(packet,body_size); RTMPPacket_Reset(packet); unsigned char * body = packet->m_body; //头信息配置 /*AF 00 + AAC RAW data*/ body[0] = 0xAF;//10 5 SoundFormat(4bits):10=AAC,SoundRate(2bits):3=44kHz,SoundSize(1bit):1=16-bit samples,SoundType(1bit):1=Stereo sound body[1] = 0x01;//AACPacketType:1表示AAC raw memcpy(&body[2], buf, len); /*spec_buf是AAC raw数据*/ packet->m_packetType = RTMP_PACKET_TYPE_AUDIO; packet->m_nBodySize = body_size; packet->m_nChannel = 0x04; packet->m_hasAbsTimestamp = 0; packet->m_headerType = RTMP_PACKET_SIZE_LARGE; packet->m_nTimeStamp = RTMP_GetTime() - start_time; add_rtmp_packet(packet);
}
- Android音视频学习第5章:视频直播实现之推送音频篇
- Android音视频学习第4章:视频直播实现之推送视频篇
- Android音视频学习第6章:视频直播实现完整代码
- Android音视频学习第3章:音视频同步实现视频播放器
- 手机Android音视频采集与直播推送,实现单兵、移动监控类应用
- 手机Android音视频采集与直播推送,实现单兵、移动监控类应用
- 手机Android音视频采集与直播推送,实现单兵、移动监控类应用
- 手机Android音视频采集与直播推送,实现单兵、移动监控类应用
- 手机Android音视频采集与直播推送,实现单兵、移动监控类应用
- 视频直播,音频直播,m3u8
- 手机Android音视频采集与直播推送
- android 音视频直播
- Android音视频学习第2章:使用ffmpeg进行音频解码
- Android音视频学习第7章:使用OpenSL ES进行音频解码
- Android音视频学习第8章:使用fmod对音频进行变调处理
- Android视频直播的实现
- Android视频直播的实现
- Android视频直播的实现
- [JZOJ3893] 画矩形
- python 网络编程记录
- linux 开机自启动 tomcat 服务
- JAVA之参数传递实例一
- 我写的avltree
- Android音视频学习第5章:视频直播实现之推送音频篇
- 如何设置table,使单元格内容无论多少,只显示一行,超过单元格宽度的部分自动隐藏,当鼠标放到单元格上,内容自动显示完整?
- bzoj 4742 [Usaco2016 Dec]Team Building
- SQL语言的基本操作学习(一)
- VTK修炼之道17:图像基本操作_图像信息的访问与修改(vtkImageData)
- 图片读取工具类
- 优化redis 分页(二)
- fork系统调用实现剖析
- 去掉eclipse校验,减少eclipse卡顿