源码下载地址: http://download.csdn.net/detail/liukang325/9489952

我用的ffmpeg版本为 ffmpeg-2.1.8.tar.bz2 
版本低了恐怕有些头文件和API找不到。 
在Linux下解压后编译,Linux下编译很简单,我这里生成的动态库: 
./configure –enable-shared 
make 
就能找到各个so动态库文件。 
移动位置后,记得手动链接 一下:

ln -s libavcodec.so.55 libavcodec.so
ln -s libavdevice.so.55 libavdevice.so
ln -s libavfilter.so.3 libavfilter.so
ln -s libavformat.so.55 libavformat.so
ln -s libavutil.so.52 libavutil.so
ln -s libswscale.so.2 libswscale.so

QT pro文件中记得加入: 
INCLUDEPATH += ffmpeg/include 
// windows下用这几个 
win32: LIBS += ffmpeg/lib/libavcodec.dll.a ffmpeg/lib/libavfilter.dll.a ffmpeg/lib/libavformat.dll.a ffmpeg/lib/libswscale.dll.a ffmpeg/lib/libavutil.dll.a 
// Linux下用这几个 
LIBS += -lavcodec -lavdevice -lavfilter -lavformat -lavutil -lswscale -L./ffmpeg/so

我这里对外提供三个接口:

void VideoStream::setUrl(QString url)
{
m_str_url = url;
} void VideoStream::startStream()
{
videoStreamIndex=-1;
av_register_all();//注册库中所有可用的文件格式和解码器
avformat_network_init();//初始化网络流格式,使用RTSP网络流时必须先执行
pAVFormatContext = avformat_alloc_context();//申请一个AVFormatContext结构的内存,并进行简单初始化
pAVFrame=av_frame_alloc();
if (this->Init())
{
m_timerPlay->start();
}
}
void VideoStream::stopStream()
{
m_timerPlay->stop(); avformat_free_context(pAVFormatContext);
av_frame_free(&pAVFrame);
sws_freeContext(pSwsContext);
}

里面与ffmpeg解码相关的私有变量:

    QMutex mutex;
AVPicture pAVPicture;
AVFormatContext *pAVFormatContext;
AVCodecContext *pAVCodecContext;
AVFrame *pAVFrame;
SwsContext * pSwsContext;
AVPacket pAVPacket;

在QT里,用一个QLabel的对象来显示解码后的视频画面:

connect(this,SIGNAL(GetImage(QImage)),this,SLOT(SetImageSlots(QImage)));

...
void VideoStream::SetImageSlots(const QImage &image)
{
if (image.height()>0){
QPixmap pix = QPixmap::fromImage(image.scaled(m_i_w,m_i_h));
m_label->setPixmap(pix);
}
}

这里用的QTimer来进行一帧帧数据的解码,也可以用一个线程比如QThread来进行解码:

    m_timerPlay = new QTimer;
m_timerPlay->setInterval(10);
connect(m_timerPlay,SIGNAL(timeout()),this,SLOT(playSlots())); m_i_frameFinished = 0; ...
bool VideoStream::Init()
{
if(m_str_url.isEmpty())
return false;
//打开视频流
int result=avformat_open_input(&pAVFormatContext, m_str_url.toStdString().c_str(),NULL,NULL);
if (result<0){
qDebug()<<"打开视频流失败";
return false;
} //获取视频流信息
result=avformat_find_stream_info(pAVFormatContext,NULL);
if (result<0){
qDebug()<<"获取视频流信息失败";
return false;
} //获取视频流索引
videoStreamIndex = -1;
for (uint i = 0; i < pAVFormatContext->nb_streams; i++) {
if (pAVFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStreamIndex = i;
break;
}
} if (videoStreamIndex==-1){
qDebug()<<"获取视频流索引失败";
return false;
} //获取视频流的分辨率大小
pAVCodecContext = pAVFormatContext->streams[videoStreamIndex]->codec;
videoWidth=pAVCodecContext->width;
videoHeight=pAVCodecContext->height; avpicture_alloc(&pAVPicture,PIX_FMT_RGB24,videoWidth,videoHeight); AVCodec *pAVCodec; //获取视频流解码器
pAVCodec = avcodec_find_decoder(pAVCodecContext->codec_id);
pSwsContext = sws_getContext(videoWidth,videoHeight,PIX_FMT_YUV420P,videoWidth,videoHeight,PIX_FMT_RGB24,SWS_BICUBIC,0,0,0); //打开对应解码器
result=avcodec_open2(pAVCodecContext,pAVCodec,NULL);
if (result<0){
qDebug()<<"打开解码器失败";
return false;
} qDebug()<<"初始化视频流成功";
return true;
} void VideoStream::playSlots()
{
//一帧一帧读取视频
if (av_read_frame(pAVFormatContext, &pAVPacket) >= 0){
if(pAVPacket.stream_index==videoStreamIndex){
qDebug()<<"开始解码"<<QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
avcodec_decode_video2(pAVCodecContext, pAVFrame, &m_i_frameFinished, &pAVPacket);
if (m_i_frameFinished){
mutex.lock();
sws_scale(pSwsContext,(const uint8_t* const *)pAVFrame->data,pAVFrame->linesize,0,videoHeight,pAVPicture.data,pAVPicture.linesize);
//发送获取一帧图像信号
QImage image(pAVPicture.data[0],videoWidth,videoHeight,QImage::Format_RGB888);
emit GetImage(image);
mutex.unlock();
}
}
}
av_free_packet(&pAVPacket);//释放资源,否则内存会一直上升
}

