Saturday 24 December 2016

Raspberry Pi Kodi CEC for Yamaha A/V Receiver

CEC works out of the box on Kodi on the Pi but not if you have an A/V Receiver and a projector rather than a TV.

If can put put right in the settings in Kodi if you have a working remote but a mouse doesn't seem to do it.

Copying the relevant config file from a working system is the easiest way. For me this file gets created as:
 
/home/kodi/.kodi/userdata/peripheral_data/rpi_2708_1001.xml

2708:1001 is the device ID for the pi's CEC adapter.

The contents of my file are:

<settings>
    <setting id="activate_source" value="0" />
    <setting id="button_release_delay_ms" value="0" />
    <setting id="button_repeat_rate_ms" value="0" />
    <setting id="cec_hdmi_port" value="1" />
    <setting id="cec_standby_screensaver" value="0" />
    <setting id="cec_wake_screensaver" value="1" />
    <setting id="connected_device" value="36037" />
    <setting id="device_name" value="Kodi" />
    <setting id="device_type" value="1" />
    <setting id="double_tap_timeout_ms" value="300" />
    <setting id="enabled" value="1" />
    <setting id="pause_playback_on_deactivate" value="1" />
    <setting id="physical_address" value="0" />
    <setting id="port" value="" />
    <setting id="send_inactive_source" value="1" />
    <setting id="standby_devices" value="231" />
    <setting id="standby_devices_advanced" value="" />
    <setting id="standby_pc_on_tv_standby" value="13005" />
    <setting id="standby_tv_on_pc_standby" value="1" />
    <setting id="tv_vendor" value="0" />
    <setting id="use_tv_menu_language" value="1" />
    <setting id="wake_devices" value="231" />
    <setting id="wake_devices_advanced" value="" />
</settings>

Saturday 17 December 2016

MPEG-DASH and HLS with Gstreamer

Gstreamer does a good job with the modern streaming protocols.

The command line client gst123 can be used to listen to BBC AoD and live streams.

BBC AoD streams can be found here: BBC World Service AoD feed (replace worldservice with your channel of choice).

BBC Live streams can be found here: BBC IMDA transports

Here are some examples using gst123:

Play an MPEG-DASH stream listed in imda_transports.xml:

gst123 -q http://a.files.bbci.co.uk/media/live/manifesto/audio/simulcast/dash/nonuk/dash_low/ak/bbc_radio_three.mpd

Play an HLS stream listed in imda_transports.xml:

 gst123 -q http://a.files.bbci.co.uk/media/live/manifesto/audio/simulcast/hls/uk/sbr_vlow/llnw/bbc_radio_three.m3u8

Play an on-demand DASH stream from Radio 4 (you will need to look in the xml file for a current programme):

 gst123 -q http://open.live.bbc.co.uk/mediaselector/5/redir/version/2.0/mediaset/audio-syndication-dash/proto/http/vpid/b084d7wf

It is really easy to roll your own Gstreamer based player using python. There are some examples here.

I rolled this one by adding command line processing to basic-tutorial-1:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import sys
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst
Gst.init(None)

# Build the pipeline
pipeline = Gst.parse_launch("playbin uri=%s" % sys.argv[1
# Start playing
pipeline.set_state(Gst.State.PLAYING)

# Wait until error or EOS
bus = pipeline.get_bus()
msg = bus.timed_pop_filtered(
    Gst.CLOCK_TIME_NONE, Gst.MessageType.ERROR | Gst.MessageType.EOS)

# Free resourcespipeline.set_state(Gst.State.NULL)

Then you can use the same example streams:

./gst.py http://a.files.bbci.co.uk/media/live/manifesto/audio/simulcast/dash/nonuk/dash_low/ak/bbc_radio_three.mpd

./gst.py http://a.files.bbci.co.uk/media/live/manifesto/audio/simulcast/hls/uk/sbr_vlow/llnw/bbc_radio_three.m3u8

It only takes a little more effort to make something useful. The following python3 script takes the name of a programme and the url of an AoD feed on the command line and plays the latest episode of that programme:

# Free #!/usr/bin/env python3
# -*- coding:utf-8 -*-
import sys
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst
from xml.etree import ElementTree
from datetime import datetime
import arrow
from urllib.request import urlopen

Gst.init(None)

# Get a url

title = sys.argv[1]
feed = sys.argv[2]
now = arrow.utcnow()
wanted = now.replace(hours=-1)
with urlopen(feed) as f:
    tree = ElementTree.parse(f)
for node in tree.iter('entry'):
    for entry in node.iter('parent'):
        if entry.text == title:
            for field in node.iter():
                if field.tag == 'link' and field.attrib.get('transferformat') == 'dash':
                    thisurl = field.text
                if field.tag == 'availability':
                    start = arrow.get(field.attrib.get("start"))
                    end = arrow.get(field.attrib.get("end"))
                    if (start <= now) and (now <= end) and (start > wanted):
                        wanted = start
                        url = thisurl
# Build the pipeline
pipeline = Gst.parse_launch("playbin uri=%s" % url)

# Start playing
pipeline.set_state(Gst.State.PLAYING)

# Wait until error or EOS
bus = pipeline.get_bus()
msg = bus.timed_pop_filtered(
    Gst.CLOCK_TIME_NONE, Gst.MessageType.ERROR | Gst.MessageType.EOS)

# Free resources
pipeline.set_state(Gst.State.NULL)


So you can do this:

./bbcaod.py   "BBC News" http://www.bbc.co.uk/radio/aod/availability/worldservice.xml