1.ffmpeg推送rtmp流时,要求将音视频封装为flv格式,对音视频的编码格式都有要求:
关于flv还会单独开辟一篇文章进行详细分析
<1>视频支持格式如下:
{ AV_CODEC_ID_FLV1, FLV_CODECID_H263 },
{ AV_CODEC_ID_H263, FLV_CODECID_REALH263 },
{ AV_CODEC_ID_MPEG4, FLV_CODECID_MPEG4 },
{ AV_CODEC_ID_FLASHSV, FLV_CODECID_SCREEN },
{ AV_CODEC_ID_FLASHSV2, FLV_CODECID_SCREEN2 },
{ AV_CODEC_ID_VP6F, FLV_CODECID_VP6 },
{ AV_CODEC_ID_VP6, FLV_CODECID_VP6 },
{ AV_CODEC_ID_VP6A, FLV_CODECID_VP6A },
{ AV_CODEC_ID_H264, FLV_CODECID_H264 },
{ AV_CODEC_ID_NONE, 0 }
<2>音频支持格式如下:
{ AV_CODEC_ID_MP3 },
{ AV_CODEC_ID_PCM_U8},
{ AV_CODEC_ID_PCM_S16BE },
{ AV_CODEC_ID_PCM_S16LE },
{ AV_CODEC_ID_ADPCM_SWF },
{ AV_CODEC_ID_AAC},
{ AV_CODEC_ID_NELLYMOSER },
{ AV_CODEC_ID_PCM_MULAW },
{ AV_CODEC_ID_PCM_ALAW},
{ AV_CODEC_ID_SPEEX},
{ AV_CODEC_ID_NONE, 0 }
目前主流大多采用h.264+aac的编码组合
2.ffmpeg可提供flvflags选项以配置FLV头的额外数据,设置后AAC音频可支持除44100, 22050, 11025以外的采样率;
原理:该问题主要是利用了aac的扩展字节来实现的;
{ "flvflags", "FLV muxer flags", offsetof(FLVContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" },
原代码如下:
if (!enc->extradata_size && flv->flags & 1) {
PutBitContext pbc;
int samplerate_index;
int channels = flv->audio_enc->channels - (flv->audio_enc->channels == 8 ? 1 : 0);
uint8_t data[2];
for (samplerate_index = 0; samplerate_index < 16; samplerate_index++)
if (flv->audio_enc->sample_rate == mpeg4audio_sample_rates[samplerate_index])
break;
init_put_bits(&pbc, data, sizeof(data));
put_bits(&pbc, 5, flv->audio_enc->profile + 1); //profile
put_bits(&pbc, 4, samplerate_index); //sample rate index
put_bits(&pbc, 4, channels);
put_bits(&pbc, 1, 0); //frame length - 1024 samples
put_bits(&pbc, 1, 0); //does not depend on core coder
put_bits(&pbc, 1, 0); //is not extension
flush_put_bits(&pbc);
avio_w8(pb, data[0]);
avio_w8(pb, data[1]);
av_log(s, AV_LOG_WARNING, "AAC sequence header: %02x %02x.\n", data[0], data[1]);
}
avio_write(pb, enc->extradata, enc->extradata_size);
3.将TS(H.264+AAC)的流重新封装为FLV时,需要丢掉AAC的ADTS HEADER
flv_muxer的源码如下:
if (enc->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&(AV_RB16(pkt->data) & 0xfff0) == 0xfff0) { //音频为AAC,且存在ADTS的同步头syncword
if (!s->streams[pkt->stream_index]->nb_frames) {
av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: "
"use the audio bitstream filter 'aac_adtstoasc' to fix it "
"('-bsf:a aac_adtstoasc' option with ffmpeg)\n");
return AVERROR_INVALIDDATA;
}
av_log(s, AV_LOG_WARNING, "aac bitstream error\n");
}
|ADTS AAC数据格式|
|--------------------------------------------------------------------------|
|ADTS_header | AAC ES | ADTS_header | AAC ES | ... | ADTS_header | AAC ES |
|--------------------------------------------------------------------------|
|ADTS_header adts_fixed_header数据格式|
|
|--syncword[12]:同步头,值固定为0xFFF,表示一个ADTS帧的开始;
|--ID[1]:MPEG版本。(0:MPEG-4,1:MPEG-2);
|--Layer[2]:always: '00'
|--protection_absent[1]
|--profile[2]:表示使用哪个级别的AAC,有些芯片只支持AAC LC 。在MPEG-2 AAC中定义了3种:0-main profile;1-Low Complexity profile(LC);2-Scalable Sampling Rate profile(SSR);3-reserved
|--sampling_frequency_index[4]:表示使用的采样率下标,通过这个下标在 Sampling Frequencies[ ]数组中查找得知采样率的值;
There are 13 supported frequencies:
0: 96000 Hz 1: 88200 Hz 2: 64000 Hz 3: 48000 Hz 4: 44100 Hz 5: 32000 Hz
6: 24000 Hz 7: 22050 Hz 8: 16000 Hz 9: 12000 Hz 10: 11025 Hz 11: 8000 Hz
12: 7350 Hz 13: Reserved 14: Reserved 15: frequency is written explictly
|--private_bit[1]
|--channel_configuration[3]: 表示声道数
0: Defined in AOT Specifc Config
1: 1 channel: front-center
2: 2 channels: front-left, front-right
3: 3 channels: front-center, front-left, front-right
4: 4 channels: front-center, front-left, front-right, back-center
5: 5 channels: front-center, front-left, front-right, back-left, back-right
6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel
7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel
8-15: Reserved
|--original_copy[1]
|--home[1]
|ADTS_header adts_variable_header数据格式|
|--copyright_identification_bit
|--copyright_identification_start
|--aac_frame_length: 一个ADTS帧的长度包括ADTS头和AAC原始流;
|--adts_buffer_fullness:0x7FF 说明是码率可变的码流;
|--number_of_raw_data_blocks_in_frame
4.ffmpeg关于rtmp的实现:
<1>借助第三方库librtmp(librtmp.c);
<2>自己实现的rtmp接口(rtmpproto.c)