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:
parent
5557ce7677
commit
30b51506c4
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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_
|
Loading…
Reference in New Issue