mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-04 07:40:42 +00:00
Bug 938686 - Refactor Opus header parsing so it can be reused. r=kinetik
We want to be able to use the same header parser for both the WebM and Ogg readers.
This commit is contained in:
parent
873c9e99d3
commit
748f641e19
@ -826,18 +826,7 @@ nsresult VorbisState::ReconstructVorbisGranulepos()
|
||||
#ifdef MOZ_OPUS
|
||||
OpusState::OpusState(ogg_page* aBosPage) :
|
||||
OggCodecState(aBosPage, true),
|
||||
mRate(0),
|
||||
mNominalRate(0),
|
||||
mChannels(0),
|
||||
mPreSkip(0),
|
||||
#ifdef MOZ_SAMPLE_TYPE_FLOAT32
|
||||
mGain(1.0f),
|
||||
#else
|
||||
mGain_Q16(65536),
|
||||
#endif
|
||||
mChannelMapping(0),
|
||||
mStreams(0),
|
||||
mCoupledStreams(0),
|
||||
mParser(nullptr),
|
||||
mDecoder(nullptr),
|
||||
mSkip(0),
|
||||
mPrevPacketGranulepos(0),
|
||||
@ -869,7 +858,7 @@ nsresult OpusState::Reset(bool aStart)
|
||||
// Reset the decoder.
|
||||
opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE);
|
||||
// Let the seek logic handle pre-roll if we're not seeking to the start.
|
||||
mSkip = aStart ? mPreSkip : 0;
|
||||
mSkip = aStart ? mParser->mPreSkip : 0;
|
||||
// This lets us distinguish the first page being the last page vs. just
|
||||
// not having processed the previous page when we encounter the last page.
|
||||
mPrevPageGranulepos = aStart ? 0 : -1;
|
||||
@ -895,14 +884,14 @@ bool OpusState::Init(void)
|
||||
|
||||
NS_ASSERTION(mDecoder == nullptr, "leaking OpusDecoder");
|
||||
|
||||
mDecoder = opus_multistream_decoder_create(mRate,
|
||||
mChannels,
|
||||
mStreams,
|
||||
mCoupledStreams,
|
||||
mMappingTable,
|
||||
mDecoder = opus_multistream_decoder_create(mParser->mRate,
|
||||
mParser->mChannels,
|
||||
mParser->mStreams,
|
||||
mParser->mCoupledStreams,
|
||||
mParser->mMappingTable,
|
||||
&error);
|
||||
|
||||
mSkip = mPreSkip;
|
||||
mSkip = mParser->mPreSkip;
|
||||
|
||||
LOG(PR_LOG_DEBUG, ("Opus decoder init, to skip %d", mSkip));
|
||||
|
||||
@ -915,147 +904,26 @@ bool OpusState::DecodeHeader(ogg_packet* aPacket)
|
||||
switch(mPacketCount++) {
|
||||
// Parse the id header.
|
||||
case 0: {
|
||||
if (aPacket->bytes < 19 || memcmp(aPacket->packet, "OpusHead", 8)) {
|
||||
LOG(PR_LOG_DEBUG, ("Invalid Opus file: unrecognized header"));
|
||||
return false;
|
||||
}
|
||||
|
||||
mRate = 48000; // The Opus decoder runs at 48 kHz regardless.
|
||||
|
||||
int version = aPacket->packet[8];
|
||||
// Accept file format versions 0.x.
|
||||
if ((version & 0xf0) != 0) {
|
||||
LOG(PR_LOG_DEBUG, ("Rejecting unknown Opus file version %d", version));
|
||||
return false;
|
||||
}
|
||||
|
||||
mChannels = aPacket->packet[9];
|
||||
if (mChannels<1) {
|
||||
LOG(PR_LOG_DEBUG, ("Invalid Opus file: Number of channels %d", mChannels));
|
||||
return false;
|
||||
}
|
||||
mPreSkip = LEUint16(aPacket->packet + 10);
|
||||
mNominalRate = LEUint32(aPacket->packet + 12);
|
||||
double gain_dB = LEInt16(aPacket->packet + 16) / 256.0;
|
||||
mParser = new OpusParser;
|
||||
if(!mParser->DecodeHeader(aPacket->packet, aPacket->bytes)) {
|
||||
return false;
|
||||
}
|
||||
mRate = mParser->mRate;
|
||||
mChannels = mParser->mChannels;
|
||||
mPreSkip = mParser->mPreSkip;
|
||||
#ifdef MOZ_SAMPLE_TYPE_FLOAT32
|
||||
mGain = static_cast<float>(pow(10,0.05*gain_dB));
|
||||
mGain = mParser->mGain;
|
||||
#else
|
||||
mGain_Q16 = static_cast<int32_t>(std::min(65536*pow(10,0.05*gain_dB)+0.5,
|
||||
static_cast<double>(INT32_MAX)));
|
||||
#endif
|
||||
mChannelMapping = aPacket->packet[18];
|
||||
|
||||
if (mChannelMapping == 0) {
|
||||
// Mapping family 0 only allows two channels
|
||||
if (mChannels>2) {
|
||||
LOG(PR_LOG_DEBUG, ("Invalid Opus file: too many channels (%d) for"
|
||||
" mapping family 0.", mChannels));
|
||||
return false;
|
||||
}
|
||||
mStreams = 1;
|
||||
mCoupledStreams = mChannels - 1;
|
||||
mMappingTable[0] = 0;
|
||||
mMappingTable[1] = 1;
|
||||
} else if (mChannelMapping == 1) {
|
||||
// Currently only up to 8 channels are defined for mapping family 1
|
||||
if (mChannels>8) {
|
||||
LOG(PR_LOG_DEBUG, ("Invalid Opus file: too many channels (%d) for"
|
||||
" mapping family 1.", mChannels));
|
||||
return false;
|
||||
}
|
||||
if (aPacket->bytes>20+mChannels) {
|
||||
mStreams = aPacket->packet[19];
|
||||
mCoupledStreams = aPacket->packet[20];
|
||||
int i;
|
||||
for (i=0; i<mChannels; i++)
|
||||
mMappingTable[i] = aPacket->packet[21+i];
|
||||
} else {
|
||||
LOG(PR_LOG_DEBUG, ("Invalid Opus file: channel mapping %d,"
|
||||
" but no channel mapping table", mChannelMapping));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LOG(PR_LOG_DEBUG, ("Invalid Opus file: unsupported channel mapping "
|
||||
"family %d", mChannelMapping));
|
||||
return false;
|
||||
}
|
||||
if (mStreams < 1) {
|
||||
LOG(PR_LOG_DEBUG, ("Invalid Opus file: no streams"));
|
||||
return false;
|
||||
}
|
||||
if (mCoupledStreams > mStreams) {
|
||||
LOG(PR_LOG_DEBUG, ("Invalid Opus file: more coupled streams (%d) than "
|
||||
"total streams (%d)", mCoupledStreams, mStreams));
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
LOG(PR_LOG_DEBUG, ("Opus stream header:"));
|
||||
LOG(PR_LOG_DEBUG, (" channels: %d", mChannels));
|
||||
LOG(PR_LOG_DEBUG, (" preskip: %d", mPreSkip));
|
||||
LOG(PR_LOG_DEBUG, (" original: %d Hz", mNominalRate));
|
||||
LOG(PR_LOG_DEBUG, (" gain: %.2f dB", gain_dB));
|
||||
LOG(PR_LOG_DEBUG, ("Channel Mapping:"));
|
||||
LOG(PR_LOG_DEBUG, (" family: %d", mChannelMapping));
|
||||
LOG(PR_LOG_DEBUG, (" streams: %d", mStreams));
|
||||
mGain_Q16 = mParser->mGain_Q16;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
// Parse the metadata header.
|
||||
case 1: {
|
||||
if (aPacket->bytes < 16 || memcmp(aPacket->packet, "OpusTags", 8))
|
||||
return false;
|
||||
|
||||
// Copy out the raw comment lines, but only do basic validation
|
||||
// checks against the string packing: too little data, too many
|
||||
// comments, or comments that are too long. Rejecting these cases
|
||||
// helps reduce the propagation of broken files.
|
||||
// We do not ensure they are valid UTF-8 here, nor do we validate
|
||||
// the required ASCII_TAG=value format of the user comments.
|
||||
const unsigned char* buf = aPacket->packet + 8;
|
||||
uint32_t bytes = aPacket->bytes - 8;
|
||||
uint32_t len;
|
||||
// Read the vendor string.
|
||||
len = LEUint32(buf);
|
||||
buf += 4;
|
||||
bytes -= 4;
|
||||
if (len > bytes)
|
||||
return false;
|
||||
mVendorString = nsCString(reinterpret_cast<const char*>(buf), len);
|
||||
buf += len;
|
||||
bytes -= len;
|
||||
// Read the user comments.
|
||||
if (bytes < 4)
|
||||
return false;
|
||||
uint32_t ncomments = LEUint32(buf);
|
||||
buf += 4;
|
||||
bytes -= 4;
|
||||
// If there are so many comments even their length fields
|
||||
// won't fit in the packet, stop reading now.
|
||||
if (ncomments > (bytes>>2))
|
||||
return false;
|
||||
uint32_t i;
|
||||
for (i = 0; i < ncomments; i++) {
|
||||
if (bytes < 4)
|
||||
if(!mParser->DecodeTags(aPacket->packet, aPacket->bytes)) {
|
||||
return false;
|
||||
len = LEUint32(buf);
|
||||
buf += 4;
|
||||
bytes -= 4;
|
||||
if (len > bytes)
|
||||
return false;
|
||||
mTags.AppendElement(nsCString(reinterpret_cast<const char*>(buf), len));
|
||||
buf += len;
|
||||
bytes -= len;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
LOG(PR_LOG_DEBUG, ("Opus metadata header:"));
|
||||
LOG(PR_LOG_DEBUG, (" vendor: %s", mVendorString.get()));
|
||||
for (uint32_t i = 0; i < mTags.Length(); i++) {
|
||||
LOG(PR_LOG_DEBUG, (" %s", mTags[i].get()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1077,8 +945,8 @@ MetadataTags* OpusState::GetTags()
|
||||
MetadataTags* tags;
|
||||
|
||||
tags = new MetadataTags;
|
||||
for (uint32_t i = 0; i < mTags.Length(); i++) {
|
||||
AddVorbisComment(tags, mTags[i].Data(), mTags[i].Length());
|
||||
for (uint32_t i = 0; i < mParser->mTags.Length(); i++) {
|
||||
AddVorbisComment(tags, mParser->mTags[i].Data(), mParser->mTags[i].Length());
|
||||
}
|
||||
|
||||
return tags;
|
||||
@ -1090,7 +958,7 @@ int64_t OpusState::Time(int64_t aGranulepos)
|
||||
if (!mActive)
|
||||
return -1;
|
||||
|
||||
return Time(mPreSkip, aGranulepos);
|
||||
return Time(mParser->mPreSkip, aGranulepos);
|
||||
}
|
||||
|
||||
int64_t OpusState::Time(int aPreSkip, int64_t aGranulepos)
|
||||
|
@ -36,6 +36,8 @@
|
||||
#include <map>
|
||||
#endif
|
||||
|
||||
#include "OpusParser.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Deallocates a packet, used in OggPacketQueue below.
|
||||
@ -341,7 +343,6 @@ public:
|
||||
|
||||
// Various fields from the Ogg Opus header.
|
||||
int mRate; // Sample rate the decoder uses (always 48 kHz).
|
||||
uint32_t mNominalRate; // Original sample rate of the data (informational).
|
||||
int mChannels; // Number of channels the stream encodes.
|
||||
uint16_t mPreSkip; // Number of samples to strip after decoder reset.
|
||||
#ifdef MOZ_SAMPLE_TYPE_FLOAT32
|
||||
@ -349,11 +350,8 @@ public:
|
||||
#else
|
||||
int32_t mGain_Q16; // Gain to apply to the decoder output.
|
||||
#endif
|
||||
int mChannelMapping; // Channel mapping family.
|
||||
int mStreams; // Number of packed streams in each packet.
|
||||
int mCoupledStreams; // Number of packed coupled streams in each packet.
|
||||
unsigned char mMappingTable[255]; // Channel mapping table.
|
||||
|
||||
nsAutoPtr<OpusParser> mParser;
|
||||
OpusMSDecoder *mDecoder;
|
||||
|
||||
int mSkip; // Number of samples left to trim before playback.
|
||||
@ -366,9 +364,6 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
nsCString mVendorString; // Encoder vendor string from the header.
|
||||
nsTArray<nsCString> mTags; // Unparsed comment strings from the header.
|
||||
|
||||
// Reconstructs the granulepos of Opus packets stored in the
|
||||
// mUnstamped array. mUnstamped must be filled with consecutive packets from
|
||||
// the stream, with the last packet having a known granulepos. Using this
|
||||
|
196
content/media/ogg/OpusParser.cpp
Normal file
196
content/media/ogg/OpusParser.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "OpusParser.h"
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include "MediaDecoderReader.h"
|
||||
#include "VideoUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "opus/opus.h"
|
||||
extern "C" {
|
||||
#include "opus/opus_multistream.h"
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* gMediaDecoderLog;
|
||||
#define OPUS_LOG(type, msg) PR_LOG(gMediaDecoderLog, type, msg)
|
||||
#else
|
||||
#define OPUS_LOG(type, msg)
|
||||
#endif
|
||||
|
||||
OpusParser::OpusParser():
|
||||
mRate(0),
|
||||
mNominalRate(0),
|
||||
mChannels(0),
|
||||
mPreSkip(0),
|
||||
#ifdef MOZ_SAMPLE_TYPE_FLOAT32
|
||||
mGain(1.0f),
|
||||
#else
|
||||
mGain_Q16(65536),
|
||||
#endif
|
||||
mChannelMapping(0),
|
||||
mStreams(0),
|
||||
mCoupledStreams(0)
|
||||
{ }
|
||||
|
||||
bool OpusParser::DecodeHeader(unsigned char* aData, size_t aLength)
|
||||
{
|
||||
if (aLength < 19 || memcmp(aData, "OpusHead", 8)) {
|
||||
OPUS_LOG(PR_LOG_DEBUG, ("Invalid Opus file: unrecognized header"));
|
||||
return false;
|
||||
}
|
||||
|
||||
mRate = 48000; // The Opus decoder runs at 48 kHz regardless.
|
||||
|
||||
int version = aData[8];
|
||||
// Accept file format versions 0.x.
|
||||
if ((version & 0xf0) != 0) {
|
||||
OPUS_LOG(PR_LOG_DEBUG, ("Rejecting unknown Opus file version %d", version));
|
||||
return false;
|
||||
}
|
||||
|
||||
mChannels = aData[9];
|
||||
if (mChannels<1) {
|
||||
OPUS_LOG(PR_LOG_DEBUG, ("Invalid Opus file: Number of channels %d", mChannels));
|
||||
return false;
|
||||
}
|
||||
|
||||
mPreSkip = LEUint16(aData + 10);
|
||||
mNominalRate = LEUint32(aData + 12);
|
||||
double gain_dB = LEInt16(aData + 16) / 256.0;
|
||||
#ifdef MOZ_SAMPLE_TYPE_FLOAT32
|
||||
mGain = static_cast<float>(pow(10,0.05*gain_dB));
|
||||
#else
|
||||
mGain_Q16 = static_cast<int32_t>(std::min(65536*pow(10,0.05*gain_dB)+0.5,
|
||||
static_cast<double>(INT32_MAX)));
|
||||
#endif
|
||||
mChannelMapping = aData[18];
|
||||
|
||||
if (mChannelMapping == 0) {
|
||||
// Mapping family 0 only allows two channels
|
||||
if (mChannels>2) {
|
||||
OPUS_LOG(PR_LOG_DEBUG, ("Invalid Opus file: too many channels (%d) for"
|
||||
" mapping family 0.", mChannels));
|
||||
return false;
|
||||
}
|
||||
mStreams = 1;
|
||||
mCoupledStreams = mChannels - 1;
|
||||
mMappingTable[0] = 0;
|
||||
mMappingTable[1] = 1;
|
||||
} else if (mChannelMapping == 1) {
|
||||
// Currently only up to 8 channels are defined for mapping family 1
|
||||
if (mChannels>8) {
|
||||
OPUS_LOG(PR_LOG_DEBUG, ("Invalid Opus file: too many channels (%d) for"
|
||||
" mapping family 1.", mChannels));
|
||||
return false;
|
||||
}
|
||||
if (aLength>20+mChannels) {
|
||||
mStreams = aData[19];
|
||||
mCoupledStreams = aData[20];
|
||||
int i;
|
||||
for (i=0; i<mChannels; i++)
|
||||
mMappingTable[i] = aData[21+i];
|
||||
} else {
|
||||
OPUS_LOG(PR_LOG_DEBUG, ("Invalid Opus file: channel mapping %d,"
|
||||
" but no channel mapping table", mChannelMapping));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
OPUS_LOG(PR_LOG_DEBUG, ("Invalid Opus file: unsupported channel mapping "
|
||||
"family %d", mChannelMapping));
|
||||
return false;
|
||||
}
|
||||
if (mStreams < 1) {
|
||||
OPUS_LOG(PR_LOG_DEBUG, ("Invalid Opus file: no streams"));
|
||||
return false;
|
||||
}
|
||||
if (mCoupledStreams > mStreams) {
|
||||
OPUS_LOG(PR_LOG_DEBUG, ("Invalid Opus file: more coupled streams (%d) than "
|
||||
"total streams (%d)", mCoupledStreams, mStreams));
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
OPUS_LOG(PR_LOG_DEBUG, ("Opus stream header:"));
|
||||
OPUS_LOG(PR_LOG_DEBUG, (" channels: %d", mChannels));
|
||||
OPUS_LOG(PR_LOG_DEBUG, (" preskip: %d", mPreSkip));
|
||||
OPUS_LOG(PR_LOG_DEBUG, (" original: %d Hz", mNominalRate));
|
||||
OPUS_LOG(PR_LOG_DEBUG, (" gain: %.2f dB", gain_dB));
|
||||
OPUS_LOG(PR_LOG_DEBUG, ("Channel Mapping:"));
|
||||
OPUS_LOG(PR_LOG_DEBUG, (" family: %d", mChannelMapping));
|
||||
OPUS_LOG(PR_LOG_DEBUG, (" streams: %d", mStreams));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpusParser::DecodeTags(unsigned char* aData, size_t aLength)
|
||||
{
|
||||
if (aLength < 16 || memcmp(aData, "OpusTags", 8))
|
||||
return false;
|
||||
|
||||
// Copy out the raw comment lines, but only do basic validation
|
||||
// checks against the string packing: too little data, too many
|
||||
// comments, or comments that are too long. Rejecting these cases
|
||||
// helps reduce the propagation of broken files.
|
||||
// We do not ensure they are valid UTF-8 here, nor do we validate
|
||||
// the required ASCII_TAG=value format of the user comments.
|
||||
const unsigned char* buf = aData + 8;
|
||||
uint32_t bytes = aLength - 8;
|
||||
uint32_t len;
|
||||
// Read the vendor string.
|
||||
len = LEUint32(buf);
|
||||
buf += 4;
|
||||
bytes -= 4;
|
||||
if (len > bytes)
|
||||
return false;
|
||||
mVendorString = nsCString(reinterpret_cast<const char*>(buf), len);
|
||||
buf += len;
|
||||
bytes -= len;
|
||||
// Read the user comments.
|
||||
if (bytes < 4)
|
||||
return false;
|
||||
uint32_t ncomments = LEUint32(buf);
|
||||
buf += 4;
|
||||
bytes -= 4;
|
||||
// If there are so many comments even their length fields
|
||||
// won't fit in the packet, stop reading now.
|
||||
if (ncomments > (bytes>>2))
|
||||
return false;
|
||||
uint32_t i;
|
||||
for (i = 0; i < ncomments; i++) {
|
||||
if (bytes < 4)
|
||||
return false;
|
||||
len = LEUint32(buf);
|
||||
buf += 4;
|
||||
bytes -= 4;
|
||||
if (len > bytes)
|
||||
return false;
|
||||
mTags.AppendElement(nsCString(reinterpret_cast<const char*>(buf), len));
|
||||
buf += len;
|
||||
bytes -= len;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
OPUS_LOG(PR_LOG_DEBUG, ("Opus metadata header:"));
|
||||
OPUS_LOG(PR_LOG_DEBUG, (" vendor: %s", mVendorString.get()));
|
||||
for (uint32_t i = 0; i < mTags.Length(); i++) {
|
||||
OPUS_LOG(PR_LOG_DEBUG, (" %s", mTags[i].get()));
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
51
content/media/ogg/OpusParser.h
Normal file
51
content/media/ogg/OpusParser.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#if !defined(OpusParser_h_)
|
||||
#define OpusParser_h_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <opus/opus.h>
|
||||
#include "opus/opus_multistream.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class OpusParser
|
||||
{
|
||||
public:
|
||||
OpusParser();
|
||||
|
||||
bool DecodeHeader(unsigned char* aData, size_t aLength);
|
||||
bool DecodeTags(unsigned char* aData, size_t aLength);
|
||||
|
||||
// Various fields from the Ogg Opus header.
|
||||
int mRate; // Sample rate the decoder uses (always 48 kHz).
|
||||
uint32_t mNominalRate; // Original sample rate of the data (informational).
|
||||
int mChannels; // Number of channels the stream encodes.
|
||||
uint16_t mPreSkip; // Number of samples to strip after decoder reset.
|
||||
#ifdef MOZ_SAMPLE_TYPE_FLOAT32
|
||||
float mGain; // Gain to apply to decoder output.
|
||||
#else
|
||||
int32_t mGain_Q16; // Gain to apply to the decoder output.
|
||||
#endif
|
||||
int mChannelMapping; // Channel mapping family.
|
||||
int mStreams; // Number of packed streams in each packet.
|
||||
int mCoupledStreams; // Number of packed coupled streams in each packet.
|
||||
unsigned char mMappingTable[255]; // Channel mapping table.
|
||||
|
||||
// Granule position (end sample) of the last decoded Opus packet. This is
|
||||
// used to calculate the amount we should trim from the last packet.
|
||||
int64_t mPrevPacketGranulepos;
|
||||
|
||||
nsTArray<nsCString> mTags; // Unparsed comment strings from the header.
|
||||
|
||||
nsCString mVendorString; // Encoder vendor string from the header.
|
||||
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -9,6 +9,7 @@ EXPORTS += [
|
||||
'OggDecoder.h',
|
||||
'OggReader.h',
|
||||
'OggWriter.h',
|
||||
'OpusParser.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
@ -16,6 +17,7 @@ UNIFIED_SOURCES += [
|
||||
'OggDecoder.cpp',
|
||||
'OggReader.cpp',
|
||||
'OggWriter.cpp',
|
||||
'OpusParser.cpp',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
Loading…
x
Reference in New Issue
Block a user