您好,登錄后才能下訂單哦!
本篇內容介紹了“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比較簡單就是,并沒有演示所有的功能,只演示了最基礎的功能比如播放視頻進度控制等,離一個完整的視頻播放器差十萬八千里不止。
主要接口如下:
通用獲取屬性接口函數 get_property_variant
通用設置屬性接口函數 set_property_variant
通用設置參數接口函數 set_option_variant
通用執行命令接口函數 command_variant
多線程實時播放視頻流+本地視頻等。
支持windows+linux+mac。
多線程顯示圖像,不卡主界面。
自動重連網絡攝像頭。
可設置是否保存到文件以及文件名。
可直接拖曳文件到mpvwidget控件播放。
支持h365視頻流+rtmp等常見視頻流。
可暫停播放和繼續播放。
支持存儲單個視頻文件和定時存儲視頻文件。
自定義頂部懸浮條,發送單擊信號通知,可設置是否啟用。
可設置畫面拉伸填充或者等比例填充。
可對視頻進行截圖(原始圖片)和截屏。
錄像文件存儲MP4文件。
支持qsv、dxva2、d3d11va等硬解碼。
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通用接口怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。