Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++ Qt
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
ZigliShow
4 / 3 / 2
Регистрация: 20.02.2018
Сообщений: 12
1

Использование библиотек FFmpeg в QMdiSubWindow

13.03.2018, 08:19. Просмотров 1099. Ответов 4
Метки нет (Все метки)

На ГитХабе есть пример использования библиотек FFmpeg для просмотра камер видеонаблюдения по протоколу RTSP.
https://github.com/liushuo0826/QT-RTSP-DEMO
Собственно вот:
https://cdn1.savepice.ru/uploads/201...e7f6a-full.png
Пример рабочий.

Необходимо сделать так, чтобы одновременно можно было подключить несколько камер. Решено было использовать QMdiArea и QSubWindow.
Добавил кнопочку на форму, по нажатию которой в QMdiArea добавлялись QSubWindow.
https://cdn1.savepice.ru/uploads/201...5fabb-full.png
И изменил пример с ГитХаба под мои нужды.

RTSPClient.pro
C++ (Qt)
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
QT       += core gui
 
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 
TARGET = RTSPClient
TEMPLATE = app
 
 
SOURCES += main.cpp\
    FFmpeg.cpp \
    login.cpp \
    dynamiclist.cpp \
    cameras.cpp
 
HEADERS  += \
    FFmpeg.h \
    login.h \
    dynamiclist.h \
    cameras.h
 
FORMS    += login.ui \
    cameras.ui
 
LIBS += "C:\Qt\Qt5.1.1\Tools\ffmpeg-3.4.1-desktop-MINGW\lib\x86\libavcodec.dll.a"
LIBS += "C:\Qt\Qt5.1.1\Tools\ffmpeg-3.4.1-desktop-MINGW\lib\x86\libavformat.dll.a"
LIBS += "C:\Qt\Qt5.1.1\Tools\ffmpeg-3.4.1-desktop-MINGW\lib\x86\libavfilter.dll.a"
LIBS += "C:\Qt\Qt5.1.1\Tools\ffmpeg-3.4.1-desktop-MINGW\lib\x86\libswscale.dll.a"
LIBS += "C:\Qt\Qt5.1.1\Tools\ffmpeg-3.4.1-desktop-MINGW\lib\x86\libavdevice.dll.a"
LIBS += "C:\Qt\Qt5.1.1\Tools\ffmpeg-3.4.1-desktop-MINGW\lib\x86\libavutil.dll.a"
INCLUDEPATH += "C:\Qt\Qt5.1.1\Tools\ffmpeg-3.4.1-desktop-MINGW\include"
cameras.h
C++ (Qt)
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
#ifndef CAMERAS_H
#define CAMERAS_H
 
#include <QWidget>
#include <QMainWindow>
#include "FFmpeg.h"
#include <QMdiArea>
 
namespace Ui {
class CAMERAS;
}
 
class CAMERAS : public QWidget
{
    Q_OBJECT
 
public:
    explicit CAMERAS(QWidget *parent = 0);
    ~CAMERAS();
    void paintEvent(QPaintEvent *);
    void setFFmpeg(FFmpeg * ff);
 
 
private:
    Ui::CAMERAS *ui;
    FFmpeg * ffmpeg;
    QMdiArea * mdiArea;
};
 
#endif // CAMERAS_H
FFmpeg.h
C++ (Qt)
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
/*
 * FFmpeg.h
 *
 *  Created on: 2014年2жњ€25ж—Ґ
 *      Author: ny
 */
 
#ifndef FFMPEG_H_
#define FFMPEG_H_
 
#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif
 
extern "C"
{
 
 
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libswscale/swscale.h>
#include <libavutil/frame.h>
}
#include <QReadWriteLock>
#include <QMutex>
#include <QString>
class FFmpeg
{
public:
    FFmpeg();
    int initial(QString & url);
    int h264Decodec();
    virtual ~FFmpeg();
    friend class Video;
//private:
    AVFormatContext *pFormatCtx;
    AVCodecContext *pCodecCtx;
    AVFrame *pFrame;
    AVPacket packet;
    AVPicture  picture;
    SwsContext * pSwsCtx;
    int videoStream;
    int width;
    int height;
    QMutex mutex;
    QString rtspURL;
 
};
 
#endif /* FFMPEG_H_ */
login.h
C++ (Qt)
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
#ifndef LOGIN_H
#define LOGIN_H
 
