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
opus stream chaining #205
Conversation
|
Without looking at the code: if your PR contains text, this means that your commit message is bad. |
|
should I change it? |
|
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. |
|
@MaxKellermann done. it's hard to read because back when I changed it, it was kind of rewrite. |
|
@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); | |||
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 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().
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.
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"; | |||
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.
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.
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.
it has nothing to do with chaining feature, yes
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.
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; |
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.
Make this const and use a C++ initializer in the constructor.
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.
rest of things are parsed and initialized inside PreparedEncoder::PreparedEncoder()'s body.
I just did things in consistent way. Should I really change this?
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.
though they all had reason to be in body, because they couldn't be done with just initializer so I guess I will
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.
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; |
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.
What is this change about?
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.
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; | |||
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.
Why does this need to be initialized now? Was this a bug previously, or did your other code changes require it?
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.
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.
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'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
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.
|
Thanks, much better now. And each time before you push, please rebase on my master branch. |
|
@MaxKellermann did changes you requested. didn't fold yet to not disturb previous review |
|
squashed |
|
Thanks, this looks good now. Now what's missing is a patch for |
|
@MaxKellermann documented. |
|
uh, documentation isn't quite correct, it uses ICY headers only in case of http output plugin. need to fix |
|
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.
|
pushed some minor syntax fixes |
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.