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

fighttosky 2017-09-24 12:18:48

最近遇到一个需要多窗口同时播放多路视频流的应用场景,视频流的来源为网络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实现的锁管理函数,但是没有什么实质性的改善。

请各路大神给个解决方向的建议,多谢了。
...全文
1646 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
cantian1234 2018-09-28
  • 打赏
  • 举报
回复
查到一个方法:可以一试
https://blog.csdn.net/xiaoxianerqq/article/details/49762463
解决了,几处重点:
1 用SDL2,因为ffplay.c用的是SDL1.2.5,不支持多窗口显示。  ffplay.c的需要修改queue_picture(),video_image_display()等函数。
2 SDL2的render不支持多线程处理(同时渲染的时候会内存冲突),需要修改SDL2的D3D函数(我用的windows),SDL_render_d3d.c,D3D_CreateRenderer()函数里面 IDirect3D9_CreateDevice()的调用参数,加上D3DCREATE_MULTITHREADED(支持多线程)。

修改源码
result = IDirect3D9_CreateDevice(data->d3d, data->adapter,
D3DDEVTYPE_HAL,
pparams.hDeviceWindow,
device_flags | D3DCREATE_MULTITHREADED,
&pparams, &data->device);

3 多线程启动播放。
fighttosky 2017-10-08
  • 打赏
  • 举报
回复
各路大神,有人在么?

2,542

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 多媒体/流媒体开发
社区管理员
  • 多媒体/流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