91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Qt mpv通用接口怎么實現

發布時間:2021-12-15 10:30:44 來源:億速云 閱讀:119 作者:iii 欄目:互聯網科技

本篇內容介紹了“Qt mpv通用接口怎么實現”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

一、前言

前面幾篇文章,依次講了解碼播放、錄像存儲、讀取和控制、事件訂閱等,其實這些功能的實現都離不開封裝的通用的接口,最開始本人去調用一些設置的時候,發現多參數的不好實現,原來需要用mpv_node處理,而Qt中如何轉成mpv_node需要特殊的處理才行,后來在開源主頁看到了官方提供的demo例子,直接用qt封裝好了多個接口(https://github.com/mpv-player/mpv-examples/tree/master/libmpv),看里面的注釋是英文的,估計應該是官方提供的,傳入的參數都是支持QVariant的,這樣兼容性就超級強大了,多種不同類型的數據參數都可以傳入進去,再次感謝官方的demo,官方的demo除了有QWidget的外還有qml的版本,同時還提供了opengl版本,各位有興趣都可以down下來看看,不過demo比較簡單就是,并沒有演示所有的功能,只演示了最基礎的功能比如播放視頻進度控制等,離一個完整的視頻播放器差十萬八千里不止。

主要接口如下:

  1. 通用獲取屬性接口函數 get_property_variant

  2. 通用設置屬性接口函數 set_property_variant

  3. 通用設置參數接口函數 set_option_variant

  4. 通用執行命令接口函數 command_variant

二、功能特點

  1. 多線程實時播放視頻流+本地視頻等。

  2. 支持windows+linux+mac。

  3. 多線程顯示圖像,不卡主界面。

  4. 自動重連網絡攝像頭。

  5. 可設置是否保存到文件以及文件名。

  6. 可直接拖曳文件到mpvwidget控件播放。

  7. 支持h365視頻流+rtmp等常見視頻流。

  8. 可暫停播放和繼續播放。

  9. 支持存儲單個視頻文件和定時存儲視頻文件。

  10. 自定義頂部懸浮條,發送單擊信號通知,可設置是否啟用。

  11. 可設置畫面拉伸填充或者等比例填充。

  12. 可對視頻進行截圖(原始圖片)和截屏。

  13. 錄像文件存儲MP4文件。

  14. 支持qsv、dxva2、d3d11va等硬解碼。

三、效果圖

Qt mpv通用接口怎么實現

四、核心代碼

struct node_builder {
    node_builder(const QVariant &v) {
        set(&node_, v);
    }
    ~node_builder() {
        free_node(&node_);
    }
    mpv_node *node() {
        return &node_;
    }
private:
    Q_DISABLE_COPY(node_builder)
    mpv_node node_;
    mpv_node_list *create_list(mpv_node *dst, bool is_map, int num) {
        dst->format = is_map ? MPV_FORMAT_NODE_MAP : MPV_FORMAT_NODE_ARRAY;
        mpv_node_list *list = new mpv_node_list();
        dst->u.list = list;
        if (!list) {
            goto err;
        }
        list->values = new mpv_node[num]();
        if (!list->values) {
            goto err;
        }
        if (is_map) {
            list->keys = new char *[num]();
            if (!list->keys) {
                goto err;
            }
        }
        return list;
    err:
        free_node(dst);
        return NULL;
    }
    char *dup_qstring(const QString &s) {
        QByteArray b = s.toUtf8();
        char *r = new char[b.size() + 1];
        if (r) {
            std::memcpy(r, b.data(), b.size() + 1);
        }
        return r;
    }
    bool test_type(const QVariant &v, QMetaType::Type t) {
        // The Qt docs say: "Although this function is declared as returning
        // "QVariant::Type(obsolete), the return value should be interpreted
        // as QMetaType::Type."
        // So a cast really seems to be needed to avoid warnings (urgh).
        return static_cast<int>(v.type()) == static_cast<int>(t);
    }
    void set(mpv_node *dst, const QVariant &src) {
        if (test_type(src, QMetaType::QString)) {
            dst->format = MPV_FORMAT_STRING;
            dst->u.string = dup_qstring(src.toString());
            if (!dst->u.string) {
                goto fail;
            }
        } else if (test_type(src, QMetaType::Bool)) {
            dst->format = MPV_FORMAT_FLAG;
            dst->u.flag = src.toBool() ? 1 : 0;
        } else if (test_type(src, QMetaType::Int) ||
                   test_type(src, QMetaType::LongLong) ||
                   test_type(src, QMetaType::UInt) ||
                   test_type(src, QMetaType::ULongLong)) {
            dst->format = MPV_FORMAT_INT64;
            dst->u.int64 = src.toLongLong();
        } else if (test_type(src, QMetaType::Double)) {
            dst->format = MPV_FORMAT_DOUBLE;
            dst->u.double_ = src.toDouble();
        } else if (src.canConvert<QVariantList>()) {
            QVariantList qlist = src.toList();
            mpv_node_list *list = create_list(dst, false, qlist.size());
            if (!list) {
                goto fail;
            }
            list->num = qlist.size();
            for (int n = 0; n < qlist.size(); n++) {
                set(&list->values[n], qlist[n]);
            }
        } else if (src.canConvert<QVariantMap>()) {
            QVariantMap qmap = src.toMap();
            mpv_node_list *list = create_list(dst, true, qmap.size());
            if (!list) {
                goto fail;
            }
            list->num = qmap.size();
            for (int n = 0; n < qmap.size(); n++) {
                list->keys[n] = dup_qstring(qmap.keys()[n]);
                if (!list->keys[n]) {
                    free_node(dst);
                    goto fail;
                }
                set(&list->values[n], qmap.values()[n]);
            }
        } else {
            goto fail;
        }
        return;
    fail:
        dst->format = MPV_FORMAT_NONE;
    }
    void free_node(mpv_node *dst) {
        switch (dst->format) {
            case MPV_FORMAT_STRING:
                delete[] dst->u.string;
                break;
            case MPV_FORMAT_NODE_ARRAY:
            case MPV_FORMAT_NODE_MAP: {
                mpv_node_list *list = dst->u.list;
                if (list) {
                    for (int n = 0; n < list->num; n++) {
                        if (list->keys) {
                            delete[] list->keys[n];
                        }
                        if (list->values) {
                            free_node(&list->values[n]);
                        }
                    }
                    delete[] list->keys;
                    delete[] list->values;
                }
                delete list;
                break;
            }
            default:
                ;
        }
        dst->format = MPV_FORMAT_NONE;
    }
};

struct node_autofree {
    mpv_node *ptr;
    node_autofree(mpv_node *a_ptr) : ptr(a_ptr) {}
    ~node_autofree() {
        mpv_free_node_contents(ptr);
    }
};

static inline QVariant get_property_variant(mpv_handle *ctx, const QString &name)
{
    mpv_node node;
    if (mpv_get_property(ctx, name.toUtf8().data(), MPV_FORMAT_NODE, &node) < 0) {
        return QVariant();
    }
    node_autofree f(&node);
    return node_to_variant(&node);
}

static inline int set_property_variant(mpv_handle *ctx, const QString &name,
                                       const QVariant &v)
{
    node_builder node(v);
    return mpv_set_property(ctx, name.toUtf8().data(), MPV_FORMAT_NODE, node.node());
}

static inline int set_option_variant(mpv_handle *ctx, const QString &name,
                                     const QVariant &v)
{
    node_builder node(v);
    return mpv_set_option(ctx, name.toUtf8().data(), MPV_FORMAT_NODE, node.node());
}

static inline QVariant command_variant(mpv_handle *ctx, const QVariant &args)
{
    node_builder node(args);
    mpv_node res;
    if (mpv_command_node(ctx, node.node(), &res) < 0) {
        return QVariant();
    }
    node_autofree f(&res);
    return node_to_variant(&res);
}

static inline QVariant get_property(mpv_handle *ctx, const QString &name)
{
    mpv_node node;
    int err = mpv_get_property(ctx, name.toUtf8().data(), MPV_FORMAT_NODE, &node);
    if (err < 0) {
        return QVariant::fromValue(ErrorReturn(err));
    }
    node_autofree f(&node);
    return node_to_variant(&node);
}

static inline int set_property(mpv_handle *ctx, const QString &name,
                               const QVariant &v)
{
    node_builder node(v);
    return mpv_set_property(ctx, name.toUtf8().data(), MPV_FORMAT_NODE, node.node());
}

“Qt mpv通用接口怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

qt
AI

同德县| 中卫市| 安岳县| 县级市| 贺兰县| 宜兴市| 黔西| 边坝县| 牡丹江市| 盐池县| 和静县| 石台县| 个旧市| 东丰县| 正安县| 休宁县| 沅陵县| 台湾省| 清水河县| 通化市| 英山县| 灵山县| 梁山县| 永川市| 桐庐县| 日照市| 镶黄旗| 木兰县| 锡林浩特市| 大城县| 呼和浩特市| 山东省| 通化县| 黑水县| 天台县| 玛多县| 兴山县| 天祝| 油尖旺区| 扶风县| 南部县|