Qt/C++ Audio- und Videoentwicklung 61-Multi-Screen-Rendering/Ein-Dekodierungs-Rendering in mehrere Fenster/Echtzeit-Bildsynchronisation

I. Einleitung

Multi-Screen-Rendering bedeutet, dass ein Decodierungsthread mehreren Rendering-Schnittstellen entspricht. Durch Addrender werden mehrere Zeichnungsformen hinzugefügt. Auf Ausstellungen oder an Orten, an denen Fernseher verkauft werden, können wir oft das gleiche Bild sehen, das von vielen Fernsehern abgespielt wird. Das Prinzip sollte ähnlich sein. , Ein Ort ist für das Öffnen, Dekodieren und Abspielen verantwortlich und überträgt das Bild synchron an mehrere Anzeigeorte, um die Konsistenz des Bildes vollständig sicherzustellen. Dies entspricht einer Wiederverwendung der Dekodierung, wodurch die Ressourcenbelegung erheblich reduziert und die Dekodierungsressourcen wiederverwendet werden.

Wenn es vom ffmpeg-Kernel oder einem anderen Kernel in ein Bildsignal konvertiert wird, können Sie das Signal direkt der entsprechenden Form zuordnen. Wenn es sich um den MDK-Kernel oder den Qtav-Kernel handelt, stellen sie die Addrender-Methode bereit, die von qopenglwidget geerbt wird Oder Fügen Sie einfach das qglwidget-Formular zur Warteschlange hinzu, die gerendert werden muss. Sie können so viele hinzufügen, wie Sie möchten. Das Zeichnen von Videodaten über OpenGL ist immer noch sehr gut. Jedes Mal, wenn ein Formular hinzugefügt wird, erhöht es nur einen Teil der GPU-Auslastung und kaum erhöht die CPU-Auslastung. Dies ist der gewünschte Effekt.

2. Effektzeichnung

Fügen Sie hier eine Bildbeschreibung ein

3. Adresse erleben

  1. Inländische Website: https://gitee.com/feiyangqingyun
  2. Internationale Website: https://github.com/feiyangqingyun
  3. Persönliche Arbeit: https://blog.csdn.net/feiyangqingyun/article/details/97565652
  4. Erfahrungsadresse: https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g Extraktionscode: 01jf Dateiname: bin_video_demo.
  5. Video-Homepage: https://space.bilibili.com/687803542

4. Funktionsmerkmale

4.1. Grundfunktionen

  1. Unterstützt verschiedene Audio- und Videodateiformate wie MP3, WAV, MP4, ASF, RM, RMVB, MKV usw.
  2. Unterstützt lokale Kamerageräte und lokale Desktop-Sammlung sowie mehrere Geräte und mehrere Bildschirme.
  3. Unterstützt verschiedene Video-Streaming-Formate wie RTP, RTSP, RTMP, http, UDP usw.
  4. Lokale Audio- und Videodateien sowie Netzwerk-Audio- und Videodateien können Dateilänge, Wiedergabefortschritt, Lautstärke, Stummschaltungsstatus usw. automatisch erkennen.
  5. Dateien können die Wiedergabeposition angeben, die Lautstärke anpassen, den Stummschaltungsstatus festlegen usw.
  6. Unterstützt die Wiedergabe von Dateien mit doppelter Geschwindigkeit, mit optionalen Geschwindigkeiten von 0,5x, 1,0x, 2,5x, 5,0x usw., was einer langsamen Wiedergabe und einer schnellen Wiedergabe entspricht.
  7. Unterstützt das Starten, Stoppen, Anhalten und Fortsetzen der Wiedergabe.
  8. Unterstützt die Aufnahme von Screenshots, Sie können den Dateipfad angeben und auswählen, ob nach Abschluss der Aufnahme automatisch eine Vorschau angezeigt werden soll.
  9. Unterstützen Sie die Videospeicherung, starten Sie die Aufnahme manuell, stoppen Sie die Aufnahme. Einige Kernel unterstützen die Fortsetzung der Aufnahme nach dem Anhalten der Aufnahme und überspringen die Teile, die für die Aufnahme nicht benötigt werden.
  10. Unterstützt Mechanismen wie sinnlose Umschaltschleifenwiedergabe und automatische Wiederverbindung.
  11. Bietet Signale wie erfolgreiche Wiedergabe, Abschluss der Wiedergabe, empfangenes dekodiertes Bild, empfangenes aufgenommenes Bild, Änderung der Videogröße, Änderung des Aufnahmestatus usw.
  12. Multithread-Verarbeitung, ein Decodierungsthread, kein Hängenbleiben an der Hauptschnittstelle.

