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

opus stream chaining #205

Merged
merged 1 commit into from Feb 26, 2018
Merged

opus stream chaining #205

merged 1 commit into from Feb 26, 2018

Conversation

cathugger
Copy link
Contributor

support for chaining streams to enable changing stream' metadata on the fly.
currently support is opt-in because lots of clients can't handle this properly yet.

@MaxKellermann
Copy link
Member

Without looking at the code: if your PR contains text, this means that your commit message is bad.

@cathugger
Copy link
Contributor Author

should I change it?

@MaxKellermann
Copy link
Member

Please fold the two commits (the second one is just fixup for the first one, even though it's not documented that way) and add a proper commit message.
Your first patch is hard to read because you moved original code around and renamed a method; that appears in the diff, even though nothing (but the method name) was changed. Please move that back so I can read your patch properly.

@cathugger
Copy link
Contributor Author

@MaxKellermann done. it's hard to read because back when I changed it, it was kind of rewrite.
there are some changes on how it inserts tags into stream (old version overrides Read() to inject them, my version pushes them when tags appear because otherwise I'd need to hold tags somewhere waiting for Read() and doing that didn't make much sense to me).
also some unrelated changes like changing mime type from "audio/ogg" to "audio/ogg; codecs=opus" because that made more sense to me (I can get rid of this one if you want, I didn't observed any changes in clients from it).

@cathugger
Copy link
Contributor Author

@MaxKellermann I attempted to make it easier to review by moving functions to be closer to their original locations

@@ -183,24 +190,25 @@ OpusEncoder::~OpusEncoder()
void
OpusEncoder::DoEncode(bool eos)
{
assert(buffer_position == buffer_size);
if (!eos)
assert(buffer_position == buffer_size);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't call a macro after an if statement without curly braces, because this is unsafe; and it doesn't make sense to check the eos flag in the non-debug build. It's better to move that check into the assert().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do

@@ -84,7 +88,7 @@ class PreparedOpusEncoder final : public PreparedEncoder {
Encoder *Open(AudioFormat &audio_format) override;

const char *GetMimeType() const override {
return "audio/ogg";
return "audio/ogg; codecs=opus";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change has nothing to do with chaining feature, does it? Should be a separate commit; I can cherry-pick such a tiny commit easily, even if there are issues left with the "large" commit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it has nothing to do with chaining feature, yes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From RFC 7845:
An "Ogg Opus file" consists of one or more sequentially multiplexed
segments, each containing exactly one Ogg Opus stream. The
RECOMMENDED mime-type for Ogg Opus files is "audio/ogg".

If more specificity is desired, one MAY indicate the presence of Opus
streams using the codecs parameter defined in [RFC6381] and
[RFC5334], e.g.,

                        audio/ogg; codecs=opus

for an Ogg Opus file.

so I guess I should leave it as audio/ogg, as it's recommended

};

class PreparedOpusEncoder final : public PreparedEncoder {
opus_int32 bitrate;
int complexity;
int signal;
bool chaining;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this const and use a C++ initializer in the constructor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rest of things are parsed and initialized inside PreparedEncoder::PreparedEncoder()'s body.
I just did things in consistent way. Should I really change this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

though they all had reason to be in body, because they couldn't be done with just initializer so I guess I will

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's because the other attributes have more complex parsers. But I welcome patches which move the parsers into separate (throwing) functions and make the other attributes const as well. The old code was from a time when MPD had C++ exceptions disabled (-fno-exceptions) and error handling was different (more complicated).

if (result < 0)
throw std::runtime_error("Opus encoder error");

granulepos += buffer_frames;
granulepos += buffer_position / frame_size;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this change about?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on final stream packet (one with eos set), we are allowed to have granulepos less than packet actually contains. decoder should take smaller granulepos into account and discard unused data. this is for stream cutting - we need to push final packet to inject tags, but we don't have enough data for whole packet. therefore we encode full packet, but specify lesser granulepos.

@@ -52,30 +53,33 @@ class OpusEncoder final : public OggEncoder {

ogg_int64_t packetno = 0;

ogg_int64_t granulepos;
ogg_int64_t granulepos = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need to be initialized now? Was this a bug previously, or did your other code changes require it?

Copy link
Contributor Author

@cathugger cathugger Feb 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this a bug previously

probably. it's not initialised anywhere else. technically granulepos in stream can start from any value, so decoders probably didn't complain and it was unnoticed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, so this change has nothing to do with this patch. Separate patch, please, so I can cherry-pick this into the stable branch v0.20.x

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MaxKellermann
Copy link
Member

Thanks, much better now. And each time before you push, please rebase on my master branch.

@cathugger
Copy link
Contributor Author

@MaxKellermann did changes you requested. didn't fold yet to not disturb previous review

@cathugger
Copy link
Contributor Author

squashed

@MaxKellermann
Copy link
Member

Thanks, this looks good now. Now what's missing is a patch for doc/user.xml with documentation and maybe a NEWS line telling people about it, then I'll merge it.

@cathugger
Copy link
Contributor Author

@MaxKellermann documented.
hopefully I got docs syntax right.
NEWS line isn't exactly same as commit message, I hope that's ok.

@cathugger
Copy link
Contributor Author

uh, documentation isn't quite correct, it uses ICY headers only in case of http output plugin. need to fix

@cathugger
Copy link
Contributor Author

fixed documentation. now should be all good.

support for chaining ogg opus streams to enable changing stream' metadata on the fly.
currently support is opt-in (enabled by additional option) because lots of clients can't handle this properly yet.
@cathugger
Copy link
Contributor Author

pushed some minor syntax fixes

@MaxKellermann MaxKellermann merged commit 47d1d3c into MusicPlayerDaemon:master Feb 26, 2018
@cathugger cathugger deleted the opustags-pr branch February 26, 2018 21:59
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

Successfully merging this pull request may close these issues.

None yet

2 participants