QT开发中文网

用c++ ffmpeg qt实现一个实现一个视频播放器

这是一个比较复杂的实现,需要涉及到多个技术领域。以下是一些基本的步骤:

  1. 安装FFmpeg库,并确保其可以在您的系统上正常工作。

  2. 使用Qt创建一个GUI界面,包含播放按钮、停止按钮、进度条等组件。

  3. 创建一个视频播放类,该类将使用FFmpeg读取视频并将其显示在屏幕上。

  4. 将播放类与Qt界面连接,并使用Qt信号和槽机制控制播放。

  5. 实现快进、快退、截图等功能。

下面是一个简单的代码示例,仅供参考:

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLabel>
#include <QTimer>
#include <QFileDialog>
#include <QDebug>

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}

class VideoPlayer : public QLabel
{
    Q_OBJECT

public:
    VideoPlayer(QWidget *parent = nullptr)
        : QLabel(parent), m_formatCtx(nullptr), m_codecCtx(nullptr), m_frame(nullptr), m_rgbFrame(nullptr),
          m_scaleCtx(nullptr), m_timer(nullptr), m_isPlaying(false), m_frameIndex(0) {
    }

    ~VideoPlayer() {
        if (m_formatCtx != nullptr) {
            avformat_close_input(&m_formatCtx);
        }
        if (m_codecCtx != nullptr) {
            avcodec_free_context(&m_codecCtx);
        }
        if (m_frame != nullptr) {
            av_frame_free(&m_frame);
        }
        if (m_rgbFrame != nullptr) {
            av_frame_free(&m_rgbFrame);
        }
        if (m_scaleCtx != nullptr) {
            sws_freeContext(m_scaleCtx);
        }
    }

public slots:
    void openFile() {
        QString fileName = QFileDialog::getOpenFileName(this, tr("Open Video"), "", tr("Video Files (*.avi *.mp4 *.mkv)"));
        if (!fileName.isEmpty()) {
            m_fileName = fileName;
            startPlayback();
        }
    }

    void play() {
        if (m_isPlaying) {
            return;
        }
        m_isPlaying = true;
        m_timer->start(1000 / m_fps);
    }

    void stop() {
        if (!m_isPlaying) {
            return;
        }
        m_isPlaying = false;
        m_timer->stop();
    }

    void setProgress(int value) {
        m_frameIndex = value * m_fps / 1000 - 1;
        m_frameIndex = qBound(0, m_frameIndex, m_numFrames - 1);
        showFrame();
    }

protected:
    void showEvent(QShowEvent *event) {
        QLabel::showEvent(event);
        if (m_formatCtx == nullptr) {
            startPlayback();
        }
    }

private slots:
    void nextFrame() {
        m_frameIndex++;
        if (m_frameIndex >= m_numFrames) {
            m_frameIndex = 0;
        }
        showFrame();
    }

private:
    void startPlayback() {
        if (m_formatCtx != nullptr) {
            avformat_close_input(&m_formatCtx);
            m_formatCtx = nullptr;
        }
        if (m_codecCtx != nullptr) {
            avcodec_free_context(&m_codecCtx);
            m_codecCtx = nullptr;
        }

        avformat_open_input(&m_formatCtx, m_fileName.toUtf8().data(), nullptr, nullptr);
        avformat_find_stream_info(m_formatCtx, nullptr);

        int videoStreamIndex = -1;

        for (int i = 0; i < m_formatCtx->nb_streams; i++) {
            AVStream *stream = m_formatCtx->streams[i];
            AVCodecParameters *codecParams = stream->codecpar;
            if (codecParams->codec_type == AVMEDIA_TYPE_VIDEO) {
                videoStreamIndex = i;
                break;
            }
        }

        if (videoStreamIndex == -1) {
            qDebug() << "No video stream found!";
            return;
        }

        AVStream *videoStream = m_formatCtx->streams[videoStreamIndex];
        m_codecCtx = avcodec_alloc_context3(nullptr);
        avcodec_parameters_to_context(m_codecCtx, videoStream->codecpar);
        AVCodec *codec = avcodec_find_decoder(m_codecCtx->codec_id);
        avcodec_open2(m_codecCtx, codec, nullptr);

        m_fps = av_q2d(videoStream->r_frame_rate);
        m_numFrames = videoStream->nb_frames;

        m_frame = av_frame_alloc();
        m_rgbFrame = av_frame_alloc();

        int width = m_codecCtx->width;
        int height = m_codecCtx->height;

        m_scaleCtx = sws_getContext(width, height, m_codecCtx->pix_fmt,
                                    width, height, AV_PIX_FMT_RGB24,
                                    SWS_BILINEAR, nullptr, nullptr, nullptr);
        int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, width, height, 1);
        uint8_t *buffer = new uint8_t[numBytes];
        av_image_fill_arrays(m_rgbFrame->data, m_rgbFrame->linesize, buffer,
                              AV_PIX_FMT_RGB24, width, height, 1);

