diff options
author | jrummell <jrummell@chromium.org> | 2015-11-24 19:10:10 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-25 03:11:56 +0000 |
commit | e45d9fa36a51ed750b71b7543563960962d44a90 (patch) | |
tree | c330c2834fa2ded7df01e5fd4d1ab9ebc742acf3 | |
parent | c321986254c6b5cc4ce919131894b4f67d45f7d3 (diff) | |
download | chromium_src-e45d9fa36a51ed750b71b7543563960962d44a90.zip chromium_src-e45d9fa36a51ed750b71b7543563960962d44a90.tar.gz chromium_src-e45d9fa36a51ed750b71b7543563960962d44a90.tar.bz2 |
Define AudioBuffer and VideoFrame for mojo
Adds support so they can be converted to and from the matching classes
in media::
BUG=510088
TEST=new tests pass
Review URL: https://codereview.chromium.org/1468153003
Cr-Commit-Position: refs/heads/master@{#361530}
-rw-r--r-- | media/base/audio_buffer.cc | 32 | ||||
-rw-r--r-- | media/base/audio_buffer.h | 17 | ||||
-rw-r--r-- | media/base/sample_format.cc | 36 | ||||
-rw-r--r-- | media/base/sample_format.h | 6 | ||||
-rw-r--r-- | media/mojo/interfaces/decryptor.mojom | 4 | ||||
-rw-r--r-- | media/mojo/interfaces/media_types.mojom | 55 | ||||
-rw-r--r-- | media/mojo/services/BUILD.gn | 2 | ||||
-rw-r--r-- | media/mojo/services/media_type_converters.cc | 122 | ||||
-rw-r--r-- | media/mojo/services/media_type_converters.h | 28 | ||||
-rw-r--r-- | media/mojo/services/media_type_converters_unittest.cc | 157 |
10 files changed, 438 insertions, 21 deletions
diff --git a/media/base/audio_buffer.cc b/media/base/audio_buffer.cc index 564cff15..a497640 100644 --- a/media/base/audio_buffer.cc +++ b/media/base/audio_buffer.cc @@ -37,7 +37,8 @@ AudioBuffer::AudioBuffer(SampleFormat sample_format, timestamp_(timestamp), duration_(end_of_stream_ ? base::TimeDelta() - : CalculateDuration(adjusted_frame_count_, sample_rate_)) { + : CalculateDuration(adjusted_frame_count_, sample_rate_)), + data_size_(0) { CHECK_GE(channel_count_, 0); CHECK_LE(channel_count_, limits::kMaxChannels); CHECK_GE(frame_count, 0); @@ -46,49 +47,46 @@ AudioBuffer::AudioBuffer(SampleFormat sample_format, int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format); DCHECK_LE(bytes_per_channel, kChannelAlignment); - int data_size = frame_count * bytes_per_channel; // Empty buffer? if (!create_buffer) return; - if (sample_format == kSampleFormatPlanarF32 || - sample_format == kSampleFormatPlanarS16 || - sample_format == kSampleFormatPlanarS32) { + int data_size_per_channel = frame_count * bytes_per_channel; + if (IsPlanar(sample_format)) { // Planar data, so need to allocate buffer for each channel. // Determine per channel data size, taking into account alignment. int block_size_per_channel = - (data_size + kChannelAlignment - 1) & ~(kChannelAlignment - 1); - DCHECK_GE(block_size_per_channel, data_size); + (data_size_per_channel + kChannelAlignment - 1) & + ~(kChannelAlignment - 1); + DCHECK_GE(block_size_per_channel, data_size_per_channel); // Allocate a contiguous buffer for all the channel data. - data_.reset(static_cast<uint8*>(base::AlignedAlloc( - channel_count_ * block_size_per_channel, kChannelAlignment))); + data_size_ = channel_count_ * block_size_per_channel; + data_.reset( + static_cast<uint8*>(base::AlignedAlloc(data_size_, kChannelAlignment))); channel_data_.reserve(channel_count_); // Copy each channel's data into the appropriate spot. for (int i = 0; i < channel_count_; ++i) { channel_data_.push_back(data_.get() + i * block_size_per_channel); if (data) - memcpy(channel_data_[i], data[i], data_size); + memcpy(channel_data_[i], data[i], data_size_per_channel); } return; } // Remaining formats are interleaved data. - DCHECK(sample_format_ == kSampleFormatU8 || - sample_format_ == kSampleFormatS16 || - sample_format_ == kSampleFormatS32 || - sample_format_ == kSampleFormatF32) << sample_format_; + DCHECK(IsInterleaved(sample_format)) << sample_format_; // Allocate our own buffer and copy the supplied data into it. Buffer must // contain the data for all channels. - data_size *= channel_count_; + data_size_ = data_size_per_channel * channel_count_; data_.reset( - static_cast<uint8*>(base::AlignedAlloc(data_size, kChannelAlignment))); + static_cast<uint8*>(base::AlignedAlloc(data_size_, kChannelAlignment))); channel_data_.reserve(1); channel_data_.push_back(data_.get()); if (data) - memcpy(data_.get(), data[0], data_size); + memcpy(data_.get(), data[0], data_size_); } AudioBuffer::~AudioBuffer() {} diff --git a/media/base/audio_buffer.h b/media/base/audio_buffer.h index 63390d4..bf8e433 100644 --- a/media/base/audio_buffer.h +++ b/media/base/audio_buffer.h @@ -15,9 +15,20 @@ #include "media/base/media_export.h" #include "media/base/sample_format.h" +namespace mojo { +template <typename T, typename U> +struct TypeConverter; +template <typename T> +class StructPtr; +}; + namespace media { class AudioBus; +namespace interfaces { +class AudioBuffer; +} + // An audio buffer that takes a copy of the data passed to it, holds it, and // copies it into an AudioBus when needed. Also supports an end of stream // marker. @@ -123,6 +134,11 @@ class MEDIA_EXPORT AudioBuffer private: friend class base::RefCountedThreadSafe<AudioBuffer>; + // mojo::TypeConverter added as a friend so that AudioBuffer can be + // transferred across a mojo connection. + friend struct mojo::TypeConverter<mojo::StructPtr<interfaces::AudioBuffer>, + scoped_refptr<AudioBuffer>>; + // Allocates aligned contiguous buffer to hold all channel data (1 block for // interleaved data, |channel_count| blocks for planar data), copies // [data,data+data_size) to the allocated buffer(s). If |data| is null, no @@ -151,6 +167,7 @@ class MEDIA_EXPORT AudioBuffer // Contiguous block of channel data. scoped_ptr<uint8, base::AlignedFreeDeleter> data_; + size_t data_size_; // For planar data, points to each channels data. std::vector<uint8*> channel_data_; diff --git a/media/base/sample_format.cc b/media/base/sample_format.cc index 464fc1b..dd0bc1d 100644 --- a/media/base/sample_format.cc +++ b/media/base/sample_format.cc @@ -51,4 +51,40 @@ const char* SampleFormatToString(SampleFormat sample_format) { return ""; } +bool IsPlanar(SampleFormat sample_format) { + switch (sample_format) { + case kSampleFormatPlanarS16: + case kSampleFormatPlanarF32: + case kSampleFormatPlanarS32: + return true; + case kUnknownSampleFormat: + case kSampleFormatU8: + case kSampleFormatS16: + case kSampleFormatS32: + case kSampleFormatF32: + return false; + } + + NOTREACHED() << "Invalid sample format provided: " << sample_format; + return false; +} + +bool IsInterleaved(SampleFormat sample_format) { + switch (sample_format) { + case kSampleFormatU8: + case kSampleFormatS16: + case kSampleFormatS32: + case kSampleFormatF32: + return true; + case kUnknownSampleFormat: + case kSampleFormatPlanarS16: + case kSampleFormatPlanarF32: + case kSampleFormatPlanarS32: + return false; + } + + NOTREACHED() << "Invalid sample format provided: " << sample_format; + return false; +} + } // namespace media diff --git a/media/base/sample_format.h b/media/base/sample_format.h index 7a48843..0260f169 100644 --- a/media/base/sample_format.h +++ b/media/base/sample_format.h @@ -34,6 +34,12 @@ MEDIA_EXPORT int SampleFormatToBytesPerChannel(SampleFormat sample_format); // Returns the name of the sample format as a string MEDIA_EXPORT const char* SampleFormatToString(SampleFormat sample_format); +// Returns true if |sample_format| is planar, false otherwise. +MEDIA_EXPORT bool IsPlanar(SampleFormat sample_format); + +// Returns true if |sample_format| is interleaved, false otherwise. +MEDIA_EXPORT bool IsInterleaved(SampleFormat sample_format); + } // namespace media #endif // MEDIA_BASE_SAMPLE_FORMAT_H diff --git a/media/mojo/interfaces/decryptor.mojom b/media/mojo/interfaces/decryptor.mojom index 9c5d678..e25df3e 100644 --- a/media/mojo/interfaces/decryptor.mojom +++ b/media/mojo/interfaces/decryptor.mojom @@ -7,10 +7,6 @@ module media.interfaces; import "media/mojo/interfaces/demuxer_stream.mojom"; import "media/mojo/interfaces/media_types.mojom"; -// TODO(xhwang): Add mojo types for AudioBuffer and VideoFrame. -struct AudioBuffer {}; -struct VideoFrame {}; - // Interface for decrypting (and decoding) encrypted streams. // See media/base/decryptor.h for details. interface Decryptor { diff --git a/media/mojo/interfaces/media_types.mojom b/media/mojo/interfaces/media_types.mojom index a16203e..78784f9 100644 --- a/media/mojo/interfaces/media_types.mojom +++ b/media/mojo/interfaces/media_types.mojom @@ -231,3 +231,58 @@ struct DecoderBuffer { // Indicates this buffer is part of a splice around |splice_timestamp_usec|. int64 splice_timestamp_usec; }; + +// This defines a mojo transport format for media::AudioBuffer. +struct AudioBuffer { + // Format of the audio. + SampleFormat sample_format; + + // How the channels are laid out. + ChannelLayout channel_layout; + + // Number of channels. + int32 channel_count; + + // Sample rate of the buffer. + int32 sample_rate; + + // Number of frames in the buffer. + int32 frame_count; + + // True if end of stream. + bool end_of_stream; + + // Timestamp in microseconds of the first frame. + int64 timestamp_usec; + + // Channel data. Will be null for EOS buffers. + array<uint8>? data; +}; + +// This defines a mojo transport format for media::VideoFrame. +// TODO(jrummell): Support shared memory based VideoFrame to avoid copying +// the data multiple times. +struct VideoFrame { + // Format of the frame. + VideoFormat format; + + // Width and height of the video frame, in pixels. + mojo.Size coded_size; + + // Visible size of the frame. + mojo.Rect visible_rect; + + // Natural size of the frame. + mojo.Size natural_size; + + // True if end of stream. + bool end_of_stream; + + // Timestamp in microseconds of the associated frame. + int64 timestamp_usec; + + // Frame data for each plane. Will be null for EOS buffers. + array<uint8>? y_data; + array<uint8>? u_data; + array<uint8>? v_data; +}; diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn index 24fcdfc..23690f80 100644 --- a/media/mojo/services/BUILD.gn +++ b/media/mojo/services/BUILD.gn @@ -183,8 +183,10 @@ test("media_mojo_unittests") { "//base", "//base/test:test_support", "//media", + "//media/base:test_support", "//media/mojo/interfaces", "//mojo/environment:chromium", + "//testing/gmock", "//testing/gtest", "//third_party/mojo/src/mojo/edk/system", "//third_party/mojo/src/mojo/edk/test:run_all_unittests", diff --git a/media/mojo/services/media_type_converters.cc b/media/mojo/services/media_type_converters.cc index 5f84a49..ae2c7e2 100644 --- a/media/mojo/services/media_type_converters.cc +++ b/media/mojo/services/media_type_converters.cc @@ -4,6 +4,7 @@ #include "media/mojo/services/media_type_converters.h" +#include "media/base/audio_buffer.h" #include "media/base/audio_decoder_config.h" #include "media/base/buffering_state.h" #include "media/base/cdm_config.h" @@ -13,6 +14,7 @@ #include "media/base/demuxer_stream.h" #include "media/base/media_keys.h" #include "media/base/video_decoder_config.h" +#include "media/base/video_frame.h" #include "media/mojo/interfaces/demuxer_stream.mojom.h" #include "mojo/converters/geometry/geometry_type_converters.h" @@ -529,4 +531,124 @@ TypeConverter<media::CdmConfig, media::interfaces::CdmConfigPtr>::Convert( return config; } +// static +media::interfaces::AudioBufferPtr +TypeConverter<media::interfaces::AudioBufferPtr, + scoped_refptr<media::AudioBuffer>>:: + Convert(const scoped_refptr<media::AudioBuffer>& input) { + media::interfaces::AudioBufferPtr buffer( + media::interfaces::AudioBuffer::New()); + buffer->sample_format = + static_cast<media::interfaces::SampleFormat>(input->sample_format_); + buffer->channel_layout = + static_cast<media::interfaces::ChannelLayout>(input->channel_layout()); + buffer->channel_count = input->channel_count(); + buffer->sample_rate = input->sample_rate(); + buffer->frame_count = input->frame_count(); + buffer->end_of_stream = input->end_of_stream(); + buffer->timestamp_usec = input->timestamp().InMicroseconds(); + + if (!input->end_of_stream()) { + std::vector<uint8_t> input_data(input->data_.get(), + input->data_.get() + input->data_size_); + buffer->data.Swap(&input_data); + } + + return buffer.Pass(); +} + +// static +scoped_refptr<media::AudioBuffer> +TypeConverter<scoped_refptr<media::AudioBuffer>, + media::interfaces::AudioBufferPtr>:: + Convert(const media::interfaces::AudioBufferPtr& input) { + if (input->end_of_stream) + return media::AudioBuffer::CreateEOSBuffer(); + + // Setup channel pointers. AudioBuffer::CopyFrom() will only use the first + // one in the case of interleaved data. + std::vector<const uint8_t*> channel_ptrs(input->channel_count, nullptr); + std::vector<uint8_t> storage = input->data.storage(); + const int size_per_channel = storage.size() / input->channel_count; + DCHECK_EQ(0u, storage.size() % input->channel_count); + for (int i = 0; i < input->channel_count; ++i) + channel_ptrs[i] = storage.data() + i * size_per_channel; + + return media::AudioBuffer::CopyFrom( + static_cast<media::SampleFormat>(input->sample_format), + static_cast<media::ChannelLayout>(input->channel_layout), + input->channel_count, input->sample_rate, input->frame_count, + &channel_ptrs[0], + base::TimeDelta::FromMicroseconds(input->timestamp_usec)); +} + +// static +media::interfaces::VideoFramePtr +TypeConverter<media::interfaces::VideoFramePtr, + scoped_refptr<media::VideoFrame>>:: + Convert(const scoped_refptr<media::VideoFrame>& input) { + media::interfaces::VideoFramePtr buffer(media::interfaces::VideoFrame::New()); + buffer->end_of_stream = + input->metadata()->IsTrue(media::VideoFrameMetadata::END_OF_STREAM); + if (buffer->end_of_stream) + return buffer.Pass(); + + // handle non EOS buffer. + buffer->format = static_cast<media::interfaces::VideoFormat>(input->format()); + buffer->coded_size = Size::From(input->coded_size()); + buffer->visible_rect = Rect::From(input->visible_rect()); + buffer->natural_size = Size::From(input->natural_size()); + buffer->timestamp_usec = input->timestamp().InMicroseconds(); + + if (!input->coded_size().IsEmpty()) { + // TODO(jrummell): Use a shared buffer rather than copying the data for + // each plane. + std::vector<uint8_t> y_data( + input->data(media::VideoFrame::kYPlane), + input->data(media::VideoFrame::kYPlane) + + input->rows(media::VideoFrame::kYPlane) * + input->stride(media::VideoFrame::kYPlane)); + buffer->y_data.Swap(&y_data); + + std::vector<uint8_t> u_data( + input->data(media::VideoFrame::kUPlane), + input->data(media::VideoFrame::kUPlane) + + input->rows(media::VideoFrame::kUPlane) * + input->stride(media::VideoFrame::kUPlane)); + buffer->u_data.Swap(&u_data); + + std::vector<uint8_t> v_data( + input->data(media::VideoFrame::kVPlane), + input->data(media::VideoFrame::kVPlane) + + input->rows(media::VideoFrame::kVPlane) * + input->stride(media::VideoFrame::kVPlane)); + buffer->v_data.Swap(&v_data); + } + + return buffer.Pass(); +} + +// static +scoped_refptr<media::VideoFrame> +TypeConverter<scoped_refptr<media::VideoFrame>, + media::interfaces::VideoFramePtr>:: + Convert(const media::interfaces::VideoFramePtr& input) { + if (input->end_of_stream) + return media::VideoFrame::CreateEOSFrame(); + + scoped_refptr<media::VideoFrame> frame = media::VideoFrame::CreateFrame( + static_cast<media::VideoPixelFormat>(input->format), + input->coded_size.To<gfx::Size>(), input->visible_rect.To<gfx::Rect>(), + input->natural_size.To<gfx::Size>(), + base::TimeDelta::FromMicroseconds(input->timestamp_usec)); + memcpy(frame->data(media::VideoFrame::kYPlane), + input->y_data.storage().data(), input->y_data.storage().size()); + memcpy(frame->data(media::VideoFrame::kUPlane), + input->u_data.storage().data(), input->u_data.storage().size()); + memcpy(frame->data(media::VideoFrame::kVPlane), + input->v_data.storage().data(), input->v_data.storage().size()); + + return frame.Pass(); +} + } // namespace mojo diff --git a/media/mojo/services/media_type_converters.h b/media/mojo/services/media_type_converters.h index 0133a99..92450c8 100644 --- a/media/mojo/services/media_type_converters.h +++ b/media/mojo/services/media_type_converters.h @@ -12,10 +12,12 @@ #include "mojo/public/cpp/bindings/type_converter.h" namespace media { +class AudioBuffer; class AudioDecoderConfig; class DecoderBuffer; class DecryptConfig; class VideoDecoderConfig; +class VideoFrame; struct CdmConfig; struct CdmKeyInformation; struct SubsampleEntry; @@ -112,6 +114,32 @@ struct TypeConverter<media::CdmConfig, media::interfaces::CdmConfigPtr> { static media::CdmConfig Convert(const media::interfaces::CdmConfigPtr& input); }; +template <> +struct TypeConverter<media::interfaces::AudioBufferPtr, + scoped_refptr<media::AudioBuffer>> { + static media::interfaces::AudioBufferPtr Convert( + const scoped_refptr<media::AudioBuffer>& input); +}; +template <> +struct TypeConverter<scoped_refptr<media::AudioBuffer>, + media::interfaces::AudioBufferPtr> { + static scoped_refptr<media::AudioBuffer> Convert( + const media::interfaces::AudioBufferPtr& input); +}; + +template <> +struct TypeConverter<media::interfaces::VideoFramePtr, + scoped_refptr<media::VideoFrame>> { + static media::interfaces::VideoFramePtr Convert( + const scoped_refptr<media::VideoFrame>& input); +}; +template <> +struct TypeConverter<scoped_refptr<media::VideoFrame>, + media::interfaces::VideoFramePtr> { + static scoped_refptr<media::VideoFrame> Convert( + const media::interfaces::VideoFramePtr& input); +}; + } // namespace mojo #endif // MEDIA_MOJO_SERVICES_MEDIA_TYPE_CONVERTERS_H_ diff --git a/media/mojo/services/media_type_converters_unittest.cc b/media/mojo/services/media_type_converters_unittest.cc index 38559f3..dae82d4 100644 --- a/media/mojo/services/media_type_converters_unittest.cc +++ b/media/mojo/services/media_type_converters_unittest.cc @@ -4,14 +4,87 @@ #include "media/mojo/services/media_type_converters.h" +#include <string.h> + +#include "media/base/audio_buffer.h" #include "media/base/audio_decoder_config.h" #include "media/base/cdm_config.h" #include "media/base/decoder_buffer.h" #include "media/base/media_util.h" +#include "media/base/sample_format.h" +#include "media/base/test_helpers.h" +#include "media/base/video_frame.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { +namespace { + +void CompareBytes(uint8* original_data, uint8* result_data, size_t length) { + EXPECT_GT(length, 0u); + EXPECT_EQ(memcmp(original_data, result_data, length), 0); +} + +void CompareAudioBuffers(SampleFormat sample_format, + const scoped_refptr<AudioBuffer>& original, + const scoped_refptr<AudioBuffer>& result) { + EXPECT_EQ(original->frame_count(), result->frame_count()); + EXPECT_EQ(original->timestamp(), result->timestamp()); + EXPECT_EQ(original->duration(), result->duration()); + EXPECT_EQ(original->sample_rate(), result->sample_rate()); + EXPECT_EQ(original->channel_count(), result->channel_count()); + EXPECT_EQ(original->channel_layout(), result->channel_layout()); + EXPECT_EQ(original->end_of_stream(), result->end_of_stream()); + + // Compare bytes in buffer. + int bytes_per_channel = + original->frame_count() * SampleFormatToBytesPerChannel(sample_format); + if (IsPlanar(sample_format)) { + for (int i = 0; i < original->channel_count(); ++i) { + CompareBytes(original->channel_data()[i], result->channel_data()[i], + bytes_per_channel); + } + return; + } + + DCHECK(IsInterleaved(sample_format)) << sample_format; + CompareBytes(original->channel_data()[0], result->channel_data()[0], + bytes_per_channel * original->channel_count()); +} + +void CompareVideoPlane(size_t plane, + const scoped_refptr<VideoFrame>& original, + const scoped_refptr<VideoFrame>& result) { + EXPECT_EQ(original->stride(plane), result->stride(plane)); + EXPECT_EQ(original->row_bytes(plane), result->row_bytes(plane)); + EXPECT_EQ(original->rows(plane), result->rows(plane)); + CompareBytes(original->data(plane), result->data(plane), + original->rows(plane) * original->row_bytes(plane)); +} + +void CompareVideoFrames(const scoped_refptr<VideoFrame>& original, + const scoped_refptr<VideoFrame>& result) { + if (original->metadata()->IsTrue(media::VideoFrameMetadata::END_OF_STREAM)) { + EXPECT_TRUE( + result->metadata()->IsTrue(media::VideoFrameMetadata::END_OF_STREAM)); + return; + } + + EXPECT_EQ(original->format(), result->format()); + EXPECT_EQ(original->coded_size().height(), result->coded_size().height()); + EXPECT_EQ(original->coded_size().width(), result->coded_size().width()); + EXPECT_EQ(original->visible_rect().height(), result->visible_rect().height()); + EXPECT_EQ(original->visible_rect().width(), result->visible_rect().width()); + EXPECT_EQ(original->natural_size().height(), result->natural_size().height()); + EXPECT_EQ(original->natural_size().width(), result->natural_size().width()); + + CompareVideoPlane(media::VideoFrame::kYPlane, original, result); + CompareVideoPlane(media::VideoFrame::kUPlane, original, result); + CompareVideoPlane(media::VideoFrame::kVPlane, original, result); +} + +} // namespace + TEST(MediaTypeConvertersTest, ConvertDecoderBuffer_Normal) { const uint8 kData[] = "hello, world"; const uint8 kSideData[] = "sideshow bob"; @@ -172,4 +245,88 @@ TEST(MediaTypeConvertersTest, ConvertCdmConfig) { EXPECT_EQ(config.use_hw_secure_codecs, result.use_hw_secure_codecs); } +TEST(MediaTypeConvertersTest, ConvertAudioBuffer_EOS) { + // Original. + scoped_refptr<AudioBuffer> buffer(AudioBuffer::CreateEOSBuffer()); + + // Convert to and back. + interfaces::AudioBufferPtr ptr(interfaces::AudioBuffer::From(buffer)); + scoped_refptr<AudioBuffer> result(ptr.To<scoped_refptr<AudioBuffer>>()); + + // Compare. + EXPECT_TRUE(result->end_of_stream()); +} + +TEST(MediaTypeConvertersTest, ConvertAudioBuffer_MONO) { + // Original. + const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_MONO; + const int kSampleRate = 48000; + scoped_refptr<AudioBuffer> buffer = MakeAudioBuffer<uint8>( + kSampleFormatU8, kChannelLayout, + ChannelLayoutToChannelCount(kChannelLayout), kSampleRate, 1, 1, + kSampleRate / 100, base::TimeDelta()); + + // Convert to and back. + interfaces::AudioBufferPtr ptr(interfaces::AudioBuffer::From(buffer)); + scoped_refptr<AudioBuffer> result(ptr.To<scoped_refptr<AudioBuffer>>()); + + // Compare. + CompareAudioBuffers(kSampleFormatU8, buffer, result); +} + +TEST(MediaTypeConvertersTest, ConvertAudioBuffer_FLOAT) { + // Original. + const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_4_0; + const int kSampleRate = 48000; + const base::TimeDelta start_time = base::TimeDelta::FromSecondsD(1000.0); + scoped_refptr<AudioBuffer> buffer = MakeAudioBuffer<float>( + kSampleFormatPlanarF32, kChannelLayout, + ChannelLayoutToChannelCount(kChannelLayout), kSampleRate, 0.0f, 1.0f, + kSampleRate / 10, start_time); + // Convert to and back. + interfaces::AudioBufferPtr ptr(interfaces::AudioBuffer::From(buffer)); + scoped_refptr<AudioBuffer> result(ptr.To<scoped_refptr<AudioBuffer>>()); + + // Compare. + CompareAudioBuffers(kSampleFormatPlanarF32, buffer, result); +} + +TEST(MediaTypeConvertersTest, ConvertVideoFrame_EOS) { + // Original. + scoped_refptr<VideoFrame> buffer(VideoFrame::CreateEOSFrame()); + + // Convert to and back. + interfaces::VideoFramePtr ptr(interfaces::VideoFrame::From(buffer)); + scoped_refptr<VideoFrame> result(ptr.To<scoped_refptr<VideoFrame>>()); + + // Compare. + CompareVideoFrames(buffer, result); +} + +TEST(MediaTypeConvertersTest, ConvertVideoFrame_BlackFrame) { + // Original. + scoped_refptr<VideoFrame> buffer( + VideoFrame::CreateBlackFrame(gfx::Size(100, 100))); + + // Convert to and back. + interfaces::VideoFramePtr ptr(interfaces::VideoFrame::From(buffer)); + scoped_refptr<VideoFrame> result(ptr.To<scoped_refptr<VideoFrame>>()); + + // Compare. + CompareVideoFrames(buffer, result); +} + +TEST(MediaTypeConvertersTest, ConvertVideoFrame_ColorFrame) { + // Original. + scoped_refptr<VideoFrame> buffer(VideoFrame::CreateColorFrame( + gfx::Size(50, 100), 255, 128, 128, base::TimeDelta::FromSeconds(26))); + + // Convert to and back. + interfaces::VideoFramePtr ptr(interfaces::VideoFrame::From(buffer)); + scoped_refptr<VideoFrame> result(ptr.To<scoped_refptr<VideoFrame>>()); + + // Compare. + CompareVideoFrames(buffer, result); +} + } // namespace media |