Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HLS support #16

Closed
attah opened this issue Jan 13, 2019 · 34 comments
Closed

HLS support #16

attah opened this issue Jan 13, 2019 · 34 comments

Comments

@attah
Copy link

attah commented Jan 13, 2019

What an amazing idea with a Dbus API! This basically solves the issue of all other developers having to do their own DLNA integration. (I arrived here from working on a a svtplay.se app for SFOS) However, I can't seem to add a HLS (http://x.y/z.m3u8) stream as an URL. Could you please look in to if that can be made possible?

I have separately verified that the renderer can play it when given the same url i tested with.

@mkiol
Copy link
Owner

mkiol commented Jan 14, 2019

It is so nice to hear that someone finds it useful 😄. If you have any special needs regarding API just let me know.

Yes, HLS (or DASH) is not supported.. but I can look into it and check what could be done. Could you please provide me (as an example) a URL to some content? It could be something from svtplay.se.

@mkiol
Copy link
Owner

mkiol commented Jan 14, 2019

BTW, Maybe you have already noticed it but also Kodimote exposes DBus API. For instance Quickddit uses it to share Youtube links.

@attah
Copy link
Author

attah commented Jan 14, 2019

I had actually missed that aspect of kodimote, and that it wasn't openrepos-only. I'll check on it too.
Any chances of seeing you on #sailfishos on freenode?
Here is a link, but probably due to expire in a week since it's a weather report:
http://svtplay2r-f.akamaihd.net/i/world/open/20190114/1392573-009A/PG-1392573-009A-VADER_,988,240,348,456,636,1680,2796,.mp4.csmil/master.m3u8
You can drop number values from the comma separated list to reduce the number of bitrates available, but keep a first and last comma.

Also, I'm not asking for HLS termination in the app itself, just relaying the URL to the renderer...
(HLS actually already works in the QML MediaPlayer, so more local playback isn't really needed)

Here is what i did to hackishly play stuff on my renderer (URL made to be variable, $1, not what i ran with though):

#!/bin/bash curl -H 'Content-Type: text/xml; charset=utf-8' -H 'SOAPAction: "urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI"' -d '<?xml version="1.0" encoding="utf-8"?><s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><u:SetAVTransportURI xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID><CurrentURI>$1</CurrentURI><CurrentURIMetaData></CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>' 'http://192.168.1.249:60099/AVTransport/control'

#!/bin/bash curl -H 'Content-Type: text/xml; charset=utf-8' -H 'SOAPAction: "urn:schemas-upnp-org:service:AVTransport:1#Play"' -d '<?xml version="1.0" encoding="utf-8"?><s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><u:Play xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID><Speed>1</Speed></u:Play></s:Body></s:Envelope>' 'http://192.168.1.249:60099/AVTransport/control'

Method from here: http://www.accella.net/knowledgebase/sending-a-video-content-to-a-dlnaupnp-softwaredevice-using-curl/

@mkiol
Copy link
Owner

mkiol commented Jan 16, 2019

Actually, Jupii does more than just passing URL. To provide as wide as possible compatibility with different renderers I've decided to proxy every HTTP stream. It enables me to implement additional features like removing in-stream meta data that "confuses" some devices. In current implementation when you add m3u URL Jupii tries to discover direct stream (direct URL to media resource) and than it downloads small portion of the data to find out what a media type and meta data of the stream is. Unfortunately this mechanism doesn't work well with HLS playlist...

Anyway, I will fix it by adding detection if m3u playlist is a HLS playlist instead regular one. Thanks to URL you provided I've already tested it and the fix seems to work fine with Kodi. I'm not sure how this test is representative because from my experience Kodi is extremely liberal in terms of accepting different variants of protocols, codecs and URLs. It literally can play anything!

The fix will be included in the next beta release (possibly in 2-3 days).

@attah
Copy link
Author

attah commented Jan 16, 2019

I realize that, and it is a very valuable feature, one that i could certainly not find the time to replicate. However, in this particular case it would be a good feature and perhaps sensible default option (not Jupii-global, but rather my use of it) to not proxy the stream and thereby drain the battery. Regardless of the outcome, thanks for your attention and dedication :)

BTW... there are really cheap ~$12 DLNA renderers on eBay etc "Mirascreen", i got a "V2" for testing this, since my TV is the wrong class of device. I will at least test with that.

@mkiol
Copy link
Owner

mkiol commented Jan 19, 2019

In 7e35a99 I've added fix to detect HLS playlist and apply proxy-less handling. It is just "workaround" rather than final solution. As you suggested, I have to re-think this "proxy everything" concept and introduce less radical approach.

I would be grateful if you could test Jupii recent 2.2.0 release (it is available via OpenRepos).

@attah
Copy link
Author

attah commented Jan 19, 2019

Thanks for that! Proxying everything in the spirit of compatibility is a fair first version, nothing wrong with that... but optimizations/improvements are nice :)

I need to fix my reading comprehension... I built my own from source, but that should be equivalent i guess.
Seems to work fine for just inputting the uri, both with proxying and without. Haven't done the dbus integration on my side, but i should get going with that now. One thing though, are there no controls apart from volume?

One thing with running in proxy mode is that the automatic bitrate selection was using a quite low setting, delegating it worked better (for me, this time). I'm already planning to limit the bitrate choices on my end with the stupid and specific method i described previously. A generic implementation suitable for Jupii might be harder.

Btw, may i steal your icon-m-device.png for using as an icon for invoking Jupii from my app?

@attah
Copy link
Author

attah commented Jan 19, 2019

Didn't have time to start hacking until now in the evening, but POC is coming along nicely (i.e. i can add streams to Jupii from my app).
I guess i had sort of expected addUrl to do more of playUrl, but keeping the "old" streams there has its use... Probably mainly need to figure out how to switch to jupii, if at all possible.

@attah
Copy link
Author

attah commented Jan 19, 2019

I threw in a "MimeType=x-scheme-handler/jupii;" to the harbour-jupii.desktop file. xdg-open jupii:// does launch the app, but a new instance of it, but Qt.openUrlExternally("jupii://") in my app does nothing. Oh, and adding the same url again does just that... it will appear multiple times in the list in the list. Any interface where i could avoid this would be much appreciated.

@mkiol
Copy link
Owner

mkiol commented Jan 20, 2019

Very briefly, everything is doable. For instance I can add new methods to DBus API like: addUrlOnce and addUrlOnceAndPlay... Right now I'm not available for few days but when get back I will go through all your questions/ideas.

@mkiol
Copy link
Owner

mkiol commented Jan 26, 2019

Hello.. I'm back

One thing though, are there no controls apart from volume?

Definitely they are. Just tap on bottom panel. It will expand and other controls will be visible. Like on this screenshot.

may i steal your icon-m-device.png

Sure, no problem. I will be delighted. Raw SVG files are here.

i had sort of expected addUrl to do more of playUrl, but keeping the "old" streams there has its use
Oh, and adding the same url again does just that... it will appear multiple times in the list in the list

You right it is useless in the current form. In df61f30 I've added new methods: addUrlOnce and addUrlOnceAndPlay. Description and API details are in org.jupii.xml. Hopefully It will address all your use cases. If not just let me know.

@attah
Copy link
Author

attah commented Jan 26, 2019

Thanks, awesome work!
I had completely missed the bottom panel... but now when i know what to look for i can see it appearing and then quickly disappearing when starting to play something.
I've compiled a new version, which didn't change anything in that regard. Digging in to the logs to see if i can understand what went wrong.

It happens during this log snippet anyway:
https://pastebin.com/Wk7MdXe7

BTW... Jupii hangs for me if i power off the DLNA renderer. Should i open a separate issue?

@attah
Copy link
Author

attah commented Jan 26, 2019

Another thought and possible feature request related to this... it would be neat if one could raise/front/activate/... Jupii from the invoking app, either explicitly or as part of addUrlOnceAndPlay.

Currently i do Qt.openUrlExternally(Qt.resolvedUrl("/usr/share/applications/harbour-jupii.desktop"))
which works well enough... it just feels wrong...

One example of what i was thinking is perhaps:
https://github.com/sailfishos/sailfish-office/blob/fdf5a30468f0b79ac975f2215abf3e51b435e3df/dbusadaptor.cpp#L42

