Check-in of unmodified audio elementary stream parsing code.

Source of media/base/*:
    http://src.chromium.org/chrome/trunk/src/media/base@262934
Source of media/formats/mpeg/*:
    http://src.chromium.org/chrome/trunk/src/media/formats/mpeg@257932

Change-Id: Icd56b6f496befcd0c9f4eec2460fb2e998ae8bd2
This commit is contained in:
Thomas Inskip 2014-04-07 10:27:07 -07:00
parent 5557ce7677
commit 30b51506c4
5 changed files with 324 additions and 0 deletions

View File

@ -0,0 +1,75 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/base/audio_timestamp_helper.h"
#include "base/logging.h"
#include "media/base/buffers.h"
namespace media {
AudioTimestampHelper::AudioTimestampHelper(int samples_per_second)
: base_timestamp_(kNoTimestamp()),
frame_count_(0) {
DCHECK_GT(samples_per_second, 0);
double fps = samples_per_second;
microseconds_per_frame_ = base::Time::kMicrosecondsPerSecond / fps;
}
void AudioTimestampHelper::SetBaseTimestamp(base::TimeDelta base_timestamp) {
base_timestamp_ = base_timestamp;
frame_count_ = 0;
}
base::TimeDelta AudioTimestampHelper::base_timestamp() const {
return base_timestamp_;
}
void AudioTimestampHelper::AddFrames(int frame_count) {
DCHECK_GE(frame_count, 0);
DCHECK(base_timestamp_ != kNoTimestamp());
frame_count_ += frame_count;
}
base::TimeDelta AudioTimestampHelper::GetTimestamp() const {
return ComputeTimestamp(frame_count_);
}
base::TimeDelta AudioTimestampHelper::GetFrameDuration(int frame_count) const {
DCHECK_GE(frame_count, 0);
base::TimeDelta end_timestamp = ComputeTimestamp(frame_count_ + frame_count);
return end_timestamp - GetTimestamp();
}
int64 AudioTimestampHelper::GetFramesToTarget(base::TimeDelta target) const {
DCHECK(base_timestamp_ != kNoTimestamp());
DCHECK(target >= base_timestamp_);
int64 delta_in_us = (target - GetTimestamp()).InMicroseconds();
if (delta_in_us == 0)
return 0;
// Compute a timestamp relative to |base_timestamp_| since timestamps
// created from |frame_count_| are computed relative to this base.
// This ensures that the time to frame computation here is the proper inverse
// of the frame to time computation in ComputeTimestamp().
base::TimeDelta delta_from_base = target - base_timestamp_;
// Compute frame count for the time delta. This computation rounds to
// the nearest whole number of frames.
double threshold = microseconds_per_frame_ / 2;
int64 target_frame_count =
(delta_from_base.InMicroseconds() + threshold) / microseconds_per_frame_;
return target_frame_count - frame_count_;
}
base::TimeDelta AudioTimestampHelper::ComputeTimestamp(
int64 frame_count) const {
DCHECK_GE(frame_count, 0);
DCHECK(base_timestamp_ != kNoTimestamp());
double frames_us = microseconds_per_frame_ * frame_count;
return base_timestamp_ + base::TimeDelta::FromMicroseconds(frames_us);
}
} // namespace media

View File

@ -0,0 +1,72 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_BASE_AUDIO_TIMESTAMP_HELPER_H_
#define MEDIA_BASE_AUDIO_TIMESTAMP_HELPER_H_
#include "base/time/time.h"
#include "media/base/media_export.h"
namespace media {
// Generates timestamps for a sequence of audio sample frames. This class should
// be used any place timestamps need to be calculated for a sequence of audio
// samples. It helps avoid timestamps inaccuracies caused by rounding/truncation
// in repeated sample count to timestamp conversions.
//
// The class is constructed with samples_per_second information so that it can
// convert audio sample frame counts into timestamps. After the object is
// constructed, SetBaseTimestamp() must be called to specify the starting
// timestamp of the audio sequence. As audio samples are received, their frame
// counts are added using AddFrames(). These frame counts are accumulated by
// this class so GetTimestamp() can be used to determine the timestamp for the
// samples that have been added. GetDuration() calculates the proper duration
// values for samples added to the current timestamp. GetFramesToTarget()
// determines the number of frames that need to be added/removed from the
// accumulated frames to reach a target timestamp.
class MEDIA_EXPORT AudioTimestampHelper {
public:
explicit AudioTimestampHelper(int samples_per_second);
// Sets the base timestamp to |base_timestamp| and the sets count to 0.
void SetBaseTimestamp(base::TimeDelta base_timestamp);
base::TimeDelta base_timestamp() const;
int64 frame_count() const { return frame_count_; }
// Adds |frame_count| to the frame counter.
// Note: SetBaseTimestamp() must be called with a value other than
// kNoTimestamp() before this method can be called.
void AddFrames(int frame_count);
// Get the current timestamp. This value is computed from the base_timestamp()
// and the number of sample frames that have been added so far.
base::TimeDelta GetTimestamp() const;
// Gets the duration if |frame_count| frames were added to the current
// timestamp reported by GetTimestamp(). This method ensures that
// (GetTimestamp() + GetFrameDuration(n)) will equal the timestamp that
// GetTimestamp() will return if AddFrames(n) is called.
base::TimeDelta GetFrameDuration(int frame_count) const;
// Returns the number of frames needed to reach the target timestamp.
// Note: |target| must be >= |base_timestamp_|.
int64 GetFramesToTarget(base::TimeDelta target) const;
private:
base::TimeDelta ComputeTimestamp(int64 frame_count) const;
double microseconds_per_frame_;
base::TimeDelta base_timestamp_;
// Number of frames accumulated by AddFrames() calls.
int64 frame_count_;
DISALLOW_IMPLICIT_CONSTRUCTORS(AudioTimestampHelper);
};
} // namespace media
#endif

View File

@ -0,0 +1,122 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/base/audio_timestamp_helper.h"
#include "media/base/buffers.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
static const int kDefaultSampleRate = 44100;
class AudioTimestampHelperTest : public ::testing::Test {
public:
AudioTimestampHelperTest() : helper_(kDefaultSampleRate) {
helper_.SetBaseTimestamp(base::TimeDelta());
}
// Adds frames to the helper and returns the current timestamp in
// microseconds.
int64 AddFrames(int frames) {
helper_.AddFrames(frames);
return helper_.GetTimestamp().InMicroseconds();
}
int64 FramesToTarget(int target_in_microseconds) {
return helper_.GetFramesToTarget(
base::TimeDelta::FromMicroseconds(target_in_microseconds));
}
void TestGetFramesToTargetRange(int frame_count, int start, int end) {
for (int i = start; i <= end; ++i) {
EXPECT_EQ(frame_count, FramesToTarget(i)) << " Failure for timestamp "
<< i << " us.";
}
}
protected:
AudioTimestampHelper helper_;
DISALLOW_COPY_AND_ASSIGN(AudioTimestampHelperTest);
};
TEST_F(AudioTimestampHelperTest, Basic) {
EXPECT_EQ(0, helper_.GetTimestamp().InMicroseconds());
// Verify that the output timestamp is always rounded down to the
// nearest microsecond. 1 frame @ 44100 is ~22.67573 microseconds,
// which is why the timestamp sometimes increments by 23 microseconds
// and other times it increments by 22 microseconds.
EXPECT_EQ(0, AddFrames(0));
EXPECT_EQ(22, AddFrames(1));
EXPECT_EQ(45, AddFrames(1));
EXPECT_EQ(68, AddFrames(1));
EXPECT_EQ(90, AddFrames(1));
EXPECT_EQ(113, AddFrames(1));
// Verify that adding frames one frame at a time matches the timestamp
// returned if the same number of frames are added all at once.
base::TimeDelta timestamp_1 = helper_.GetTimestamp();
helper_.SetBaseTimestamp(kNoTimestamp());
EXPECT_TRUE(kNoTimestamp() == helper_.base_timestamp());
helper_.SetBaseTimestamp(base::TimeDelta());
EXPECT_EQ(0, helper_.GetTimestamp().InMicroseconds());
helper_.AddFrames(5);
EXPECT_EQ(113, helper_.GetTimestamp().InMicroseconds());
EXPECT_TRUE(timestamp_1 == helper_.GetTimestamp());
}
TEST_F(AudioTimestampHelperTest, GetDuration) {
helper_.SetBaseTimestamp(base::TimeDelta::FromMicroseconds(100));
int frame_count = 5;
int64 expected_durations[] = { 113, 113, 114, 113, 113, 114 };
for (size_t i = 0; i < arraysize(expected_durations); ++i) {
base::TimeDelta duration = helper_.GetFrameDuration(frame_count);
EXPECT_EQ(expected_durations[i], duration.InMicroseconds());
base::TimeDelta timestamp_1 = helper_.GetTimestamp() + duration;
helper_.AddFrames(frame_count);
base::TimeDelta timestamp_2 = helper_.GetTimestamp();
EXPECT_TRUE(timestamp_1 == timestamp_2);
}
}
TEST_F(AudioTimestampHelperTest, GetFramesToTarget) {
// Verify GetFramesToTarget() rounding behavior.
// 1 frame @ 44100 is ~22.67573 microseconds,
// Test values less than half of the frame duration.
TestGetFramesToTargetRange(0, 0, 11);
// Test values between half the frame duration & the
// full frame duration.
TestGetFramesToTargetRange(1, 12, 22);
// Verify that the same number of frames is returned up
// to the next half a frame.
TestGetFramesToTargetRange(1, 23, 34);
// Verify the next 3 ranges.
TestGetFramesToTargetRange(2, 35, 56);
TestGetFramesToTargetRange(3, 57, 79);
TestGetFramesToTargetRange(4, 80, 102);
TestGetFramesToTargetRange(5, 103, 124);
// Add frames to the helper so negative frame counts can be tested.
helper_.AddFrames(5);
// Note: The timestamp ranges must match the positive values
// tested above to verify that the code is rounding properly.
TestGetFramesToTargetRange(0, 103, 124);
TestGetFramesToTargetRange(-1, 80, 102);
TestGetFramesToTargetRange(-2, 57, 79);
TestGetFramesToTargetRange(-3, 35, 56);
TestGetFramesToTargetRange(-4, 12, 34);
TestGetFramesToTargetRange(-5, 0, 11);
}
} // namespace media

View File

@ -0,0 +1,27 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/formats/mpeg/adts_constants.h"
#include "base/macros.h"
namespace media {
// The following conversion table is extracted from ISO 14496 Part 3 -
// Table 1.16 - Sampling Frequency Index.
const int kADTSFrequencyTable[] = {96000, 88200, 64000, 48000, 44100,
32000, 24000, 22050, 16000, 12000,
11025, 8000, 7350};
const size_t kADTSFrequencyTableSize = arraysize(kADTSFrequencyTable);
// The following conversion table is extracted from ISO 14496 Part 3 -
// Table 1.17 - Channel Configuration.
const media::ChannelLayout kADTSChannelLayoutTable[] = {
media::CHANNEL_LAYOUT_NONE, media::CHANNEL_LAYOUT_MONO,
media::CHANNEL_LAYOUT_STEREO, media::CHANNEL_LAYOUT_SURROUND,
media::CHANNEL_LAYOUT_4_0, media::CHANNEL_LAYOUT_5_0_BACK,
media::CHANNEL_LAYOUT_5_1_BACK, media::CHANNEL_LAYOUT_7_1};
const size_t kADTSChannelLayoutTableSize = arraysize(kADTSChannelLayoutTable);
} // namespace media

View File

@ -0,0 +1,28 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_FORMATS_MPEG_ADTS_CONSTANTS_H_
#define MEDIA_FORMATS_MPEG_ADTS_CONSTANTS_H_
#include <stddef.h>
#include "media/base/channel_layout.h"
#include "media/base/media_export.h"
namespace media {
enum {
kADTSHeaderMinSize = 7,
kSamplesPerAACFrame = 1024,
};
MEDIA_EXPORT extern const int kADTSFrequencyTable[];
MEDIA_EXPORT extern const size_t kADTSFrequencyTableSize;
MEDIA_EXPORT extern const media::ChannelLayout kADTSChannelLayoutTable[];
MEDIA_EXPORT extern const size_t kADTSChannelLayoutTableSize;
} // namespace media
#endif // MEDIA_FORMATS_MPEG_ADTS_CONSTANTS_H_