问题1)探测的码流数据是否会进行解码显示
AVFMT_FLAG_NOBUFFER宏定义剖析
默认情况下,读取的缓存数据将会用于解码,如果不想探测的码流用于显示,可以这样子设置:
pAVFormatContext->flags =pAVFormatContext->flags & AVFMT_FLAG_NOBUFFER;
代码剖析
函数调用int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
if (ic->flags & AVFMT_FLAG_NOBUFFER)
free_packet_buffer(&ic->packet_buffer, &ic->packet_buffer_end);
问题描述:因为没有设置该宏定义,传递进去I帧数据,应该会被保存下来,但是明显的得到PPS/SPS不存在的异常,究竟传输进去的码流哪里去了??
查看所有的函数引用
1)static int h364_slice_header_parse(const H264Context *h, H264SliceContext *sl, const H2645NAL *nal)
if (!h->ps.pps_list[sl->pps_id]) {
av_log(h->avctx, AV_LOG_ERROR,
"non-existing PPS %u referenced\n",
sl->pps_id);
return AVERROR_INVALIDDATA;
}
2)static inline int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t * const buf, int buf_size)
if (!p->ps.pps_list[pps_id]) {
av_log(avctx, AV_LOG_ERROR,
"non-existing PPS %u referenced\n", pps_id);
goto fail;
}
avcodec_send_packet函数返回-1094995529错误,根据FFmpeg的错误信息,得知为AVERROR_INVALIDDATA,猜测是第一种情况
在调用h364_slice_header_parse函数的时候,出现了错误,无法定位PPS
函数的调用逻辑
static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
int ff_h364_queue_decode_slice(H264Context *h, const H2645NAL *nal)
static int h364_slice_header_parse(const H264Context *h, H264SliceContext *sl, const H2645NAL *nal)
结构体的获取
H264Context* pH264Context = AVCodecContext->priv_data
H264SliceContext *sl = H264Context->slice_ctx + H264Context->nb_slice_ctx_queued;
av_read_frame()读取一个包并且把它保存到AVPacket结构体中。这些数据可以在后面通过av_free_packet()来释放。
函数avcodec_decode_video()把包转换为帧。然而当解码一个包的时候,我们可能没有得到我们需要的关于帧的信息。
因此,当我们得到下一帧的时候,avcodec_decode_video()为我们设置了帧结束标志frameFinished。
注意到相当重要的一点av_read_frame()需要足够的信息去解码,如果没有SPS/PPS,会继续探测码流,打印错误如下:
I:2018-01-06 14:35:33 ms:313:nal_unit_type: 1, nal_ref_idc: 3
I:2018-01-06 14:35:33 ms:313:non-existing PPS 0 referenced
I:2018-01-06 14:35:33 ms:313:decode_slice_header error
I:2018-01-06 14:35:33 ms:313:no frame!
网上提供了一些方案,暂时没有理解
1)1.确保第一个解码的帧为I帧,确保I帧中有sps和pps信息
2)如果直接从rtsp流中一帧一帧的取,再一帧一帧的转码yuv,对AVpacket,AVframe没有特殊要求,完整就好。
3) 若果现将h364实时流存在共享内存中,再从共享内存中读取一帧的AVpacket,那么AVframe就不要循环清理,最好做成成员变量,否则非关键帧无法解码,会提示如上错误。
解决办法:将AVframe做成成员变量,不能用一次清理一次
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。