Skip to content

Commit

Permalink
media: Add MemoryDataSource.
Browse files Browse the repository at this point in the history
This is mainly for testing purpose. It will be used by PipelineIntegrationTestBase to test data in memory. Currently PipelineIntegrationTestBase only supports test data in file.

BUG=584119
TEST=Added unittest.

Review URL: https://codereview.chromium.org/1748333003

Cr-Commit-Position: refs/heads/master@{#378585}
  • Loading branch information
xhwang-chromium authored and Commit bot committed Mar 1, 2016
1 parent 3238b29 commit 95acbba
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 0 deletions.
2 changes: 2 additions & 0 deletions media/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ component("media") {
"filters/jpeg_parser.h",
"filters/media_source_state.cc",
"filters/media_source_state.h",
"filters/memory_data_source.cc",
"filters/memory_data_source.h",
"filters/opus_audio_decoder.cc",
"filters/opus_audio_decoder.h",
"filters/opus_constants.cc",
Expand Down
57 changes: 57 additions & 0 deletions media/filters/memory_data_source.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2016 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/filters/memory_data_source.h"

#include <algorithm>

#include "base/logging.h"

namespace media {

MemoryDataSource::MemoryDataSource(const uint8_t* data, size_t size)
: data_(data), size_(size) {}

MemoryDataSource::~MemoryDataSource() {}

void MemoryDataSource::Read(int64_t position,
int size,
uint8_t* data,
const DataSource::ReadCB& read_cb) {
DCHECK(!read_cb.is_null());

if (is_stopped_ || size < 0 || position < 0 ||
static_cast<size_t>(position) > size_) {
read_cb.Run(kReadError);
return;
}

// Cap size within bounds.
size_t clamped_size = std::min(static_cast<size_t>(size),
size_ - static_cast<size_t>(position));

if (clamped_size > 0) {
DCHECK(data);
memcpy(data, data_ + position, clamped_size);
}

read_cb.Run(clamped_size);
}

void MemoryDataSource::Stop() {
is_stopped_ = true;
}

bool MemoryDataSource::GetSize(int64_t* size_out) {
*size_out = size_;
return true;
}

bool MemoryDataSource::IsStreaming() {
return false;
}

void MemoryDataSource::SetBitrate(int bitrate) {}

} // namespace media
45 changes: 45 additions & 0 deletions media/filters/memory_data_source.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2016 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_FILTERS_MEMORY_DATA_SOURCE_H_
#define MEDIA_FILTERS_MEMORY_DATA_SOURCE_H_

#include <stdint.h>

#include "base/macros.h"
#include "media/base/data_source.h"

namespace media {

// Basic data source that treats the URL as a file path, and uses the file
// system to read data for a media pipeline.
class MEDIA_EXPORT MemoryDataSource : public DataSource {
public:
// Construct MemoryDataSource with |data| and |size|. The data is guaranteed
// to be valid during the lifetime of MemoryDataSource.
MemoryDataSource(const uint8_t* data, size_t size);
~MemoryDataSource() final;

// Implementation of DataSource.
void Read(int64_t position,
int size,
uint8_t* data,
const DataSource::ReadCB& read_cb) final;
void Stop() final;
bool GetSize(int64_t* size_out) final;
bool IsStreaming() final;
void SetBitrate(int bitrate) final;

private:
const uint8_t* data_ = nullptr;
size_t size_ = 0;

bool is_stopped_ = false;

DISALLOW_COPY_AND_ASSIGN(MemoryDataSource);
};

} // namespace media

#endif // MEDIA_FILTERS_MEMORY_DATA_SOURCE_H_
108 changes: 108 additions & 0 deletions media/filters/memory_data_source_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Copyright 2016 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 "base/bind.h"
#include "base/macros.h"
#include "base/rand_util.h"
#include "media/filters/memory_data_source.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace media {

class MemoryDataSourceTest : public ::testing::Test {
public:
MemoryDataSourceTest() {}

protected:
void Initialize(size_t size) {
data_.assign(size, 0);
base::RandBytes(data_.data(), size);
memory_data_source_.reset(new MemoryDataSource(data_.data(), size));
EXPECT_EQ(size, GetSize());
}

// Reads |size| bytes starting from |position|, expects |expected_read_size|
// bytes to be read and checks the read data. Expects error when
// |expected_read_size| is DataSource::kReadError.
void ReadAndExpect(int64_t position, int size, int expected_read_size) {
std::vector<uint8_t> data(size < 0 ? 0 : size, 0);

EXPECT_CALL(*this, ReadCB(expected_read_size));
memory_data_source_->Read(
position, size, data.data(),
base::Bind(&MemoryDataSourceTest::ReadCB, base::Unretained(this)));

if (expected_read_size != DataSource::kReadError) {
EXPECT_EQ(
0, memcmp(data_.data() + position, data.data(), expected_read_size));
}
}

size_t GetSize() {
int64_t size = 0;
EXPECT_TRUE(memory_data_source_->GetSize(&size));
EXPECT_GE(size, 0);
return size;
}

void Stop() { memory_data_source_->Stop(); }

MOCK_METHOD1(ReadCB, void(int size));

private:
std::vector<uint8_t> data_;
scoped_ptr<MemoryDataSource> memory_data_source_;

DISALLOW_COPY_AND_ASSIGN(MemoryDataSourceTest);
};

TEST_F(MemoryDataSourceTest, EmptySource) {
Initialize(0);
ReadAndExpect(0, 0, 0);
}

TEST_F(MemoryDataSourceTest, ReadData) {
Initialize(128);
ReadAndExpect(0, 0, 0);
ReadAndExpect(0, 128, 128);
ReadAndExpect(12, 64, 64);
ReadAndExpect(128, 0, 0);
}

TEST_F(MemoryDataSourceTest, ReadData_InvalidPosition) {
Initialize(128);
ReadAndExpect(-7, 64, DataSource::kReadError);
ReadAndExpect(129, 64, DataSource::kReadError);
}

TEST_F(MemoryDataSourceTest, ReadData_InvalidSize) {
Initialize(128);
ReadAndExpect(0, -12, DataSource::kReadError);
}

TEST_F(MemoryDataSourceTest, ReadData_PartialRead) {
Initialize(128);
ReadAndExpect(0, 129, 128);
ReadAndExpect(96, 100, 32);
}

// All ReadData() will fail after Stop().
TEST_F(MemoryDataSourceTest, Stop) {
Initialize(128);
ReadAndExpect(12, 64, 64);
Stop();
ReadAndExpect(12, 64, DataSource::kReadError);
}

// ReadData() doesn't affect GetSize().
TEST_F(MemoryDataSourceTest, GetSize) {
Initialize(128);
ReadAndExpect(12, 64, 64);
EXPECT_EQ(128u, GetSize());
ReadAndExpect(-7, 64, DataSource::kReadError);
EXPECT_EQ(128u, GetSize());
}

} // namespace media
3 changes: 3 additions & 0 deletions media/media.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,8 @@
'filters/jpeg_parser.h',
'filters/media_source_state.cc',
'filters/media_source_state.h',
'filters/memory_data_source.cc',
'filters/memory_data_source.h',
'filters/opus_audio_decoder.cc',
'filters/opus_audio_decoder.h',
'filters/opus_constants.cc',
Expand Down Expand Up @@ -1260,6 +1262,7 @@
'filters/in_memory_url_protocol_unittest.cc',
'filters/ivf_parser_unittest.cc',
'filters/jpeg_parser_unittest.cc',
'filters/memory_data_source_unittest.cc',
'filters/source_buffer_stream_unittest.cc',
'filters/video_cadence_estimator_unittest.cc',
'filters/video_decoder_selector_unittest.cc',
Expand Down

0 comments on commit 95acbba

Please sign in to comment.