FFmpeg+SDL2 同一运行时观察主线程卡顿播放卡顿解决方法

MFC中FFMPEG+SDL播放音频的时候在主界面中播放有声音,创建线程去播放没有声音
[问题点数:40分]
本版专家分:0
CSDN今日推荐
匿名用户不能发表回复!|
其他相关推荐vc中ffmpeg+sdl如何实现多路网络视频流播放?
[问题点数:40分]
本版专家分:0
CSDN今日推荐
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
本版专家分:0
匿名用户不能发表回复!|
其他相关推荐本人自己学习记录,大家觉得有益则取,无用则弃。
SDL+FFMPEG+VS2017遇到的问题及解决方法(更新)
1被声明为已否决
其他类似错误请参见:https://blog.csdn.net/qq_/article/details/pCodecCtx = pFormatCtx-&streams[videoIndex]-&//不能这么得到codec
正确做法:
pCodecCtx = avcodec_alloc_context3(NULL);
if (pCodecCtx == NULL) {
printf("Could not allocate AVCodecContext\n");
return -1; }
avcodec_parameters_to_context(pCodecCtx, pFormatCtx-&streams[videoIndex]-&codecpar);
pCodec = avcodec_find_decoder(pCodecCtx-&codec_id);
if (pCodec == NULL) {
printf("Codec not found.\n");
return -1; }fopen_s(&fp,filename, "w+b");//fopen不可用2 小记
AVInputFormat:封装格式mp4,avi
AVStream[2]:0视频流 1音频流
index:标识符0/1
AVPacket:h.264:AVCodec
AVFrame:yuv
AVFormatContext-&AV
H264文件头数据其实是一段包含SPS(序列参数集)、PPS(图像参数集)的数据,里面的参数用来配置解码器的初始化。
H264格式文件中每一段NALU的长度不是固定的,这就需要在读取文件中做判断。
AVFormatContext *pFormatCtx = NULL;
AVCodecContext *pCodecCtx = NULL;
AVCodec *pC3 未定义标识符AV_CODEC_FLAG2_CHUNKS
解决:转到定义,填具体代表的数据4 ffmpeg.exe 命令行详细解析:http://www.cnblogs.com/wainiwann/p/4128154.html5 包含SDL库的main函数:int main(int argc, char *argv[])6 .cpp文件即C++写的,包含文件应该为extern "C"{
//包含SDL.h和ffmpeg的库
};extern "C"{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswresample/swresample.h"
#include "libavutil/audio_fifo.h"
#include &SDL.h&
#include &SDL_thread.h&7 测试SDL配置是否成果的代码:int main(int argc, char *argv[]) {
if (SDL_Init(SDL_INIT_VIDEO))
cout && 1;
else cout && 0;
getchar();
8 测试SDL 必须定义程序入口点
解决:我原先建立的是空项目,so把子系统改为控制台即可。or#ifdef __MINGW32__#undef main // Prevents SDL from overriding main().#endif9//音视频输出格式信息
av_dump_format(CodecCtx, 0, 文件名, 0);10 ffmpeg音频处理过程11
structSwsContext
(software scale)主要用于视频图像的转换,比如格式转换:参考
structSwrContext
(software resample)主要用于音频重采样,比如采样率转换,声道转换。参考:重采样,也就是对已得到的数据进行重新的采样;比如,原先的PCM音频数据是2 个声道,44100采样率,32bit 单精度型(sample format采样格式)。 那么通过重采样,我们改变它的声道数、采样率和采样格式。12 memset()
没有更多推荐了,FFMPEG+SDL解码出现声音视频都是一卡一卡的
[问题点数:60分,无满意结帖,结帖人a]
本版专家分:0
结帖率 99.02%
CSDN今日推荐
本版专家分:0
匿名用户不能发表回复!|
其他相关推荐&最近因为项目接近收尾阶段,所以变的没有之前那么忙了,所以最近重新拿起了之前的一些FFMPEG和SDL的相关流媒体播放器的例子在看。
同时自己也用FFMPEG2.01,SDL2.01结合MFC以及网上罗列的一些资料,打算打造一款自己的简易播放器。
最先开始是阅读了&An ffmpeg and SDL Tutorial&以及来源与(http://blog.csdn.net/love4mario/article/details/)中的中文资料,同时认真对tutorial01-08中的代码,也进行一次阅读。
然后打算修改tutorial07中的代码来做播放器的代码。
修改完了以后,编译也通过了,然后播放出来的画面却是这个样子的:
开始的时候,不理解者几个函数里面的参数,感觉是这里设置出错了。
在经过查找资料以后,得到的个人理解为:
\brief Update the given texture rectangle with new pixel data. *
\param texture
The texture to update *
\param rect
A pointer to the rectangle of pixels to update, or NULL to&update the entire texture. *
\param pixels
The raw pixel data. *
\param pitch
The number of bytes between rows of pixel data. *
\return 0 on success, or -1 if the texture is not valid. *
\note This is a fairly slow function. */extern DECLSPEC int SDLCALL SDL_UpdateTexture(SDL_Texture * texture,const SDL_Rect * rect,const void *pixels, int pitch);
SDL_UpdateTexture( SDL_Texture * texture, & & & &/*需要更新的Texture,*/ & & &         const SDL_Rect * rect, & & & & /*更新的区域,如果为NULL,表示更新整个区域*/            const void *pixels, & & & & & &/*the raw pixel data,元素像素数据*/           int pitch); & & & & & & & & & & &/*the number of bytes between rows of pixel data,每一行原始数据的大小*/
------------------------------------------------------------------------------------------------------------------------------------------
\brief Copy a portion of the texture to the current rendering target. *
\param renderer The renderer which should copy parts of a texture. *
\param texture The source texture. *
\param srcrect
A pointer to the source rectangle, or NULL for the entire&&texture. *
\param dstrect
A pointer to the destination rectangle, or NULL for the&entire rendering target. *
\return 0 on success, or -1 on error */extern DECLSPEC int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer,   /*从texture复制到rendering的目标*/
                         SDL_Texture * texture,    /*源texture*/
                         const SDL_Rect * srcrect,   /*源拷贝的范围*/
                         const SDL_Rect * dstrect);  /*目的拷贝范围*/
于是继续进行修改:
这个时候,画面已经能正常显示了,但是并没有达到我的目的,我的目的本来是想让整个绿色区域(也就算一个static控件)全部铺满视频。
所以这个时候,我去群里问了一下,有好心的朋友告诉我,你看一下是不是转化的时候设置有问题。
于是我这个时候我就拿很有代表性的例子,也比较简单的例子&最简单的基于FFMPEG+SDL的视频播放器 ver2 (采用SDL2.0&来做测试,查看时哪里出了问题。
这个例子虽然简单,但是很有代表性,因为代码工程不大,容易调试和找问题,同时它又把重点函数全部提了出来。
下一步,调试&最简单的基于FFMPEG+SDL的视频播放器 ver2 (采用SDL2.0&:
*pFrame,*pFrameYUV;
pFrame=avcodec_alloc_frame();
pFrameYUV=avcodec_alloc_frame();
uint8_t *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);
int screen_w=0,screen_h=0;
SDL_Window *
//SDL 2.0 Support for multiple windows
screen_w = pCodecCtx-&
screen_h = pCodecCtx-&
screen = SDL_CreateWindow("Simplest ffmpeg player's Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
    screen_w, screen_h,
    SDL_WINDOW_OPENGL);
//IYUV: Y + U + V
(3 planes)
//YV12: Y + V + U
(3 planes)
SDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer,
SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING,
                pCodecCtx-&width,pCodecCtx-&height);
SDL_Rect sdlR
sdlRect.x = 0;
sdlRect.y = 0;
sdlRect.w = screen_w;
sdlRect.h = screen_h;
struct SwsContext *img_convert_
img_convert_ctx = sws_getContext(pCodecCtx-&width, pCodecCtx-&height, pCodecCtx-&pix_fmt,
                   pCodecCtx-&width, pCodecCtx-&height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
上面这4段代码就是转换参数相关的代码,因为这里面的代码,它在设置显示的时候:
&screen_w = pCodecCtx-&
screen_h = pCodecCtx-&
所以我们在参考上面代码时候,目的和源设置一样的,所以不知道上面这些关键函数到底是跟显示有什么关系,哪些应该需要设置为我们想要的显示效果,哪些参数必须使用源流中的参数。
所以现在我打算改变一下参数,让它最后显示出来的视频大小为宽度为800,高度为600.
所以我们再创建窗口的时候,
screen_w =800;
screen_h =600;
那么还需要哪些关键函数必须跟着做变化呢?
首先来看代码1:
AVFrame *pFrame,*pFrameYUV;这两个指针,前面一个用来指向解码以后的帧数据缓存,后面一个pFrameYUV用来指向数据转换以后的缓存,就算我们最后显示的时候取数据的缓存指针。
SDL_UpdateTexture( sdlTexture, NULL, pFrameYUV-&data[0], pFrameYUV-&linesize[0] );&
这个函数在进行更新数据的时候,需要从pFrameYUV指向的内存数据区去取数据,然后更新到sdlTexture缓冲区。
在这个更新的过程,其实并不是仅仅的进行数据缓冲区的拷贝,因为这个函数还需要做很多的事情.()
SDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING,                        screen_w,screen_h);
这个函数指定显示的时候,数据格式:SDL_PIXELFORMAT_YV12
而渲染数据进行拷贝的时候:
SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, NULL);&
就是把开始更新到sdlTexture数据缓冲区的数据,再进行一次拷贝到渲染缓冲区。最后就可以进行渲染显示了。
那么在数据格式进行转换之前,我们需要设置什么呢?
img_convert_ctx = sws_getContext(pCodecCtx-&width, pCodecCtx-&height, pCodecCtx-&pix_fmt, /*源数据格式信息*/
                  screen_w,screen_h,PIX_FMT_YUV420P,            /*目的数据格式信息*/
                  SWS_BICUBIC, NULL, NULL, NULL);