        m_timer = new QTimer(this);
        connect(m_timer, &QTimer::timeout, this, &VideoPlayer::nextFrame);

        showFrame();
    }

    void showFrame() {
        if (m_formatCtx == nullptr || m_codecCtx == nullptr) {
            return;
        }
        av_seek_frame(m_formatCtx, -1, m_frameIndex, AVSEEK_FLAG_FRAME);
        avcodec_flush_buffers(m_codecCtx);
        int frameFinished = 0;
        while (!frameFinished) {
            AVPacket packet;
            av_read_frame(m_formatCtx, &packet);
            if (packet.stream_index == m_codecCtx->pkt_in_frames
                    && avcodec_send_packet(m_codecCtx, &packet) == 0) {
                while (avcodec_receive_frame(m_codecCtx, m_frame) == 0) {
                    sws_scale(m_scaleCtx, m_frame->data, m_frame->linesize, 0,
                              m_codecCtx->height, m_rgbFrame->data, m_rgbFrame->linesize);
                    QImage image(m_rgbFrame->data[0], m_codecCtx->width, m_codecCtx->height,
                                 m_rgbFrame->linesize[0], QImage::Format_RGB888);
                    setPixmap(QPixmap::fromImage(image));
                    frameFinished = 1;
                    break;
                }
            }
            av_packet_unref(&packet);
        }
    }

private:
    AVFormatContext *m_formatCtx;
    AVCodecContext *m_codecCtx;
    AVFrame *m_frame;
    AVFrame *m_rgbFrame;
    SwsContext *m_scaleCtx;
    QTimer *m_timer;
    QString m_fileName;
    bool m_isPlaying;
    int m_fps;
    int m_numFrames;
    int m_frameIndex;
};

int main(int argc, char *argv[])
{
    av_register_all();
    avcodec_register_all();

    QApplication app(argc, argv);

    QWidget window;
    VideoPlayer player(&window);
    QPushButton *openButton = new QPushButton("Open");
    QPushButton *playButton = new QPushButton("Play");
    QPushButton *stopButton = new QPushButton("Stop");
    QSlider *progressSlider = new QSlider(Qt::Horizontal);
    QVBoxLayout *layout = new QVBoxLayout(&window);
    layout->addWidget(&player);
    layout->addWidget(openButton);
    layout->addWidget(playButton);
    layout->addWidget(stopButton);
    layout->addWidget(progressSlider);
    window.setLayout(layout);

    QObject::connect(openButton, &QPushButton::clicked, &player, &VideoPlayer::openFile);
    QObject::connect(playButton, &QPushButton::clicked, &player, &VideoPlayer::play);
    QObject::connect(stopButton, &QPushButton::clicked, &player, &VideoPlayer::stop);
    QObject::connect(progressSlider, &QSlider::valueChanged, &player, &VideoPlayer::setProgress);

    window.show();

    return app.exec();
}

#include "main.moc"

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://qt.0voice.com/?id=33

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?