我用的ffmpeg版本为 ffmpeg-2.1.8.tar.bz2

来源:互联网 发布:js文件解压缩 编辑:程序博客网 时间:2024/06/05 09:03

源码下载地址: 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.soln -s libavdevice.so.55 libavdevice.soln -s libavfilter.so.3 libavfilter.soln -s libavformat.so.55 libavformat.soln -s libavutil.so.52 libavutil.soln -s libswscale.so.2 libswscale.so
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

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

    QMutex mutex;    AVPicture  pAVPicture;    AVFormatContext *pAVFormatContext;    AVCodecContext *pAVCodecContext;    AVFrame *pAVFrame;    SwsContext * pSwsContext;    AVPacket pAVPacket;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在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);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这里用的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);//释放资源,否则内存会一直上升}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

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

//必须加以下内容,否则编译不能通过,为了兼容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>}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

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

0 0