Remember parsed comments from the OpusTags header in
an array member variable. Add a method to generate
the nsHTMLMediaElement::MetadataTags hash table from
those entries, performing the same validatation we
do for Vorbis.
This feature is tested by adding the existing opus
test file to gMetadataTests.
IsValidVorbisTagName is moved to a static method
on nsOggCodecState so it can be shared among the
subclasses and easily called externally.
MetadataTags generation for Vorbis streams is moved
to the same method name on nsVorbisState to allow
sharing of the parsing and validation code as much
as possible, since both formats use the same scheme.
It's arguable whether contrustuction better belongs to
nsOggReader or to the nsCodecState subclasses, since in
theory the various multiplexed streams interact in
determining the canonical tag list, but it is the
per-codec streams which contain the metadata in Ogg.
Bug 748144 switched our opus decoding to use the
opus_multistream api so we could handle surround
audio files. The version of opus in our tree at
the time didn't include extern "C" {} protection
in the corresponding header, so we had to provide
our own.
With the update to the opus 1.0.0 source release
in bug 790381, this oversight is corrected and
we can remove our work-around.
Verify that tag names are ASCII within the valid character
ranges and that values are UTF-8, skipping comments where
these checks fail.
As written, the check in IsValidVorbisTagName() for the
separator character isn't necessary, because we've already
split on the first occurance. However, it's better to run
the extra check in case the function is reused elsewhere.
The Opus audio format supports multichannel (surround) audio, but our initial implementation used a simpler API which only supported mono and stereo output.
To handle these files gracefully, this patch uses the multichannel api and downmixes the output, if possible, to stereo, since we don't currently support surround sound playback.
nsOggReader::RangeEndTime() relied on CRC values from valid ogg
pages to keep track of already-searched data when looking for a
end timestamp. This caused quadratic behaviour searching in a
section of a file with no valid pages.
Instead, remember where we last looked, and backoff immediately
if we go more than the maximum length of a page into previously
scanned data. This avoids searching data we've eliminated as
containing valid Ogg pages and lets us search backward with O(N)
instead.
Implements a media.mozGetMetadata() method returning a new javascript object whose properties are key value pairs respresenting metadata tags from the media resource. This data is available after readystate enters METADATA_LOADED.
Currently this is only implemented for Ogg Vorbis streams.
Media format metadata is parsed out by the media decoders. In the nsCodecStateMachine::ReadMetadata subclasses we fill in an nsDataHashtable pointer using the format-specifc api.
The hash pointer is passed up to the media element as part of the MetadataLoaded event.
The hash is deleted if the load is aborted. The audio metadata is also reset to zero (as in the constructor), resolving a todo comment.
We trim the initial few samples out of the opus decoder,
to give the output time to converge, and to correct for
the encoding delay. Encoders store the delay in the preskip
field of the Ogg encapsulation header.
The previous code to do this was a hack based on the granulepos
values and could fail on some inputs. Instead, keep a count
of how many samples we want to trip, and remove packet data
until that value matches the preskip value from the header.
The value is set to the preskip value from the header when
the decoder is initialized. We also need to do this after
seek. To do this we add a specialized nsOggReader::ResetDecode
method which takes a boolean argument, set to true when
we are seeking to the start of the stream. In that case,
the method resets the skip count.
There is still an issue after general seeks. The spec recommends
trimming a full 80 ms (3840 frames) to allow the decoder to fully
settle from the previous state. It's tricky to do this inside
nsOpusState because it doesn't know where it is in the stream.
Also add some debug output to track the decode behaviour.
Fix a crash loading opus files when the media.opus.enabled pref is
false. The buffering code still tries to call our Time() method,
but without having read the headers we cannot perform the
conversion.
This commit adds a guard on mActive like the other ::Time
methods use.
On 2012 May 10, the Ogg encapsulation spec for Opus at
https://wiki.xiph.org/OggOpus bumped the version number
from zero to one. The one-byte field is also now notionally
split into major and minor subfields, with incompatible
changes signalled by the major field.
We update nsOpusState::DecodeHeader to parse the version
field separately from the stream identification and reject
any stream where the high four bits of the version field
is non-zero.
The opus-tools repo was updated 2012 May 22 to set with
version = 1. This commit enables playback of those files.
Parse and decode Opus streams embedded in the Ogg
container. Based on the draft specification from
https://wiki.xiph.org/OggOpus
Support is conditional on the runtime preference
setting media.opus.enabled, which is false by
default until we're confident the spec is stable
and useful.
This patch doesn't support the gain header or
multichannel files.
The LEUint*() functions from the skeleton parser
are used to read the multi-byte header fields.
This requires moving them to earlier in the file.
Mappings for the .opus filename extension are also
added to facilitate testing with local files.