Compare commits

...

2 commits

Author SHA1 Message Date
cbdbc25bce rusttechx: Various changes 2024-11-23 12:17:50 +05:30
60b7f9e152 Use typst for monads presentation 2024-11-21 20:53:06 +05:30
12 changed files with 827 additions and 3292 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*/plots/*

View file

@ -1,11 +1,8 @@
all:
make slide slideshow
make slide
slide:
pandoc -t beamer --include-in-header=./style.tex monads.md -f markdown-implicit_figures -V colorlinks=true -V linkcolor=blue -V urlcolor=red -o monads.pdf
slideshow:
pandoc -t beamer --include-in-header=./style.tex monads.md -f markdown-implicit_figures -V colorlinks=true -V linkcolor=blue -V urlcolor=red -i -o monads-slideshow.pdf
pandoc monads.md --filter pandoc-plot -f markdown-implicit_figures --pdf-engine=typst --template=template.typ -o monads.pdf
view:
zathura --mode=presentation monads.pdf &

View file

@ -1,21 +1,23 @@
---
title:
- Monads
- Monads in Haskell
author:
- Sanchayan Maity
theme:
- default
classoption:
- aspectratio=169
aspectratio:
- 169
fontsize:
- 14pt
papersize:
- "presentation-16-9"
---
# Agenda
## Agenda
- Recap of Functors
- Recap of Applicative
- Monads
# Functor[^1][^2]
## Functor
```haskell
class Functor f where
@ -23,8 +25,6 @@ class Functor f where
(<$) :: a -> f b -> f a
```
Functors Laws
- Must preserve identity
```haskell
@ -37,16 +37,13 @@ fmap id = id
fmap (f . g) == fmap f . fmap g
```
[^1]: [Category Design Pattern](https://www.haskellforall.com/2012/08/the-category-design-pattern.html)
[^2]: [Functor Design Pattern](https://www.haskellforall.com/2012/09/the-functor-design-pattern.html)
## Higher order kinds
# Higher order kinds[^3]
- For something to be a functor, it has to be a first order kind[^1].
- For something to be a functor, it has to be a first order kind.
[^1]: [Haskell's Kind System](https://diogocastro.com/blog/2018/10/17/haskells-kind-system-a-primer/)
[^3]: [Haskell's Kind System](https://diogocastro.com/blog/2018/10/17/haskells-kind-system-a-primer/)
# Applicative
## Applicative
```haskell
class Functor f => Applicative (f :: TYPE -> TYPE) where
@ -63,7 +60,7 @@ class Functor f => Applicative (f :: TYPE -> TYPE) where
fmap f x = pure f <*> x
```
# Examples
## Examples
```haskell
pure (+1) <*> [1..3]
@ -85,7 +82,7 @@ pure (+1) <*> [1..3]
[(1,3),(1,4),(2,3),(2,4)]
```
# Use cases[^4]
## Use cases
```haskell
Person
@ -94,7 +91,7 @@ Person
<*> parseTelephone "telephone" o
```
Can also be written as
Can also be written as[^2]
```haskell
liftA3 Person
@ -102,9 +99,9 @@ liftA3 Person
(parseInt "age" o)
(parseTelephone "telephone" o)
```
[^4]: [FP Complete - Crash course to Applicative syntax](https://www.fpcomplete.com/haskell/tutorial/applicative-syntax/)
[^2]: [FP Complete - Crash course to Applicative syntax](https://www.fpcomplete.com/haskell/tutorial/applicative-syntax/)
# Use cases[^5]
## Use cases
```haskell
parsePerson :: Parser Person
@ -118,9 +115,7 @@ parsePerson = do
pure $ Person name age
```
[^5]: [FP Complete - Crash course to Applicative syntax](https://www.fpcomplete.com/haskell/tutorial/applicative-syntax/)
# Use cases[^6]
## Use cases
```haskell
helper :: () -> Text -> () -> () -> Int -> () -> Person
@ -136,10 +131,7 @@ parsePerson = helper
<*> endOfLine
```
[^6]: [FP Complete - Crash course to Applicative syntax](https://www.fpcomplete.com/haskell/tutorial/applicative-syntax/)
# Lifting
## Lifting
- Seeing Functor as unary lifting and Applicative as n-ary lifting
@ -153,7 +145,7 @@ liftA4 :: Applicative f => ..
Where `liftA0 = pure` and `liftA1 = fmap`.
# Monoidal functors
## Monoidal functors
- Remember Monoid?
@ -177,7 +169,7 @@ instance Monoid a => Applicative ((,) a) where
(u, f) <*> (v, x) = (u `mappend` v, f x)
```
# Where are monoids again
## Where are monoids again
```haskell
fmap (+1) ("blah", 0)
@ -193,17 +185,15 @@ liftA2 (,) [1, 2] [3, 4]
[(1,3),(1,4),(2,3),(2,4)]
```
# Function apply
## Function apply
- Applying a function to an `effectful` argument
```haskell
(<$>) :: Functor m => (a -> b) -> m a -> m b
(<*>) :: Applicative m => m (a -> b) -> m a -> m b
(=<<) :: Monad m => (a -> m b) -> m a -> m b
```
# Applicative laws
## Applicative laws
```haskell
-- Identity
@ -219,23 +209,26 @@ pure f <*> pure x = pure (f x)
u <*> pure y = pure ($ y) <*> u
```
# Operators[^7]
## Operators
- `pure` wraps up a pure value into some kind of Applicative
- `liftA2` applies a pure function to the values inside two `Applicative` wrapped values
- `<$>` operator version of `fmap`
- `<*>` apply a wrapped function to a wrapped value
- `*>`, `<*`
- See more at[^3]
[^7]: [FP Complete - Crash course to Applicative syntax](https://www.fpcomplete.com/haskell/tutorial/applicative-syntax/)
[^3]: [FP Complete - Crash course to Applicative syntax](https://www.fpcomplete.com/haskell/tutorial/applicative-syntax/)
# Monad, is that you?[^8]
## Monad, is that you?
![*_Monads_*](burrito-monad.png){width=60%}
[^8]: [The Unreasonable Effectiveness of Metaphor](https://argumatronic.com/posts/2018-09-02-effective-metaphor.html)
- Unreasonable Effectiveness of Metaphor[^4]
# Motivation - I
[^4]: [The Unreasonable Effectiveness of Metaphor](https://argumatronic.com/posts/2018-09-02-effective-metaphor.html)
## Motivation - I
```haskell
safeInverse :: Float -> Maybe Float
@ -251,7 +244,7 @@ sqrtInverse1 :: Float -> Maybe (Maybe Float)
sqrtInverse1 x = safeInverse <$> (safeSqrt x)
```
# Motivation - I
## Motivation - I
```haskell
joinMaybe :: Maybe (Maybe a) -> Maybe a
@ -265,7 +258,7 @@ sqrtInverse2 x = joinMaybe $ safeInverse <$> (safeSqrt x)
-- join :: Monad m => m (m a) -> m a
```
# Motivation - II
## Motivation - II
```haskell
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
@ -282,7 +275,7 @@ sqrtInverse x = (>>=) (safeSqrt x) safeInverse
-- (>>=) :: Monad m => m a -> (a -> m b) -> m b
```
# Motivation - III
## Motivation - III
```haskell
(>=>) :: (a -> Maybe b) -> (b -> Maybe c) -> (a -> Maybe c)
@ -297,13 +290,13 @@ sqrtInverse3 = safeSqrt >=> safeInverse
-- (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
```
# Motivations
## Motivations
- Flattening
- Sequencing
- Composition
# Monad
## Monad
```haskell
class Applicative m => Monad (m :: Type -> Type) where
@ -315,7 +308,7 @@ import Control.Monad (join)
join :: Monad m => m (m a) -> m a
```
# `do` notation
## Just **do**
```haskell
main :: IO ()
@ -326,7 +319,7 @@ main = do
putStrLn greeting
```
# Monad laws
## Monad laws
```haskell
-- Left identity
@ -339,11 +332,11 @@ x >>= return == x
m >>= (\x -> k x >>= h) == (m >>= k) >>= h
```
# ???
## ???
![*_WTH_*](endofunctor.jpg){width=60%}
# Monoids recap
## Monoids recap
```haskell
class Semigroup m where
@ -357,7 +350,7 @@ class Semigroup m => Monoid m where
mappend = (<>)
```
# Some Math
## Some Math
![*_Morphism_*](morphism.png){width=30%}
@ -365,7 +358,7 @@ class Semigroup m => Monoid m where
- Arrows between objects (morphisms): functions mapping one object to another
- Two categories: **Set** and **Hask**
# Categories
## Categories
- **Set**
- Category of sets
@ -376,9 +369,9 @@ class Semigroup m => Monoid m where
- Arrows between objects `a` & `b` are functions of type `a -> b`
- `a -> b` also a `Type` in **Hask**
- If `A -> B` and `B -> C`, then `A -> C` ~= `.` in **Hask**
- Fun fact: Function composition forms a monoid! (See [Endo](https://hackage.haskell.org/package/base-4.20.0.1/docs/Data-Monoid.html#t:Endo)).
- Fun fact: Function composition forms a monoid! (See [Endo](https://hackage.haskell.org/package/base-4.20.0.1/docs/Data-Monoid.html##t:Endo)).
# Monads are monoids...
## Monads are monoids...
In Haskell
@ -400,24 +393,24 @@ Type
a -> m b
```
# Now?
## Now?
![*_WTH_*](endofunctor2.jpg){width=80%}
# Contrasts with Monad
## Contrasts with Monad
- No data dependency between `f a` and `f b`
- Result of `f a` can't possibly influence the behaviour of `f b`
- That needs something like `a -> f b`
# Applicative vs Monads
## Applicative vs Monads
- Applicative
* Effects
* Batching and aggregation
* Concurrency/Independent
- Parsing context free grammar
- Exploring all branches of computation (see [`Alternative`](https://hackage.haskell.org/package/base-4.20.0.1/docs/Control-Applicative.html#t:Alternative))
- Exploring all branches of computation (see [`Alternative`](https://hackage.haskell.org/package/base-4.20.0.1/docs/Control-Applicative.html##t:Alternative))
- Monads
* Effects
@ -426,14 +419,14 @@ a -> m b
- Parsing context sensitive grammar
- Branching on previous results
# Weaker but better
## Weaker but better
- Weaker than monads but thus also more common
- Lends itself to optimisation (See Facebook's [Haxl](https://hackage.haskell.org/package/haxl) project)
- Always opt for the least powerful mechanism to get things done
- No dependency issues or branching? just use applicative
# State monad
## State monad
```haskell
newtype State s a = State { runState :: s -> (a, s) }
@ -452,7 +445,7 @@ instance Applicative (State s) where
(aTob a, s'')
```
# State monad
## State monad
```haskell
instance Monad (State s) where
@ -473,7 +466,7 @@ get :: State s s
get = State $ \s -> (s, s)
```
# State monad
## State monad
```haskell
put :: s -> State s ()
@ -487,7 +480,7 @@ eval (State sa) x = let (a, _) = sa x
in a
```
# Context
## Context
```haskell
type Stack = [Int]
@ -505,7 +498,7 @@ tos :: State Stack Int
tos = State $ \(x:xs) -> (x, x:xs)
```
# Context
## Context
```haskell
stackManip :: State Stack Int
@ -520,7 +513,7 @@ stackManip = do
testState = eval stackManip empty
```
# Reader monad
## Reader monad
```haskell
class Monad m => MonadReader r m | m -> r where
@ -528,7 +521,7 @@ class Monad m => MonadReader r m | m -> r where
local :: (r -> r) -> m a -> m a
```
# Context
## Context
```haskell
import Control.Monad.Reader
@ -544,7 +537,7 @@ jerry = do
return (env ++ " This is Jerry.")
```
# Context
## Context
```haskell
tomAndJerry :: Reader String String
@ -557,10 +550,8 @@ runJerryRun :: String
runJerryRun = runReader tomAndJerry "Who is this?"
```
# Questions
## Questions
- Reach out on
* Email: me@sanchayanmaity.net
* Mastodon: [sanchayanmaity.com](https://sanchayanmaity.com/@sanchayan)
* Telegram: [t.me/SanchayanMaity](https://t.me/SanchayanMaity)
* Blog: [sanchayanmaity.net](https://sanchayanmaity.net/)

Binary file not shown.

View file

@ -1 +0,0 @@
\logo{\includegraphics[height=0.5cm]{../images/Haskell.jpg}\vspace{220pt}\hspace{8pt}}

131
monads/template.typ Normal file
View file

@ -0,0 +1,131 @@
#import "@preview/diatypst:0.2.0": *
#show: slides.with(
title: "Monads in Haskell",
authors: ("Sanchayan Maity"),
ratio: 16/9,
layout: "large",
toc: false,
footer: false,
count: true,
)
$definitions.typst()$
#show terms: it => {
it.children
.map(child => [
#strong[#child.term]
#block(inset: (left: 1.5em, top: -0.4em))[#child.description]
])
.join()
}
#set table(
inset: 6pt,
stroke: none
)
#show figure.where(
kind: table
): set figure.caption(position: $if(table-caption-position)$$table-caption-position$$else$top$endif$)
#show figure.where(
kind: image
): set figure.caption(position: $if(figure-caption-position)$$figure-caption-position$$else$bottom$endif$)
$if(template)$
#import "$template$": conf
$else$
$template.typst()$
$endif$
$for(header-includes)$
$header-includes$
$endfor$
#show: doc => conf(
$if(title)$
title: [$title$],
$endif$
$if(subtitle)$
subtitle: [$subtitle$],
$endif$
$if(author)$
authors: (
$for(author)$
$if(author.name)$
( name: [$author.name$],
affiliation: [$author.affiliation$],
email: [$author.email$] ),
$else$
( name: [$author$],
affiliation: "",
email: "" ),
$endif$
$endfor$
),
$endif$
$if(keywords)$
keywords: ($for(keywords)$$keyword$$sep$,$endfor$),
$endif$
$if(date)$
date: [$date$],
$endif$
$if(lang)$
lang: "$lang$",
$endif$
$if(region)$
region: "$region$",
$endif$
$if(abstract)$
abstract: [$abstract$],
$endif$
$if(margin)$
margin: ($for(margin/pairs)$$margin.key$: $margin.value$,$endfor$),
$endif$
$if(papersize)$
paper: "$papersize$",
$endif$
$if(mainfont)$
font: ("$mainfont$",),
$endif$
$if(fontsize)$
fontsize: $fontsize$,
$endif$
$if(section-numbering)$
sectionnumbering: "$section-numbering$",
$endif$
cols: $if(columns)$$columns$$else$1$endif$,
doc,
)
$for(include-before)$
$include-before$
$endfor$
$if(toc)$
#outline(
title: auto,
depth: $toc-depth$
);
$endif$
$body$
$if(citations)$
$if(csl)$
#set bibliography(style: "$csl$")
$elseif(bibliographystyle)$
#set bibliography(style: "$bibliographystyle$")
$endif$
$if(bibliography)$
#bibliography($for(bibliography)$"$bibliography$"$sep$,$endfor$)
$endif$
$endif$
$for(include-after)$
$include-after$
$endfor$

View file

@ -0,0 +1,508 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.1.2 (0)
-->
<!-- Title: pipeline Pages: 1 -->
<svg width="2935pt" height="526pt"
viewBox="0.00 0.00 2935.20 525.75" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 521.75)">
<title>pipeline</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-521.75 2931.2,-521.75 2931.2,4 -4,4"/>
<text text-anchor="middle" x="1463.6" y="-504.25" font-family="sans" font-size="10.00">&lt;GstPipeline&gt;</text>
<text text-anchor="middle" x="1463.6" y="-490" font-family="sans" font-size="10.00">pipeline0</text>
<text text-anchor="middle" x="1463.6" y="-475.75" font-family="sans" font-size="10.00">[&gt;]</text>
<g id="clust1" class="cluster">
<title>cluster_autoaudiosink0_0x7e06740576f0</title>
<path fill="#ffffff" stroke="black" d="M2350.45,-8C2350.45,-8 2915.2,-8 2915.2,-8 2921.2,-8 2927.2,-14 2927.2,-20 2927.2,-20 2927.2,-193 2927.2,-193 2927.2,-199 2921.2,-205 2915.2,-205 2915.2,-205 2350.45,-205 2350.45,-205 2344.45,-205 2338.45,-199 2338.45,-193 2338.45,-193 2338.45,-20 2338.45,-20 2338.45,-14 2344.45,-8 2350.45,-8"/>
<text text-anchor="middle" x="2632.82" y="-193.4" font-family="Bitstream Vera Sans" font-size="8.00">GstAutoAudioSink</text>
<text text-anchor="middle" x="2632.82" y="-183.65" font-family="Bitstream Vera Sans" font-size="8.00">autoaudiosink0</text>
<text text-anchor="middle" x="2632.82" y="-173.9" font-family="Bitstream Vera Sans" font-size="8.00">[&gt;]</text>
<text text-anchor="middle" x="2632.82" y="-164.15" font-family="Bitstream Vera Sans" font-size="8.00">filter&#45;caps=audio/x&#45;raw</text>
</g>
<g id="clust2" class="cluster">
<title>cluster_autoaudiosink0_0x7e06740576f0_sink</title>
</g>
<g id="clust3" class="cluster">
<title>cluster_autoaudiosink0_actual_sink_pulse_0x7e0674069520</title>
<path fill="#aaaaff" stroke="black" d="M2699.2,-16C2699.2,-16 2907.2,-16 2907.2,-16 2913.2,-16 2919.2,-22 2919.2,-28 2919.2,-28 2919.2,-138 2919.2,-138 2919.2,-144 2913.2,-150 2907.2,-150 2907.2,-150 2699.2,-150 2699.2,-150 2693.2,-150 2687.2,-144 2687.2,-138 2687.2,-138 2687.2,-28 2687.2,-28 2687.2,-22 2693.2,-16 2699.2,-16"/>
<text text-anchor="middle" x="2803.2" y="-138.4" font-family="Bitstream Vera Sans" font-size="8.00">GstPulseSink</text>
<text text-anchor="middle" x="2803.2" y="-128.65" font-family="Bitstream Vera Sans" font-size="8.00">autoaudiosink0&#45;actual&#45;sink&#45;pulse</text>
<text text-anchor="middle" x="2803.2" y="-118.9" font-family="Bitstream Vera Sans" font-size="8.00">[&gt;]</text>
<text text-anchor="middle" x="2803.2" y="-109.15" font-family="Bitstream Vera Sans" font-size="8.00">enable&#45;last&#45;sample=FALSE</text>
<text text-anchor="middle" x="2803.2" y="-99.4" font-family="Bitstream Vera Sans" font-size="8.00">device=&quot;bluez_output.00_02_5B_00_FF_0C.1&quot;</text>
<text text-anchor="middle" x="2803.2" y="-89.65" font-family="Bitstream Vera Sans" font-size="8.00">current&#45;device=&quot;bluez_output.00_02_5B_00_FF_0C.1&quot;</text>
<text text-anchor="middle" x="2803.2" y="-79.9" font-family="Bitstream Vera Sans" font-size="8.00">device&#45;name=&quot;DX3 Pro+&quot;</text>
</g>
<g id="clust4" class="cluster">
<title>cluster_autoaudiosink0_actual_sink_pulse_0x7e0674069520_sink</title>
</g>
<g id="clust5" class="cluster">
<title>cluster_queue3_0x7e067405b990</title>
<path fill="#aaffaa" stroke="black" d="M1914.7,-37C1914.7,-37 2063.7,-37 2063.7,-37 2069.7,-37 2075.7,-43 2075.7,-49 2075.7,-49 2075.7,-150 2075.7,-150 2075.7,-156 2069.7,-162 2063.7,-162 2063.7,-162 1914.7,-162 1914.7,-162 1908.7,-162 1902.7,-156 1902.7,-150 1902.7,-150 1902.7,-49 1902.7,-49 1902.7,-43 1908.7,-37 1914.7,-37"/>
<text text-anchor="middle" x="1989.2" y="-150.4" font-family="Bitstream Vera Sans" font-size="8.00">GstQueue</text>
<text text-anchor="middle" x="1989.2" y="-140.65" font-family="Bitstream Vera Sans" font-size="8.00">queue3</text>
<text text-anchor="middle" x="1989.2" y="-130.9" font-family="Bitstream Vera Sans" font-size="8.00">[&gt;]</text>
<text text-anchor="middle" x="1989.2" y="-121.15" font-family="Bitstream Vera Sans" font-size="8.00">current&#45;level&#45;buffers=39</text>
<text text-anchor="middle" x="1989.2" y="-111.4" font-family="Bitstream Vera Sans" font-size="8.00">current&#45;level&#45;bytes=319488</text>
<text text-anchor="middle" x="1989.2" y="-101.65" font-family="Bitstream Vera Sans" font-size="8.00">current&#45;level&#45;time=832000000</text>
</g>
<g id="clust6" class="cluster">
<title>cluster_queue3_0x7e067405b990_sink</title>
</g>
<g id="clust7" class="cluster">
<title>cluster_queue3_0x7e067405b990_src</title>
</g>
<g id="clust8" class="cluster">
<title>cluster_vorbisdec0_0x7e0674054030</title>
<path fill="#aaffaa" stroke="black" d="M1478.95,-57C1478.95,-57 1627.95,-57 1627.95,-57 1633.95,-57 1639.95,-63 1639.95,-69 1639.95,-69 1639.95,-140 1639.95,-140 1639.95,-146 1633.95,-152 1627.95,-152 1627.95,-152 1478.95,-152 1478.95,-152 1472.95,-152 1466.95,-146 1466.95,-140 1466.95,-140 1466.95,-69 1466.95,-69 1466.95,-63 1472.95,-57 1478.95,-57"/>
<text text-anchor="middle" x="1553.45" y="-140.4" font-family="Bitstream Vera Sans" font-size="8.00">GstVorbisDec</text>
<text text-anchor="middle" x="1553.45" y="-130.65" font-family="Bitstream Vera Sans" font-size="8.00">vorbisdec0</text>
<text text-anchor="middle" x="1553.45" y="-120.9" font-family="Bitstream Vera Sans" font-size="8.00">[&gt;]</text>
</g>
<g id="clust9" class="cluster">
<title>cluster_vorbisdec0_0x7e0674054030_sink</title>
</g>
<g id="clust10" class="cluster">
<title>cluster_vorbisdec0_0x7e0674054030_src</title>
</g>
<g id="clust11" class="cluster">
<title>cluster_queue2_0x7e0674058fd0</title>
<path fill="#aaffaa" stroke="black" d="M1043.2,-67C1043.2,-67 1192.2,-67 1192.2,-67 1198.2,-67 1204.2,-73 1204.2,-79 1204.2,-79 1204.2,-150 1204.2,-150 1204.2,-156 1198.2,-162 1192.2,-162 1192.2,-162 1043.2,-162 1043.2,-162 1037.2,-162 1031.2,-156 1031.2,-150 1031.2,-150 1031.2,-79 1031.2,-79 1031.2,-73 1037.2,-67 1043.2,-67"/>
<text text-anchor="middle" x="1117.7" y="-150.4" font-family="Bitstream Vera Sans" font-size="8.00">GstQueue</text>
<text text-anchor="middle" x="1117.7" y="-140.65" font-family="Bitstream Vera Sans" font-size="8.00">queue2</text>
<text text-anchor="middle" x="1117.7" y="-130.9" font-family="Bitstream Vera Sans" font-size="8.00">[&gt;]</text>
</g>
<g id="clust12" class="cluster">
<title>cluster_queue2_0x7e0674058fd0_sink</title>
</g>
<g id="clust13" class="cluster">
<title>cluster_queue2_0x7e0674058fd0_src</title>
</g>
<g id="clust14" class="cluster">
<title>cluster_autovideosink0_0x7e0674027fa0</title>
<path fill="#ffffff" stroke="black" d="M2350.45,-213C2350.45,-213 2902.07,-213 2902.07,-213 2908.07,-213 2914.07,-219 2914.07,-225 2914.07,-225 2914.07,-447 2914.07,-447 2914.07,-453 2908.07,-459 2902.07,-459 2902.07,-459 2350.45,-459 2350.45,-459 2344.45,-459 2338.45,-453 2338.45,-447 2338.45,-447 2338.45,-225 2338.45,-225 2338.45,-219 2344.45,-213 2350.45,-213"/>
<text text-anchor="middle" x="2626.26" y="-447.4" font-family="Bitstream Vera Sans" font-size="8.00">GstAutoVideoSink</text>
<text text-anchor="middle" x="2626.26" y="-437.65" font-family="Bitstream Vera Sans" font-size="8.00">autovideosink0</text>
<text text-anchor="middle" x="2626.26" y="-427.9" font-family="Bitstream Vera Sans" font-size="8.00">[&gt;]</text>
<text text-anchor="middle" x="2626.26" y="-418.15" font-family="Bitstream Vera Sans" font-size="8.00">filter&#45;caps=video/x&#45;raw</text>
</g>
<g id="clust15" class="cluster">
<title>cluster_autovideosink0_0x7e0674027fa0_sink</title>
</g>
<g id="clust16" class="cluster">
<title>cluster_autovideosink0_actual_sink_xvimage_0x7e0674038f30</title>
<path fill="#aaaaff" stroke="black" d="M2712.32,-221C2712.32,-221 2894.07,-221 2894.07,-221 2900.07,-221 2906.07,-227 2906.07,-233 2906.07,-233 2906.07,-392 2906.07,-392 2906.07,-398 2900.07,-404 2894.07,-404 2894.07,-404 2712.32,-404 2712.32,-404 2706.32,-404 2700.32,-398 2700.32,-392 2700.32,-392 2700.32,-233 2700.32,-233 2700.32,-227 2706.32,-221 2712.32,-221"/>
<text text-anchor="middle" x="2803.2" y="-392.4" font-family="Bitstream Vera Sans" font-size="8.00">GstXvImageSink</text>
<text text-anchor="middle" x="2803.2" y="-382.65" font-family="Bitstream Vera Sans" font-size="8.00">autovideosink0&#45;actual&#45;sink&#45;xvimage</text>
<text text-anchor="middle" x="2803.2" y="-372.9" font-family="Bitstream Vera Sans" font-size="8.00">[&gt;]</text>
<text text-anchor="middle" x="2803.2" y="-363.15" font-family="Bitstream Vera Sans" font-size="8.00">max&#45;lateness=5000000</text>
<text text-anchor="middle" x="2803.2" y="-353.4" font-family="Bitstream Vera Sans" font-size="8.00">qos=TRUE</text>
<text text-anchor="middle" x="2803.2" y="-343.65" font-family="Bitstream Vera Sans" font-size="8.00">last&#45;sample=((GstSample*) 0x5e6a30673490)</text>
<text text-anchor="middle" x="2803.2" y="-333.9" font-family="Bitstream Vera Sans" font-size="8.00">processing&#45;deadline=15000000</text>
<text text-anchor="middle" x="2803.2" y="-324.15" font-family="Bitstream Vera Sans" font-size="8.00">device&#45;name=&quot;glamor textured video&quot;</text>
<text text-anchor="middle" x="2803.2" y="-314.4" font-family="Bitstream Vera Sans" font-size="8.00">double&#45;buffer=FALSE</text>
<text text-anchor="middle" x="2803.2" y="-304.65" font-family="Bitstream Vera Sans" font-size="8.00">colorkey=526352</text>
<text text-anchor="middle" x="2803.2" y="-294.9" font-family="Bitstream Vera Sans" font-size="8.00">window&#45;width=1912</text>
<text text-anchor="middle" x="2803.2" y="-285.15" font-family="Bitstream Vera Sans" font-size="8.00">window&#45;height=2111</text>
</g>
<g id="clust17" class="cluster">
<title>cluster_autovideosink0_actual_sink_xvimage_0x7e0674038f30_sink</title>
</g>
<g id="clust18" class="cluster">
<title>cluster_queue1_0x7e067402f440</title>
<path fill="#aaffaa" stroke="black" d="M1914.7,-206C1914.7,-206 2063.7,-206 2063.7,-206 2069.7,-206 2075.7,-212 2075.7,-218 2075.7,-218 2075.7,-319 2075.7,-319 2075.7,-325 2069.7,-331 2063.7,-331 2063.7,-331 1914.7,-331 1914.7,-331 1908.7,-331 1902.7,-325 1902.7,-319 1902.7,-319 1902.7,-218 1902.7,-218 1902.7,-212 1908.7,-206 1914.7,-206"/>
<text text-anchor="middle" x="1989.2" y="-319.4" font-family="Bitstream Vera Sans" font-size="8.00">GstQueue</text>
<text text-anchor="middle" x="1989.2" y="-309.65" font-family="Bitstream Vera Sans" font-size="8.00">queue1</text>
<text text-anchor="middle" x="1989.2" y="-299.9" font-family="Bitstream Vera Sans" font-size="8.00">[&gt;]</text>
<text text-anchor="middle" x="1989.2" y="-290.15" font-family="Bitstream Vera Sans" font-size="8.00">current&#45;level&#45;buffers=4</text>
<text text-anchor="middle" x="1989.2" y="-280.4" font-family="Bitstream Vera Sans" font-size="8.00">current&#45;level&#45;bytes=12441600</text>
<text text-anchor="middle" x="1989.2" y="-270.65" font-family="Bitstream Vera Sans" font-size="8.00">current&#45;level&#45;time=166666666</text>
</g>
<g id="clust19" class="cluster">
<title>cluster_queue1_0x7e067402f440_sink</title>
</g>
<g id="clust20" class="cluster">
<title>cluster_queue1_0x7e067402f440_src</title>
</g>
<g id="clust21" class="cluster">
<title>cluster_theoradec0_0x7e06740233a0</title>
<path fill="#aaffaa" stroke="black" d="M1478.95,-193C1478.95,-193 1627.95,-193 1627.95,-193 1633.95,-193 1639.95,-199 1639.95,-205 1639.95,-205 1639.95,-276 1639.95,-276 1639.95,-282 1633.95,-288 1627.95,-288 1627.95,-288 1478.95,-288 1478.95,-288 1472.95,-288 1466.95,-282 1466.95,-276 1466.95,-276 1466.95,-205 1466.95,-205 1466.95,-199 1472.95,-193 1478.95,-193"/>
<text text-anchor="middle" x="1553.45" y="-276.4" font-family="Bitstream Vera Sans" font-size="8.00">GstTheoraDec</text>
<text text-anchor="middle" x="1553.45" y="-266.65" font-family="Bitstream Vera Sans" font-size="8.00">theoradec0</text>
<text text-anchor="middle" x="1553.45" y="-256.9" font-family="Bitstream Vera Sans" font-size="8.00">[&gt;]</text>
</g>
<g id="clust22" class="cluster">
<title>cluster_theoradec0_0x7e06740233a0_sink</title>
</g>
<g id="clust23" class="cluster">
<title>cluster_theoradec0_0x7e06740233a0_src</title>
</g>
<g id="clust24" class="cluster">
<title>cluster_queue0_0x7e067402cbd0</title>
<path fill="#aaffaa" stroke="black" d="M1043.2,-186C1043.2,-186 1192.2,-186 1192.2,-186 1198.2,-186 1204.2,-192 1204.2,-198 1204.2,-198 1204.2,-299 1204.2,-299 1204.2,-305 1198.2,-311 1192.2,-311 1192.2,-311 1043.2,-311 1043.2,-311 1037.2,-311 1031.2,-305 1031.2,-299 1031.2,-299 1031.2,-198 1031.2,-198 1031.2,-192 1037.2,-186 1043.2,-186"/>
<text text-anchor="middle" x="1117.7" y="-299.4" font-family="Bitstream Vera Sans" font-size="8.00">GstQueue</text>
<text text-anchor="middle" x="1117.7" y="-289.65" font-family="Bitstream Vera Sans" font-size="8.00">queue0</text>
<text text-anchor="middle" x="1117.7" y="-279.9" font-family="Bitstream Vera Sans" font-size="8.00">[&gt;]</text>
<text text-anchor="middle" x="1117.7" y="-270.15" font-family="Bitstream Vera Sans" font-size="8.00">current&#45;level&#45;buffers=24</text>
<text text-anchor="middle" x="1117.7" y="-260.4" font-family="Bitstream Vera Sans" font-size="8.00">current&#45;level&#45;bytes=1475593</text>
<text text-anchor="middle" x="1117.7" y="-250.65" font-family="Bitstream Vera Sans" font-size="8.00">current&#45;level&#45;time=1000000000</text>
</g>
<g id="clust25" class="cluster">
<title>cluster_queue0_0x7e067402cbd0_sink</title>
</g>
<g id="clust26" class="cluster">
<title>cluster_queue0_0x7e067402cbd0_src</title>
</g>
<g id="clust27" class="cluster">
<title>cluster_oggdemux0_0x5e6a306699a0</title>
<path fill="#aaffaa" stroke="black" d="M602.95,-117C602.95,-117 756.45,-117 756.45,-117 762.45,-117 768.45,-123 768.45,-129 768.45,-129 768.45,-233 768.45,-233 768.45,-239 762.45,-245 756.45,-245 756.45,-245 602.95,-245 602.95,-245 596.95,-245 590.95,-239 590.95,-233 590.95,-233 590.95,-129 590.95,-129 590.95,-123 596.95,-117 602.95,-117"/>
<text text-anchor="middle" x="679.7" y="-233.4" font-family="Bitstream Vera Sans" font-size="8.00">GstOggDemux</text>
<text text-anchor="middle" x="679.7" y="-223.65" font-family="Bitstream Vera Sans" font-size="8.00">oggdemux0</text>
<text text-anchor="middle" x="679.7" y="-213.9" font-family="Bitstream Vera Sans" font-size="8.00">[&gt;]</text>
</g>
<g id="clust28" class="cluster">
<title>cluster_oggdemux0_0x5e6a306699a0_sink</title>
</g>
<g id="clust29" class="cluster">
<title>cluster_oggdemux0_0x5e6a306699a0_src</title>
</g>
<g id="clust30" class="cluster">
<title>cluster_filesrc0_0x5e6a306639a0</title>
<path fill="#ffaaaa" stroke="black" d="M113.47,-150C113.47,-150 199.97,-150 199.97,-150 205.97,-150 211.97,-156 211.97,-162 211.97,-162 211.97,-243 211.97,-243 211.97,-249 205.97,-255 199.97,-255 199.97,-255 113.47,-255 113.47,-255 107.47,-255 101.47,-249 101.47,-243 101.47,-243 101.47,-162 101.47,-162 101.47,-156 107.47,-150 113.47,-150"/>
<text text-anchor="middle" x="156.72" y="-243.4" font-family="Bitstream Vera Sans" font-size="8.00">GstFileSrc</text>
<text text-anchor="middle" x="156.72" y="-233.65" font-family="Bitstream Vera Sans" font-size="8.00">filesrc0</text>
<text text-anchor="middle" x="156.72" y="-223.9" font-family="Bitstream Vera Sans" font-size="8.00">[&gt;]</text>
<text text-anchor="middle" x="156.72" y="-214.15" font-family="Bitstream Vera Sans" font-size="8.00">location=&quot;sample.ogv&quot;</text>
</g>
<g id="clust31" class="cluster">
<title>cluster_filesrc0_0x5e6a306639a0_src</title>
</g>
<!-- legend -->
<g id="node1" class="node">
<title>legend</title>
<polygon fill="lightgrey" stroke="black" points="312.45,-142.47 0,-142.47 0,-71.53 312.45,-71.53 312.45,-142.47"/>
<text text-anchor="start" x="3.6" y="-130.32" font-family="sans" font-size="9.00">Legend</text>
<text text-anchor="start" x="3.6" y="-117.58" font-family="sans" font-size="9.00">Element&#45;States: [~] void&#45;pending, [0] null, [&#45;] ready, [=] paused, [&gt;] playing</text>
<text text-anchor="start" x="3.6" y="-104.83" font-family="sans" font-size="9.00">Pad&#45;Activation: [&#45;] none, [&gt;] push, [&lt;] pull</text>
<text text-anchor="start" x="3.6" y="-92.08" font-family="sans" font-size="9.00">Pad&#45;Flags: [b]locked, [f]lushing, [b]locking, [E]OS; upper&#45;case is set</text>
<text text-anchor="start" x="3.6" y="-79.33" font-family="sans" font-size="9.00">Pad&#45;Task: [T] has started task, [t] has paused task</text>
</g>
<!-- _proxypad1_0x7e0674058020 -->
<g id="node2" class="node">
<title>_proxypad1_0x7e0674058020</title>
<polygon fill="#ddddff" stroke="black" points="2408.45,-100.75 2354.45,-100.75 2354.45,-75.25 2408.45,-75.25 2408.45,-100.75"/>
<text text-anchor="middle" x="2381.45" y="-92.2" font-family="sans" font-size="9.00">proxypad1</text>
<text text-anchor="middle" x="2381.45" y="-79.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- autoaudiosink0_actual_sink_pulse_0x7e0674069520_sink_0x7e0674069930 -->
<g id="node4" class="node">
<title>autoaudiosink0_actual_sink_pulse_0x7e0674069520_sink_0x7e0674069930</title>
<polygon fill="#aaaaff" stroke="black" points="2829.7,-57.75 2775.7,-57.75 2775.7,-32.25 2829.7,-32.25 2829.7,-57.75"/>
<text text-anchor="middle" x="2802.7" y="-49.2" font-family="sans" font-size="9.00">sink</text>
<text text-anchor="middle" x="2802.7" y="-36.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- _proxypad1_0x7e0674058020&#45;&gt;autoaudiosink0_actual_sink_pulse_0x7e0674069520_sink_0x7e0674069930 -->
<g id="edge2" class="edge">
<title>_proxypad1_0x7e0674058020&#45;&gt;autoaudiosink0_actual_sink_pulse_0x7e0674069520_sink_0x7e0674069930</title>
<path fill="none" stroke="black" d="M2408.68,-85.31C2480.43,-77.95 2680.18,-57.46 2763.96,-48.87"/>
<polygon fill="black" stroke="black" points="2764.12,-52.37 2773.71,-47.87 2763.4,-45.41 2764.12,-52.37"/>
<text text-anchor="start" x="2442.82" y="-151.48" font-family="monospace" font-size="9.00">audio/x&#45;raw</text>
<text text-anchor="start" x="2442.82" y="-138.73" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;format: F32LE</text>
<text text-anchor="start" x="2442.82" y="-125.98" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;layout: interleaved</text>
<text text-anchor="start" x="2442.82" y="-113.23" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;rate: 48000</text>
<text text-anchor="start" x="2442.82" y="-100.48" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;channels: 2</text>
<text text-anchor="start" x="2442.82" y="-87.73" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;channel&#45;mask: 0x0000000000000003</text>
</g>
<!-- autoaudiosink0_0x7e06740576f0_sink_0x7e0674057d30 -->
<g id="node3" class="node">
<title>autoaudiosink0_0x7e06740576f0_sink_0x7e0674057d30</title>
<polygon fill="#ddddff" stroke="black" points="2408.45,-67.75 2354.45,-67.75 2354.45,-42.25 2408.45,-42.25 2408.45,-67.75"/>
<text text-anchor="middle" x="2381.45" y="-59.2" font-family="sans" font-size="9.00">sink</text>
<text text-anchor="middle" x="2381.45" y="-46.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- autoaudiosink0_0x7e06740576f0_sink_0x7e0674057d30&#45;&gt;_proxypad1_0x7e0674058020 -->
<g id="edge1" class="edge">
<title>autoaudiosink0_0x7e06740576f0_sink_0x7e0674057d30&#45;&gt;_proxypad1_0x7e0674058020</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M2381.45,-68.15C2381.45,-68.29 2381.45,-68.43 2381.45,-68.57"/>
<polygon fill="black" stroke="black" points="2377.95,-63.46 2381.45,-73.46 2384.95,-63.46 2377.95,-63.46"/>
</g>
<!-- queue3_0x7e067405b990_sink_0x7e067405be50 -->
<g id="node5" class="node">
<title>queue3_0x7e067405b990_sink_0x7e067405be50</title>
<polygon fill="#aaaaff" stroke="black" points="1972.7,-78.75 1918.7,-78.75 1918.7,-53.25 1972.7,-53.25 1972.7,-78.75"/>
<text text-anchor="middle" x="1945.7" y="-70.2" font-family="sans" font-size="9.00">sink</text>
<text text-anchor="middle" x="1945.7" y="-57.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- queue3_0x7e067405b990_src_0x7e067405c350 -->
<g id="node6" class="node">
<title>queue3_0x7e067405b990_src_0x7e067405c350</title>
<polygon fill="#ffaaaa" stroke="black" points="2059.7,-78.75 2005.7,-78.75 2005.7,-53.25 2059.7,-53.25 2059.7,-78.75"/>
<text text-anchor="middle" x="2032.7" y="-70.2" font-family="sans" font-size="9.00">src</text>
<text text-anchor="middle" x="2032.7" y="-57.45" font-family="sans" font-size="9.00">[&gt;][bfb][T]</text>
</g>
<!-- queue3_0x7e067405b990_sink_0x7e067405be50&#45;&gt;queue3_0x7e067405b990_src_0x7e067405c350 -->
<!-- queue3_0x7e067405b990_src_0x7e067405c350&#45;&gt;autoaudiosink0_0x7e06740576f0_sink_0x7e0674057d30 -->
<g id="edge4" class="edge">
<title>queue3_0x7e067405b990_src_0x7e067405c350&#45;&gt;autoaudiosink0_0x7e06740576f0_sink_0x7e0674057d30</title>
<path fill="none" stroke="black" d="M2060.05,-65.16C2121,-63.23 2271.94,-58.44 2342.7,-56.2"/>
<polygon fill="black" stroke="black" points="2342.75,-59.7 2352.63,-55.88 2342.52,-52.7 2342.75,-59.7"/>
<text text-anchor="start" x="2102.07" y="-132.35" font-family="monospace" font-size="9.00">audio/x&#45;raw</text>
<text text-anchor="start" x="2102.07" y="-119.6" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;format: F32LE</text>
<text text-anchor="start" x="2102.07" y="-106.85" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;layout: interleaved</text>
<text text-anchor="start" x="2102.07" y="-94.1" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;rate: 48000</text>
<text text-anchor="start" x="2102.07" y="-81.35" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;channels: 2</text>
<text text-anchor="start" x="2102.07" y="-68.6" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;channel&#45;mask: 0x0000000000000003</text>
</g>
<!-- vorbisdec0_0x7e0674054030_sink_0x7e0674054690 -->
<g id="node7" class="node">
<title>vorbisdec0_0x7e0674054030_sink_0x7e0674054690</title>
<polygon fill="#aaaaff" stroke="black" points="1536.95,-98.75 1482.95,-98.75 1482.95,-73.25 1536.95,-73.25 1536.95,-98.75"/>
<text text-anchor="middle" x="1509.95" y="-90.2" font-family="sans" font-size="9.00">sink</text>
<text text-anchor="middle" x="1509.95" y="-77.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- vorbisdec0_0x7e0674054030_src_0x7e0674054960 -->
<g id="node8" class="node">
<title>vorbisdec0_0x7e0674054030_src_0x7e0674054960</title>
<polygon fill="#ffaaaa" stroke="black" points="1623.95,-98.75 1569.95,-98.75 1569.95,-73.25 1623.95,-73.25 1623.95,-98.75"/>
<text text-anchor="middle" x="1596.95" y="-90.2" font-family="sans" font-size="9.00">src</text>
<text text-anchor="middle" x="1596.95" y="-77.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- vorbisdec0_0x7e0674054030_sink_0x7e0674054690&#45;&gt;vorbisdec0_0x7e0674054030_src_0x7e0674054960 -->
<!-- vorbisdec0_0x7e0674054030_src_0x7e0674054960&#45;&gt;queue3_0x7e067405b990_sink_0x7e067405be50 -->
<g id="edge6" class="edge">
<title>vorbisdec0_0x7e0674054030_src_0x7e0674054960&#45;&gt;queue3_0x7e067405b990_sink_0x7e067405be50</title>
<path fill="none" stroke="black" d="M1624.3,-84.48C1685.25,-80.96 1836.19,-72.26 1906.95,-68.18"/>
<polygon fill="black" stroke="black" points="1907.1,-71.67 1916.88,-67.6 1906.7,-64.69 1907.1,-71.67"/>
<text text-anchor="start" x="1666.32" y="-151.05" font-family="monospace" font-size="9.00">audio/x&#45;raw</text>
<text text-anchor="start" x="1666.32" y="-138.3" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;format: F32LE</text>
<text text-anchor="start" x="1666.32" y="-125.55" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;layout: interleaved</text>
<text text-anchor="start" x="1666.32" y="-112.8" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;rate: 48000</text>
<text text-anchor="start" x="1666.32" y="-100.05" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;channels: 2</text>
<text text-anchor="start" x="1666.32" y="-87.3" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;channel&#45;mask: 0x0000000000000003</text>
</g>
<!-- queue2_0x7e0674058fd0_sink_0x7e0674059490 -->
<g id="node9" class="node">
<title>queue2_0x7e0674058fd0_sink_0x7e0674059490</title>
<polygon fill="#aaaaff" stroke="black" points="1101.2,-108.75 1047.2,-108.75 1047.2,-83.25 1101.2,-83.25 1101.2,-108.75"/>
<text text-anchor="middle" x="1074.2" y="-100.2" font-family="sans" font-size="9.00">sink</text>
<text text-anchor="middle" x="1074.2" y="-87.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- queue2_0x7e0674058fd0_src_0x7e0674059990 -->
<g id="node10" class="node">
<title>queue2_0x7e0674058fd0_src_0x7e0674059990</title>
<polygon fill="#ffaaaa" stroke="black" points="1188.2,-108.75 1134.2,-108.75 1134.2,-83.25 1188.2,-83.25 1188.2,-108.75"/>
<text text-anchor="middle" x="1161.2" y="-100.2" font-family="sans" font-size="9.00">src</text>
<text text-anchor="middle" x="1161.2" y="-87.45" font-family="sans" font-size="9.00">[&gt;][bfb][T]</text>
</g>
<!-- queue2_0x7e0674058fd0_sink_0x7e0674059490&#45;&gt;queue2_0x7e0674058fd0_src_0x7e0674059990 -->
<!-- queue2_0x7e0674058fd0_src_0x7e0674059990&#45;&gt;vorbisdec0_0x7e0674054030_sink_0x7e0674054690 -->
<g id="edge8" class="edge">
<title>queue2_0x7e0674058fd0_src_0x7e0674059990&#45;&gt;vorbisdec0_0x7e0674054030_sink_0x7e0674054690</title>
<path fill="none" stroke="black" d="M1188.55,-95.24C1249.5,-93.48 1400.44,-89.13 1471.2,-87.09"/>
<polygon fill="black" stroke="black" points="1471.24,-90.59 1481.13,-86.8 1471.03,-83.59 1471.24,-90.59"/>
<text text-anchor="start" x="1212.2" y="-137" font-family="monospace" font-size="9.00">audio/x&#45;vorbis</text>
<text text-anchor="start" x="1212.2" y="-124.25" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;rate: 48000</text>
<text text-anchor="start" x="1212.2" y="-111.5" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;channels: 2</text>
<text text-anchor="start" x="1212.2" y="-98.75" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;streamheader: &lt; (buffer)01766f7262... &gt;</text>
</g>
<!-- _proxypad0_0x7e0674028fa0 -->
<g id="node11" class="node">
<title>_proxypad0_0x7e0674028fa0</title>
<polygon fill="#ddddff" stroke="black" points="2408.45,-287.75 2354.45,-287.75 2354.45,-262.25 2408.45,-262.25 2408.45,-287.75"/>
<text text-anchor="middle" x="2381.45" y="-279.2" font-family="sans" font-size="9.00">proxypad0</text>
<text text-anchor="middle" x="2381.45" y="-266.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- autovideosink0_actual_sink_xvimage_0x7e0674038f30_sink_0x7e06740393d0 -->
<g id="node13" class="node">
<title>autovideosink0_actual_sink_xvimage_0x7e0674038f30_sink_0x7e06740393d0</title>
<polygon fill="#aaaaff" stroke="black" points="2829.7,-262.75 2775.7,-262.75 2775.7,-237.25 2829.7,-237.25 2829.7,-262.75"/>
<text text-anchor="middle" x="2802.7" y="-254.2" font-family="sans" font-size="9.00">sink</text>
<text text-anchor="middle" x="2802.7" y="-241.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- _proxypad0_0x7e0674028fa0&#45;&gt;autovideosink0_actual_sink_xvimage_0x7e0674038f30_sink_0x7e06740393d0 -->
<g id="edge10" class="edge">
<title>_proxypad0_0x7e0674028fa0&#45;&gt;autovideosink0_actual_sink_xvimage_0x7e0674038f30_sink_0x7e06740393d0</title>
<path fill="none" stroke="black" d="M2408.68,-273.44C2480.43,-269.16 2680.18,-257.25 2763.96,-252.25"/>
<polygon fill="black" stroke="black" points="2763.93,-255.76 2773.7,-251.67 2763.51,-248.77 2763.93,-255.76"/>
<text text-anchor="start" x="2424.45" y="-404.1" font-family="monospace" font-size="9.00">video/x&#45;raw</text>
<text text-anchor="start" x="2424.45" y="-391.35" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;format: I420</text>
<text text-anchor="start" x="2424.45" y="-378.6" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;width: 1920</text>
<text text-anchor="start" x="2424.45" y="-365.85" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;height: 1080</text>
<text text-anchor="start" x="2424.45" y="-353.1" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;interlace&#45;mode: progressive</text>
<text text-anchor="start" x="2424.45" y="-340.35" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;multiview&#45;mode: mono</text>
<text text-anchor="start" x="2424.45" y="-327.6" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;multiview&#45;flags: 0:ffffffff:/right&#45;view...</text>
<text text-anchor="start" x="2424.45" y="-314.85" font-family="monospace" font-size="9.00"> &#160;pixel&#45;aspect&#45;ratio: 1/1</text>
<text text-anchor="start" x="2424.45" y="-302.1" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;chroma&#45;site: jpeg</text>
<text text-anchor="start" x="2424.45" y="-289.35" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;colorimetry: 2:4:5:0</text>
<text text-anchor="start" x="2424.45" y="-276.6" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;framerate: 24/1</text>
</g>
<!-- autovideosink0_0x7e0674027fa0_sink_0x7e0674028b60 -->
<g id="node12" class="node">
<title>autovideosink0_0x7e0674027fa0_sink_0x7e0674028b60</title>
<polygon fill="#ddddff" stroke="black" points="2408.45,-254.75 2354.45,-254.75 2354.45,-229.25 2408.45,-229.25 2408.45,-254.75"/>
<text text-anchor="middle" x="2381.45" y="-246.2" font-family="sans" font-size="9.00">sink</text>
<text text-anchor="middle" x="2381.45" y="-233.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- autovideosink0_0x7e0674027fa0_sink_0x7e0674028b60&#45;&gt;_proxypad0_0x7e0674028fa0 -->
<g id="edge9" class="edge">
<title>autovideosink0_0x7e0674027fa0_sink_0x7e0674028b60&#45;&gt;_proxypad0_0x7e0674028fa0</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M2381.45,-255.15C2381.45,-255.29 2381.45,-255.43 2381.45,-255.57"/>
<polygon fill="black" stroke="black" points="2377.95,-250.46 2381.45,-260.46 2384.95,-250.46 2377.95,-250.46"/>
</g>
<!-- queue1_0x7e067402f440_sink_0x7e067402f900 -->
<g id="node14" class="node">
<title>queue1_0x7e067402f440_sink_0x7e067402f900</title>
<polygon fill="#aaaaff" stroke="black" points="1972.7,-247.75 1918.7,-247.75 1918.7,-222.25 1972.7,-222.25 1972.7,-247.75"/>
<text text-anchor="middle" x="1945.7" y="-239.2" font-family="sans" font-size="9.00">sink</text>
<text text-anchor="middle" x="1945.7" y="-226.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- queue1_0x7e067402f440_src_0x7e067402fe00 -->
<g id="node15" class="node">
<title>queue1_0x7e067402f440_src_0x7e067402fe00</title>
<polygon fill="#ffaaaa" stroke="black" points="2059.7,-247.75 2005.7,-247.75 2005.7,-222.25 2059.7,-222.25 2059.7,-247.75"/>
<text text-anchor="middle" x="2032.7" y="-239.2" font-family="sans" font-size="9.00">src</text>
<text text-anchor="middle" x="2032.7" y="-226.45" font-family="sans" font-size="9.00">[&gt;][bfb][T]</text>
</g>
<!-- queue1_0x7e067402f440_sink_0x7e067402f900&#45;&gt;queue1_0x7e067402f440_src_0x7e067402fe00 -->
<!-- queue1_0x7e067402f440_src_0x7e067402fe00&#45;&gt;autovideosink0_0x7e0674027fa0_sink_0x7e0674028b60 -->
<g id="edge12" class="edge">
<title>queue1_0x7e067402f440_src_0x7e067402fe00&#45;&gt;autovideosink0_0x7e0674027fa0_sink_0x7e0674028b60</title>
<path fill="none" stroke="black" d="M2060.05,-235.53C2121,-236.76 2271.94,-239.81 2342.7,-241.24"/>
<polygon fill="black" stroke="black" points="2342.56,-244.74 2352.63,-241.44 2342.7,-237.74 2342.56,-244.74"/>
<text text-anchor="start" x="2083.7" y="-372.68" font-family="monospace" font-size="9.00">video/x&#45;raw</text>
<text text-anchor="start" x="2083.7" y="-359.93" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;format: I420</text>
<text text-anchor="start" x="2083.7" y="-347.18" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;width: 1920</text>
<text text-anchor="start" x="2083.7" y="-334.43" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;height: 1080</text>
<text text-anchor="start" x="2083.7" y="-321.68" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;interlace&#45;mode: progressive</text>
<text text-anchor="start" x="2083.7" y="-308.93" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;multiview&#45;mode: mono</text>
<text text-anchor="start" x="2083.7" y="-296.18" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;multiview&#45;flags: 0:ffffffff:/right&#45;view...</text>
<text text-anchor="start" x="2083.7" y="-283.43" font-family="monospace" font-size="9.00"> &#160;pixel&#45;aspect&#45;ratio: 1/1</text>
<text text-anchor="start" x="2083.7" y="-270.68" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;chroma&#45;site: jpeg</text>
<text text-anchor="start" x="2083.7" y="-257.93" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;colorimetry: 2:4:5:0</text>
<text text-anchor="start" x="2083.7" y="-245.18" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;framerate: 24/1</text>
</g>
<!-- theoradec0_0x7e06740233a0_sink_0x7e0674023790 -->
<g id="node16" class="node">
<title>theoradec0_0x7e06740233a0_sink_0x7e0674023790</title>
<polygon fill="#aaaaff" stroke="black" points="1536.95,-234.75 1482.95,-234.75 1482.95,-209.25 1536.95,-209.25 1536.95,-234.75"/>
<text text-anchor="middle" x="1509.95" y="-226.2" font-family="sans" font-size="9.00">sink</text>
<text text-anchor="middle" x="1509.95" y="-213.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- theoradec0_0x7e06740233a0_src_0x7e0674023ac0 -->
<g id="node17" class="node">
<title>theoradec0_0x7e06740233a0_src_0x7e0674023ac0</title>
<polygon fill="#ffaaaa" stroke="black" points="1623.95,-234.75 1569.95,-234.75 1569.95,-209.25 1623.95,-209.25 1623.95,-234.75"/>
<text text-anchor="middle" x="1596.95" y="-226.2" font-family="sans" font-size="9.00">src</text>
<text text-anchor="middle" x="1596.95" y="-213.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- theoradec0_0x7e06740233a0_sink_0x7e0674023790&#45;&gt;theoradec0_0x7e06740233a0_src_0x7e0674023ac0 -->
<!-- theoradec0_0x7e06740233a0_src_0x7e0674023ac0&#45;&gt;queue1_0x7e067402f440_sink_0x7e067402f900 -->
<g id="edge14" class="edge">
<title>theoradec0_0x7e06740233a0_src_0x7e0674023ac0&#45;&gt;queue1_0x7e067402f440_sink_0x7e067402f900</title>
<path fill="none" stroke="black" d="M1624.3,-222.99C1685.25,-225.27 1836.19,-230.93 1906.95,-233.58"/>
<polygon fill="black" stroke="black" points="1906.76,-237.08 1916.88,-233.96 1907.02,-230.08 1906.76,-237.08"/>
<text text-anchor="start" x="1647.95" y="-364.81" font-family="monospace" font-size="9.00">video/x&#45;raw</text>
<text text-anchor="start" x="1647.95" y="-352.06" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;format: I420</text>
<text text-anchor="start" x="1647.95" y="-339.31" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;width: 1920</text>
<text text-anchor="start" x="1647.95" y="-326.56" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;height: 1080</text>
<text text-anchor="start" x="1647.95" y="-313.81" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;interlace&#45;mode: progressive</text>
<text text-anchor="start" x="1647.95" y="-301.06" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;multiview&#45;mode: mono</text>
<text text-anchor="start" x="1647.95" y="-288.31" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;multiview&#45;flags: 0:ffffffff:/right&#45;view...</text>
<text text-anchor="start" x="1647.95" y="-275.56" font-family="monospace" font-size="9.00"> &#160;pixel&#45;aspect&#45;ratio: 1/1</text>
<text text-anchor="start" x="1647.95" y="-262.81" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;chroma&#45;site: jpeg</text>
<text text-anchor="start" x="1647.95" y="-250.06" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;colorimetry: 2:4:5:0</text>
<text text-anchor="start" x="1647.95" y="-237.31" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;framerate: 24/1</text>
</g>
<!-- queue0_0x7e067402cbd0_sink_0x7e067402d050 -->
<g id="node18" class="node">
<title>queue0_0x7e067402cbd0_sink_0x7e067402d050</title>
<polygon fill="#aaaaff" stroke="black" points="1101.2,-227.75 1047.2,-227.75 1047.2,-202.25 1101.2,-202.25 1101.2,-227.75"/>
<text text-anchor="middle" x="1074.2" y="-219.2" font-family="sans" font-size="9.00">sink</text>
<text text-anchor="middle" x="1074.2" y="-206.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- queue0_0x7e067402cbd0_src_0x7e067402d440 -->
<g id="node19" class="node">
<title>queue0_0x7e067402cbd0_src_0x7e067402d440</title>
<polygon fill="#ffaaaa" stroke="black" points="1188.2,-227.75 1134.2,-227.75 1134.2,-202.25 1188.2,-202.25 1188.2,-227.75"/>
<text text-anchor="middle" x="1161.2" y="-219.2" font-family="sans" font-size="9.00">src</text>
<text text-anchor="middle" x="1161.2" y="-206.45" font-family="sans" font-size="9.00">[&gt;][bfb][T]</text>
</g>
<!-- queue0_0x7e067402cbd0_sink_0x7e067402d050&#45;&gt;queue0_0x7e067402cbd0_src_0x7e067402d440 -->
<!-- queue0_0x7e067402cbd0_src_0x7e067402d440&#45;&gt;theoradec0_0x7e06740233a0_sink_0x7e0674023790 -->
<g id="edge16" class="edge">
<title>queue0_0x7e067402cbd0_src_0x7e067402d440&#45;&gt;theoradec0_0x7e06740233a0_sink_0x7e0674023790</title>
<path fill="none" stroke="black" d="M1188.55,-215.53C1249.5,-216.76 1400.44,-219.81 1471.2,-221.24"/>
<polygon fill="black" stroke="black" points="1471.06,-224.74 1481.13,-221.44 1471.2,-217.74 1471.06,-224.74"/>
<text text-anchor="start" x="1212.2" y="-288.93" font-family="monospace" font-size="9.00">video/x&#45;theora</text>
<text text-anchor="start" x="1212.2" y="-276.18" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;width: 1920</text>
<text text-anchor="start" x="1212.2" y="-263.43" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;height: 1080</text>
<text text-anchor="start" x="1212.2" y="-250.68" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;framerate: 24/1</text>
<text text-anchor="start" x="1212.2" y="-237.93" font-family="monospace" font-size="9.00"> &#160;pixel&#45;aspect&#45;ratio: 1/1</text>
<text text-anchor="start" x="1212.2" y="-225.18" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;streamheader: &lt; (buffer)807468656f... &gt;</text>
</g>
<!-- oggdemux0_0x5e6a306699a0_sink_0x5e6a30669ee0 -->
<g id="node20" class="node">
<title>oggdemux0_0x5e6a306699a0_sink_0x5e6a30669ee0</title>
<polygon fill="#aaaaff" stroke="black" points="660.95,-191.75 606.95,-191.75 606.95,-166.25 660.95,-166.25 660.95,-191.75"/>
<text text-anchor="middle" x="633.95" y="-183.2" font-family="sans" font-size="9.00">sink</text>
<text text-anchor="middle" x="633.95" y="-170.45" font-family="sans" font-size="9.00">[&lt;][bfb][T]</text>
</g>
<!-- oggdemux0_0x5e6a306699a0_src_135e55b4_0x7e067400c200 -->
<g id="node21" class="node">
<title>oggdemux0_0x5e6a306699a0_src_135e55b4_0x7e067400c200</title>
<polygon fill="#ffaaaa" stroke="black" points="752.45,-191.75 693.95,-191.75 693.95,-166.25 752.45,-166.25 752.45,-191.75"/>
<text text-anchor="middle" x="723.2" y="-183.2" font-family="sans" font-size="9.00">src_135e55b4</text>
<text text-anchor="middle" x="723.2" y="-170.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- oggdemux0_0x5e6a306699a0_sink_0x5e6a30669ee0&#45;&gt;oggdemux0_0x5e6a306699a0_src_135e55b4_0x7e067400c200 -->
<!-- oggdemux0_0x5e6a306699a0_src_135e55b4_0x7e067400c200&#45;&gt;queue0_0x7e067402cbd0_sink_0x7e067402d050 -->
<g id="edge18" class="edge">
<title>oggdemux0_0x5e6a306699a0_src_135e55b4_0x7e067400c200&#45;&gt;queue0_0x7e067402cbd0_sink_0x7e067402d050</title>
<path fill="none" stroke="black" d="M752.76,-181.95C815.55,-188.42 965.58,-203.9 1035.78,-211.14"/>
<polygon fill="black" stroke="black" points="1035.32,-214.61 1045.62,-212.16 1036.04,-207.65 1035.32,-214.61"/>
<text text-anchor="start" x="776.45" y="-277.72" font-family="monospace" font-size="9.00">video/x&#45;theora</text>
<text text-anchor="start" x="776.45" y="-264.97" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;width: 1920</text>
<text text-anchor="start" x="776.45" y="-252.22" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;height: 1080</text>
<text text-anchor="start" x="776.45" y="-239.47" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;framerate: 24/1</text>
<text text-anchor="start" x="776.45" y="-226.72" font-family="monospace" font-size="9.00"> &#160;pixel&#45;aspect&#45;ratio: 1/1</text>
<text text-anchor="start" x="776.45" y="-213.97" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;streamheader: &lt; (buffer)807468656f... &gt;</text>
</g>
<!-- oggdemux0_0x5e6a306699a0_src_4d0453ff_0x7e0674013fa0 -->
<g id="node22" class="node">
<title>oggdemux0_0x5e6a306699a0_src_4d0453ff_0x7e0674013fa0</title>
<polygon fill="#ffaaaa" stroke="black" points="750.2,-158.75 696.2,-158.75 696.2,-133.25 750.2,-133.25 750.2,-158.75"/>
<text text-anchor="middle" x="723.2" y="-150.2" font-family="sans" font-size="9.00">src_4d0453ff</text>
<text text-anchor="middle" x="723.2" y="-137.45" font-family="sans" font-size="9.00">[&gt;][bfb]</text>
</g>
<!-- oggdemux0_0x5e6a306699a0_src_4d0453ff_0x7e0674013fa0&#45;&gt;queue2_0x7e0674058fd0_sink_0x7e0674059490 -->
<g id="edge19" class="edge">
<title>oggdemux0_0x5e6a306699a0_src_4d0453ff_0x7e0674013fa0&#45;&gt;queue2_0x7e0674058fd0_sink_0x7e0674059490</title>
<path fill="none" stroke="black" d="M750.65,-138.77C758.87,-136.69 768,-134.57 776.45,-133 868.9,-115.8 979.07,-104.42 1035.61,-99.23"/>
<polygon fill="black" stroke="black" points="1035.69,-102.74 1045.33,-98.35 1035.06,-95.77 1035.69,-102.74"/>
<text text-anchor="start" x="776.45" y="-175.45" font-family="monospace" font-size="9.00">audio/x&#45;vorbis</text>
<text text-anchor="start" x="776.45" y="-162.7" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;rate: 48000</text>
<text text-anchor="start" x="776.45" y="-149.95" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;channels: 2</text>
<text text-anchor="start" x="776.45" y="-137.2" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;streamheader: &lt; (buffer)01766f7262... &gt;</text>
</g>
<!-- filesrc0_0x5e6a306639a0_src_0x5e6a30663cf0 -->
<g id="node23" class="node">
<title>filesrc0_0x5e6a306639a0_src_0x5e6a30663cf0</title>
<polygon fill="#ffaaaa" stroke="black" points="183.22,-191.75 129.22,-191.75 129.22,-166.25 183.22,-166.25 183.22,-191.75"/>
<text text-anchor="middle" x="156.22" y="-183.2" font-family="sans" font-size="9.00">src</text>
<text text-anchor="middle" x="156.22" y="-170.45" font-family="sans" font-size="9.00">[&lt;][bfb]</text>
</g>
<!-- filesrc0_0x5e6a306639a0_src_0x5e6a30663cf0&#45;&gt;oggdemux0_0x5e6a306699a0_sink_0x5e6a30669ee0 -->
<g id="edge20" class="edge">
<title>filesrc0_0x5e6a306639a0_src_0x5e6a30663cf0&#45;&gt;oggdemux0_0x5e6a306699a0_sink_0x5e6a30669ee0</title>
<path fill="none" stroke="black" d="M183.48,-179C263.07,-179 501.87,-179 595.09,-179"/>
<polygon fill="black" stroke="black" points="594.97,-182.5 604.97,-179 594.97,-175.5 594.97,-182.5"/>
<text text-anchor="middle" x="451.7" y="-183.2" font-family="monospace" font-size="9.00"> &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text>
<text text-anchor="start" x="476.48" y="-191.3" font-family="monospace" font-size="6.00">application/ogg</text>
<text text-anchor="start" x="476.48" y="-182.3" font-family="monospace" font-size="6.00">audio/ogg</text>
<text text-anchor="start" x="476.48" y="-173.3" font-family="monospace" font-size="6.00">video/ogg</text>
<text text-anchor="start" x="476.48" y="-164.3" font-family="monospace" font-size="6.00">application/kate</text>
<text text-anchor="middle" x="283.48" y="-177.8" font-family="monospace" font-size="6.00">ANY</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 46 KiB

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

View file

@ -48,34 +48,53 @@ gst-launch-1.0 videotestsrc ! autovideosink
gst-launch-1.0 audiotestsrc ! autoaudiosink
```
## Media pipeline[^1]
## **gst-inspect**
```bash
Factory Details:
Rank none (0)
Long-name Video test source
Klass Source/Video
Description Creates a test video stream
Author David A. Schleef <ds@schleef.org>
Documentation https://gstreamer.freedesktop.org/documentation/videotestsrc/#videotestsrc-page
Plugin Details:
Name videotestsrc
Description Creates a test video stream
Filename /usr/lib/gstreamer-1.0/libgstvideotestsrc.so
Version 1.24.9
License LGPL
Source module gst-plugins-base
Documentation https://gstreamer.freedesktop.org/documentation/videotestsrc/
Source release date 2024-10-30
Binary package Arch Linux GStreamer 1.24.9-3
Origin URL https://www.archlinux.org/
GObject
+----GInitiallyUnowned
+----GstObject
+----GstElement
+----GstBaseSrc
+----GstPushSrc
+----GstVideoTestSrc
Pad Templates:
SRC template: 'src'
Availability: Always
Capabilities:
video/x-raw
```
## Media pipeline
![*_Simple Player_*](simple-player.png){width=80%}
[^1]: [Dynamic Pipelines](https://gstreamer.freedesktop.org/documentation/tutorials/basic/dynamic-pipelines.html?gi-language=c)
## Playback pipeline
```bash
gst-play-1.0 https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_ts/master.m3u8
```
## Playback pipeline graph
![*_playbin HLS_*](playbin-hls.svg)
## Custom elements
![*_Rounded Corners_*](roundedcorners.jpg){width=58%}
```bash
gst-launch-1.0 filesrc location=bunny.mp4 ! decodebin ! videoconvert ! roundedcorners border-radius-px=100 ! videoconvert ! gtksink
```
## Why Rust?
- Codec implementations in pure Rust (Rust Audio, Xiph AV1, Symphonia)
- Things we care about
- Things to care about
* **Low cognitive overhead**
* Immutability
* Expressive type system
@ -84,7 +103,7 @@ gst-launch-1.0 filesrc location=bunny.mp4 ! decodebin ! videoconvert ! roundedco
## Why Rust?
- Bindings/abstractions over GLib/GObject and for GStreamer[^2]
- Bindings/abstractions over GLib/GObject and for GStreamer[^1]
- Provides a root for the object hierarchy tree filed in by the GStreamer library
- Gives basic reference counting, parenting functionality and locking.
- GObject
@ -99,7 +118,7 @@ gst-launch-1.0 filesrc location=bunny.mp4 ! decodebin ! videoconvert ! roundedco
- GstElement
- GstPad
[^2]: [GstObject](https://gstreamer.freedesktop.org/documentation/gstreamer/gstobject.html?gi-language=c)
[^1]: [GstObject](https://gstreamer.freedesktop.org/documentation/gstreamer/gstobject.html?gi-language=c)
## Why immutability and types matter?
@ -210,9 +229,86 @@ For more information about this error, try `rustc --explain E0596`.
}
```
## GStreamer & Rust
## Code
- Some stats[^3]
```rust
let src = gst::ElementFactory::make("filesrc")
.property("location", "sample.ogv")
.build()
.unwrap();
let demux = gst::ElementFactory::make("oggdemux").build().unwrap();
let pipeline_weak = pipeline.downgrade();
demux.connect("pad-added", false, move |args| {
let pipeline = match pipeline_weak.upgrade() {
Some(self_) => self_,
None => return None,
};
let pad = args[1]
.get::<gst::Pad>()
.expect("Second argument to demux pad-added must be pad");
```
## Code
```rust
if let Some(caps) = pad.current_caps() {
let s = caps.structure(0).unwrap();
let (decoder, sink) = if s.name().starts_with("video") {
let decoder = gst::ElementFactory::make("theoradec").build().unwrap();
let sink = gst::ElementFactory::make("autovideosink").build().unwrap();
(decoder, sink)
} else {
let decoder = gst::ElementFactory::make("vorbisdec").build().unwrap();
let sink = gst::ElementFactory::make("autoaudiosink").build().unwrap();
(decoder, sink)
};
let queue1 = gst::ElementFactory::make("queue").build().unwrap();
let queue2 = gst::ElementFactory::make("queue").build().unwrap();
```
## Code
```rust
pipeline
.add_many([&queue1, &decoder, &queue2, &sink])
.unwrap();
let sinkpad = queue1.static_pad("sink").unwrap();
pad.link(&sinkpad).unwrap();
queue1.link(&decoder).unwrap();
decoder.link(&queue2).unwrap();
queue2.link(&sink).unwrap();
queue1.sync_state_with_parent().unwrap();
decoder.sync_state_with_parent().unwrap();
queue2.sync_state_with_parent().unwrap();
sink.sync_state_with_parent().unwrap();
}
```
## Code
```rust
None
});
pipeline.add_many([&src, &demux]).unwrap();
src.link(&demux).unwrap();
```
## Media pipeline
![*_OGG_Demux_*](ogg-demux-pipeline.svg)
## Some stats
- **gstreamer-rs** & **gst-plugins-rs**[^2]
- gstreamer-rs: ~2700 commits, gst-plugins-rs: ~2600 commits
- gstreamer-rs: ~85 contributors, gst-plugins-rs: ~110 contributors
- gst-plugins-rs: ~ +180k SLOC / -37k SLOC
@ -221,22 +317,24 @@ For more information about this error, try `rustc --explain E0596`.
- 1.22 cycle: ~33% commits / MRs in Rust modules
- 1.24 cycle: ~25% commits / MRs in Rust modules
[^3]: [GStreamer & Rust: What has happened over the last 5 years](https://gstconf.ubicast.tv/videos/gstreamer-rust-what-has-happened-over-the-last-5-years_f8qxhpuzi9/)
[^2]: [GStreamer & Rust: What has happened over the last 5 years](https://gstconf.ubicast.tv/videos/gstreamer-rust-what-has-happened-over-the-last-5-years_f8qxhpuzi9/)
## Resources
- [Dynamic Pipelines](https://gstreamer.freedesktop.org/documentation/tutorials/basic/dynamic-pipelines.html?gi-language=c)
- [GObject subclassing in Rust ](https://www.youtube.com/watch?v=TSf3rVyv7c8)
- [GStreamer bindings for Rust](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs)
- [Rust GStreamer Plugins](https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs)
- [Using GStreamer](https://www.youtube.com/watch?v=ZphadMGufY8)
- [How to get started with GStreamer](https://www.youtube.com/watch?v=OkOsm9FyzdM&t=2s)
- [GStreamer for your backend services](https://asymptotic.io/blog/gstreamer-for-your-backend-services/)
- [OGG demultiplexing Rust sample code](https://gitlab.freedesktop.org/SanchayanMaity/ogg-demux)
## Questions?
- Rust Bangalore
* Meetup: https://hasgeek.com/rustbangalore
* Telegram: t.me/RustIndia
* Meetup: [https://hasgeek.com/rustbangalore](https://hasgeek.com/rustbangalore)
* Telegram: [https://t.me/RustIndia](https://t.me/RustIndia)
- Reach out on
* email:

View file

@ -1,7 +1,6 @@
#import "@preview/diatypst:0.2.0": *
#show: slides.with(
title: "Multimedia using Rust & GStreamer",
authors: ("Sanchayan Maity"),
ratio: 16/9,
layout: "large",
toc: false,