Qt+FFmpeg+OpenGL实现视频播放器(3)

1、加入多线程

用主线程同时处理音视频编解码会导致视频出现卡顿,音频出现电音的情况。为避免这种情况,在项目中添加多线程,并将音频和视频解码分开能有效解决该问题。新建AudioInfo类来实现音频
解码和播放的逻辑,并将其放入一个独立的线程中。

为了配合多线程播放音视频的功能,你需要对VideoInfo类进行以下调整:

  1. 确保VideoInfo类可以独立处理视频解码和渲染。

  2. 将视频解码和渲染放入独立的线程中运行,以避免与音频解码的线程发生冲突。

需要让VideoInfo类继承自QThread,以便它可以在单独的线程中运行。除此之外,代码结构保持不变,只是解码和渲染的逻辑将放入run()方法中。

代码如下:

AudioInfo.h

#ifndef AUDIOINFO_H
#define AUDIOINFO_H

#include <QObject>
#include <QAudioSink>
#include <QBuffer>
#include<QThread>

extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswresample/swresample.h>
#include <libavutil/opt.h>
#include <libavutil/channel_layout.h>
#include <libavutil/samplefmt.h>
}

class AudioInfo : public QObject
{
    Q_OBJECT
public:
    explicit AudioInfo(QObject *parent = nullptr);
    ~AudioInfo();

    bool openFile(const QString &filePath);
    bool initializeAudio();
    void startPlayback();
    void stopPlayback();

private:
    AVFormatContext *formatContext;
    AVCodecContext *codecContext;
    AVFrame *frame;
    AVPacket *packet;
    SwrContext *swrContext;
    int audioStreamIndex;

    QAudioSink *audioSink;
    QBuffer audioBuffer;

    void decodeAndPlayAudio();

signals:
    void playbackFinished();
};

#endif // AUDIOINFO_H

AudioInfo.cpp

#include "audioinfo.h"
#include <QDebug>
#include <QMediaDevices>
#include <QAudioSink>
#include <QBuffer>
#include <QThread>

AudioInfo::AudioInfo(QObject *parent)
    : QObject(parent), formatContext(nullptr), codecContext(nullptr),
    frame(nullptr), packet(nullptr), swrContext(nullptr),
    audioStreamIndex(-1), audioSink(nullptr)
{
    avformat_network_init();
}

AudioInfo::~AudioInfo()
{
    if (frame) av_frame_free(&frame);
    if (packet) av_packet_free(&packet);
    if (codecContext) avcodec_free_context(&codecContext);
    if (formatContext) avformat_close_input(&formatContext);
    if (swrContext) swr_free(&swrContext);
    if (audioSink) delete audioSink;
}

bool AudioInfo::openFile(const QString &filePath)
{
    if (avformat_open_input(&formatContext, filePath.toStdString().c_str(), nullptr, nullptr) != 0) {
        qWarning() << "Could not open file:" << filePath;
        return false;
    }

    if (avformat_find_stream_info(formatContext, nullptr) < 0) {
        qWarning() << "Could not find stream information";
        return false;
    }

    av_dump_format(formatContext, 0, filePath.toStdString().c_str(), 0);

    audioStreamIndex = -1;
    for (unsigned int i = 0; i < formatContext->nb_streams; i++) {
        if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            audioStreamIndex = i;
            break;
        }
    }

    if (audioStreamIndex == -1) {
        qWarning() << "Could not find audio stream";
        return false;
    }

    AVCodecParameters *codecParameters = formatContext->streams[audioStreamIndex]->codecpar;
    const AVCodec *codec = avcodec_find_decoder(codecParameters->codec_id);
    if (!codec) {
        qWarning() << "Unsupported codec!";
        return false;
    }

    codecContext = avcodec_alloc_context3(codec);
    if (!codecContext) {
        qWarning() << "Could not 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值