diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/modules/webcodecs/audio_frame.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/modules/webcodecs/audio_frame.cc | 85 |
1 files changed, 71 insertions, 14 deletions
diff --git a/chromium/third_party/blink/renderer/modules/webcodecs/audio_frame.cc b/chromium/third_party/blink/renderer/modules/webcodecs/audio_frame.cc index 6987b60b297..d9ab76dd6be 100644 --- a/chromium/third_party/blink/renderer/modules/webcodecs/audio_frame.cc +++ b/chromium/third_party/blink/renderer/modules/webcodecs/audio_frame.cc @@ -3,10 +3,12 @@ // found in the LICENSE file. #include "third_party/blink/renderer/modules/webcodecs/audio_frame.h" + #include "media/base/audio_buffer.h" #include "media/base/audio_bus.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_audio_frame_init.h" #include "third_party/blink/renderer/modules/webaudio/audio_buffer.h" +#include "third_party/blink/renderer/modules/webcodecs/audio_frame_serialization_data.h" namespace blink { @@ -25,23 +27,77 @@ AudioFrame::AudioFrame(scoped_refptr<media::AudioBuffer> buffer) buffer_ = AudioBuffer::CreateUninitialized( buffer->channel_count(), buffer->frame_count(), buffer->sample_rate()); - // Wrap blink buffer a media::AudioBus so we can interface with - // media::AudioBuffer to copy the data out. - auto media_bus_wrapper = - media::AudioBus::CreateWrapper(buffer->channel_count()); - for (int i = 0; i < media_bus_wrapper->channels(); ++i) { - DCHECK_EQ(buffer_->getChannelData(i)->byteLength(), - buffer->frame_count() * sizeof(float)); - float* channel_data = buffer_->getChannelData(i)->Data(); - media_bus_wrapper->SetChannelData(i, channel_data); - } - media_bus_wrapper->set_frames(buffer->frame_count()); + // AudioBuffer::CreateUninitialized() can fail. This can be the result of + // running out of memory, or having parameters that exceed some of WebAudio's + // limits. Crash here to prevent accessing uninitialized data below. + // TODO(crbug.com/1179079): Add upstream checks to prevent initializing + // |buffer_| with parameters outside of WebAudio's limits. + CHECK(buffer_); - // Copy the frames. + auto converted_data = + media::AudioBus::Create(buffer->channel_count(), buffer->frame_count()); + + std::vector<float*> wrapped_channels(buffer_->numberOfChannels()); + for (unsigned ch = 0; ch < buffer_->numberOfChannels(); ++ch) + wrapped_channels[ch] = buffer_->getChannelData(ch)->Data(); + + // Copy the frames, converting from |buffer|'s internal format to float. // TODO(chcunningham): Avoid this copy by refactoring blink::AudioBuffer to // ref a media::AudioBuffer and only copy for calls to copyToChannel(). - buffer->ReadFrames(media_bus_wrapper->frames(), 0 /* source_frame_offset */, - 0 /* dest_frame_offset */, media_bus_wrapper.get()); + buffer->ReadAllFrames(wrapped_channels); +} + +std::unique_ptr<AudioFrameSerializationData> +AudioFrame::GetSerializationData() { + DCHECK(buffer_); + + // Copy buffer unaligned memory into media::AudioBus' aligned memory. + // TODO(https://crbug.com/1168418): reevaluate if this copy is necessary after + // our changes. E.g. If we can ever guarantee AudioBuffer's memory alignment, + // we could save this copy here, by using buffer_->GetSharedAudioBuffer() and + // wrapping it directly. + auto data_copy = + media::AudioBus::Create(buffer_->numberOfChannels(), buffer_->length()); + + for (int i = 0; i < data_copy->channels(); ++i) { + size_t byte_length = buffer_->getChannelData(i)->byteLength(); + DCHECK_EQ(byte_length, data_copy->frames() * sizeof(float)); + float* buffer_data_src = buffer_->getChannelData(i)->Data(); + memcpy(data_copy->channel(i), buffer_data_src, byte_length); + } + + return AudioFrameSerializationData::Wrap( + std::move(data_copy), buffer_->sampleRate(), + base::TimeDelta::FromMicroseconds(timestamp_)); +} + +AudioFrame::AudioFrame(std::unique_ptr<AudioFrameSerializationData> data) + : timestamp_(data->timestamp().InMicroseconds()) { + media::AudioBus* data_bus = data->data(); + + buffer_ = AudioBuffer::CreateUninitialized( + data_bus->channels(), data_bus->frames(), data->sample_rate()); + + // AudioBuffer::CreateUninitialized() can fail. This can be the result of + // running out of memory, or having parameters that exceed some of WebAudio's + // limits. Crash here to prevent accessing uninitialized data below. + // TODO(crbug.com/1179079): Add upstream checks to prevent initializing + // |buffer_| with parameters outside of WebAudio's limits. + CHECK(buffer_); + + // Copy the frames. + // TODO(https://crbug.com/1168418): Avoid this copy by refactoring + // blink::AudioBuffer accept a serializable audio data backing object. + DCHECK_EQ(static_cast<int>(buffer_->numberOfChannels()), + data_bus->channels()); + DCHECK_EQ(static_cast<int>(buffer_->length()), data_bus->frames()); + + for (int i = 0; i < data_bus->channels(); ++i) { + size_t byte_length = buffer_->getChannelData(i)->byteLength(); + DCHECK_EQ(byte_length, data_bus->frames() * sizeof(float)); + float* buffer_data_dest = buffer_->getChannelData(i)->Data(); + memcpy(buffer_data_dest, data_bus->channel(i), byte_length); + } } void AudioFrame::close() { @@ -51,6 +107,7 @@ void AudioFrame::close() { uint64_t AudioFrame::timestamp() const { return timestamp_; } + AudioBuffer* AudioFrame::buffer() const { return buffer_; } |