blob: 2922bcbe2413fb6b33257bd1df1099c4543cf60c [file] [log] [blame]
// Copyright 2020 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 "third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.h"
#include <utility>
#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_chunk_init.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
EncodedAudioChunk* EncodedAudioChunk::Create(
const EncodedAudioChunkInit* init) {
auto data_wrapper = AsSpan<const uint8_t>(init->data());
auto buffer = data_wrapper.empty()
? base::MakeRefCounted<media::DecoderBuffer>(0)
: media::DecoderBuffer::CopyFrom(data_wrapper.data(),
data_wrapper.size());
// Clamp within bounds of our internal TimeDelta-based duration. See
// media/base/timestamp_constants.h
auto timestamp = base::Microseconds(init->timestamp());
if (timestamp == media::kNoTimestamp)
timestamp = base::TimeDelta::FiniteMin();
else if (timestamp == media::kInfiniteDuration)
timestamp = base::TimeDelta::FiniteMax();
buffer->set_timestamp(timestamp);
// media::kNoTimestamp corresponds to base::TimeDelta::Min(), and internally
// denotes the absence of duration. We use base::TimeDelta::FiniteMax() -
// which is one less than base::TimeDelta::Max() - because
// base::TimeDelta::Max() is reserved for media::kInfiniteDuration, and is
// handled differently.
buffer->set_duration(
init->hasDuration()
? base::Microseconds(std::min(
uint64_t{base::TimeDelta::FiniteMax().InMicroseconds()},
init->duration()))
: media::kNoTimestamp);
buffer->set_is_key_frame(init->type() == "key");
return MakeGarbageCollected<EncodedAudioChunk>(std::move(buffer));
}
EncodedAudioChunk::EncodedAudioChunk(scoped_refptr<media::DecoderBuffer> buffer)
: buffer_(std::move(buffer)) {}
String EncodedAudioChunk::type() const {
return buffer_->is_key_frame() ? "key" : "delta";
}
int64_t EncodedAudioChunk::timestamp() const {
return buffer_->timestamp().InMicroseconds();
}
absl::optional<uint64_t> EncodedAudioChunk::duration() const {
if (buffer_->duration() == media::kNoTimestamp)
return absl::nullopt;
return buffer_->duration().InMicroseconds();
}
uint64_t EncodedAudioChunk::byteLength() const {
return buffer_->data_size();
}
void EncodedAudioChunk::copyTo(const AllowSharedBufferSource* destination,
ExceptionState& exception_state) {
// Validate destination buffer.
auto dest_wrapper = AsSpan<uint8_t>(destination);
if (!dest_wrapper.data()) {
exception_state.ThrowTypeError("destination is detached.");
return;
}
if (dest_wrapper.size() < buffer_->data_size()) {
exception_state.ThrowTypeError("destination is not large enough.");
return;
}
// Copy data.
memcpy(dest_wrapper.data(), buffer_->data(), buffer_->data_size());
}
} // namespace blink