转换前的获取转换上下文,这个函数将告诉我们在进行转换的时候,需要将源数据---(转换成怎么样的)---&目的数据格式信息。
也许你也跟我有一样的疑问,为什么这里设置转换参数的时候,目的数据格式为:PIX_FMT_YUV420P 而不是我们最后显示的数据格式:YV12.
确实是这样的,这里我们设置的转换目的参数为PIX_FMT_YUV420P 而不是YV12.
显示的数据格式为yv12,我们可以从
SDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING,screen_w,screen_h);
这个函数指定,这里就是对显示的数据进行初始化。
那么数据从PIX_FMT_YUV420P -----------------------------&YV12又是那个函数做的呢?
这个过程就是我们上面的函数SDL_UpdateTexture中实现的,它不仅会将pFrameYUV指向的缓存区进行拷贝,而且会将PIX_FMT_YUV420P --拷贝成-&YV12格式。
上面这个过程我们明白了从转换后处理的数据到显示数据的一个过程。那么如果源数据的宽度和高度并不是我们想要的,我们需要对源数据进行拉伸或者放大,那么我们转换后的数据缓冲区是不是就和源数据缓冲区的大小不一样?
这是肯定的。
所以转换前后存放数据的缓冲区大小也就不一样,所以这里我们需要为转换后的数据缓冲区申请缓冲区大小,同时需要对申请以后得到的转换后的数据缓冲区进行一定格式的划分。
这个过程我们由下面这个函数来完成:
uint8_t *out_buffer=(uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P,
                      screen_w,screen_h));
申请转换以后的数据缓冲区大小。 avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P,
            screen_w,screen_h);
对转换后存放数据的数据缓冲区,进行按格式存放划分。
---------------------------------------------------------------------------------------------
其中查找资料的过程中,记录下资料的出处:
1)SDL实现overlay方式双屏显示的应用流程分析(thinkvd开发日志)
  http://blog.163.com/tfn2008@yeah/blog/static//
  http://blog.csdn.net/zhuweigangzwg/article/details/
3)SDL2.0在mfc窗口中显示yuv的一种方法 &
  http://airmanisvip.blog.163.com/blog/static// 
  http://blog.csdn.net/love4mario/article/details/
  http://blog.csdn.net/leixiaohua1020/article/details/
6)SDL 2.0 API by Name
  https://wiki.libsdl.org/CategoryAPI
-----------------------------------------------------------------------------------------------
本文出自:http://www.cnblogs.com/lihaiping/p/4025138.html
个人的理解,如果有误,请指正。望努力拍砖。
阅读(...) 评论()

我要回帖

更多关于 玩dnf卡顿解决方法 的文章

 

随机推荐