summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordalecurtis@google.com <dalecurtis@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-31 20:35:25 +0000
committerdalecurtis@google.com <dalecurtis@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-31 20:35:25 +0000
commitf42d6a10c8645a83220341ef9cfd22b36b3b49b5 (patch)
treedb76016f0b892d43961d1ead916de9f79534fa62
parent665e4fbc3d7de70829f6db36a955f63f9c4d7f9f (diff)
downloadchromium_src-f42d6a10c8645a83220341ef9cfd22b36b3b49b5.zip
chromium_src-f42d6a10c8645a83220341ef9cfd22b36b3b49b5.tar.gz
chromium_src-f42d6a10c8645a83220341ef9cfd22b36b3b49b5.tar.bz2
Introducing DecoderBuffer and general Buffer cleanup.
FFmpeg expects data to be padded and aligned in a certain way. It's currently possible to do this incorrectly and introduce dangerous issues. I enforce padding and alignment by introducing a new Buffer called DecoderBuffer and forcing DemuxerStream::Read to only accept it for transfer into decoders. DecoderBuffer allocates all memory through av_malloc (which takes care of alignment) with the appropriate padding size (except for Android, which doesn't care about this). Along the way it was necessary to clean up a large smattering of code to replace usage of DataBuffer with DecoderBuffer. I've rolled in several cleanup actions as well: - Moved DecryptConfig from Buffer to DecoderBuffer. - Replaced AVPacketBuffer and av_dup_packet with a DecoderBuffer::CopyFrom. - Fixed a resultant issue with FFmpegBitStreamConverter after removing the av_dup_packet functionality. Removed some unsupported bitstream filters. - Reduce TestDataUtil::ReadTestDataFile() to a single method returning a DecoderBuffer so unit tests will always have safe buffers. - Replace new DataBuffer(0)/new DecoderBuffer(0) w/ DecoderBuffer::CreateEOSBuffer. - Remove extraneous IsEndOfStream check from FFmpegAudioDecoder. BUG=129843 TEST=media_unittests + valgrind, layout tests. Review URL: https://chromiumcodereview.appspot.com/10447035 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139857 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--media/audio/win/audio_low_latency_output_win_unittest.cc12
-rw-r--r--media/base/buffers.cc4
-rw-r--r--media/base/buffers.h5
-rw-r--r--media/base/buffers_unittest.cc5
-rw-r--r--media/base/data_buffer.cc48
-rw-r--r--media/base/data_buffer.h8
-rw-r--r--media/base/decoder_buffer.cc87
-rw-r--r--media/base/decoder_buffer.h66
-rw-r--r--media/base/decoder_buffer_unittest.cc103
-rw-r--r--media/base/demuxer_stream.h4
-rw-r--r--media/base/mock_reader.h4
-rw-r--r--media/base/stream_parser_buffer.cc2
-rw-r--r--media/base/stream_parser_buffer.h4
-rw-r--r--media/base/test_data_util.cc37
-rw-r--r--media/base/test_data_util.h26
-rw-r--r--media/base/video_decoder.h1
-rw-r--r--media/crypto/aes_decryptor.cc22
-rw-r--r--media/crypto/aes_decryptor.h7
-rw-r--r--media/crypto/aes_decryptor_unittest.cc13
-rw-r--r--media/filters/chunk_demuxer.cc4
-rw-r--r--media/filters/chunk_demuxer_unittest.cc72
-rw-r--r--media/filters/ffmpeg_audio_decoder.cc16
-rw-r--r--media/filters/ffmpeg_audio_decoder.h5
-rw-r--r--media/filters/ffmpeg_audio_decoder_unittest.cc23
-rw-r--r--media/filters/ffmpeg_demuxer.cc108
-rw-r--r--media/filters/ffmpeg_demuxer.h7
-rw-r--r--media/filters/ffmpeg_demuxer_unittest.cc2
-rw-r--r--media/filters/ffmpeg_h264_bitstream_converter.cc4
-rw-r--r--media/filters/ffmpeg_video_decoder.cc11
-rw-r--r--media/filters/ffmpeg_video_decoder.h7
-rw-r--r--media/filters/ffmpeg_video_decoder_unittest.cc29
-rw-r--r--media/filters/gpu_video_decoder.cc9
-rw-r--r--media/filters/gpu_video_decoder.h8
-rw-r--r--media/filters/pipeline_integration_test.cc19
-rw-r--r--media/media.gyp3
-rw-r--r--media/tools/seek_tester/seek_tester.cc2
36 files changed, 461 insertions, 326 deletions
diff --git a/media/audio/win/audio_low_latency_output_win_unittest.cc b/media/audio/win/audio_low_latency_output_win_unittest.cc
index 298aaf7..c7e4ab5 100644
--- a/media/audio/win/audio_low_latency_output_win_unittest.cc
+++ b/media/audio/win/audio_low_latency_output_win_unittest.cc
@@ -18,6 +18,7 @@
#include "media/audio/audio_manager.h"
#include "media/audio/audio_util.h"
#include "media/audio/win/audio_low_latency_output_win.h"
+#include "media/base/decoder_buffer.h"
#include "media/base/seekable_buffer.h"
#include "media/base/test_data_util.h"
#include "testing/gmock_mutant.h"
@@ -70,7 +71,7 @@ class ReadFromFileAudioSource : public AudioOutputStream::AudioSourceCallback {
elements_to_write_(0) {
// Reads a test file from media/test/data directory and stores it in
// a scoped_array.
- ReadTestDataFile(name, &file_, &file_size_);
+ file_ = ReadTestDataFile(name);
// Creates an array that will store delta times between callbacks.
// The content of this array will be written to a text file at
@@ -115,8 +116,8 @@ class ReadFromFileAudioSource : public AudioOutputStream::AudioSourceCallback {
// Use samples read from a data file and fill up the audio buffer
// provided to us in the callback.
- if (pos_ + static_cast<int>(max_size) > file_size_)
- max_size = file_size_ - pos_;
+ if (pos_ + static_cast<int>(max_size) > file_size())
+ max_size = file_size() - pos_;
if (max_size) {
memcpy(dest, &file_[pos_], max_size);
pos_ += max_size;
@@ -126,12 +127,11 @@ class ReadFromFileAudioSource : public AudioOutputStream::AudioSourceCallback {
virtual void OnError(AudioOutputStream* stream, int code) {}
- int file_size() { return file_size_; }
+ int file_size() { return file_->GetDataSize(); }
private:
- scoped_array<uint8> file_;
+ scoped_refptr<DecoderBuffer> file_;
scoped_array<int> delta_times_;
- int file_size_;
int pos_;
base::Time previous_call_time_;
FILE* text_file_;
diff --git a/media/base/buffers.cc b/media/base/buffers.cc
index 743626a..63802c6 100644
--- a/media/base/buffers.cc
+++ b/media/base/buffers.cc
@@ -17,8 +17,4 @@ bool Buffer::IsEndOfStream() const {
return GetData() == NULL;
}
-const DecryptConfig* Buffer::GetDecryptConfig() const {
- return NULL;
-}
-
} // namespace media
diff --git a/media/base/buffers.h b/media/base/buffers.h
index f4e4264..d14f4db 100644
--- a/media/base/buffers.h
+++ b/media/base/buffers.h
@@ -33,8 +33,6 @@
namespace media {
-class DecryptConfig;
-
// Indicates an invalid or missing timestamp.
MEDIA_EXPORT extern inline base::TimeDelta kNoTimestamp() {
return base::TimeDelta::FromMicroseconds(kint64min);
@@ -56,9 +54,6 @@ class MEDIA_EXPORT Buffer : public base::RefCountedThreadSafe<Buffer> {
// If there's no data in this buffer, it represents end of stream.
bool IsEndOfStream() const;
- // Return DecryptConfig if buffer is encrypted, or NULL otherwise.
- virtual const DecryptConfig* GetDecryptConfig() const;
-
base::TimeDelta GetTimestamp() const {
return timestamp_;
}
diff --git a/media/base/buffers_unittest.cc b/media/base/buffers_unittest.cc
index 6cf0e09..a96b40b 100644
--- a/media/base/buffers_unittest.cc
+++ b/media/base/buffers_unittest.cc
@@ -82,9 +82,4 @@ TEST(BufferTest, IsEndOfStream) {
EXPECT_FALSE(buffer->IsEndOfStream());
}
-TEST(BufferTest, GetDecryptConfig) {
- scoped_refptr<TestBuffer> buffer = new TestBuffer();
- EXPECT_FALSE(buffer->GetDecryptConfig());
-}
-
} // namespace media
diff --git a/media/base/data_buffer.cc b/media/base/data_buffer.cc
index 9a491e3..56d858c 100644
--- a/media/base/data_buffer.cc
+++ b/media/base/data_buffer.cc
@@ -4,10 +4,6 @@
#include "base/logging.h"
#include "media/base/data_buffer.h"
-#include "media/base/decrypt_config.h"
-#if !defined(OS_ANDROID)
-#include "media/ffmpeg/ffmpeg_common.h"
-#endif
namespace media {
@@ -20,38 +16,32 @@ DataBuffer::DataBuffer(scoped_array<uint8> buffer, int buffer_size)
DataBuffer::DataBuffer(int buffer_size)
: Buffer(base::TimeDelta(), base::TimeDelta()),
- data_(new uint8[buffer_size]),
buffer_size_(buffer_size),
data_size_(0) {
- CHECK(data_.get()) << "DataBuffer ctor failed to allocate memory";
-
- // Prevent arbitrary pointers.
- if (buffer_size == 0)
- data_.reset(NULL);
+ Initialize();
}
DataBuffer::DataBuffer(const uint8* data, int data_size)
: Buffer(base::TimeDelta(), base::TimeDelta()),
- buffer_size_(0),
- data_size_(0) {
- if (data_size == 0)
- return;
+ buffer_size_(data_size),
+ data_size_(data_size) {
+ Initialize();
+ memcpy(data_.get(), data, data_size_);
+}
- int padding_size = 0;
-#if !defined(OS_ANDROID)
- // FFmpeg assumes all input buffers are padded with this value.
- padding_size = FF_INPUT_BUFFER_PADDING_SIZE;
-#endif
+DataBuffer::~DataBuffer() {}
+
+void DataBuffer::Initialize() {
+ // Prevent arbitrary pointers.
+ if (buffer_size_ <= 0) {
+ buffer_size_ = data_size_ = 0;
+ data_.reset();
+ return;
+ }
- buffer_size_ = data_size + padding_size;
data_.reset(new uint8[buffer_size_]);
- memcpy(data_.get(), data, data_size);
- memset(data_.get() + data_size, 0, padding_size);
- SetDataSize(data_size);
}
-DataBuffer::~DataBuffer() {}
-
scoped_refptr<DataBuffer> DataBuffer::CopyFrom(const uint8* data,
int data_size) {
return make_scoped_refptr(new DataBuffer(data, data_size));
@@ -65,10 +55,6 @@ int DataBuffer::GetDataSize() const {
return data_size_;
}
-const DecryptConfig* DataBuffer::GetDecryptConfig() const {
- return decrypt_config_.get();
-}
-
uint8* DataBuffer::GetWritableData() {
return data_.get();
}
@@ -82,8 +68,4 @@ int DataBuffer::GetBufferSize() const {
return buffer_size_;
}
-void DataBuffer::SetDecryptConfig(scoped_ptr<DecryptConfig> decrypt_config) {
- decrypt_config_ = decrypt_config.Pass();
-}
-
} // namespace media
diff --git a/media/base/data_buffer.h b/media/base/data_buffer.h
index 136bb85..af05e81 100644
--- a/media/base/data_buffer.h
+++ b/media/base/data_buffer.h
@@ -30,7 +30,6 @@ class MEDIA_EXPORT DataBuffer : public Buffer {
// Buffer implementation.
virtual const uint8* GetData() const OVERRIDE;
virtual int GetDataSize() const OVERRIDE;
- virtual const DecryptConfig* GetDecryptConfig() const OVERRIDE;
// Returns a read-write pointer to the buffer data.
virtual uint8* GetWritableData();
@@ -42,21 +41,18 @@ class MEDIA_EXPORT DataBuffer : public Buffer {
// Returns the size of the underlying buffer.
virtual int GetBufferSize() const;
- virtual void SetDecryptConfig(scoped_ptr<DecryptConfig> decrypt_config);
-
protected:
// Copies from [data,data+size) to owned array.
DataBuffer(const uint8* data, int size);
virtual ~DataBuffer();
private:
- // Helper method to allocate |data_| with at least |buffer_size| bytes.
- void AllocateBuffer(int buffer_size);
+ // Constructor helper method for memory allocations.
+ void Initialize();
scoped_array<uint8> data_;
int buffer_size_;
int data_size_;
- scoped_ptr<DecryptConfig> decrypt_config_;
DISALLOW_COPY_AND_ASSIGN(DataBuffer);
};
diff --git a/media/base/decoder_buffer.cc b/media/base/decoder_buffer.cc
new file mode 100644
index 0000000..527fb65
--- /dev/null
+++ b/media/base/decoder_buffer.cc
@@ -0,0 +1,87 @@
+// 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/decoder_buffer.h"
+
+#include "base/logging.h"
+#include "media/base/decrypt_config.h"
+#if !defined(OS_ANDROID)
+#include "media/ffmpeg/ffmpeg_common.h"
+#endif
+
+namespace media {
+
+DecoderBuffer::DecoderBuffer(int buffer_size)
+ : Buffer(base::TimeDelta(), base::TimeDelta()),
+ buffer_size_(buffer_size) {
+ Initialize();
+}
+
+DecoderBuffer::DecoderBuffer(const uint8* data, int buffer_size)
+ : Buffer(base::TimeDelta(), base::TimeDelta()),
+ buffer_size_(buffer_size) {
+ // Prevent invalid allocations. Also used to create end of stream buffers.
+ if (!data) {
+ buffer_size_ = 0;
+ data_ = NULL;
+ return;
+ }
+
+ Initialize();
+ memcpy(data_, data, buffer_size_);
+}
+
+DecoderBuffer::~DecoderBuffer() {
+#if !defined(OS_ANDROID)
+ av_free(data_);
+#else
+ delete[] data_;
+#endif
+}
+
+void DecoderBuffer::Initialize() {
+ DCHECK_GE(buffer_size_, 0);
+#if !defined(OS_ANDROID)
+ // Why FF_INPUT_BUFFER_PADDING_SIZE? FFmpeg assumes all input buffers are
+ // padded. Using av_malloc with padding ensures FFmpeg only recieves data
+ // padded and aligned to its specifications.
+ data_ = reinterpret_cast<uint8*>(
+ av_malloc(buffer_size_ + FF_INPUT_BUFFER_PADDING_SIZE));
+ memset(data_ + buffer_size_, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+#else
+ data_ = new uint8[buffer_size_];
+#endif
+}
+
+scoped_refptr<DecoderBuffer> DecoderBuffer::CopyFrom(const uint8* data,
+ int data_size) {
+ DCHECK(data);
+ return make_scoped_refptr(new DecoderBuffer(data, data_size));
+}
+
+scoped_refptr<DecoderBuffer> DecoderBuffer::CreateEOSBuffer() {
+ return make_scoped_refptr(new DecoderBuffer(NULL, 0));
+}
+
+const uint8* DecoderBuffer::GetData() const {
+ return data_;
+}
+
+int DecoderBuffer::GetDataSize() const {
+ return buffer_size_;
+}
+
+uint8* DecoderBuffer::GetWritableData() {
+ return data_;
+}
+
+const DecryptConfig* DecoderBuffer::GetDecryptConfig() const {
+ return decrypt_config_.get();
+}
+
+void DecoderBuffer::SetDecryptConfig(scoped_ptr<DecryptConfig> decrypt_config) {
+ decrypt_config_ = decrypt_config.Pass();
+}
+
+} // namespace media
diff --git a/media/base/decoder_buffer.h b/media/base/decoder_buffer.h
new file mode 100644
index 0000000..e822de5
--- /dev/null
+++ b/media/base/decoder_buffer.h
@@ -0,0 +1,66 @@
+// 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.
+
+// A specialized buffer for interfacing with audio / video decoders.
+//
+// Specifically ensures that data is aligned and padded as necessary by the
+// underlying decoding framework. On desktop platforms this means memory is
+// allocated using FFmpeg with particular alignment and padding requirements.
+//
+// Also includes decoder specific functionality for decryption.
+
+#ifndef MEDIA_BASE_DECODER_BUFFER_H_
+#define MEDIA_BASE_DECODER_BUFFER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "media/base/buffers.h"
+#include "media/base/decrypt_config.h"
+
+namespace media {
+
+class MEDIA_EXPORT DecoderBuffer : public Buffer {
+ public:
+ // Allocates buffer of size |buffer_size| >= 0. Buffer will be padded and
+ // aligned as necessary.
+ explicit DecoderBuffer(int buffer_size);
+
+ // Create a DecoderBuffer whose |data_| is copied from |data|. Buffer will be
+ // padded and aligned as necessary. |data| must not be NULL and |size| >= 0.
+ static scoped_refptr<DecoderBuffer> CopyFrom(const uint8* data, int size);
+
+ // Create a DecoderBuffer indicating we've reached end of stream. GetData()
+ // and GetWritableData() will return NULL and GetDataSize() will return 0.
+ static scoped_refptr<DecoderBuffer> CreateEOSBuffer();
+
+ // Buffer implementation.
+ virtual const uint8* GetData() const OVERRIDE;
+ virtual int GetDataSize() const OVERRIDE;
+
+ // Returns a read-write pointer to the buffer data.
+ virtual uint8* GetWritableData();
+
+ virtual const DecryptConfig* GetDecryptConfig() const;
+ virtual void SetDecryptConfig(scoped_ptr<DecryptConfig> decrypt_config);
+
+ protected:
+ // Allocates a buffer of size |size| >= 0 and copies |data| into it. Buffer
+ // will be padded and aligned as necessary. If |data| is NULL then |data_| is
+ // set to NULL and |buffer_size_| to 0.
+ DecoderBuffer(const uint8* data, int size);
+ virtual ~DecoderBuffer();
+
+ private:
+ int buffer_size_;
+ uint8* data_;
+ scoped_ptr<DecryptConfig> decrypt_config_;
+
+ // Constructor helper method for memory allocations.
+ void Initialize();
+
+ DISALLOW_COPY_AND_ASSIGN(DecoderBuffer);
+};
+
+} // namespace media
+
+#endif // MEDIA_BASE_DECODER_BUFFER_H_
diff --git a/media/base/decoder_buffer_unittest.cc b/media/base/decoder_buffer_unittest.cc
new file mode 100644
index 0000000..f7ec578
--- /dev/null
+++ b/media/base/decoder_buffer_unittest.cc
@@ -0,0 +1,103 @@
+// 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 "base/string_util.h"
+#include "media/base/decoder_buffer.h"
+#if !defined(OS_ANDROID)
+#include "media/ffmpeg/ffmpeg_common.h"
+#endif
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+TEST(DecoderBufferTest, Constructors) {
+ scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(0));
+ EXPECT_TRUE(buffer->GetData());
+ EXPECT_EQ(0, buffer->GetDataSize());
+ EXPECT_FALSE(buffer->IsEndOfStream());
+
+ const int kTestSize = 10;
+ scoped_refptr<DecoderBuffer> buffer3(new DecoderBuffer(kTestSize));
+ ASSERT_TRUE(buffer3);
+ EXPECT_EQ(kTestSize, buffer3->GetDataSize());
+}
+
+TEST(DecoderBufferTest, CreateEOSBuffer) {
+ scoped_refptr<DecoderBuffer> buffer(DecoderBuffer::CreateEOSBuffer());
+ EXPECT_TRUE(buffer->IsEndOfStream());
+ EXPECT_FALSE(buffer->GetData());
+ EXPECT_EQ(0, buffer->GetDataSize());
+}
+
+TEST(DecoderBufferTest, CopyFrom) {
+ const uint8 kData[] = "hello";
+ const int kDataSize = arraysize(kData);
+ scoped_refptr<DecoderBuffer> buffer2(DecoderBuffer::CopyFrom(
+ reinterpret_cast<const uint8*>(&kData), kDataSize));
+ ASSERT_TRUE(buffer2);
+ EXPECT_NE(kData, buffer2->GetData());
+ EXPECT_EQ(buffer2->GetDataSize(), kDataSize);
+ EXPECT_EQ(0, memcmp(buffer2->GetData(), kData, kDataSize));
+ EXPECT_FALSE(buffer2->IsEndOfStream());
+}
+
+#if !defined(OS_ANDROID)
+TEST(DecoderBufferTest, PaddingAlignment) {
+ const uint8 kData[] = "hello";
+ const int kDataSize = arraysize(kData);
+ scoped_refptr<DecoderBuffer> buffer2(DecoderBuffer::CopyFrom(
+ reinterpret_cast<const uint8*>(&kData), kDataSize));
+ ASSERT_TRUE(buffer2);
+
+ // FFmpeg padding data should always be zeroed.
+ for(int i = 0; i < FF_INPUT_BUFFER_PADDING_SIZE; i++)
+ EXPECT_EQ((buffer2->GetData() + kDataSize)[i], 0);
+
+ // If the data is padded correctly we should be able to read and write past
+ // the end of the data by FF_INPUT_BUFFER_PADDING_SIZE bytes without crashing
+ // or Valgrind/ASAN throwing errors.
+ const uint8 kFillChar = 0xFF;
+ memset(
+ buffer2->GetWritableData() + kDataSize, kFillChar,
+ FF_INPUT_BUFFER_PADDING_SIZE);
+ for(int i = 0; i < FF_INPUT_BUFFER_PADDING_SIZE; i++)
+ EXPECT_EQ((buffer2->GetData() + kDataSize)[i], kFillChar);
+
+ // These alignments will need to be updated to match FFmpeg when it changes.
+#if defined(ARCH_CPU_ARM_FAMILY)
+ // FFmpeg data should be aligned on a 16 byte boundary for ARM.
+ const int kDataAlignment = 16;
+#else
+ // FFmpeg data should be aligned on a 32 byte boundary for x86.
+ const int kDataAlignment = 32;
+#endif
+ EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(
+ buffer2->GetData()) & (kDataAlignment - 1));
+}
+#endif
+
+TEST(DecoderBufferTest, ReadingWriting) {
+ const char kData[] = "hello";
+ const int kDataSize = arraysize(kData);
+
+ scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(kDataSize));
+ ASSERT_TRUE(buffer);
+
+ uint8* data = buffer->GetWritableData();
+ ASSERT_TRUE(data);
+ ASSERT_EQ(kDataSize, buffer->GetDataSize());
+ memcpy(data, kData, kDataSize);
+ const uint8* read_only_data = buffer->GetData();
+ ASSERT_EQ(data, read_only_data);
+ ASSERT_EQ(0, memcmp(read_only_data, kData, kDataSize));
+ EXPECT_FALSE(buffer->IsEndOfStream());
+}
+
+TEST(DecoderBufferTest, GetDecryptConfig) {
+ scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(0));
+ EXPECT_FALSE(buffer->GetDecryptConfig());
+}
+
+} // namespace media
diff --git a/media/base/demuxer_stream.h b/media/base/demuxer_stream.h
index 457818c..4168d04 100644
--- a/media/base/demuxer_stream.h
+++ b/media/base/demuxer_stream.h
@@ -12,7 +12,7 @@
namespace media {
class AudioDecoderConfig;
-class Buffer;
+class DecoderBuffer;
class VideoDecoderConfig;
class MEDIA_EXPORT DemuxerStream
@@ -30,7 +30,7 @@ class MEDIA_EXPORT DemuxerStream
// Non-NULL buffer pointers will contain media data or signal the end of the
// stream. A NULL pointer indicates an aborted Read(). This can happen if the
// DemuxerStream gets flushed and doesn't have any more data to return.
- typedef base::Callback<void(const scoped_refptr<Buffer>&)> ReadCB;
+ typedef base::Callback<void(const scoped_refptr<DecoderBuffer>&)> ReadCB;
virtual void Read(const ReadCB& read_cb) = 0;
// Returns the audio decoder configuration. It is an error to call this method
diff --git a/media/base/mock_reader.h b/media/base/mock_reader.h
index 6098362..b007684 100644
--- a/media/base/mock_reader.h
+++ b/media/base/mock_reader.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -70,7 +70,7 @@ class MockReader
};
// Commonly used reader types.
-typedef MockReader<DemuxerStream, Buffer> DemuxerStreamReader;
+typedef MockReader<DemuxerStream, DecoderBuffer> DemuxerStreamReader;
} // namespace media
diff --git a/media/base/stream_parser_buffer.cc b/media/base/stream_parser_buffer.cc
index b6c3970..6b9a66d 100644
--- a/media/base/stream_parser_buffer.cc
+++ b/media/base/stream_parser_buffer.cc
@@ -26,7 +26,7 @@ base::TimeDelta StreamParserBuffer::GetEndTimestamp() const {
StreamParserBuffer::StreamParserBuffer(const uint8* data, int data_size,
bool is_keyframe)
- : DataBuffer(data, data_size),
+ : DecoderBuffer(data, data_size),
is_keyframe_(is_keyframe) {
SetDuration(kNoTimestamp());
}
diff --git a/media/base/stream_parser_buffer.h b/media/base/stream_parser_buffer.h
index cdd01c5..fa1b944 100644
--- a/media/base/stream_parser_buffer.h
+++ b/media/base/stream_parser_buffer.h
@@ -5,12 +5,12 @@
#ifndef MEDIA_BASE_STREAM_PARSER_BUFFER_H_
#define MEDIA_BASE_STREAM_PARSER_BUFFER_H_
-#include "media/base/data_buffer.h"
+#include "media/base/decoder_buffer.h"
#include "media/base/media_export.h"
namespace media {
-class MEDIA_EXPORT StreamParserBuffer : public DataBuffer {
+class MEDIA_EXPORT StreamParserBuffer : public DecoderBuffer {
public:
static scoped_refptr<StreamParserBuffer> CreateEOSBuffer();
static scoped_refptr<StreamParserBuffer> CopyFrom(
diff --git a/media/base/test_data_util.cc b/media/base/test_data_util.cc
index bb08175..4cba4a8 100644
--- a/media/base/test_data_util.cc
+++ b/media/base/test_data_util.cc
@@ -7,9 +7,7 @@
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
-#include "media/base/buffers.h"
-#include "media/base/data_buffer.h"
-#include "media/ffmpeg/ffmpeg_common.h"
+#include "media/base/decoder_buffer.h"
namespace media {
@@ -24,8 +22,7 @@ std::string GetTestDataURL(const std::string& name) {
return file_path.MaybeAsASCII();
}
-void ReadTestDataFile(const std::string& name, scoped_array<uint8>* buffer,
- int* size) {
+scoped_refptr<DecoderBuffer> ReadTestDataFile(const std::string& name) {
FilePath file_path;
CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
@@ -38,34 +35,14 @@ void ReadTestDataFile(const std::string& name, scoped_array<uint8>* buffer,
CHECK(file_util::GetFileSize(file_path, &tmp))
<< "Failed to get file size for '" << name << "'";
- // Why FF_INPUT_BUFFER_PADDING_SIZE? FFmpeg assumes all input buffers are
- // padded. Since most of our test data is passed to FFmpeg, it makes sense
- // to do the padding here instead of scattering it around test code.
int file_size = static_cast<int>(tmp);
- int padded_size = file_size + FF_INPUT_BUFFER_PADDING_SIZE;
- buffer->reset(reinterpret_cast<uint8_t*>(new uint8[padded_size]));
- memset(buffer->get(), 0, padded_size);
- CHECK(file_size == file_util::ReadFile(file_path,
- reinterpret_cast<char*>(buffer->get()),
- file_size))
- << "Failed to read '" << name << "'";
- *size = file_size;
-}
-
-void ReadTestDataFile(const std::string& name,
- scoped_refptr<DataBuffer>* buffer) {
- scoped_array<uint8> buf;
- int buf_size;
- ReadTestDataFile(name, &buf, &buf_size);
- *buffer = new DataBuffer(buf.Pass(), buf_size);
-}
+ scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(file_size));
+ CHECK_EQ(file_size, file_util::ReadFile(
+ file_path, reinterpret_cast<char*>(buffer->GetWritableData()), file_size))
+ << "Failed to read '" << name << "'";
-void ReadTestDataFile(const std::string& name,
- scoped_refptr<Buffer>* buffer) {
- scoped_refptr<DataBuffer> data_buffer;
- ReadTestDataFile(name, &data_buffer);
- *buffer = data_buffer;
+ return buffer;
}
} // namespace media
diff --git a/media/base/test_data_util.h b/media/base/test_data_util.h
index a132875..81efa80 100644
--- a/media/base/test_data_util.h
+++ b/media/base/test_data_util.h
@@ -13,36 +13,18 @@
namespace media {
-class Buffer;
-class DataBuffer;
+class DecoderBuffer;
// Returns a URL path for a file in the media/test/data directory.
std::string GetTestDataURL(const std::string& name);
// Reads a test file from media/test/data directory and stores it in
-// a scoped_array.
+// a DecoderBuffer. Use DecoderBuffer vs DataBuffer to ensure no matter
+// what a test does, it's safe to use FFmpeg methods.
//
// |name| - The name of the file.
// |buffer| - The contents of the file.
-// |size| - The size of the buffer.
-void ReadTestDataFile(const std::string& name,
- scoped_array<uint8>* buffer,
- int* size);
-
-// Reads a test file from media/test/data directory and stores it in
-// a DataBuffer.
-//
-// |name| - The name of the file.
-// |buffer| - The contents of the file.
-void ReadTestDataFile(const std::string& name,
- scoped_refptr<DataBuffer>* buffer);
-
-// Reads a test file from media/test/data directory and stores it in
-// a Buffer.
-//
-// |name| - The name of the file.
-// |buffer| - The contents of the file.
-void ReadTestDataFile(const std::string& name, scoped_refptr<Buffer>* buffer);
+scoped_refptr<DecoderBuffer> ReadTestDataFile(const std::string& name);
} // namespace media
diff --git a/media/base/video_decoder.h b/media/base/video_decoder.h
index 61b626e..31589d1 100644
--- a/media/base/video_decoder.h
+++ b/media/base/video_decoder.h
@@ -13,7 +13,6 @@
namespace media {
-class Buffer;
class DemuxerStream;
class VideoFrame;
diff --git a/media/crypto/aes_decryptor.cc b/media/crypto/aes_decryptor.cc
index 8d56d76..cbb75b3 100644
--- a/media/crypto/aes_decryptor.cc
+++ b/media/crypto/aes_decryptor.cc
@@ -9,8 +9,7 @@
#include "base/string_piece.h"
#include "crypto/encryptor.h"
#include "crypto/symmetric_key.h"
-#include "media/base/buffers.h"
-#include "media/base/data_buffer.h"
+#include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h"
namespace media {
@@ -19,10 +18,10 @@ namespace media {
static const char kInitialCounter[] = "0000000000000000";
// Decrypt |input| using |key|.
-// Return a scoped_refptr to a Buffer object with the decrypted data on success.
-// Return a scoped_refptr to NULL if the data could not be decrypted.
-static scoped_refptr<Buffer> DecryptData(const Buffer& input,
- crypto::SymmetricKey* key) {
+// Return a DecoderBuffer with the decrypted data if decryption succeeded.
+// Return NULL if decryption failed.
+static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input,
+ crypto::SymmetricKey* key) {
CHECK(input.GetDataSize());
CHECK(key);
@@ -43,9 +42,8 @@ static scoped_refptr<Buffer> DecryptData(const Buffer& input,
return NULL;
}
- // TODO(xhwang): Implement a string based Buffer implementation to avoid
- // data copying.
- return DataBuffer::CopyFrom(
+ // TODO(xhwang): Find a way to avoid this data copy.
+ return DecoderBuffer::CopyFrom(
reinterpret_cast<const uint8*>(decrypted_text.data()),
decrypted_text.size());
}
@@ -81,8 +79,8 @@ void AesDecryptor::AddKey(const uint8* key_id, int key_id_size,
key_map_[key_id_string] = symmetric_key;
}
-scoped_refptr<Buffer> AesDecryptor::Decrypt(
- const scoped_refptr<Buffer>& encrypted) {
+scoped_refptr<DecoderBuffer> AesDecryptor::Decrypt(
+ const scoped_refptr<DecoderBuffer>& encrypted) {
CHECK(encrypted->GetDecryptConfig());
const uint8* key_id = encrypted->GetDecryptConfig()->key_id();
const int key_id_size = encrypted->GetDecryptConfig()->key_id_size();
@@ -101,7 +99,7 @@ scoped_refptr<Buffer> AesDecryptor::Decrypt(
key = found->second;
}
- scoped_refptr<Buffer> decrypted = DecryptData(*encrypted, key);
+ scoped_refptr<DecoderBuffer> decrypted = DecryptData(*encrypted, key);
if (decrypted) {
decrypted->SetTimestamp(encrypted->GetTimestamp());
diff --git a/media/crypto/aes_decryptor.h b/media/crypto/aes_decryptor.h
index 212c9ac..d62528f 100644
--- a/media/crypto/aes_decryptor.h
+++ b/media/crypto/aes_decryptor.h
@@ -19,7 +19,7 @@ class SymmetricKey;
namespace media {
-class Buffer;
+class DecoderBuffer;
// Decrypts AES encrypted buffer into unencrypted buffer.
class MEDIA_EXPORT AesDecryptor {
@@ -35,9 +35,10 @@ class MEDIA_EXPORT AesDecryptor {
const uint8* key, int key_size);
// Decrypt |input| buffer. The |input| should not be NULL.
- // Return a Buffer that contains decrypted data if decryption succeeded.
+ // Return a DecoderBuffer with the decrypted data if decryption succeeded.
// Return NULL if decryption failed.
- scoped_refptr<Buffer> Decrypt(const scoped_refptr<Buffer>& input);
+ scoped_refptr<DecoderBuffer> Decrypt(
+ const scoped_refptr<DecoderBuffer>& input);
private:
// KeyMap owns the crypto::SymmetricKey* and must delete them when they are
diff --git a/media/crypto/aes_decryptor_unittest.cc b/media/crypto/aes_decryptor_unittest.cc
index 70b6881..0b33f61 100644
--- a/media/crypto/aes_decryptor_unittest.cc
+++ b/media/crypto/aes_decryptor_unittest.cc
@@ -4,7 +4,7 @@
#include <string>
-#include "media/base/data_buffer.h"
+#include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h"
#include "media/crypto/aes_decryptor.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -28,7 +28,8 @@ static const unsigned char kKeyId2[] = "Key ID 2.";
class AesDecryptorTest : public testing::Test {
public:
AesDecryptorTest() {
- encrypted_data_ = DataBuffer::CopyFrom(kEncryptedData, kEncryptedDataSize);
+ encrypted_data_ = DecoderBuffer::CopyFrom(
+ kEncryptedData, kEncryptedDataSize);
}
protected:
@@ -38,7 +39,8 @@ class AesDecryptorTest : public testing::Test {
}
void DecryptAndExpectToSucceed() {
- scoped_refptr<Buffer> decrypted = decryptor_.Decrypt(encrypted_data_);
+ scoped_refptr<DecoderBuffer> decrypted =
+ decryptor_.Decrypt(encrypted_data_);
ASSERT_TRUE(decrypted);
int data_length = sizeof(kOriginalData) - 1;
ASSERT_EQ(data_length, decrypted->GetDataSize());
@@ -46,11 +48,12 @@ class AesDecryptorTest : public testing::Test {
}
void DecryptAndExpectToFail() {
- scoped_refptr<Buffer> decrypted = decryptor_.Decrypt(encrypted_data_);
+ scoped_refptr<DecoderBuffer> decrypted =
+ decryptor_.Decrypt(encrypted_data_);
EXPECT_FALSE(decrypted);
}
- scoped_refptr<DataBuffer> encrypted_data_;
+ scoped_refptr<DecoderBuffer> encrypted_data_;
AesDecryptor decryptor_;
};
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc
index 8ec5161..39ceda4 100644
--- a/media/filters/chunk_demuxer.cc
+++ b/media/filters/chunk_demuxer.cc
@@ -189,7 +189,7 @@ void ChunkDemuxerStream::StartWaitingForSeek() {
}
for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it)
- it->Run(scoped_refptr<Buffer>());
+ it->Run(NULL);
}
void ChunkDemuxerStream::Seek(base::TimeDelta time) {
@@ -231,7 +231,7 @@ void ChunkDemuxerStream::Shutdown() {
// Helper function that makes sure |read_cb| runs on |message_loop|.
static void RunOnMessageLoop(const DemuxerStream::ReadCB& read_cb,
MessageLoop* message_loop,
- const scoped_refptr<Buffer>& buffer) {
+ const scoped_refptr<DecoderBuffer>& buffer) {
if (MessageLoop::current() != message_loop) {
message_loop->PostTask(FROM_HERE, base::Bind(
&RunOnMessageLoop, read_cb, message_loop, buffer));
diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc
index aafaf28..a1de2d3 100644
--- a/media/filters/chunk_demuxer_unittest.cc
+++ b/media/filters/chunk_demuxer_unittest.cc
@@ -4,6 +4,7 @@
#include "base/bind.h"
#include "media/base/audio_decoder_config.h"
+#include "media/base/decoder_buffer.h"
#include "media/base/mock_callback.h"
#include "media/base/mock_demuxer_host.h"
#include "media/base/test_data_util.h"
@@ -70,7 +71,7 @@ MATCHER_P(HasTimestamp, timestamp_in_ms, "") {
static void OnReadDone(const base::TimeDelta& expected_time,
bool* called,
- const scoped_refptr<Buffer>& buffer) {
+ const scoped_refptr<DecoderBuffer>& buffer) {
EXPECT_EQ(expected_time, buffer->GetTimestamp());
*called = true;
}
@@ -115,63 +116,61 @@ class ChunkDemuxerTest : public testing::Test {
void CreateInfoTracks(bool has_audio, bool has_video,
bool video_content_encoded, scoped_array<uint8>* buffer,
int* size) {
- scoped_array<uint8> info;
- int info_size = 0;
- scoped_array<uint8> audio_track_entry;
- int audio_track_entry_size = 0;
- scoped_array<uint8> video_track_entry;
- int video_track_entry_size = 0;
- scoped_array<uint8> video_content_encodings;
- int video_content_encodings_size = 0;
+ scoped_refptr<DecoderBuffer> info;
+ scoped_refptr<DecoderBuffer> audio_track_entry;
+ scoped_refptr<DecoderBuffer> video_track_entry;
+ scoped_refptr<DecoderBuffer> video_content_encodings;
- ReadTestDataFile("webm_info_element", &info, &info_size);
+ info = ReadTestDataFile("webm_info_element");
int tracks_element_size = 0;
if (has_audio) {
- ReadTestDataFile("webm_vorbis_track_entry", &audio_track_entry,
- &audio_track_entry_size);
- tracks_element_size += audio_track_entry_size;
+ audio_track_entry = ReadTestDataFile("webm_vorbis_track_entry");
+ tracks_element_size += audio_track_entry->GetDataSize();
}
if (has_video) {
- ReadTestDataFile("webm_vp8_track_entry", &video_track_entry,
- &video_track_entry_size);
- tracks_element_size += video_track_entry_size;
+ video_track_entry = ReadTestDataFile("webm_vp8_track_entry");
+ tracks_element_size += video_track_entry->GetDataSize();
if (video_content_encoded) {
- ReadTestDataFile("webm_content_encodings", &video_content_encodings,
- &video_content_encodings_size);
- tracks_element_size += video_content_encodings_size;
+ video_content_encodings = ReadTestDataFile("webm_content_encodings");
+ tracks_element_size += video_content_encodings->GetDataSize();
}
}
- *size = info_size + kTracksHeaderSize + tracks_element_size;
+ *size = info->GetDataSize() + kTracksHeaderSize + tracks_element_size;
buffer->reset(new uint8[*size]);
uint8* buf = buffer->get();
- memcpy(buf, info.get(), info_size);
- buf += info_size;
+ memcpy(buf, info->GetData(), info->GetDataSize());
+ buf += info->GetDataSize();
memcpy(buf, kTracksHeader, kTracksHeaderSize);
WriteInt64(buf + kTracksSizeOffset, tracks_element_size);
buf += kTracksHeaderSize;
if (has_audio) {
- memcpy(buf, audio_track_entry.get(), audio_track_entry_size);
- buf += audio_track_entry_size;
+ memcpy(buf, audio_track_entry->GetData(),
+ audio_track_entry->GetDataSize());
+ buf += audio_track_entry->GetDataSize();
}
if (has_video) {
- memcpy(buf, video_track_entry.get(), video_track_entry_size);
+ memcpy(buf, video_track_entry->GetData(),
+ video_track_entry->GetDataSize());
if (video_content_encoded) {
- memcpy(buf + video_track_entry_size, video_content_encodings.get(),
- video_content_encodings_size);
- video_track_entry_size += video_content_encodings_size;
+ memcpy(buf + video_track_entry->GetDataSize(),
+ video_content_encodings->GetData(),
+ video_content_encodings->GetDataSize());
WriteInt64(buf + kVideoTrackSizeOffset,
- video_track_entry_size - kVideoTrackEntryHeaderSize);
+ video_track_entry->GetDataSize() +
+ video_content_encodings->GetDataSize() -
+ kVideoTrackEntryHeaderSize);
+ buf += video_content_encodings->GetDataSize();
}
- buf += video_track_entry_size;
+ buf += video_track_entry->GetDataSize();
}
}
@@ -340,7 +339,7 @@ class ChunkDemuxerTest : public testing::Test {
}
}
- MOCK_METHOD1(ReadDone, void(const scoped_refptr<Buffer>&));
+ MOCK_METHOD1(ReadDone, void(const scoped_refptr<DecoderBuffer>&));
void ExpectRead(DemuxerStream* stream, int64 timestamp_in_ms) {
EXPECT_CALL(*this, ReadDone(HasTimestamp(timestamp_in_ms)));
@@ -365,9 +364,6 @@ class ChunkDemuxerTest : public testing::Test {
bool ParseWebMFile(const std::string& filename,
const BufferTimestamps* timestamps,
const base::TimeDelta& duration) {
- scoped_array<uint8> buffer;
- int buffer_size = 0;
-
EXPECT_CALL(*client_, DemuxerOpened(_));
demuxer_->Initialize(
&host_, CreateInitDoneCB(duration, PIPELINE_OK));
@@ -376,8 +372,8 @@ class ChunkDemuxerTest : public testing::Test {
return false;
// Read a WebM file into memory and send the data to the demuxer.
- ReadTestDataFile(filename, &buffer, &buffer_size);
- if (!AppendDataInPieces(buffer.get(), buffer_size, 512))
+ scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
+ if (!AppendDataInPieces(buffer->GetData(), buffer->GetDataSize(), 512))
return false;
scoped_refptr<DemuxerStream> audio =
@@ -774,8 +770,8 @@ class EndOfStreamHelper {
}
private:
- static void OnEndOfStreamReadDone(bool* called,
- const scoped_refptr<Buffer>& buffer) {
+ static void OnEndOfStreamReadDone(
+ bool* called, const scoped_refptr<DecoderBuffer>& buffer) {
EXPECT_TRUE(buffer->IsEndOfStream());
*called = true;
}
diff --git a/media/filters/ffmpeg_audio_decoder.cc b/media/filters/ffmpeg_audio_decoder.cc
index dc660e5..be750bf 100644
--- a/media/filters/ffmpeg_audio_decoder.cc
+++ b/media/filters/ffmpeg_audio_decoder.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/data_buffer.h"
+#include "media/base/decoder_buffer.h"
#include "media/base/demuxer.h"
#include "media/base/pipeline.h"
#include "media/ffmpeg/ffmpeg_common.h"
@@ -168,7 +169,8 @@ void FFmpegAudioDecoder::DoRead(const ReadCB& read_cb) {
ReadFromDemuxerStream();
}
-void FFmpegAudioDecoder::DoDecodeBuffer(const scoped_refptr<Buffer>& input) {
+void FFmpegAudioDecoder::DoDecodeBuffer(
+ const scoped_refptr<DecoderBuffer>& input) {
DCHECK_EQ(MessageLoop::current(), message_loop_);
DCHECK(!read_cb_.is_null());
@@ -190,13 +192,8 @@ void FFmpegAudioDecoder::DoDecodeBuffer(const scoped_refptr<Buffer>& input) {
AVPacket packet;
av_init_packet(&packet);
- if (input->IsEndOfStream()) {
- packet.data = NULL;
- packet.size = 0;
- } else {
- packet.data = const_cast<uint8*>(input->GetData());
- packet.size = input->GetDataSize();
- }
+ packet.data = const_cast<uint8*>(input->GetData());
+ packet.size = input->GetDataSize();
PipelineStatistics statistics;
statistics.audio_bytes_decoded = input->GetDataSize();
@@ -256,7 +253,8 @@ void FFmpegAudioDecoder::ReadFromDemuxerStream() {
demuxer_stream_->Read(base::Bind(&FFmpegAudioDecoder::DecodeBuffer, this));
}
-void FFmpegAudioDecoder::DecodeBuffer(const scoped_refptr<Buffer>& buffer) {
+void FFmpegAudioDecoder::DecodeBuffer(
+ const scoped_refptr<DecoderBuffer>& buffer) {
// TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read
// callback on the same execution stack so we can get rid of forced task post.
message_loop_->PostTask(FROM_HERE, base::Bind(
diff --git a/media/filters/ffmpeg_audio_decoder.h b/media/filters/ffmpeg_audio_decoder.h
index 04739a2..5dbe895 100644
--- a/media/filters/ffmpeg_audio_decoder.h
+++ b/media/filters/ffmpeg_audio_decoder.h
@@ -16,6 +16,7 @@ struct AVCodecContext;
namespace media {
class DataBuffer;
+class DecoderBuffer;
class MEDIA_EXPORT FFmpegAudioDecoder : public AudioDecoder {
public:
@@ -41,11 +42,11 @@ class MEDIA_EXPORT FFmpegAudioDecoder : public AudioDecoder {
const StatisticsCB& statistics_cb);
void DoReset(const base::Closure& closure);
void DoRead(const ReadCB& read_cb);
- void DoDecodeBuffer(const scoped_refptr<Buffer>& input);
+ void DoDecodeBuffer(const scoped_refptr<DecoderBuffer>& input);
// Reads from the demuxer stream with corresponding callback method.
void ReadFromDemuxerStream();
- void DecodeBuffer(const scoped_refptr<Buffer>& buffer);
+ void DecodeBuffer(const scoped_refptr<DecoderBuffer>& buffer);
// Updates the output buffer's duration and timestamp based on the input
// buffer. Will fall back to an estimated timestamp if the input lacks a
diff --git a/media/filters/ffmpeg_audio_decoder_unittest.cc b/media/filters/ffmpeg_audio_decoder_unittest.cc
index cbd1b10..b81b73b 100644
--- a/media/filters/ffmpeg_audio_decoder_unittest.cc
+++ b/media/filters/ffmpeg_audio_decoder_unittest.cc
@@ -7,7 +7,7 @@
#include "base/bind.h"
#include "base/message_loop.h"
#include "base/stringprintf.h"
-#include "media/base/data_buffer.h"
+#include "media/base/decoder_buffer.h"
#include "media/base/mock_callback.h"
#include "media/base/mock_filters.h"
#include "media/base/test_data_util.h"
@@ -35,14 +35,12 @@ class FFmpegAudioDecoderTest : public testing::Test {
demuxer_(new StrictMock<MockDemuxerStream>()) {
CHECK(FFmpegGlue::GetInstance());
- ReadTestDataFile("vorbis-extradata",
- &vorbis_extradata_,
- &vorbis_extradata_size_);
+ vorbis_extradata_ = ReadTestDataFile("vorbis-extradata");
// Refer to media/test/data/README for details on vorbis test data.
for (int i = 0; i < 4; ++i) {
- scoped_refptr<Buffer> buffer;
- ReadTestDataFile(base::StringPrintf("vorbis-packet-%d", i), &buffer);
+ scoped_refptr<DecoderBuffer> buffer =
+ ReadTestDataFile(base::StringPrintf("vorbis-packet-%d", i));
if (i < 3) {
buffer->SetTimestamp(base::TimeDelta());
@@ -55,14 +53,14 @@ class FFmpegAudioDecoderTest : public testing::Test {
}
// Push in an EOS buffer.
- encoded_audio_.push_back(new DataBuffer(0));
+ encoded_audio_.push_back(DecoderBuffer::CreateEOSBuffer());
config_.Initialize(kCodecVorbis,
16,
CHANNEL_LAYOUT_STEREO,
44100,
- vorbis_extradata_.get(),
- vorbis_extradata_size_,
+ vorbis_extradata_->GetData(),
+ vorbis_extradata_->GetDataSize(),
true);
}
@@ -83,7 +81,7 @@ class FFmpegAudioDecoderTest : public testing::Test {
void ReadPacket(const DemuxerStream::ReadCB& read_cb) {
CHECK(!encoded_audio_.empty()) << "ReadPacket() called too many times";
- scoped_refptr<Buffer> buffer(encoded_audio_.front());
+ scoped_refptr<DecoderBuffer> buffer(encoded_audio_.front());
encoded_audio_.pop_front();
read_cb.Run(buffer);
}
@@ -117,10 +115,9 @@ class FFmpegAudioDecoderTest : public testing::Test {
scoped_refptr<StrictMock<MockDemuxerStream> > demuxer_;
MockStatisticsCB statistics_cb_;
- scoped_array<uint8> vorbis_extradata_;
- int vorbis_extradata_size_;
+ scoped_refptr<DecoderBuffer> vorbis_extradata_;
- std::deque<scoped_refptr<Buffer> > encoded_audio_;
+ std::deque<scoped_refptr<DecoderBuffer> > encoded_audio_;
std::deque<scoped_refptr<Buffer> > decoded_audio_;
AudioDecoderConfig config_;
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index 3d7a5fe..16c5447 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -16,7 +16,7 @@
#include "base/string_util.h"
#include "base/time.h"
#include "media/base/audio_decoder_config.h"
-#include "media/base/data_buffer.h"
+#include "media/base/decoder_buffer.h"
#include "media/base/limits.h"
#include "media/base/media_switches.h"
#include "media/base/video_decoder_config.h"
@@ -28,37 +28,6 @@
namespace media {
//
-// AVPacketBuffer
-//
-class AVPacketBuffer : public Buffer {
- public:
- AVPacketBuffer(scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet,
- const base::TimeDelta& timestamp,
- const base::TimeDelta& duration)
- : Buffer(timestamp, duration),
- packet_(packet.Pass()) {
- }
-
- // Buffer implementation.
- virtual const uint8* GetData() const {
- return reinterpret_cast<const uint8*>(packet_->data);
- }
-
- virtual int GetDataSize() const {
- return packet_->size;
- }
-
- protected:
- virtual ~AVPacketBuffer() {}
-
- private:
- scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet_;
-
- DISALLOW_COPY_AND_ASSIGN(AVPacketBuffer);
-};
-
-
-//
// FFmpegDemuxerStream
//
FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer,
@@ -100,10 +69,6 @@ bool FFmpegDemuxerStream::HasPendingReads() {
void FFmpegDemuxerStream::EnqueuePacket(
scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet) {
DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop());
- base::TimeDelta timestamp =
- ConvertStreamTimestamp(stream_->time_base, packet->pts);
- base::TimeDelta duration =
- ConvertStreamTimestamp(stream_->time_base, packet->duration);
base::AutoLock auto_lock(lock_);
if (stopped_) {
@@ -111,19 +76,26 @@ void FFmpegDemuxerStream::EnqueuePacket(
return;
}
- // Convert if the packet if there is bitstream filter.
- if (packet->data && bitstream_converter_.get() &&
- !bitstream_converter_->ConvertPacket(packet.get())) {
- LOG(ERROR) << "Format converstion failed.";
- }
+ scoped_refptr<DecoderBuffer> buffer;
+ if (!packet.get()) {
+ buffer = DecoderBuffer::CreateEOSBuffer();
+ } else {
+ // Convert the packet if there is a bitstream filter.
+ if (packet->data && bitstream_converter_.get() &&
+ !bitstream_converter_->ConvertPacket(packet.get())) {
+ LOG(ERROR) << "Format converstion failed.";
+ }
- // Enqueue the callback and attempt to satisfy a read immediately.
- scoped_refptr<Buffer> buffer(
- new AVPacketBuffer(packet.Pass(), timestamp, duration));
- if (!buffer) {
- NOTREACHED() << "Unable to allocate AVPacketBuffer";
- return;
+ // If a packet is returned by FFmpeg's av_parser_parse2() the packet will
+ // reference inner memory of FFmpeg. As such we should transfer the packet
+ // into memory we control.
+ buffer = DecoderBuffer::CopyFrom(packet->data, packet->size);
+ buffer->SetTimestamp(ConvertStreamTimestamp(
+ stream_->time_base, packet->pts));
+ buffer->SetDuration(ConvertStreamTimestamp(
+ stream_->time_base, packet->duration));
}
+
buffer_queue_.push_back(buffer);
FulfillPendingRead();
return;
@@ -142,7 +114,7 @@ void FFmpegDemuxerStream::Stop() {
buffer_queue_.clear();
for (ReadQueue::iterator it = read_queue_.begin();
it != read_queue_.end(); ++it) {
- it->Run(scoped_refptr<Buffer>(new DataBuffer(0)));
+ it->Run(scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer()));
}
read_queue_.clear();
stopped_ = true;
@@ -165,7 +137,7 @@ void FFmpegDemuxerStream::Read(const ReadCB& read_cb) {
//
// TODO(scherkus): it would be cleaner if we replied with an error message.
if (stopped_) {
- read_cb.Run(scoped_refptr<Buffer>(new DataBuffer(0)));
+ read_cb.Run(scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer()));
return;
}
@@ -179,7 +151,7 @@ void FFmpegDemuxerStream::Read(const ReadCB& read_cb) {
}
// Send the oldest buffer back.
- scoped_refptr<Buffer> buffer = buffer_queue_.front();
+ scoped_refptr<DecoderBuffer> buffer = buffer_queue_.front();
buffer_queue_.pop_front();
read_cb.Run(buffer);
}
@@ -192,7 +164,7 @@ void FFmpegDemuxerStream::ReadTask(const ReadCB& read_cb) {
//
// TODO(scherkus): it would be cleaner if we replied with an error message.
if (stopped_) {
- read_cb.Run(scoped_refptr<Buffer>(new DataBuffer(0)));
+ read_cb.Run(scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer()));
return;
}
@@ -214,7 +186,7 @@ void FFmpegDemuxerStream::FulfillPendingRead() {
}
// Dequeue a buffer and pending read pair.
- scoped_refptr<Buffer> buffer = buffer_queue_.front();
+ scoped_refptr<DecoderBuffer> buffer = buffer_queue_.front();
ReadCB read_cb(read_queue_.front());
buffer_queue_.pop_front();
read_queue_.pop_front();
@@ -233,22 +205,12 @@ void FFmpegDemuxerStream::EnableBitstreamConverter() {
bitstream_converter_.reset(
new FFmpegH264BitstreamConverter(stream_->codec));
CHECK(bitstream_converter_->Initialize());
- return;
- }
-
- const char* filter_name = NULL;
- if (stream_->codec->codec_id == CODEC_ID_MPEG4) {
- filter_name = "mpeg4video_es";
- } else if (stream_->codec->codec_id == CODEC_ID_WMV3) {
- filter_name = "vc1_asftorcv";
- } else if (stream_->codec->codec_id == CODEC_ID_VC1) {
- filter_name = "vc1_asftoannexg";
- }
-
- if (filter_name) {
+ } else if (stream_->codec->codec_id == CODEC_ID_MPEG4) {
bitstream_converter_.reset(
- new FFmpegBitstreamConverter(filter_name, stream_->codec));
+ new FFmpegBitstreamConverter("mpeg4video_es", stream_->codec));
CHECK(bitstream_converter_->Initialize());
+ } else {
+ NOTREACHED() << "Unsupported bitstream format.";
}
}
@@ -676,15 +638,6 @@ void FFmpegDemuxer::DemuxTask() {
(!audio_disabled_ ||
streams_[packet->stream_index]->type() != DemuxerStream::AUDIO)) {
FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index];
-
- // If a packet is returned by FFmpeg's av_parser_parse2()
- // the packet will reference an inner memory of FFmpeg.
- // In this case, the packet's "destruct" member is NULL,
- // and it MUST be duplicated. This fixes issue with MP3 and possibly
- // other codecs. It is safe to call this function even if the packet does
- // not refer to inner memory from FFmpeg.
- av_dup_packet(packet.get());
-
demuxer_stream->EnqueuePacket(packet.Pass());
}
@@ -739,9 +692,8 @@ void FFmpegDemuxer::StreamHasEnded() {
(audio_disabled_ && (*iter)->type() == DemuxerStream::AUDIO)) {
continue;
}
- scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet(new AVPacket());
- memset(packet.get(), 0, sizeof(*packet.get()));
- (*iter)->EnqueuePacket(packet.Pass());
+ (*iter)->EnqueuePacket(
+ scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket>());
}
}
diff --git a/media/filters/ffmpeg_demuxer.h b/media/filters/ffmpeg_demuxer.h
index ba7d1f2..dee6db3 100644
--- a/media/filters/ffmpeg_demuxer.h
+++ b/media/filters/ffmpeg_demuxer.h
@@ -29,7 +29,7 @@
#include "base/gtest_prod_util.h"
#include "base/synchronization/waitable_event.h"
#include "media/base/audio_decoder_config.h"
-#include "media/base/buffers.h"
+#include "media/base/decoder_buffer.h"
#include "media/base/demuxer.h"
#include "media/base/pipeline.h"
#include "media/base/video_decoder_config.h"
@@ -58,7 +58,8 @@ class FFmpegDemuxerStream : public DemuxerStream {
// Safe to call on any thread.
bool HasPendingReads();
- // Enqueues the given AVPacket.
+ // Enqueues the given AVPacket. If |packet| is NULL an end of stream packet
+ // is enqueued.
void EnqueuePacket(scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet);
// Signals to empty the buffer queue and mark next packet as discontinuous.
@@ -115,7 +116,7 @@ class FFmpegDemuxerStream : public DemuxerStream {
bool discontinuous_;
bool stopped_;
- typedef std::deque<scoped_refptr<Buffer> > BufferQueue;
+ typedef std::deque<scoped_refptr<DecoderBuffer> > BufferQueue;
BufferQueue buffer_queue_;
typedef std::deque<ReadCB> ReadQueue;
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc
index 292bb2f..261578f 100644
--- a/media/filters/ffmpeg_demuxer_unittest.cc
+++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -442,7 +442,7 @@ class MockReadCB : public base::RefCountedThreadSafe<MockReadCB> {
MockReadCB() {}
MOCK_METHOD0(OnDelete, void());
- MOCK_METHOD1(Run, void(const scoped_refptr<Buffer>& buffer));
+ MOCK_METHOD1(Run, void(const scoped_refptr<DecoderBuffer>& buffer));
protected:
virtual ~MockReadCB() {
diff --git a/media/filters/ffmpeg_h264_bitstream_converter.cc b/media/filters/ffmpeg_h264_bitstream_converter.cc
index 6220daf..2995083 100644
--- a/media/filters/ffmpeg_h264_bitstream_converter.cc
+++ b/media/filters/ffmpeg_h264_bitstream_converter.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -91,7 +91,7 @@ bool FFmpegH264BitstreamConverter::ConvertPacket(AVPacket* packet) {
}
// At the end we must destroy the old packet.
- packet->destruct(packet);
+ av_free_packet(packet);
*packet = dest_packet; // Finally, replace the values in the input packet.
return true;
diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc
index f85b6cb..930a290 100644
--- a/media/filters/ffmpeg_video_decoder.cc
+++ b/media/filters/ffmpeg_video_decoder.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/string_number_conversions.h"
+#include "media/base/decoder_buffer.h"
#include "media/base/demuxer_stream.h"
#include "media/base/limits.h"
#include "media/base/media_switches.h"
@@ -208,14 +209,16 @@ void FFmpegVideoDecoder::ReadFromDemuxerStream() {
demuxer_stream_->Read(base::Bind(&FFmpegVideoDecoder::DecodeBuffer, this));
}
-void FFmpegVideoDecoder::DecodeBuffer(const scoped_refptr<Buffer>& buffer) {
+void FFmpegVideoDecoder::DecodeBuffer(
+ const scoped_refptr<DecoderBuffer>& buffer) {
// TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read
// callback on the same execution stack so we can get rid of forced task post.
message_loop_->PostTask(FROM_HERE, base::Bind(
&FFmpegVideoDecoder::DoDecodeBuffer, this, buffer));
}
-void FFmpegVideoDecoder::DoDecodeBuffer(const scoped_refptr<Buffer>& buffer) {
+void FFmpegVideoDecoder::DoDecodeBuffer(
+ const scoped_refptr<DecoderBuffer>& buffer) {
DCHECK_EQ(MessageLoop::current(), message_loop_);
DCHECK_NE(state_, kUninitialized);
DCHECK_NE(state_, kDecodeFinished);
@@ -262,7 +265,7 @@ void FFmpegVideoDecoder::DoDecodeBuffer(const scoped_refptr<Buffer>& buffer) {
state_ = kFlushCodec;
}
- scoped_refptr<Buffer> unencrypted_buffer = buffer;
+ scoped_refptr<DecoderBuffer> unencrypted_buffer = buffer;
if (buffer->GetDecryptConfig() && buffer->GetDataSize()) {
unencrypted_buffer = decryptor_.Decrypt(buffer);
if (!unencrypted_buffer || !unencrypted_buffer->GetDataSize()) {
@@ -303,7 +306,7 @@ void FFmpegVideoDecoder::DoDecodeBuffer(const scoped_refptr<Buffer>& buffer) {
}
bool FFmpegVideoDecoder::Decode(
- const scoped_refptr<Buffer>& buffer,
+ const scoped_refptr<DecoderBuffer>& buffer,
scoped_refptr<VideoFrame>* video_frame) {
DCHECK(video_frame);
diff --git a/media/filters/ffmpeg_video_decoder.h b/media/filters/ffmpeg_video_decoder.h
index d1d181d..4d99a43 100644
--- a/media/filters/ffmpeg_video_decoder.h
+++ b/media/filters/ffmpeg_video_decoder.h
@@ -12,6 +12,7 @@
#include "media/base/video_decoder.h"
#include "media/crypto/aes_decryptor.h"
+class DecoderBuffer;
class MessageLoop;
struct AVCodecContext;
@@ -50,11 +51,11 @@ class MEDIA_EXPORT FFmpegVideoDecoder : public VideoDecoder {
// Reads from the demuxer stream with corresponding callback method.
void ReadFromDemuxerStream();
- void DecodeBuffer(const scoped_refptr<Buffer>& buffer);
+ void DecodeBuffer(const scoped_refptr<DecoderBuffer>& buffer);
// Carries out the decoding operation scheduled by DecodeBuffer().
- void DoDecodeBuffer(const scoped_refptr<Buffer>& buffer);
- bool Decode(const scoped_refptr<Buffer>& buffer,
+ void DoDecodeBuffer(const scoped_refptr<DecoderBuffer>& buffer);
+ bool Decode(const scoped_refptr<DecoderBuffer>& buffer,
scoped_refptr<VideoFrame>* video_frame);
// Delivers the frame to |read_cb_| and resets the callback.
diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc
index 24e716e..b0fc360 100644
--- a/media/filters/ffmpeg_video_decoder_unittest.cc
+++ b/media/filters/ffmpeg_video_decoder_unittest.cc
@@ -8,7 +8,7 @@
#include "base/message_loop.h"
#include "base/memory/singleton.h"
#include "base/string_util.h"
-#include "media/base/data_buffer.h"
+#include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h"
#include "media/base/limits.h"
#include "media/base/mock_callback.h"
@@ -57,11 +57,11 @@ class FFmpegVideoDecoderTest : public testing::Test {
// Initialize various test buffers.
frame_buffer_.reset(new uint8[kCodedSize.GetArea()]);
- end_of_stream_buffer_ = new DataBuffer(0);
- ReadTestDataFile("vp8-I-frame-320x240", &i_frame_buffer_);
- ReadTestDataFile("vp8-corrupt-I-frame", &corrupt_i_frame_buffer_);
- ReadTestDataFile("vp8-encrypted-I-frame-320x240",
- &encrypted_i_frame_buffer_);
+ end_of_stream_buffer_ = DecoderBuffer::CreateEOSBuffer();
+ i_frame_buffer_ = ReadTestDataFile("vp8-I-frame-320x240");
+ corrupt_i_frame_buffer_ = ReadTestDataFile("vp8-corrupt-I-frame");
+ encrypted_i_frame_buffer_ = ReadTestDataFile(
+ "vp8-encrypted-I-frame-320x240");
config_.Initialize(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN,
kVideoFormat, kCodedSize, kVisibleRect,
@@ -129,7 +129,7 @@ class FFmpegVideoDecoderTest : public testing::Test {
// uncompressed output to |video_frame|. This method works with single
// and multithreaded decoders. End of stream buffers are used to trigger
// the frame to be returned in the multithreaded decoder case.
- void DecodeSingleFrame(const scoped_refptr<Buffer>& buffer,
+ void DecodeSingleFrame(const scoped_refptr<DecoderBuffer>& buffer,
VideoDecoder::DecoderStatus* status,
scoped_refptr<VideoFrame>* video_frame) {
EXPECT_CALL(*demuxer_, Read(_))
@@ -154,8 +154,7 @@ class FFmpegVideoDecoderTest : public testing::Test {
scoped_refptr<VideoFrame> video_frame_a;
scoped_refptr<VideoFrame> video_frame_b;
- scoped_refptr<Buffer> buffer;
- ReadTestDataFile(test_file_name, &buffer);
+ scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(test_file_name);
EXPECT_CALL(*demuxer_, Read(_))
.WillOnce(ReturnBuffer(i_frame_buffer_))
@@ -204,10 +203,10 @@ class FFmpegVideoDecoderTest : public testing::Test {
// Various buffers for testing.
scoped_array<uint8_t> frame_buffer_;
- scoped_refptr<Buffer> end_of_stream_buffer_;
- scoped_refptr<Buffer> i_frame_buffer_;
- scoped_refptr<Buffer> corrupt_i_frame_buffer_;
- scoped_refptr<DataBuffer> encrypted_i_frame_buffer_;
+ scoped_refptr<DecoderBuffer> end_of_stream_buffer_;
+ scoped_refptr<DecoderBuffer> i_frame_buffer_;
+ scoped_refptr<DecoderBuffer> corrupt_i_frame_buffer_;
+ scoped_refptr<DecoderBuffer> encrypted_i_frame_buffer_;
// Used for generating timestamped buffers.
std::deque<int64> timestamps_;
@@ -271,7 +270,7 @@ TEST_F(FFmpegVideoDecoderTest, DecodeFrame_Normal) {
TEST_F(FFmpegVideoDecoderTest, DecodeFrame_0ByteFrame) {
Initialize();
- scoped_refptr<DataBuffer> zero_byte_buffer = new DataBuffer(1);
+ scoped_refptr<DecoderBuffer> zero_byte_buffer = new DecoderBuffer(0);
VideoDecoder::DecoderStatus status_a;
VideoDecoder::DecoderStatus status_b;
@@ -514,7 +513,7 @@ TEST_F(FFmpegVideoDecoderTest, AbortPendingRead) {
Initialize();
EXPECT_CALL(*demuxer_, Read(_))
- .WillOnce(ReturnBuffer(scoped_refptr<Buffer>()));
+ .WillOnce(ReturnBuffer(scoped_refptr<DecoderBuffer>()));
VideoDecoder::DecoderStatus status;
scoped_refptr<VideoFrame> video_frame;
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc
index ee0ba30..9352790 100644
--- a/media/filters/gpu_video_decoder.cc
+++ b/media/filters/gpu_video_decoder.cc
@@ -8,6 +8,7 @@
#include "base/callback_helpers.h"
#include "base/message_loop.h"
#include "base/stl_util.h"
+#include "media/base/decoder_buffer.h"
#include "media/base/demuxer_stream.h"
#include "media/base/filter_host.h"
#include "media/base/pipeline.h"
@@ -29,7 +30,8 @@ GpuVideoDecoder::SHMBuffer::SHMBuffer(base::SharedMemory* m, size_t s)
GpuVideoDecoder::SHMBuffer::~SHMBuffer() {}
GpuVideoDecoder::BufferPair::BufferPair(
- SHMBuffer* s, const scoped_refptr<Buffer>& b) : shm_buffer(s), buffer(b) {
+ SHMBuffer* s, const scoped_refptr<DecoderBuffer>& b)
+ : shm_buffer(s), buffer(b) {
}
GpuVideoDecoder::BufferPair::~BufferPair() {}
@@ -193,7 +195,8 @@ void GpuVideoDecoder::Read(const ReadCB& read_cb) {
}
}
-void GpuVideoDecoder::RequestBufferDecode(const scoped_refptr<Buffer>& buffer) {
+void GpuVideoDecoder::RequestBufferDecode(
+ const scoped_refptr<DecoderBuffer>& buffer) {
if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
&GpuVideoDecoder::RequestBufferDecode, this, buffer));
@@ -440,7 +443,7 @@ void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) {
}
PutSHM(it->second.shm_buffer);
- const scoped_refptr<Buffer>& buffer = it->second.buffer;
+ const scoped_refptr<DecoderBuffer>& buffer = it->second.buffer;
if (buffer->GetDataSize()) {
PipelineStatistics statistics;
statistics.video_bytes_decoded = buffer->GetDataSize();
diff --git a/media/filters/gpu_video_decoder.h b/media/filters/gpu_video_decoder.h
index b91b015..4274d15 100644
--- a/media/filters/gpu_video_decoder.h
+++ b/media/filters/gpu_video_decoder.h
@@ -22,6 +22,8 @@ class SharedMemory;
namespace media {
+class DecoderBuffer;
+
// GPU-accelerated video decoder implementation. Relies on
// AcceleratedVideoDecoderMsg_Decode and friends.
// All methods internally trampoline to the |message_loop| passed to the ctor.
@@ -98,7 +100,7 @@ class MEDIA_EXPORT GpuVideoDecoder
void EnsureDemuxOrDecode();
// Callback to pass to demuxer_stream_->Read() for receiving encoded bits.
- void RequestBufferDecode(const scoped_refptr<Buffer>& buffer);
+ void RequestBufferDecode(const scoped_refptr<DecoderBuffer>& buffer);
// Enqueue a frame for later delivery (or drop it on the floor if a
// vda->Reset() is in progress) and trigger out-of-line delivery of the oldest
@@ -175,10 +177,10 @@ class MEDIA_EXPORT GpuVideoDecoder
// Book-keeping variables.
struct BufferPair {
- BufferPair(SHMBuffer* s, const scoped_refptr<Buffer>& b);
+ BufferPair(SHMBuffer* s, const scoped_refptr<DecoderBuffer>& b);
~BufferPair();
SHMBuffer* shm_buffer;
- scoped_refptr<Buffer> buffer;
+ scoped_refptr<DecoderBuffer> buffer;
};
std::map<int32, BufferPair> bitstream_buffers_in_decoder_;
std::map<int32, PictureBuffer> picture_buffers_in_decoder_;
diff --git a/media/filters/pipeline_integration_test.cc b/media/filters/pipeline_integration_test.cc
index dae9423..c3f81e3 100644
--- a/media/filters/pipeline_integration_test.cc
+++ b/media/filters/pipeline_integration_test.cc
@@ -5,6 +5,7 @@
#include "media/filters/pipeline_integration_test_base.h"
#include "base/bind.h"
+#include "media/base/decoder_buffer.h"
#include "media/base/test_data_util.h"
#include "media/filters/chunk_demuxer_client.h"
@@ -24,10 +25,10 @@ class MockMediaSource : public ChunkDemuxerClient {
: url_(GetTestDataURL(filename)),
current_position_(0),
initial_append_size_(initial_append_size) {
- ReadTestDataFile(filename, &file_data_, &file_data_size_);
+ file_data_ = ReadTestDataFile(filename);
DCHECK_GT(initial_append_size_, 0);
- DCHECK_LE(initial_append_size_, file_data_size_);
+ DCHECK_LE(initial_append_size_, file_data_->GetDataSize());
}
virtual ~MockMediaSource() {}
@@ -45,7 +46,7 @@ class MockMediaSource : public ChunkDemuxerClient {
chunk_demuxer_->StartWaitingForSeek();
DCHECK_GE(new_position, 0);
- DCHECK_LT(new_position, file_data_size_);
+ DCHECK_LT(new_position, file_data_->GetDataSize());
current_position_ = new_position;
AppendData(seek_append_size);
@@ -53,11 +54,10 @@ class MockMediaSource : public ChunkDemuxerClient {
void AppendData(int size) {
DCHECK(chunk_demuxer_.get());
- DCHECK_LT(current_position_, file_data_size_);
- DCHECK_LE(current_position_ + size, file_data_size_);
- CHECK(chunk_demuxer_->AppendData(kSourceId,
- file_data_.get() + current_position_,
- size));
+ DCHECK_LT(current_position_, file_data_->GetDataSize());
+ DCHECK_LE(current_position_ + size, file_data_->GetDataSize());
+ CHECK(chunk_demuxer_->AppendData(
+ kSourceId, file_data_->GetData() + current_position_, size));
current_position_ += size;
}
@@ -98,8 +98,7 @@ class MockMediaSource : public ChunkDemuxerClient {
private:
std::string url_;
- scoped_array<uint8> file_data_;
- int file_data_size_;
+ scoped_refptr<DecoderBuffer> file_data_;
int current_position_;
int initial_append_size_;
scoped_refptr<ChunkDemuxer> chunk_demuxer_;
diff --git a/media/media.gyp b/media/media.gyp
index 7d9b4eb..8c5a3b7 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -141,6 +141,8 @@
'base/data_buffer.h',
'base/data_source.cc',
'base/data_source.h',
+ 'base/decoder_buffer.cc',
+ 'base/decoder_buffer.h',
'base/decrypt_config.cc',
'base/decrypt_config.h',
'base/demuxer.cc',
@@ -662,6 +664,7 @@
'base/clock_unittest.cc',
'base/composite_filter_unittest.cc',
'base/data_buffer_unittest.cc',
+ 'base/decoder_buffer_unittest.cc',
'base/djb2_unittest.cc',
'base/filter_collection_unittest.cc',
'base/h264_bitstream_converter_unittest.cc',
diff --git a/media/tools/seek_tester/seek_tester.cc b/media/tools/seek_tester/seek_tester.cc
index 901c1bd..f8e769d 100644
--- a/media/tools/seek_tester/seek_tester.cc
+++ b/media/tools/seek_tester/seek_tester.cc
@@ -41,7 +41,7 @@ void QuitMessageLoop(MessageLoop* loop, media::PipelineStatus status) {
void TimestampExtractor(uint64* timestamp_ms,
MessageLoop* loop,
- const scoped_refptr<media::Buffer>& buffer) {
+ const scoped_refptr<media::DecoderBuffer>& buffer) {
if (buffer->GetTimestamp() == media::kNoTimestamp())
*timestamp_ms = -1;
else