summaryrefslogtreecommitdiffstats
path: root/media/filters
diff options
context:
space:
mode:
authorralphl@chromium.org <ralphl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-12 03:49:11 +0000
committerralphl@chromium.org <ralphl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-12 03:49:11 +0000
commit84dd17ec3f2b4ccd2bec330596bb1aa912ae78d7 (patch)
treebad98923f3e52e2e7f5f6e07e94dd557cb672715 /media/filters
parenta90bb01b260de37d4390af4721960e63095b991c (diff)
downloadchromium_src-84dd17ec3f2b4ccd2bec330596bb1aa912ae78d7.zip
chromium_src-84dd17ec3f2b4ccd2bec330596bb1aa912ae78d7.tar.gz
chromium_src-84dd17ec3f2b4ccd2bec330596bb1aa912ae78d7.tar.bz2
A very basic implementation of a data source, which opens a file. Implementation of the DataSource media filter interface.
Review URL: http://codereview.chromium.org/21111 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9642 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/filters')
-rw-r--r--media/filters/file_data_source.cc114
-rw-r--r--media/filters/file_data_source.h64
-rw-r--r--media/filters/file_data_source_unittest.cc95
3 files changed, 273 insertions, 0 deletions
diff --git a/media/filters/file_data_source.cc b/media/filters/file_data_source.cc
new file mode 100644
index 0000000..95b0ec0
--- /dev/null
+++ b/media/filters/file_data_source.cc
@@ -0,0 +1,114 @@
+// Copyright (c) 2009 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/file_util.h"
+#include "base/string_util.h"
+#include "media/base/filter_host.h"
+#include "media/base/filters.h"
+#include "media/base/pipeline.h"
+#include "media/filters/file_data_source.h"
+
+namespace media {
+
+FileDataSource::FileDataSource()
+ : file_(NULL),
+ file_size_(0) {
+}
+
+FileDataSource::~FileDataSource() {
+ Stop();
+}
+
+bool FileDataSource::Initialize(const std::string& url) {
+ DCHECK(!file_);
+#if defined(OS_WIN)
+ FilePath file_path(UTF8ToWide(url));
+#else
+ FilePath file_path(url);
+#endif
+ if (file_util::GetFileSize(file_path, &file_size_)) {
+ file_ = file_util::OpenFile(file_path, "rb");
+ }
+ if (!file_) {
+ file_size_ = 0;
+ host_->Error(PIPELINE_ERROR_NETWORK);
+ return false;
+ }
+ media_format_.SetAsString(MediaFormat::kMimeType,
+ mime_type::kApplicationOctetStream);
+ media_format_.SetAsString(MediaFormat::kURL, url);
+ host_->SetTotalBytes(file_size_);
+ host_->SetBufferedBytes(file_size_);
+ host_->InitializationComplete();
+ return true;
+}
+
+void FileDataSource::Stop() {
+ AutoLock l(lock_);
+ if (file_) {
+ file_util::CloseFile(file_);
+ file_ = NULL;
+ file_size_ = 0;
+ }
+}
+
+const MediaFormat* FileDataSource::GetMediaFormat() {
+ return &media_format_;
+}
+
+size_t FileDataSource::Read(char* data, size_t size) {
+ DCHECK(file_);
+ AutoLock l(lock_);
+ if (file_) {
+ size_t size_read = fread(data, 1, size, file_);
+ if (size_read == size || !ferror(file_)) {
+ return size_read;
+ }
+ }
+ return kReadError;
+}
+
+bool FileDataSource::GetPosition(int64* position_out) {
+ DCHECK(position_out);
+ DCHECK(file_);
+ AutoLock l(lock_);
+ if (!file_) {
+ *position_out = 0;
+ return false;
+ }
+// Linux and mac libraries don't seem to support 64 versions of seek and
+// ftell. TODO(ralph): Try to figure out how to enable int64 versions on
+// these platforms.
+#if defined(OS_WIN)
+ *position_out = _ftelli64(file_);
+#else
+ *position_out = ftell(file_);
+#endif
+ return true;
+}
+
+bool FileDataSource::SetPosition(int64 position) {
+ DCHECK(file_);
+ AutoLock l(lock_);
+#if defined(OS_WIN)
+ if (file_ && 0 == _fseeki64(file_, position, SEEK_SET)) {
+ return true;
+ }
+#else
+ if (file_ && 0 == fseek(file_, static_cast<int32>(position), SEEK_SET)) {
+ return true;
+ }
+#endif
+ return false;
+}
+
+bool FileDataSource::GetSize(int64* size_out) {
+ DCHECK(size_out);
+ DCHECK(file_);
+ AutoLock l(lock_);
+ *size_out = file_size_;
+ return (NULL != file_);
+}
+
+} // namespace media
diff --git a/media/filters/file_data_source.h b/media/filters/file_data_source.h
new file mode 100644
index 0000000..9caa435
--- /dev/null
+++ b/media/filters/file_data_source.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2009 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_FILE_DATA_SOURCE_H_
+#define MEDIA_FILTERS_FILE_DATA_SOURCE_H_
+
+#include <string>
+
+#include "base/lock.h"
+#include "media/base/filters.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.
+// TODO(ralph): We will add a pure virtual interface so that the chrome
+// media player delegate can give us the file handle, bytes downloaded so far,
+// and file size.
+class FileDataSource : public DataSource {
+ public:
+ // Public method to get a filter factory for the FileDataSource.
+ static FilterFactory* CreateFactory() {
+ return new FilterFactoryImpl0<FileDataSource>();
+ }
+
+ // Implementation of MediaFilter.
+ virtual void Stop();
+
+ // Implementation of DataSource.
+ virtual bool Initialize(const std::string& url);
+ virtual const MediaFormat* GetMediaFormat();
+ virtual size_t Read(char* data, size_t size);
+ virtual bool GetPosition(int64* position_out);
+ virtual bool SetPosition(int64 position);
+ virtual bool GetSize(int64* size_out);
+
+ private:
+ friend class FilterFactoryImpl0<FileDataSource>;
+ FileDataSource();
+ virtual ~FileDataSource();
+
+ // File handle. Null if not initialized or an error occurs.
+ FILE* file_;
+
+ // Size of the file in bytes.
+ int64 file_size_;
+
+ // Media format handed out by the DataSource::GetMediaFormat method.
+ MediaFormat media_format_;
+
+ // Critical section that protects all of the DataSource methods to prevent
+ // a Stop from happening while in the middle of a file I/O operation.
+ // TODO(ralphl): Ideally this would use asynchronous I/O or we will know
+ // that we will block for a short period of time in reads. Othewise, we can
+ // hang the pipeline Stop.
+ Lock lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileDataSource);
+};
+
+} // namespace media
+
+#endif // MEDIA_FILTERS_FILE_DATA_SOURCE_H_
diff --git a/media/filters/file_data_source_unittest.cc b/media/filters/file_data_source_unittest.cc
new file mode 100644
index 0000000..3006454
--- /dev/null
+++ b/media/filters/file_data_source_unittest.cc
@@ -0,0 +1,95 @@
+// Copyright (c) 2009 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 <string>
+
+#include "base/base_paths.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/string_util.h"
+#include "base/task.h"
+#include "base/waitable_event.h"
+#include "media/base/buffers.h"
+#include "media/base/pipeline_impl.h"
+#include "media/base/media_format.h"
+#include "media/base/filters.h"
+#include "media/base/factory.h"
+#include "media/base/filter_host.h"
+#include "media/base/mock_filter_host.h"
+#include "media/filters/file_data_source.h"
+#include "media/base/mock_media_filters.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using media::FileDataSource;
+using media::FilterFactoryCollection;
+using media::InitializationHelper;
+using media::MediaFormat;
+using media::MockDemuxer;
+using media::MockAudioDecoder;
+using media::MockAudioRenderer;
+using media::MockFilterHost;
+using media::PipelineImpl;
+
+std::string TestFileURL() {
+ FilePath data_dir;
+ EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &data_dir));
+ data_dir = data_dir.Append(FILE_PATH_LITERAL("media"))
+ .Append(FILE_PATH_LITERAL("test"))
+ .Append(FILE_PATH_LITERAL("data"))
+ .Append(FILE_PATH_LITERAL("ten_byte_file"));
+#if defined (OS_WIN)
+ return WideToUTF8(data_dir.value());
+#else
+ return data_dir.value();
+#endif
+}
+
+// Use the "real" pipeline to open the file.
+TEST(FileDataSourceTest, OpenFile) {
+ PipelineImpl pipeline;
+ scoped_refptr<FilterFactoryCollection> c = new FilterFactoryCollection();
+ c->AddFactory(FileDataSource::CreateFactory());
+ c->AddFactory(MockDemuxer::CreateFactory());
+ c->AddFactory(MockAudioDecoder::CreateFactory());
+ c->AddFactory(MockAudioRenderer::CreateFactory());
+ InitializationHelper h;
+ h.Start(&pipeline, c, TestFileURL());
+ h.Wait();
+ EXPECT_EQ(pipeline.GetError(), media::PIPELINE_OK);
+ EXPECT_EQ(pipeline.GetTotalBytes(), 10);
+ EXPECT_EQ(pipeline.GetBufferedBytes(), 10);
+ pipeline.Stop();
+}
+
+// Use the mock filter host to directly call the Read and GetPosition methods.
+TEST(FileDataSourceTest, ReadData) {
+ MediaFormat url_format;
+ int64 position;
+ int64 size;
+ char ten_bytes[10];
+ std::string url = TestFileURL();
+ url_format.SetAsString(MediaFormat::kMimeType, media::mime_type::kURL);
+ url_format.SetAsString(MediaFormat::kURL, url);
+ MockFilterHost<FileDataSource, std::string> mock_host(&url_format, url);
+
+ EXPECT_TRUE(mock_host.filter()->GetSize(&size));
+ EXPECT_EQ(10, size);
+
+ EXPECT_TRUE(mock_host.filter()->GetPosition(&position));
+ EXPECT_EQ(0, position);
+
+ EXPECT_EQ(10u, mock_host.filter()->Read(ten_bytes, sizeof(ten_bytes)));
+ EXPECT_EQ('0', ten_bytes[0]);
+ EXPECT_EQ('5', ten_bytes[5]);
+ EXPECT_EQ('9', ten_bytes[9]);
+ EXPECT_TRUE(mock_host.filter()->GetPosition(&position));
+ EXPECT_EQ(10, position);
+ EXPECT_EQ(0u, mock_host.filter()->Read(ten_bytes, sizeof(ten_bytes)));
+
+ EXPECT_TRUE(mock_host.filter()->SetPosition(5));
+ EXPECT_EQ(5u, mock_host.filter()->Read(ten_bytes, sizeof(ten_bytes)));
+ EXPECT_EQ('5', ten_bytes[0]);
+ EXPECT_TRUE(mock_host.filter()->GetPosition(&position));
+ EXPECT_EQ(10, position);
+}