mbox series

[v10,0/4] Media Device Allocator API

Message ID cover.1548360791.git.shuah@kernel.org (mailing list archive)
Headers show
Series Media Device Allocator API | expand

Message

Shuah Jan. 24, 2019, 8:32 p.m. UTC
Media Device Allocator API to allows multiple drivers share a media device.
This API solves a very common use-case for media devices where one physical
device (an USB stick) provides both audio and video. When such media device
exposes a standard USB Audio class, a proprietary Video class, two or more
independent drivers will share a single physical USB bridge. In such cases,
it is necessary to coordinate access to the shared resource.

Using this API, drivers can allocate a media device with the shared struct
device as the key. Once the media device is allocated by a driver, other
drivers can get a reference to it. The media device is released when all
the references are released.

- This patch series is tested on 5.0-rc3 and addresses comments on
  v9 series from Hans Verkuil.
- v9 was tested on 4.20-rc6.
- Tested sharing resources with kaffeine, vlc, xawtv, tvtime, and
  arecord. When analog is streaming, digital and audio user-space
  applications detect that the tuner is busy and exit. When digital
  is streaming, analog and audio applications detect that the tuner is
  busy and exit. When arecord is owns the tuner, digital and analog
  detect that the tuner is busy and exit.
- Tested media device allocator API with bind/unbind testing on
  snd-usb-audio and au0828 drivers to make sure /dev/mediaX is released
  only when the last driver is unbound.
- Addressed review comments from Hans on the RFC v8 (rebased on 4.19)
- Updated change log to describe the use-case more clearly.
- No changes to 0001,0002 code since the v7 referenced below.
- 0003 is a new patch to enable ALSA defines that have been
  disabled for kernel between 4.9 and 4.19.
- Minor merge conflict resolution in 0004.
- Added SPDX to new files.

Changes since v9:
- Patch 1: Fix mutex assert warning from find_module() calls. This
  code was written before the change to find_module() that requires
  callers to hold module_mutex. I missed this during my testing on
  4.20-rc6. Hans Verkuil reported the problem.
- Patch 4: sound/usb: Initializes all the entities it can before
  registering the device based on comments from Hans Verkuil
- Carried Reviewed-by tag from Takashi Iwai for the sound from v9.
- No changes to Patches 2 and 3.

References:
https://lkml.org/lkml/2018/11/2/169
https://www.mail-archive.com/linux-media@vger.kernel.org/msg105854.html

Shuah Khan (4):
  media: Media Device Allocator API
  media: change au0828 to use Media Device Allocator API
  media: media.h: Enable ALSA MEDIA_INTF_T* interface types
  sound/usb: Use Media Controller API to share media resources

 Documentation/media/kapi/mc-core.rst   |  41 ++++
 drivers/media/Makefile                 |   4 +
 drivers/media/media-dev-allocator.c    | 144 +++++++++++
 drivers/media/usb/au0828/au0828-core.c |  12 +-
 drivers/media/usb/au0828/au0828.h      |   1 +
 include/media/media-dev-allocator.h    |  53 ++++
 include/uapi/linux/media.h             |  25 +-
 sound/usb/Kconfig                      |   4 +
 sound/usb/Makefile                     |   2 +
 sound/usb/card.c                       |  14 ++
 sound/usb/card.h                       |   3 +
 sound/usb/media.c                      | 327 +++++++++++++++++++++++++
 sound/usb/media.h                      |  74 ++++++
 sound/usb/mixer.h                      |   3 +
 sound/usb/pcm.c                        |  29 ++-
 sound/usb/quirks-table.h               |   1 +
 sound/usb/stream.c                     |   2 +
 sound/usb/usbaudio.h                   |   6 +
 18 files changed, 723 insertions(+), 22 deletions(-)
 create mode 100644 drivers/media/media-dev-allocator.c
 create mode 100644 include/media/media-dev-allocator.h
 create mode 100644 sound/usb/media.c
 create mode 100644 sound/usb/media.h

Comments

Sakari Ailus Jan. 25, 2019, 3:28 p.m. UTC | #1
Hi Shuah,

On Thu, Jan 24, 2019 at 01:32:37PM -0700, Shuah Khan wrote:
> Media Device Allocator API to allows multiple drivers share a media device.
> This API solves a very common use-case for media devices where one physical
> device (an USB stick) provides both audio and video. When such media device
> exposes a standard USB Audio class, a proprietary Video class, two or more
> independent drivers will share a single physical USB bridge. In such cases,
> it is necessary to coordinate access to the shared resource.
> 
> Using this API, drivers can allocate a media device with the shared struct
> device as the key. Once the media device is allocated by a driver, other
> drivers can get a reference to it. The media device is released when all
> the references are released.

Thanks for the update. I have to apologise I haven't ended up reviewing the
set for some time. After taking a look at the current version, I'm happy to
see that a number of issues recognised during earlier review rounds have
been addressed.

Would you happen to have a media graph (media-ctl --print-dot and media-ctl
-p) from the device? That'd help understanding the device a bit better for
those who are not familiar with it.

> 
> - This patch series is tested on 5.0-rc3 and addresses comments on
>   v9 series from Hans Verkuil.
> - v9 was tested on 4.20-rc6.
> - Tested sharing resources with kaffeine, vlc, xawtv, tvtime, and
>   arecord. When analog is streaming, digital and audio user-space
>   applications detect that the tuner is busy and exit. When digital
>   is streaming, analog and audio applications detect that the tuner is
>   busy and exit. When arecord is owns the tuner, digital and analog
>   detect that the tuner is busy and exit.
> - Tested media device allocator API with bind/unbind testing on
>   snd-usb-audio and au0828 drivers to make sure /dev/mediaX is released
>   only when the last driver is unbound.
> - Addressed review comments from Hans on the RFC v8 (rebased on 4.19)
> - Updated change log to describe the use-case more clearly.
> - No changes to 0001,0002 code since the v7 referenced below.
> - 0003 is a new patch to enable ALSA defines that have been
>   disabled for kernel between 4.9 and 4.19.
> - Minor merge conflict resolution in 0004.
> - Added SPDX to new files.
> 
> Changes since v9:
> - Patch 1: Fix mutex assert warning from find_module() calls. This
>   code was written before the change to find_module() that requires
>   callers to hold module_mutex. I missed this during my testing on
>   4.20-rc6. Hans Verkuil reported the problem.
> - Patch 4: sound/usb: Initializes all the entities it can before
>   registering the device based on comments from Hans Verkuil
> - Carried Reviewed-by tag from Takashi Iwai for the sound from v9.
> - No changes to Patches 2 and 3.
> 
> References:
> https://lkml.org/lkml/2018/11/2/169
> https://www.mail-archive.com/linux-media@vger.kernel.org/msg105854.html
> 
> Shuah Khan (4):
>   media: Media Device Allocator API
>   media: change au0828 to use Media Device Allocator API
>   media: media.h: Enable ALSA MEDIA_INTF_T* interface types
>   sound/usb: Use Media Controller API to share media resources
> 
>  Documentation/media/kapi/mc-core.rst   |  41 ++++
>  drivers/media/Makefile                 |   4 +
>  drivers/media/media-dev-allocator.c    | 144 +++++++++++
>  drivers/media/usb/au0828/au0828-core.c |  12 +-
>  drivers/media/usb/au0828/au0828.h      |   1 +
>  include/media/media-dev-allocator.h    |  53 ++++
>  include/uapi/linux/media.h             |  25 +-
>  sound/usb/Kconfig                      |   4 +
>  sound/usb/Makefile                     |   2 +
>  sound/usb/card.c                       |  14 ++
>  sound/usb/card.h                       |   3 +
>  sound/usb/media.c                      | 327 +++++++++++++++++++++++++
>  sound/usb/media.h                      |  74 ++++++
>  sound/usb/mixer.h                      |   3 +
>  sound/usb/pcm.c                        |  29 ++-
>  sound/usb/quirks-table.h               |   1 +
>  sound/usb/stream.c                     |   2 +
>  sound/usb/usbaudio.h                   |   6 +
>  18 files changed, 723 insertions(+), 22 deletions(-)
>  create mode 100644 drivers/media/media-dev-allocator.c
>  create mode 100644 include/media/media-dev-allocator.h
>  create mode 100644 sound/usb/media.c
>  create mode 100644 sound/usb/media.h
>
Shuah Jan. 26, 2019, 12:19 a.m. UTC | #2
Hi Sakari,

On 1/25/19 8:28 AM, Sakari Ailus wrote:
> Hi Shuah,
> 
> On Thu, Jan 24, 2019 at 01:32:37PM -0700, Shuah Khan wrote:
>> Media Device Allocator API to allows multiple drivers share a media device.
>> This API solves a very common use-case for media devices where one physical
>> device (an USB stick) provides both audio and video. When such media device
>> exposes a standard USB Audio class, a proprietary Video class, two or more
>> independent drivers will share a single physical USB bridge. In such cases,
>> it is necessary to coordinate access to the shared resource.
>>
>> Using this API, drivers can allocate a media device with the shared struct
>> device as the key. Once the media device is allocated by a driver, other
>> drivers can get a reference to it. The media device is released when all
>> the references are released.
> 
> Thanks for the update. I have to apologise I haven't ended up reviewing the
> set for some time. After taking a look at the current version, I'm happy to
> see that a number of issues recognised during earlier review rounds have
> been addressed.
> 
> Would you happen to have a media graph (media-ctl --print-dot and media-ctl
> -p) from the device? That'd help understanding the device a bit better for
> those who are not familiar with it.
> 

Please see the attached files for the below. It came in very handy
for testing partial graphs as I did bind and unbind of the drivers
in this mix.

media-ctl --print-dot and
media-ctl --print-topology

thanks,
-- Shuah
Media controller API version 5.0.0

Media device information
------------------------
driver          au0828
model           WinTV HVR-950
serial          4035198866
bus info        usb-0000:00:1a.0-1.4
hw revision     0x5
driver version  5.0.0

Device topology
- entity 1: au8522 13-0047 (3 pads, 6 links)
            type V4L2 subdev subtype Decoder flags 0
	pad0: Sink
		<- "Xceive XC5000":1 []
		<- "Composite":0 []
		<- "S-Video":0 []
	pad1: Source
		-> "au0828a video":0 [ENABLED]
		-> "au0828a vbi":0 [ENABLED]
	pad2: Source
		-> "USB Mixer":0 [ENABLED]

- entity 5: Xceive XC5000 (3 pads, 3 links)
            type V4L2 subdev subtype Tuner flags 0
	pad0: Sink
		-> "Auvitek AU8522 QAM/8VSB Fronten":0 []
		<- "Television":0 [ENABLED]
	pad1: Source
		-> "au8522 13-0047":0 []
	pad2: Source

- entity 9: Television (1 pad, 1 link)
            type Node subtype Unknown flags 2
	pad0: Source
		-> "Xceive XC5000":0 [ENABLED]

- entity 11: Composite (1 pad, 1 link)
             type Node subtype Unknown flags 2
	pad0: Source
		-> "au8522 13-0047":0 []

- entity 13: S-Video (1 pad, 1 link)
             type Node subtype Unknown flags 2
	pad0: Source
		-> "au8522 13-0047":0 []

- entity 15: au0828a video (1 pad, 1 link)
             type Node subtype V4L flags 0
             device node name /dev/video0
	pad0: Sink
		<- "au8522 13-0047":1 [ENABLED]

- entity 19: au0828a vbi (1 pad, 1 link)
             type Node subtype Unknown flags 0
             device node name /dev/vbi0
	pad0: Sink
		<- "au8522 13-0047":1 [ENABLED]

- entity 35: Auvitek AU8522 QAM/8VSB Fronten (2 pads, 2 links)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "Xceive XC5000":0 []
	pad1: Source
		-> "dvb-demux":0 [ENABLED]

- entity 40: demux-tsout #0 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":1 []

- entity 42: demux-tsout #1 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":2 []

- entity 44: demux-tsout #2 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":3 []

- entity 46: demux-tsout #3 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":4 []

- entity 48: demux-tsout #4 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":5 []

- entity 50: demux-tsout #5 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":6 []

- entity 52: demux-tsout #6 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":7 []

- entity 54: demux-tsout #7 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":8 []

- entity 56: demux-tsout #8 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":9 []

- entity 58: demux-tsout #9 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":10 []

- entity 60: demux-tsout #10 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":11 []

- entity 62: demux-tsout #11 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":12 []

- entity 64: demux-tsout #12 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":13 []

- entity 66: demux-tsout #13 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":14 []

- entity 68: demux-tsout #14 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":15 []

- entity 70: demux-tsout #15 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":16 []

- entity 72: demux-tsout #16 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":17 []

- entity 74: demux-tsout #17 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":18 []

- entity 76: demux-tsout #18 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":19 []

- entity 78: demux-tsout #19 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":20 []

- entity 80: demux-tsout #20 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":21 []

- entity 82: demux-tsout #21 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":22 []

- entity 84: demux-tsout #22 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":23 []

- entity 86: demux-tsout #23 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":24 []

- entity 88: demux-tsout #24 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":25 []

- entity 90: demux-tsout #25 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":26 []

- entity 92: demux-tsout #26 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":27 []

- entity 94: demux-tsout #27 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":28 []

- entity 96: demux-tsout #28 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":29 []

- entity 98: demux-tsout #29 (1 pad, 1 link)
             type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":30 []

- entity 100: demux-tsout #30 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":31 []

- entity 102: demux-tsout #31 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":32 []

- entity 104: demux-tsout #32 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":33 []

- entity 106: demux-tsout #33 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":34 []

- entity 108: demux-tsout #34 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":35 []

- entity 110: demux-tsout #35 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":36 []

- entity 112: demux-tsout #36 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":37 []

- entity 114: demux-tsout #37 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":38 []

- entity 116: demux-tsout #38 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":39 []

- entity 118: demux-tsout #39 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":40 []

- entity 120: demux-tsout #40 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":41 []

- entity 122: demux-tsout #41 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":42 []

- entity 124: demux-tsout #42 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":43 []

- entity 126: demux-tsout #43 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":44 []

