зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1667728 - Use only one notion of sample rate for AudioTrackEncoder. r=bryce
Differential Revision: https://phabricator.services.mozilla.com/D91951
This commit is contained in:
Родитель
335693edce
Коммит
ec3a23c754
|
@ -129,7 +129,7 @@ OpusTrackEncoder::~OpusTrackEncoder() {
|
|||
}
|
||||
}
|
||||
|
||||
nsresult OpusTrackEncoder::Init(int aChannels, int aSamplingRate) {
|
||||
nsresult OpusTrackEncoder::Init(int aChannels) {
|
||||
NS_ENSURE_TRUE((aChannels <= MAX_SUPPORTED_AUDIO_CHANNELS) && (aChannels > 0),
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -139,8 +139,8 @@ nsresult OpusTrackEncoder::Init(int aChannels, int aSamplingRate) {
|
|||
mChannels = aChannels > MAX_CHANNELS ? MAX_CHANNELS : aChannels;
|
||||
|
||||
// Reject non-audio sample rates.
|
||||
NS_ENSURE_TRUE(aSamplingRate >= 8000, NS_ERROR_INVALID_ARG);
|
||||
NS_ENSURE_TRUE(aSamplingRate <= 192000, NS_ERROR_INVALID_ARG);
|
||||
NS_ENSURE_TRUE(mTrackRate >= 8000, NS_ERROR_INVALID_ARG);
|
||||
NS_ENSURE_TRUE(mTrackRate <= 192000, NS_ERROR_INVALID_ARG);
|
||||
|
||||
// According to www.opus-codec.org, creating an opus encoder requires the
|
||||
// sampling rate of source signal be one of 8000, 12000, 16000, 24000, or
|
||||
|
@ -149,18 +149,15 @@ nsresult OpusTrackEncoder::Init(int aChannels, int aSamplingRate) {
|
|||
supportedSamplingRates.AppendElements(
|
||||
kOpusSupportedInputSamplingRates,
|
||||
ArrayLength(kOpusSupportedInputSamplingRates));
|
||||
if (!supportedSamplingRates.Contains(aSamplingRate)) {
|
||||
if (!supportedSamplingRates.Contains(mTrackRate)) {
|
||||
int error;
|
||||
mResampler =
|
||||
speex_resampler_init(mChannels, aSamplingRate, kOpusSamplingRate,
|
||||
SPEEX_RESAMPLER_QUALITY_DEFAULT, &error);
|
||||
mResampler = speex_resampler_init(mChannels, mTrackRate, kOpusSamplingRate,
|
||||
SPEEX_RESAMPLER_QUALITY_DEFAULT, &error);
|
||||
|
||||
if (error != RESAMPLER_ERR_SUCCESS) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
mSamplingRate = aSamplingRate;
|
||||
NS_ENSURE_TRUE(mSamplingRate > 0, NS_ERROR_FAILURE);
|
||||
|
||||
int error = 0;
|
||||
mEncoder = opus_encoder_create(GetOutputSampleRate(), mChannels,
|
||||
|
@ -196,7 +193,7 @@ nsresult OpusTrackEncoder::Init(int aChannels, int aSamplingRate) {
|
|||
}
|
||||
|
||||
int OpusTrackEncoder::GetOutputSampleRate() {
|
||||
return mResampler ? kOpusSamplingRate : mSamplingRate;
|
||||
return mResampler ? kOpusSamplingRate : mTrackRate;
|
||||
}
|
||||
|
||||
int OpusTrackEncoder::GetPacketDuration() {
|
||||
|
@ -218,12 +215,12 @@ already_AddRefed<TrackMetadataBase> OpusTrackEncoder::GetMetadata() {
|
|||
|
||||
RefPtr<OpusMetadata> meta = new OpusMetadata();
|
||||
meta->mChannels = mChannels;
|
||||
meta->mSamplingFrequency = mSamplingRate;
|
||||
meta->mSamplingFrequency = mTrackRate;
|
||||
|
||||
// The ogg time stamping and pre-skip is always timed at 48000.
|
||||
// Ogg and Webm timestamps are always sampled at 48k for Opus.
|
||||
SerializeOpusIdHeader(
|
||||
mChannels, mLookahead * (kOpusSamplingRate / GetOutputSampleRate()),
|
||||
mSamplingRate, &meta->mIdHeader);
|
||||
mTrackRate, &meta->mIdHeader);
|
||||
|
||||
nsCString vendor;
|
||||
vendor.AppendASCII(opus_get_version_string());
|
||||
|
@ -273,7 +270,7 @@ nsresult OpusTrackEncoder::GetEncodedTrack(
|
|||
const int framesToFetch = !mResampler
|
||||
? GetPacketDuration()
|
||||
: (GetPacketDuration() - framesLeft) *
|
||||
mSamplingRate / kOpusSamplingRate +
|
||||
mTrackRate / kOpusSamplingRate +
|
||||
frameRoundUp;
|
||||
|
||||
if (!mEndOfStream && mSourceSegment.GetDuration() < framesToFetch) {
|
||||
|
@ -341,7 +338,7 @@ nsresult OpusTrackEncoder::GetEncodedTrack(
|
|||
// We want to consume all the input data, so we slightly oversize the
|
||||
// resampled data buffer so we can fit the output data in. We cannot
|
||||
// really predict the output frame count at each call.
|
||||
uint32_t outframes = frameCopied * kOpusSamplingRate / mSamplingRate + 1;
|
||||
uint32_t outframes = frameCopied * kOpusSamplingRate / mTrackRate + 1;
|
||||
uint32_t inframes = frameCopied;
|
||||
|
||||
resamplingDest.SetLength(outframes * mChannels);
|
||||
|
@ -378,8 +375,8 @@ nsresult OpusTrackEncoder::GetEncodedTrack(
|
|||
framesInPCM = framesLeft + outframesToCopy;
|
||||
duration = framesInPCM;
|
||||
} else {
|
||||
// The ogg time stamping and pre-skip is always timed at 48000.
|
||||
duration = frameCopied * (kOpusSamplingRate / mSamplingRate);
|
||||
// Ogg and Webm timestamps are always sampled at 48k for Opus.
|
||||
duration = frameCopied * (kOpusSamplingRate / mTrackRate);
|
||||
}
|
||||
|
||||
// Remove the raw data which has been pulled to pcm buffer.
|
||||
|
|
|
@ -42,7 +42,7 @@ class OpusTrackEncoder : public AudioTrackEncoder {
|
|||
protected:
|
||||
int GetPacketDuration() override;
|
||||
|
||||
nsresult Init(int aChannels, int aSamplingRate) override;
|
||||
nsresult Init(int aChannels) override;
|
||||
|
||||
/**
|
||||
* Get the samplerate of the data to be fed to the Opus encoder. This might be
|
||||
|
|
|
@ -178,7 +178,7 @@ void AudioTrackEncoder::TryInit(const AudioSegment& aSegment,
|
|||
continue;
|
||||
}
|
||||
|
||||
nsresult rv = Init(iter->mChannelData.Length(), mTrackRate);
|
||||
nsresult rv = Init(iter->mChannelData.Length());
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
TRACK_LOG(LogLevel::Info,
|
||||
|
@ -204,7 +204,7 @@ void AudioTrackEncoder::TryInit(const AudioSegment& aSegment,
|
|||
("[AudioTrackEncoder]: Initialize failed for %ds. Attempting to "
|
||||
"init with %d (default) channels!",
|
||||
AUDIO_INIT_FAILED_DURATION, DEFAULT_CHANNELS));
|
||||
nsresult rv = Init(DEFAULT_CHANNELS, mTrackRate);
|
||||
nsresult rv = Init(DEFAULT_CHANNELS);
|
||||
Telemetry::Accumulate(
|
||||
Telemetry::MEDIA_RECORDER_TRACK_ENCODER_INIT_TIMEOUT_TYPE, 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -231,7 +231,7 @@ void AudioTrackEncoder::NotifyEndOfStream() {
|
|||
if (!mCanceled && !mInitialized) {
|
||||
// If source audio track is completely silent till the end of encoding,
|
||||
// initialize the encoder with a default channel count.
|
||||
Init(DEFAULT_CHANNELS, mTrackRate);
|
||||
Init(DEFAULT_CHANNELS);
|
||||
}
|
||||
|
||||
mEndOfStream = true;
|
||||
|
|
|
@ -175,7 +175,7 @@ class TrackEncoder {
|
|||
/**
|
||||
* The track rate of source media.
|
||||
*/
|
||||
TrackRate mTrackRate;
|
||||
const TrackRate mTrackRate;
|
||||
|
||||
/**
|
||||
* If set we assert that all methods are called on this thread.
|
||||
|
@ -190,7 +190,6 @@ class AudioTrackEncoder : public TrackEncoder {
|
|||
explicit AudioTrackEncoder(TrackRate aTrackRate)
|
||||
: TrackEncoder(aTrackRate),
|
||||
mChannels(0),
|
||||
mSamplingRate(0),
|
||||
mNotInitDuration(0),
|
||||
mAudioBitrate(0) {}
|
||||
|
||||
|
@ -297,7 +296,7 @@ class AudioTrackEncoder : public TrackEncoder {
|
|||
* Initializes the audio encoder. The call of this method is delayed until we
|
||||
* have received the first valid track from MediaTrackGraph.
|
||||
*/
|
||||
virtual nsresult Init(int aChannels, int aSamplingRate) = 0;
|
||||
virtual nsresult Init(int aChannels) = 0;
|
||||
|
||||
/**
|
||||
* The number of channels are used for processing PCM data in the audio
|
||||
|
@ -307,11 +306,6 @@ class AudioTrackEncoder : public TrackEncoder {
|
|||
*/
|
||||
int mChannels;
|
||||
|
||||
/**
|
||||
* The sampling rate of source audio data.
|
||||
*/
|
||||
int mSamplingRate;
|
||||
|
||||
/**
|
||||
* A segment queue of outgoing audio track data to the encoder.
|
||||
* The contents of mOutgoingBuffer will always be what has been appended on
|
||||
|
|
|
@ -13,11 +13,12 @@ using namespace mozilla;
|
|||
|
||||
class TestOpusTrackEncoder : public OpusTrackEncoder {
|
||||
public:
|
||||
TestOpusTrackEncoder() : OpusTrackEncoder(90000) {}
|
||||
explicit TestOpusTrackEncoder(TrackRate aTrackRate)
|
||||
: OpusTrackEncoder(aTrackRate) {}
|
||||
|
||||
// Return true if it has successfully initialized the Opus encoder.
|
||||
bool TestOpusRawCreation(int aChannels, int aSamplingRate) {
|
||||
if (Init(aChannels, aSamplingRate) == NS_OK) {
|
||||
bool TestOpusRawCreation(int aChannels) {
|
||||
if (Init(aChannels) == NS_OK) {
|
||||
if (IsInitialized()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -33,9 +34,9 @@ class TestOpusTrackEncoder : public OpusTrackEncoder {
|
|||
}
|
||||
};
|
||||
|
||||
static bool TestOpusInit(int aChannels, int aSamplingRate) {
|
||||
TestOpusTrackEncoder encoder;
|
||||
return encoder.TestOpusRawCreation(aChannels, aSamplingRate);
|
||||
static bool TestOpusInit(int aChannels, TrackRate aSamplingRate) {
|
||||
TestOpusTrackEncoder encoder(aSamplingRate);
|
||||
return encoder.TestOpusRawCreation(aChannels);
|
||||
}
|
||||
|
||||
TEST(OpusAudioTrackEncoder, InitRaw)
|
||||
|
@ -153,9 +154,9 @@ TEST(OpusAudioTrackEncoder, Init)
|
|||
}
|
||||
}
|
||||
|
||||
static int TestOpusResampler(int aChannels, int aSamplingRate) {
|
||||
TestOpusTrackEncoder encoder;
|
||||
EXPECT_TRUE(encoder.TestOpusRawCreation(aChannels, aSamplingRate));
|
||||
static int TestOpusResampler(int aChannels, TrackRate aTrackRate) {
|
||||
TestOpusTrackEncoder encoder(aTrackRate);
|
||||
EXPECT_TRUE(encoder.TestOpusRawCreation(aChannels));
|
||||
return encoder.TestGetOutputSampleRate();
|
||||
}
|
||||
|
||||
|
@ -178,9 +179,9 @@ TEST(OpusAudioTrackEncoder, Resample)
|
|||
TEST(OpusAudioTrackEncoder, FetchMetadata)
|
||||
{
|
||||
const int32_t channels = 1;
|
||||
const int32_t sampleRate = 44100;
|
||||
TestOpusTrackEncoder encoder;
|
||||
EXPECT_TRUE(encoder.TestOpusRawCreation(channels, sampleRate));
|
||||
const TrackRate sampleRate = 44100;
|
||||
TestOpusTrackEncoder encoder(sampleRate);
|
||||
EXPECT_TRUE(encoder.TestOpusRawCreation(channels));
|
||||
|
||||
RefPtr<TrackMetadataBase> metadata = encoder.GetMetadata();
|
||||
ASSERT_EQ(TrackMetadataBase::METADATA_OPUS, metadata->GetKind());
|
||||
|
@ -193,9 +194,9 @@ TEST(OpusAudioTrackEncoder, FetchMetadata)
|
|||
TEST(OpusAudioTrackEncoder, FrameEncode)
|
||||
{
|
||||
const int32_t channels = 1;
|
||||
const int32_t sampleRate = 44100;
|
||||
TestOpusTrackEncoder encoder;
|
||||
EXPECT_TRUE(encoder.TestOpusRawCreation(channels, sampleRate));
|
||||
const TrackRate sampleRate = 44100;
|
||||
TestOpusTrackEncoder encoder(sampleRate);
|
||||
EXPECT_TRUE(encoder.TestOpusRawCreation(channels));
|
||||
|
||||
// Generate five seconds of raw audio data.
|
||||
AudioGenerator<AudioDataValue> generator(channels, sampleRate);
|
||||
|
|
|
@ -18,8 +18,8 @@ class WebMOpusTrackEncoder : public OpusTrackEncoder {
|
|||
public:
|
||||
explicit WebMOpusTrackEncoder(TrackRate aTrackRate)
|
||||
: OpusTrackEncoder(aTrackRate) {}
|
||||
bool TestOpusCreation(int aChannels, int aSamplingRate) {
|
||||
if (NS_SUCCEEDED(Init(aChannels, aSamplingRate))) {
|
||||
bool TestOpusCreation(int aChannels) {
|
||||
if (NS_SUCCEEDED(Init(aChannels))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -40,11 +40,10 @@ class WebMVP8TrackEncoder : public VP8TrackEncoder {
|
|||
}
|
||||
};
|
||||
|
||||
static void GetOpusMetadata(int aChannels, int aSampleRate,
|
||||
TrackRate aTrackRate,
|
||||
static void GetOpusMetadata(int aChannels, TrackRate aTrackRate,
|
||||
nsTArray<RefPtr<TrackMetadataBase>>& aMeta) {
|
||||
WebMOpusTrackEncoder opusEncoder(aTrackRate);
|
||||
EXPECT_TRUE(opusEncoder.TestOpusCreation(aChannels, aSampleRate));
|
||||
EXPECT_TRUE(opusEncoder.TestOpusCreation(aChannels));
|
||||
aMeta.AppendElement(opusEncoder.GetMetadata());
|
||||
}
|
||||
|
||||
|
@ -106,18 +105,18 @@ TEST(WebMWriter, Metadata)
|
|||
|
||||
nsTArray<RefPtr<TrackMetadataBase>> meta;
|
||||
|
||||
TrackRate trackRate = 44100;
|
||||
|
||||
// Get opus metadata.
|
||||
int channel = 1;
|
||||
int sampleRate = 44100;
|
||||
TrackRate aTrackRate = 90000;
|
||||
GetOpusMetadata(channel, sampleRate, aTrackRate, meta);
|
||||
GetOpusMetadata(channel, trackRate, meta);
|
||||
|
||||
// Get vp8 metadata
|
||||
int32_t width = 640;
|
||||
int32_t height = 480;
|
||||
int32_t displayWidth = 640;
|
||||
int32_t displayHeight = 480;
|
||||
GetVP8Metadata(width, height, displayWidth, displayHeight, aTrackRate, meta);
|
||||
GetVP8Metadata(width, height, displayWidth, displayHeight, trackRate, meta);
|
||||
|
||||
// Set metadata
|
||||
writer.SetMetadata(meta);
|
||||
|
@ -130,17 +129,16 @@ TEST(WebMWriter, Cluster)
|
|||
{
|
||||
TestWebMWriter writer;
|
||||
nsTArray<RefPtr<TrackMetadataBase>> meta;
|
||||
TrackRate trackRate = 48000;
|
||||
// Get opus metadata.
|
||||
int channel = 1;
|
||||
int sampleRate = 48000;
|
||||
TrackRate aTrackRate = 90000;
|
||||
GetOpusMetadata(channel, sampleRate, aTrackRate, meta);
|
||||
GetOpusMetadata(channel, trackRate, meta);
|
||||
// Get vp8 metadata
|
||||
int32_t width = 320;
|
||||
int32_t height = 240;
|
||||
int32_t displayWidth = 320;
|
||||
int32_t displayHeight = 240;
|
||||
GetVP8Metadata(width, height, displayWidth, displayHeight, aTrackRate, meta);
|
||||
GetVP8Metadata(width, height, displayWidth, displayHeight, trackRate, meta);
|
||||
writer.SetMetadata(meta);
|
||||
|
||||
nsTArray<nsTArray<uint8_t>> encodedBuf;
|
||||
|
@ -173,17 +171,16 @@ TEST(WebMWriter, FLUSH_NEEDED)
|
|||
{
|
||||
TestWebMWriter writer;
|
||||
nsTArray<RefPtr<TrackMetadataBase>> meta;
|
||||
TrackRate trackRate = 44100;
|
||||
// Get opus metadata.
|
||||
int channel = 2;
|
||||
int sampleRate = 44100;
|
||||
TrackRate aTrackRate = 100000;
|
||||
GetOpusMetadata(channel, sampleRate, aTrackRate, meta);
|
||||
GetOpusMetadata(channel, trackRate, meta);
|
||||
// Get vp8 metadata
|
||||
int32_t width = 176;
|
||||
int32_t height = 352;
|
||||
int32_t displayWidth = 176;
|
||||
int32_t displayHeight = 352;
|
||||
GetVP8Metadata(width, height, displayWidth, displayHeight, aTrackRate, meta);
|
||||
GetVP8Metadata(width, height, displayWidth, displayHeight, trackRate, meta);
|
||||
writer.SetMetadata(meta);
|
||||
|
||||
// write the first I-Frame.
|
||||
|
@ -294,17 +291,16 @@ TEST(WebMWriter, bug970774_aspect_ratio)
|
|||
{
|
||||
TestWebMWriter writer;
|
||||
nsTArray<RefPtr<TrackMetadataBase>> meta;
|
||||
TrackRate trackRate = 44100;
|
||||
// Get opus metadata.
|
||||
int channel = 1;
|
||||
int sampleRate = 44100;
|
||||
TrackRate aTrackRate = 90000;
|
||||
GetOpusMetadata(channel, sampleRate, aTrackRate, meta);
|
||||
GetOpusMetadata(channel, trackRate, meta);
|
||||
// Set vp8 metadata
|
||||
int32_t width = 640;
|
||||
int32_t height = 480;
|
||||
int32_t displayWidth = 1280;
|
||||
int32_t displayHeight = 960;
|
||||
GetVP8Metadata(width, height, displayWidth, displayHeight, aTrackRate, meta);
|
||||
GetVP8Metadata(width, height, displayWidth, displayHeight, trackRate, meta);
|
||||
writer.SetMetadata(meta);
|
||||
|
||||
// write the first I-Frame.
|
||||
|
@ -353,7 +349,7 @@ TEST(WebMWriter, bug970774_aspect_ratio)
|
|||
rv = nestegg_track_audio_params(context, track, ¶ms);
|
||||
EXPECT_EQ(rv, 0);
|
||||
EXPECT_EQ(channel, static_cast<int>(params.channels));
|
||||
EXPECT_EQ(static_cast<double>(sampleRate), params.rate);
|
||||
EXPECT_EQ(static_cast<double>(trackRate), params.rate);
|
||||
}
|
||||
}
|
||||
if (context) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче