QT开发中文网

c++使用qt如何显示不同类型的 AVSubtitle

AVSubtitle是FFmpeg中用于存储字幕信息的结构体,包括多个字段,例如字幕的开始和结束时间、字幕类型、语言、样式等。在使用Qt显示AVSubtitle时,可以根据不同的字幕类型和样式,选择不同的控件来展示。

以下是一个简单的例子,演示如何使用Qt展示AVSubtitle的文本信息:

#include <QtCore>
#include <QtGui>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsTextItem>

#include "ffmpeg.h"

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

    // 打开视频文件
    AVFormatContext *pFormatCtx = NULL;
    if (avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) != 0) {
        qDebug() << "打开视频文件失败!";
        return -1;
    }

    // 查找流信息
    if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
        qDebug() << "无法获取流信息!";
        return -1;
    }

    int videoIndex = -1, subtitleIndex = -1;
    for (int i = 0; i < pFormatCtx->nb_streams; i++) {
        AVCodecParameters *codecpar = pFormatCtx->streams[i]->codecpar;
        if (codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoIndex = i;
        } else if (codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
            subtitleIndex = i;
        }
    }

    if (videoIndex < 0 || subtitleIndex < 0) {
        qDebug() << "没有找到视频流或字幕流!";
        return -1;
    }

    // 打开视频解码器
    AVCodecParameters *codecpar = pFormatCtx->streams[videoIndex]->codecpar;
    AVCodec *pCodec = avcodec_find_decoder(codecpar->codec_id);
    if (pCodec == NULL) {
        qDebug() << "无法找到视频解码器!";
        return -1;
    }

    AVCodecContext *pCodecCtx = avcodec_alloc_context3(pCodec);
    if (avcodec_parameters_to_context(pCodecCtx, codecpar) < 0) {
        qDebug() << "无法设置编解码器参数!";
        return -1;
    }
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
        qDebug() << "无法打开视频解码器!";
        return -1;
    }

    // 打开字幕解码器
    codecpar = pFormatCtx->streams[subtitleIndex]->codecpar;
    pCodec = avcodec_find_decoder(codecpar->codec_id);
    if (pCodec == NULL) {
        qDebug() << "无法找到字幕解码器!";
        return -1;
    }

    pCodecCtx = avcodec_alloc_context3(pCodec);
    if (avcodec_parameters_to_context(pCodecCtx, codecpar) < 0) {
        qDebug() << "无法设置编解码器参数!";
        return -1;
    }
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
        qDebug() << "无法打开字幕解码器!";
        return -1;
    }

    // 创建Qt视图和场景
    QGraphicsView *view = new QGraphicsView;
    view->show();
    QGraphicsScene *scene = new QGraphicsScene;
    view->setScene(scene);

    // 循环读取帧
    AVPacket packet;
    av_init_packet(&packet);
    while (av_read_frame(pFormatCtx, &packet) >= 0) {
        if (packet.stream_index == videoIndex) {
            // 解码视频帧
            AVFrame *pFrame = av_frame_alloc();
            int ret = avcodec_send_packet(pCodecCtx, &packet);
            if (ret < 0) {
                qDebug() << "解码视频帧失败!";
                break;
            }
            while (ret >= 0) {
                ret = avcodec_receive_frame(pCodecCtx, pFrame);
                if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) {
                    break;
                } else if (ret < 0) {
                    qDebug() << "解码视频帧失败!";
                    break;
                }

                // 将解码后的视频帧转换为QImage并展示在Qt视图中
                QImage image(pFrame->data[0], pFrame->width, pFrame->height, QImage::Format_RGB888);
                QGraphicsPixmapItem *item = scene->addPixmap(QPixmap::fromImage(image));
                item->setScale(1.0 * view->width() / pFrame->width);
                item->setPos(0, 0);
                QCoreApplication::processEvents();
            }
            av_frame_free(&pFrame);
        } else if (packet.stream_index == subtitleIndex) {
            // 解码字幕包
            AVSubtitle subtitle;
            int ret = avcodec_decode_subtitle2(pCodecCtx, &subtitle, NULL, &packet);
            if (ret < 0) {
                qDebug() << "解码字幕包失败!";
                break;
            }

            // 根据字幕类型和样式,选择不同的控件来展示
            if (subtitle.format == SUBTITLE_ASS || subtitle.format == SUBTITLE_SSA) {
                // ASS/SSA格式字幕,使用QGraphicsTextItem显示
                QGraphicsTextItem *item = new QGraphicsTextItem(QString::fromUtf8(subtitle.rects[0]->ass));
                item->setPos(0, view->height() - 50);
                scene->addItem(item);
            } else {
                // 其他格式字幕,使用QLabel显示
                QLabel *label = new QLabel(view);
                label->setText(QString::fromLatin1((const char *)subtitle.rects[0]->data, subtitle.rects[0]->size));
                label->setAlignment(Qt::AlignCenter);
                label->setStyleSheet("background-color:black;color:white;");
                label->setGeometry(0, view->height() - 50, view->width(), 50);
                label->show();
            }

            avsubtitle_free(&subtitle);
        }
        av_packet_unref(&packet);
    }

    // 释放资源
    avcodec_close(pCodecCtx);
    avformat_close_input(&pFormatCtx);

    return 0;
}

在上述例子中,我们分别使用QGraphicsTextItem和QLabel两种不同的控件来展示ASS/SSA格式和其他格式的字幕。当然,还可以根据具体需求选择其他控件或自定义控件来展示字幕。

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

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

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

联系我们

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

微信号:3007537140

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

关注我们
x

注册

已经有帐号?