VC+ffmpeg+SDL 单进程多线程多路视频流解码及显示

fighttosky fighttosky 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区

最近遇到一个需要多窗口同时播放多路视频流的应用场景,视频流的来源为网络udp传输。

采用了 ffmpeg+SDL进行解码显示的方案,每有一个新打开的窗口,就启动一个对应的解码显示线程进行处理。
ffmpeg和sdl的初始化单独在主进程中进行。

每个线程的处理流程基本上就是下面的处理过程(简略代码中关于错误的判断,全粘上来有点多了)

pFormatCtx = avformat_alloc_context();
avformat_open_input(&pFormatCtx, url, NULL, &options);
avformat_find_stream_info(pFormatCtx, NULL)
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
avcodec_open2(pCodecCtx, pCodec, NULL)
pFrame = av_frame_alloc();
pFrameYUV = av_frame_alloc();
out_buffer=(uint8_t *)av_malloc(
avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)
);
avpicture_fill(
(AVPicture *)pFrameYUV,
out_buffer,
PIX_FMT_YUV420P,
pCodecCtx->width,
pCodecCtx->height
);

之后进行SDL的Render和Texture的准备,然后进入循环,循环中反复调用
av_read_frame(pFormatCtx, packet);
avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
SDL_UpdateTexture( sdlTexture, NULL, pFrameYUV->data[0], pFrameYUV->linesize[0] );
SDL_RenderClear( sdlRenderer );
SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, NULL);
SDL_RenderPresent( sdlRenderer );
进行逐帧的解码与渲染。

就执行效果上看,基本上能够实现预期目的。
但是在进行压力测试的情况下,频繁进行视频流的切换时(每次切换视频流来源,对应的线程也会进行停止和启动),系统就容易出现崩溃的情况。
在论坛上搜索到,之前有人曾经提到ffmpeg实质上对于单进程多路解码并不是完美支持,需要进行锁注册。按照帖子里面提到的,后来在初始化时增加了 av_lockmgr_register(lockmgr_cs) 的对应代码, lockmgr_cs 是采用临界区实现的锁管理函数,也尝试过mutex实现的锁管理函数,但是没有什么实质性的改善。

请各路大神给个解决方向的建议,多谢了。
...全文

相关推荐

评论 2
收藏 已收藏
分享
返回顶部