4.2. Funktionen

  1. Unterstützt mehrere Dekodierungskerne gleichzeitig, einschließlich qmedia-Kernel (Qt4/Qt5/Qt6), ffmpeg-Kernel (ffmpeg2/ffmpeg3/ffmpeg4/ffmpeg5/ffmpeg6), vlc-Kernel (vlc2/vlc3), mpv-Kernel (mpv1/mp2), und MDK-Kernel, Hikvision SDK, Easyplayer-Kernel usw.
  2. Bei einem sehr vollständigen Design mit mehreren Basisklassen erfordert das Hinzufügen eines neuen Decodierungskernels nur eine sehr kleine Menge Code, um den gesamten Mechanismus anzuwenden, was eine einfache Erweiterung ermöglicht.
  3. Unterstützt mehrere Bildschirmanzeigestrategien gleichzeitig, automatische Anpassung (die ursprüngliche Auflösung ist kleiner als die Größe des Anzeigesteuerelements, sie wird entsprechend der ursprünglichen Auflösung angezeigt, andernfalls wird sie proportional skaliert), proportionale Skalierung (immer proportionale Skalierung). ), Stretchfüllung (immer gedehnt und gefüllt) ). Drei Bildanzeigestrategien werden in allen Kernen und in allen Videoanzeigemodi unterstützt.
  4. Unterstützt mehrere Videoanzeigemodi gleichzeitig, Handle-Modus (das eingehende Steuerhandle wird zur Zeichensteuerung an die andere Partei übergeben), Zeichenmodus (der Rückruf ruft die Daten ab und konvertiert sie dann zum Zeichnen mit QPainter in QImage), GPU Modus (der Rückruf ruft die Daten ab und konvertiert sie dann in yuv) QOpenglWidget-Zeichnung).
  5. Unterstützt mehrere Hardwarebeschleunigungstypen: ffmpeg kann zwischen dxva2, d3d11va usw. wählen, vlc kann beliebig wählen, dxva2, d3d11va, mpv kann automatisch wählen, dxva2, d3d11va, mdk kann dxva2, d3d11va, cuda, mft usw. wählen. In verschiedenen Systemumgebungen stehen unterschiedliche Typen zur Auswahl. Beispielsweise verfügen Linux-Systeme über Vaapi und VDPau und MacOS-Systeme über Videotoolbox.
  6. Der Dekodierungsthread und die Anzeigeform sind getrennt, und jeder Dekodierungskern kann so angegeben werden, dass er in jede Anzeigeform eingebunden und dynamisch umgeschaltet wird.
  7. Unterstützt den gemeinsamen Dekodierungsthread, der standardmäßig aktiviert ist und automatisch verarbeitet wird. Wenn dieselbe Videoadresse erkannt wird, wird ein Dekodierungsthread gemeinsam genutzt, was den Netzwerkverkehr und den Streaming-Druck auf dem anderen Gerät in einer Netzwerkvideoumgebung erheblich reduzieren kann. Die führenden inländischen Videohersteller verfolgen alle diese Strategie. Auf diese Weise kann, solange ein Videostream abgerufen wird, dieser auf Dutzenden oder Hunderten von Kanälen zur Anzeige freigegeben werden.
  8. Identifizieren Sie den Videodrehwinkel automatisch und zeichnen Sie ihn. Beispielsweise werden auf Mobiltelefonen aufgenommene Videos im Allgemeinen um 90 Grad gedreht. Sie müssen während der Wiedergabe automatisch gedreht werden, da sie sonst standardmäßig auf dem Kopf stehen.
  9. Erkennen Sie automatisch Auflösungsänderungen während der Videostream-Wiedergabe und passen Sie die Größe automatisch in den Videosteuerelementen an. So kann die Kamera beispielsweise die Auflösung während der Nutzung dynamisch konfigurieren und auch die entsprechenden Videosteuerungen müssen synchron reagieren, wenn die Auflösung geändert wird.
  10. Audio- und Videodateien werden automatisch umgeschaltet und in einer Schleife abgespielt, ohne dass dies wahrnehmbar ist, und beim Umschalten treten keine sichtbaren Umschaltspuren wie ein schwarzer Bildschirm auf.
  11. Die Videosteuerung unterstützt außerdem jeden Dekodierungskern, jede Bildanzeigestrategie und jeden Videoanzeigemodus.
  12. Die schwebende Leiste der Videosteuerung unterstützt drei Modi: Griff, Zeichnen und GPU gleichzeitig, und nicht absolute Koordinaten können verschoben werden.
  13. Das lokale Kameragerät unterstützt die Angabe des Gerätenamens, der Auflösung und der Bildrate für die Wiedergabe.
  14. Die lokale Desktop-Sammlung unterstützt das Festlegen des Sammelbereichs, des Offset-Werts, des angegebenen Desktop-Index, der Bildrate, der gleichzeitigen Sammlung mehrerer Desktops usw. Es unterstützt auch die Angabe des Fenstertitels zum Sammeln fester Fenster.
  15. Aufnahmedateien unterstützen auch offene Videodateien, lokale Kameras, lokale Desktops, Netzwerkvideostreams usw.
  16. Sofortige Reaktion auf das Öffnen und Schließen, sei es das Öffnen eines nicht vorhandenen Video- oder Netzwerkstreams, das Erkennen der Anwesenheit eines Geräts, das Warten auf eine Zeitüberschreitung beim Lesen und das sofortige Unterbrechen des vorherigen Vorgangs und das Reagieren nach Erhalt eines Befehls zum Herunterfahren.
  17. Unterstützt das Öffnen verschiedener Bilddateien und die Drag-and-Drop-Wiedergabe lokaler Audio- und Videodateien.
  18. Die Video-Streaming-Kommunikationsmethode kann TCP/UDP sein. Einige Geräte bieten möglicherweise nur eine bestimmte Protokollkommunikation wie TCP. Sie müssen die Protokollmethode zum Öffnen angeben.
  19. Sie können das Verbindungs-Timeout (Timeout für die Videostream-Erkennung) und das Lese-Timeout (Timeout während der Erfassung) festlegen.
  20. Unterstützt die Bild-für-Bild-Wiedergabe, bietet eine Funktionsschnittstelle für das vorherige/nächste Bild und kann die gesammelten Bilder Bild für Bild anzeigen.
  21. Audiodateien extrahieren automatisch Albuminformationen wie Titel, Interpret, Album und Albumcover und zeigen automatisch das Albumcover an.
  22. Die Videoantwort hat eine extrem niedrige Latenz von etwa 0,2 Sekunden und die extrem schnelle Reaktion auf das Öffnen des Videostreams beträgt etwa 0,5 Sekunden, was speziell optimiert wurde.
  23. Unterstützt die H264/H265-Kodierung (immer mehr Überwachungskameras verwenden mittlerweile das H265-Videostream-Format) zur Generierung von Videodateien und erkennt das Kodierungsformat automatisch und schaltet es intern um.
  24. Unterstützt die Wiedergabe von Videostreams, die Sonderzeichen in Benutzerinformationen enthalten (z. B. Zeichen wie +#@ in Benutzerinformationen), mit integrierter Analyse und Escape-Verarbeitung.
  25. Unterstützt Filter, verschiedene Wasserzeichen und Grafikeffekte, unterstützt mehrere Wasserzeichen und Bilder und kann OSD-Tag-Informationen und verschiedene Grafikinformationen in MP4-Dateien schreiben.
  26. Unterstützt verschiedene Audioformate in Videostreams, einschließlich AAC, PCM, G.726, G.711A, G.711Mu, G.711ulaw, G.711alaw, MP2L2 usw. Für die beste plattformübergreifende Kompatibilität wird die Wahl von AAC empfohlen .
  27. Der Kernel ffmpeg verwendet reine qt+ffmpeg-Dekodierung und ist nicht auf die Zeichnung und Wiedergabe von Drittanbietern wie SDL angewiesen. Die GPU-Zeichnung verwendet qopenglwidget und die Audiowiedergabe verwendet qaudiooutput.
  28. Kernel ffmpeg und Kernel MDK unterstützen Android, wobei MDK die harte Dekodierung von Android unterstützt, und die Leistung ist sehr brutal.
  29. Sie können Audio- und Videospuren, also Programmkanäle, wechseln. Möglicherweise enthält die TS-Datei mehrere Audio- und Videoprogrammströme. Sie können festlegen, welcher jeweils abgespielt werden soll. Sie können dies vor der Wiedergabe und dynamisch während der Wiedergabe festlegen.
  30. Der Videodrehwinkel kann vor der Wiedergabe eingestellt und während der Wiedergabe dynamisch geändert werden.
  31. Die schwebende Videosteuerungsleiste verfügt über Funktionen wie das Starten und Stoppen der Aufnahme, das Stummschalten des Tons, das Aufnehmen von Screenshots und das Schließen des Videos.
  32. Die Audiokomponente unterstützt die Datenanalyse von Schallwellenformwerten. Basierend auf diesem Wert können Wellenformkurven und säulenförmige Klangbalken gezeichnet werden. Standardmäßig werden Schallamplitudensignale bereitgestellt.
  33. Beschriftungen und Grafikinformationen unterstützen drei Zeichenmethoden: Zeichnen auf Maskenebene, Zeichnen auf Bild und Quellzeichnung (entsprechende Informationen können in einer Datei gespeichert werden).
  34. Durch die Eingabe einer URL-Adresse kann die Adresse ohne weitere Einstellungen Kommunikationsprotokoll, Auflösung, Bildrate und andere Informationen bereitstellen.
  35. Für das Speichern von Videos in Dateien werden drei Strategien unterstützt: automatische Verarbeitung, nur Datei und gesamte Transkodierung. Die Transkodierungsstrategie unterstützt die automatische Identifizierung, die Konvertierung in 264 und die Konvertierung in 265. Das Speichern der Kodierung unterstützt die angegebene Auflösungsskalierung oder die gleiche Skalierung. Wenn Sie beispielsweise Anforderungen an die Größe der gespeicherten Datei haben, können Sie vor dem Speichern eine Skalierung festlegen.
  36. Unterstützt verschlüsselte Speicherdateien und entschlüsselte Wiedergabedateien, und Sie können den geheimen Schlüsseltext angeben.
  37. Die bereitgestellte Überwachungslayoutklasse unterstützt die gleichzeitige Anzeige von 64 Kanälen und unterstützt auch verschiedene spezielle Layouts, wie z. B. 13-Kanal-, 6-Zeilen- und 2-Spalten-Layouts auf Mobiltelefonen. Verschiedene Layouts können frei definiert werden.
  38. Es unterstützt die elektronische Vergrößerung. Wechseln Sie in der schwebenden Leiste in den elektronischen Vergrößerungsmodus, wählen Sie den Bereich auf dem Bildschirm aus, der vergrößert werden muss, und nach der Auswahl wird er automatisch vergrößert. Er kann durch erneutes Umschalten des Vergrößerungsmodus zurückgesetzt werden.
  39. Äußerst detaillierte Druckinformationsaufforderungen in jeder Komponente, insbesondere Fehlermeldungsaufforderungen, und ein einheitliches Druckformat für Verpackungen. Es ist äußerst praktisch und nützlich, die komplexe Geräteumgebung vor Ort zu testen, was gleichbedeutend mit der Lokalisierung des spezifischen Kanals und Schritts ist, der fehlgeschlagen ist.
  40. Gleichzeitig werden einfache Beispiele, Videoplayer, Multi-Screen-Videoüberwachung, Überwachungswiedergabe, Einzelbildwiedergabe, Multi-Screen-Rendering und andere separate Formularbeispiele bereitgestellt, um die Verwendung der entsprechenden Funktionen konkret zu demonstrieren.
  41. Bei der Überwachung der Wiedergabe können verschiedene Herstellertypen, Wiedergabezeiträume, Benutzerinformationen und bestimmte Kanäle ausgewählt werden. Unterstützt das Umschalten des Wiedergabefortschritts.
  42. Sie können im Dropdown-Feld „Soundkartengerät“ eine Soundkarte für die Tonwiedergabe auswählen und eine entsprechende Funktionsschnittstelle zum Wechseln der Soundkarten bereitstellen.
  43. Es unterstützt die Kompilierung in eine mobile App und bietet eine spezielle Layout-Schnittstelle für mobile Apps, die zur Videoüberwachung auf Mobiltelefonen verwendet werden kann.
  44. Das Code-Framework und die Struktur sind optimal optimiert, mit leistungsstarker Leistung, detaillierten Anmerkungen und kontinuierlichen iterativen Aktualisierungen und Upgrades.
  45. Der Quellcode unterstützt Windows, Linux, Mac, Android usw. und unterstützt verschiedene inländische Linux-Systeme, einschließlich, aber nicht beschränkt auf Tongxin UOS/Winning Kirin/Galaxy Kirin usw. Auch eingebettetes Linux wird unterstützt.
  46. Der Quellcode unterstützt Qt4, Qt5 und Qt6 und ist mit allen Versionen kompatibel.

4.3. Videosteuerung

  1. Es können beliebig viele OSD-Etiketteninformationen dynamisch hinzugefügt werden. Zu den Etiketteninformationen gehören Name, sichtbar oder nicht, Schriftgröße, Texttext, Textfarbe, Hintergrundfarbe, Etikettenbild, Etikettenkoordinaten, Etikettenformat (Text, Datum, Uhrzeit, Datum und Uhrzeit). , Bild), Beschriftungsposition (obere linke Ecke, untere linke Ecke, obere rechte Ecke, untere rechte Ecke, Mitte, benutzerdefinierte Koordinaten).
  2. Es können beliebig viele grafische Informationen dynamisch hinzugefügt werden, was sehr nützlich ist. Beispielsweise können die vom Algorithmus der künstlichen Intelligenz analysierten grafischen Bereichsinformationen direkt an die Videosteuerung gesendet werden. Grafikinformationen unterstützen beliebige Formen und werden mit absoluten Koordinaten direkt auf dem Originalbild gezeichnet.
  3. Zu den grafischen Informationen gehören Name, Rahmengröße, Rahmenfarbe, Hintergrundfarbe, rechteckiger Bereich, Pfadsatz, Punktkoordinatensatz usw.
  4. Jede Grafikinformation kann einen oder mehrere der drei Bereiche angeben, und die angegebenen Bereiche werden gezeichnet.
  5. Integrierte schwebende Balkensteuerung, die schwebende Balkenposition unterstützt oben, unten, links und rechts.
  6. Zu den Parametern des schwebenden Balkensteuerelements gehören Ränder, Abstand, Hintergrundtransparenz, Hintergrundfarbe, Textfarbe, gedrückte Farbe, Position, Tastensymbolcodesatz, Tastennamenidentifikationssatz und Tastenaufforderungsinformationssatz.
  7. Die Reihe der Werkzeugschaltflächen im schwebenden Balkensteuerelement kann angepasst werden. Über die Strukturparametereinstellungen kann das Symbol grafische Schriftarten oder benutzerdefinierte Bilder auswählen.
  8. Die schwebende Leistenschaltfläche implementiert intern Funktionen wie Videoumschaltung, Aufnahme von Screenshots, Stummschaltung und Schließen von Videos. Sie können dem Quellcode auch eigene entsprechende Funktionen hinzufügen.
  9. Die Schaltfläche mit der schwebenden Leiste entspricht der Schaltfläche, die die Funktion implementiert hat, und verfügt über eine entsprechende Verarbeitung zum Umschalten von Symbolen. Beispielsweise wird nach dem Drücken der Videotaste auf das Symbol für die Aufnahme umgeschaltet, und nachdem die Tontaste umgeschaltet wurde, wird dies der Fall sein wird zum Stummschaltsymbol und wird durch erneutes Umschalten wiederhergestellt.
  10. Wenn auf die Schaltfläche mit der schwebenden Leiste geklickt wird, wird sie mit einem eindeutigen Namen als Signal gesendet und kann selbst mit der Antwortverarbeitung verknüpft werden.
  11. Im leeren Bereich der schwebenden Leiste können Eingabeaufforderungsinformationen angezeigt werden. Standardmäßig wird die aktuelle Videoauflösung angezeigt. Informationen wie Bildrate und Bitstream-Größe können hinzugefügt werden.
  12. Zu den Videosteuerungsparametern gehören Rahmengröße, Rahmenfarbe, Fokusfarbe, Hintergrundfarbe (Standard transparent), Textfarbe (Standardfarbe für globalen Text), Füllfarbe (der leere Raum außerhalb des Videos wird mit Schwarz gefüllt), Hintergrundtext und Hintergrundbild ( wenn eingestellt, werden zuerst Bilder aufgenommen), ob Bilder kopiert werden sollen, Zoom-Anzeigemodus (automatische Anpassung, proportionale Skalierung, Streckfüllung), Video-Anzeigemodus (Griff, Zeichnung, GPU), schwebende Leiste aktivieren, schwebende Leistengröße (horizontal ist Höhe, Vertikal ist die Breite und die Position der schwebenden Leiste (oben, unten, links, rechts).

5. Verwandte Codes

#include "frmplayplus.h"
#include "frmmain.h"
#include "ui_frmplayplus.h"
#include "qthelper.h"
#include "videoutil.h"
#include "videohelper.h"
#include "videobox.h"
#include "videowidgetx.h"

#ifdef mdkx
#include "mdkplayer.h"
#include "mdkwidget.h"
#include "mdkhelper.h"
#endif

#ifdef qtavx
#include "AVPlayer.h"
#include "VideoOutput.h"
#include "qtavhelper.h"
using namespace QtAV;
#endif

frmPlayPlus::frmPlayPlus(QWidget *parent) : QWidget(parent), ui(new Ui::frmPlayPlus)
{
    
    
    ui->setupUi(this);
    this->initForm();
    this->initUrl();
    this->initConfig();
    this->initWidget(0);
}

frmPlayPlus::~frmPlayPlus()
{
    
    
    if (ui->btnOpen->text() == "关闭") {
    
    
        this->clearWidget(0);
    }
    delete ui;
}

bool frmPlayPlus::eventFilter(QObject *watched, QEvent *event)
{
    
    
    int type = event->type();
    if (type == QEvent::MouseButtonPress) {
    
    
        pressedTime = QDateTime::currentDateTime();
        if (qApp->mouseButtons() == Qt::RightButton) {
    
    
            videoMenu->exec(QCursor::pos());
        }
    } else if (type == QEvent::MouseButtonRelease) {
    
    
#ifdef Q_OS_ANDROID
        //长按弹出菜单
        int offset = pressedTime.msecsTo(QDateTime::currentDateTime());
        if (offset >= 1000) {
    
    
            videoMenu->exec(QCursor::pos());
        }
#endif
    }

    return QWidget::eventFilter(watched, event);
}

void frmPlayPlus::initForm()
{
    
    
#ifdef appui
    ui->verticalLayout->insertWidget(1, ui->cboxVideoUrl);
    ui->cboxVideoCore->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    ui->cboxScaleMode->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    ui->cboxHardware->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
#endif

    player = new QObject;

    //右键菜单
    videoMenu = new QMenu(this);
    this->installEventFilter(this);

    //实例化通道布局类
    videoBox = new VideoBox(this);
    connect(videoBox, SIGNAL(changeVideo(int, QString, bool)), this, SLOT(changeVideo(int, QString, bool)));
    videoBox->setLayout(ui->gridLayout);
    videoBox->setVideoType(AppConfig::Plus_VideoType);

    //添加自定义行列数的布局
    //videoBox->appendType(1, 8, 3);
    videoBox->initMenu(videoMenu);
}

void frmPlayPlus::initUrl()
{
    
    
    frmMain::initUrl(ui->cboxVideoUrl, AppConfig::Plus_VideoUrl);
}

void frmPlayPlus::initConfig()
{
    
    
    VideoUtil::loadVideoUrl(ui->cboxVideoUrl, AppConfig::Plus_VideoUrl, -1);
    connect(ui->cboxVideoUrl->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(saveConfig()));

    VideoUtil::loadVideoCore(ui->cboxVideoCore, AppConfig::Plus_VideoCore, true);
    connect(ui->cboxVideoCore, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));

    VideoUtil::loadScaleMode(ui->cboxScaleMode);
    ui->cboxScaleMode->setCurrentIndex(AppConfig::Plus_ScaleMode);
    connect(ui->cboxScaleMode, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));

    VideoUtil::loadHardware(ui->cboxHardware, (VideoCore)AppConfig::Plus_VideoCore, AppConfig::Plus_Hardware);
    connect(ui->cboxHardware, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
}