- entity 128: demux-tsout #44 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":45 []

- entity 130: demux-tsout #45 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":46 []

- entity 132: demux-tsout #46 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":47 []

- entity 134: demux-tsout #47 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":48 []

- entity 136: demux-tsout #48 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":49 []

- entity 138: demux-tsout #49 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":50 []

- entity 140: demux-tsout #50 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":51 []

- entity 142: demux-tsout #51 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":52 []

- entity 144: demux-tsout #52 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":53 []

- entity 146: demux-tsout #53 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":54 []

- entity 148: demux-tsout #54 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":55 []

- entity 150: demux-tsout #55 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":56 []

- entity 152: demux-tsout #56 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":57 []

- entity 154: demux-tsout #57 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":58 []

- entity 156: demux-tsout #58 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":59 []

- entity 158: demux-tsout #59 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":60 []

- entity 160: demux-tsout #60 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":61 []

- entity 162: demux-tsout #61 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":62 []

- entity 164: demux-tsout #62 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":63 []

- entity 166: demux-tsout #63 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":64 []

- entity 168: demux-tsout #64 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":65 []

- entity 170: demux-tsout #65 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":66 []

- entity 172: demux-tsout #66 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":67 []

- entity 174: demux-tsout #67 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":68 []

- entity 176: demux-tsout #68 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":69 []

- entity 178: demux-tsout #69 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":70 []

- entity 180: demux-tsout #70 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":71 []

- entity 182: demux-tsout #71 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":72 []

- entity 184: demux-tsout #72 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":73 []

- entity 186: demux-tsout #73 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":74 []

- entity 188: demux-tsout #74 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":75 []

- entity 190: demux-tsout #75 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":76 []

- entity 192: demux-tsout #76 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":77 []

- entity 194: demux-tsout #77 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":78 []

- entity 196: demux-tsout #78 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":79 []

- entity 198: demux-tsout #79 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":80 []

- entity 200: demux-tsout #80 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":81 []

- entity 202: demux-tsout #81 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":82 []

- entity 204: demux-tsout #82 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":83 []

- entity 206: demux-tsout #83 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":84 []

- entity 208: demux-tsout #84 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":85 []

- entity 210: demux-tsout #85 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":86 []

- entity 212: demux-tsout #86 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":87 []

- entity 214: demux-tsout #87 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":88 []

- entity 216: demux-tsout #88 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":89 []

- entity 218: demux-tsout #89 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":90 []

- entity 220: demux-tsout #90 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":91 []

- entity 222: demux-tsout #91 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":92 []

- entity 224: demux-tsout #92 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":93 []

- entity 226: demux-tsout #93 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":94 []

- entity 228: demux-tsout #94 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":95 []

- entity 230: demux-tsout #95 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":96 []

- entity 232: demux-tsout #96 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":97 []

- entity 234: demux-tsout #97 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":98 []

- entity 236: demux-tsout #98 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":99 []

- entity 238: demux-tsout #99 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":100 []

- entity 240: demux-tsout #100 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":101 []

- entity 242: demux-tsout #101 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":102 []

- entity 244: demux-tsout #102 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":103 []

- entity 246: demux-tsout #103 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":104 []

- entity 248: demux-tsout #104 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":105 []

- entity 250: demux-tsout #105 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":106 []

- entity 252: demux-tsout #106 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":107 []

- entity 254: demux-tsout #107 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":108 []

- entity 256: demux-tsout #108 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":109 []

- entity 258: demux-tsout #109 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":110 []

- entity 260: demux-tsout #110 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":111 []

- entity 262: demux-tsout #111 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":112 []

- entity 264: demux-tsout #112 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":113 []

- entity 266: demux-tsout #113 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":114 []

- entity 268: demux-tsout #114 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":115 []

- entity 270: demux-tsout #115 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":116 []

- entity 272: demux-tsout #116 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":117 []

- entity 274: demux-tsout #117 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":118 []

- entity 276: demux-tsout #118 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":119 []

- entity 278: demux-tsout #119 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":120 []

- entity 280: demux-tsout #120 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":121 []

- entity 282: demux-tsout #121 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":122 []

- entity 284: demux-tsout #122 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":123 []

- entity 286: demux-tsout #123 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":124 []

- entity 288: demux-tsout #124 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":125 []

- entity 290: demux-tsout #125 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":126 []

- entity 292: demux-tsout #126 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":127 []

- entity 294: demux-tsout #127 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":128 []

- entity 296: demux-tsout #128 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":129 []

- entity 298: demux-tsout #129 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":130 []

- entity 300: demux-tsout #130 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":131 []

- entity 302: demux-tsout #131 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":132 []

- entity 304: demux-tsout #132 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":133 []

- entity 306: demux-tsout #133 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":134 []

- entity 308: demux-tsout #134 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":135 []

- entity 310: demux-tsout #135 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":136 []

- entity 312: demux-tsout #136 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":137 []

- entity 314: demux-tsout #137 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":138 []

- entity 316: demux-tsout #138 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":139 []

- entity 318: demux-tsout #139 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":140 []

- entity 320: demux-tsout #140 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":141 []

- entity 322: demux-tsout #141 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":142 []

- entity 324: demux-tsout #142 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":143 []

- entity 326: demux-tsout #143 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":144 []

- entity 328: demux-tsout #144 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":145 []

- entity 330: demux-tsout #145 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":146 []

- entity 332: demux-tsout #146 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":147 []

- entity 334: demux-tsout #147 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":148 []

- entity 336: demux-tsout #148 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":149 []

- entity 338: demux-tsout #149 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":150 []

- entity 340: demux-tsout #150 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":151 []

- entity 342: demux-tsout #151 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":152 []

- entity 344: demux-tsout #152 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":153 []

- entity 346: demux-tsout #153 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":154 []

- entity 348: demux-tsout #154 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":155 []

- entity 350: demux-tsout #155 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":156 []

- entity 352: demux-tsout #156 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":157 []

- entity 354: demux-tsout #157 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":158 []

- entity 356: demux-tsout #158 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":159 []

- entity 358: demux-tsout #159 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":160 []

- entity 360: demux-tsout #160 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":161 []

- entity 362: demux-tsout #161 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":162 []

- entity 364: demux-tsout #162 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":163 []

- entity 366: demux-tsout #163 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":164 []

- entity 368: demux-tsout #164 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":165 []

- entity 370: demux-tsout #165 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":166 []

- entity 372: demux-tsout #166 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":167 []

- entity 374: demux-tsout #167 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":168 []

- entity 376: demux-tsout #168 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":169 []

- entity 378: demux-tsout #169 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":170 []

- entity 380: demux-tsout #170 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":171 []

- entity 382: demux-tsout #171 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":172 []

- entity 384: demux-tsout #172 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":173 []

- entity 386: demux-tsout #173 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":174 []

- entity 388: demux-tsout #174 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":175 []

- entity 390: demux-tsout #175 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":176 []

- entity 392: demux-tsout #176 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":177 []

- entity 394: demux-tsout #177 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":178 []

- entity 396: demux-tsout #178 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":179 []

- entity 398: demux-tsout #179 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":180 []

- entity 400: demux-tsout #180 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":181 []

- entity 402: demux-tsout #181 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":182 []

- entity 404: demux-tsout #182 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":183 []

- entity 406: demux-tsout #183 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":184 []

- entity 408: demux-tsout #184 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":185 []

- entity 410: demux-tsout #185 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":186 []

- entity 412: demux-tsout #186 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":187 []

- entity 414: demux-tsout #187 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":188 []

- entity 416: demux-tsout #188 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":189 []

- entity 418: demux-tsout #189 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":190 []

- entity 420: demux-tsout #190 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":191 []

- entity 422: demux-tsout #191 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":192 []

- entity 424: demux-tsout #192 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":193 []

- entity 426: demux-tsout #193 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":194 []

- entity 428: demux-tsout #194 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":195 []

- entity 430: demux-tsout #195 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":196 []

- entity 432: demux-tsout #196 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":197 []

- entity 434: demux-tsout #197 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":198 []

- entity 436: demux-tsout #198 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":199 []

- entity 438: demux-tsout #199 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":200 []

- entity 440: demux-tsout #200 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":201 []

- entity 442: demux-tsout #201 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":202 []

- entity 444: demux-tsout #202 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":203 []

- entity 446: demux-tsout #203 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":204 []

- entity 448: demux-tsout #204 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":205 []

- entity 450: demux-tsout #205 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":206 []

- entity 452: demux-tsout #206 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":207 []

- entity 454: demux-tsout #207 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":208 []

- entity 456: demux-tsout #208 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":209 []

- entity 458: demux-tsout #209 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":210 []

- entity 460: demux-tsout #210 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":211 []

- entity 462: demux-tsout #211 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":212 []

- entity 464: demux-tsout #212 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":213 []

- entity 466: demux-tsout #213 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":214 []

- entity 468: demux-tsout #214 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":215 []

- entity 470: demux-tsout #215 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":216 []

- entity 472: demux-tsout #216 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":217 []

- entity 474: demux-tsout #217 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":218 []

- entity 476: demux-tsout #218 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":219 []

- entity 478: demux-tsout #219 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":220 []

- entity 480: demux-tsout #220 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":221 []

- entity 482: demux-tsout #221 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":222 []

- entity 484: demux-tsout #222 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":223 []

- entity 486: demux-tsout #223 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":224 []

- entity 488: demux-tsout #224 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":225 []

- entity 490: demux-tsout #225 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":226 []

- entity 492: demux-tsout #226 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":227 []

- entity 494: demux-tsout #227 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":228 []

- entity 496: demux-tsout #228 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":229 []

- entity 498: demux-tsout #229 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":230 []

- entity 500: demux-tsout #230 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":231 []

- entity 502: demux-tsout #231 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":232 []

- entity 504: demux-tsout #232 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":233 []

- entity 506: demux-tsout #233 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":234 []

- entity 508: demux-tsout #234 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":235 []

- entity 510: demux-tsout #235 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":236 []

- entity 512: demux-tsout #236 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":237 []

- entity 514: demux-tsout #237 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":238 []

- entity 516: demux-tsout #238 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":239 []

- entity 518: demux-tsout #239 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":240 []

- entity 520: demux-tsout #240 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":241 []

- entity 522: demux-tsout #241 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":242 []

- entity 524: demux-tsout #242 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":243 []

- entity 526: demux-tsout #243 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":244 []

- entity 528: demux-tsout #244 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":245 []

- entity 530: demux-tsout #245 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":246 []

- entity 532: demux-tsout #246 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":247 []

- entity 534: demux-tsout #247 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":248 []

- entity 536: demux-tsout #248 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":249 []

- entity 538: demux-tsout #249 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":250 []

- entity 540: demux-tsout #250 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":251 []

- entity 542: demux-tsout #251 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":252 []

- entity 544: demux-tsout #252 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":253 []

- entity 546: demux-tsout #253 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":254 []

- entity 548: demux-tsout #254 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":255 []

- entity 550: demux-tsout #255 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":256 []

- entity 552: dvb-demux (257 pads, 513 links)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "Auvitek AU8522 QAM/8VSB Fronten":1 [ENABLED]
	pad1: Source
		-> "demux-tsout #0":0 []
		-> "dvr-tsout #0":0 []
	pad2: Source
		-> "demux-tsout #1":0 []
		-> "dvr-tsout #1":0 []
	pad3: Source
		-> "demux-tsout #2":0 []
		-> "dvr-tsout #2":0 []
	pad4: Source
		-> "demux-tsout #3":0 []
		-> "dvr-tsout #3":0 []
	pad5: Source
		-> "demux-tsout #4":0 []
		-> "dvr-tsout #4":0 []
	pad6: Source
		-> "demux-tsout #5":0 []
		-> "dvr-tsout #5":0 []
	pad7: Source
		-> "demux-tsout #6":0 []
		-> "dvr-tsout #6":0 []
	pad8: Source
		-> "demux-tsout #7":0 []
		-> "dvr-tsout #7":0 []
	pad9: Source
		-> "demux-tsout #8":0 []
		-> "dvr-tsout #8":0 []
	pad10: Source
		-> "demux-tsout #9":0 []
		-> "dvr-tsout #9":0 []
	pad11: Source
		-> "demux-tsout #10":0 []
		-> "dvr-tsout #10":0 []
	pad12: Source
		-> "demux-tsout #11":0 []
		-> "dvr-tsout #11":0 []
	pad13: Source
		-> "demux-tsout #12":0 []
		-> "dvr-tsout #12":0 []
	pad14: Source
		-> "demux-tsout #13":0 []
		-> "dvr-tsout #13":0 []
	pad15: Source
		-> "demux-tsout #14":0 []
		-> "dvr-tsout #14":0 []
	pad16: Source
		-> "demux-tsout #15":0 []
		-> "dvr-tsout #15":0 []
	pad17: Source
		-> "demux-tsout #16":0 []
		-> "dvr-tsout #16":0 []
	pad18: Source
		-> "demux-tsout #17":0 []
		-> "dvr-tsout #17":0 []
	pad19: Source
		-> "demux-tsout #18":0 []
		-> "dvr-tsout #18":0 []
	pad20: Source
		-> "demux-tsout #19":0 []
		-> "dvr-tsout #19":0 []
	pad21: Source
		-> "demux-tsout #20":0 []
		-> "dvr-tsout #20":0 []
	pad22: Source
		-> "demux-tsout #21":0 []
		-> "dvr-tsout #21":0 []
	pad23: Source
		-> "demux-tsout #22":0 []
		-> "dvr-tsout #22":0 []
	pad24: Source
		-> "demux-tsout #23":0 []
		-> "dvr-tsout #23":0 []
	pad25: Source
		-> "demux-tsout #24":0 []
		-> "dvr-tsout #24":0 []
	pad26: Source
		-> "demux-tsout #25":0 []
		-> "dvr-tsout #25":0 []
	pad27: Source
		-> "demux-tsout #26":0 []
		-> "dvr-tsout #26":0 []
	pad28: Source
		-> "demux-tsout #27":0 []
		-> "dvr-tsout #27":0 []
	pad29: Source
		-> "demux-tsout #28":0 []
		-> "dvr-tsout #28":0 []
	pad30: Source
		-> "demux-tsout #29":0 []
		-> "dvr-tsout #29":0 []
	pad31: Source
		-> "demux-tsout #30":0 []
		-> "dvr-tsout #30":0 []
	pad32: Source
		-> "demux-tsout #31":0 []
		-> "dvr-tsout #31":0 []
	pad33: Source
		-> "demux-tsout #32":0 []
		-> "dvr-tsout #32":0 []
	pad34: Source
		-> "demux-tsout #33":0 []
		-> "dvr-tsout #33":0 []
	pad35: Source
		-> "demux-tsout #34":0 []
		-> "dvr-tsout #34":0 []
	pad36: Source
		-> "demux-tsout #35":0 []
		-> "dvr-tsout #35":0 []
	pad37: Source
		-> "demux-tsout #36":0 []
		-> "dvr-tsout #36":0 []
	pad38: Source
		-> "demux-tsout #37":0 []
		-> "dvr-tsout #37":0 []
	pad39: Source
		-> "demux-tsout #38":0 []
		-> "dvr-tsout #38":0 []
	pad40: Source
		-> "demux-tsout #39":0 []
		-> "dvr-tsout #39":0 []
	pad41: Source
		-> "demux-tsout #40":0 []
		-> "dvr-tsout #40":0 []
	pad42: Source
		-> "demux-tsout #41":0 []
		-> "dvr-tsout #41":0 []
	pad43: Source
		-> "demux-tsout #42":0 []
		-> "dvr-tsout #42":0 []
	pad44: Source
		-> "demux-tsout #43":0 []
		-> "dvr-tsout #43":0 []
	pad45: Source
		-> "demux-tsout #44":0 []
		-> "dvr-tsout #44":0 []
	pad46: Source
		-> "demux-tsout #45":0 []
		-> "dvr-tsout #45":0 []
	pad47: Source
		-> "demux-tsout #46":0 []
		-> "dvr-tsout #46":0 []
	pad48: Source
		-> "demux-tsout #47":0 []
		-> "dvr-tsout #47":0 []
	pad49: Source
		-> "demux-tsout #48":0 []
		-> "dvr-tsout #48":0 []
	pad50: Source
		-> "demux-tsout #49":0 []
		-> "dvr-tsout #49":0 []
	pad51: Source
		-> "demux-tsout #50":0 []
		-> "dvr-tsout #50":0 []
	pad52: Source
		-> "demux-tsout #51":0 []
		-> "dvr-tsout #51":0 []
	pad53: Source
		-> "demux-tsout #52":0 []
		-> "dvr-tsout #52":0 []
	pad54: Source
		-> "demux-tsout #53":0 []
		-> "dvr-tsout #53":0 []
	pad55: Source
		-> "demux-tsout #54":0 []
		-> "dvr-tsout #54":0 []
	pad56: Source
		-> "demux-tsout #55":0 []
		-> "dvr-tsout #55":0 []
	pad57: Source
		-> "demux-tsout #56":0 []
		-> "dvr-tsout #56":0 []
	pad58: Source
		-> "demux-tsout #57":0 []
		-> "dvr-tsout #57":0 []
	pad59: Source
		-> "demux-tsout #58":0 []
		-> "dvr-tsout #58":0 []
	pad60: Source
		-> "demux-tsout #59":0 []
		-> "dvr-tsout #59":0 []
	pad61: Source
		-> "demux-tsout #60":0 []
		-> "dvr-tsout #60":0 []
	pad62: Source
		-> "demux-tsout #61":0 []
		-> "dvr-tsout #61":0 []
	pad63: Source
		-> "demux-tsout #62":0 []
		-> "dvr-tsout #62":0 []
	pad64: Source
		-> "demux-tsout #63":0 []
		-> "dvr-tsout #63":0 []
	pad65: Source
		-> "demux-tsout #64":0 []
		-> "dvr-tsout #64":0 []
	pad66: Source
		-> "demux-tsout #65":0 []
		-> "dvr-tsout #65":0 []
	pad67: Source
		-> "demux-tsout #66":0 []
		-> "dvr-tsout #66":0 []
	pad68: Source
		-> "demux-tsout #67":0 []
		-> "dvr-tsout #67":0 []
	pad69: Source
		-> "demux-tsout #68":0 []
		-> "dvr-tsout #68":0 []
	pad70: Source
		-> "demux-tsout #69":0 []
		-> "dvr-tsout #69":0 []
	pad71: Source
		-> "demux-tsout #70":0 []
		-> "dvr-tsout #70":0 []
	pad72: Source
		-> "demux-tsout #71":0 []
		-> "dvr-tsout #71":0 []
	pad73: Source
		-> "demux-tsout #72":0 []
		-> "dvr-tsout #72":0 []
	pad74: Source
		-> "demux-tsout #73":0 []
		-> "dvr-tsout #73":0 []
	pad75: Source
		-> "demux-tsout #74":0 []
		-> "dvr-tsout #74":0 []
	pad76: Source
		-> "demux-tsout #75":0 []
		-> "dvr-tsout #75":0 []
	pad77: Source
		-> "demux-tsout #76":0 []
		-> "dvr-tsout #76":0 []
	pad78: Source
		-> "demux-tsout #77":0 []
		-> "dvr-tsout #77":0 []
	pad79: Source
		-> "demux-tsout #78":0 []
		-> "dvr-tsout #78":0 []
	pad80: Source
		-> "demux-tsout #79":0 []
		-> "dvr-tsout #79":0 []
	pad81: Source
		-> "demux-tsout #80":0 []
		-> "dvr-tsout #80":0 []
	pad82: Source
		-> "demux-tsout #81":0 []
		-> "dvr-tsout #81":0 []
	pad83: Source
		-> "demux-tsout #82":0 []
		-> "dvr-tsout #82":0 []
	pad84: Source
		-> "demux-tsout #83":0 []
		-> "dvr-tsout #83":0 []
	pad85: Source
		-> "demux-tsout #84":0 []
		-> "dvr-tsout #84":0 []
	pad86: Source
		-> "demux-tsout #85":0 []
		-> "dvr-tsout #85":0 []
	pad87: Source
		-> "demux-tsout #86":0 []
		-> "dvr-tsout #86":0 []
	pad88: Source
		-> "demux-tsout #87":0 []
		-> "dvr-tsout #87":0 []
	pad89: Source
		-> "demux-tsout #88":0 []
		-> "dvr-tsout #88":0 []
	pad90: Source
		-> "demux-tsout #89":0 []
		-> "dvr-tsout #89":0 []
	pad91: Source
		-> "demux-tsout #90":0 []
		-> "dvr-tsout #90":0 []
	pad92: Source
		-> "demux-tsout #91":0 []
		-> "dvr-tsout #91":0 []
	pad93: Source
		-> "demux-tsout #92":0 []
		-> "dvr-tsout #92":0 []
	pad94: Source
		-> "demux-tsout #93":0 []
		-> "dvr-tsout #93":0 []
	pad95: Source
		-> "demux-tsout #94":0 []
		-> "dvr-tsout #94":0 []
	pad96: Source
		-> "demux-tsout #95":0 []
		-> "dvr-tsout #95":0 []
	pad97: Source
		-> "demux-tsout #96":0 []
		-> "dvr-tsout #96":0 []
	pad98: Source
		-> "demux-tsout #97":0 []
		-> "dvr-tsout #97":0 []
	pad99: Source
		-> "demux-tsout #98":0 []
		-> "dvr-tsout #98":0 []
	pad100: Source
		-> "demux-tsout #99":0 []
		-> "dvr-tsout #99":0 []
	pad101: Source
		-> "demux-tsout #100":0 []
		-> "dvr-tsout #100":0 []
	pad102: Source
		-> "demux-tsout #101":0 []
		-> "dvr-tsout #101":0 []
	pad103: Source
		-> "demux-tsout #102":0 []
		-> "dvr-tsout #102":0 []
	pad104: Source
		-> "demux-tsout #103":0 []
		-> "dvr-tsout #103":0 []
	pad105: Source
		-> "demux-tsout #104":0 []
		-> "dvr-tsout #104":0 []
	pad106: Source
		-> "demux-tsout #105":0 []
		-> "dvr-tsout #105":0 []
	pad107: Source
		-> "demux-tsout #106":0 []
		-> "dvr-tsout #106":0 []
	pad108: Source
		-> "demux-tsout #107":0 []
		-> "dvr-tsout #107":0 []
	pad109: Source
		-> "demux-tsout #108":0 []
		-> "dvr-tsout #108":0 []
	pad110: Source
		-> "demux-tsout #109":0 []
		-> "dvr-tsout #109":0 []
	pad111: Source
		-> "demux-tsout #110":0 []
		-> "dvr-tsout #110":0 []
	pad112: Source
		-> "demux-tsout #111":0 []
		-> "dvr-tsout #111":0 []
	pad113: Source
		-> "demux-tsout #112":0 []
		-> "dvr-tsout #112":0 []
	pad114: Source
		-> "demux-tsout #113":0 []
		-> "dvr-tsout #113":0 []
	pad115: Source
		-> "demux-tsout #114":0 []
		-> "dvr-tsout #114":0 []
	pad116: Source
		-> "demux-tsout #115":0 []
		-> "dvr-tsout #115":0 []
	pad117: Source
		-> "demux-tsout #116":0 []
		-> "dvr-tsout #116":0 []
	pad118: Source
		-> "demux-tsout #117":0 []
		-> "dvr-tsout #117":0 []
	pad119: Source
		-> "demux-tsout #118":0 []
		-> "dvr-tsout #118":0 []
	pad120: Source
		-> "demux-tsout #119":0 []
		-> "dvr-tsout #119":0 []
	pad121: Source
		-> "demux-tsout #120":0 []
		-> "dvr-tsout #120":0 []
	pad122: Source
		-> "demux-tsout #121":0 []
		-> "dvr-tsout #121":0 []
	pad123: Source
		-> "demux-tsout #122":0 []
		-> "dvr-tsout #122":0 []
	pad124: Source
		-> "demux-tsout #123":0 []
		-> "dvr-tsout #123":0 []
	pad125: Source
		-> "demux-tsout #124":0 []
		-> "dvr-tsout #124":0 []
	pad126: Source
		-> "demux-tsout #125":0 []
		-> "dvr-tsout #125":0 []
	pad127: Source
		-> "demux-tsout #126":0 []
		-> "dvr-tsout #126":0 []
	pad128: Source
		-> "demux-tsout #127":0 []
		-> "dvr-tsout #127":0 []
	pad129: Source
		-> "demux-tsout #128":0 []
		-> "dvr-tsout #128":0 []
	pad130: Source
		-> "demux-tsout #129":0 []
		-> "dvr-tsout #129":0 []
	pad131: Source
		-> "demux-tsout #130":0 []
		-> "dvr-tsout #130":0 []
	pad132: Source
		-> "demux-tsout #131":0 []
		-> "dvr-tsout #131":0 []
	pad133: Source
		-> "demux-tsout #132":0 []
		-> "dvr-tsout #132":0 []
	pad134: Source
		-> "demux-tsout #133":0 []
		-> "dvr-tsout #133":0 []
	pad135: Source
		-> "demux-tsout #134":0 []
		-> "dvr-tsout #134":0 []
	pad136: Source
		-> "demux-tsout #135":0 []
		-> "dvr-tsout #135":0 []
	pad137: Source
		-> "demux-tsout #136":0 []
		-> "dvr-tsout #136":0 []
	pad138: Source
		-> "demux-tsout #137":0 []
		-> "dvr-tsout #137":0 []
	pad139: Source
		-> "demux-tsout #138":0 []
		-> "dvr-tsout #138":0 []
	pad140: Source
		-> "demux-tsout #139":0 []
		-> "dvr-tsout #139":0 []
	pad141: Source
		-> "demux-tsout #140":0 []
		-> "dvr-tsout #140":0 []
	pad142: Source
		-> "demux-tsout #141":0 []
		-> "dvr-tsout #141":0 []
	pad143: Source
		-> "demux-tsout #142":0 []
		-> "dvr-tsout #142":0 []
	pad144: Source
		-> "demux-tsout #143":0 []
		-> "dvr-tsout #143":0 []
	pad145: Source
		-> "demux-tsout #144":0 []
		-> "dvr-tsout #144":0 []
	pad146: Source
		-> "demux-tsout #145":0 []
		-> "dvr-tsout #145":0 []
	pad147: Source
		-> "demux-tsout #146":0 []
		-> "dvr-tsout #146":0 []
	pad148: Source
		-> "demux-tsout #147":0 []
		-> "dvr-tsout #147":0 []
	pad149: Source
		-> "demux-tsout #148":0 []
		-> "dvr-tsout #148":0 []
	pad150: Source
		-> "demux-tsout #149":0 []
		-> "dvr-tsout #149":0 []
	pad151: Source
		-> "demux-tsout #150":0 []
		-> "dvr-tsout #150":0 []
	pad152: Source
		-> "demux-tsout #151":0 []
		-> "dvr-tsout #151":0 []
	pad153: Source
		-> "demux-tsout #152":0 []
		-> "dvr-tsout #152":0 []
	pad154: Source
		-> "demux-tsout #153":0 []
		-> "dvr-tsout #153":0 []
	pad155: Source
		-> "demux-tsout #154":0 []
		-> "dvr-tsout #154":0 []
	pad156: Source
		-> "demux-tsout #155":0 []
		-> "dvr-tsout #155":0 []
	pad157: Source
		-> "demux-tsout #156":0 []
		-> "dvr-tsout #156":0 []
	pad158: Source
		-> "demux-tsout #157":0 []
		-> "dvr-tsout #157":0 []
	pad159: Source
		-> "demux-tsout #158":0 []
		-> "dvr-tsout #158":0 []
	pad160: Source
		-> "demux-tsout #159":0 []
		-> "dvr-tsout #159":0 []
	pad161: Source
		-> "demux-tsout #160":0 []
		-> "dvr-tsout #160":0 []
	pad162: Source
		-> "demux-tsout #161":0 []
		-> "dvr-tsout #161":0 []
	pad163: Source
		-> "demux-tsout #162":0 []
		-> "dvr-tsout #162":0 []
	pad164: Source
		-> "demux-tsout #163":0 []
		-> "dvr-tsout #163":0 []
	pad165: Source
		-> "demux-tsout #164":0 []
		-> "dvr-tsout #164":0 []
	pad166: Source
		-> "demux-tsout #165":0 []
		-> "dvr-tsout #165":0 []
	pad167: Source
		-> "demux-tsout #166":0 []
		-> "dvr-tsout #166":0 []
	pad168: Source
		-> "demux-tsout #167":0 []
		-> "dvr-tsout #167":0 []
	pad169: Source
		-> "demux-tsout #168":0 []
		-> "dvr-tsout #168":0 []
	pad170: Source
		-> "demux-tsout #169":0 []
		-> "dvr-tsout #169":0 []
	pad171: Source
		-> "demux-tsout #170":0 []
		-> "dvr-tsout #170":0 []
	pad172: Source
		-> "demux-tsout #171":0 []
		-> "dvr-tsout #171":0 []
	pad173: Source
		-> "demux-tsout #172":0 []
		-> "dvr-tsout #172":0 []
	pad174: Source
		-> "demux-tsout #173":0 []
		-> "dvr-tsout #173":0 []
	pad175: Source
		-> "demux-tsout #174":0 []
		-> "dvr-tsout #174":0 []
	pad176: Source
		-> "demux-tsout #175":0 []
		-> "dvr-tsout #175":0 []
	pad177: Source
		-> "demux-tsout #176":0 []
		-> "dvr-tsout #176":0 []
	pad178: Source
		-> "demux-tsout #177":0 []
		-> "dvr-tsout #177":0 []
	pad179: Source
		-> "demux-tsout #178":0 []
		-> "dvr-tsout #178":0 []
	pad180: Source
		-> "demux-tsout #179":0 []
		-> "dvr-tsout #179":0 []
	pad181: Source
		-> "demux-tsout #180":0 []
		-> "dvr-tsout #180":0 []
	pad182: Source
		-> "demux-tsout #181":0 []
		-> "dvr-tsout #181":0 []
	pad183: Source
		-> "demux-tsout #182":0 []
		-> "dvr-tsout #182":0 []
	pad184: Source
		-> "demux-tsout #183":0 []
		-> "dvr-tsout #183":0 []
	pad185: Source
		-> "demux-tsout #184":0 []
		-> "dvr-tsout #184":0 []
	pad186: Source
		-> "demux-tsout #185":0 []
		-> "dvr-tsout #185":0 []
	pad187: Source
		-> "demux-tsout #186":0 []
		-> "dvr-tsout #186":0 []
	pad188: Source
		-> "demux-tsout #187":0 []
		-> "dvr-tsout #187":0 []
	pad189: Source
		-> "demux-tsout #188":0 []
		-> "dvr-tsout #188":0 []
	pad190: Source
		-> "demux-tsout #189":0 []
		-> "dvr-tsout #189":0 []
	pad191: Source
		-> "demux-tsout #190":0 []
		-> "dvr-tsout #190":0 []
	pad192: Source
		-> "demux-tsout #191":0 []
		-> "dvr-tsout #191":0 []
	pad193: Source
		-> "demux-tsout #192":0 []
		-> "dvr-tsout #192":0 []
	pad194: Source
		-> "demux-tsout #193":0 []
		-> "dvr-tsout #193":0 []
	pad195: Source
		-> "demux-tsout #194":0 []
		-> "dvr-tsout #194":0 []
	pad196: Source
		-> "demux-tsout #195":0 []
		-> "dvr-tsout #195":0 []
	pad197: Source
		-> "demux-tsout #196":0 []
		-> "dvr-tsout #196":0 []
	pad198: Source
		-> "demux-tsout #197":0 []
		-> "dvr-tsout #197":0 []
	pad199: Source
		-> "demux-tsout #198":0 []
		-> "dvr-tsout #198":0 []
	pad200: Source
		-> "demux-tsout #199":0 []
		-> "dvr-tsout #199":0 []
	pad201: Source
		-> "demux-tsout #200":0 []
		-> "dvr-tsout #200":0 []
	pad202: Source
		-> "demux-tsout #201":0 []
		-> "dvr-tsout #201":0 []
	pad203: Source
		-> "demux-tsout #202":0 []
		-> "dvr-tsout #202":0 []
	pad204: Source
		-> "demux-tsout #203":0 []
		-> "dvr-tsout #203":0 []
	pad205: Source
		-> "demux-tsout #204":0 []
		-> "dvr-tsout #204":0 []
	pad206: Source
		-> "demux-tsout #205":0 []
		-> "dvr-tsout #205":0 []
	pad207: Source
		-> "demux-tsout #206":0 []
		-> "dvr-tsout #206":0 []
	pad208: Source
		-> "demux-tsout #207":0 []
		-> "dvr-tsout #207":0 []
	pad209: Source
		-> "demux-tsout #208":0 []
		-> "dvr-tsout #208":0 []
	pad210: Source
		-> "demux-tsout #209":0 []
		-> "dvr-tsout #209":0 []
	pad211: Source
		-> "demux-tsout #210":0 []
		-> "dvr-tsout #210":0 []
	pad212: Source
		-> "demux-tsout #211":0 []
		-> "dvr-tsout #211":0 []
	pad213: Source
		-> "demux-tsout #212":0 []
		-> "dvr-tsout #212":0 []
	pad214: Source
		-> "demux-tsout #213":0 []
		-> "dvr-tsout #213":0 []
	pad215: Source
		-> "demux-tsout #214":0 []
		-> "dvr-tsout #214":0 []
	pad216: Source
		-> "demux-tsout #215":0 []
		-> "dvr-tsout #215":0 []
	pad217: Source
		-> "demux-tsout #216":0 []
		-> "dvr-tsout #216":0 []
	pad218: Source
		-> "demux-tsout #217":0 []
		-> "dvr-tsout #217":0 []
	pad219: Source
		-> "demux-tsout #218":0 []
		-> "dvr-tsout #218":0 []
	pad220: Source
		-> "demux-tsout #219":0 []
		-> "dvr-tsout #219":0 []
	pad221: Source
		-> "demux-tsout #220":0 []
		-> "dvr-tsout #220":0 []
	pad222: Source
		-> "demux-tsout #221":0 []
		-> "dvr-tsout #221":0 []
	pad223: Source
		-> "demux-tsout #222":0 []
		-> "dvr-tsout #222":0 []
	pad224: Source
		-> "demux-tsout #223":0 []
		-> "dvr-tsout #223":0 []
	pad225: Source
		-> "demux-tsout #224":0 []
		-> "dvr-tsout #224":0 []
	pad226: Source
		-> "demux-tsout #225":0 []
		-> "dvr-tsout #225":0 []
	pad227: Source
		-> "demux-tsout #226":0 []
		-> "dvr-tsout #226":0 []
	pad228: Source
		-> "demux-tsout #227":0 []
		-> "dvr-tsout #227":0 []
	pad229: Source
		-> "demux-tsout #228":0 []
		-> "dvr-tsout #228":0 []
	pad230: Source
		-> "demux-tsout #229":0 []
		-> "dvr-tsout #229":0 []
	pad231: Source
		-> "demux-tsout #230":0 []
		-> "dvr-tsout #230":0 []
	pad232: Source
		-> "demux-tsout #231":0 []
		-> "dvr-tsout #231":0 []
	pad233: Source
		-> "demux-tsout #232":0 []
		-> "dvr-tsout #232":0 []
	pad234: Source
		-> "demux-tsout #233":0 []
		-> "dvr-tsout #233":0 []
	pad235: Source
		-> "demux-tsout #234":0 []
		-> "dvr-tsout #234":0 []
	pad236: Source
		-> "demux-tsout #235":0 []
		-> "dvr-tsout #235":0 []
	pad237: Source
		-> "demux-tsout #236":0 []
		-> "dvr-tsout #236":0 []
	pad238: Source
		-> "demux-tsout #237":0 []
		-> "dvr-tsout #237":0 []
	pad239: Source
		-> "demux-tsout #238":0 []
		-> "dvr-tsout #238":0 []
	pad240: Source
		-> "demux-tsout #239":0 []
		-> "dvr-tsout #239":0 []
	pad241: Source
		-> "demux-tsout #240":0 []
		-> "dvr-tsout #240":0 []
	pad242: Source
		-> "demux-tsout #241":0 []
		-> "dvr-tsout #241":0 []
	pad243: Source
		-> "demux-tsout #242":0 []
		-> "dvr-tsout #242":0 []
	pad244: Source
		-> "demux-tsout #243":0 []
		-> "dvr-tsout #243":0 []
	pad245: Source
		-> "demux-tsout #244":0 []
		-> "dvr-tsout #244":0 []
	pad246: Source
		-> "demux-tsout #245":0 []
		-> "dvr-tsout #245":0 []
	pad247: Source
		-> "demux-tsout #246":0 []
		-> "dvr-tsout #246":0 []
	pad248: Source
		-> "demux-tsout #247":0 []
		-> "dvr-tsout #247":0 []
	pad249: Source
		-> "demux-tsout #248":0 []
		-> "dvr-tsout #248":0 []
	pad250: Source
		-> "demux-tsout #249":0 []
		-> "dvr-tsout #249":0 []
	pad251: Source
		-> "demux-tsout #250":0 []
		-> "dvr-tsout #250":0 []
	pad252: Source
		-> "demux-tsout #251":0 []
		-> "dvr-tsout #251":0 []
	pad253: Source
		-> "demux-tsout #252":0 []
		-> "dvr-tsout #252":0 []
	pad254: Source
		-> "demux-tsout #253":0 []
		-> "dvr-tsout #253":0 []
	pad255: Source
		-> "demux-tsout #254":0 []
		-> "dvr-tsout #254":0 []
	pad256: Source
		-> "demux-tsout #255":0 []
		-> "dvr-tsout #255":0 []

