ffmpeg解码RTSP/TCP视频流H.264(QT界面显示视频画面)

源码下载地址: 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 
可直接解码播放。

时间: 2024-10-05 06:39:43

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

怎样实现对h.264接收的视频进行实时播放

问题描述 我现在在弄一个实时视频播放,采用java开发,由采集器上送rtp视频报文,报文中视频格式为h.264,我已经编写java代码实现了h.264的解码,现在要找一个开源的播放器实现在浏览器上实时播放采集的视频,请问我应该怎样实现,有demo的最好. 解决方案 解决方案二:哪个大神帮帮忙啊解决方案三:顶,同问!!解决方案四:同问,,,,,,,解决方案五:http://blog.csdn.net/sweetwxh/article/details/6555199

【H.264/AVC视频编解码技术详解】三. H.264简介

<H.264/AVC视频编解码技术详解>视频教程已经在"CSDN学院"上线,视频中详述了H.264的背景.标准协议和实现,并通过一个实战工程的形式对H.264的标准进行解析和实现,欢迎观看! "纸上得来终觉浅,绝知此事要躬行",只有自己按照标准文档以代码的形式操作一遍,才能对视频压缩编码标准的思想和方法有足够深刻的理解和体会! 链接地址:H.264/AVC视频编解码技术详解 本节视频免费 一. H.264视频编码标准 H.264视频编码标准是ITU-T与

基于Live555,ffmpeg的RTSP播放器直播与点播

基于Live555,ffmpeg的RTSP播放器直播与点播 多路RTSP高清视频播放器下载地址:http://download.csdn.net/detail/u011352914/6604437多路RTSP播放器源码下载地址:http://download.csdn.net/detail/u011352914/6603251多路RTSP播放器SDK说明下载地址:http://download.csdn.net/detail/u011352914/6603271详细完整资料下载地址:http:/

H.264视听新境界

长期关注电影信息的朋友一定会注意到,最近有一种带有"H.264"标识的电影资源开始出现在网上.有这种标识的电影文件通常体积庞大,基本上都在4GB以上,而且往往与"HDTV"之类的字样伴随出现.这个标识究竟有着什么样的含义呢? 什么是H.264 简单地说,H.264就是一种新型的视频编码格式,它是目前MPEG-4标准所定义的最新.技术含量最高的视频编码格式之一.绕过那些晦涩难懂的技术名词,一言以蔽之,H.264的优点在于更高的数据压缩比,在同等的图像质量条件下,H.2

H.264码流结构解析

from:http://wenku.baidu.com/link?url=hYQHJcAWUIS-8C7nSBbf-8lGagYGXKb5msVwQKWyXFAcPLU5gR4BKOVLrFOw4bX5nWwGxQ9d1-kj0JYvAZA5-wz7KmW4tYeF_qmS1FNyV2e   H.264码流结构解析 1. H.264简介 MPEG(Moving Picture Experts Group)和VCEG(Video Coding Experts Group)已经联合开发了一个比早期研

【FFMpeg视频开发与应用基础】三、调用FFmpeg SDK对H.264格式的视频压缩码流进行解码

<FFMpeg视频开发与应用基础--使用FFMpeg工具与SDK>视频教程已经在"CSDN学院"上线,视频中包含了从0开始逐行代码实现FFMpeg视频开发的过程,欢迎观看!链接地址:FFMpeg视频开发与应用基础--使用FFMpeg工具与SDK 工程代码地址:FFmpeg_Tutorial 经过了上篇调用FFMpeg SDK对视频进行编码的过程之后,我们可以比较容易地理解本篇的内容,即上一篇的逆过程--将H.264格式的裸码流解码为像素格式的图像信息. 1.FFMpeg视频

嵌入式 RTP通话:视频流(H.264)的传输

从摄像头获取的视频数据,经过编码后(当然,也可以不编码,如果你觉得也很ok的话),既可以视频录制,同时如果需要,当然也可以视频远程传输咯,而实时传输协议(Real-time Transport Protocol,RTP)是在Internet上处理多媒体数据流的一种网络协议,利用它能够在一对一(unicast,单播)或者一对多(multicast,多播)的网络环境中实现传流媒体数据的实时传输(不需要下载完毕后才能看视频).RTP通常使用UDP来进行多媒体数据的传输,但如果需要的话可以使用TCP等其

视频-qt通过显示ffmpeg解码出的图像

问题描述 qt通过显示ffmpeg解码出的图像 已经实现ffmpeg解码http视频流为一帧一帧是图像. 想通过OpenGL 或者 QML 或者 还有其他什么办法可以把这些帧图像显示出(视频帧率:30fps,大小:1280x720) 解决方案 http://www.oschina.net/question/202950_88107?sort=timehttp://www.oschina.net/code/snippet_1466652_44272

【H.264/AVC视频编解码技术详解】七、 熵编码算法(1):基础知识

<H.264/AVC视频编解码技术详解>视频教程已经在"CSDN学院"上线,视频中详述了H.264的背景.标准协议和实现,并通过一个实战工程的形式对H.264的标准进行解析和实现,欢迎观看! "纸上得来终觉浅,绝知此事要躬行",只有自己按照标准文档以代码的形式操作一遍,才能对视频压缩编码标准的思想和方法有足够深刻的理解和体会! 链接地址:H.264/AVC视频编解码技术详解 GitHub代码地址:点击这里 本节视频免费 1. 熵编码概念 "熵&