void frmPlayPlus::saveConfig()
{
    
    
    //内核变化后做出对应的处理/比如切换硬解码名称
    int videoCore = ui->cboxVideoCore->itemData(ui->cboxVideoCore->currentIndex()).toInt();
    if (AppConfig::Plus_VideoCore != videoCore) {
    
    
        AppConfig::Plus_VideoCore = videoCore;
        VideoCore core = (VideoCore)AppConfig::Plus_VideoCore;
        VideoUtil::loadHardware(ui->cboxHardware, core, AppConfig::Plus_Hardware);
    }

    AppConfig::Plus_ScaleMode = ui->cboxScaleMode->currentIndex();
    AppConfig::Plus_VideoUrl = ui->cboxVideoUrl->currentText().trimmed();
    AppConfig::Plus_Hardware = ui->cboxHardware->currentText();
    AppConfig::writeConfig();
}

void frmPlayPlus::initPlayer(int type)
{
    
    
    player->deleteLater();
    player = NULL;

    if (type == 5) {
    
    
#ifdef mdkx
        player = new MdkPlayer;
        player->setObjectName("MdkPlayer");
#endif
    } else if (type == 6) {
    
    
#ifdef qtavx
        player = new AVPlayer;
        player->setObjectName("AVPlayer");
#endif
    }

    if (!player) {
    
    
        player = new QObject;
    }
}