@mkiol
Copy link
Owner

mkiol commented Jan 27, 2019

I had completely missed the bottom panel... but now when i know what to look for i can see it appearing and then quickly disappearing when starting to play something.

[D] AVTransport::updateCurrentTransportActions:1384 - CurrentTransportActions:
[D] AVTransport::updateCurrentTransportActions:1385 -   actions: 4
[D] AVTransport::updateCurrentTransportActions:1386 -   Next: 0
[D] AVTransport::updateCurrentTransportActions:1387 -   Pause: 0
[D] AVTransport::updateCurrentTransportActions:1388 -   Play: 4
[D] AVTransport::updateCurrentTransportActions:1389 -   Previous: 0
[D] AVTransport::updateCurrentTransportActions:1390 -   Seek: 0
[D] AVTransport::updateCurrentTransportActions:1391 -   Stop: 0

It is weird but your device reports that only Play action is supported. The control panel is visible only when you can use it. When content is playing, you cannot do anything so, the panel gets hidden.

I've notice that you enabled "Redirection mode". Please try to use "Proxy" instead. In Proxy mode Jupii adds extra HTTP header contentFeatures.dlna.org which contains "magic" flags that tell DLNA renderer what are the stream capabilities. I've added extra hook for HLS so in Proxy mode, Jupii will relay only playlist file but the actual video stream will go directly. Maybe lack of DLNA flags is the problem.

Additionally, could you please check if you can play video/audio files stored on your phone and control panel is visible?

Jupii hangs for me if i power off the DLNA renderer.

Yes. I'm aware of that. I'm going to fix it but is has low priority right now.

@attah
Copy link
Author

attah commented Jan 27, 2019

Yes, quite weird... Volume does work, and that's a pretty worthless feature compared to play/pause.
Is that reported/handled separately?
It's not every time that the controls flash past, sometimes they just never appear. I've tried with proxy mode and local video, no difference. Logs for playback of local file: https://pastebin.com/6rDVkr4X

@attah
Copy link
Author

attah commented Jan 27, 2019

I can confirm that it can at least pause, reporting could still be haywire of course. I took my curl example above replaced Play with Pause throughout. Didn't even have to take out the speed entry. Tested with both a file that was local to the phone, and a redirected stream.

@mkiol
Copy link
Owner

mkiol commented Jan 27, 2019

Volume does work, and that's a pretty worthless feature compared to play/pause.
Is that reported/handled separately?

Yes. Volume control is a part of completely different UPnP service (RenderingControl) and they are handled separately. Support for Play/Pause/Stop/Seek can be retrieved with GetCurrentTransportActions action (for reference check chapter 2.4 of AVTransport spec). It appears that your device sends back that only Play is supported. You already confirmed that Pause works as expected, so possibly it is just a crappy UPnP implementation.

In 3b49b74 I've added workaround to ignore GetCurrentTransportActions result. Could you please test it? It is new branch (ignore-actions-supported), so you need to checkout to it first.

@attah
Copy link
Author

attah commented Jan 27, 2019

That made controls work. :)
This is that output after pausing:

[D] AVTransport::updateCurrentTransportActions:1394 - CurrentTransportActions:
[D] AVTransport::updateCurrentTransportActions:1395 -   actions: 2
[D] AVTransport::updateCurrentTransportActions:1396 -   Next: 0
[D] AVTransport::updateCurrentTransportActions:1397 -   Pause: 2
[D] AVTransport::updateCurrentTransportActions:1398 -   Play: 0
[D] AVTransport::updateCurrentTransportActions:1399 -   Previous: 0
[D] AVTransport::updateCurrentTransportActions:1400 -   Seek: 0
[D] AVTransport::updateCurrentTransportActions:1401 -   Stop: 0

I'll see if I can't poke around the querying a bit.

@attah
Copy link
Author

attah commented Jan 27, 2019

Output of GetCurrentTransportActions
Paused:

<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <u:GetCurrentTransportActionsResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
<Actions>Pause</Actions>
      </u:GetCurrentTransportActionsResponse>
   </s:Body>

Playing:

<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <u:GetCurrentTransportActionsResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
<Actions>Play</Actions>
      </u:GetCurrentTransportActionsResponse>
   </s:Body>