- entity 812: dvr-tsout #0 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":1 []

- entity 814: dvr-tsout #1 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":2 []

- entity 816: dvr-tsout #2 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":3 []

- entity 818: dvr-tsout #3 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":4 []

- entity 820: dvr-tsout #4 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":5 []

- entity 822: dvr-tsout #5 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":6 []

- entity 824: dvr-tsout #6 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":7 []

- entity 826: dvr-tsout #7 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":8 []

- entity 828: dvr-tsout #8 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":9 []

- entity 830: dvr-tsout #9 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":10 []

- entity 832: dvr-tsout #10 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":11 []

- entity 834: dvr-tsout #11 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":12 []

- entity 836: dvr-tsout #12 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":13 []

- entity 838: dvr-tsout #13 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":14 []

- entity 840: dvr-tsout #14 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":15 []

- entity 842: dvr-tsout #15 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":16 []

- entity 844: dvr-tsout #16 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":17 []

- entity 846: dvr-tsout #17 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":18 []

- entity 848: dvr-tsout #18 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":19 []

- entity 850: dvr-tsout #19 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":20 []

- entity 852: dvr-tsout #20 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":21 []

- entity 854: dvr-tsout #21 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":22 []

- entity 856: dvr-tsout #22 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":23 []

- entity 858: dvr-tsout #23 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":24 []

- entity 860: dvr-tsout #24 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":25 []

- entity 862: dvr-tsout #25 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":26 []

- entity 864: dvr-tsout #26 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":27 []

- entity 866: dvr-tsout #27 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":28 []

- entity 868: dvr-tsout #28 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":29 []

- entity 870: dvr-tsout #29 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":30 []

- entity 872: dvr-tsout #30 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":31 []

- entity 874: dvr-tsout #31 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":32 []

- entity 876: dvr-tsout #32 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":33 []

- entity 878: dvr-tsout #33 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":34 []

- entity 880: dvr-tsout #34 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":35 []

- entity 882: dvr-tsout #35 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":36 []

- entity 884: dvr-tsout #36 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":37 []

- entity 886: dvr-tsout #37 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":38 []

- entity 888: dvr-tsout #38 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":39 []

- entity 890: dvr-tsout #39 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":40 []

- entity 892: dvr-tsout #40 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":41 []

- entity 894: dvr-tsout #41 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":42 []

- entity 896: dvr-tsout #42 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":43 []

- entity 898: dvr-tsout #43 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":44 []

- entity 900: dvr-tsout #44 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":45 []

- entity 902: dvr-tsout #45 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":46 []

- entity 904: dvr-tsout #46 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":47 []

- entity 906: dvr-tsout #47 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":48 []

- entity 908: dvr-tsout #48 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":49 []

- entity 910: dvr-tsout #49 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":50 []

- entity 912: dvr-tsout #50 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":51 []

- entity 914: dvr-tsout #51 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":52 []

- entity 916: dvr-tsout #52 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":53 []

- entity 918: dvr-tsout #53 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":54 []

- entity 920: dvr-tsout #54 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":55 []

- entity 922: dvr-tsout #55 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":56 []

- entity 924: dvr-tsout #56 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":57 []

- entity 926: dvr-tsout #57 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":58 []

- entity 928: dvr-tsout #58 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":59 []

- entity 930: dvr-tsout #59 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":60 []

- entity 932: dvr-tsout #60 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":61 []

- entity 934: dvr-tsout #61 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":62 []

- entity 936: dvr-tsout #62 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":63 []

- entity 938: dvr-tsout #63 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":64 []

- entity 940: dvr-tsout #64 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":65 []

- entity 942: dvr-tsout #65 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":66 []

- entity 944: dvr-tsout #66 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":67 []

- entity 946: dvr-tsout #67 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":68 []

- entity 948: dvr-tsout #68 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":69 []

- entity 950: dvr-tsout #69 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":70 []

- entity 952: dvr-tsout #70 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":71 []

- entity 954: dvr-tsout #71 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":72 []

- entity 956: dvr-tsout #72 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":73 []

- entity 958: dvr-tsout #73 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":74 []

- entity 960: dvr-tsout #74 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":75 []

- entity 962: dvr-tsout #75 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":76 []