void frmPlayPlus::initWidget(int type)
{
    
    
    this->clearWidget(type);
    this->initPlayer(type);

    int scale = AppConfig::Plus_ScaleMode;
    QString hardware = AppConfig::Plus_Hardware;

    //取出当前画面数
    int count = 4;
    QString videoType = videoBox->getVideoType();
    QStringList list = videoType.split("_");
    if (videoType.contains("x")) {
    
    
        list = list.last().split("x");
        count = (list.at(0).toInt() * list.at(1).toInt());
    } else if (list.count() == 2) {
    
    
        count = (list.at(1).toInt() - list.at(0).toInt() + 1);
    }

    //按照当前画面数量生成需要同屏渲染的画面
    for (int i = 0; i < count; ++i) {
    
    
        QWidget *widget;
        if (type == 5) {
    
    
#ifdef mdkx
            MdkPlayer *p = (MdkPlayer *)player;
            widget = new MdkWidget(p);
            p->setAspect((scale != 2 ? mdk::KeepAspectRatio : mdk::IgnoreAspectRatio), widget);
#endif
        } else if (type == 6) {
    
    
#ifdef qtavx
            VideoOutput *v = new VideoOutput;
            v->setOutAspectRatioMode((scale != 2 ? VideoOutput::VideoAspectRatio : VideoOutput::RendererAspectRatio));
            widget = v->widget();
            renders << v;
#endif
        } else {
    
    
            VideoWidget *w = new VideoWidget;
            connect(w, SIGNAL(sig_receivePlayFinsh()), w, SLOT(stop()));
            WidgetPara widgetPara = w->getWidgetPara();
            widgetPara.sharedData = true;
            widgetPara.scaleMode = (ScaleMode)scale;
            w->setWidgetPara(widgetPara);

            VideoPara videoPara = w->getVideoPara();
            videoPara.videoCore = VideoCore_FFmpeg;
            videoPara.hardware = hardware;
            videoPara.playRepeat = true;
            videoPara.connectTimeout = 0;
            w->setVideoPara(videoPara);
            widget = w;
        }

        //widget->installEventFilter(this);
        widgets << widget;
    }

    //剩余的用空窗体填充
    for (int i = 0; i < (64 - count); ++i) {
    
    
        VideoWidget *widget = new VideoWidget;
        widget->installEventFilter(this);
        widgets << widget;
    }

    videoBox->setWidgets(widgets);
    videoBox->show_video_all();
    this->playWidget(type);
}

