diff --git a/.gitignore b/.gitignore index ea8c4bf..0a25f36 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +/out diff --git a/Cargo.lock b/Cargo.lock index 009ad05..78f0241 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,25 +3,22 @@ version = 3 [[package]] -name = "aho-corasick" -version = "0.7.18" +name = "anyhow" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" -dependencies = [ - "memchr", -] +checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" [[package]] -name = "anyhow" -version = "1.0.51" +name = "atomic_refcell" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" +checksum = "73b5e5f48b927f04e952dedc932f31995a65a0bf65ec971c74436e51bf6e970d" [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" @@ -31,9 +28,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "cfg-expr" -version = "0.9.0" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edae0b9625d1fce32f7d64b71784d9b1bf8469ec1a9c417e44aaf16a9cbd7571" +checksum = "0aacacf4d96c24b2ad6eb8ee6df040e4f27b0d0b39a5710c30091baa830485db" dependencies = [ "smallvec", ] @@ -44,42 +41,26 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chrono" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "fragile" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69a039c3498dc930fe810151a34ba0c1c70b02b8625035592e74432f678591f2" - [[package]] name = "futures-channel" -version = "0.3.18" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27" +checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.18" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445" +checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" [[package]] name = "futures-executor" -version = "0.3.18" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b808bf53348a36cab739d7e04755909b9fcaaa69b7d7e588b37b6ec62704c97" +checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" dependencies = [ "futures-core", "futures-task", @@ -87,30 +68,36 @@ dependencies = [ ] [[package]] -name = "futures-io" -version = "0.3.18" +name = "futures-macro" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11" +checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "futures-sink" -version = "0.3.18" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af" +checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" [[package]] name = "futures-task" -version = "0.3.18" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12" +checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" [[package]] name = "futures-util" -version = "0.3.18" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e" +checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" dependencies = [ "futures-core", + "futures-macro", "futures-task", "pin-project-lite", "pin-utils", @@ -118,55 +105,40 @@ dependencies = [ ] [[package]] -name = "gio" -version = "0.15.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#f412e5e4e6d90f7f4331075c21880cffa59161c7" +name = "getrandom" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ - "bitflags", - "futures-channel", - "futures-core", - "futures-io", - "gio-sys", - "glib", + "cfg-if", "libc", - "once_cell", - "thiserror", -] - -[[package]] -name = "gio-sys" -version = "0.15.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#f412e5e4e6d90f7f4331075c21880cffa59161c7" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", - "winapi", + "wasi", ] [[package]] name = "glib" -version = "0.15.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#f412e5e4e6d90f7f4331075c21880cffa59161c7" +version = "0.16.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#12148df3e029a763fb1fdeb4252abccb4b2d28c7" dependencies = [ "bitflags", "futures-channel", "futures-core", "futures-executor", "futures-task", + "futures-util", "glib-macros", "glib-sys", "gobject-sys", "libc", "once_cell", "smallvec", + "thiserror", ] [[package]] name = "glib-macros" -version = "0.15.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#f412e5e4e6d90f7f4331075c21880cffa59161c7" +version = "0.16.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#12148df3e029a763fb1fdeb4252abccb4b2d28c7" dependencies = [ "anyhow", "heck", @@ -179,8 +151,8 @@ dependencies = [ [[package]] name = "glib-sys" -version = "0.15.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#f412e5e4e6d90f7f4331075c21880cffa59161c7" +version = "0.16.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#12148df3e029a763fb1fdeb4252abccb4b2d28c7" dependencies = [ "libc", "system-deps", @@ -188,46 +160,21 @@ dependencies = [ [[package]] name = "gobject-sys" -version = "0.15.0" -source = "git+https://github.com/gtk-rs/gtk-rs-core#f412e5e4e6d90f7f4331075c21880cffa59161c7" +version = "0.16.0" +source = "git+https://github.com/gtk-rs/gtk-rs-core#12148df3e029a763fb1fdeb4252abccb4b2d28c7" dependencies = [ "glib-sys", "libc", "system-deps", ] -[[package]] -name = "gst-plugin-hlssink3" -version = "0.1.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs#66e987c174d23b053124d3d8c2f3e39f10caf70b" -dependencies = [ - "gio", - "glib", - "gst-plugin-version-helper", - "gstreamer", - "gstreamer-app", - "gstreamer-base", - "m3u8-rs", - "once_cell", - "regex", -] - -[[package]] -name = "gst-plugin-version-helper" -version = "0.8.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs#66e987c174d23b053124d3d8c2f3e39f10caf70b" -dependencies = [ - "chrono", -] - [[package]] name = "gstreamer" -version = "0.18.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs#ee1a5e8395d0b2d2e07ffd0dd90acd10843c35c1" +version = "0.19.0" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs#69ea30dbda58fde2387dfdd29215eb9ff1c64339" dependencies = [ "bitflags", "cfg-if", - "fragile", "futures-channel", "futures-core", "futures-util", @@ -246,8 +193,8 @@ dependencies = [ [[package]] name = "gstreamer-app" -version = "0.18.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs#ee1a5e8395d0b2d2e07ffd0dd90acd10843c35c1" +version = "0.19.0" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs#69ea30dbda58fde2387dfdd29215eb9ff1c64339" dependencies = [ "bitflags", "futures-core", @@ -262,8 +209,8 @@ dependencies = [ [[package]] name = "gstreamer-app-sys" -version = "0.18.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs#ee1a5e8395d0b2d2e07ffd0dd90acd10843c35c1" +version = "0.19.0" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs#69ea30dbda58fde2387dfdd29215eb9ff1c64339" dependencies = [ "glib-sys", "gstreamer-base-sys", @@ -274,9 +221,10 @@ dependencies = [ [[package]] name = "gstreamer-base" -version = "0.18.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs#ee1a5e8395d0b2d2e07ffd0dd90acd10843c35c1" +version = "0.19.0" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs#69ea30dbda58fde2387dfdd29215eb9ff1c64339" dependencies = [ + "atomic_refcell", "bitflags", "cfg-if", "glib", @@ -287,8 +235,8 @@ dependencies = [ [[package]] name = "gstreamer-base-sys" -version = "0.18.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs#ee1a5e8395d0b2d2e07ffd0dd90acd10843c35c1" +version = "0.19.0" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs#69ea30dbda58fde2387dfdd29215eb9ff1c64339" dependencies = [ "glib-sys", "gobject-sys", @@ -299,8 +247,8 @@ dependencies = [ [[package]] name = "gstreamer-sys" -version = "0.18.0" -source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs#ee1a5e8395d0b2d2e07ffd0dd90acd10843c35c1" +version = "0.19.0" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs#69ea30dbda58fde2387dfdd29215eb9ff1c64339" dependencies = [ "glib-sys", "gobject-sys", @@ -309,40 +257,45 @@ dependencies = [ ] [[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +name = "gstreamer-video" +version = "0.19.0" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs#69ea30dbda58fde2387dfdd29215eb9ff1c64339" dependencies = [ - "unicode-segmentation", + "bitflags", + "cfg-if", + "futures-channel", + "glib", + "gstreamer", + "gstreamer-base", + "gstreamer-video-sys", + "libc", + "once_cell", ] +[[package]] +name = "gstreamer-video-sys" +version = "0.19.0" +source = "git+https://gitlab.freedesktop.org/gstreamer/gstreamer-rs#69ea30dbda58fde2387dfdd29215eb9ff1c64339" +dependencies = [ + "glib-sys", + "gobject-sys", + "gstreamer-base-sys", + "gstreamer-sys", + "libc", + "system-deps", +] + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "libc" -version = "0.2.109" +version = "0.2.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98a04dce437184842841303488f70d0188c5f51437d2a834dc097eafa909a01" - -[[package]] -name = "m3u8-rs" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50fe05791a7f418b59d6cddebdc293d77c9c1f652adbff855c071d4507cd883b" -dependencies = [ - "nom", -] - -[[package]] -name = "memchr" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" [[package]] name = "muldiv" @@ -350,22 +303,11 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5136edda114182728ccdedb9f5eda882781f35fa6e80cc360af12a8932507f3" -[[package]] -name = "nom" -version = "7.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" -dependencies = [ - "memchr", - "minimal-lexical", - "version_check", -] - [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", @@ -373,9 +315,9 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", "num-integer", @@ -384,39 +326,39 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] [[package]] name = "once_cell" -version = "1.8.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "option-operations" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95d6113415f41b268f1195907427519769e40ee6f28cbb053795098a2c16f447" +checksum = "7c26d27bb1aeab65138e4bf7666045169d1717febcc9ff870166be8348b223d0" dependencies = [ "paste", ] [[package]] name = "paste" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "pin-project-lite" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -426,22 +368,29 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.22" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "pretty-hex" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5c99d529f0d30937f6f4b8a86d988047327bb88d04d2c4afc356de74722131" +checksum = "c6fa0831dd7cc608c38a5e323422a0077678fa5744aa2be4ad91c4ece8eec8d5" [[package]] name = "proc-macro-crate" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" dependencies = [ + "once_cell", "thiserror", "toml", ] @@ -472,82 +421,100 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.33" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb37d2df5df740e582f28f8560cf425f52bb267d872fe58358eadb554909f07a" +checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.10" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] [[package]] -name = "regex" -version = "1.5.4" +name = "rand" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", + "libc", + "rand_chacha", + "rand_core", ] [[package]] -name = "regex-syntax" -version = "0.6.25" +name = "rand_chacha" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] [[package]] name = "serde" -version = "1.0.130" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" [[package]] name = "slab" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] [[package]] name = "slim-live" version = "0.1.0" dependencies = [ "anyhow", - "gst-plugin-hlssink3", "gstreamer", + "gstreamer-app", + "gstreamer-video", + "ulid", ] [[package]] name = "smallvec" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "syn" -version = "1.0.82" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] name = "system-deps" -version = "6.0.0" +version = "6.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1487aaddaacbc5d60a2a507ba1617c5ca66c57dd0dd07d0c5efd5b693841d4" +checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709" dependencies = [ "cfg-expr", "heck", @@ -558,18 +525,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", @@ -578,24 +545,27 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] [[package]] -name = "unicode-segmentation" -version = "1.8.0" +name = "ulid" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "13a3aaa69b04e5b66cc27309710a569ea23593612387d67daaf102e73aa974fd" +dependencies = [ + "rand", +] [[package]] -name = "unicode-xid" -version = "0.2.2" +name = "unicode-ident" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "version-compare" @@ -605,28 +575,12 @@ checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] -name = "winapi" -version = "0.3.9" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/Cargo.toml b/Cargo.toml index 3a64b0a..e9be4c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,8 @@ edition = "2021" rust-version = "1.56" [dependencies] -gst = { package = "gstreamer", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_18"] } -gst-plugin-hlssink3 = { package = "gst-plugin-hlssink3", git = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs" } # path = "../gst-plugins-rs/net/hlssink3" } +gst = { package = "gstreamer", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_20"] } +gst-video = { package = "gstreamer-video", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } +gst-app = { package = "gstreamer-app", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } anyhow = "1.0.51" +ulid = "1" diff --git a/src/main.rs b/src/main.rs index a00901a..a7c56a8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,48 +1,252 @@ -use gst::prelude::*; use anyhow::Error; +use gst::{Buffer, FlowError, FlowSuccess, glib}; +use gst::meta::CustomMeta; +use gst::prelude::*; +use std::collections::{HashMap, VecDeque}; +use std::sync::{Arc, Mutex}; -fn main() -> Result<(), Error> { +static IDENTITY_META: &str = "IdentityMeta"; +static BUFFERS_AHEAD_META: &str = "BuffersAheadMeta"; + +trait UidSetter { + fn set_uid(&mut self, id: String); +} + +trait UidGetter { + fn uid(&self) -> Option; +} + +impl UidSetter for &mut gst::BufferRef { + fn set_uid(&mut self, id: String) { + let mut meta = gst::meta::CustomMeta::add(self, IDENTITY_META).unwrap(); + let s = meta.mut_structure(); + s.set("id", id); + } +} + +impl UidGetter for &gst::BufferRef { + fn uid(&self) -> Option { + let meta = match CustomMeta::from_buffer(self, IDENTITY_META) { + Ok(m) => m, + Err(_) => return None, + }; + let s = meta.structure(); + s.get::("id").ok() + } +} + +trait BuffersAheadSetter { + fn set_buffers_ahead(&mut self, buffers: Vec); +} + +trait BuffersAheadGetter { + fn buffers_ahead(&self) -> Option>; +} + +impl BuffersAheadSetter for &mut gst::BufferRef { + fn set_buffers_ahead(&mut self, buffers: Vec) { + let mut meta = gst::meta::CustomMeta::add(self, BUFFERS_AHEAD_META).unwrap(); + let s = meta.mut_structure(); + s.set("buffers", gst::Array::new(buffers)); + } +} + +impl BuffersAheadGetter for &gst::BufferRef { + fn buffers_ahead(&self) -> Option> { + let meta = match CustomMeta::from_buffer(self, BUFFERS_AHEAD_META) { + Ok(m) => m, + Err(_) => return None, + }; + let s = meta.structure(); + if let Ok(buffers) = s.get::("buffers") { + // println!("\n\t------Found the list\n"); + //let v = buffers.to_vec().map(|v| v.get_owned::().unwrap()).collect::>(); + let mut res = Vec::new(); + for buffer in buffers.iter() { + let b = buffer.to_value().get_owned::().unwrap(); + res.push(b); + } + Some(res) + } else { + None + } + + } +} + +fn main() -> Result<(), Error> { gst::init()?; - gst_plugin_hlssink3::plugin_register_static()?; - let pipeline = gst::parse_launch("videotestsrc num-buffers=2500 ! timecodestamper ! video/x-raw,format=I420,width=1280,height=720,framerate=30/1 ! timeoverlay ! x264enc bframes=0 bitrate=2048 key-int-max=180 option-string=scenecut=0:force-cfr=1 ! video/x-h264,stream-format=avc,alignment=au,profile=main ! h264parse ! tee name=t ! queue ! hlssink3 name=hls-output t. ! queue ! fakesink sync=true").unwrap().downcast::().unwrap(); - let hls_output = pipeline.by_name("hls-output").unwrap(); - hls_output.set_properties(&[ - ("playlist-type", &"vod"), - ("location", &"s%05d.ts"), - ("playlist-location", &"master.m3u8"), - ("target-duration", &6u32), - ]); + let pipeline = gst::parse_launch(r#" + + srtsrc uri=srt://127.0.0.1:7002 ! tsdemux ! h264parse update-timecode=true name=parser ! tee name=t + + t. ! queue ! avdec_h264 ! appsink name=picture-type-setter + t. ! queue name=drop-b-frames ! identity name=include-back-b-frame-buffers ! avdec_h264 ! videoconvert ! timeoverlay ! gtksink + + "#,)?.downcast::().unwrap(); + /* + + t. ! queue name=drop-b-frames ! transcriberbin name=trans cc-caps=closedcaption/x-cea-708,format=cc_data + + trans.src_video ! queue name=include-back-b-frame-buffers ! avdec_h264 ! videoconvert ! timeoverlay ! cea608overlay black-background=1 ! gtksink + trans.src_audio ! audioconvert ! audiorate ! audioresample ! autoaudiosink + + */ + + gst::meta::CustomMeta::register(IDENTITY_META, &[]); + gst::meta::CustomMeta::register(BUFFERS_AHEAD_META, &[]); + + let id_gen_shared = Arc::new(Mutex::new(ulid::Generator::new())); + let buffer_type_store = Arc::new(Mutex::new(HashMap::new())); + let last_dropped_buffers = Arc::new(Mutex::new(Vec::new())); + + let parser = pipeline.by_name("parser").unwrap(); + parser + .static_pad("src") + .unwrap() + .add_probe(gst::PadProbeType::BUFFER, { + let id_gen_shared = id_gen_shared.clone(); + move |_pad, probe_info| { + if let Some(gst::PadProbeData::Buffer(ref mut buffer)) = probe_info.data { + let mut id_gen = id_gen_shared.lock().unwrap(); + let mut buffer = buffer.get_mut().unwrap(); + + buffer.set_uid(id_gen.generate().unwrap().to_string()); + } + gst::PadProbeReturn::Ok + } + }); + + let picture_type_setter = pipeline + .by_name("picture-type-setter") + .unwrap() + .downcast::() + .unwrap(); + picture_type_setter.set_callbacks( + gst_app::AppSinkCallbacks::builder() + // Add a handler to the "new-sample" signal. + .new_sample({ + let buffer_type_store = buffer_type_store.clone(); + move |appsink| { + // Pull the sample in question out of the appsink's buffer. + let sample = appsink.pull_sample().map_err(|_| gst::FlowError::Eos)?; + let buffer = sample.buffer().ok_or(gst::FlowError::Error)?; + + // Pull FFMpeg picture information + let picture_type = { + let ffmpeg_meta = CustomMeta::from_buffer(buffer, "GstFFMpegPictureMeta") + .map_err(|_| { + eprintln!("Buffer does not contain FFMpeg meta information, you need to use a modified version of GStreamer"); + gst::FlowError::Eos + })?; + let s = ffmpeg_meta.structure(); + s.get::("picture-type").map_err(|_| gst::FlowError::Eos)? + }; + + let buffer_id = buffer.uid().ok_or_else(|| { + eprintln!("Buffer does not contain Identity meta information"); + gst::FlowError::Eos + })?; + + let mut type_store = buffer_type_store.lock().unwrap(); + type_store.insert(buffer_id, picture_type); + + Ok(gst::FlowSuccess::Ok) + } + }) + .build(), + ); + + let drop_b_frames_queue = pipeline.by_name("drop-b-frames").unwrap(); + let queue_srcpad = drop_b_frames_queue.static_pad("src").unwrap(); + queue_srcpad.set_offset(gst::ClockTime::from_mseconds(500).nseconds() as i64); + queue_srcpad.add_probe(gst::PadProbeType::BUFFER, { + let buffer_type_store = buffer_type_store.clone(); + let last_dropped_buffers = last_dropped_buffers.clone(); + + move |_pad, probe_info| { + if let Some(gst::PadProbeData::Buffer(ref mut buffer)) = probe_info.data { + let buffer_id = buffer.as_ref().uid().expect("Buffer UID available"); + + let type_store = buffer_type_store.lock().unwrap(); + let mut last_dropped_buffers = last_dropped_buffers.lock().unwrap(); + + if let Some(pic_type) = type_store.get(&buffer_id) { + if pic_type == "B" { + // Drop B-frame buffers, but save it to cache for later lookup + last_dropped_buffers.push( buffer.to_owned()); + println!("Dropped buffer {buffer_id}"); + return gst::PadProbeReturn::Drop; + } else if last_dropped_buffers.len() > 0 { + println!("Found some dropped buffers ahead of {buffer_id}: {:?}", last_dropped_buffers.iter().map(|b| b.as_ref().uid()).collect::>()); + // it is the first non-B-frame buffer since we last dropped + let mut buffer = buffer.get_mut().unwrap(); + buffer.set_buffers_ahead(last_dropped_buffers.to_owned()); + *last_dropped_buffers = Vec::new(); + } + } else { + // The first buffer does not have picture type available, but next ones should have it + println!("Buffer with id({buffer_id}) does not have picture type information"); + } + } + gst::PadProbeReturn::Ok + } + }); + + let reconstruct = pipeline.by_name("include-back-b-frame-buffers").unwrap(); + reconstruct + .static_pad("src") + .unwrap() + .add_probe(gst::PadProbeType::BUFFER, |pad, probe_info| { + if let Some(gst::PadProbeData::Buffer(ref buffer)) = probe_info.data { + let mut reconstructed = VecDeque::new(); + for buffer_ahead in buffer.as_ref().buffers_ahead().unwrap_or_else(|| Vec::new()) { + let buffer_id = buffer_ahead.as_ref().uid().unwrap(); + pad.push(buffer_ahead).expect(format!("Could not push buffer: {buffer_id}").as_str()); + reconstructed.push_front(buffer_id); + } + reconstructed.push_front(buffer.as_ref().uid().unwrap()); + println!("Reconstructed buffer line: {:?}", reconstructed); + } + gst::PadProbeReturn::Ok + }); pipeline.set_state(gst::State::Playing)?; - let bus = pipeline - .bus() - .expect("Pipeline without bus. Shouldn't happen!"); + let context = glib::MainContext::default(); + let main_loop = glib::MainLoop::new(Some(&context), false); - for msg in bus.iter_timed(gst::ClockTime::NONE) { - use gst::MessageView; + pipeline.set_state(gst::State::Playing)?; - match msg.view() { - MessageView::Eos(..) => { - println!("EOS"); - break; - } - MessageView::Error(err) => { - pipeline.set_state(gst::State::Null)?; - eprintln!( - "Got error from {}: {} ({})", - msg.src() - .map(|s| String::from(s.path_string())) - .unwrap_or_else(|| "None".into()), - err.error(), - err.debug().unwrap_or_else(|| "".into()), - ); - break; - } - _ => {}, + let bus = pipeline.bus().unwrap(); + bus.add_watch({ + let main_loop = main_loop.clone(); + move |_, msg| { + use gst::MessageView; + let main_loop = &main_loop; + match msg.view() { + MessageView::Eos(..) => main_loop.quit(), + MessageView::Error(err) => { + println!( + "Error from {:?}: {} ({:?})", + err.src().map(|s| s.path_string()), + err.error(), + err.debug() + ); + main_loop.quit(); + } + _ => (), + }; + glib::Continue(true) } - } + }) + .expect("Failed to add bus watch"); + + main_loop.run(); + + pipeline.set_state(gst::State::Null)?; + bus.remove_watch().unwrap(); pipeline.set_state(gst::State::Null)?;