In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/01 Report--
This article introduces the knowledge of "how to implement the Qt mpv general interface". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
I. Preface
The previous articles in turn talked about decoding and playback, video storage, reading and control, event subscription and so on. In fact, the realization of these functions is inseparable from the encapsulated general interface. At first, when I went to call some settings, I found that it was difficult to implement multi-parameters, which originally needed to be handled by mpv_node, while how to convert to mpv_node in Qt required special processing. Later, I saw an official demo example provided on the open source home page. Directly use qt to encapsulate multiple interfaces (https://github.com/mpv-player/mpv-examples/tree/master/libmpv). Look at the comments in English. It is estimated that the comments should be provided officially. The parameters passed in all support QVariant, so the compatibility is super strong. Many different types of data parameters can be passed in. Thanks again to the official demo, the official demo has a version of qml in addition to QWidget. At the same time, the opengl version is also provided. If you are interested, you can down down and have a look. However, demo is relatively simple. It does not demonstrate all the functions, only the most basic features such as video playback progress control. It is more than 108000 miles away from a complete video player.
The main APIs are as follows:
General access attribute interface function get_property_variant
General setting property interface function set_property_variant
General setting parameter interface function set_option_variant
General execution command interface function command_variant
II. Functional features
Multi-thread real-time playback video stream + local video and so on.
Windows+linux+mac is supported.
Multi-thread display image, do not card the main interface.
Automatically reconnect the webcam.
You can set whether to save to a file and the file name.
You can drag the file directly to the mpvwidget control to play.
Supports h365 video streams + rtmp and other common video streams.
Playback can be paused and resumed.
Support for storing individual video files and storing video files at regular intervals.
Customize the top suspension bar and send click signal notification, which can be set whether it is enabled or not.
Can set screen stretch fill or proportional fill.
You can take screenshots (original pictures) and screenshots of the video.
Video files store MP4 files.
Qsv, dxva2, d3d11va and other hard decoding are supported.
Third, effect picture
4. The core code 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 (v.type ()) = = static_cast (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.roomle= src.toDouble ();} else if (src.canConvert ()) {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 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; values +) {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 ());} "how to implement the Qt mpv Universal Interface". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.