Abonnement à l'événement Qt pour le développement audio et vidéo de 15 mpv

Introduction

Dans le processus d'utilisation de libmpv, en vous abonnant à l'événement mpv, vous pouvez connaître certains événements plus précisément et à temps, tels que l'ouverture réussie du fichier, le changement de l'état de lecture, etc., sans avoir besoin d'une minuterie pour lire l'état, en particulier l'ouverture réussie. Événement, si vous n'utilisez pas d'abonnement aux événements, le flux vidéo sera parfois bloqué pendant un certain temps. Par exemple, lorsqu'il n'y a pas de flux vidéo ou que le réseau n'est pas bon, il existe deux façons de contourner cette situation. Il en va de même pour le décodage vlc et ffmpeg. Une façon consiste à l'ouvrir directement au thread pour exécution. À l'origine, le processus de décodage est une classe de thread complète, de sorte que l'initialisation est effectuée directement dans le thread en modifiant le bit d'indicateur. Il n'y a aucune pression pour éviter de rester bloqué. Une autre méthode est À l'aide des rappels d'événements, une fois l'ouverture réussie, effectuez d'autres traitements, tels que la lecture de la largeur et de la hauteur de la vidéo. Ces informations ne peuvent généralement être lues qu'une fois le fichier ouvert.

Il ne fait aucun doute que mpv prend également en charge l'abonnement aux événements. Les modifications d'événement de propriété qui doivent être souscrites sont ajoutées à la file d'attente d'abonnement aux événements via la fonction mpv_observe_property. Cette fonction comporte quatre paramètres. Le premier paramètre fait référence à l'objet mpv (généré par mpv_create) et le second paramètre fait référence à Données utilisateur, si vous n'en avez pas besoin, remplissez directement 0, généralement vous n'en avez pas besoin. Le troisième paramètre fait référence au nom de l'attribut. En ce qui concerne le nom de l'attribut, vous pouvez vous référer au manuel sur le site officiel (http://mpv.io/manual/master/# properties), le quatrième paramètre fait référence au type de format de la propriété. De manière générale, vous vous abonnerez aux changements de ces événements attributaires: durée (longueur du fichier), time-pos (progression de la lecture actuelle). Une fois l'événement abonné, exécutez la fonction mpv_set_wakeup_callback pour définir le traitement de la fonction de rappel d'événement.

2. Caractéristiques

  1. Lecture de flux vidéo en temps réel multi-thread + vidéo locale, etc.
  2. Prend en charge Windows + Linux + Mac.
  3. Images d'affichage multi-thread, non bloquées dans l'interface principale.
  4. Reconnectez la webcam automatiquement.
  5. Peut définir s'il faut enregistrer dans le fichier et le nom du fichier.
  6. Vous pouvez faire glisser des fichiers directement vers le contrôle mpvwidget pour les lire.
  7. Prend en charge les flux vidéo courants tels que le flux vidéo h265 + rtmp.
  8. Peut mettre en pause et reprendre la lecture.
  9. Prend en charge le stockage de fichiers vidéo uniques et le stockage de synchronisation des fichiers vidéo.
  10. Personnalisez la barre flottante supérieure, envoyez une notification de signal de clic et indiquez si vous souhaitez l'activer.
  11. Vous pouvez définir le remplissage extensible de l'écran ou le remplissage à proportion égale.
  12. Peut prendre des captures d'écran (images originales) et des captures d'écran de vidéos.
  13. Le fichier vidéo stocke les fichiers MP4.
  14. Prend en charge le décodage dur tel que qsv, dxva2, d3d11va, etc.

Trois, rendus

Insérez la description de l'image ici

Quatre sites connexes

  1. Site national: https://gitee.com/feiyangqingyun/QWidgetDemo
  2. Site international: https://github.com/feiyangqingyun/QWidgetDemo
  3. Page d'accueil personnelle: https://blog.csdn.net/feiyangqingyun
  4. Page d'accueil de Zhihu: https://www.zhihu.com/people/feiyangqingyun/
  5. Adresse de l'expérience: https://blog.csdn.net/feiyangqingyun/article/details/97565652

Cinq, le code de base

//事件处理
static void handleEvents(mpv_handle *mpvPlayer, mpv_event *event, MpvThread *thread)
{
    switch (event->event_id) {
        case MPV_EVENT_PROPERTY_CHANGE: {
            mpv_event_property *property = (mpv_event_property *)event->data;
            QString propertyName = property->name;
            mpv_format propertyFormat = property->format;
            if (propertyName == "duration") {
                //文件总长度
                if (propertyFormat == MPV_FORMAT_DOUBLE) {
                    double time = *(double *)property->data;
                    uint length = time * 1000;
                    thread->doEvent(1, QVariantList() << length);
                    qDebug() << TIMEMS << "文件总长: " << length;
                }
            } else if (propertyName == "time-pos") {
                //当前播放进度
                if (propertyFormat == MPV_FORMAT_DOUBLE) {
                    double time = *(double *)property->data;
                    uint position = time * 1000;
                    thread->doEvent(2, QVariantList() << position);
                    //qDebug() << TIMEMS << "当前时间: " << position;
                }
            } else {
                qDebug() << TIMEMS << propertyName;
                if (propertyFormat == MPV_FORMAT_NODE) {
#if 0
                    QVariant data = qtmpv::node_to_variant((mpv_node *)property->data);
                    QJsonDocument json = QJsonDocument::fromVariant(data);
                    qDebug() << TIMEMS << json.toJson().data();
#endif
                }
            }

            break;
        }

        //获取宽高
        case MPV_EVENT_VIDEO_RECONFIG: {
            //这里会执行两次,不知道为什么
            int dwidth, dheight;
            mpv_get_property(mpvPlayer, "dwidth", MPV_FORMAT_INT64, &dwidth);
            mpv_get_property(mpvPlayer, "dheight", MPV_FORMAT_INT64, &dheight);
            qDebug() << TIMEMS << "dwidth:" << dwidth << "dheight:" << dheight;
            break;
        }

        //打印日志
        case MPV_EVENT_LOG_MESSAGE: {
            struct mpv_event_log_message *msg = (struct mpv_event_log_message *)event->data;
            QString data = QString("[%1] %2: %3").arg(msg->prefix).arg(msg->level).arg(msg->text);
            data.replace("\r", "");
            data.replace("\n", "");
            //qDebug() << TIMEMS << data;
            break;
        }

        //文件播放结束
        case MPV_EVENT_END_FILE: {
            thread->doEvent(0, QVariantList());
            break;
        }

        default:
            break;
    }
}

//订阅事件
static void attachEvents(mpv_handle *mpvPlayer)
{
    mpv_observe_property(mpvPlayer, 0, "duration", MPV_FORMAT_DOUBLE);
    mpv_observe_property(mpvPlayer, 0, "time-pos", MPV_FORMAT_DOUBLE);
    mpv_observe_property(mpvPlayer, 0, "track-list", MPV_FORMAT_NODE);
    mpv_observe_property(mpvPlayer, 0, "chapter-list", MPV_FORMAT_NODE);
}

Je suppose que tu aimes

Origine blog.csdn.net/feiyangqingyun/article/details/108152138
conseillé
Classement