-
Notifications
You must be signed in to change notification settings - Fork 234
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
[streaming] support multiple output formats #982
[streaming] support multiple output formats #982
Conversation
bc2de86
to
4104639
Compare
I know this is not really the place to make a feature request but supporting HLS could be pretty cool! |
@ejurgensen - this should be good to ask for your input on the refactoring to support additonal streaming formats. I've given this a bit more testing and there's nothing untoward I see from the refactoring. |
streaming_not_supported = 1; | ||
DPRINTF(E_LOG, L_STREAMING, "Will not be able to stream %s, libav does not support encoding: %d/%d/%d @ %d\n", ctx->name, ctx->quality_out.sample_rate, ctx->quality_out.bits_per_sample, ctx->quality_out.channels, ctx->quality_out.bit_rate); | ||
ctx->not_supported = 1; | ||
streaming_end(ctx); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The addition of streaming_end(..)
is a bug fix - if we don't have this, the sessions
list is never cleared down so the player will continue to send data and we reenter here.
@ejurgensen - do you still want to proceed with this enhancement or comments on the structure here? I think the original requestor wanted to stream this to their Roku Soundbridge but it appears that the Roku does not support a http/streamed pcm and therefore that particular use case is no longer valid. It does not negate the work here though as the structure should easily allow additional formats (maybe HLS or aac) to be supported if |
I haven't looked so much into this, but I think more formats is fine, so it's on my todo list. I am wondering about the choice of pcm, why not at least wav? Pcm has no headers, so the receiver has to know sample rate and format a priori. Maybe that is why it is not working on the Roku? Wav is also a bit of bandwidth hog, what about flac or some other lossless format? |
For my use case, soundbridge, wav is a known option. Windows lossless is
also supported by the soundbridge.
I recently did some experiments with Plex transcoding from FLAC to wav with
the soundbridge over upnp and was unsuccessful there as well.
When I finish converting all my music from mp3 to FLAC, I will be circling
back around to both forked-daapd and plex experimentation.
…On Tue, May 19, 2020 at 4:33 PM ejurgensen ***@***.***> wrote:
I haven't looked so much into this, but I think more formats is fine, so
it's on my todo list.
I am wondering about the choice of pcm, why not at least wav? Pcm has no
headers, so the receiver has to know sample rate and format a priori. Maybe
that is why it is not working on the Roku?
Wav is also a bit of bandwidth hog, what about flac or some other lossless
format?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#982 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/APETTJRNG5GXSPQ6ZDBSR7TRSL3KRANCNFSM4MXH4OCA>
.
|
@ejurgensen - yes, the PCM/wav was added to help with the original @frankusb request. In fact, the code is sending headers so the name is misleading and I should fix that - as for the Soundbridge not supporting the stream, it might be that SB doesn't support anything other than streamed mp3. supported Roku streaming formats
However the primary focus of this PR should really be about the structure/refactor of the streaming module to be able to support other streaming formats. I can drop the PCM stream from this PR (it's just dropping it out of |
A couple other thoughts. Roku Soundbridge also supports Apple Lossless (ALAC). During my Plex UPnP experiment, I noticed that when the Soundbridge requested a file to play, Plex responded with an http link. So I think that will be my next experiment. Put a WAV file on Plex and see if it provides it via http and if the Soundbridge can play it. |
@frankusb - can you try to setup Plex to stream to your roku
The first two are apparently supported based on Roku's old old webite link (https://soundbridge.roku.com/soundbridge/internet.php). If you can serve the top 2 to the roku but not the wav, it'd suggest the Roku doesnt support that streamming format. |
a80518e
to
74e89ab
Compare
6c546f3
to
092e532
Compare
@whatdoineed2do, my results are.
|
@ejurgensen - I've split this PR off into structural change so that we're not relying on globals/can add other streaming formats along with some additional commits to add streaming support for wav and flac - the latter of which we can drop easily out of this PR if you feel like that needs a little more attetion. If you can take a look this'll be great. @frankusb - thanks, it does suggest that the SB doesnt like those other formats (non MP3/wma) as per the link I shared. |
Good news, I got WAV playing from Plex today. The Soundbridge shows Kind: WAV audio file while playing back. I believe the key was adding:
The Plex log below Jun 02, 2020 16:32:06.038 [0x7f80dbfff700] DEBUG - Proxied GET to http://127.0.0.1:32400/library/parts/124454/1591130247/file.wav?X-Plex-Token=xxxxxxxxxxxxxxxxxxxx: HTTP/1.1 200 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've had a look at this pr, but didn't get to go through it all. There is one basic issue, which is that the change involves having the streaming output do it's own transcoding, and output modules are not supposed to do that. They should leave this to the output via the subscription function. This has the advantage that the output middle layer takes care that no double transcoding is done. So you need to refactor this PR to make use of this. Perhaps you should make an entirely new PR, and just close this one. Some of my other comments probably won't apply either after such a refactor.
|
||
// Means we're not able to encode to mp3 | ||
static bool streaming_not_supported; | ||
static struct streaming_ctx streaming_ctxs[] = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Below you only need to define the stuff that is non-zero
struct streaming_session *this; | ||
struct streaming_session *session; | ||
struct streaming_session *prev; | ||
char *address; | ||
ev_uint16_t port; | ||
|
||
this = (struct streaming_session *)arg; | ||
this = ctx->sessions; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not used any more (plus it seems confusing that "this" is the head of the list, not the actual session)
pthread_mutex_lock(&streaming_sessions_lck); | ||
if (!streaming_sessions) | ||
pthread_mutex_lock(&ctx->sessions_lck); | ||
if (!ctx->sessions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there might be something wrong here. Before "this" pointed to the session, but now it looks like it points to the head of the list - so is the name still correct? Also why is "this" being set, but not used in the if test above? Plus the comment says that "this" may be a dangling pointer, and in that case (!ctx->sessions) will not be true, so in that context the comment doesn't make sense any more.
else | ||
prev->next = session->next; | ||
|
||
++(ctx->available_sessions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Counters like this are dangerous, they easily go out of sync without any clear signs. When operating with a fixed max number of sessions it is maybe better to have corresponding fixed array size of ctx->sessions (so not a linked list). When you want a new session you look for a free slot, and when a session ends you zero a slot.
|
||
while (ctx->name) | ||
{ | ||
pthread_mutex_lock(&ctx->sessions_lck); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You cannot lock here, since it can block the player thread. I think you need to keep the simple global variable here.
const enum transcode_profile xcode; | ||
|
||
pthread_mutex_t sessions_lck; | ||
struct streaming_session *sessions; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The data model seems to be two way, since streaming_session->ctx points at a streaming_ctx, and streaming_ctx->sessions points at a list of sessions. That means ownership is somewhat unclear. I think you should consider a more simple model where you don't point both ways. I would think that you should have streaming_session->ctx, but not the other way around.
ret = write(streaming_meta[1], &obuf->data[0].quality, sizeof(struct media_quality)); | ||
pthread_mutex_lock(&ctx->sessions_lck); | ||
if (!ctx->sessions) | ||
goto next; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just unlock and continue, don't use goto for this
Let me close this and have another look when I free up. In the meantime, I'll put in the oneliner fix for when libav doesnt support MP3 encoding since currently it doesnt drop the client leading to the server always trying to get a decoding ctx |
closes #971 - support additional streaming formats to mp3
The work consists mostly of rework of all static globals used to track and manage streaming are now moved to a
streaming_ctx
structure which represents a single streaming format (ie mp3, pcm44.1, pcm 48). For each different stream format we have anotherstreaming_ctx
structure.The supported streaming formats are defined in the
streaming_ctxs[]
array. Streams available at:* http://forked-daapd:3689/stream48k.pcmTested this with multiple concurrent mp3/pcm streams (played with
mpv
) sub/unsub/resub and it seems good.Will leave this in draft for requester @frankusb to help with testing and structural commentsThere is one bug fix dealing with handling unsupported encoding and a commit to limit the number of client streams - the last one is to address the potential resource starvation in the shared
httpd
event_base
loop