The prior algorithm summed up all Opus frame's number of samples and
calculated the expected timestamp from there. That expected timestamp
was compared to the Ogg page's granule position, and the discard
padding was calculated from that.
This lead to problems in several cases:
1. When the first packet's granule position was bigger than the number
of samples in the Opus frame, the specs say that the first sample's
timestamp is positive in that case. mkvmerge was wrongfully using 0
as the timestamp and thought discard padding was needed in such a
case.
2. When the first packet's granule position was smaller than the
number of samples in the Opus frame (meaning the first sample's
timestamp was negative), a technically invalid bitstream, mkvmerge
was wrongfully forcing the first packet's timestamp up to 0 and
inserting discard padding elements all over the place as its
internal calculations got confused.
The new algorithm bases the calculation on the last known granule
position special-casing for certain Ogg packet numbers:
1. For the first Ogg page the timestamps of all packets is calculated
by subtracting each packet's number of samples from the page's
granule position in reverse order. This may result in the first
packet's timestamp being positive, which mkvmerge now preserves.
mkvmerge won't calculate a discard padding for this page.
2. For all other pages each packet's timestamp is calculated by adding
each packet's number of samples to the previous Ogg page's end
timestamp as given by its granule position.
mkvmerge then calculates the discard padding for the last packet of
the page by comparing the calculated end timestamp of that packet
with the Ogg page's end timestamp as given by the granule
position.
As a workaround for certain rounding errors encountered in the
wild, a discard padding of one sample will be treated as if no
discard padding was present for all but the very last packet as
indicated by the "end of stream" bit.
Fixes#2280.
Only applies to the packetizers for the following formats: AAC, AC-3,
DTS, MP3 and TrueHD. The other packetizers were already keeping the
value.
Fixes#2296.
Together with the additions of building `libiconv` and a complete
`gettext` in `build.sh` in revision
e17cbecb16, this enables the use of all
available interface translations on macOS.
Fixes#2110, #2307, #2323.
nlohmann's JSON libraries in version 2.x used to strip bytes that
aren't valid UTF-8 from strings (e.g. service/station names in MPEG
transport streams) before outputting the JSON data structures. With
MKVToolNix v24 that bundled library was updated to v3 which now throws
an exception on such invalid data.
Therefore mkvmerge now takes care of replacing invalid bytes with
placeholder characters itself before passing the strings to nlohmann's
JSON library.
Fixes#2327.
It is dangerous insofar as it pollutes an immense number of source
files. For example, utf8cpp's stuff uses relative namespace
names (e.g. `utf8::some_type`). If `using namespace libebml` is in
effect, then this clashes with `libebml::utf8` which is a typedef for
`unsigned char`, causing compiler errors.
One side affect of the fixed bug was that trying to identify/mux an
empty file (file with a size of 0) resulted in the following error
message:
> Error: buffer_c: num > m_filled. Should not have happened. Please
> file a bug report.
After reading the headers, the file is read again from the
start. Therefore no data must be left in the parser's internal
buffers. That was the intention behind calling `flush()` - but that
isn't actually what flush does. Instead it tries to use the remaining
data in the buffers as a frame.
This is not only wrong, it can also fail and cause an exception to be
thrown. That in turn causes a failure when reading the headers — both
identification and muxing abort at that point.
This is the HEVC analog for what was fixed for AVC in #2325.
After reading the headers, the file is read again from the
start. Therefore no data must be left in the parser's internal
buffers. That was the intention behind calling `flush()` - but that
isn't actually what flush does. Instead it tries to use the remaining
data in the buffers as a frame.
This is not only wrong, it can also fail and cause an exception to be
thrown. That in turn causes a failure when reading the headers — both
identification and muxing abort at that point.
Fixes#2325.