开始写博客!!今天第一个:FFmpeg解码网络rtsp流的一般流程和这几天遇到的问题,尤其是avformat_input_open解析错误的网络串流长时间不返回!
2014-09-26 17:16
519 查看
AVFormatContext* m_pFormatCtx;
AVCodecContext * m_pCodecCtx;
AVCodec* m_pCodec;
AVFrame* m_pFrame;
AVPacket m_AVPkt;
// 注册库
av_register_all();
avformat_network_init();
//打开文件或者是网络串流
avformat_open_input(&m_pFormatCtx,pcURL,NULL,NULL);
/***************************************************************************************/
在函数avformat_open_input函数中,我们解析错误的网络缠流会出现函数长时间不返回的现象
要解决这个现象,我们需要在AVFromatContext结构体中为nterrupt_callback.callback赋回调函数,来保证打开流超时的情况下函数avformat_open_input能够正确
返回错误代码
回调函数示例:
int CRtpStreamCtlByFFMpeg::interrupt_cb(LPVOID ctx)
{
/*AVFormatContext* formatContext =
reinterpret_cast<AVFormatContext*>(ctx);*/
// CRtpStreamCtlByFFMpeg:解码类
// 该函数主要的思想就是在解码启动的时候获得启动时间(p->m_VideoInfoForShow.nLastTime )
// 然后判断程序是否已经获得流信息并开始接收流,也就是判断AVFormatContext中start_time参数是否已经有了大于0的值
CRtpStreamCtlByFFMpeg* p = (CRtpStreamCtlByFFMpeg*)ctx;
//timeout after 5 seconds of no activity
if (p->m_pFormatCtx->start_time < 0)
{
p->m_pFormatCtx->start_time = 0;
}
if (p->m_pFormatCtx->start_time <= 0 && timeGetTime() - p->m_VideoInfoForShow.nLastTime >5000)
{
p->m_count = 0;
return 1;
}
return 0;
}
/***************************************************************************************/
// 查找流的信息,从网络串流中找到我们需要的视频\音频流
avformat_find_stream_info(m_pFormatCtx,NULL)
// 查找解码解码器
avcodec_find_decoder(m_pCodecCtx->codec_id)
// 打开解码器
avcodec_open2(m_pCodecCtx, m_pCodec,NULL)
// 为帧申请内存
m_pFrame = avcodec_alloc_frame();
// 从文件\网络串流中读取数据帧
av_read_frame(pC->m_pFormatCtx, &AvPkt)
// 解码,got_picture 的值表示解码是否成功,成功为1,失败为0
avcodec_decode_video2(m_pCodecCtx, m_pFrame, &got_picture, &avPkt)
/***************************************************************************************/
至此,使用FFmpeg打开文件\网络串流、接收数据,解码的工作已经全部完成,但要注意的是
FFMpeg默认解码h264数据位YUV420格式,如果需要将YUV420数据转换到RGB24数据,则需要
使用sws函数组
/***************************************************************************************/
// 首先为一个AVFrame申请内存
pFrameRGB=avcodec_alloc_frame();
// 获得YUV420格式帧的大小
nRGBSize = avpicture_get_size(PIX_FMT_RGB24, m_pCodecCtx->width, m_pCodecCtx->height);
// 填充新申请的RGB数据帧
avpicture_fill((AVPicture *)pFrameRGB, out_buffer, PIX_FMT_RGB24, m_pCodecCtx->width, m_pCodecCtx->height);
// 获得swsContext
img_convert_ctx = sws_getContext(m_pCodecCtx->width, m_pCodecCtx->height, m_pCodecCtx->pix_fmt,\
m_pCodecCtx->width, m_pCodecCtx->height, PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
// 转码
sws_scale(img_convert_ctx, (const uint8_t* const*)m_pFrame->data, m_pFrame->linesize, 0, m_pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
//释放swsContext
sws_freeContext(img_convert_ctx); //这一步非常重要,如果不将swsContext释放掉,就会造成内存泄露
AVCodecContext * m_pCodecCtx;
AVCodec* m_pCodec;
AVFrame* m_pFrame;
AVPacket m_AVPkt;
// 注册库
av_register_all();
avformat_network_init();
//打开文件或者是网络串流
avformat_open_input(&m_pFormatCtx,pcURL,NULL,NULL);
/***************************************************************************************/
在函数avformat_open_input函数中,我们解析错误的网络缠流会出现函数长时间不返回的现象
要解决这个现象,我们需要在AVFromatContext结构体中为nterrupt_callback.callback赋回调函数,来保证打开流超时的情况下函数avformat_open_input能够正确
返回错误代码
回调函数示例:
int CRtpStreamCtlByFFMpeg::interrupt_cb(LPVOID ctx)
{
/*AVFormatContext* formatContext =
reinterpret_cast<AVFormatContext*>(ctx);*/
// CRtpStreamCtlByFFMpeg:解码类
// 该函数主要的思想就是在解码启动的时候获得启动时间(p->m_VideoInfoForShow.nLastTime )
// 然后判断程序是否已经获得流信息并开始接收流,也就是判断AVFormatContext中start_time参数是否已经有了大于0的值
CRtpStreamCtlByFFMpeg* p = (CRtpStreamCtlByFFMpeg*)ctx;
//timeout after 5 seconds of no activity
if (p->m_pFormatCtx->start_time < 0)
{
p->m_pFormatCtx->start_time = 0;
}
if (p->m_pFormatCtx->start_time <= 0 && timeGetTime() - p->m_VideoInfoForShow.nLastTime >5000)
{
p->m_count = 0;
return 1;
}
return 0;
}
/***************************************************************************************/
// 查找流的信息,从网络串流中找到我们需要的视频\音频流
avformat_find_stream_info(m_pFormatCtx,NULL)
// 查找解码解码器
avcodec_find_decoder(m_pCodecCtx->codec_id)
// 打开解码器
avcodec_open2(m_pCodecCtx, m_pCodec,NULL)
// 为帧申请内存
m_pFrame = avcodec_alloc_frame();
// 从文件\网络串流中读取数据帧
av_read_frame(pC->m_pFormatCtx, &AvPkt)
// 解码,got_picture 的值表示解码是否成功,成功为1,失败为0
avcodec_decode_video2(m_pCodecCtx, m_pFrame, &got_picture, &avPkt)
/***************************************************************************************/
至此,使用FFmpeg打开文件\网络串流、接收数据,解码的工作已经全部完成,但要注意的是
FFMpeg默认解码h264数据位YUV420格式,如果需要将YUV420数据转换到RGB24数据,则需要
使用sws函数组
/***************************************************************************************/
// 首先为一个AVFrame申请内存
pFrameRGB=avcodec_alloc_frame();
// 获得YUV420格式帧的大小
nRGBSize = avpicture_get_size(PIX_FMT_RGB24, m_pCodecCtx->width, m_pCodecCtx->height);
// 填充新申请的RGB数据帧
avpicture_fill((AVPicture *)pFrameRGB, out_buffer, PIX_FMT_RGB24, m_pCodecCtx->width, m_pCodecCtx->height);
// 获得swsContext
img_convert_ctx = sws_getContext(m_pCodecCtx->width, m_pCodecCtx->height, m_pCodecCtx->pix_fmt,\
m_pCodecCtx->width, m_pCodecCtx->height, PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
// 转码
sws_scale(img_convert_ctx, (const uint8_t* const*)m_pFrame->data, m_pFrame->linesize, 0, m_pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
//释放swsContext
sws_freeContext(img_convert_ctx); //这一步非常重要,如果不将swsContext释放掉,就会造成内存泄露
相关文章推荐
- FFmpeg avformat_open_input函数打开acc,h264失败的错误问题
- ffmpeg源码简析(七)解码-avformat_open_input,avformat_find_stream_info()
- 针对ffmpeg做rtsp客户端时,avformat_find_stream_info长时间等待问题
- ffmpeg调用 avformat_open_input失败,返回 -2
- ffmpeg avformat_open_input返回失败的解决办法
- FFMpeg分析:第一个函数avformat_open_input
- ffmpeg调用 avformat_open_input失败,返回 -2
- android ndk ffmpeg 用avformat_input_file 打开rtsp流,返回错误信息-5的解决方法
- ffmpeg avformat_open_input返回失败的解决办法
- ffmpeg问题汇总及解决方案 <设置avformat_open_input 超时><转>
- ffmpeg avformat_open_input返回失败的解决办法
- ffmpeg avformat_open_input返回失败的解决办法
- FFMPEG学习遇到avformat_open_input Invalid data found when processing input
- FFmpeg中函数avformat_open_input()(含URL解析文件格式)
- ffmpeg avformat_open_input返回失败的解决办法
- FFMpeg分析:第一个函数avformat_open_input
- 从今天开始我遇到所有问题及解决办法我都要写博客了
- 解决ajax程序访问服务器返回的XML文件时, firebug出现: XML 解析错误问题
- 遇到的问题-在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误
- FFMPEG-avformat_open_input