- entity 964: dvr-tsout #76 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":77 []

- entity 966: dvr-tsout #77 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":78 []

- entity 968: dvr-tsout #78 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":79 []

- entity 970: dvr-tsout #79 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":80 []

- entity 972: dvr-tsout #80 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":81 []

- entity 974: dvr-tsout #81 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":82 []

- entity 976: dvr-tsout #82 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":83 []

- entity 978: dvr-tsout #83 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":84 []

- entity 980: dvr-tsout #84 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":85 []

- entity 982: dvr-tsout #85 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":86 []

- entity 984: dvr-tsout #86 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":87 []

- entity 986: dvr-tsout #87 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":88 []

- entity 988: dvr-tsout #88 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":89 []

- entity 990: dvr-tsout #89 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":90 []

- entity 992: dvr-tsout #90 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":91 []

- entity 994: dvr-tsout #91 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":92 []

- entity 996: dvr-tsout #92 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":93 []

- entity 998: dvr-tsout #93 (1 pad, 1 link)
              type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":94 []

- entity 1000: dvr-tsout #94 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":95 []

- entity 1002: dvr-tsout #95 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":96 []

- entity 1004: dvr-tsout #96 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":97 []

- entity 1006: dvr-tsout #97 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":98 []

- entity 1008: dvr-tsout #98 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":99 []

- entity 1010: dvr-tsout #99 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":100 []

- entity 1012: dvr-tsout #100 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":101 []

- entity 1014: dvr-tsout #101 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":102 []

- entity 1016: dvr-tsout #102 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":103 []

- entity 1018: dvr-tsout #103 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":104 []

- entity 1020: dvr-tsout #104 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":105 []

- entity 1022: dvr-tsout #105 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":106 []

- entity 1024: dvr-tsout #106 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":107 []

- entity 1026: dvr-tsout #107 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":108 []

- entity 1028: dvr-tsout #108 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":109 []

- entity 1030: dvr-tsout #109 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":110 []

- entity 1032: dvr-tsout #110 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":111 []

- entity 1034: dvr-tsout #111 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":112 []

- entity 1036: dvr-tsout #112 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":113 []

- entity 1038: dvr-tsout #113 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":114 []

- entity 1040: dvr-tsout #114 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":115 []

- entity 1042: dvr-tsout #115 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":116 []

- entity 1044: dvr-tsout #116 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":117 []

- entity 1046: dvr-tsout #117 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":118 []

- entity 1048: dvr-tsout #118 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":119 []

- entity 1050: dvr-tsout #119 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":120 []

- entity 1052: dvr-tsout #120 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":121 []

- entity 1054: dvr-tsout #121 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":122 []

- entity 1056: dvr-tsout #122 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":123 []

- entity 1058: dvr-tsout #123 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":124 []

- entity 1060: dvr-tsout #124 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":125 []

- entity 1062: dvr-tsout #125 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":126 []

- entity 1064: dvr-tsout #126 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":127 []

- entity 1066: dvr-tsout #127 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":128 []

- entity 1068: dvr-tsout #128 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":129 []

- entity 1070: dvr-tsout #129 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":130 []

- entity 1072: dvr-tsout #130 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":131 []

- entity 1074: dvr-tsout #131 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":132 []

- entity 1076: dvr-tsout #132 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":133 []

- entity 1078: dvr-tsout #133 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":134 []

- entity 1080: dvr-tsout #134 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":135 []

- entity 1082: dvr-tsout #135 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":136 []

- entity 1084: dvr-tsout #136 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":137 []

- entity 1086: dvr-tsout #137 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":138 []

- entity 1088: dvr-tsout #138 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":139 []

- entity 1090: dvr-tsout #139 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":140 []

- entity 1092: dvr-tsout #140 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":141 []

- entity 1094: dvr-tsout #141 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":142 []

- entity 1096: dvr-tsout #142 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":143 []

- entity 1098: dvr-tsout #143 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":144 []

- entity 1100: dvr-tsout #144 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":145 []

- entity 1102: dvr-tsout #145 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":146 []

- entity 1104: dvr-tsout #146 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":147 []

- entity 1106: dvr-tsout #147 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":148 []

- entity 1108: dvr-tsout #148 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":149 []

- entity 1110: dvr-tsout #149 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":150 []

- entity 1112: dvr-tsout #150 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":151 []

- entity 1114: dvr-tsout #151 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":152 []

- entity 1116: dvr-tsout #152 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":153 []

- entity 1118: dvr-tsout #153 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":154 []

- entity 1120: dvr-tsout #154 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":155 []

- entity 1122: dvr-tsout #155 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":156 []

- entity 1124: dvr-tsout #156 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":157 []

- entity 1126: dvr-tsout #157 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":158 []

- entity 1128: dvr-tsout #158 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":159 []

- entity 1130: dvr-tsout #159 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":160 []

- entity 1132: dvr-tsout #160 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":161 []

- entity 1134: dvr-tsout #161 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":162 []

- entity 1136: dvr-tsout #162 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":163 []

- entity 1138: dvr-tsout #163 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":164 []

- entity 1140: dvr-tsout #164 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":165 []

- entity 1142: dvr-tsout #165 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":166 []

- entity 1144: dvr-tsout #166 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":167 []

- entity 1146: dvr-tsout #167 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":168 []

- entity 1148: dvr-tsout #168 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":169 []

- entity 1150: dvr-tsout #169 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":170 []

- entity 1152: dvr-tsout #170 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":171 []

- entity 1154: dvr-tsout #171 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":172 []

- entity 1156: dvr-tsout #172 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":173 []

- entity 1158: dvr-tsout #173 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":174 []

- entity 1160: dvr-tsout #174 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":175 []

- entity 1162: dvr-tsout #175 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":176 []

- entity 1164: dvr-tsout #176 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":177 []

- entity 1166: dvr-tsout #177 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":178 []

- entity 1168: dvr-tsout #178 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":179 []

- entity 1170: dvr-tsout #179 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":180 []

- entity 1172: dvr-tsout #180 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":181 []

- entity 1174: dvr-tsout #181 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":182 []

- entity 1176: dvr-tsout #182 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":183 []

- entity 1178: dvr-tsout #183 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":184 []

- entity 1180: dvr-tsout #184 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":185 []

- entity 1182: dvr-tsout #185 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":186 []

- entity 1184: dvr-tsout #186 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":187 []

- entity 1186: dvr-tsout #187 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":188 []

- entity 1188: dvr-tsout #188 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":189 []

- entity 1190: dvr-tsout #189 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":190 []

- entity 1192: dvr-tsout #190 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":191 []

- entity 1194: dvr-tsout #191 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":192 []

- entity 1196: dvr-tsout #192 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":193 []

- entity 1198: dvr-tsout #193 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":194 []

- entity 1200: dvr-tsout #194 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":195 []

- entity 1202: dvr-tsout #195 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":196 []

- entity 1204: dvr-tsout #196 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":197 []

- entity 1206: dvr-tsout #197 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":198 []

- entity 1208: dvr-tsout #198 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":199 []

- entity 1210: dvr-tsout #199 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":200 []

- entity 1212: dvr-tsout #200 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":201 []

- entity 1214: dvr-tsout #201 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":202 []

- entity 1216: dvr-tsout #202 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":203 []

- entity 1218: dvr-tsout #203 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":204 []

- entity 1220: dvr-tsout #204 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":205 []

- entity 1222: dvr-tsout #205 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":206 []

- entity 1224: dvr-tsout #206 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":207 []

- entity 1226: dvr-tsout #207 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":208 []

- entity 1228: dvr-tsout #208 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":209 []

- entity 1230: dvr-tsout #209 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":210 []

- entity 1232: dvr-tsout #210 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":211 []

- entity 1234: dvr-tsout #211 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":212 []

- entity 1236: dvr-tsout #212 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":213 []

- entity 1238: dvr-tsout #213 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":214 []

- entity 1240: dvr-tsout #214 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":215 []

- entity 1242: dvr-tsout #215 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":216 []

- entity 1244: dvr-tsout #216 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":217 []

- entity 1246: dvr-tsout #217 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":218 []

- entity 1248: dvr-tsout #218 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":219 []

- entity 1250: dvr-tsout #219 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":220 []

- entity 1252: dvr-tsout #220 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":221 []

- entity 1254: dvr-tsout #221 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":222 []

- entity 1256: dvr-tsout #222 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":223 []

- entity 1258: dvr-tsout #223 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":224 []

- entity 1260: dvr-tsout #224 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":225 []

- entity 1262: dvr-tsout #225 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":226 []

- entity 1264: dvr-tsout #226 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":227 []

- entity 1266: dvr-tsout #227 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":228 []

- entity 1268: dvr-tsout #228 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":229 []

- entity 1270: dvr-tsout #229 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":230 []

- entity 1272: dvr-tsout #230 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":231 []

- entity 1274: dvr-tsout #231 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":232 []

- entity 1276: dvr-tsout #232 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":233 []

- entity 1278: dvr-tsout #233 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":234 []

- entity 1280: dvr-tsout #234 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":235 []

- entity 1282: dvr-tsout #235 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":236 []

- entity 1284: dvr-tsout #236 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":237 []

- entity 1286: dvr-tsout #237 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":238 []

- entity 1288: dvr-tsout #238 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":239 []

- entity 1290: dvr-tsout #239 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":240 []

- entity 1292: dvr-tsout #240 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":241 []

- entity 1294: dvr-tsout #241 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":242 []

- entity 1296: dvr-tsout #242 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":243 []

- entity 1298: dvr-tsout #243 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":244 []

- entity 1300: dvr-tsout #244 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":245 []

- entity 1302: dvr-tsout #245 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":246 []

- entity 1304: dvr-tsout #246 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":247 []

- entity 1306: dvr-tsout #247 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":248 []

- entity 1308: dvr-tsout #248 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":249 []

- entity 1310: dvr-tsout #249 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":250 []

- entity 1312: dvr-tsout #250 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":251 []

- entity 1314: dvr-tsout #251 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":252 []

- entity 1316: dvr-tsout #252 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":253 []

- entity 1318: dvr-tsout #253 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":254 []

- entity 1320: dvr-tsout #254 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":255 []

- entity 1322: dvr-tsout #255 (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "dvb-demux":256 []

- entity 2868: USB Mixer (3 pads, 2 links)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "au8522 13-0047":2 [ENABLED]
	pad1: Source
	pad2: Source
		-> "USB Audio":0 [ENABLED]

- entity 2875: USB Audio (1 pad, 1 link)
               type Node subtype Unknown flags 0
	pad0: Sink
		<- "USB Mixer":2 [ENABLED]
Hans Verkuil Jan. 28, 2019, 12:03 p.m. UTC | #3
Hi Shuah,

On 1/24/19 9:32 PM, Shuah Khan wrote:
> Media Device Allocator API to allows multiple drivers share a media device.
> This API solves a very common use-case for media devices where one physical
> device (an USB stick) provides both audio and video. When such media device
> exposes a standard USB Audio class, a proprietary Video class, two or more
> independent drivers will share a single physical USB bridge. In such cases,
> it is necessary to coordinate access to the shared resource.
> 
> Using this API, drivers can allocate a media device with the shared struct
> device as the key. Once the media device is allocated by a driver, other
> drivers can get a reference to it. The media device is released when all
> the references are released.
> 
> - This patch series is tested on 5.0-rc3 and addresses comments on
>   v9 series from Hans Verkuil.
> - v9 was tested on 4.20-rc6.
> - Tested sharing resources with kaffeine, vlc, xawtv, tvtime, and
>   arecord. When analog is streaming, digital and audio user-space
>   applications detect that the tuner is busy and exit. When digital
>   is streaming, analog and audio applications detect that the tuner is
>   busy and exit. When arecord is owns the tuner, digital and analog
>   detect that the tuner is busy and exit.

I've been doing some testing with my au0828, and I am confused about one
thing, probably because it has been too long ago since I last looked into
this in detail:

Why can't I change the tuner frequency if arecord (and only arecord) is
streaming audio? If arecord is streaming, then it is recording the audio
from the analog TV tuner, right? So changing the analog TV frequency
should be fine.

I understand why you can't switch to DVB mode, but analog TV should be OK.
Or am I missing something?

Regards,

	Hans

> - Tested media device allocator API with bind/unbind testing on
>   snd-usb-audio and au0828 drivers to make sure /dev/mediaX is released
>   only when the last driver is unbound.
> - Addressed review comments from Hans on the RFC v8 (rebased on 4.19)
> - Updated change log to describe the use-case more clearly.
> - No changes to 0001,0002 code since the v7 referenced below.
> - 0003 is a new patch to enable ALSA defines that have been
>   disabled for kernel between 4.9 and 4.19.
> - Minor merge conflict resolution in 0004.
> - Added SPDX to new files.
> 
> Changes since v9:
> - Patch 1: Fix mutex assert warning from find_module() calls. This
>   code was written before the change to find_module() that requires
>   callers to hold module_mutex. I missed this during my testing on
>   4.20-rc6. Hans Verkuil reported the problem.
> - Patch 4: sound/usb: Initializes all the entities it can before
>   registering the device based on comments from Hans Verkuil
> - Carried Reviewed-by tag from Takashi Iwai for the sound from v9.
> - No changes to Patches 2 and 3.
> 
> References:
> https://lkml.org/lkml/2018/11/2/169
> https://www.mail-archive.com/linux-media@vger.kernel.org/msg105854.html
> 
> Shuah Khan (4):
>   media: Media Device Allocator API
>   media: change au0828 to use Media Device Allocator API
>   media: media.h: Enable ALSA MEDIA_INTF_T* interface types
>   sound/usb: Use Media Controller API to share media resources
> 
>  Documentation/media/kapi/mc-core.rst   |  41 ++++
>  drivers/media/Makefile                 |   4 +
>  drivers/media/media-dev-allocator.c    | 144 +++++++++++
>  drivers/media/usb/au0828/au0828-core.c |  12 +-
>  drivers/media/usb/au0828/au0828.h      |   1 +
>  include/media/media-dev-allocator.h    |  53 ++++
>  include/uapi/linux/media.h             |  25 +-
>  sound/usb/Kconfig                      |   4 +
>  sound/usb/Makefile                     |   2 +
>  sound/usb/card.c                       |  14 ++
>  sound/usb/card.h                       |   3 +
>  sound/usb/media.c                      | 327 +++++++++++++++++++++++++
>  sound/usb/media.h                      |  74 ++++++
>  sound/usb/mixer.h                      |   3 +
>  sound/usb/pcm.c                        |  29 ++-
>  sound/usb/quirks-table.h               |   1 +
>  sound/usb/stream.c                     |   2 +
>  sound/usb/usbaudio.h                   |   6 +
>  18 files changed, 723 insertions(+), 22 deletions(-)
>  create mode 100644 drivers/media/media-dev-allocator.c
>  create mode 100644 include/media/media-dev-allocator.h
>  create mode 100644 sound/usb/media.c
>  create mode 100644 sound/usb/media.h
>
Shuah Jan. 28, 2019, 11:48 p.m. UTC | #4
Hi Hans,