备注: 
头文件包含及注意事项

//必须加以下内容,否则编译不能通过,为了兼容C和C99标准

#ifndef INT64_C
#define INT64_C
#define UINT64_C
#endif //引入ffmpeg头文件
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libswscale/swscale.h>
#include <libavutil/frame.h>
}

启发: 
setUrl(QString url); 
这里的url 一般情况下是一个RTSP流的播放地址,如rtsp://192.168.1.123:554/stream1 
但也可以是一个TCP流。 
我这边测试的是一个本地的socket流,设url地址为 http://127.0.0.1:5858 
可直接解码播放。

ffmpeg解码RTSP/TCP视频流H.264(QT界面显示视频画面)的更多相关文章

  1. 视音频编解码学习工程:H.264分析器

    =====================================================视音频编解码学习工程系列文章列表: 视音频编解码学习工程:H.264分析器 视音频编解码学习工 ...

  2. FFmpeg开发笔记(九):ffmpeg解码rtsp流并使用SDL同步播放

    前言   ffmpeg播放rtsp网络流和摄像头流.   Demo   使用ffmpeg播放局域网rtsp1080p海康摄像头:延迟0.2s,存在马赛克     使用ffmpeg播放网络rtsp文件流 ...

  3. FMS发布视频流H.264如何设置

    FMS这个话题由来已久,H.264这个编码格式也由来已久.FMS不叫FMS了,改叫AMS了.因为是Adobe. 今天就说说flash发布流媒体视频,以H.264编码出现的问题.在网上找,大把的关于as ...

  4. (转)引用---FFMPEG解码过程

    视频播放过程 首先简单介绍以下视频文件的相关知识.我们平时看到的视频文件有许多格式,比如 avi, mkv, rmvb, mov, mp4等等,这些被称为容器(Container), 不同的容器格式规 ...

  5. 树莓派编译安装 FFmpeg(添加 H.264 硬件编解码器支持)

    说明 FFmpeg 是一套开源的音视频编解码库,有非常强大的功能,包括视频采集功能.视频格式转换等.众所周知视频编解码是一个非常消耗系统资源的过程,而树莓派自带了 H.264 的硬件编解码器,因此本文 ...

  6. FFmpeg的H.264解码器源代码简单分析:解析器(Parser)部分

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  7. h.264并行熵解码

    在前面讨论并行解码的章节中,我们专注于讨论解码的宏块重建部分,甚至把宏块重建描述成宏块解码,这是因为在解码工作中,宏块重建确实占了相当大的比重,不过解码还包含其它的部分,按照解码流程可粗略分为: 读取 ...

  8. 音视频编解码技术(一):MPEG-4/H.264 AVC 编解码标准

    一.H264 概述 H.264,通常也被称之为H.264/AVC(或者H.264/MPEG-4 AVC或MPEG-4/H.264 AVC) 1. H.264视频编解码的意义 H.264的出现就是为了创 ...

  9. (转载)H.264码流的RTP封包说明

    H.264的NALU,RTP封包说明(转自牛人) 2010-06-30 16:28 H.264 RTP payload 格式 H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) ...

随机推荐

  1. hihoCoder #1321 : 搜索五•数独 (Dancing Links ,精确覆盖)

    hiho一下第102周的题目. 原题地址:http://hihocoder.com/problemset/problem/1321 题意:输入一个9*9数独矩阵,0表示没填的空位,输出这个数独的答案. ...

  2. Lumen开发:lumen源码解读之初始化(1)——app实例

    版权声明:本文为博主原创文章,未经博主允许不得转载. 有些注释来着原文的百度翻译,可以有些难理解或者奇怪,我后面会根据自己的理解做调整的哈!!!不喜勿喷,层主英语不过关... 先来看看入口文件publ ...

  3. 纯JS实现动态时间

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. Idea 远程调试jenkins 项目

    1.Jenkins配置 jenkins 服务启动时 需要在jvm启动项里加入如下代码: -Xdebug -Xrunjdwp:transport=dt_socket,suspend=n,server=y ...

  5. 【BZOJ2401】陶陶的难题I 欧拉函数+线性筛

    [BZOJ2401]陶陶的难题I 题意:求,n<=1000000,T<=100000 题解:直接做是n*sqrt(n)的,显然会TLE,不过这题a和b都是循环到n,那么就可以进行如下的神奇 ...

  6. devexpress gridcontrol如何遍历每一行

    List<Medicine> medicinelist = new List<Medicine>(); foreach (GridViewRow row in GridView ...

  7. iptables的扩展,layer7实现

    l7filter:介绍 能过滤7层协议,例如过滤QQ.迅雷 原版只支持2.6.28,不支持centos6的2.6.32:马哥的版本支持2.6.32 实现l7filter: 给内核(netfilter) ...

  8. Action获取表单数据的三种方式

    1.使用ActionContext类获取 示例 获取用户提交的用户名和密码 jsp页面 action中的java代码 2.使用ServletActionContext类获取 jsp页面 Java代码 ...

  9. Python锁

    # coding:utf-8 import threading import time def test_xc(): f = open("test.txt","a&quo ...

  10. LeetCode:加一【66】

    LeetCode:加一[66] 题目描述 给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一. 最高位数字存放在数组的首位, 数组中每个元素只存储一个数字. 你可以假设除了整数 0 之外 ...