void frmPlayPlus::clearWidget(int type)
{
    
    
    if (type == 0 && player) {
    
    
        QString objName = player->objectName();
        int core = AppConfig::Plus_VideoCore;
        if (core == 2) {
    
    
            foreach (QWidget *widget, widgets) {
    
    
                VideoWidget *w = (VideoWidget *)widget;
                w->stop();
            }
        } else if (core == 5) {
    
    
#ifdef mdkx
            if (objName == "MdkPlayer") {
    
    
                MdkPlayer *p = (MdkPlayer *)player;
                p->stop();
            }
#endif
        } else if (core == 6) {
    
    
#ifdef qtavx
            if (objName == "AVPlayer") {
    
    
                AVPlayer *p = (AVPlayer *)player;
                p->stop();
                qDeleteAll(renders);
                renders.clear();
            }
#endif
        }
    }

    qDeleteAll(widgets);
    widgets.clear();
}

void frmPlayPlus::playWidget(int type)
{
    
    
    QString url = AppConfig::Plus_VideoUrl;
    VideoType videoType = VideoHelper::getVideoType(url);
    url = VideoHelper::getRightUrl(videoType, url);
    QString hardware = AppConfig::Plus_Hardware;

    if (type == 2) {
    
    
        foreach (QWidget *widget, widgets) {
    
    
            VideoWidget *w = (VideoWidget *)widget;
            w->open(url);
        }
    } else if (type == 5) {
    
    
#ifdef mdkx
        MdkPlayer *p = (MdkPlayer *)player;
        p->setDecoders(MdkHelper::getHardware(hardware));
        p->setMedia(url);
        p->setLoop(-1);
        p->play();
#endif
    } else if (type == 6) {
    
    
#ifdef qtavx
        AVPlayer *p = (AVPlayer *)player;
        foreach (VideoOutput *v, renders) {
    
    
            p->addVideoRenderer(v);
        }
        p->setVideoDecoderPriority(QtavHelper::getHardware(hardware));
        p->setRepeat(-1);
        p->play(url);
#endif
    }
}

void frmPlayPlus::changeVideo(int type, const QString &videoType, bool videoMax)
{
    
    
    AppConfig::Plus_VideoType = videoType;
    AppConfig::writeConfig();
}

void frmPlayPlus::on_btnOpen_clicked()
{
    
    
    if (ui->btnOpen->text() == "打开") {
    
    
        this->initWidget(AppConfig::Plus_VideoCore);
        ui->btnOpen->setText("关闭");
        ui->cboxVideoCore->setEnabled(false);
    } else {
    
    
        this->initWidget(0);
        ui->btnOpen->setText("打开");
        ui->cboxVideoCore->setEnabled(true);
    }
}

Supongo que te gusta

Origin blog.csdn.net/feiyangqingyun/article/details/135215305
Recomendado
Clasificación