-
Notifications
You must be signed in to change notification settings - Fork 47
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
Add a callback to select which element are written #173
Conversation
51eb97d
to
844f7ac
Compare
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.
Interesting, thanks. I haven't tried converted MKVToolNix yet & cannot say how much work supporting both types of interfaces would be & whether I like it or not. Fact is that this type of interface change does require a substantial amount of changes, whereas the simple flag/toggle I suggested to add in the elements wouldn't. On the other hand callback-type systems are more flexible. But do we really need that flexibility?
Have to think about it some more.
@@ -601,21 +601,21 @@ filepos_t EbmlElement::OverwriteData(IOCallback & output, bool bKeepPosition) | |||
|
|||
auto CurrentPosition = output.getFilePointer(); | |||
output.setFilePointer(GetElementPosition() + HeaderSize); | |||
auto Result = RenderData(output, true, bKeepPosition); | |||
auto Result = RenderData(output, true, bKeepPosition ? WriteAll : WriteSkipDefault); |
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 don't understand the intent behind this change. What does keeping the position have to do with the question whether or not to write the element?
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 is just the translation of the previous call into the new system. bKeepPosition
would be used as the bWithDefault
value. So if it's true it writes elements even if they are the default value (WriteAll), if it's false it only writes the elements if they are not the default value (SkipDefault).
The original logic may be flawed and it should be fixed separately. In fact when overwriting you'd probably want to tell which elements you want to write (the least possible).
This whole API is a recipe for broken files (which originally was a welcome possibility in libebml to be able to generate broken files to test against). It seems mkvtoolnix doesn't use it, there's only a test calling OverwriteHead(). So I'd rather remove the API altogether.
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.
Ah, I see. Thanks for the explanation. Yeah, MKVToolNix (or rather: mkvpropedit
) only uses OverwriteHead
for cases where it has to cover a one-byte space that's suddenly left by other operations; in such a case it forces the element size field to be one byte longer than necessary.
It never uses OverwriteData
, though. If it has to overwrite a whole element, I think it simply uses Render
& sets the file position manually.
@@ -413,4 +427,6 @@ class EBML_DLL_API EbmlElement { | |||
|
|||
} // namespace libebml | |||
|
|||
#define EBML_WRITE_FILTER 1 |
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… don't like this #define
. Consumers can already use the version number #defines
in order to differentiate between v1 & v2 of the library.
Not sure how I'll handle it in MKVToolNix. Will have to look into how many places will have to be changed as I'm generally not a fan of a lot of conditional compilation anyway. Maybe I'll just throw the switch & require v2 as soon as I add support for 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.
The define is there to tell v2 users which API they can expect. Once v2 is stable we can remove it and everyone should assume it's there for v2 code. In other words it's to make your life easier if you want to support the old and new API in your codebase for a while. I don't mind removing it and you handle it on your side.
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.
Makes sense, but isn't needed, at least not for me. As there's no official release of v2 yet, I won't support different snapshots of the upcoming v2 API in MKVToolNix. I'll try my best to support v1 & the latest v2 simultaneously, but even that is in question with this RFC.
There's either the ForceNoDefault() we currently have which tells a specific instance it's not it's default value (even when it does, completely changing the meaning of the IsDefault test). Even if you change the value after. Or we keep the IsDefault meaning intact and change the logic to tell if an element has to be written. Maybe we can still add a flag in each instance that would replace the ForceNoDefault(). But IMO it's intrusive and wastes space in each and every instance. While passing the "algorithm" to decide how to store it when we do seems less intrusive. Being less intrusive you don't have to have a |
844f7ac
to
40d64d9
Compare
Also this kind of "agnostic" filter means we can also select which element to write based on the Matroska version targeted. When writing a v2 file, you don't want to end up writing v4 or v5 elements. Once we have the supported version inside each element class, we can easily do that. |
Hmmm I somehow wasn't aware of |
Not sure if that would actually help me. MKVToolNix does it the other way around: it first writes v2 as the If the library routines need to know what to use before the whole file is written, a lot would have to changed in MKVToolNix. Or I'd simply have to use a filter callback that ignores the profiles altogether so that the existing code continues to work. For me this type of feature be an advantage. |
I wasn't sure if I should add an opaque pointer (or if there's a cleaner way in C++ for such callbacks) but it might be useful in your case. During the write phase each element written goes through your filter which could collect the highest profile used. Not that you'd have to implement it this way, but it might be useful as a generic solution. |
40d64d9
to
f735b15
Compare
I've finished the required modifications in MKVToolNix. All in all I'm fine with this change if the callback type is changed to the aforementioned On top of that the only remaining change I'd like to ask for is the other aforementioned one, getting rid of that one unused variable warning. Thanks. |
I've pushed branch |
This is more flexible than a flag that applies to all the elements inside a Master. It can now be filtered by element, based on their ID, position, profile, etc. A EBML_WRITE_FILTER define is added to be able to check libmatroska 2.0 with this feature or not.
This is a hack to pretend an element doesn't have its default value so it ends up being written.
16d5d6a
to
8b6c24e
Compare
And remove the ForceNoDefault() which is not needed anymore.
There's a
EBML_WRITE_FILTER
define to tell between libmatroska versions with this feature or not.