#include <QDialog>
#include <qstring.h>
#include "video.h"
#include "dynamiclist.h"
#include <QPointer>
#include "ui_cameras.h"
#include "cameras.h"
#include <QMdiArea>
#include <QMdiSubWindow>
 
 
namespace Ui {
class Login;
}
 
class cameras
{
};
 
class Login : public QDialog
{
    Q_OBJECT
 
public:
    explicit Login(QWidget *parent = 0);
    ~Login();
    QString getRtspURL();
    void loadSubWindow(cameras *widget);
 
private slots:
    void on_btn_play_clicked();
    void on_pushButton_Cameras_clicked();
    //void slotGetNumber();
    void addSubWin() {
        CAMERAS *camera = new CAMERAS;
        mdi->addSubWindow(camera);
        camera->show();
    }
private:
    Ui::Login *ui;
    QString rtspURL;
    QMdiArea *mdi;
};
 
#endif // LOGIN_H
cameras.cpp
C++ (Qt)
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
#include "cameras.h"
#include "ui_cameras.h"
#include <QPainter>
 
CAMERAS::CAMERAS(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::CAMERAS)
{
    ui->setupUi(this);
    ffmpeg=NULL;
}
 
CAMERAS::~CAMERAS()
{
    delete ui;
}
void CAMERAS::setFFmpeg(FFmpeg *ff)
{
    ffmpeg=ff;
}
 
void CAMERAS::paintEvent(QPaintEvent *)
{
 
    if(ffmpeg->picture.data!=NULL)
    {
     QPainter painter(this);
    if(ffmpeg->mutex.tryLock(1000))
    {
        QImage image=QImage(ffmpeg->picture.data[0],ffmpeg->width,ffmpeg->height,QImage::Format_RGB888);
        QPixmap  pix =  QPixmap::fromImage(image);
        painter.drawPixmap(0, 0, this->geometry().width(),this->geometry().height(), pix);
        update();
        ffmpeg->mutex.unlock();
    }
    }
}
FFmpeg.cpp
C++ (Qt)
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
 * FFmpeg.cpp
 *
 *  Created on: 2014年2жњ€25ж—Ґ
 *      Author: ny
 */
 
#include "FFmpeg.h"
 
FFmpeg::FFmpeg()
{
    pCodecCtx = NULL;
    videoStream=-1;
 
}
 
FFmpeg::~FFmpeg()
{
    sws_freeContext(pSwsCtx);
}
 
int FFmpeg::initial(QString & url)
{
    int err;
    rtspURL=url;
    AVCodec *pCodec;
    av_register_all();
    avformat_network_init();
    pFormatCtx = avformat_alloc_context();
    pFrame=av_frame_alloc();
    err = avformat_open_input(&pFormatCtx, rtspURL.toStdString().c_str(), NULL,
                              NULL);
    if (err < 0)
    {
        printf("Can not open this file");
        return -1;
    }
    if (avformat_find_stream_info(pFormatCtx,NULL) < 0)
    {
        printf("Unable to get stream info");
        return -1;
    }
    int i = 0;
    videoStream = -1;
    for (i = 0; i < pFormatCtx->nb_streams; i++)
    {
        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            videoStream = i;
            break;
        }
    }
    if (videoStream == -1)
    {
        printf("Unable to find video stream");
        return -1;
    }
    pCodecCtx = pFormatCtx->streams[videoStream]->codec;
 
    width=pCodecCtx->width;
    height=pCodecCtx->height;
    avpicture_alloc(&picture,AV_PIX_FMT_RGB24,pCodecCtx->width,pCodecCtx->height);
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    pSwsCtx = sws_getContext(width, height, AV_PIX_FMT_YUV420P, width,
            height, AV_PIX_FMT_RGB24,
            SWS_BICUBIC, 0, 0, 0);
 
    if (pCodec == NULL)
    {
        printf("Unsupported codec");
        return -1;
    }
    printf("video size : width=%d height=%d \n", pCodecCtx->width,
           pCodecCtx->height);
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
    {
        printf("Unable to open codec");
        return -1;
    }
    printf("initial successfully");
    return 0;
}
 
int FFmpeg::h264Decodec()
{
    int frameFinished=0;
    while (av_read_frame(pFormatCtx, &packet) >= 0)
    {
        if(packet.stream_index==videoStream)
        {
            avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
            if (frameFinished)
            {
                printf("***************ffmpeg decodec*******************\n");
                mutex.lock();
                int rs = sws_scale(pSwsCtx, (const uint8_t* const *) pFrame->data,
                                   pFrame->linesize, 0,
                                   height, picture.data, picture.linesize);
                mutex.unlock();
                if (rs == -1)
                {
                    printf("__________Can open to change to des imag_____________e\n");
                    return -1;
                }
            }
        }
    }
    return 1;
 
}
cameras.cpp
C++ (Qt)
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
#include "login.h"
#include "ui_login.h"
#include <qstring.h>
#include <stdio.h>
#include <QString>
#include "video.h"
#include "FFmpeg.h"
#include <qthread.h>
#include <QWidget>
#include "CAMERAS.h"
#include <QMdiSubWindow>
 
Login::Login(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Login)
{
    ui->setupUi(this);
}
 
Login::~Login()
{
    delete ui;
}
 
void Login::on_btn_play_clicked()
{
    rtspURL=QString(ui->rtspURL->text());
}
QString Login::getRtspURL()
{
    return rtspURL;
}
 
void Login::on_pushButton_Cameras_clicked() //Кнопка "Камера"
{
    rtspURL=QString(ui->rtspURL->text());
    QDynamicList *List = new QDynamicList(this);
    CAMERAS *cameras = new CAMERAS;
    ui->mdiArea->addSubWindow(cameras);
    cameras->show();
    ui->verticalLayout->addWidget(List);
}
main.cpp
C++ (Qt)
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
#include "login.h"
#include <QApplication>
#include <QString>
#include <stdio.h>
#include "FFmpeg.h"
#include <qthread.h>
#include "video.h"
#include <unistd.h>
#include "cameras.h"
 
 
/**
 * @brief The RtspThread class
 * Receive Thread
 */
class RtspThread : public QThread
{
public :
    void run();
    void setRtspURL(QString url);
    void setFFmpeg(FFmpeg * ff);
private:
    QString  rtspURL;// user input url
    FFmpeg * ffmpeg;//mian thread and rtspthread use the some ffmpeg object
};
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Login login;// login Doialog
    login.show();
    CAMERAS cameras;
    FFmpeg * ffmpeg;//global data for ffmpeg event
    ffmpeg=new FFmpeg();
    cameras.setFFmpeg(ffmpeg);
    RtspThread rtspthread;
 
    if(login.exec()==QDialog::Accepted)
    {
        printf("%s\n",login.getRtspURL().toStdString().c_str());
        rtspthread.setRtspURL(login.getRtspURL());
        rtspthread.setFFmpeg(ffmpeg);
        rtspthread.start();
        cameras.show();
        return a.exec();
 
    }else
    {
       return 0;
    }
 
}
 
void  RtspThread::run()
{
    ffmpeg->initial(rtspURL);
    ffmpeg->h264Decodec();
}
 
void RtspThread::setRtspURL(QString url)
{
    rtspURL=url;
}
void RtspThread::setFFmpeg(FFmpeg * ff)
{
    ffmpeg=ff;
}
Но ничего не работает.
Прошу помощи в решении.
Qt Creator 2.8.1
Qt 5.1.1 MinGW 32bit
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.03.2018, 08:19
Ответы с готовыми решениями:

QMdiSubWindow
I have wtitten a vode from Max Schlee, but it doesn'twork. void...

Использование библиотек qt для проекта
Всем привет) Подскажите пожалуйста, кто знает. Я использую eclipse или...

Поиск и использование динамических библиотек
У меня есть несколько библиотек в которых хранятся классы фигур. Мне нужно...

Использование одних dll библиотек несколькими программами
Есть несколько qt проектов взаимосвязанных, и есть dll файлы - mingw10.dll,...

Rgb -> ffmpeg
Здравствуйте! Не знаю, здесь ли спрашивать, но формально это имеет отношение...

4
Ygg
1559 / 356 / 140
Регистрация: 10.02.2018
Сообщений: 776
13.03.2018, 12:47 2
Лучший ответ Сообщение было отмечено ZigliShow как решение

Решение

Могу только предположить.
Для каждого объекта CAMERAS должен создаваться свой FFmpeg и RtspThread. В main что-то похожее на это присутствует, только cameras ни в какое mdi не добавляется, возможно это остатки от оригинального проекта.
C++
1
2
3
4
5
6
7
8
    CAMERAS cameras;
    FFmpeg * ffmpeg=new FFmpeg();
    cameras.setFFmpeg(ffmpeg);
    RtspThread rtspthread;
    rtspthread.setRtspURL(login.getRtspURL());
    rtspthread.setFFmpeg(ffmpeg);
    rtspthread.start();
    cameras.show();
