AndroidHDMI for Channels (ah4c): A virtual channel tuner using HDMI Encoder(s) + streaming stick(s)

That's my plan (a PR).

I don't know where the best place to mention this is, so here goes....

I noticed that most prebmitune.sh scripts include a fragment like this:

    $adbTarget shell input keyevent KEYCODE_WAKEUP
    local adbEventSuccess=$?

    if [[ $adbEventSuccess -eq 0 ]]; then
      break
    fi

In my experiments, I am never able to get any adb shell input command to have an exit code other than 0. In other words, that loop always breaks out on the first iteration, so it's not meaningful. I don't know if there are environments where it might be meaningful.

I changed mine to look for the screen being on, in the same sort of loop:

  while true; do
    screenOn=`$adbTarget shell "input keyevent KEYCODE_WAKEUP ; dumpsys deviceidle get screen`

    if [ "${screenOn}" = "true" ]; then
      break
    fi

I combined the two ADB shell commands to avoid a second round trip per iteration.

The particular dongle I am using can take 4 seconds or so to get from sleeping to screen on, and that can be enough to trigger the Channels timeout discussed a few posts above. Still fiddling with that.

I think you'll find that if the adb target device is offline, it'll return 1. I just tested that by using a non-existent streaming device, but the same should be true for one that exists but isn't reachable for some reason:

bash-5.1# adb connect firestick-travel3:5555
failed to resolve host: 'firestick-travel3': Name does not resolve
bash-5.1# adb -s firestick-travel3:5555 shell input keyevent KEYCODE_WAKEUP
adb: device 'firestick-travel3:5555' not found
bash-5.1# echo $?
1

I've never had a failed wakeup if the device is available, so I'd suggest removing your test, given how long it takes to run.

EDIT: You could do any number of different shell commands to confirm the streaming stick is there and responding. Such as:

bash-5.1# adb -s firestick-travel2:5555 shell echo "true"
true
bash-5.1# adb -s firestick-travel2:5555 shell getprop net.bt.name
Android

Anything like that would return a 1 if it can't reach the device, and could be used.

1 Like

I've already moved the wake-up test to my bmitune.sh script. Instead, I just send a wakeup and don't wait for anything in prebmitune.sh to get the ball rolling.

I still need to wait for the device to wake up before moving on to the next steps of the remote emulation to avoid those early button presses being ignored. I made going to sleep in stopbmitune.sh configurable.

I'm not so sure the two things would give the same results, but the net result is still useful.

For a non-existent device, you get an immediate failure because the DNS lookup for adb connect promptly tells you there is no such device, and any later adb command is doomed because the adb connect failed. That's what your test showed.

For a device already known to the client (previous adb connect success) whose DNS name does resolve but happens to be offline, adb connect will fail with "no route to host" or similar, and give an exit code of 0. (If the device only recently went offline, it may take a while for various caches to time out to get to the "no route to host" condition.) A subsequent adb shell command fails and returns exit code 1.

$ adb devices
List of devices attached
tivo4k.carpenter.org:5555	device

$ adb connect tivo4k.carpenter.org:5555
failed to connect to 'tivo4k.carpenter.org:5555': No route to host
$ echo $?
0
$ adb devices
List of devices attached
tivo4k.carpenter.org:5555	offline

$ adb -s tivo4k.carpenter.org:5555 shell input keyevent KEYCODE_WAKEUP
adb: device offline
$ echo $?
1

Unless you're kind of lucky and the device is just coming back online, the loop is probably not going to succeed before the Channels retry timeout. I guess the loop doesn't do any harm, though.

Interestingly, when I waited a few minutes and repeated the key input command, the offline device had been removed from the devices list. I don't know the parameters around that happening. The adb connect on the next prebmitune.sh does connect it again without incident.

$ adb -s tivo4k.carpenter.org:5555 shell input keyevent KEYCODE_WAKEUP
adb: device 'tivo4k.carpenter.org:5555' not found
wjc@yogi:/tmp$ adb devices
List of devices attached

The fact that a failed adb connect returns a 0 is exactly why we need a subsequent test. Any one of the shell based tests will do the trick. A failed adb connect should really return 1, but since it doesn't, our loop needs to test for something that does.

I'm not disagreeing about that. I'm just saying that looping after the first failure is of pretty minimal value.

Agreed. I was just looking at that. Maybe just a connect, followed by a shell test, followed by an exit 1 if it fails would make more sense.

For this connectivity testing purpose, sending KEYCODE_WAKEUP is reasonable. I don't know the precise android definition of what happens after KEYCODE_SLEEP, but it certainly turns the display off, and you need to make sure it comes back on at some point.

(I'm doing some experiments now to see if there is any need to wait for the screen to come on before doing any remote emulation. I had assumed there was, but maybe that's not so.)

I decided to see what the difference is between being asleep and being awake for my Android TV device. For me, it's a Chromecast HD with Google TV (not the 4K version).

When asleep, the device is consuming 0.9 W. When awake and idle (not streaming video), it varies between 1.1 W and 2.0 W. When actually streaming, it spikes as high as about 2.5 W but has a steady state that I eyeball between 1.5 W and 2.0 W.

I'm kind of surprised it's so low since the device feels a little warm. With numbers like that, I'm not worrying too much about keeping the device awake all the time. This doesn't include the power drawn by the HDMI encoder box, but I don't have any control over that anyhow.

1 Like

A big part of the motivation to putting streaming devices to sleep, is not so much related to the device itself -- but rather to the encoder.

