最近在做ffmpeg接口封装,遇到一些问题,简单分享下;后续将代码分析后再上传分享
1、flv封装:flv封装不支持16000采样率,需要重采样,才能进一步封装
2、音频重采样需要经过解码->重采样->编码;每一步中对每一帧数据都需要使用同一个Context
3、avi封装:avi封装,25帧,视频时间基为1/600,则duration为24,但是封装后avi文件中的duration=1;导致文件无法在android中播放,所以修改时间基1/50.使得duration=1有效,可以播放
// 设置avi格式的时间基;原有时间基1/600,在android中无法播放
// avi封装后解析出来的duration都等于1,通过修改时间基,使得duration等于1可以正常解析
if (p_output->format == FFMPEG_MUXER_AVI)
{
p_output->stream[V_INDEX]->time_base.num = 1;
p_output->stream[V_INDEX]->time_base.den = 50;
}
3、内存读写中的读函数返回值注意,返回-1,代表已经封装结束,不能再进行读数据了
4、打开输入流时,需要指定音频或视频数据
// 不设置in_fmt或默认都是视频输入,音频读写一百多字节的数据导致报到文件尾的错误
in_fmt = av_find_input_format(format);
if (NULL == in_fmt)
{
ALOGE("%s[%d]:av_find_input_format %s failed\n", __FUNCTION__, __LINE__, format);
goto err;
}
if ((ret = avformat_open_input(&p_input_info->fmt_ctx, NULL, in_fmt, NULL)) < 0)
{
ALOGE("%s[%d]:avformat_open_input failed ret=%d\n", __FUNCTION__, __LINE__, ret);
goto err;
}
5、aac编码需要添加头aac音频流的头,否则无法在android上播放,保存在extradata中
//添加aac音频流的头;不添加无法在安卓上播放
if (p_output->audio.encType == AV_CODEC_ID_AAC)
{
make_dsi( (unsigned int)get_sr_index( (unsigned int)p_output->audio.sample_rate),\
(unsigned int)p_output->audio.channels, p_output->audio_extradata);
p_output->stream[A_INDEX]->codecpar->extradata = p_output->audio_extradata;
p_output->stream[A_INDEX]->codecpar->extradata_size = 2;
}
6、h264编码需要添加sps等信息,否则无法在android上播放,保存在extradata中
// 判断是I帧,再进行保存,
flag = (*(p_data_buf+4)&0x1F);
if (flag == 0x05 || flag == 0x07 || flag == 0x08)
{
memcpy(p_muxer_info->output.video_extradata, p_data_buf, 32);
p_muxer_info->output.stream[V_INDEX]->codecpar->extradata = p_muxer_info->output.video_extradata;
p_muxer_info->output.stream[V_INDEX]->codecpar->extradata_size = 32;
}
7、aac编码,封装每一帧时需要过滤掉aac音频帧前面的头
//aac音频数据需要过滤
if (p_muxer_info->output.audio.encType == AV_CODEC_ID_AAC)
{
p_muxer_info->input_a.bsfc = av_bitstream_filter_init("aac_adtstoasc");
if (p_muxer_info->input_a.bsfc == NULL)
{
ALOGE("%s[%d]:av_bitstream_filter_init failed\n", __FUNCTION__, __LINE__);
return -1;
}
}
// 分离某些格式
if (p_muxer_info->output.audio.encType == AV_CODEC_ID_AAC)
{
ret = av_bitstream_filter_filter(p_muxer_info->input_a.bsfc, p_muxer_info->input_a.stream->codec,NULL, &pkt->data, &pkt->size, pkt->data, pkt->size, 0);
if (ret < 0)
{
ALOGE("%s[%d]:av_bitstream_filter_filter failed ret = %d\n", __FUNCTION__, __LINE__, ret);
return -1;
}
}