В классе Login есть два метода, добавляющие камеры on_pushButton_Cameras_clicked и addSubWin. Причём в обоих методах создаётся только CAMERAS и нет намёка на FFmpeg и RtspThread. Может, конечно, я не совсем улавливаю логику вашего приложения.
C++
1
2
3
        CAMERAS *camera = new CAMERAS;
        mdi->addSubWindow(camera);
        camera->show();
1
ZigliShow
4 / 3 / 2
Регистрация: 20.02.2018
Сообщений: 12
13.03.2018, 13:43  [ТС] 3
Да, думал уже об этом и переписал login.cpp: добавил класс RtspThread, его методы, и закомментировал их в main.cpp.
C++ (Qt)
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
#include "login.h"
#include "ui_login.h"
#include <qstring.h>
#include <stdio.h>
#include <QString>
#include "video.h"
#include "FFmpeg.h"
#include <qthread.h>
#include <QWidget>
#include "CAMERAS.h"
#include <QMdiSubWindow>
 
 
class RtspThread : public QThread
{
public :
    void run();
    void setRtspURL(QString url);
    void setFFmpeg(FFmpeg * ff);
private:
    QString  rtspURL;// user input url
    FFmpeg * ffmpeg;//mian thread and rtspthread use the some ffmpeg object
};
void  RtspThread::run()
{
    ffmpeg->initial(rtspURL);
    ffmpeg->h264Decodec();
}
 
void RtspThread::setRtspURL(QString url)
{
    rtspURL=url;
}
void RtspThread::setFFmpeg(FFmpeg * ff)
{
    ffmpeg=ff;
}
 
 
 
Login::Login(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Login)
{
    ui->setupUi(this);
}
 
Login::~Login()
{
    delete ui;
}
 
void Login::on_btn_play_clicked()
{
    rtspURL=QString(ui->rtspURL->text());
}
QString Login::getRtspURL()
{
    return rtspURL;
}
 
void Login::on_pushButton_Cameras_clicked()
{
    rtspURL=QString(ui->rtspURL->text());
    QDynamicList *List = new QDynamicList(this);
    CAMERAS *cameras = new CAMERAS (this);
    FFmpeg * ffmpeg;//global data for ffmpeg event
    ffmpeg=new FFmpeg();
    cameras->setFFmpeg(ffmpeg);
    RtspThread *rtspthread = new RtspThread();
    printf("%s\n",this->getRtspURL().toStdString().c_str());
    rtspthread->setRtspURL(this->getRtspURL());
    rtspthread->setFFmpeg(ffmpeg);
    rtspthread->start();
    ui->mdiArea->addSubWindow(cameras);
    cameras->show();
    ui->verticalLayout->addWidget(List);
}
Но все равно борода. LineEdit'ы добавляются, а SubWindow нет.
https://cdn1.savepice.ru/uploads/201...0e01b-full.png
0
Ygg
1559 / 356 / 140
Регистрация: 10.02.2018
Сообщений: 776
13.03.2018, 14:25 4
Можно точку останова поставить в RtspThread::run, пройтись по шагам и посмотреть всё ли успешно подключается и создаётся, доходит ли дело до декодирования.

Есть ещё момент с отрисовкой CAMERAS. Там используются ffmpeg->picture, ffmpeg->width, ffmpeg->height, которые не инициализируются явно в конструкторе, а только из потока и если всё удачно. Если что-то пошло не так или отрисовка раньше потока запустится, там ведь и мусор какой-нибудь может лежать.
C++
1
2
3
4
typedef struct AVPicture {
    uint8_t *data[AV_NUM_DATA_POINTERS];    ///< pointers to the image data planes
    int linesize[AV_NUM_DATA_POINTERS];     ///< number of bytes per line
} AVPicture;
1
ZigliShow
4 / 3 / 2
Регистрация: 20.02.2018
Сообщений: 12
14.03.2018, 08:28  [ТС] 5
В общем, не знаю что это, но сегодня все работает.
Хмммм.
https://cdn1.savepice.ru/uploads/201...28a16-full.png
Ygg, спасибо за отклик =)
0
14.03.2018, 08:28
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.03.2018, 08:28

Как к Qt можно подключить библиотеки ffmpeg под Ubuntu 16.04?
Друзья, всем привет! Подскажите пожалуйста как к Qt можно подключить...

Подключить стороннюю библиотеку (в данном случае ffmpeg) для работы с различными аудио файлами
Здравствуйте! В программе необходимо подключить стороннюю библиотеку (в...

Ffmpeg конфликт библиотек
В проекте возникает потребность пользоваться одновременно (или хотя бы...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru