Разработка программного обеспечения QT - разработка видеоплеера на основе FFMPEG - программное декодирование видео ЦП (1)
https://cloud.tencent.com/developer/article/2211590
Разработка программного обеспечения QT-Проектирование видеоплеера на основе жесткого декодирования видео FFMPEG-GPU (2)
https://xiaolong.blog.csdn.net/article/details/126833434
Разработка программного обеспечения QT - разработка видеоплеера на основе FFMPEG - декодирование звука (3)
https://xiaolong.blog.csdn.net/article/details/126836582
Разработка программного обеспечения QT — проектирование видеоплеера на основе видео рендеринга FFMPEG-OpenGL (4)
https://xiaolong.blog.csdn.net/article/details/126842988
Разработка программного обеспечения QT-проектирование видеоплеера на базе FFMPEG-потокового медиаплеера (5)
https://xiaolong.blog.csdn.net/article/details/126915003
Разработка программного обеспечения QT-Дизайн видеоплеера на основе FFMPEG-Видеоплеер (6)
https://blog.csdn.net/xiaolong1126626497/article/details/126916817
Говоря о ffmpeg, каждый, кто занимается разработкой аудио и видео, должен был о нем слышать. FFmpeg предоставляет очень продвинутую библиотеку аудио/видео кодеков и поддерживает кроссплатформенность.
Сейчас в Интернете существует множество статей и руководств, посвященных ffmpeg. Сам ffmpeg в основном используется для декодирования и кодирования видео и аудио. Он не обеспечивает рендеринг изображения, вывод звука и другие функции. Чтобы создать собственный проигрыватель, вам сначала понадобятся некоторые другие знания, чтобы вызвать ffmpeg для выполнения задачи.
Чтобы просто и быстро познакомить с использованием ffmpeg, я напишу несколько статей и кейсов, чтобы шаг за шагом продемонстрировать использование ffmpeg и, наконец, завершу разработку полноценного плеера без привлечения теоретических знаний (в Интернете слишком много теоретических знаний). ), в основном основанный на коде и функциональности.
Знакомство со средой, которую я использую для разработки видеоплеера, здесь:
версия ffmpeg: 4.2.2
Qt-версия : 5.12.6
тип компилятора : MinGW32bit
Планирование контента и кейсы этих статей, написанных шаг за шагом, следующие:
(1) Используйте ffmpeg для декодирования видео и визуализации декодированного изображения через QWidget. Он поддерживает переход по индикатору выполнения, отображение индикатора выполнения, отображение общего времени и отображение основной информации о видео.
Особенности: Он использует программное декодирование (ЦП) только для декодирования данных изображения и игнорирования аудиоданных. В основном он демонстрирует базовый процесс использования ffmpeg, как завершить декодирование видео с помощью ffmpeg, преобразовать формат пикселей изображения и, наконец, завершить рендеринг изображения.
(2) Используйте интерфейс аппаратного ускорения ffmpeg для завершения декодирования видео, поддержки обнаружения методов ускорения, поддерживаемых текущим оборудованием, копирования данных из графического процессора в процессор после декодирования, завершения преобразования пикселей, а затем рендеринга изображения через QWidget с поддержкой индикатора выполнения. Индикаторы прыжков и прогресса. Отображение общего времени, отображение основной информации о видео.
Особенности: Он использует декодирование с аппаратным ускорением (GPU) только для декодирования данных изображения и игнорирования аудиоданных. В основном он демонстрирует базовый процесс использования аппаратного декодирования ffmpeg, как завершить декодирование видео с помощью ffmpeg, преобразовать формат пикселей изображения и, наконец, завершить изображение. рендеринг.
(3) Используйте ffmpeg для декодирования аудиопакетов в видео и воспроизведения аудиоданных через QAudioOutput.
Особенности: Декодирует только аудиоданные и игнорирует данные видеоизображения. В основном он демонстрирует базовый процесс использования ffmpeg, как завершить декодирование аудиоданных с помощью ffmpeg, преобразовать формат аудиоданных и, наконец, воспроизвести его через QAudioOutput.
(4)Используйте интерфейс аппаратного ускорения ffmpeg для завершения декодирования видео.,Поддерживает обнаружение методов ускорения, поддерживаемых текущим оборудованием.,проходитьQOpenGLWidget
рендерингдекодированиеданные изображения,Поддержка перехода по индикатору выполнения и отображение индикатора выполнения,отображение общего времени,Отображается основная информация о видео.
Особенности: Использование аппаратного ускоренного декодирования (GPU), рендеринг OpenGL, декодирование только данных изображения, игнорирование аудиоданных, в основном демонстрация базового процесса использования аппаратного декодирования ffmpeg и рендеринга OpenGL.
(5) Добавьте в пример поддержку воспроизведения потокового мультимедиа (4),Поддержка распространенных форматов потокового мультимедиа, таких как rtmp, rtsp, HLS (протокол HTTP).,Используйте интерфейс аппаратного ускорения ffmpeg для завершения декодирования видео.,Поддерживает обнаружение методов ускорения, поддерживаемых текущим оборудованием.,проходитьQOpenGLWidget
рендерингдекодированиеданные изображения。
Особенности: Использование аппаратного ускоренного декодирования (GPU), рендеринг OpenGL, декодирование только данных изображения, игнорирование аудиоданных, в основном демонстрация базового процесса использования аппаратного декодирования ffmpeg и рендеринга OpenGL.
(6) Объединение примеров (3) и (5),Добавить аудиопакет, декодирование воспроизведения,Используйте интерфейс аппаратного ускорения ffmpeg для завершения декодирования видео.,Поддерживает обнаружение методов ускорения, поддерживаемых текущим оборудованием.,проходитьQOpenGLWidget
рендерингдекодированиеданные изображения,проходитьQAudioOutputВоспроизведение аудиоданных。Поддержка перехода по индикатору выполнения и отображение индикатора выполнения,отображение общего времени,Отображается основная информация о видео.
Функции: Использование декодирования с аппаратным ускорением (GPU), рендеринга OpenGL, декодирования только данных изображения, игнорирования аудиоданных, в основном демонстрирует базовый процесс использования аппаратного декодирования ffmpeg и рендеринга OpenGL, а также процесс воспроизведения аудиоданных через QAudioOutput.
(7) Объедините предыдущие примеры, чтобы создать готовый видеоплеер.
Если вы хотите создать видеоплеер, вам нужно решить три основные проблемы: (1) Декодирование (2) Рендеринг (3) Синхронизация аудио и видео.
ffmpeg поддерживает чисто программное декодирование и декодирование с аппаратным ускорением. Пока чистое программное декодирование зависит от ЦП, мягкое декодирование видео с большим разрешением (4K и выше) будет потреблять много ресурсов ЦП, а скорость декодирования будет относительно низкой, а также время рендеринга, общее видеоплеер будет. Явление. Если используется декодирование с аппаратным ускорением (GPU), время декодирования значительно сокращается. Мой компьютер - процессор i7 с низким энергопотреблением. Тестирование на моем компьютере: для видео с разрешением 3840x2160 требуется около 300 мс для мягкого декодирования одного кадра. Если включено аппаратное ускоренное декодирование, один кадр занимает около 10 мс. Скорость. разница может быть очень большой. А во время мягкого декодирования загрузка процессора составляет почти 100%. Если декодировать через графический процессор, загрузка процессора будет очень низкой, что освобождает больше времени для других дел.
Разница между мягким декодированием и жестким декодированием не очень большая, потому что ffmpeg инкапсулировал все API и нужно только их вызывать. Нет необходимости разбираться во многих базовых вещах, и его очень удобно разрабатывать.
В исходном коде ffmpeg представлено множество примеров, включая примеры декодирования видео.
ffmpeg\doc\examples\decode_video.c
ffmpeg\doc\examples\hw_decode.c
Оба эти примера имеют большую справочную ценность. hw_decode.c
Это пример декодирования с аппаратным ускорением ffmpeg. На этом примере вы можете понять, как ffmpeg вызывает графический процессор для аппаратного декодирования.
Конечно, в состав ffmpeg также входит проигрыватель командной строки. Исходный код — ffplay.c. Этот код прекрасно реализован и представляет собой всего лишь проигрыватель. Однако в дополнение к API-вызовам самого ffmpeg. рендеринг Эта часть реализуется через SDL. Если вы не знакомы с ffmpeg и SDL на ранней стадии, непосредственный просмотр ffplay.c может оказаться не очень эффективным.
Лучший способ — начать с простого, понять это шаг за шагом и, наконец, просмотреть ffplay.c, так эффект будет намного лучше.
Сам по себе ffmpeg — это всего лишь библиотека декодирования и кодирования, а рендеринг декодированного изображения необходимо реализовать самостоятельно. Так называемый рендеринг предназначен для отображения данных изображения, полученных после декодирования видео ffmpeg. Рендеринг также делится на программный рендеринг и рендеринг с аппаратным ускорением. В настоящее время я здесьUIпринятQtСделал,Существует множество способов отображения изображений в Qt.,Его можно нарисовать напрямую через Qwidget, QLabel display и т. д. Этот метод является наиболее традиционным методом,Это также самый простой способ,Рисование таким способом использует процессор,Высокая загрузка ЦП,И его нужно отображать через Qwidget, QLabel и т.п.,Нужно получить данные из ffmpegдекодирование формата пикселей,переупаковано какQImage
Формат,Этот процесс требует много времени. Если вы хотите уменьшить загрузку процессора,Ускорить рендеринг,Можно использовать OpenGL рендеринг,Qtинкапсулированный вQOpenGLWidget
,Вызов OpenGL также относительно удобен.
Используйте ffmpeg для декодирования видео и визуализации декодированного изображения через QWidget. Он поддерживает переход по индикатору выполнения, отображение индикатора выполнения, отображение общего времени и отображение основной информации о видео.
Особенности: Он использует программное декодирование (ЦП) только для декодирования данных изображения и игнорирования аудиоданных. В основном он демонстрирует базовый процесс использования ffmpeg, как завершить декодирование видео с помощью ffmpeg, преобразовать формат пикселей изображения и, наконец, завершить рендеринг изображения.
Для декодирования видео используется независимый подпоток. После декодирования полученные данные изображения передаются в интерфейс пользовательского интерфейса для рендеринга посредством передачи слота сигнала.
Ниже приведен основной процесс декодирования с помощью программного обеспечения ffmpeg:
//1. Откройте мультимедийный поток и получите некоторую информацию.
avformat_open_input(&format_ctx, m_MediaFile, nullptr, nullptr)
//2. Чтение пакетов медиафайлов для получения информации о потоке
avformat_find_stream_info(format_ctx, nullptr)
//3. Найти устройство декодирования
AVCodec *video_pCodec=avcodec_find_decoder(stream->codecpar->codec_id);
//4. Откройте инструмент декодирования
avcodec_open2(stream->codec,video_pCodec,nullptr)
//5. Чтение кадра данных
av_read_frame(format_ctx, &pkt)
//6. Отправить видеокадры
avcodec_send_packet(format_ctx->streams[video_stream_index]->codec,&pkt)
//7. декодирование по видеокадрам
avcodec_receive_frame(format_ctx->streams[video_stream_index]->codec, SRC_VIDEO_pFrame)
//8. Преобразование формата пикселей
sws_scale(img_convert_ctx,
(uint8_t const **) SRC_VIDEO_pFrame->data,
SRC_VIDEO_pFrame->linesize, 0, video_height, RGB24_pFrame->data,
RGB24_pFrame->linesize);
//9. рендеринг
Здесь требуется больше времениsws_scale
,Чем выше разрешение видео,Чем дольше это занимает。Второйavcodec_receive_frame
,ирендеринг,Если мягко декодированное видео превышает 4K,декодирование занимает особенно много времени,Если разрешение ниже 4K,Время, затраченное на декодирование, приемлемое.
//Кодировка указанного файла — UTF-8
#pragma execution_character_set("utf-8")
#include "ReverseDecodThread.h"
ReverseDecodThread::ReverseDecodThread()
{
qDebug() << «Информация о версии FFMPEG:» << av_version_info();
}
ReverseDecodThread::~ReverseDecodThread()
{
}
/*
Функция: Настройка медиафайлов
*/
int ReverseDecodThread::set_VideoFile(QString media)
{
//Открываем медиафайл
QByteArray array=media.toUtf8();
strncpy(m_MediaFile, array.data(), sizeof(m_MediaFile));
}
void ReverseDecodThread::SetSate(int run)
{
m_run = run;
}
int ReverseDecodThread::GetSate()
{
return m_run;
}
//Перейти к кадру видео
void ReverseDecodThread::SetSeekPos(qint64 pos)
{
is_CurrentSeekPos = 1;
m_n64CurrentSeekPos = pos;
m_run=1; //Работающий статус
//Получаем местное время системы
play_base_time=QDateTime::currentMSecsSinceEpoch();
}
void ReverseDecodThread::PausePlay()
{
m_run = 2;
}
void ReverseDecodThread::StopPlay()
{
m_run = 0;
}
void ReverseDecodThread::LogSend(QString text)
{
qDebug() << text;
}
//Начальная точка выполнения потока
void ReverseDecodThread::run()
{
LogSend("Начать воспроизведение видео.\n");
StartPlay();
}
//Воспроизведение видео
int ReverseDecodThread::StartPlay()
{
//1. Откройте мультимедийный поток и получите некоторую информацию.
if(avformat_open_input(&format_ctx, m_MediaFile, nullptr, nullptr) != 0)
{
LogSend(tr("Невозможно открыть видеофайл: %1").arg(m_MediaFile));
return -1;
}
//2. Чтение пакетов медиафайлов для получения информации о потоке
if(avformat_find_stream_info(format_ctx, nullptr) < 0)
{
LogSend(tr("Невозможно получить информацию о потоке.\n"));
return -1;
}
//3. Распечатать информацию о видео.
LogSend(tr("Количество потоков в видео: %1\n").arg(format_ctx->nb_streams));
for(int i = 0; i < format_ctx->nb_streams; ++i)
{
const AVStream* stream = format_ctx->streams[i];
if(stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
//Найти устройство декодирования
AVCodec *video_pCodec=avcodec_find_decoder(stream->codecpar->codec_id);
//Откройте инструмент декодирования
if(avcodec_open2(stream->codec,video_pCodec,nullptr)!=0)
{
LogSend(tr("Не удалось открыть декодирование.\n"));
return -1;
}
video_stream_index = i;
//Получаем ширину и высоту видеокадра
video_width=stream->codecpar->width;
video_height=stream->codecpar->height;
LogSend(tr("Размер видеокадра (в пикселях)): (ширина х высота)%1x%2 Формат пикселей: %3\n").arg(
stream->codecpar->width).arg(stream->codecpar->height).arg(stream->codecpar->format));
}
}
if (video_stream_index == -1)
{
LogSend("Видеопоток не обнаружен.\n");
return -1;
}
AVRational frameRate = format_ctx->streams[video_stream_index]->avg_frame_rate;
/*Установить транскодер видео*/
SRC_VIDEO_pFrame = av_frame_alloc();
RGB24_pFrame = av_frame_alloc();// Буфер для хранения данных YUV после декодирования
//Конвертируем данные YUV после декодирования в RGB24
img_convert_ctx = sws_getContext(video_width, video_height,
format_ctx->streams[video_stream_index]->codec->pix_fmt,video_width, video_height,
AV_PIX_FMT_RGB24, SWS_BICUBIC, nullptr, nullptr, nullptr);
//Вычисляем размер в байтах, занимаемый изображением RGB
int numBytes=avpicture_get_size(AV_PIX_FMT_RGB24,video_width,video_height);
//Пространство приложения для хранения данных изображения RGB
out_buffer_rgb = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
// Функция avpicture_fill заполняет изображение, на которое указывает ptr, но не копирует его. Она просто указывает указатель данных в структуре изображения на данные ptr.
avpicture_fill((AVPicture *) RGB24_pFrame, out_buffer_rgb, AV_PIX_FMT_RGB24,
video_width, video_height);
qDebug()<<"format_ctx->duration:"<<format_ctx->duration;
//Получаем местное время системы
play_base_time=QDateTime::currentMSecsSinceEpoch();
//Указывает, что видео успешно загружено
while(m_run)
{
if(m_run == 2)
{
msleep(100); //пауза воспроизведения
continue;
}
if (is_CurrentSeekPos)
{
is_CurrentSeekPos = 0;
//Смещаем на указанную позицию и затем начинаем декодирование AVSEEK_FLAG_BACKWARD Найти ближайший ключевой кадр назад
av_seek_frame(format_ctx, -1, m_n64CurrentSeekPos* AV_TIME_BASE, AVSEEK_FLAG_BACKWARD);
qDebug()<<"Позиция прыжка:"<<m_n64CurrentSeekPos;
}
double video_clock;
AVPacket pkt;
//1. Чтение кадра данных
if(av_read_frame(format_ctx, &pkt) < 0)
{
m_run=2; //Устанавливаем состояние паузы
qDebug()<<"Чтение данных завершено.";
continue;
}
if(pkt.stream_index == video_stream_index)
{
//Текущее время
video_clock = av_q2d(format_ctx->streams[video_stream_index]->time_base) * pkt.pts;
qDebug()<<"pkt.pts:"<<pkt.pts<<"video_clock:"<<video_clock;
//декодированиевидео frame
//2. Отправить видеокадры
if (avcodec_send_packet(format_ctx->streams[video_stream_index]->codec,&pkt) != 0)
{
av_packet_unref(&pkt);//В случае неудачи отпустите этоpkt
continue;
}
//3. После приемкидекодирование по видеокадрам
if (avcodec_receive_frame(format_ctx->streams[video_stream_index]->codec, SRC_VIDEO_pFrame) != 0)
{
av_packet_unref(&pkt);//В случае неудачи отпустите этоpkt
continue;
}
//4. Конвертировать формат
sws_scale(img_convert_ctx,
(uint8_t const **) SRC_VIDEO_pFrame->data,
SRC_VIDEO_pFrame->linesize, 0, video_height, RGB24_pFrame->data,
RGB24_pFrame->linesize);
//5. Загрузить данные изображения
QImage image(out_buffer_rgb,video_width,video_height,QImage::Format_RGB888);
//Синхронизировать видеокадры через pts--показать видеокадры
// while (true)
// {
// qint64 t1=QDateTime::currentMSecsSinceEpoch();
// qint64 t2=t1-play_base_time;
// qDebug()<<"t1:"<<t1;
// qDebug()<<"t2:"<<t2;
// qDebug()<<"video_clock:"<<video_clock*1000;
// if(t2>=video_clock*1000)
// {
// break;
// }
// else
// {
// QThread::msleep(1);
// }
// }
//Обновление интерфейса уведомлений
VideoDataOutput(image.copy());
// сигнал времени
sig_getCurrentTime(video_clock, format_ctx->duration *1.0 / AV_TIME_BASE);
// QThread::msleep(40);
}
//Выпуск пакета
av_packet_unref(&pkt);
}
LogSend("Поток плеера декодирования видео и аудио завершился успешно.\n");
if(SRC_VIDEO_pFrame) av_frame_free(&SRC_VIDEO_pFrame);
if(RGB24_pFrame) av_frame_free(&RGB24_pFrame);
if(img_convert_ctx)sws_freeContext(img_convert_ctx);
if(out_buffer_rgb)av_free(out_buffer_rgb);
SRC_VIDEO_pFrame=nullptr;
RGB24_pFrame=nullptr;
img_convert_ctx=nullptr;
out_buffer_rgb=nullptr;
if(format_ctx)
{
avformat_close_input(&format_ctx);//Освободите место в обертке,Чтобы пространство не расходовалось быстро
avformat_free_context (format_ctx);
}
вернуть 0;
}
#ifndef VIDEO_PLAY_H
#define VIDEO_PLAY_H
#include <QThread>
#include <qdebug.h>
#include <QImage>
#include <QDateTime>
extern "C" {
#include <libavutil/opt.h>
#include <libavutil/mem.h>
#include <libavutil/fifo.h>
#include <libavutil/pixfmt.h>
#include <libavutil/log.h>
#include <libavutil/opt.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
#include <libavfilter/avfilter.h>
#include <libavfilter/buffersrc.h>
#include <libavfilter/buffersink.h>
}
//Тема декодирования видео и аудио
class ReverseDecodThread: public QThread
{
Q_OBJECT
public:
//Конструктор
ReverseDecodThread();
~ReverseDecodThread();
char m_MediaFile[1024];
int m_run; //1 означает запуск 0 означает остановку 2 означает паузу
double m_n64CurrentSeekPos = 0; //Текущая позиция поиска
bool is_CurrentSeekPos = 0; //1 нужно прыгнуть 0Нет необходимости
void SetSate(int run);
int GetSate();
void SetSeekPos(qint64 pos);
void PausePlay();
void StopPlay();
void LogSend(QString text);
//Загружаем видеофайл
int set_VideoFile(QString media);
protected:
void run();
int StartPlay();
signals:
void sig_getCurrentTime(double Sec, double total_Sec);
void VideoDataOutput(QImage); //выходной сигнал
private:
int video_width=0;
int video_height=0;
AVFormatContext *format_ctx=nullptr;
int video_stream_index = -1;
AVFrame *RGB24_pFrame = nullptr;
AVFrame *SRC_VIDEO_pFrame= nullptr;
uint8_t *out_buffer_rgb= nullptr;
struct SwsContext *img_convert_ctx=nullptr; //Используется для преобразования формата видео после декодирования
double video_clock_tmp;
qint64 play_base_time=0;
};
#endif // VIDEO_PLAY_H
#include "VideoFrameDisplay.h"
#include <QPainter>
VideoFrameDisplay::VideoFrameDisplay(QWidget *parent) :
QWidget(parent)
{
m_nRotateDegree=0;
this->setMouseTracking(true);
}
VideoFrameDisplay::~VideoFrameDisplay()
{
}
void VideoFrameDisplay::Set_Rotate(int Rotate)
{
m_nRotateDegree=Rotate;
}
void VideoFrameDisplay::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::TextAntialiasing);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.setRenderHint(QPainter::HighQualityAntialiasing);
painter.setBrush(Qt::black);
painter.drawRect(0,0,this->width(),this->height()); //Сначала рисуем черный цвет
if (mImage.size().width() <= 0) return;
//Масштабируем изображение пропорционально размеру окна
QImage img = mImage.scaled(this->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
//Поворот экрана
if(m_nRotateDegree > 0)
{
QTransform matrix;
matrix.rotate(m_nRotateDegree);
img = img.transformed(matrix, Qt::SmoothTransformation);
}
int x = this->width() - img.width();
int y = this->height() - img.height();
x /= 2;
y /= 2;
painter.drawImage(QPoint(x,y),img); //Рисуем изображение
}
void VideoFrameDisplay::slotSetOneFrame(QImage img)
{
src_mImage =mImage = img;
update(); //Обновление вызова будет выполнено функция PaintEvent
}
/*
Функция: Получить исходные данные изображения
*/
QImage VideoFrameDisplay::GetImage()
{
return src_mImage.copy();
}
/*
Функция: Событие двойного щелчка мыши
*/
void VideoFrameDisplay::mouseDoubleClickEvent(QMouseEvent *e)
{
emit s_VideoWidgetEvent(1);
}
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->horizontalSlider_time->installEventFilter(this);
//Сопутствующее устройство декодирования видео
connect(&DecodeWorkThread, SIGNAL(VideoDataOutput(QImage)), ui->widget_video, SLOT(slotSetOneFrame(QImage)));
//Текущее время
connect(&DecodeWorkThread, SIGNAL(sig_getCurrentTime(double, double)), this, SLOT(slotGetCurrentTime(double, double)));
}
Widget::~Widget()
{
delete ui;
}
void Widget::slotGetCurrentTime(double pts, double duration)
{
ui->horizontalSlider_time->setMaximum(duration);
ui->horizontalSlider_time->setMinimum(0);
ui->horizontalSlider_time->setValue(pts);
ui->label_duration->setText(QString("%1/%2").arg(pts).arg(duration));
}
void Widget::on_pushButton_play_clicked()
{
DecodeWorkThread.SetSate(0);
DecodeWorkThread.quit();
DecodeWorkThread.wait();
DecodeWorkThread.SetSate(1);
QString filename = QFileDialog::getOpenFileName(this, «Выберите файл для открытия», "C:/", tr("*.*"));
DecodeWorkThread.set_VideoFile(filename);
DecodeWorkThread.start();
}
void Widget::on_pushButton_pause_clicked()
{
if (DecodeWorkThread.GetSate() == 2)
{
DecodeWorkThread.SetSate(1);
}
else if(DecodeWorkThread.GetSate() == 1)
{
DecodeWorkThread.SetSate(2);
}
}
void Widget::on_pushButton_stop_clicked()
{
DecodeWorkThread.SetSate(0);
}
bool Widget::eventFilter(QObject *obj, QEvent *event)
{
//Решаем проблему, связанную с тем, что QSlider не может щелкнуть мышью в позиции, указанной мышью
if(obj==ui->horizontalSlider_time)
{
if (event->type()==QEvent::MouseButtonPress) //Оцениваем тип
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
if (mouseEvent->button() == Qt::LeftButton) //Оцениваем левую кнопку
{
int value = QStyle::sliderValueFromPosition(ui->horizontalSlider_time->minimum(), ui->horizontalSlider_time->maximum(), mouseEvent->pos().x(), ui->horizontalSlider_time->width());
ui->horizontalSlider_time->setValue(value);
qDebug()<<"value:"<<value;
//Переходим в указанное место
DecodeWorkThread.SetSeekPos(ui->horizontalSlider_time->value());
}
}
}
return QObject::eventFilter(obj,event);
}
win32
{
message('Запустить версию Win32')
INCLUDEPATH+=C:/FFMPEG/ffmpeg_x86_4.2.2/include
LIBS+=C:/FFMPEG/ffmpeg_x86_4.2.2/bin/av*
LIBS+=C:/FFMPEG/ffmpeg_x86_4.2.2/bin/sw*
LIBS+=C:/FFMPEG/ffmpeg_x86_4.2.2/bin/pos*
}