If your device doesn't sleep, and is displaying video constantly, that means your encoder is constantly encoding -- whether you're watching anything or not. Multiply that times 4 or 5 devices in the typical multi-port encoder, and your encoder is hard-at-it 24x7. There's power draw, heat generation, and un-needed encoder CPU utilization all associated with a no-sleep strategy.

I have the popular EXVIST single-channel encoder. When the dongle is sleeping, the encoder is using 1.3 W. When the dongle is awake but idle (not streaming video), the encoder draws 2.6 W. When the dongle is streaming video, the encoder draws 2.8 W.

I don't doubt that there are devices with higher loads, but I wouldn't worry about it without actual power measurements showing that it's worth the trouble.

Your numbers prove the point though don't they? Double the power usage when doing basically nothing, and that's for one single-port encoder. Personally, I have 5-port, 4-port and a 1-port encoders in everyday service.

The other observation I'd make, at least with the streaming sticks I have, is that putting them to sleep and waking them up both happen very quickly. Obviously these things vary with the type of equipment you have, but at least with the FireStick 4K Max and Max 2, there's very little motivation to not have them sleep.

1 Like

Sure, but even that double is a pretty trivial amount. It's probably way less than the standby power for various devices in my house that have "soft off". Before I measured it, I thought the absolute difference was going to be a lot bigger.

The reason this is interesting to me is something that might be peculiar to the EXVIST device (and maybe some others). When the dongle is sleeping, it shows a static image "Video Lost". The codecs for that are funky in some way that Channels doesn't like.

2024/06/14 16:39:28.068367 [ENC] Starting encoder for ch28 in /shares/DVR/Streaming/ch28-dANY-ip192.168.1.33-1696669460/encoder-1-3963693481 at 1 (0.000000) (encoder=h264_v4l2m2m, codec=h264, acodec=copy, resolution=1080, deinterlacer=blend, bitrate=10000, segment_size=0.01)
2024/06/14 16:39:28.080797 [HLS] ffmpeg: ch28-dANY-ip192.168.1.33-1-h264-copy---10000-0-1080-0-0---false-false-0.01-0:  [mpegts @ 0x1c5a7080] Could not find codec parameters for stream 0 (Video: h264 ([27][0][0][0] / 0x001B), none): unspecified size
2024/06/14 16:39:28.080917 [HLS] ffmpeg: ch28-dANY-ip192.168.1.33-1-h264-copy---10000-0-1080-0-0---false-false-0.01-0:  Consider increasing the value for the 'analyzeduration' and 'probesize' options
2024/06/14 16:39:28.080960 [HLS] ffmpeg: ch28-dANY-ip192.168.1.33-1-h264-copy---10000-0-1080-0-0---false-false-0.01-0:  [mpegts @ 0x1c5a7080] Could not find codec parameters for stream 1 (Audio: aac ([15][0][0][0] / 0x000F), 0 channels, fltp): unspecified sample rate
2024/06/14 16:39:28.081002 [HLS] ffmpeg: ch28-dANY-ip192.168.1.33-1-h264-copy---10000-0-1080-0-0---false-false-0.01-0:  Consider increasing the value for the 'analyzeduration' and 'probesize' options
2024/06/14 16:39:28.083727 [HLS] ffmpeg: ch28-dANY-ip192.168.1.33-1-h264-copy---10000-0-1080-0-0---false-false-0.01-0:  Cannot determine format of input stream 0:0 after EOF
2024/06/14 16:39:28.083886 [HLS] ffmpeg: ch28-dANY-ip192.168.1.33-1-h264-copy---10000-0-1080-0-0---false-false-0.01-0:  Error marking filters as finished
2024/06/14 16:39:28.099973 [ENC] Encoder stopped for ch28 in /shares/DVR/Streaming/ch28-dANY-ip192.168.1.33-1696669460/encoder-1-3963693481 after starting from 1 without encoding any segments
2

Channels treats it as an error and retries a couple times. Not that it matters, but VLC closes the stream when the encoder switches from static to video or vice versa; VLC doesn't have any trouble displaying either thing, but it doesn't care for the transition.

It makes the timing to wake up kind of complicated. With enough effort, I could probably work it out. (I should say "with enough additional effort" because I've already spent quite a bit of time on it.) I'm taking the lazy man's easy way out.

I'm not criticizing, but I am curious if you have measured the power draw of any of those encoders in various states.

I haven't. Mostly I'm just trying to share what's worked well for me over the last year, and that includes the state devices begin and end in. If you have something that's working for you, with your mix of gear and streaming app, definitely go with it.

That's part of the reason I organized the scripts by device/app, which allows for this kind of variation. Timing can be a significant issue with remote control emulation, and that can be easily affected by your specific combination of stuff.

For anyone interested in the PBS app, my PR with scripts and sample m3u has been merged into the repo. The scripts use remote control emulation to navigate to the live stream. If you have more than one PBS affiliate in your area, the scripts know how to switch among them.

More info in the README.txt

And, now included in the multi-arch ah4c container! New bnhf/ah4c:latest (aka bnhf/ah4c:2024.06.21) with PBS app support courtesy of @wjcarpenter

1 Like

I'm curious, why do we need controls for the PBS app when the docker container works great and allows you to tune as many different PBS channels as you want?

I believe @wjcarpenter's primary motivation was to have Closed Captions, which aren't available in the vlc-bridge-pbs project.

Thanks, forgot about CC.