summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/webcodecs/audio_frame.cc
diff options
context:
space:
mode:
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.cc85
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_;
}