On 1/28/19 5:03 AM, Hans Verkuil wrote:
> Hi Shuah,
> 
> On 1/24/19 9:32 PM, Shuah Khan wrote:
>> Media Device Allocator API to allows multiple drivers share a media device.
>> This API solves a very common use-case for media devices where one physical
>> device (an USB stick) provides both audio and video. When such media device
>> exposes a standard USB Audio class, a proprietary Video class, two or more
>> independent drivers will share a single physical USB bridge. In such cases,
>> it is necessary to coordinate access to the shared resource.
>>
>> Using this API, drivers can allocate a media device with the shared struct
>> device as the key. Once the media device is allocated by a driver, other
>> drivers can get a reference to it. The media device is released when all
>> the references are released.
>>
>> - This patch series is tested on 5.0-rc3 and addresses comments on
>>    v9 series from Hans Verkuil.
>> - v9 was tested on 4.20-rc6.
>> - Tested sharing resources with kaffeine, vlc, xawtv, tvtime, and
>>    arecord. When analog is streaming, digital and audio user-space
>>    applications detect that the tuner is busy and exit. When digital
>>    is streaming, analog and audio applications detect that the tuner is
>>    busy and exit. When arecord is owns the tuner, digital and analog
>>    detect that the tuner is busy and exit.
> 
> I've been doing some testing with my au0828, and I am confused about one
> thing, probably because it has been too long ago since I last looked into
> this in detail:
> 

Great.

> Why can't I change the tuner frequency if arecord (and only arecord) is
> streaming audio? If arecord is streaming, then it is recording the audio
> from the analog TV tuner, right? So changing the analog TV frequency
> should be fine.
> 

Changing analog TV frequency would be s_frequency. The way it works is
any s_* calls would require holding the pipeline. In Analog TV case, it
would mean holding both audio and video pipelines for any changes
including TV.

As I recall, we discussed this design and the decision was to make all
s_* calls interfaces to hold the tuner. A special exception is g_tuner
in case of au0828. au0828 initializes the tuner from s_* interfaces and
its g_tuner interfaces. Allowing s_frequency to proceed will disrupt the
arecord audio stream.

Query (q_*) works just fine without holding the pipeline. I limited the
analog holds to just the ones that are required. The current set is
required to avoid audio stream disruptions.

I made sure v4l-ctl --all works when the pipeline is locked by any one
of the 3 (audio, video, DVB).

Hope this helps.

thanks,
-- Shuah
Hans Verkuil Jan. 29, 2019, 9:43 a.m. UTC | #5
On 1/29/19 12:48 AM, shuah wrote:
> Hi Hans,
> 
> On 1/28/19 5:03 AM, Hans Verkuil wrote:
>> Hi Shuah,
>>
>> On 1/24/19 9:32 PM, Shuah Khan wrote:
>>> Media Device Allocator API to allows multiple drivers share a media device.
>>> This API solves a very common use-case for media devices where one physical
>>> device (an USB stick) provides both audio and video. When such media device
>>> exposes a standard USB Audio class, a proprietary Video class, two or more
>>> independent drivers will share a single physical USB bridge. In such cases,
>>> it is necessary to coordinate access to the shared resource.
>>>
>>> Using this API, drivers can allocate a media device with the shared struct
>>> device as the key. Once the media device is allocated by a driver, other
>>> drivers can get a reference to it. The media device is released when all
>>> the references are released.
>>>
>>> - This patch series is tested on 5.0-rc3 and addresses comments on
>>>    v9 series from Hans Verkuil.
>>> - v9 was tested on 4.20-rc6.
>>> - Tested sharing resources with kaffeine, vlc, xawtv, tvtime, and
>>>    arecord. When analog is streaming, digital and audio user-space
>>>    applications detect that the tuner is busy and exit. When digital
>>>    is streaming, analog and audio applications detect that the tuner is
>>>    busy and exit. When arecord is owns the tuner, digital and analog
>>>    detect that the tuner is busy and exit.
>>
>> I've been doing some testing with my au0828, and I am confused about one
>> thing, probably because it has been too long ago since I last looked into
>> this in detail:
>>
> 
> Great.
> 
>> Why can't I change the tuner frequency if arecord (and only arecord) is
>> streaming audio? If arecord is streaming, then it is recording the audio
>> from the analog TV tuner, right? So changing the analog TV frequency
>> should be fine.
>>
> 
> Changing analog TV frequency would be s_frequency. The way it works is
> any s_* calls would require holding the pipeline. In Analog TV case, it
> would mean holding both audio and video pipelines for any changes
> including TV.
> 
> As I recall, we discussed this design and the decision was to make all
> s_* calls interfaces to hold the tuner. A special exception is g_tuner
> in case of au0828. au0828 initializes the tuner from s_* interfaces and
> its g_tuner interfaces. Allowing s_frequency to proceed will disrupt the
> arecord audio stream.
> 
> Query (q_*) works just fine without holding the pipeline. I limited the
> analog holds to just the ones that are required. The current set is
> required to avoid audio stream disruptions.

So I am not sure about that ('avoid audio stream disruptions'): if I
stream video AND use arecord, then I can just set the frequency while
streaming. Doesn't that interrupt audio as well? And are you sure changing
the tuner frequency actually disrupts audio? And if audio is disrupted,
are we talking about a glitch or is audio permanently disrupted?

That's basically the inconsistent behavior I noticed: just running arecord
will prevent me from changing the frequency, but if I run arecord and stream
video, then it is suddenly OK to change the frequency.

BTW, I think there was also inconsistent behavior in the order of streaming
audio and video: if I stream video first, then I can stream audio afterwards.
But if I stream audio first, then (if I remember correctly) I can't start
video streaming.

Regards,

	Hans

> 
> I made sure v4l-ctl --all works when the pipeline is locked by any one
> of the 3 (audio, video, DVB).
> 
> Hope this helps.
> 
> thanks,
> -- Shuah
> 
>
Shuah Jan. 30, 2019, 1:50 a.m. UTC | #6
On 1/29/19 2:43 AM, Hans Verkuil wrote:
> On 1/29/19 12:48 AM, shuah wrote:
>> Hi Hans,
>>
>> On 1/28/19 5:03 AM, Hans Verkuil wrote:
>>> Hi Shuah,
>>>
>>> On 1/24/19 9:32 PM, Shuah Khan wrote:
>>>> Media Device Allocator API to allows multiple drivers share a media device.
>>>> This API solves a very common use-case for media devices where one physical
>>>> device (an USB stick) provides both audio and video. When such media device
>>>> exposes a standard USB Audio class, a proprietary Video class, two or more
>>>> independent drivers will share a single physical USB bridge. In such cases,
>>>> it is necessary to coordinate access to the shared resource.
>>>>
>>>> Using this API, drivers can allocate a media device with the shared struct
>>>> device as the key. Once the media device is allocated by a driver, other
>>>> drivers can get a reference to it. The media device is released when all
>>>> the references are released.
>>>>
>>>> - This patch series is tested on 5.0-rc3 and addresses comments on
>>>>     v9 series from Hans Verkuil.
>>>> - v9 was tested on 4.20-rc6.
>>>> - Tested sharing resources with kaffeine, vlc, xawtv, tvtime, and
>>>>     arecord. When analog is streaming, digital and audio user-space
>>>>     applications detect that the tuner is busy and exit. When digital
>>>>     is streaming, analog and audio applications detect that the tuner is
>>>>     busy and exit. When arecord is owns the tuner, digital and analog
>>>>     detect that the tuner is busy and exit.
>>>
>>> I've been doing some testing with my au0828, and I am confused about one
>>> thing, probably because it has been too long ago since I last looked into
>>> this in detail:
>>>
>>
>> Great.
>>
>>> Why can't I change the tuner frequency if arecord (and only arecord) is
>>> streaming audio? If arecord is streaming, then it is recording the audio
>>> from the analog TV tuner, right? So changing the analog TV frequency
>>> should be fine.
>>>
>>
>> Changing analog TV frequency would be s_frequency. The way it works is
>> any s_* calls would require holding the pipeline. In Analog TV case, it
>> would mean holding both audio and video pipelines for any changes
>> including TV.
>>
>> As I recall, we discussed this design and the decision was to make all
>> s_* calls interfaces to hold the tuner. A special exception is g_tuner
>> in case of au0828. au0828 initializes the tuner from s_* interfaces and
>> its g_tuner interfaces. Allowing s_frequency to proceed will disrupt the
>> arecord audio stream.
>>
>> Query (q_*) works just fine without holding the pipeline. I limited the
>> analog holds to just the ones that are required. The current set is
>> required to avoid audio stream disruptions.
> 
> So I am not sure about that ('avoid audio stream disruptions'): if I
> stream video AND use arecord, then I can just set the frequency while
> streaming. Doesn't that interrupt audio as well? And are you sure changing
> the tuner frequency actually disrupts audio? And if audio is disrupted,
> are we talking about a glitch or is audio permanently disrupted?

I think it is a glitch. I will run some tests and let you know.
> 
> That's basically the inconsistent behavior I noticed: just running arecord
> will prevent me from changing the frequency, but if I run arecord and stream
> video, then it is suddenly OK to change the frequency.

How are you changing frequency? I want to duplicate what you are doing.

> 
> BTW, I think there was also inconsistent behavior in the order of streaming
> audio and video: if I stream video first, then I can stream audio afterwards.
> But if I stream audio first, then (if I remember correctly) I can't start
> video streaming.
> 

I will run some tests tomorrow and see what I find. Which video apps are
you running for these tests?

thanks,
-- Shuah
Hans Verkuil Jan. 30, 2019, 7:42 a.m. UTC | #7
On 1/30/19 2:50 AM, shuah wrote:
> On 1/29/19 2:43 AM, Hans Verkuil wrote:
>> On 1/29/19 12:48 AM, shuah wrote:
>>> Hi Hans,
>>>
>>> On 1/28/19 5:03 AM, Hans Verkuil wrote:
>>>> Hi Shuah,
>>>>
>>>> On 1/24/19 9:32 PM, Shuah Khan wrote:
>>>>> Media Device Allocator API to allows multiple drivers share a media device.
>>>>> This API solves a very common use-case for media devices where one physical
>>>>> device (an USB stick) provides both audio and video. When such media device
>>>>> exposes a standard USB Audio class, a proprietary Video class, two or more
>>>>> independent drivers will share a single physical USB bridge. In such cases,
>>>>> it is necessary to coordinate access to the shared resource.
>>>>>
>>>>> Using this API, drivers can allocate a media device with the shared struct
>>>>> device as the key. Once the media device is allocated by a driver, other
>>>>> drivers can get a reference to it. The media device is released when all
>>>>> the references are released.
>>>>>
>>>>> - This patch series is tested on 5.0-rc3 and addresses comments on
>>>>>     v9 series from Hans Verkuil.
>>>>> - v9 was tested on 4.20-rc6.
>>>>> - Tested sharing resources with kaffeine, vlc, xawtv, tvtime, and
>>>>>     arecord. When analog is streaming, digital and audio user-space
>>>>>     applications detect that the tuner is busy and exit. When digital
>>>>>     is streaming, analog and audio applications detect that the tuner is
>>>>>     busy and exit. When arecord is owns the tuner, digital and analog
>>>>>     detect that the tuner is busy and exit.
>>>>
>>>> I've been doing some testing with my au0828, and I am confused about one
>>>> thing, probably because it has been too long ago since I last looked into
>>>> this in detail:
>>>>
>>>
>>> Great.
>>>
>>>> Why can't I change the tuner frequency if arecord (and only arecord) is
>>>> streaming audio? If arecord is streaming, then it is recording the audio
>>>> from the analog TV tuner, right? So changing the analog TV frequency
>>>> should be fine.
>>>>
>>>
>>> Changing analog TV frequency would be s_frequency. The way it works is
>>> any s_* calls would require holding the pipeline. In Analog TV case, it
>>> would mean holding both audio and video pipelines for any changes
>>> including TV.
>>>
>>> As I recall, we discussed this design and the decision was to make all
>>> s_* calls interfaces to hold the tuner. A special exception is g_tuner
>>> in case of au0828. au0828 initializes the tuner from s_* interfaces and
>>> its g_tuner interfaces. Allowing s_frequency to proceed will disrupt the
>>> arecord audio stream.
>>>
>>> Query (q_*) works just fine without holding the pipeline. I limited the
>>> analog holds to just the ones that are required. The current set is
>>> required to avoid audio stream disruptions.
>>
>> So I am not sure about that ('avoid audio stream disruptions'): if I
>> stream video AND use arecord, then I can just set the frequency while
>> streaming. Doesn't that interrupt audio as well? And are you sure changing
>> the tuner frequency actually disrupts audio? And if audio is disrupted,
>> are we talking about a glitch or is audio permanently disrupted?
> 
> I think it is a glitch. I will run some tests and let you know.
>>
>> That's basically the inconsistent behavior I noticed: just running arecord
>> will prevent me from changing the frequency, but if I run arecord and stream
>> video, then it is suddenly OK to change the frequency.
> 
> How are you changing frequency? I want to duplicate what you are doing.

v4l2-ctl -f <freq>

> 
>>
>> BTW, I think there was also inconsistent behavior in the order of streaming
>> audio and video: if I stream video first, then I can stream audio afterwards.
>> But if I stream audio first, then (if I remember correctly) I can't start
>> video streaming.
>>
> 
> I will run some tests tomorrow and see what I find. Which video apps are
> you running for these tests?

v4l2-ctl or qv4l2.

Regards,

	Hans

> 
> thanks,
> -- Shuah
>
Shuah Feb. 1, 2019, 12:46 a.m. UTC | #8
Hi Hans,

On 1/30/19 12:42 AM, Hans Verkuil wrote:
> On 1/30/19 2:50 AM, shuah wrote:
>> On 1/29/19 2:43 AM, Hans Verkuil wrote:
>>> On 1/29/19 12:48 AM, shuah wrote:
>>>> Hi Hans,
>>>>
>>>> On 1/28/19 5:03 AM, Hans Verkuil wrote:
>>>>> Hi Shuah,
>>>>>
>>>>> On 1/24/19 9:32 PM, Shuah Khan wrote:
>>>>>> Media Device Allocator API to allows multiple drivers share a media device.
>>>>>> This API solves a very common use-case for media devices where one physical
>>>>>> device (an USB stick) provides both audio and video. When such media device
>>>>>> exposes a standard USB Audio class, a proprietary Video class, two or more
>>>>>> independent drivers will share a single physical USB bridge. In such cases,
>>>>>> it is necessary to coordinate access to the shared resource.
>>>>>>
>>>>>> Using this API, drivers can allocate a media device with the shared struct
>>>>>> device as the key. Once the media device is allocated by a driver, other
>>>>>> drivers can get a reference to it. The media device is released when all
>>>>>> the references are released.
>>>>>>
>>>>>> - This patch series is tested on 5.0-rc3 and addresses comments on
>>>>>>      v9 series from Hans Verkuil.
>>>>>> - v9 was tested on 4.20-rc6.
>>>>>> - Tested sharing resources with kaffeine, vlc, xawtv, tvtime, and
>>>>>>      arecord. When analog is streaming, digital and audio user-space
>>>>>>      applications detect that the tuner is busy and exit. When digital
>>>>>>      is streaming, analog and audio applications detect that the tuner is
>>>>>>      busy and exit. When arecord is owns the tuner, digital and analog
>>>>>>      detect that the tuner is busy and exit.
>>>>>
>>>>> I've been doing some testing with my au0828, and I am confused about one
>>>>> thing, probably because it has been too long ago since I last looked into
>>>>> this in detail:
>>>>>
>>>>
>>>> Great.
>>>>
>>>>> Why can't I change the tuner frequency if arecord (and only arecord) is
>>>>> streaming audio? If arecord is streaming, then it is recording the audio
>>>>> from the analog TV tuner, right? So changing the analog TV frequency
>>>>> should be fine.
>>>>>
>>>>
>>>> Changing analog TV frequency would be s_frequency. The way it works is
>>>> any s_* calls would require holding the pipeline. In Analog TV case, it
>>>> would mean holding both audio and video pipelines for any changes
>>>> including TV.
>>>>
>>>> As I recall, we discussed this design and the decision was to make all
>>>> s_* calls interfaces to hold the tuner. A special exception is g_tuner
>>>> in case of au0828. au0828 initializes the tuner from s_* interfaces and
>>>> its g_tuner interfaces. Allowing s_frequency to proceed will disrupt the
>>>> arecord audio stream.
>>>>
>>>> Query (q_*) works just fine without holding the pipeline. I limited the
>>>> analog holds to just the ones that are required. The current set is
>>>> required to avoid audio stream disruptions.
>>>
>>> So I am not sure about that ('avoid audio stream disruptions'): if I
>>> stream video AND use arecord, then I can just set the frequency while
>>> streaming. Doesn't that interrupt audio as well? And are you sure changing
>>> the tuner frequency actually disrupts audio? And if audio is disrupted,
>>> are we talking about a glitch or is audio permanently disrupted?
>>
>> I think it is a glitch. I will run some tests and let you know.
>>>
>>> That's basically the inconsistent behavior I noticed: just running arecord
>>> will prevent me from changing the frequency, but if I run arecord and stream
>>> video, then it is suddenly OK to change the frequency.
>>
>> How are you changing frequency? I want to duplicate what you are doing.
> 
> v4l2-ctl -f <freq>

I am not seeing the inconsistent behavior. Here are my results.

1. Started acecord and while it is running:

arecord -M -D plughw:2,0 -c2  -f S16_LE -t wav foo.wav
Recording WAVE 'foo.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Stereo

2. Ran v4l2-ctl -f as follows:

v4l2-ctl -f 700
VIDIOC_G_TUNER: failed: Device or resource busy
VIDIOC_S_FREQUENCY: failed: Device or resource busy

Based on the current implementation, it failed with resource
busy as expected.

3. Started v4l2-ctl as follows:

  v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video0
VIDIOC_STREAMON: failed: Device or resource busy
shuah@deneb:/mnt/data/lkml/v4l-utils/utils/v4l2-ctl$ v4l2-ctl -f 700
VIDIOC_G_TUNER: failed: Device or resource busy
VIDIOC_S_FREQUENCY: failed: Device or resource busy

Based on the current implementation, it failed with resource
busy as expected.

4. After stopping arecord:

v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video0
<<<<<<<<<<<<< 11.88 fps
<<<<<<<<<<<<<<< 13.36 fps
<<<<<<<<<<<<<<< 14.00 fps
<<<<<<<<<<<<<<<< 14.35 fps
<<<<<<<<<<<<<<< 14.57 fps
<<<<<<<<<<<<<<<< 14.71 fps
<<<<<<<<<


Worked as expected.


5. After stopping above video streaming:

arecord -M -D plughw:2,0 -c2  -f S16_LE -t wav foo.wav
Recording WAVE 'foo.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Stereo


Worked as expected.

> 
>>
>>>
>>> BTW, I think there was also inconsistent behavior in the order of streaming
>>> audio and video: if I stream video first, then I can stream audio afterwards.
>>> But if I stream audio first, then (if I remember correctly) I can't start
>>> video streaming.
>>>

Okay this is what I saw:

While v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video0

I could start arecord -M -D plughw:2,0 -c2  -f S16_LE -t wav foo.wav

I ran strace on v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video0
and I didn't see AUDIO holds. The only think of here is that

v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video0

doesn't open audio device. I didn't see this when tested with other
video apps, (tvtine, xawtv, vlc). When video is streaming, I see
arecord failing with device busy.

As far I can see, exclusion logic is working correctly. s_freq does
fail now based on the current logic.

btw I tested all of this on 5.0-rc4

thanks,
-- Shuah
Hans Verkuil Feb. 1, 2019, 9:21 a.m. UTC | #9
On 2/1/19 1:46 AM, shuah wrote:
> Hi Hans,
> 
> On 1/30/19 12:42 AM, Hans Verkuil wrote:
>> On 1/30/19 2:50 AM, shuah wrote:
>>> On 1/29/19 2:43 AM, Hans Verkuil wrote:
>>>> On 1/29/19 12:48 AM, shuah wrote:
>>>>> Hi Hans,
>>>>>
>>>>> On 1/28/19 5:03 AM, Hans Verkuil wrote:
>>>>>> Hi Shuah,
>>>>>>
>>>>>> On 1/24/19 9:32 PM, Shuah Khan wrote:
>>>>>>> Media Device Allocator API to allows multiple drivers share a media device.
>>>>>>> This API solves a very common use-case for media devices where one physical
>>>>>>> device (an USB stick) provides both audio and video. When such media device
>>>>>>> exposes a standard USB Audio class, a proprietary Video class, two or more
>>>>>>> independent drivers will share a single physical USB bridge. In such cases,
>>>>>>> it is necessary to coordinate access to the shared resource.
>>>>>>>
>>>>>>> Using this API, drivers can allocate a media device with the shared struct
>>>>>>> device as the key. Once the media device is allocated by a driver, other
>>>>>>> drivers can get a reference to it. The media device is released when all
>>>>>>> the references are released.
>>>>>>>
>>>>>>> - This patch series is tested on 5.0-rc3 and addresses comments on
>>>>>>>      v9 series from Hans Verkuil.
>>>>>>> - v9 was tested on 4.20-rc6.
>>>>>>> - Tested sharing resources with kaffeine, vlc, xawtv, tvtime, and
>>>>>>>      arecord. When analog is streaming, digital and audio user-space
>>>>>>>      applications detect that the tuner is busy and exit. When digital
>>>>>>>      is streaming, analog and audio applications detect that the tuner is
>>>>>>>      busy and exit. When arecord is owns the tuner, digital and analog
>>>>>>>      detect that the tuner is busy and exit.
>>>>>>
>>>>>> I've been doing some testing with my au0828, and I am confused about one
>>>>>> thing, probably because it has been too long ago since I last looked into
>>>>>> this in detail:
>>>>>>
>>>>>
>>>>> Great.
>>>>>
>>>>>> Why can't I change the tuner frequency if arecord (and only arecord) is
>>>>>> streaming audio? If arecord is streaming, then it is recording the audio
>>>>>> from the analog TV tuner, right? So changing the analog TV frequency
>>>>>> should be fine.
>>>>>>
>>>>>
>>>>> Changing analog TV frequency would be s_frequency. The way it works is
>>>>> any s_* calls would require holding the pipeline. In Analog TV case, it
>>>>> would mean holding both audio and video pipelines for any changes
>>>>> including TV.
>>>>>
>>>>> As I recall, we discussed this design and the decision was to make all
>>>>> s_* calls interfaces to hold the tuner. A special exception is g_tuner
>>>>> in case of au0828. au0828 initializes the tuner from s_* interfaces and
>>>>> its g_tuner interfaces. Allowing s_frequency to proceed will disrupt the
>>>>> arecord audio stream.
>>>>>
>>>>> Query (q_*) works just fine without holding the pipeline. I limited the
>>>>> analog holds to just the ones that are required. The current set is
>>>>> required to avoid audio stream disruptions.
>>>>
>>>> So I am not sure about that ('avoid audio stream disruptions'): if I
>>>> stream video AND use arecord, then I can just set the frequency while
>>>> streaming. Doesn't that interrupt audio as well? And are you sure changing
>>>> the tuner frequency actually disrupts audio? And if audio is disrupted,
>>>> are we talking about a glitch or is audio permanently disrupted?
>>>
>>> I think it is a glitch. I will run some tests and let you know.
>>>>
>>>> That's basically the inconsistent behavior I noticed: just running arecord
>>>> will prevent me from changing the frequency, but if I run arecord and stream
>>>> video, then it is suddenly OK to change the frequency.
>>>
>>> How are you changing frequency? I want to duplicate what you are doing.
>>
>> v4l2-ctl -f <freq>
> 
> I am not seeing the inconsistent behavior. Here are my results.
> 
> 1. Started acecord and while it is running:
> 
> arecord -M -D plughw:2,0 -c2  -f S16_LE -t wav foo.wav
> Recording WAVE 'foo.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Stereo
> 
> 2. Ran v4l2-ctl -f as follows:
> 
> v4l2-ctl -f 700
> VIDIOC_G_TUNER: failed: Device or resource busy
> VIDIOC_S_FREQUENCY: failed: Device or resource busy
> 
> Based on the current implementation, it failed with resource
> busy as expected.
> 
> 3. Started v4l2-ctl as follows:
> 
>  v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video0
> VIDIOC_STREAMON: failed: Device or resource busy

Why is this? You have one analog tuner and it delivers independent audio
and video streams. I should be able to start/stop audio and video independently.

And as mentioned above, if I use v4l2-ctl for video streaming, then start arecord,
then that works fine. And I can change the tuner frequency while both are streaming.

But doing this the other way around (first start arecord, then v4l2-ctl) then that
doesn't work.

It makes no sense.

Note that v4l2-ctl does not open audio, it solely deals with video. qv4l2 will
open both audio and video, but for testing audio and video independently you
need to use arecord/v4l2-ctl.

In any case, my understanding of how this should work is that both arecord and
v4l2-ctl should attempt to lock the analog tuner resource, but they can share it.

If DVB is using the tuner, then both arecord and v4l2-ctl should fail with -EBUSY.
Same if either of arecord/v4l2-ctl is running, then DVB should fail with -EBUSY.

BTW, I won't be able to test anything myself until Feb 9th since I'm abroad and
don't have access to my au0828.

Regards,

	Hans