</s:Envelope>

And did I mention seeking works?
smh

@mkiol
Copy link
Owner

mkiol commented Jan 28, 2019

It is very very weird.. but it's funny as well. It seems that GetCurrentTransportActions returns current transport state instead available actions. When state is Paused device returns that only Pause action is available, when state is Playing it returns Play action. It should be completely opposite.

The only solution I see right now is to add extra switch (in the Settings) to assume that all control actions are always supported.

@attah
Copy link
Author

attah commented Jan 28, 2019

Yes indeed. I suspect there may be a language barrier between the spec and the implementers.
That is a very good solution, thanks. :) Perhaps something to indicate to the user that the Renderer reported no supported actions too, instead of controls being completely missing.
Interestingly enough, they responded to a support request. Sure it's still the normal first line crap, but maybe, just maybe they can even fix it.

@mkiol
Copy link
Owner

mkiol commented Feb 5, 2019

Just to sum up. Extra configuration option (switch in the Settings) could be too much confusing so I've resolved it differently. From 8f87a27 supported actions retrieved with GetCurrentTransportActions will be ignored if they are meaningless like in the examples above.

@attah
Copy link
Author

attah commented Feb 16, 2019

Any chance of a release in Harbour?
I'm to a level where I'm considering to release the svt play app, not that I'm in a hurry, or that Jupii integration is completely essential. Anyway, here is my attempt at an abstraction for integration https://github.com/attah/harbour-s2play/blob/master/qml/pages/JupiiConnection.qml

@mkiol
Copy link
Owner

mkiol commented Feb 17, 2019

Yes, Jupii is now ready for the release. Actually, it awaits to be approved by Harbour reviewer.

Anyway, here is my attempt at an abstraction for integration

Looks awesome. Additionally you could also use canControl property. When it is true it means that Jupii is connected to DLNA device and it makes sense to use AddX methods. Here is my super simple QML app that I'm using to test DBus. The canControlPropertyChanged function is called whenever canControl property get changed. For instance, in your app, "send to Jupii" button could be visible only when canControl is true.. I've copied this concept from Quickddit and Kodimote DBus integration.

@attah
Copy link
Author

attah commented Feb 17, 2019

Great news :)
For a while there the signal handler wasn't working for me, but it is and it seems i can simplify down to where the whole component is just the DBusInterface, no visibility hook needed. Thanks. I'll let it stew and see if i lost any robustness.

@attah
Copy link
Author

attah commented Feb 17, 2019

Meh, it's not reliable for me... so doing a compromise

@mkiol
Copy link
Owner

mkiol commented Feb 18, 2019

Just an info => Jupii 2.2.2 release is now available in Harbour

@attah
Copy link
Author

attah commented Apr 14, 2019

Any chance you could add bringing Jupii to front/focus when the addUrlOnceAndPlay method is invoked?
Seems Jolla broke my way of "doing it for you" (suggestion for what to do in link)
https://together.jolla.com/question/201843/3028-xdg-open-desktop-dont-open-application-anymore/?comment=202115#comment-202115

@mkiol
Copy link
Owner

mkiol commented Apr 15, 2019

Done in a7d9b15.

@attah
Copy link
Author

attah commented Apr 15, 2019

Thanks, works great!

@carlosgonz0
Copy link
Contributor

It is not HLS already supported?

@mkiol
Copy link
Owner

mkiol commented Mar 12, 2020

It is not HLS already supported?

I would not say that HLS is 100% supported. There is a workaround.

When URL points to HLS playlist (special kind of M3U playlist) Jupii pass this playlist without any change to UPnP device. It might work for some devices (Kodi for instance) but for most it will not work because devices don't understand HLS.

The ideal implementation would be to convert on-the-fly HLS to "normal" single bit-rate stream and then pass this stream to UPnP device. It is possible but hard to implement.

@carlosgonz0
Copy link
Contributor

carlosgonz0 commented Mar 12, 2020

I know that you can implement HLS 100%. ; )

@mkiol
Copy link
Owner

mkiol commented Feb 7, 2024

Closing this old issue report. HLS (but only for audio) is supported from version 2.14.

@mkiol mkiol closed this as completed Feb 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants