ffmpeg jpeg图片播放失败之问题排查
2017-06-21 20:17 nigaopeng 阅读(2766) 评论(0) 编辑 收藏 举报
播放jpeg时,avformat_find_stream_info出现以下问题,排查:
[jpeg_pipe @ 0x146a80] Could not find codec parameters for stream 0 (Video: mjpeg, none(bt470bg/unknown/unknown)): unspecified size
Consider increasing the value for the 'analyzeduration' and 'probesize' options
1. 打印开启的codec信息,发现mjpeg codec已经开启
AVCodec * av_codec = av_codec_next(NULL); while(av_codec) { printf("codec name:%s\n", av_codec->name); av_codec = av_codec_next(av_codec); }
检查demux的支持哪些format状况
AVInputFormat *av_i = av_iformat_next(NULL);
while(av_i)
{
printf("name:%s\n", av_i->name);
av_i = av_iformat_next(av_i);
}
2. 阅读avformat_find_stream_info代码,在里面加log确认卡住的地方
发现has_codec_parameters()check失败导致,然后就追查avctx->width为何没有赋值。
3.发现read_frame_internal()调用出错,导致没有try decode。然后trace flow
4.iformat->read_packet(),format已经知道为jpeg_pipe,可惜搜不到相应的demuxer。
好像是这里,可惜搜不到函数。wav有ff_wav_demuxer,但是image_jpeg_pipe没有ff_image_jpeg_pipe的变量定义。
此时你已经知道自己掉坑里了,没事,习惯就好了。
void av_register_all(void) { //... /* image demuxers */ REGISTER_DEMUXER (IMAGE_JPEG_PIPE, image_jpeg_pipe); REGISTER_DEMUXER (IMAGE_JPEGLS_PIPE, image_jpegls_pipe); //... }
最后发现定义在img2dec.c中,别问我怎么找到的,_pipe这个字符串不是很特别嘛,虽然也很多。。。
#define IMAGEAUTO_DEMUXER(imgname, codecid)\ static const AVClass imgname ## _class = {\ .class_name = AV_STRINGIFY(imgname) " demuxer",\ .item_name = av_default_item_name,\ .option = ff_img_options,\ .version = LIBAVUTIL_VERSION_INT,\ };\ AVInputFormat ff_image_ ## imgname ## _pipe_demuxer = {\ .name = AV_STRINGIFY(imgname) "_pipe",\ .long_name = NULL_IF_CONFIG_SMALL("piped " AV_STRINGIFY(imgname) " sequence"),\ .priv_data_size = sizeof(VideoDemuxData),\ .read_probe = imgname ## _probe,\ .read_header = ff_img_read_header,\ .read_packet = ff_img_read_packet,\ .priv_class = & imgname ## _class,\ .flags = AVFMT_GENERIC_INDEX, \ .raw_codec_id = codecid,\ }; IMAGEAUTO_DEMUXER(bmp, AV_CODEC_ID_BMP) IMAGEAUTO_DEMUXER(dds, AV_CODEC_ID_DDS) IMAGEAUTO_DEMUXER(dpx, AV_CODEC_ID_DPX) IMAGEAUTO_DEMUXER(exr, AV_CODEC_ID_EXR) IMAGEAUTO_DEMUXER(j2k, AV_CODEC_ID_JPEG2000) IMAGEAUTO_DEMUXER(jpeg, AV_CODEC_ID_MJPEG) IMAGEAUTO_DEMUXER(jpegls, AV_CODEC_ID_JPEGLS) IMAGEAUTO_DEMUXER(pictor, AV_CODEC_ID_PICTOR) IMAGEAUTO_DEMUXER(png, AV_CODEC_ID_PNG) IMAGEAUTO_DEMUXER(qdraw, AV_CODEC_ID_QDRAW) IMAGEAUTO_DEMUXER(sgi, AV_CODEC_ID_SGI) IMAGEAUTO_DEMUXER(sunrast, AV_CODEC_ID_SUNRAST) IMAGEAUTO_DEMUXER(tiff, AV_CODEC_ID_TIFF) IMAGEAUTO_DEMUXER(webp, AV_CODEC_ID_WEBP)
4. 进入ff_img_read_packet分析,这个流程图就不画了(因为网上没搜到)
原因很简单我的avio不能seek,所以size[0]为-38,然后packet new不出来,然后就少了一个螺丝钉,然后就打仗打输了。
所以问题点就是我的avio不能seek?what?
} else { f[0] = s1->pb; if (avio_feof(f[0]) && s->loop && s->is_pipe) avio_seek(f[0], 0, SEEK_SET); if (avio_feof(f[0])) return AVERROR_EOF; if (s->frame_size > 0) { size[0] = s->frame_size; } else if (!s1->streams[0]->parser) { size[0] = avio_size(s1->pb);//执行到这咯,size[0]为-38 } else { size[0] = 4096; } } //这个报错了,res为-22 res = av_new_packet(pkt, size[0] + size[1] + size[2]);
5. avio不能seek是由于,这个avio是定制的(说白了,自己写的,自己给自己挖坑)
AVIOContext *avio_alloc_context( unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t (*seek)(void *opaque, int64_t offset, int whence)) //... avio = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size, 0, &bd, &read_bs, NULL, NULL);
6.当然如果故事就这样结束了,我也会很happy。同样的图片解码的code,在另一个平台用得好好的,但在这个平台却非要实现一个seek不可?
7.然后在另一个ok的平台上调试,发现走的flow不一样。
在另一个平台上是有相应的parser的。
} else { f[0] = s1->pb; if (avio_feof(f[0]) && s->loop && s->is_pipe) avio_seek(f[0], 0, SEEK_SET); if (avio_feof(f[0])) return AVERROR_EOF; if (s->frame_size > 0) { size[0] = s->frame_size; } else if (!s1->streams[0]->parser) { size[0] = avio_size(s1->pb); } else { size[0] = 4096;//我是走这的,笨蛋 } } res = av_new_packet(pkt, size[0] + size[1] + size[2]);
8. 最终原因很简单,该平台的mjpeg的parse没有开....
9.找到原因就结束了吗?!当然不是,我们还要认真反思。(被老板发现,一分钟就可以开好的配置,具体调试了一天,分分钟被抽死)
第一步就检查了配置,而且是在代码里加code,这样太不方便了。
./configure就会打印到底开了哪些,如果一开始就仔细检查是不是就不用这么花时间调试了。(假装自己是老板,严厉呵斥该码农)
Enabled programs:
ffmpeg ffprobe ffserver
External libraries:
iconv zlib
External libraries providing hardware acceleration:
cuda cuvid nvenc
Libraries:
avcodec avdevice avfilter avformat avutil swresample swscale
Enabled decoders:
aac adpcm_yamaha cpia fourxm mdec on2avc pjs srt vp3
Enabled encoders:
a64multi ass ffv1 mjpeg pcm_alaw pcm_s64be prores_aw srt vorbis
a64multi5
Enabled parsers:
aac cavsvideo dpx dvdsub h261 mjpeg mpegvideo rv30 vorbis
aac_latm
10. 还有第十步,不说了,今晚又得加班了...