> shuah@deneb:/mnt/data/lkml/v4l-utils/utils/v4l2-ctl$ v4l2-ctl -f 700
> VIDIOC_G_TUNER: failed: Device or resource busy
> VIDIOC_S_FREQUENCY: failed: Device or resource busy
> 
> Based on the current implementation, it failed with resource
> busy as expected.
> 
> 4. After stopping arecord:
> 
> v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video0
> <<<<<<<<<<<<< 11.88 fps
> <<<<<<<<<<<<<<< 13.36 fps
> <<<<<<<<<<<<<<< 14.00 fps
> <<<<<<<<<<<<<<<< 14.35 fps
> <<<<<<<<<<<<<<< 14.57 fps
> <<<<<<<<<<<<<<<< 14.71 fps
> <<<<<<<<<
> 
> 
> Worked as expected.
> 
> 
> 5. After stopping above video streaming:
> 
> arecord -M -D plughw:2,0 -c2  -f S16_LE -t wav foo.wav
> Recording WAVE 'foo.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Stereo
> 
> 
> Worked as expected.
> 
>>
>>>
>>>>
>>>> BTW, I think there was also inconsistent behavior in the order of streaming
>>>> audio and video: if I stream video first, then I can stream audio afterwards.
>>>> But if I stream audio first, then (if I remember correctly) I can't start
>>>> video streaming.
>>>>
> 
> Okay this is what I saw:
> 
> While v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video0
> 
> I could start arecord -M -D plughw:2,0 -c2  -f S16_LE -t wav foo.wav
> 
> I ran strace on v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video0
> and I didn't see AUDIO holds. The only think of here is that
> 
> v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video0
> 
> doesn't open audio device. I didn't see this when tested with other
> video apps, (tvtine, xawtv, vlc). When video is streaming, I see
> arecord failing with device busy.
> 
> As far I can see, exclusion logic is working correctly. s_freq does
> fail now based on the current logic.
> 
> btw I tested all of this on 5.0-rc4
> 
> thanks,
> -- Shuah
Shuah Feb. 5, 2019, 6:10 p.m. UTC | #10
On 2/1/19 2:21 AM, Hans Verkuil wrote:
> On 2/1/19 1:46 AM, shuah wrote:
>> Hi Hans,
>>
>> On 1/30/19 12:42 AM, Hans Verkuil wrote:
>>> On 1/30/19 2:50 AM, shuah wrote:
>>>> On 1/29/19 2:43 AM, Hans Verkuil wrote:
>>>>> On 1/29/19 12:48 AM, shuah wrote:
>>>>>> Hi Hans,
>>>>>>
>>>>>> On 1/28/19 5:03 AM, Hans Verkuil wrote:
>>>>>>> Hi Shuah,
>>>>>>>
>>>>>>> On 1/24/19 9:32 PM, Shuah Khan wrote:
>>>>>>>> Media Device Allocator API to allows multiple drivers share a media device.
>>>>>>>> This API solves a very common use-case for media devices where one physical
>>>>>>>> device (an USB stick) provides both audio and video. When such media device
>>>>>>>> exposes a standard USB Audio class, a proprietary Video class, two or more
>>>>>>>> independent drivers will share a single physical USB bridge. In such cases,
>>>>>>>> it is necessary to coordinate access to the shared resource.
>>>>>>>>
>>>>>>>> Using this API, drivers can allocate a media device with the shared struct
>>>>>>>> device as the key. Once the media device is allocated by a driver, other
>>>>>>>> drivers can get a reference to it. The media device is released when all
>>>>>>>> the references are released.
>>>>>>>>
>>>>>>>> - This patch series is tested on 5.0-rc3 and addresses comments on
>>>>>>>>       v9 series from Hans Verkuil.
>>>>>>>> - v9 was tested on 4.20-rc6.
>>>>>>>> - Tested sharing resources with kaffeine, vlc, xawtv, tvtime, and
>>>>>>>>       arecord. When analog is streaming, digital and audio user-space
>>>>>>>>       applications detect that the tuner is busy and exit. When digital
>>>>>>>>       is streaming, analog and audio applications detect that the tuner is
>>>>>>>>       busy and exit. When arecord is owns the tuner, digital and analog
>>>>>>>>       detect that the tuner is busy and exit.
>>>>>>>
>>>>>>> I've been doing some testing with my au0828, and I am confused about one
>>>>>>> thing, probably because it has been too long ago since I last looked into
>>>>>>> this in detail:
>>>>>>>
>>>>>>
>>>>>> Great.
>>>>>>
>>>>>>> Why can't I change the tuner frequency if arecord (and only arecord) is
>>>>>>> streaming audio? If arecord is streaming, then it is recording the audio
>>>>>>> from the analog TV tuner, right? So changing the analog TV frequency
>>>>>>> should be fine.
>>>>>>>
>>>>>>
>>>>>> Changing analog TV frequency would be s_frequency. The way it works is
>>>>>> any s_* calls would require holding the pipeline. In Analog TV case, it
>>>>>> would mean holding both audio and video pipelines for any changes
>>>>>> including TV.
>>>>>>
>>>>>> As I recall, we discussed this design and the decision was to make all
>>>>>> s_* calls interfaces to hold the tuner. A special exception is g_tuner
>>>>>> in case of au0828. au0828 initializes the tuner from s_* interfaces and
>>>>>> its g_tuner interfaces. Allowing s_frequency to proceed will disrupt the
>>>>>> arecord audio stream.
>>>>>>
>>>>>> Query (q_*) works just fine without holding the pipeline. I limited the
>>>>>> analog holds to just the ones that are required. The current set is
>>>>>> required to avoid audio stream disruptions.
>>>>>
>>>>> So I am not sure about that ('avoid audio stream disruptions'): if I
>>>>> stream video AND use arecord, then I can just set the frequency while
>>>>> streaming. Doesn't that interrupt audio as well? And are you sure changing
>>>>> the tuner frequency actually disrupts audio? And if audio is disrupted,
>>>>> are we talking about a glitch or is audio permanently disrupted?
>>>>
>>>> I think it is a glitch. I will run some tests and let you know.
>>>>>
>>>>> That's basically the inconsistent behavior I noticed: just running arecord
>>>>> will prevent me from changing the frequency, but if I run arecord and stream
>>>>> video, then it is suddenly OK to change the frequency.
>>>>
>>>> How are you changing frequency? I want to duplicate what you are doing.
>>>
>>> v4l2-ctl -f <freq>
>>
>> I am not seeing the inconsistent behavior. Here are my results.
>>
>> 1. Started acecord and while it is running:
>>
>> arecord -M -D plughw:2,0 -c2  -f S16_LE -t wav foo.wav
>> Recording WAVE 'foo.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Stereo
>>
>> 2. Ran v4l2-ctl -f as follows:
>>
>> v4l2-ctl -f 700
>> VIDIOC_G_TUNER: failed: Device or resource busy
>> VIDIOC_S_FREQUENCY: failed: Device or resource busy
>>
>> Based on the current implementation, it failed with resource
>> busy as expected.
>>
>> 3. Started v4l2-ctl as follows:
>>
>>   v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video0
>> VIDIOC_STREAMON: failed: Device or resource busy
> 
> Why is this? You have one analog tuner and it delivers independent audio
> and video streams. I should be able to start/stop audio and video independently.
> 
> And as mentioned above, if I use v4l2-ctl for video streaming, then start arecord,
> then that works fine. And I can change the tuner frequency while both are streaming.
> 
> But doing this the other way around (first start arecord, then v4l2-ctl) then that
> doesn't work.
> 
> It makes no sense.
> 
> Note that v4l2-ctl does not open audio, it solely deals with video. qv4l2 will
> open both audio and video, but for testing audio and video independently you
> need to use arecord/v4l2-ctl.
> 
> In any case, my understanding of how this should work is that both arecord and
> v4l2-ctl should attempt to lock the analog tuner resource, but they can share it.
> 
> If DVB is using the tuner, then both arecord and v4l2-ctl should fail with -EBUSY.
> Same if either of arecord/v4l2-ctl is running, then DVB should fail with -EBUSY.
> 
> BTW, I won't be able to test anything myself until Feb 9th since I'm abroad and
> don't have access to my au0828.
> 

I am also on a business trip at the moment and won't have access to my
au0828 until Feb 8th.

I think I understand your concern and the change to get the desired 
behavior of allowing tuner to be shared by arecord and v4l2-ctl is
going to in the code that is already in the mainline which is the
au0828_enable_source().

If you would like to wait to pull this series for the problem to be 
fixed, I can send that change in. It will be another patch added to
the series.

Or if you pull this and I can send fix on top. Let me know your preference.

thanks,
-- Shuah
Hans Verkuil Feb. 6, 2019, 7:36 a.m. UTC | #11
On 2/5/19 7:10 PM, shuah wrote:
> On 2/1/19 2:21 AM, Hans Verkuil wrote:
>> On 2/1/19 1:46 AM, shuah wrote:
>>> Hi Hans,
>>>
>>> On 1/30/19 12:42 AM, Hans Verkuil wrote:
>>>> On 1/30/19 2:50 AM, shuah wrote:
>>>>> On 1/29/19 2:43 AM, Hans Verkuil wrote:
>>>>>> On 1/29/19 12:48 AM, shuah wrote:
>>>>>>> Hi Hans,
>>>>>>>
>>>>>>> On 1/28/19 5:03 AM, Hans Verkuil wrote:
>>>>>>>> Hi Shuah,
>>>>>>>>
>>>>>>>> On 1/24/19 9:32 PM, Shuah Khan wrote:
>>>>>>>>> Media Device Allocator API to allows multiple drivers share a media device.
>>>>>>>>> This API solves a very common use-case for media devices where one physical
>>>>>>>>> device (an USB stick) provides both audio and video. When such media device
>>>>>>>>> exposes a standard USB Audio class, a proprietary Video class, two or more
>>>>>>>>> independent drivers will share a single physical USB bridge. In such cases,
>>>>>>>>> it is necessary to coordinate access to the shared resource.
>>>>>>>>>
>>>>>>>>> Using this API, drivers can allocate a media device with the shared struct
>>>>>>>>> device as the key. Once the media device is allocated by a driver, other
>>>>>>>>> drivers can get a reference to it. The media device is released when all
>>>>>>>>> the references are released.
>>>>>>>>>
>>>>>>>>> - This patch series is tested on 5.0-rc3 and addresses comments on
>>>>>>>>>       v9 series from Hans Verkuil.
>>>>>>>>> - v9 was tested on 4.20-rc6.
>>>>>>>>> - Tested sharing resources with kaffeine, vlc, xawtv, tvtime, and
>>>>>>>>>       arecord. When analog is streaming, digital and audio user-space
>>>>>>>>>       applications detect that the tuner is busy and exit. When digital
>>>>>>>>>       is streaming, analog and audio applications detect that the tuner is
>>>>>>>>>       busy and exit. When arecord is owns the tuner, digital and analog
>>>>>>>>>       detect that the tuner is busy and exit.
>>>>>>>>
>>>>>>>> I've been doing some testing with my au0828, and I am confused about one
>>>>>>>> thing, probably because it has been too long ago since I last looked into
>>>>>>>> this in detail:
>>>>>>>>
>>>>>>>
>>>>>>> Great.
>>>>>>>
>>>>>>>> Why can't I change the tuner frequency if arecord (and only arecord) is
>>>>>>>> streaming audio? If arecord is streaming, then it is recording the audio
>>>>>>>> from the analog TV tuner, right? So changing the analog TV frequency
>>>>>>>> should be fine.
>>>>>>>>
>>>>>>>
>>>>>>> Changing analog TV frequency would be s_frequency. The way it works is
>>>>>>> any s_* calls would require holding the pipeline. In Analog TV case, it
>>>>>>> would mean holding both audio and video pipelines for any changes
>>>>>>> including TV.
>>>>>>>
>>>>>>> As I recall, we discussed this design and the decision was to make all
>>>>>>> s_* calls interfaces to hold the tuner. A special exception is g_tuner
>>>>>>> in case of au0828. au0828 initializes the tuner from s_* interfaces and
>>>>>>> its g_tuner interfaces. Allowing s_frequency to proceed will disrupt the
>>>>>>> arecord audio stream.
>>>>>>>
>>>>>>> Query (q_*) works just fine without holding the pipeline. I limited the
>>>>>>> analog holds to just the ones that are required. The current set is
>>>>>>> required to avoid audio stream disruptions.
>>>>>>
>>>>>> So I am not sure about that ('avoid audio stream disruptions'): if I
>>>>>> stream video AND use arecord, then I can just set the frequency while
>>>>>> streaming. Doesn't that interrupt audio as well? And are you sure changing
>>>>>> the tuner frequency actually disrupts audio? And if audio is disrupted,
>>>>>> are we talking about a glitch or is audio permanently disrupted?
>>>>>
>>>>> I think it is a glitch. I will run some tests and let you know.
>>>>>>
>>>>>> That's basically the inconsistent behavior I noticed: just running arecord
>>>>>> will prevent me from changing the frequency, but if I run arecord and stream
>>>>>> video, then it is suddenly OK to change the frequency.
>>>>>
>>>>> How are you changing frequency? I want to duplicate what you are doing.
>>>>
>>>> v4l2-ctl -f <freq>
>>>
>>> I am not seeing the inconsistent behavior. Here are my results.
>>>
>>> 1. Started acecord and while it is running:
>>>
>>> arecord -M -D plughw:2,0 -c2  -f S16_LE -t wav foo.wav
>>> Recording WAVE 'foo.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Stereo
>>>
>>> 2. Ran v4l2-ctl -f as follows:
>>>
>>> v4l2-ctl -f 700
>>> VIDIOC_G_TUNER: failed: Device or resource busy
>>> VIDIOC_S_FREQUENCY: failed: Device or resource busy
>>>
>>> Based on the current implementation, it failed with resource
>>> busy as expected.
>>>
>>> 3. Started v4l2-ctl as follows:
>>>
>>>   v4l2-ctl --stream-mmap --stream-count=100 -d /dev/video0
>>> VIDIOC_STREAMON: failed: Device or resource busy
>>
>> Why is this? You have one analog tuner and it delivers independent audio
>> and video streams. I should be able to start/stop audio and video independently.
>>
>> And as mentioned above, if I use v4l2-ctl for video streaming, then start arecord,
>> then that works fine. And I can change the tuner frequency while both are streaming.
>>
>> But doing this the other way around (first start arecord, then v4l2-ctl) then that
>> doesn't work.
>>
>> It makes no sense.
>>
>> Note that v4l2-ctl does not open audio, it solely deals with video. qv4l2 will
>> open both audio and video, but for testing audio and video independently you
>> need to use arecord/v4l2-ctl.
>>
>> In any case, my understanding of how this should work is that both arecord and
>> v4l2-ctl should attempt to lock the analog tuner resource, but they can share it.
>>
>> If DVB is using the tuner, then both arecord and v4l2-ctl should fail with -EBUSY.
>> Same if either of arecord/v4l2-ctl is running, then DVB should fail with -EBUSY.
>>
>> BTW, I won't be able to test anything myself until Feb 9th since I'm abroad and
>> don't have access to my au0828.
>>
> 
> I am also on a business trip at the moment and won't have access to my
> au0828 until Feb 8th.
> 
> I think I understand your concern and the change to get the desired behavior of allowing tuner to be shared by arecord and v4l2-ctl is
> going to in the code that is already in the mainline which is the
> au0828_enable_source().
> 
> If you would like to wait to pull this series for the problem to be fixed, I can send that change in. It will be another patch added to
> the series.
> 
> Or if you pull this and I can send fix on top. Let me know your preference.

I prefer to wait until I can test with the additional patch if that's OK?

Regards,

	Hans