Import Cobalt 21.lts.1.283720
diff --git a/src/cobalt/CHANGELOG.md b/src/cobalt/CHANGELOG.md
index 04eb0a6..f2872b4 100644
--- a/src/cobalt/CHANGELOG.md
+++ b/src/cobalt/CHANGELOG.md
@@ -102,6 +102,23 @@
(https://lottiefiles.com/web-player). In order to support Lottie, Cobalt
updated its Skia port from m61 to m79.
+ - **Added support for MediaKeySystemMediaCapability.encryptionScheme.**
+
+ Cobalt now supports `MediaKeySystemMediaCapability.encryptionScheme` for
+ `Navigator.requestMediaKeySystemAccess()`. `encryptionScheme` can be 'cenc',
+ 'cbcs', or 'cbcs-1-9'.
+ The default implementation assumes that:
+ 1. When the Widevine DRM system is used, all the above encryption schemes
+ should be supported across all containers and codecs supported by the
+ platform.
+ 2. When the PlayReady DRM system is used, only 'cenc' is supported across all
+ containers and codecs supported by the platform.
+
+ It is possible to customize this behavior via an extension to
+ `SbMediaCanPlayMimeAndKeySystem()`. Please see the Starboard change log and
+ the comment of `SbMediaCanPlayMimeAndKeySystem()` in `media.h` for more
+ details.
+
## Version 20
- **Support for QUIC and SPDY is now enabled.**
diff --git a/src/cobalt/audio/async_audio_decoder.cc b/src/cobalt/audio/async_audio_decoder.cc
index 174cc57..c7885a1 100644
--- a/src/cobalt/audio/async_audio_decoder.cc
+++ b/src/cobalt/audio/async_audio_decoder.cc
@@ -38,7 +38,7 @@
decode_finish_callback.Run(reader->sample_rate(),
reader->ResetAndReturnAudioBus());
} else {
- decode_finish_callback.Run(0.f, std::unique_ptr<ShellAudioBus>());
+ decode_finish_callback.Run(0.f, std::unique_ptr<AudioBus>());
}
}
diff --git a/src/cobalt/audio/async_audio_decoder.h b/src/cobalt/audio/async_audio_decoder.h
index ced6fed..db8a15a 100644
--- a/src/cobalt/audio/async_audio_decoder.h
+++ b/src/cobalt/audio/async_audio_decoder.h
@@ -28,7 +28,7 @@
class AsyncAudioDecoder {
public:
typedef base::Callback<void(float sample_rate,
- std::unique_ptr<ShellAudioBus> audio_bus)>
+ std::unique_ptr<AudioBus> audio_bus)>
DecodeFinishCallback;
AsyncAudioDecoder();
diff --git a/src/cobalt/audio/audio_buffer.cc b/src/cobalt/audio/audio_buffer.cc
index 1b6ff38..0a4c203 100644
--- a/src/cobalt/audio/audio_buffer.cc
+++ b/src/cobalt/audio/audio_buffer.cc
@@ -25,8 +25,7 @@
namespace cobalt {
namespace audio {
-AudioBuffer::AudioBuffer(float sample_rate,
- std::unique_ptr<ShellAudioBus> audio_bus)
+AudioBuffer::AudioBuffer(float sample_rate, std::unique_ptr<AudioBus> audio_bus)
: sample_rate_(sample_rate), audio_bus_(std::move(audio_bus)) {
DCHECK_GT(sample_rate_, 0);
DCHECK_GT(length(), 0);
diff --git a/src/cobalt/audio/audio_buffer.h b/src/cobalt/audio/audio_buffer.h
index 9028a2b..d20beed 100644
--- a/src/cobalt/audio/audio_buffer.h
+++ b/src/cobalt/audio/audio_buffer.h
@@ -39,7 +39,7 @@
// https://www.w3.org/TR/webaudio/#AudioBuffer
class AudioBuffer : public script::Wrappable {
public:
- AudioBuffer(float sample_rate, std::unique_ptr<ShellAudioBus> audio_bus);
+ AudioBuffer(float sample_rate, std::unique_ptr<AudioBus> audio_bus);
// Web API: AudioBuffer
//
@@ -60,14 +60,14 @@
// Custom, not in any spec
//
- ShellAudioBus* audio_bus() { return audio_bus_.get(); }
+ AudioBus* audio_bus() { return audio_bus_.get(); }
DEFINE_WRAPPABLE_TYPE(AudioBuffer);
private:
const float sample_rate_;
- std::unique_ptr<ShellAudioBus> audio_bus_;
+ std::unique_ptr<AudioBus> audio_bus_;
DISALLOW_COPY_AND_ASSIGN(AudioBuffer);
};
diff --git a/src/cobalt/audio/audio_buffer_source_node.cc b/src/cobalt/audio/audio_buffer_source_node.cc
index 654e6a8..df8ca6b 100644
--- a/src/cobalt/audio/audio_buffer_source_node.cc
+++ b/src/cobalt/audio/audio_buffer_source_node.cc
@@ -27,7 +27,7 @@
namespace audio {
typedef media::InterleavedSincResampler InterleavedSincResampler;
-typedef media::ShellAudioBus ShellAudioBus;
+typedef media::AudioBus AudioBus;
// numberOfInputs : 0
// numberOfOutputs : 1
@@ -115,7 +115,7 @@
state_ = kStopped;
}
-std::unique_ptr<ShellAudioBus> AudioBufferSourceNode::PassAudioBusFromSource(
+std::unique_ptr<AudioBus> AudioBufferSourceNode::PassAudioBusFromSource(
int32 number_of_frames, SampleType sample_type, bool* finished) {
DCHECK_GT(number_of_frames, 0);
DCHECK(finished);
@@ -126,7 +126,7 @@
*finished = false;
if (state_ == kNone || !buffer_) {
- return std::unique_ptr<ShellAudioBus>();
+ return std::unique_ptr<AudioBus>();
}
if (state_ == kStopped ||
@@ -140,7 +140,7 @@
base::Unretained(this)));
buffer_source_added_ = false;
}
- return std::unique_ptr<ShellAudioBus>();
+ return std::unique_ptr<AudioBus>();
}
DCHECK_EQ(state_, kStarted);
@@ -151,22 +151,22 @@
int32 frames_to_end = buffer_->length() - read_index_;
int32 channel_count = static_cast<int32>(audio_bus->channels());
- std::unique_ptr<ShellAudioBus> result;
+ std::unique_ptr<AudioBus> result;
if (!interleaved_resampler_) {
int32 audio_bus_frames = std::min(number_of_frames, frames_to_end);
if (sample_type == kSampleTypeInt16) {
- result.reset(new ShellAudioBus(
- channel_count, audio_bus_frames,
- reinterpret_cast<int16*>(audio_bus->interleaved_data()) +
- read_index_ * channel_count));
+ result.reset(
+ new AudioBus(channel_count, audio_bus_frames,
+ reinterpret_cast<int16*>(audio_bus->interleaved_data()) +
+ read_index_ * channel_count));
} else {
DCHECK_EQ(sample_type, kSampleTypeFloat32);
- result.reset(new ShellAudioBus(
- channel_count, audio_bus_frames,
- reinterpret_cast<float*>(audio_bus->interleaved_data()) +
- read_index_ * channel_count));
+ result.reset(
+ new AudioBus(channel_count, audio_bus_frames,
+ reinterpret_cast<float*>(audio_bus->interleaved_data()) +
+ read_index_ * channel_count));
}
read_index_ += audio_bus_frames;
return result;
@@ -219,8 +219,8 @@
interleaved_resampler_->Resample(interleaved_output.get(),
number_of_frames);
- result.reset(new ShellAudioBus(channel_count, number_of_frames,
- kSampleTypeInt16, kStorageTypeInterleaved));
+ result.reset(new AudioBus(channel_count, number_of_frames, kSampleTypeInt16,
+ kStorageTypeInterleaved));
for (int32 i = 0; i < channel_count * number_of_frames; ++i) {
uint8* dest_ptr = result->interleaved_data() + sizeof(int16) * i;
*reinterpret_cast<int16*>(dest_ptr) =
@@ -229,9 +229,8 @@
} else {
DCHECK_EQ(sample_type, kSampleTypeFloat32);
- result.reset(new ShellAudioBus(channel_count, number_of_frames,
- kSampleTypeFloat32,
- kStorageTypeInterleaved));
+ result.reset(new AudioBus(channel_count, number_of_frames,
+ kSampleTypeFloat32, kStorageTypeInterleaved));
interleaved_resampler_->Resample(
reinterpret_cast<float*>(result->interleaved_data()), number_of_frames);
}
diff --git a/src/cobalt/audio/audio_buffer_source_node.h b/src/cobalt/audio/audio_buffer_source_node.h
index 1731aef..b01f54c 100644
--- a/src/cobalt/audio/audio_buffer_source_node.h
+++ b/src/cobalt/audio/audio_buffer_source_node.h
@@ -22,8 +22,8 @@
#include "cobalt/audio/audio_buffer.h"
#include "cobalt/audio/audio_node.h"
#include "cobalt/base/tokens.h"
+#include "cobalt/media/base/audio_bus.h"
#include "cobalt/media/base/interleaved_sinc_resampler.h"
-#include "cobalt/media/base/shell_audio_bus.h"
#include "cobalt/script/environment_settings.h"
namespace cobalt {
@@ -35,7 +35,7 @@
// https://www.w3.org/TR/webaudio/#AudioBufferSourceNode
class AudioBufferSourceNode : public AudioNode {
typedef media::InterleavedSincResampler InterleavedSincResampler;
- typedef media::ShellAudioBus ShellAudioBus;
+ typedef media::AudioBus AudioBus;
public:
AudioBufferSourceNode(script::EnvironmentSettings* settings,
@@ -75,8 +75,9 @@
SetAttributeEventListener(base::Tokens::ended(), event_listener);
}
- std::unique_ptr<ShellAudioBus> PassAudioBusFromSource(
- int32 number_of_frames, SampleType sample_type, bool* finished) override;
+ std::unique_ptr<AudioBus> PassAudioBusFromSource(int32 number_of_frames,
+ SampleType sample_type,
+ bool* finished) override;
DEFINE_WRAPPABLE_TYPE(AudioBufferSourceNode);
void TraceMembers(script::Tracer* tracer) override;
diff --git a/src/cobalt/audio/audio_context.cc b/src/cobalt/audio/audio_context.cc
index e909b72..6c4808e 100644
--- a/src/cobalt/audio/audio_context.cc
+++ b/src/cobalt/audio/audio_context.cc
@@ -64,7 +64,7 @@
DCHECK(main_message_loop_->BelongsToCurrentThread());
return scoped_refptr<AudioBuffer>(new AudioBuffer(
- sample_rate, std::unique_ptr<ShellAudioBus>(new ShellAudioBus(
+ sample_rate, std::unique_ptr<AudioBus>(new AudioBus(
num_of_channels, length, GetPreferredOutputSampleType(),
kStorageTypeInterleaved))));
}
@@ -151,7 +151,7 @@
// Success callback and error callback should be scheduled to run on the main
// thread's event loop.
void AudioContext::DecodeFinish(int callback_id, float sample_rate,
- std::unique_ptr<ShellAudioBus> audio_bus) {
+ std::unique_ptr<AudioBus> audio_bus) {
if (!main_message_loop_->BelongsToCurrentThread()) {
main_message_loop_->PostTask(
FROM_HERE,
diff --git a/src/cobalt/audio/audio_context.h b/src/cobalt/audio/audio_context.h
index a4667bf..536b2bd 100644
--- a/src/cobalt/audio/audio_context.h
+++ b/src/cobalt/audio/audio_context.h
@@ -190,7 +190,7 @@
void DecodeAudioDataInternal(std::unique_ptr<DecodeCallbackInfo> info);
void DecodeFinish(int callback_id, float sample_rate,
- std::unique_ptr<ShellAudioBus> audio_bus);
+ std::unique_ptr<AudioBus> audio_bus);
script::GlobalEnvironment* global_environment_;
diff --git a/src/cobalt/audio/audio_destination_node.cc b/src/cobalt/audio/audio_destination_node.cc
index 4107070..e35f1f9 100644
--- a/src/cobalt/audio/audio_destination_node.cc
+++ b/src/cobalt/audio/audio_destination_node.cc
@@ -64,8 +64,7 @@
audio_device_to_delete_ = NULL;
}
-void AudioDestinationNode::FillAudioBus(bool all_consumed,
- ShellAudioBus* audio_bus,
+void AudioDestinationNode::FillAudioBus(bool all_consumed, AudioBus* audio_bus,
bool* silence) {
// This is called on Audio thread.
AudioLock::AutoLock lock(audio_lock());
diff --git a/src/cobalt/audio/audio_destination_node.h b/src/cobalt/audio/audio_destination_node.h
index 8744034..b758d92 100644
--- a/src/cobalt/audio/audio_destination_node.h
+++ b/src/cobalt/audio/audio_destination_node.h
@@ -22,7 +22,7 @@
#include "cobalt/audio/audio_device.h"
#include "cobalt/audio/audio_helpers.h"
#include "cobalt/audio/audio_node.h"
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
#include "cobalt/script/environment_settings.h"
namespace cobalt {
@@ -37,7 +37,7 @@
// https://www.w3.org/TR/webaudio/#AudioDestinationNode
class AudioDestinationNode : public AudioNode,
public AudioDevice::RenderCallback {
- typedef media::ShellAudioBus ShellAudioBus;
+ typedef media::AudioBus AudioBus;
public:
AudioDestinationNode(script::EnvironmentSettings* settings,
@@ -51,14 +51,15 @@
// From AudioNode.
void OnInputNodeConnected() override;
- std::unique_ptr<ShellAudioBus> PassAudioBusFromSource(
- int32 number_of_frames, SampleType sample_type, bool* finished) override {
+ std::unique_ptr<AudioBus> PassAudioBusFromSource(int32 number_of_frames,
+ SampleType sample_type,
+ bool* finished) override {
NOTREACHED();
- return std::unique_ptr<ShellAudioBus>();
+ return std::unique_ptr<AudioBus>();
}
// From AudioDevice::RenderCallback.
- void FillAudioBus(bool all_consumed, ShellAudioBus* audio_bus,
+ void FillAudioBus(bool all_consumed, AudioBus* audio_bus,
bool* silence) override;
DEFINE_WRAPPABLE_TYPE(AudioDestinationNode);
diff --git a/src/cobalt/audio/audio_device.cc b/src/cobalt/audio/audio_device.cc
index d253f51..b177d07 100644
--- a/src/cobalt/audio/audio_device.cc
+++ b/src/cobalt/audio/audio_device.cc
@@ -27,7 +27,7 @@
namespace cobalt {
namespace audio {
-typedef media::ShellAudioBus ShellAudioBus;
+typedef media::AudioBus AudioBus;
namespace {
const int kRenderBufferSizeFrames = 1024;
@@ -69,7 +69,7 @@
// The |render_callback_| returns audio data in planar form. So we read it
// into |input_audio_bus_| and convert it into interleaved form and store in
// |output_frame_buffer_|.
- ShellAudioBus input_audio_bus_;
+ AudioBus input_audio_bus_;
std::unique_ptr<uint8[]> output_frame_buffer_;
@@ -102,7 +102,7 @@
#endif // SB_API_VERSION >= 11
input_audio_bus_(static_cast<size_t>(number_of_channels),
static_cast<size_t>(kRenderBufferSizeFrames),
- GetPreferredOutputSampleType(), ShellAudioBus::kPlanar),
+ GetPreferredOutputSampleType(), AudioBus::kPlanar),
output_frame_buffer_(
new uint8[frames_per_channel_ * number_of_channels_ *
GetStarboardSampleTypeSize(output_sample_type_)]) {
@@ -226,8 +226,8 @@
for (size_t channel = 0; channel < input_audio_bus_.channels(); ++channel) {
*output_buffer = ConvertSample<InputType, OutputType>(
input_audio_bus_
- .GetSampleForType<InputType, media::ShellAudioBus::kPlanar>(
- channel, frame));
+ .GetSampleForType<InputType, media::AudioBus::kPlanar>(channel,
+ frame));
++output_buffer;
}
}
@@ -237,7 +237,7 @@
TRACE_EVENT0("cobalt::audio", "AudioDevice::Impl::FillOutputAudioBus()");
const bool is_input_int16 =
- input_audio_bus_.sample_type() == media::ShellAudioBus::kInt16;
+ input_audio_bus_.sample_type() == media::AudioBus::kInt16;
const bool is_output_int16 =
output_sample_type_ == kSbMediaAudioSampleTypeInt16Deprecated;
diff --git a/src/cobalt/audio/audio_device.h b/src/cobalt/audio/audio_device.h
index b7974a7..1ccc7f9 100644
--- a/src/cobalt/audio/audio_device.h
+++ b/src/cobalt/audio/audio_device.h
@@ -19,7 +19,7 @@
#include <vector>
#include "base/basictypes.h"
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
namespace cobalt {
namespace audio {
@@ -28,7 +28,7 @@
public:
class RenderCallback {
public:
- typedef media::ShellAudioBus ShellAudioBus;
+ typedef media::AudioBus AudioBus;
// |all_consumed| will be set to true if all audio frames has been consumed.
// This gives the AudioDestinationNode a chance to decide if the AudioDevice
@@ -38,7 +38,7 @@
// |silence| will be set to true before calling if |audio_buffer| contains
// only silence samples, it will be set to |false| otherwise. It will be
// set to false on return if |audio_buffer| has been modified.
- virtual void FillAudioBus(bool all_consumed, ShellAudioBus* audio_buffer,
+ virtual void FillAudioBus(bool all_consumed, AudioBus* audio_buffer,
bool* silence) = 0;
protected:
diff --git a/src/cobalt/audio/audio_file_reader.h b/src/cobalt/audio/audio_file_reader.h
index f53eae4..6a20209 100644
--- a/src/cobalt/audio/audio_file_reader.h
+++ b/src/cobalt/audio/audio_file_reader.h
@@ -35,7 +35,7 @@
virtual int32 number_of_channels() const = 0;
virtual SampleType sample_type() const = 0;
- virtual std::unique_ptr<ShellAudioBus> ResetAndReturnAudioBus() = 0;
+ virtual std::unique_ptr<AudioBus> ResetAndReturnAudioBus() = 0;
};
} // namespace audio
diff --git a/src/cobalt/audio/audio_file_reader_wav.cc b/src/cobalt/audio/audio_file_reader_wav.cc
index 94c0bf9..f92b8bd 100644
--- a/src/cobalt/audio/audio_file_reader_wav.cc
+++ b/src/cobalt/audio/audio_file_reader_wav.cc
@@ -192,9 +192,8 @@
static_cast<int32>(size / (bytes_per_src_sample * number_of_channels_));
// We store audio samples in the current platform's preferred format.
- audio_bus_.reset(new ShellAudioBus(number_of_channels_, number_of_frames_,
- sample_type_,
- ShellAudioBus::kInterleaved));
+ audio_bus_.reset(new AudioBus(number_of_channels_, number_of_frames_,
+ sample_type_, AudioBus::kInterleaved));
// Both the source data and the destination data are stored in interleaved.
#if SB_IS(LITTLE_ENDIAN)
diff --git a/src/cobalt/audio/audio_file_reader_wav.h b/src/cobalt/audio/audio_file_reader_wav.h
index 460f268..bf3b95a 100644
--- a/src/cobalt/audio/audio_file_reader_wav.h
+++ b/src/cobalt/audio/audio_file_reader_wav.h
@@ -36,7 +36,7 @@
int32 number_of_channels() const override { return number_of_channels_; }
SampleType sample_type() const override { return sample_type_; }
- std::unique_ptr<ShellAudioBus> ResetAndReturnAudioBus() override {
+ std::unique_ptr<AudioBus> ResetAndReturnAudioBus() override {
return std::move(audio_bus_);
}
@@ -52,7 +52,7 @@
bool is_valid() { return audio_bus_ != NULL; }
- std::unique_ptr<ShellAudioBus> audio_bus_;
+ std::unique_ptr<AudioBus> audio_bus_;
float sample_rate_;
int32 number_of_frames_;
int32 number_of_channels_;
diff --git a/src/cobalt/audio/audio_helpers.h b/src/cobalt/audio/audio_helpers.h
index b4dd6f9..dc98086 100644
--- a/src/cobalt/audio/audio_helpers.h
+++ b/src/cobalt/audio/audio_helpers.h
@@ -15,7 +15,7 @@
#ifndef COBALT_AUDIO_AUDIO_HELPERS_H_
#define COBALT_AUDIO_AUDIO_HELPERS_H_
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
#if defined(OS_STARBOARD)
#include "starboard/audio_sink.h"
@@ -25,13 +25,13 @@
namespace cobalt {
namespace audio {
-typedef media::ShellAudioBus ShellAudioBus;
-typedef media::ShellAudioBus::SampleType SampleType;
-typedef media::ShellAudioBus::StorageType StorageType;
-const SampleType kSampleTypeInt16 = media::ShellAudioBus::kInt16;
-const SampleType kSampleTypeFloat32 = media::ShellAudioBus::kFloat32;
-const StorageType kStorageTypeInterleaved = media::ShellAudioBus::kInterleaved;
-const StorageType kStorageTypePlanar = media::ShellAudioBus::kPlanar;
+typedef media::AudioBus AudioBus;
+typedef media::AudioBus::SampleType SampleType;
+typedef media::AudioBus::StorageType StorageType;
+const SampleType kSampleTypeInt16 = media::AudioBus::kInt16;
+const SampleType kSampleTypeFloat32 = media::AudioBus::kFloat32;
+const StorageType kStorageTypeInterleaved = media::AudioBus::kInterleaved;
+const StorageType kStorageTypePlanar = media::AudioBus::kPlanar;
const float kMaxInt16AsFloat32 = 32767.0f;
@@ -52,7 +52,7 @@
#endif
// Get the size in bytes of an internal sample type, which is an alias for
-// media::ShellAudioBus::SampleType.
+// media::AudioBus::SampleType.
inline size_t GetSampleTypeSize(SampleType sample_type) {
switch (sample_type) {
case kSampleTypeInt16:
diff --git a/src/cobalt/audio/audio_node.h b/src/cobalt/audio/audio_node.h
index 1e9c1dd..925356c 100644
--- a/src/cobalt/audio/audio_node.h
+++ b/src/cobalt/audio/audio_node.h
@@ -27,7 +27,7 @@
#include "cobalt/audio/audio_node_output.h"
#include "cobalt/dom/dom_exception.h"
#include "cobalt/dom/event_target.h"
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
#include "cobalt/script/environment_settings.h"
namespace cobalt {
@@ -49,7 +49,7 @@
// (if it has any).
// https://www.w3.org/TR/webaudio/#AudioNode-section
class AudioNode : public dom::EventTarget {
- typedef media::ShellAudioBus ShellAudioBus;
+ typedef media::AudioBus AudioBus;
public:
AudioNode(script::EnvironmentSettings* settings, AudioContext* context);
@@ -108,7 +108,7 @@
// Called when a new input node has been connected.
virtual void OnInputNodeConnected() {}
- virtual std::unique_ptr<ShellAudioBus> PassAudioBusFromSource(
+ virtual std::unique_ptr<AudioBus> PassAudioBusFromSource(
int32 number_of_frames, SampleType sample_type, bool* finished) = 0;
AudioLock* audio_lock() const { return audio_lock_.get(); }
diff --git a/src/cobalt/audio/audio_node_input.cc b/src/cobalt/audio/audio_node_input.cc
index f8f5503..977d67e 100644
--- a/src/cobalt/audio/audio_node_input.cc
+++ b/src/cobalt/audio/audio_node_input.cc
@@ -26,12 +26,12 @@
namespace {
-typedef media::ShellAudioBus ShellAudioBus;
+typedef media::AudioBus AudioBus;
void MixAudioBufferBasedOnInterpretation(
const float* speaker, const float* discrete,
- const AudioNodeChannelInterpretation& interpretation, ShellAudioBus* source,
- ShellAudioBus* output_audio_data) {
+ const AudioNodeChannelInterpretation& interpretation, AudioBus* source,
+ AudioBus* output_audio_data) {
const float* kMatrix =
interpretation == kAudioNodeChannelInterpretationSpeakers ? speaker
: discrete;
@@ -49,7 +49,7 @@
// Up down mix equations for mono, stereo, quad, 5.1:
// https://www.w3.org/TR/webaudio/#ChannelLayouts
void MixAudioBuffer(const AudioNodeChannelInterpretation& interpretation,
- ShellAudioBus* source, ShellAudioBus* output_audio_data) {
+ AudioBus* source, AudioBus* output_audio_data) {
DCHECK_GT(source->channels(), 0u);
DCHECK_GT(output_audio_data->channels(), 0u);
DCHECK(interpretation == kAudioNodeChannelInterpretationSpeakers ||
@@ -224,8 +224,8 @@
}
}
-void AudioNodeInput::FillAudioBus(ShellAudioBus* output_audio_bus,
- bool* silence, bool* all_finished) {
+void AudioNodeInput::FillAudioBus(AudioBus* output_audio_bus, bool* silence,
+ bool* all_finished) {
DCHECK(silence);
DCHECK(all_finished);
@@ -247,7 +247,7 @@
for (std::set<AudioNodeOutput*>::iterator iter = outputs_.begin();
iter != outputs_.end(); ++iter) {
bool finished = false;
- std::unique_ptr<ShellAudioBus> audio_bus = (*iter)->PassAudioBusFromSource(
+ std::unique_ptr<AudioBus> audio_bus = (*iter)->PassAudioBusFromSource(
static_cast<int32>(output_audio_bus->frames()),
output_audio_bus->sample_type(), &finished);
*all_finished &= finished;
diff --git a/src/cobalt/audio/audio_node_input.h b/src/cobalt/audio/audio_node_input.h
index 74aca8b..1c5bee1 100644
--- a/src/cobalt/audio/audio_node_input.h
+++ b/src/cobalt/audio/audio_node_input.h
@@ -20,7 +20,7 @@
#include "base/memory/ref_counted.h"
#include "cobalt/audio/audio_buffer.h"
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
namespace cobalt {
namespace audio {
@@ -36,7 +36,7 @@
// number can change depending on the connection(s) made to the input. If the
// input has no connections, then it has one channel which is silent.
class AudioNodeInput : public base::RefCountedThreadSafe<AudioNodeInput> {
- typedef media::ShellAudioBus ShellAudioBus;
+ typedef media::AudioBus AudioBus;
public:
explicit AudioNodeInput(AudioNode* owner_node) : owner_node_(owner_node) {}
@@ -50,8 +50,7 @@
// For each input, an AudioNode performs a mixing of all connections to that
// input. FillAudioBus() performs that action. In the case of multiple
// connections, it sums the result into |audio_bus|.
- void FillAudioBus(ShellAudioBus* audio_bus, bool* silence,
- bool* all_finished);
+ void FillAudioBus(AudioBus* audio_bus, bool* silence, bool* all_finished);
private:
AudioNode* const owner_node_;
diff --git a/src/cobalt/audio/audio_node_input_output_test.cc b/src/cobalt/audio/audio_node_input_output_test.cc
index 970254a..41a2ca2 100644
--- a/src/cobalt/audio/audio_node_input_output_test.cc
+++ b/src/cobalt/audio/audio_node_input_output_test.cc
@@ -27,18 +27,18 @@
#include "cobalt/script/typed_arrays.h"
#include "testing/gtest/include/gtest/gtest.h"
-// TODO: Consolidate ShellAudioBus creation code
+// TODO: Consolidate AudioBus creation code
namespace cobalt {
namespace audio {
-typedef media::ShellAudioBus ShellAudioBus;
+typedef media::AudioBus AudioBus;
constexpr int kRenderBufferSizeFrames = 32;
class AudioDestinationNodeMock : public AudioNode,
public AudioDevice::RenderCallback {
- typedef media::ShellAudioBus ShellAudioBus;
+ typedef media::AudioBus AudioBus;
public:
AudioDestinationNodeMock(script::EnvironmentSettings* settings,
@@ -50,14 +50,15 @@
}
// From AudioNode.
- std::unique_ptr<ShellAudioBus> PassAudioBusFromSource(
- int32 number_of_frames, SampleType sample_type, bool* finished) override {
+ std::unique_ptr<AudioBus> PassAudioBusFromSource(int32 number_of_frames,
+ SampleType sample_type,
+ bool* finished) override {
NOTREACHED();
- return std::unique_ptr<ShellAudioBus>();
+ return std::unique_ptr<AudioBus>();
}
// From AudioDevice::RenderCallback.
- void FillAudioBus(bool all_consumed, ShellAudioBus* audio_bus,
+ void FillAudioBus(bool all_consumed, AudioBus* audio_bus,
bool* silence) override {
AudioLock::AutoLock lock(audio_lock());
@@ -68,9 +69,9 @@
};
void FillAudioBusFromOneSource(
- std::unique_ptr<ShellAudioBus> src_data,
- const AudioNodeChannelInterpretation& interpretation,
- ShellAudioBus* audio_bus, bool* silence) {
+ std::unique_ptr<AudioBus> src_data,
+ const AudioNodeChannelInterpretation& interpretation, AudioBus* audio_bus,
+ bool* silence) {
dom::testing::StubEnvironmentSettings environment_settings;
scoped_refptr<AudioContext> audio_context(
@@ -139,11 +140,11 @@
}
}
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
FillAudioBusFromOneSource(std::move(src_data), kInterpretation,
@@ -180,12 +181,12 @@
}
}
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
FillAudioBusFromOneSource(std::move(src_data), kInterpretation,
@@ -219,12 +220,12 @@
src_data_in_float[i] = 50.0f;
}
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
FillAudioBusFromOneSource(std::move(src_data), kInterpretation,
@@ -254,12 +255,12 @@
src_data_in_float[i] = 50.0f;
}
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
FillAudioBusFromOneSource(std::move(src_data), kInterpretation,
@@ -292,12 +293,12 @@
}
}
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
FillAudioBusFromOneSource(std::move(src_data), kInterpretation,
@@ -334,12 +335,12 @@
}
}
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
FillAudioBusFromOneSource(std::move(src_data), kInterpretation,
@@ -376,12 +377,12 @@
}
}
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
FillAudioBusFromOneSource(std::move(src_data), kInterpretation,
@@ -418,12 +419,12 @@
}
}
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
FillAudioBusFromOneSource(std::move(src_data), kInterpretation,
@@ -460,12 +461,12 @@
}
}
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
FillAudioBusFromOneSource(std::move(src_data), kInterpretation,
@@ -498,12 +499,12 @@
}
}
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
FillAudioBusFromOneSource(std::move(src_data), kInterpretation,
@@ -536,12 +537,12 @@
}
}
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
FillAudioBusFromOneSource(std::move(src_data), kInterpretation,
@@ -574,12 +575,12 @@
}
}
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
FillAudioBusFromOneSource(std::move(src_data), kInterpretation,
@@ -612,12 +613,12 @@
}
}
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
FillAudioBusFromOneSource(std::move(src_data), kInterpretation,
@@ -650,12 +651,12 @@
}
}
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames, src_data_in_float));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
FillAudioBusFromOneSource(std::move(src_data), kInterpretation,
@@ -691,8 +692,8 @@
}
}
- std::unique_ptr<ShellAudioBus> src_data_1(new ShellAudioBus(
- kNumOfSrcChannels, kNumOfFrames_1, src_data_in_float_1));
+ std::unique_ptr<AudioBus> src_data_1(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames_1, src_data_in_float_1));
scoped_refptr<AudioBufferSourceNode> source_1(
audio_context->CreateBufferSource(environment_settings()));
scoped_refptr<AudioBuffer> buffer_1(
@@ -709,8 +710,8 @@
}
}
- std::unique_ptr<ShellAudioBus> src_data_2(new ShellAudioBus(
- kNumOfSrcChannels, kNumOfFrames_2, src_data_in_float_2));
+ std::unique_ptr<AudioBus> src_data_2(
+ new AudioBus(kNumOfSrcChannels, kNumOfFrames_2, src_data_in_float_2));
scoped_refptr<AudioBufferSourceNode> source_2(
audio_context->CreateBufferSource(environment_settings()));
scoped_refptr<AudioBuffer> buffer_2(
@@ -726,9 +727,9 @@
source_1->Start(0, 0, NULL);
source_2->Start(0, 0, NULL);
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kPlanar));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kRenderBufferSizeFrames,
+ AudioBus::kFloat32, AudioBus::kPlanar));
audio_bus->ZeroAllFrames();
bool silence = true;
destination->FillAudioBus(true, audio_bus.get(), &silence);
@@ -788,9 +789,9 @@
scoped_refptr<AudioContext> audio_context(
new AudioContext(environment_settings()));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kPlanar));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfChannels, kRenderBufferSizeFrames, AudioBus::kFloat32,
+ AudioBus::kPlanar));
audio_bus->ZeroAllFrames();
scoped_refptr<AudioBuffer> buffer(
new AudioBuffer(audio_context->sample_rate(), std::move(audio_bus)));
@@ -828,9 +829,9 @@
scoped_refptr<AudioContext> audio_context(
new AudioContext(environment_settings()));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kFloat32, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfChannels, kRenderBufferSizeFrames, AudioBus::kFloat32,
+ AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
scoped_refptr<AudioBuffer> buffer(
new AudioBuffer(audio_context->sample_rate(), std::move(audio_bus)));
@@ -868,9 +869,9 @@
scoped_refptr<AudioContext> audio_context(
new AudioContext(environment_settings()));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kInt16, ShellAudioBus::kPlanar));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfChannels, kRenderBufferSizeFrames, AudioBus::kInt16,
+ AudioBus::kPlanar));
audio_bus->ZeroAllFrames();
scoped_refptr<AudioBuffer> buffer(
@@ -911,9 +912,9 @@
scoped_refptr<AudioContext> audio_context(
new AudioContext(environment_settings()));
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfChannels, kRenderBufferSizeFrames,
- ShellAudioBus::kInt16, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfChannels, kRenderBufferSizeFrames, AudioBus::kInt16,
+ AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
scoped_refptr<AudioBuffer> buffer(
@@ -966,9 +967,9 @@
for (size_t buffer_sample_rate : kBufferSampleRateArr) {
for (SampleType sample_type : kSampleTypeArr) {
- std::unique_ptr<ShellAudioBus> src_data(
- new ShellAudioBus(kNumOfSrcChannels, kNumOfSrcFrames, sample_type,
- ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> src_data(
+ new AudioBus(kNumOfSrcChannels, kNumOfSrcFrames, sample_type,
+ AudioBus::kInterleaved));
src_data->ZeroAllFrames();
scoped_refptr<AudioBuffer> buffer(
new AudioBuffer(buffer_sample_rate, std::move(src_data)));
@@ -988,9 +989,9 @@
source->Connect(destination, 0, 0, NULL);
source->Start(0, 0, NULL);
- std::unique_ptr<ShellAudioBus> audio_bus(
- new ShellAudioBus(kNumOfDestChannels, kNumOfDestFrames, sample_type,
- ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> audio_bus(
+ new AudioBus(kNumOfDestChannels, kNumOfDestFrames, sample_type,
+ AudioBus::kInterleaved));
audio_bus->ZeroAllFrames();
bool silence = true;
destination->FillAudioBus(true, audio_bus.get(), &silence);
diff --git a/src/cobalt/audio/audio_node_output.cc b/src/cobalt/audio/audio_node_output.cc
index 8ab0f43..ed6c507 100644
--- a/src/cobalt/audio/audio_node_output.cc
+++ b/src/cobalt/audio/audio_node_output.cc
@@ -24,7 +24,7 @@
namespace cobalt {
namespace audio {
-typedef media::ShellAudioBus ShellAudioBus;
+typedef media::AudioBus AudioBus;
AudioNodeOutput::~AudioNodeOutput() {
owner_node_->audio_lock()->AssertLocked();
@@ -57,7 +57,7 @@
}
}
-std::unique_ptr<ShellAudioBus> AudioNodeOutput::PassAudioBusFromSource(
+std::unique_ptr<AudioBus> AudioNodeOutput::PassAudioBusFromSource(
int32 number_of_frames, SampleType sample_type, bool* finished) {
// This is called by Audio thread.
owner_node_->audio_lock()->AssertLocked();
diff --git a/src/cobalt/audio/audio_node_output.h b/src/cobalt/audio/audio_node_output.h
index 4122390..1774ce4 100644
--- a/src/cobalt/audio/audio_node_output.h
+++ b/src/cobalt/audio/audio_node_output.h
@@ -22,7 +22,7 @@
#include "base/memory/ref_counted.h"
#include "cobalt/audio/audio_buffer.h"
#include "cobalt/audio/audio_helpers.h"
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
namespace cobalt {
namespace audio {
@@ -33,7 +33,7 @@
// This represents the output coming out of the AudioNode.
// It may be connected to one or more AudioNodeInputs.
class AudioNodeOutput : public base::RefCountedThreadSafe<AudioNodeOutput> {
- typedef media::ShellAudioBus ShellAudioBus;
+ typedef media::AudioBus AudioBus;
public:
explicit AudioNodeOutput(AudioNode* owner_node) : owner_node_(owner_node) {}
@@ -44,9 +44,9 @@
void DisconnectAll();
- std::unique_ptr<ShellAudioBus> PassAudioBusFromSource(int32 number_of_frames,
- SampleType sample_type,
- bool* finished);
+ std::unique_ptr<AudioBus> PassAudioBusFromSource(int32 number_of_frames,
+ SampleType sample_type,
+ bool* finished);
private:
AudioNode* const owner_node_;
diff --git a/src/cobalt/base/path_provider.cc b/src/cobalt/base/path_provider.cc
index ae07949..6dfbbe7 100644
--- a/src/cobalt/base/path_provider.cc
+++ b/src/cobalt/base/path_provider.cc
@@ -31,6 +31,9 @@
base::FilePath directory(path.get());
if (base::PathExists(directory) || base::CreateDirectory(directory)) {
return directory;
+ } else {
+ DLOG(ERROR) << "Attempt to open or create this path failed: " +
+ directory.value();
}
}
return base::FilePath();
diff --git a/src/cobalt/black_box_tests/testdata/pointer_test.html b/src/cobalt/black_box_tests/testdata/pointer_test.html
index 1f1b275..340e5da 100644
--- a/src/cobalt/black_box_tests/testdata/pointer_test.html
+++ b/src/cobalt/black_box_tests/testdata/pointer_test.html
@@ -98,14 +98,10 @@
['pointerover', 'top', 'bubbling'],
['pointerover', 'outer', 'bubbling'],
['pointerenter', 'top_two', 'at target'],
- ['pointerenter', 'top', 'at target'],
- ['pointerenter', 'outer', 'at target'],
['mouseover', 'top_two', 'at target'],
['mouseover', 'top', 'bubbling'],
['mouseover', 'outer', 'bubbling'],
['mouseenter', 'top_two', 'at target'],
- ['mouseenter', 'top', 'at target'],
- ['mouseenter', 'outer', 'at target'],
// actions.move_to_element_with_offset(top_two, 10, 10).pause(_SLEEP_AFTER_MOVE_TIME)
['pointermove', 'top_two', 'at target'],
['pointermove', 'top', 'bubbling'],
@@ -139,14 +135,10 @@
['pointerover', 'top', 'bubbling'],
['pointerover', 'outer', 'bubbling'],
['pointerenter', 'top_one', 'at target'],
- ['pointerenter', 'top', 'at target'],
- ['pointerenter', 'outer', 'at target'],
['mouseover', 'top_one', 'at target'],
['mouseover', 'top', 'bubbling'],
['mouseover', 'outer', 'bubbling'],
['mouseenter', 'top_one', 'at target'],
- ['mouseenter', 'top', 'at target'],
- ['mouseenter', 'outer', 'at target'],
// actions.click(top_three)
['pointerout', 'top_one', 'at target'],
['pointerout', 'top', 'bubbling'],
@@ -166,14 +158,10 @@
['pointerover', 'top', 'bubbling'],
['pointerover', 'outer', 'bubbling'],
['pointerenter', 'top_three', 'at target'],
- ['pointerenter', 'top', 'at target'],
- ['pointerenter', 'outer', 'at target'],
['mouseover', 'top_three', 'at target'],
['mouseover', 'top', 'bubbling'],
['mouseover', 'outer', 'bubbling'],
['mouseenter', 'top_three', 'at target'],
- ['mouseenter', 'top', 'at target'],
- ['mouseenter', 'outer', 'at target'],
['pointerdown', 'top_three', 'at target'],
['pointerdown', 'top', 'bubbling'],
['pointerdown', 'outer', 'bubbling'],
@@ -208,14 +196,10 @@
['pointerover', 'top', 'bubbling'],
['pointerover', 'outer', 'bubbling'],
['pointerenter', 'top_four', 'at target'],
- ['pointerenter', 'top', 'at target'],
- ['pointerenter', 'outer', 'at target'],
['mouseover', 'top_four', 'at target'],
['mouseover', 'top', 'bubbling'],
['mouseover', 'outer', 'bubbling'],
['mouseenter', 'top_four', 'at target'],
- ['mouseenter', 'top', 'at target'],
- ['mouseenter', 'outer', 'at target'],
['pointerdown', 'top_four', 'at target'],
['pointerdown', 'top', 'bubbling'],
['pointerdown', 'outer', 'bubbling'],
@@ -257,14 +241,10 @@
['pointerover', 'top', 'bubbling'],
['pointerover', 'outer', 'bubbling'],
['pointerenter', 'top_six', 'at target'],
- ['pointerenter', 'top', 'at target'],
- ['pointerenter', 'outer', 'at target'],
['mouseover', 'top_six', 'at target'],
['mouseover', 'top', 'bubbling'],
['mouseover', 'outer', 'bubbling'],
['mouseenter', 'top_six', 'at target'],
- ['mouseenter', 'top', 'at target'],
- ['mouseenter', 'outer', 'at target'],
// actions.move_to_element(bottom_six).pause(_SLEEP_AFTER_MOVE_TIME)
['pointerout', 'top_six', 'at target'],
['pointerout', 'top', 'bubbling'],
@@ -287,13 +267,11 @@
['pointerover', 'outer', 'bubbling'],
['pointerenter', 'bottom_six', 'at target'],
['pointerenter', 'bottom', 'at target'],
- ['pointerenter', 'outer', 'at target'],
['mouseover', 'bottom_six', 'at target'],
['mouseover', 'bottom', 'bubbling'],
['mouseover', 'outer', 'bubbling'],
['mouseenter', 'bottom_six', 'at target'],
['mouseenter', 'bottom', 'at target'],
- ['mouseenter', 'outer', 'at target'],
// actions.click(bottom_five)
['pointerout', 'bottom_six', 'at target'],
['pointerout', 'bottom', 'bubbling'],
@@ -313,14 +291,10 @@
['pointerover', 'bottom', 'bubbling'],
['pointerover', 'outer', 'bubbling'],
['pointerenter', 'bottom_five', 'at target'],
- ['pointerenter', 'bottom', 'at target'],
- ['pointerenter', 'outer', 'at target'],
['mouseover', 'bottom_five', 'at target'],
['mouseover', 'bottom', 'bubbling'],
['mouseover', 'outer', 'bubbling'],
['mouseenter', 'bottom_five', 'at target'],
- ['mouseenter', 'bottom', 'at target'],
- ['mouseenter', 'outer', 'at target'],
['pointerdown', 'bottom_five', 'at target'],
['pointerdown', 'bottom', 'bubbling'],
['pointerdown', 'outer', 'bubbling'],
@@ -349,14 +323,10 @@
['pointerover', 'bottom', 'bubbling'],
['pointerover', 'outer', 'bubbling'],
['pointerenter', 'bottom_four', 'at target'],
- ['pointerenter', 'bottom', 'at target'],
- ['pointerenter', 'outer', 'at target'],
['mouseover', 'bottom_four', 'at target'],
['mouseover', 'bottom', 'bubbling'],
['mouseover', 'outer', 'bubbling'],
['mouseenter', 'bottom_four', 'at target'],
- ['mouseenter', 'bottom', 'at target'],
- ['mouseenter', 'outer', 'at target'],
['pointerdown', 'bottom_four', 'at target'],
['pointerdown', 'bottom', 'bubbling'],
['pointerdown', 'outer', 'bubbling'],
@@ -383,12 +353,8 @@
['mousemove', 'bottom_two', 'at target'],
['pointerover', 'bottom_two', 'at target'],
['pointerenter', 'bottom_two', 'at target'],
- ['pointerenter', 'bottom', 'at target'],
- ['pointerenter', 'outer', 'at target'],
['mouseover', 'bottom_two', 'at target'],
['mouseenter', 'bottom_two', 'at target'],
- ['mouseenter', 'bottom', 'at target'],
- ['mouseenter', 'outer', 'at target'],
// actions.move_to_element(bottom_one).pause(_SLEEP_AFTER_MOVE_TIME)
['pointerout', 'bottom_two', 'at target'],
['pointerleave', 'bottom_two', 'at target'],
@@ -398,12 +364,8 @@
['mousemove', 'bottom_one', 'at target'],
['pointerover', 'bottom_one', 'at target'],
['pointerenter', 'bottom_one', 'at target'],
- ['pointerenter', 'bottom', 'at target'],
- ['pointerenter', 'outer', 'at target'],
['mouseover', 'bottom_one', 'at target'],
['mouseenter', 'bottom_one', 'at target'],
- ['mouseenter', 'bottom', 'at target'],
- ['mouseenter', 'outer', 'at target'],
// find_element_by_id(runner, 'end').click()
['pointerout', 'bottom_one', 'at target'],
['pointerleave', 'bottom_one', 'at target'],
@@ -418,11 +380,9 @@
['pointerover', 'end', 'at target'],
['pointerover', 'outer', 'bubbling'],
['pointerenter', 'end', 'at target'],
- ['pointerenter', 'outer', 'at target'],
['mouseover', 'end', 'at target'],
['mouseover', 'outer', 'bubbling'],
['mouseenter', 'end', 'at target'],
- ['mouseenter', 'outer', 'at target'],
['pointerdown', 'end', 'at target'],
['pointerdown', 'outer', 'bubbling'],
['mousedown', 'end', 'at target'],
@@ -489,33 +449,72 @@
e.target.setPointerCapture(e.pointerId);
}
- function SetHandlers(event, classname, callback) {
- var elements = document.getElementsByClassName(classname);
+ // If the event type has value 'type', then report an error if the
+ // 'name' property on the event target already has 'value'. Otherwise,
+ // set it to the 'value'. This is used to detect erroneous boundary
+ // events (enter/leave, over/out), and up/down event sequences on an
+ // element.
+ function TrackAndVerifyTargetState(event, type, name, value) {
+ if (event.type == type) {
+ if (event.target[name] == value) {
+ console.log('ERROR: ' + type + 'event received while ' +
+ name + ' == ' + event.target[name]);
+ assertTrue(event.target[name] != value);
+ }
+ event.target[name] = value;
+ }
+ }
+
+ function CheckState(e) {
+ // Check the target element state when the event is 'at target'.
+ if (e.eventPhase == 2) {
+ // Verify that there is not a duplicated or missing event for enter,
+ // leave, over, out, up, or down.
+ TrackAndVerifyTargetState(e, 'mouseenter', 'mouseenter', true);
+ TrackAndVerifyTargetState(e, 'mouseleave', 'mouseenter', false);
+ TrackAndVerifyTargetState(e, 'mouseover', 'mouseover', true);
+ TrackAndVerifyTargetState(e, 'mouseout', 'mouseover', false);
+ TrackAndVerifyTargetState(e, 'mousedown', 'mousedown', true);
+ TrackAndVerifyTargetState(e, 'mouseup', 'mousedown', false);
+
+ TrackAndVerifyTargetState(e, 'pointerenter', 'pointerenter', true);
+ TrackAndVerifyTargetState(e, 'pointerleave', 'pointerenter', false);
+ TrackAndVerifyTargetState(e, 'pointerover', 'pointerover', true);
+ TrackAndVerifyTargetState(e, 'pointerout', 'pointerover', false);
+ TrackAndVerifyTargetState(e, 'pointerdown', 'pointerdown', true);
+ TrackAndVerifyTargetState(e, 'pointerup', 'pointerdown', false);
+ }
+ }
+
+ function SetHandlers(event, selector, callback) {
+ var elements = document.querySelectorAll(selector);
for (var i = 0; i < elements.length; ++i) {
elements[i].addEventListener(event, callback);
}
}
- function SetAllHandlers(prefix, classname, callback) {
- SetHandlers(prefix + 'enter', classname, callback);
- SetHandlers(prefix + 'leave', classname, callback);
- SetHandlers(prefix + 'over', classname, callback);
- SetHandlers(prefix + 'out', classname, callback);
- SetHandlers(prefix + 'down', classname, callback);
- SetHandlers(prefix + 'up', classname, callback);
- SetHandlers(prefix + 'move', classname, callback);
+ function SetAllHandlers(prefix, selector, callback) {
+ SetHandlers(prefix + 'enter', selector, callback);
+ SetHandlers(prefix + 'leave', selector, callback);
+ SetHandlers(prefix + 'over', selector, callback);
+ SetHandlers(prefix + 'out', selector, callback);
+ SetHandlers(prefix + 'down', selector, callback);
+ SetHandlers(prefix + 'up', selector, callback);
+ SetHandlers(prefix + 'move', selector, callback);
}
window.onload = function() {
- SetAllHandlers('mouse', 'track', LogEvent);
- SetAllHandlers('pointer', 'track', LogEvent);
- SetHandlers('click', 'track', LogEvent);
- SetAllHandlers('mouse', 'cancel', Cancel);
- SetAllHandlers('pointer', 'cancel', Cancel);
- SetAllHandlers('mouse', 'stop', Stop);
- SetAllHandlers('pointer', 'stop', Stop);
- SetHandlers('pointerdown', 'capture', Capture);
- SetHandlers('click', 'end', EndTest);
+ SetAllHandlers('mouse', '.track', LogEvent);
+ SetAllHandlers('pointer', '.track', LogEvent);
+ SetHandlers('click', '.track', LogEvent);
+ SetAllHandlers('mouse', '.cancel', Cancel);
+ SetAllHandlers('pointer', '.cancel', Cancel);
+ SetAllHandlers('mouse', '.stop', Stop);
+ SetAllHandlers('pointer', '.stop', Stop);
+ SetHandlers('pointerdown', '.capture', Capture);
+ SetHandlers('click', '.end', EndTest);
+ SetAllHandlers('mouse', '*', CheckState);
+ SetAllHandlers('pointer', '*', CheckState);
console.log("Setup finished");
setupFinished();
}
diff --git a/src/cobalt/black_box_tests/tests/pointer_test.py b/src/cobalt/black_box_tests/tests/pointer_test.py
index 706bbc5..02e9a00 100644
--- a/src/cobalt/black_box_tests/tests/pointer_test.py
+++ b/src/cobalt/black_box_tests/tests/pointer_test.py
@@ -44,8 +44,7 @@
class PointerTest(black_box_tests.BlackBoxTestCase):
"""Tests pointer and mouse event."""
- def test_simple(self):
-
+ def test_pointer_events(self):
try:
with ThreadedWebServer(
binding_address=self.GetBindingAddress()) as server:
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc
index d5a6545..f5459ed 100644
--- a/src/cobalt/browser/application.cc
+++ b/src/cobalt/browser/application.cc
@@ -1327,3 +1327,9 @@
} // namespace browser
} // namespace cobalt
+
+const char* GetCobaltUserAgentString() {
+ static std::string ua = cobalt::browser::CreateUserAgentString(
+ cobalt::browser::GetUserAgentPlatformInfoFromSystem());
+ return ua.c_str();
+}
diff --git a/src/cobalt/browser/application.h b/src/cobalt/browser/application.h
index 2f8ab19..994e8df 100644
--- a/src/cobalt/browser/application.h
+++ b/src/cobalt/browser/application.h
@@ -239,4 +239,9 @@
} // namespace browser
} // namespace cobalt
+
+extern "C" {
+SB_IMPORT const char* GetCobaltUserAgentString();
+}
+
#endif // COBALT_BROWSER_APPLICATION_H_
diff --git a/src/cobalt/browser/user_agent_string.cc b/src/cobalt/browser/user_agent_string.cc
index 2e7f57d..8e973b5 100644
--- a/src/cobalt/browser/user_agent_string.cc
+++ b/src/cobalt/browser/user_agent_string.cc
@@ -224,10 +224,15 @@
std::string os_name_and_version = platform_info.os_name_and_version;
#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kUserAgentOsNameVersion)) {
- os_name_and_version =
- command_line->GetSwitchValueASCII(switches::kUserAgentOsNameVersion);
+ // Because we add Cobalt's user agent string to Crashpad before we actually
+ // start Cobalt, the command line won't be initialized when we first try to
+ // get the user agent string.
+ if (base::CommandLine::InitializedForCurrentProcess()) {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kUserAgentOsNameVersion)) {
+ os_name_and_version =
+ command_line->GetSwitchValueASCII(switches::kUserAgentOsNameVersion);
+ }
}
#endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index d887bd0..f24700a 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-278101
\ No newline at end of file
+283720
\ No newline at end of file
diff --git a/src/cobalt/configuration/configuration.cc b/src/cobalt/configuration/configuration.cc
index 1502037..9c5087c 100644
--- a/src/cobalt/configuration/configuration.cc
+++ b/src/cobalt/configuration/configuration.cc
@@ -25,7 +25,8 @@
Configuration* Configuration::configuration_ = nullptr;
Configuration* Configuration::GetInstance() {
- return base::Singleton<Configuration>::get();
+ return base::Singleton<Configuration,
+ base::LeakySingletonTraits<Configuration>>::get();
}
Configuration::Configuration() {
diff --git a/src/cobalt/content/fonts/font_files/NotoColorEmoji.woff2 b/src/cobalt/content/fonts/font_files/NotoColorEmoji.woff2
index 9cac5c0..72a6830 100644
--- a/src/cobalt/content/fonts/font_files/NotoColorEmoji.woff2
+++ b/src/cobalt/content/fonts/font_files/NotoColorEmoji.woff2
Binary files differ
diff --git a/src/cobalt/demos/content/media-element-demo/key-systems.html b/src/cobalt/demos/content/media-element-demo/key-systems.html
new file mode 100644
index 0000000..7358ca5
--- /dev/null
+++ b/src/cobalt/demos/content/media-element-demo/key-systems.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Media Element Demo</title>
+ <style>
+ .title {
+ background-color: #FFF;
+ color: #0047ab;
+ font-size: 20px;
+ }
+ .query {
+ }
+ .result-success {
+ background-color: rgb(0, 128, 0);
+ }
+ .result-failure {
+ background-color: rgb(128, 0, 0);
+ }
+ body {
+ background-color: #FFF;
+ font-size: 20px;
+ }
+ </style>
+</head>
+<body>
+ <span class="title">Queries on Key Systems</span>
+ <script type="text/javascript" src="key-systems.js"></script>
+</body>
+</html>
diff --git a/src/cobalt/demos/content/media-element-demo/key-systems.js b/src/cobalt/demos/content/media-element-demo/key-systems.js
new file mode 100644
index 0000000..ec8f149
--- /dev/null
+++ b/src/cobalt/demos/content/media-element-demo/key-systems.js
@@ -0,0 +1,111 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+function getRepresentation(keySystem, audioMime, videoMime, encryptionScheme) {
+ var representation = keySystem;
+ if (typeof audioMime !== 'undefined') {
+ representation += ', ' + audioMime;
+ }
+ if (typeof videoMime !== 'undefined') {
+ representation += ', ' + videoMime;
+ }
+ if (typeof encryptionScheme !== 'undefined') {
+ representation += ', encryptionscheme="' + encryptionScheme + '"';
+ }
+ return representation;
+}
+
+function checkForSupport(keySystem, audioMime, videoMime, encryptionScheme,
+ expectedResult) {
+ var configs = [{
+ initDataTypes: ['cenc', 'sinf', 'webm'],
+ audioCapabilities: [],
+ videoCapabilities: [],
+ }];
+ if (typeof audioMime !== 'undefined') {
+ configs[0].audioCapabilities.push(
+ {contentType: audioMime, encryptionScheme: encryptionScheme});
+ }
+ if (typeof videoMime !== 'undefined') {
+ configs[0].videoCapabilities.push(
+ {contentType: videoMime, encryptionScheme: encryptionScheme});
+ }
+ var representation = getRepresentation(keySystem, audioMime, videoMime,
+ encryptionScheme);
+ navigator.requestMediaKeySystemAccess(keySystem, configs)
+ .then(onKeySystemAccess.bind(this, representation, expectedResult),
+ onFailure.bind(this, representation, expectedResult));
+}
+
+function addQueryResult(query, result, expectedResult) {
+ var row = document.createElement('div');
+
+ var cell = document.createElement('span');
+ cell.className = 'query';
+ cell.textContent = query + ' => ';
+ row.appendChild(cell);
+
+ cell = document.createElement('span');
+ cell.className = result == expectedResult ? 'result-success' :
+ 'result-failure';
+ cell.textContent = result;
+ row.appendChild(cell);
+
+ document.body.appendChild(row);
+}
+
+function onKeySystemAccess(representation, expectedResult, keySystemAccess) {
+ addQueryResult(representation, 'supported', expectedResult);
+}
+
+function onFailure(representation, expectedResult) {
+ addQueryResult(representation, 'not supported', expectedResult);
+}
+
+checkForSupport('com.widevine.alpha.invalid', 'audio/mp4; codecs="mp4a.40.2"',
+ undefined, undefined, 'not supported');
+checkForSupport('com.widevine.alpha.invalid', undefined,
+ 'video/webm; codecs="vp9"', undefined, 'not supported');
+
+// 'invalid-scheme' is not a valid scheme.
+checkForSupport('com.widevine.alpha', 'audio/mp4; codecs="mp4a.40.2"',
+ undefined, 'invalid-scheme', 'not supported');
+checkForSupport('com.widevine.alpha', undefined, 'video/webm; codecs="vp9"',
+ 'invalid-scheme', 'not supported');
+
+checkForSupport('com.widevine.alpha', 'audio/mp4; codecs="mp4a.40.2"',
+ undefined, undefined, 'supported');
+checkForSupport('com.widevine.alpha', undefined, 'video/webm; codecs="vp9"',
+ undefined, 'supported');
+
+// Empty string is not a valid scheme.
+checkForSupport('com.widevine.alpha', 'audio/mp4; codecs="mp4a.40.2"',
+ undefined, '', 'not supported');
+checkForSupport('com.widevine.alpha', undefined, 'video/webm; codecs="vp9"',
+ '', 'not supported');
+
+checkForSupport('com.widevine.alpha', 'audio/mp4; codecs="mp4a.40.2"',
+ undefined, 'cenc', 'supported');
+checkForSupport('com.widevine.alpha', undefined, 'video/webm; codecs="vp9"',
+ 'cenc', 'supported');
+
+checkForSupport('com.widevine.alpha', 'audio/mp4; codecs="mp4a.40.2"',
+ undefined, 'cbcs', 'supported');
+checkForSupport('com.widevine.alpha', undefined, 'video/webm; codecs="vp9"',
+ 'cbcs', 'supported');
+
+checkForSupport('com.widevine.alpha', 'audio/mp4; codecs="mp4a.40.2"',
+ undefined, 'cbcs-1-9', 'supported');
+checkForSupport('com.widevine.alpha', undefined, 'video/webm; codecs="vp9"',
+ 'cbcs-1-9', 'supported');
diff --git a/src/cobalt/doc/resources/devtools-overlay-console-modes.png b/src/cobalt/doc/resources/devtools-overlay-console-modes.png
new file mode 100644
index 0000000..5103358
--- /dev/null
+++ b/src/cobalt/doc/resources/devtools-overlay-console-modes.png
Binary files differ
diff --git a/src/cobalt/doc/web_debugging.md b/src/cobalt/doc/web_debugging.md
index c4711db..5090e4f 100644
--- a/src/cobalt/doc/web_debugging.md
+++ b/src/cobalt/doc/web_debugging.md
@@ -102,28 +102,146 @@
### Console
-Cobalt has two consoles:
-* Overlay console in Cobalt itself (shown with ctrl-O or F1).
-* Remote console shown in a connected DevTools session.
+Cobalt has two types of consoles:
+
+* Overlay Console: shown at runtime of Cobalt. It has multiple mode that it
+ can cycle between as well:
+ * HUD
+ * HUD & Debug Console
+ * Media Console
+* Remote Console: shown in a connected devtools session.
Both console UIs show messages logged from JavaScript (with `console.log()`,
etc.), and have a command line to evaluate arbitrary JavaScript in the context
of the page being debugged.
+#### Overlay Console
+
The overlay console also shows non-JavaScript logging from Cobalt itself, which
is mostly interesting to Cobalt developers rather than web app developers.
+The various modes of the overlay console are accessed by repeatedly pressing
+"`F1`" or "`Ctrl+O`". They cycle in order between: none, HUD, HUD & Debug, and
+Media. Alternatively, initial console state can be set with the
+`--debug_console=off|hud|debug|media` command-line switch (`--debug_console=on`
+is accepted as a legacy option and maps to "debug" setting).
+
+
+
+##### HUD overlay
+
+This brings up an overlay panel which does not block sending input to the
+underlying Cobalt app. It serves to display real-time statistics (e.g. memory
+usage) and configuration values (e.g. disabled codecs) of the Cobalt app in a
+compact string.
+
+##### Debug Console overlay
+
+This overlay is interactive and it shows messages from Cobalt, along with logs
+from Javacript `console.log()`. While it is active, you cannot interact directly
+with the underlying page.
+
+Additionally, it can act as a JS interpreter that will evaluate arbitrary
+expressions on the page being debugged. The output from these JS commands will
+also be printed to the Debug console.
+
+Finally, it has some special debug commands which can be listed by calling
+`d.help()`. They are provided by a debug helper object and the list of functions
+are invoked by prepending either "`debug`" or "`d`". For example, you can
+disable the vp9 codec manually for all future played videos in this session of
+Cobalt by sending `debug.disable_media_codecs("vp9")` to the console.
+
+Note: you can clear the disabled media codecs by sending
+`debug.disable_media_codecs("")`. The command takes a semicolon separated list
+of codecs as the input list of codecs to disable.
+
+##### Media Console overlay
+
+The media console is a specialized console of the debug overlay system, for
+playback and media related tasks. The current list of implemented features are:
+
+* Reading the play/pause state of the primary video
+* Reading the current time and duration of the primary video
+* Reading the playback rate of the primary video
+* Reading the currently disabled codecs for the player
+* Toggling between playing and pausing the primary video
+* Setting the current playback rate between various presets for the primary
+ video
+* Toggling the enabled/disabled state of the available codecs
+
+While the media console is shown, it is not possible to interact with the page
+below it directly.
+
+Additionally, the console does not show any meaningful information or
+interactions when no video is currently playing (all the readouts are blank or
+undefined). A status message of “No primary video.” indicates there is no valid
+player element on the current page.
+
+In the case of multiple videos playing (such as picture in picture), only the
+primary (fullscreen) video’s information is shown and the controls are only
+enabled for the primary video.
+
+The list of hotkeys and commands are dynamically generated as they are found to
+be available on app startup.
+
+Basic always-enabled commands are (case-sensitive):
+
+* "`p`" Toggle the play/pause state
+* "`]`" Increase the playback rate
+* "`[`" Decrease the playback rate
+
+The above commands will take effect instantly for the currently playing video.
+They have no effect if there is no video playing.
+
+The following commands are dynamically loaded based on the capability of the
+system:
+
+* "`CTRL+NUM`" Enable/disable specific video codec
+* "`ALT+NUM`" Enable/disable specific audio codec
+
+**Important:** Media Console cannot be used to directly select a specific codec for
+playback. See the section below for rough outline of steps to work around this.
+
+The list of available codecs for any video is chosen based on the decoders on
+the platform, and what formats YouTube itself serves. As a result, the only way
+to get a particular codec to play is to disable all the options until the
+desired codec is the one that is picked. Simply do the following procedure:
+
+* Pick the video you want to play.
+* Enable “stats for nerds” (See [help page for
+ instructions](https://support.google.com/youtube/answer/7519898)).
+* Write down the codecs that are chosen when playing the video, without any
+ codecs disabled (one for video, and one for audio).
+* Disable the default codecs.
+* Replay the same video from the browse screen.
+* Repeat until you identify all codecs that are available for the video, until
+ the video is unable to be played.
+* Use the above knowledge to disable the codecs to force the player into
+ choosing a particular codec, by process of elimination.
+
+**Important:** Disabled codecs only take effect when a video starts playing.
+When you play a video, the current list of disabled codecs is used to select an
+arbitrary enabled format. When you seek in the video, the disabled codecs list
+does not take effect. Only when you exit the player and re-enter by playing a
+video will any toggled codecs be affected.
+
+**Important:** Disabled codecs list is persistent for the app-run. If you
+disable “av01”, then until you re-enable it, “av01” formats will never be
+chosen.
+
+**Important:** If you disable all the available codecs, no video codec can be
+selected and an error dialog will be shown. This means that YouTube does not
+have the video in any other formats, outside of the codecs that are disabled.
+The player reports that it cannot play the video in any of the available formats
+so playback will fail here, which is intended.
+
+#### Remote Console
+
The console in DevTools is a richer UI that can show evaluated objects with an
expander so you can dig in to their properties. Logging from JavaScript with
`console.log()` can show objects and exceptions as well, in contrast to the
text-only messages shown in the console overlay.
-> There may be some things (e.g. timers) that still need to be hooked up to the
-> V8 backend, so please file a bug if something isn't working as expected.
-
-> When built with MozJs instead of V8, the functionality of the console is
-> limited to showing only text log messages.
-
Chrome docs:
* https://developers.google.com/web/tools/chrome-devtools/console/
diff --git a/src/cobalt/dom/eme/media_key_system_media_capability.idl b/src/cobalt/dom/eme/media_key_system_media_capability.idl
index 56e86d5..7f1da60 100644
--- a/src/cobalt/dom/eme/media_key_system_media_capability.idl
+++ b/src/cobalt/dom/eme/media_key_system_media_capability.idl
@@ -16,7 +16,11 @@
dictionary MediaKeySystemMediaCapability {
DOMString contentType = "";
+
// TODO: Implement robustness as per
// https://www.w3.org/TR/encrypted-media/#dom-mediakeysystemmediacapability-robustness.
// DOMString robustness = "";
+
+ // https://wicg.github.io/encrypted-media-encryption-scheme/
+ DOMString? encryptionScheme = null;
};
diff --git a/src/cobalt/dom/html_element.cc b/src/cobalt/dom/html_element.cc
index ae93458..7a76ea5 100644
--- a/src/cobalt/dom/html_element.cc
+++ b/src/cobalt/dom/html_element.cc
@@ -1023,10 +1023,7 @@
// themselves still need to have their computed style updated, in case the
// value of display is changed.
if (computed_style()->display() == cssom::KeywordValue::GetNone()) {
- if (ui_nav_item_) {
- ui_nav_item_->SetEnabled(false);
- ui_nav_item_ = nullptr;
- }
+ ReleaseUiNavigationItem();
return;
}
@@ -1207,12 +1204,7 @@
}
HTMLElement::~HTMLElement() {
- // Disable any associated navigation item to prevent callbacks during
- // destruction.
- if (ui_nav_item_) {
- ui_nav_item_->SetEnabled(false);
- ui_nav_item_ = nullptr;
- }
+ ReleaseUiNavigationItem();
if (IsInDocument()) {
dom_stat_tracker_->OnHtmlElementRemovedFromDocument();
@@ -1251,11 +1243,7 @@
// Node::OnRemovedFromDocument().
ClearRuleMatchingStateInternal(false /*invalidate_descendants*/);
- // Release the associated navigation item as the object is no longer visible.
- if (ui_nav_item_) {
- ui_nav_item_->SetEnabled(false);
- ui_nav_item_ = nullptr;
- }
+ ReleaseUiNavigationItem();
}
void HTMLElement::OnMutation() { InvalidateMatchingRulesRecursively(); }
@@ -2007,6 +1995,11 @@
}
}
+ // Update the UI navigation item and invalidate layout boxes if needed.
+ if (!UpdateUiNavigationAndReturnIfLayoutBoxesAreValid()) {
+ invalidation_flags.invalidate_layout_boxes = true;
+ }
+
if (invalidation_flags.mark_descendants_as_display_none) {
MarkNotDisplayedOnDescendants();
}
@@ -2029,9 +2022,6 @@
}
}
- // Update the UI navigation item.
- UpdateUiNavigationType();
-
computed_style_valid_ = true;
pseudo_elements_computed_styles_valid_ = true;
}
@@ -2069,7 +2059,7 @@
computed_style()->visibility() == cssom::KeywordValue::GetVisible();
}
-void HTMLElement::UpdateUiNavigationType() {
+bool HTMLElement::UpdateUiNavigationAndReturnIfLayoutBoxesAreValid() {
base::Optional<ui_navigation::NativeItemType> ui_nav_item_type;
if (computed_style()->overflow() == cssom::KeywordValue::GetAuto() ||
computed_style()->overflow() == cssom::KeywordValue::GetScroll()) {
@@ -2088,7 +2078,7 @@
if (ui_nav_item_->GetType() == *ui_nav_item_type) {
// Keep using the existing navigation item.
ui_nav_item_->SetDir(ui_nav_item_dir);
- return;
+ return true;
}
// The current navigation item isn't of the correct type. Disable it so
// that callbacks won't be invoked for it. The object will be destroyed
@@ -2096,6 +2086,7 @@
ui_nav_item_->SetEnabled(false);
ui_nav_item_ = nullptr;
}
+
ui_nav_item_ = new ui_navigation::NavItem(
*ui_nav_item_type,
base::Bind(
@@ -2114,10 +2105,30 @@
FROM_HERE,
base::Bind(&HTMLElement::OnUiNavScroll, base::AsWeakPtr(this))));
ui_nav_item_->SetDir(ui_nav_item_dir);
+ return false;
} else if (ui_nav_item_) {
// This navigation item is no longer relevant.
ui_nav_item_->SetEnabled(false);
ui_nav_item_ = nullptr;
+ return false;
+ }
+
+ return true;
+}
+
+void HTMLElement::ReleaseUiNavigationItem() {
+ if (ui_nav_item_) {
+ // Make sure layout updates this element.
+ InvalidateLayoutBoxesOfNodeAndAncestors();
+ if (ui_nav_item_->IsContainer()) {
+ // Make sure layout updates any focus items that may be in this container.
+ InvalidateLayoutBoxesOfDescendants();
+ }
+
+ // Disable the UI navigation item so it won't receive anymore callbacks
+ // while being released.
+ ui_nav_item_->SetEnabled(false);
+ ui_nav_item_ = nullptr;
}
}
diff --git a/src/cobalt/dom/html_element.h b/src/cobalt/dom/html_element.h
index fae0c2b..b29c27c 100644
--- a/src/cobalt/dom/html_element.h
+++ b/src/cobalt/dom/html_element.h
@@ -412,7 +412,8 @@
void ClearRuleMatchingStateInternal(bool invalidate_descendants);
// Update the UI navigation item type for this element.
- void UpdateUiNavigationType();
+ bool UpdateUiNavigationAndReturnIfLayoutBoxesAreValid();
+ void ReleaseUiNavigationItem();
// Clear the list of active background images, and notify the animated image
// tracker to stop the animations.
diff --git a/src/cobalt/dom/html_media_element.cc b/src/cobalt/dom/html_media_element.cc
index aa21c6f..aff4334 100644
--- a/src/cobalt/dom/html_media_element.cc
+++ b/src/cobalt/dom/html_media_element.cc
@@ -250,10 +250,9 @@
DLOG_IF(ERROR, !key_system.empty())
<< "CanPlayType() only accepts one parameter but (" << key_system
<< ") is passed as a second parameter.";
- const bool kIsProgressive = true;
auto support_type =
- html_element_context()->can_play_type_handler()->CanPlayType(
- mime_type, key_system, kIsProgressive);
+ html_element_context()->can_play_type_handler()->CanPlayProgressive(
+ mime_type);
std::string result = "";
switch (support_type) {
case kSbMediaSupportTypeNotSupported:
diff --git a/src/cobalt/dom/media_source.cc b/src/cobalt/dom/media_source.cc
index e94f4c4..57817f4 100644
--- a/src/cobalt/dom/media_source.cc
+++ b/src/cobalt/dom/media_source.cc
@@ -269,10 +269,8 @@
DOMSettings* dom_settings =
base::polymorphic_downcast<DOMSettings*>(settings);
DCHECK(dom_settings->can_play_type_handler());
- const bool kIsProgressive = false;
SbMediaSupportType support_type =
- dom_settings->can_play_type_handler()->CanPlayType(type.c_str(), "",
- kIsProgressive);
+ dom_settings->can_play_type_handler()->CanPlayAdaptive(type.c_str(), "");
if (support_type == kSbMediaSupportTypeNotSupported) {
LOG(INFO) << "MediaSource::IsTypeSupported(" << type
<< ") -> not supported/false";
diff --git a/src/cobalt/dom/navigator.cc b/src/cobalt/dom/navigator.cc
index c57b886..a6d3ce3 100644
--- a/src/cobalt/dom/navigator.cc
+++ b/src/cobalt/dom/navigator.cc
@@ -31,12 +31,117 @@
using cobalt::media_session::MediaSession;
-namespace {
-const char kLicensesRelativePath[] = "/licenses/licenses_cobalt.txt";
-} // namespace
-
namespace cobalt {
namespace dom {
+namespace {
+
+const char kLicensesRelativePath[] = "/licenses/licenses_cobalt.txt";
+
+#if !defined(COBALT_BUILD_TYPE_GOLD)
+
+std::string ToString(const std::string& str, int indent_level);
+std::string ToString(const eme::MediaKeySystemMediaCapability& capability,
+ int indent_level);
+std::string ToString(const eme::MediaKeySystemConfiguration& configuration,
+ int indent_level);
+
+std::string GetIndent(int indent_level) {
+ std::string indent;
+ while (indent_level > 0) {
+ indent += " ";
+ --indent_level;
+ }
+ return indent;
+}
+
+template <typename T>
+std::string ToString(const script::Sequence<T>& sequence, int indent_level) {
+ std::stringstream ss;
+
+ ss << "{\n";
+
+ for (auto iter = sequence.begin(); iter != sequence.end(); ++iter) {
+ ss << ToString(*iter, indent_level + 1) << ",\n";
+ }
+
+ ss << GetIndent(indent_level) << "}";
+
+ return ss.str();
+}
+
+std::string ToString(const std::string& str, int indent_level) {
+ return GetIndent(indent_level) + str;
+}
+
+std::string ToString(const eme::MediaKeySystemMediaCapability& capability,
+ int indent_level) {
+ return GetIndent(indent_level) + '\'' + capability.content_type() + "'/'" +
+ capability.encryption_scheme().value_or("(null)") + '\'';
+}
+
+std::string ToString(const eme::MediaKeySystemConfiguration& configuration,
+ int indent_level) {
+ DCHECK(configuration.has_label());
+
+ std::stringstream ss;
+
+ ss << GetIndent(indent_level) << "label:'" << configuration.label()
+ << "': {\n";
+ if (configuration.has_init_data_types()) {
+ ss << GetIndent(indent_level + 1) << "init_data_types: "
+ << ToString(configuration.init_data_types(), indent_level + 1) << ",\n";
+ }
+ if (configuration.has_audio_capabilities()) {
+ ss << GetIndent(indent_level + 1) << "audio_capabilities: "
+ << ToString(configuration.audio_capabilities(), indent_level + 1)
+ << ",\n";
+ }
+ if (configuration.has_video_capabilities()) {
+ ss << GetIndent(indent_level + 1) << "video_capabilities: "
+ << ToString(configuration.video_capabilities(), indent_level + 1)
+ << ",\n";
+ }
+ ss << GetIndent(indent_level) << "}";
+
+ return ss.str();
+}
+
+#endif // !defined(COBALT_BUILD_TYPE_GOLD)
+
+// This function is used when the underlying SbMediaCanPlayMimeAndKeySystem()
+// implementation doesn't support extra attributes on |key_system|, it makes
+// decision based on the key system itself.
+bool IsEncryptionSchemeSupportedByDefault(
+ const std::string& key_system, const std::string& encryption_scheme) {
+ // 1. Playready only supports "cenc".
+ if (key_system.find("playready") != key_system.npos) {
+ return encryption_scheme == "cenc";
+ }
+ // 2. Fairplay only supports "cbcs" and "cbcs-1-9".
+ if (key_system.find("fairplay") != key_system.npos) {
+ return encryption_scheme == "cbcs" || encryption_scheme == "cbcs-1-9";
+ }
+ // 3. Widevine only supports "cenc", "cbcs" and "cbcs-1-9".
+ if (key_system.find("widevine") != key_system.npos) {
+ return encryption_scheme == "cenc" || encryption_scheme == "cbcs" ||
+ encryption_scheme == "cbcs-1-9";
+ }
+
+ // The key system is unknown, assume only "cenc" is supported.
+ return encryption_scheme == "cenc";
+}
+
+bool CanPlay(const media::CanPlayTypeHandler& can_play_type_handler,
+ const std::string& content_type, const std::string& key_system) {
+ auto can_play_result = can_play_type_handler.CanPlayAdaptive(
+ content_type.c_str(), key_system.c_str());
+ LOG_IF(INFO, can_play_result == kSbMediaSupportTypeMaybe)
+ << "CanPlayAdaptive() returns \"maybe\".";
+ return can_play_result == kSbMediaSupportTypeProbably ||
+ can_play_result == kSbMediaSupportTypeMaybe;
+}
+
+} // namespace
Navigator::Navigator(
script::EnvironmentSettings* settings, const std::string& user_agent,
@@ -123,17 +228,16 @@
return media_session_;
}
-namespace {
-
+// TODO: Move the following two functions to the bottom of the file, in sync
+// with the order of declaration.
// See
// https://www.w3.org/TR/encrypted-media/#get-supported-capabilities-for-audio-video-type.
base::Optional<script::Sequence<MediaKeySystemMediaCapability>>
-TryGetSupportedCapabilities(
+Navigator::TryGetSupportedCapabilities(
+ const media::CanPlayTypeHandler& can_play_type_handler,
const std::string& key_system,
const script::Sequence<MediaKeySystemMediaCapability>&
- requested_media_capabilities,
- const media::CanPlayTypeHandler* can_play_type_handler) {
- DCHECK(can_play_type_handler);
+ requested_media_capabilities) {
// 2. Let supported media capabilities be an empty sequence of
// MediaKeySystemMediaCapability dictionaries.
script::Sequence<MediaKeySystemMediaCapability> supported_media_capabilities;
@@ -152,17 +256,10 @@
// 3.13. If the user agent and [CDM] implementation definitely support
// playback of encrypted media data for the combination of container,
// media types [...]:
- const bool kIsProgressive = false;
- if (can_play_type_handler->CanPlayType(
- content_type.c_str(), key_system.c_str(), kIsProgressive) ==
- kSbMediaSupportTypeProbably) {
- LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type
- << ", " << key_system << ") -> supported";
+ if (CanPlayWithCapability(can_play_type_handler, key_system,
+ requested_media_capability)) {
// 3.13.1. Add requested media capability to supported media capabilities.
supported_media_capabilities.push_back(requested_media_capability);
- } else {
- LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type
- << ", " << key_system << ") -> not supported";
}
}
// 4. If supported media capabilities is empty, return null.
@@ -179,10 +276,11 @@
// is always given and go straight to "3.1.1.2 Get Supported Configuration and
// Consent". See
// https://www.w3.org/TR/encrypted-media/#get-supported-configuration-and-consent.
-base::Optional<eme::MediaKeySystemConfiguration> TryGetSupportedConfiguration(
+base::Optional<eme::MediaKeySystemConfiguration>
+Navigator::TryGetSupportedConfiguration(
+ const media::CanPlayTypeHandler& can_play_type_handler,
const std::string& key_system,
- const eme::MediaKeySystemConfiguration& candidate_configuration,
- const media::CanPlayTypeHandler* can_play_type_handler) {
+ const eme::MediaKeySystemConfiguration& candidate_configuration) {
// 1. Let accumulated configuration be a new MediaKeySystemConfiguration
// dictionary.
eme::MediaKeySystemConfiguration accumulated_configuration;
@@ -225,8 +323,8 @@
// Supported Capabilities for Audio/Video Type" algorithm.
base::Optional<script::Sequence<MediaKeySystemMediaCapability>>
maybe_video_capabilities = TryGetSupportedCapabilities(
- key_system, candidate_configuration.video_capabilities(),
- can_play_type_handler);
+ can_play_type_handler, key_system,
+ candidate_configuration.video_capabilities());
// 16.2. If video capabilities is null, return NotSupported.
if (!maybe_video_capabilities) {
return base::nullopt;
@@ -249,8 +347,8 @@
// Supported Capabilities for Audio/Video Type" algorithm.
base::Optional<script::Sequence<MediaKeySystemMediaCapability>>
maybe_audio_capabilities = TryGetSupportedCapabilities(
- key_system, candidate_configuration.audio_capabilities(),
- can_play_type_handler);
+ can_play_type_handler, key_system,
+ candidate_configuration.audio_capabilities());
// 17.2. If audio capabilities is null, return NotSupported.
if (!maybe_audio_capabilities) {
return base::nullopt;
@@ -269,8 +367,6 @@
return accumulated_configuration;
}
-} // namespace
-
// See
// https://www.w3.org/TR/encrypted-media/#dom-navigator-requestmediakeysystemaccess.
script::Handle<Navigator::InterfacePromise>
@@ -286,6 +382,12 @@
script_value_factory_
->CreateInterfacePromise<scoped_refptr<eme::MediaKeySystemAccess>>();
+#if !defined(COBALT_BUILD_TYPE_GOLD)
+ LOG(INFO) << "Navigator.RequestMediaKeySystemAccess() called with '"
+ << key_system << "', and\n"
+ << ToString(supported_configurations, 0);
+#endif // !defined(COBALT_BUILD_TYPE_GOLD)
+
// 1. If |keySystem| is the empty string, return a promise rejected
// with a newly created TypeError.
// 2. If |supportedConfigurations| is empty, return a promise rejected
@@ -302,14 +404,19 @@
// 6.3.3. If supported configuration is not NotSupported:
base::Optional<eme::MediaKeySystemConfiguration>
maybe_supported_configuration = TryGetSupportedConfiguration(
- key_system, supported_configurations.at(configuration_index),
- dom_settings->can_play_type_handler());
+ *dom_settings->can_play_type_handler(), key_system,
+ supported_configurations.at(configuration_index));
if (maybe_supported_configuration) {
// 6.3.3.1. Let access be a new MediaKeySystemAccess object.
scoped_refptr<eme::MediaKeySystemAccess> media_key_system_access(
new eme::MediaKeySystemAccess(key_system,
*maybe_supported_configuration,
script_value_factory_));
+#if !defined(COBALT_BUILD_TYPE_GOLD)
+ LOG(INFO) << "Navigator.RequestMediaKeySystemAccess() resolved with '"
+ << media_key_system_access->key_system() << "', and\n"
+ << ToString(media_key_system_access->GetConfiguration(), 0);
+#endif // !defined(COBALT_BUILD_TYPE_GOLD)
// 6.3.3.2. Resolve promise.
promise->Resolve(media_key_system_access);
return promise;
@@ -334,5 +441,115 @@
tracer->Trace(system_caption_settings_);
}
+bool Navigator::CanPlayWithCapability(
+ const media::CanPlayTypeHandler& can_play_type_handler,
+ const std::string& key_system,
+ const MediaKeySystemMediaCapability& media_capability) {
+ const std::string& content_type = media_capability.content_type();
+
+ // There is no encryption scheme specified, check directly.
+ if (!media_capability.encryption_scheme().has_value()) {
+ if (CanPlay(can_play_type_handler, content_type, key_system)) {
+ LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type
+ << ", " << key_system << ") -> supported";
+ return true;
+ }
+ LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type
+ << ", " << key_system << ") -> not supported";
+ return false;
+ }
+
+ if (!key_system_with_attributes_supported_.has_value()) {
+ if (!CanPlay(can_play_type_handler, content_type, key_system)) {
+ // If the check on the basic key system fails, we don't even bother to
+ // check if it supports key system with attributes.
+ LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type
+ << ", " << key_system << ") -> not supported";
+ return false;
+ }
+ auto key_system_with_invalid_attribute =
+ std::string(key_system) + "; invalid_attributes=\"value\"";
+ // If an implementation supports attributes, it should ignore unknown
+ // attributes and return true, as the key system has been verified to be
+ // supported above.
+ key_system_with_attributes_supported_ = CanPlay(
+ can_play_type_handler, content_type, key_system_with_invalid_attribute);
+ if (key_system_with_attributes_supported_.value()) {
+ LOG(INFO) << "Navigator::RequestMediaKeySystemAccess() will use key"
+ << " system with attributes.";
+ } else {
+ LOG(INFO) << "Navigator::RequestMediaKeySystemAccess() won't use key"
+ << " system with attributes.";
+ }
+ }
+
+ DCHECK(key_system_with_attributes_supported_.has_value());
+
+ // As a key system with attributes support is optional, and the logic to
+ // determine whether the encryptionScheme is supported can be quite different
+ // depending on whether this is supported, we encapsulate the logic into two
+ // different functions.
+ if (key_system_with_attributes_supported_.value()) {
+ return CanPlayWithAttributes(can_play_type_handler, content_type,
+ key_system,
+ media_capability.encryption_scheme().value());
+ }
+
+ return CanPlayWithoutAttributes(can_play_type_handler, content_type,
+ key_system,
+ media_capability.encryption_scheme().value());
+}
+
+bool Navigator::CanPlayWithoutAttributes(
+ const media::CanPlayTypeHandler& can_play_type_handler,
+ const std::string& content_type, const std::string& key_system,
+ const std::string& encryption_scheme) {
+ DCHECK(key_system_with_attributes_supported_.has_value());
+ DCHECK(!key_system_with_attributes_supported_.value());
+
+ if (!IsEncryptionSchemeSupportedByDefault(key_system, encryption_scheme)) {
+ LOG(INFO) << "Navigator::RequestMediaKeySystemAccess() rejects "
+ << key_system << " because encryptionScheme \""
+ << encryption_scheme << "\" is not supported.";
+ return false;
+ }
+
+ if (CanPlay(can_play_type_handler, content_type, key_system)) {
+ LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type
+ << ", " << key_system << ") with encryptionScheme \""
+ << encryption_scheme << "\" -> supported";
+ return true;
+ }
+
+ LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type << ", "
+ << key_system << ") with encryptionScheme \"" << encryption_scheme
+ << "\" -> not supported";
+ return false;
+}
+
+bool Navigator::CanPlayWithAttributes(
+ const media::CanPlayTypeHandler& can_play_type_handler,
+ const std::string& content_type, const std::string& key_system,
+ const std::string& encryption_scheme) {
+ DCHECK(key_system_with_attributes_supported_.has_value());
+ DCHECK(key_system_with_attributes_supported_.value());
+
+ auto key_system_with_attributes =
+ key_system + "; encryptionscheme=\"" + encryption_scheme + '"';
+
+ if (CanPlay(can_play_type_handler, content_type,
+ key_system_with_attributes)) {
+ LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type
+ << ", " << key_system << ") with encryptionScheme \""
+ << encryption_scheme << "\" -> supported";
+ return true;
+ }
+
+ LOG(INFO) << "Navigator::RequestMediaKeySystemAccess(" << content_type << ", "
+ << key_system << ") with encryptionScheme \"" << encryption_scheme
+ << "\" -> not supported";
+ return false;
+}
+
} // namespace dom
} // namespace cobalt
diff --git a/src/cobalt/dom/navigator.h b/src/cobalt/dom/navigator.h
index 10a417d..1489f78 100644
--- a/src/cobalt/dom/navigator.h
+++ b/src/cobalt/dom/navigator.h
@@ -18,6 +18,7 @@
#include <string>
#include "base/memory/ref_counted.h"
+#include "base/optional.h"
#include "cobalt/dom/captions/system_caption_settings.h"
#include "cobalt/dom/eme/media_key_system_configuration.h"
#include "cobalt/dom/mime_type_array.h"
@@ -26,6 +27,7 @@
#include "cobalt/media_session/media_session.h"
#include "cobalt/script/promise.h"
#include "cobalt/script/script_value_factory.h"
+#include "cobalt/script/sequence.h"
#include "cobalt/script/wrappable.h"
namespace cobalt {
@@ -84,6 +86,33 @@
private:
~Navigator() override {}
+ base::Optional<script::Sequence<MediaKeySystemMediaCapability>>
+ TryGetSupportedCapabilities(
+ const media::CanPlayTypeHandler& can_play_type_handler,
+ const std::string& key_system,
+ const script::Sequence<MediaKeySystemMediaCapability>&
+ requested_media_capabilities);
+
+ base::Optional<eme::MediaKeySystemConfiguration> TryGetSupportedConfiguration(
+ const media::CanPlayTypeHandler& can_play_type_handler,
+ const std::string& key_system,
+ const eme::MediaKeySystemConfiguration& candidate_configuration);
+
+ bool CanPlayWithCapability(
+ const media::CanPlayTypeHandler& can_play_type_handler,
+ const std::string& key_system,
+ const MediaKeySystemMediaCapability& media_capability);
+
+ bool CanPlayWithoutAttributes(
+ const media::CanPlayTypeHandler& can_play_type_handler,
+ const std::string& content_type, const std::string& key_system,
+ const std::string& encryption_scheme);
+
+ bool CanPlayWithAttributes(
+ const media::CanPlayTypeHandler& can_play_type_handler,
+ const std::string& content_type, const std::string& key_system,
+ const std::string& encryption_scheme);
+
std::string user_agent_;
std::string language_;
scoped_refptr<MimeTypeArray> mime_types_;
@@ -93,6 +122,7 @@
scoped_refptr<cobalt::dom::captions::SystemCaptionSettings>
system_caption_settings_;
script::ScriptValueFactory* script_value_factory_;
+ base::Optional<bool> key_system_with_attributes_supported_;
DISALLOW_COPY_AND_ASSIGN(Navigator);
};
diff --git a/src/cobalt/fetch/embedded_scripts/fetch.js b/src/cobalt/fetch/embedded_scripts/fetch.js
index ac5a7a3..ec89191 100644
--- a/src/cobalt/fetch/embedded_scripts/fetch.js
+++ b/src/cobalt/fetch/embedded_scripts/fetch.js
@@ -1,22 +1,22 @@
-'use strict';(function(c){function E(a){"string"!==typeof a&&(a=String(a));if(/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(a))throw new g("Invalid character in header field name");return a.toLowerCase()}function Q(a){"string"!==typeof a&&(a=String(a));var b;var d=0;for(b=a.length;d<b;d++){var e=a.charCodeAt(d);if(9!==e&&10!==e&&13!==e&&32!==e)break}for(b=a.length-1;b>d&&(e=a.charCodeAt(b),9===e||10===e||13===e||32===e);b--);a=a.substring(d,b+1);d=0;for(b=a.length;d<b;d++)if(e=a.charCodeAt(d),256<=e||0===e||
-10===e||13===e)throw new g("Invalid character in header field value");return a}function W(a,b){throw new g("Immutable header cannot be modified");}function X(a,b){return!1}function Y(a,b){a=a.toLowerCase();return-1<Z.indexOf(a)||a.startsWith("proxy-")||a.startsWith("sec-")?!0:!1}function aa(a,b){a=a.toLowerCase();return-1<ba.indexOf(a)||"content-type"===a&&(b=b.split(";")[0].toLowerCase(),-1<ca.indexOf(b))?!1:!0}function L(a,b){return-1<da.indexOf(a.toLowerCase())?!0:!1}function h(a){this[l]=new I;
-void 0===this[v]&&(this[v]=X);if(void 0!==a){if(null===a||"object"!==typeof a)throw new g("Constructing Headers with invalid parameters");a instanceof h?a.forEach(function(a,d){this.append(d,a)},this):F.isArray(a)?a.forEach(function(a){if(2!==a.length)throw new g("Constructing Headers with invalid parameters");this.append(a[0],a[1])},this):Object.getOwnPropertyNames(a).forEach(function(b){this.append(b,a[b])},this)}}function G(a,b){var d=ea(h.prototype);d[v]=b;h.call(d,a);return d}function M(a){if(a.bodyUsed)return t.reject(new g("Body was already read"));
-if(null===a.body)return t.resolve(new u(0));if(fa(a.body))return t.reject(new g("ReadableStream was already locked"));var b=a.body.getReader(),d=[],e=0;return b.read().then(function ha(a){if(a.done){if(0===d.length)a=new u(0);else if(1===d.length)a=new u(d[0].buffer);else{a=new u(e);for(var k=0,c=d.length,f=0;k<c;k++)a.set(d[k],f),f+=d[k].length}return a}return a.value instanceof u?(e+=a.value.length,d.push(a.value),b.read().then(ha)):t.reject(new g("Invalid stream data type"))})}function R(){this._initBody=
-function(a){this[N]=!1;this[m]=null===a||void 0===a?null:a instanceof O?a:new O({start:function(b){if(a)if("string"===typeof a)b.enqueue(FetchInternal.encodeToUTF8(a));else if(S.prototype.isPrototypeOf(a))b.enqueue(new u(a.slice(0)));else if(ia(a))b.enqueue(new u(a.buffer.slice(0)));else if(a instanceof Blob)b.enqueue(new u(FetchInternal.blobToArrayBuffer(a)));else throw new g("Unsupported BodyInit type");b.close()}});this[n].get("content-type")||("string"===typeof a?this[n].set("content-type","text/plain;charset=UTF-8"):
-a instanceof Blob&&""!==a.type&&this[n].set("content-type",a.type))};P(this,{body:{get:function(){return this[m]}},bodyUsed:{get:function(){return this[N]?!0:this[m]?!!ja(this[m]):!1}}});this.arrayBuffer=function(){return this[z]?t.reject(new DOMException("Aborted","AbortError")):M(this).then(function(a){return a.buffer})};this.text=function(){return this[z]?t.reject(new DOMException("Aborted","AbortError")):M(this).then(function(a){return FetchInternal.decodeFromUTF8(a)})};this.json=function(){return this[z]?
-t.reject(new DOMException("Aborted","AbortError")):this.text().then(JSON.parse)};return this}function w(a,b){var d=void 0!==b&&null!==b&&void 0===b.cloneBody;b=b||{};var e=b.body||b.cloneBody,c=b.headers,f=new AbortController;this[A]=f.signal;f=null;if(a instanceof w)this[x]=a.url,this[B]=a.cache,this[C]=a.credentials,void 0===c&&(c=a.headers),this[D]=a.integrity,this[y]=a.method,this[p]=a.mode,d&&"navigate"===this[p]&&(this[p]="same-origin"),this[H]=a.redirect,e||null===a.body||(e=a.body,a[N]=!0),
-f=a[A];else{this[x]=String(a);if(!FetchInternal.isUrlValid(this[x],!1))throw new g("Invalid request URL");this[p]="cors";this[C]="same-origin"}if(void 0!==b.window&&null!==b.window)throw new g("Invalid request window");this[B]=b.cache||this[B]||"default";if(-1===ka.indexOf(this[B]))throw new g("Invalid request cache mode");this[C]=b.credentials||this[C]||"same-origin";if(-1===la.indexOf(this[C]))throw new g("Invalid request credentials");void 0!==b.integrity?this[D]=b.integrity:void 0===this[D]&&
-(this[D]="");a=(b.method||this[y]||"GET").toUpperCase();if(-1===ma.indexOf(a))throw new g("Invalid request method");this[y]=a;if(b.mode&&-1===na.indexOf(b.mode))throw new g("Invalid request mode");this[p]=b.mode||this[p]||"no-cors";if("no-cors"===this[p]){if(-1===oa.indexOf(this[y]))throw new g("Invalid request method for no-cors");if(""!==this[D])throw new g("Request integrity data is not allowed with no-cors");}if("same-origin"!==this[p]&&"only-if-cached"===this[B])throw new g("Request mode must be same-origin for only-if-cached");
-this[H]=b.redirect||this[H]||"follow";if(-1===pa.indexOf(this[H]))throw new g("Invalid request redirect mode");this[n]="no-cors"===this[p]?G(c,aa):G(c,Y);if(("GET"===this[y]||"HEAD"===this[y])&&e)throw new g("Request body is not allowed for GET or HEAD");"signal"in b&&(f=b.signal);f&&this[A].follow(f);this._initBody(e)}function qa(a,b){var d=G(void 0,b);a.replace(/\r?\n[\t ]+/g," ").split(/\r?\n/).forEach(function(a){var b=a.split(":");if(a=b.shift().trim())b=b.join(":").trim(),d.append(a,b)});return d}
-function r(a,b){b||(b={});this[J]="default";this[q]="status"in b?b.status:200;if(200>this[q]||599<this[q])throw new T("Invalid response status");this[U]=200<=this[q]&&300>this[q];if("statusText"in b){var d=b.statusText;for(var e=0,f=d.length,c;e<f;e++)if(c=d.charCodeAt(e),9!==c&&(32>c||255<c||127===c))throw g("Invalid response status text");}else d="OK";this[K]=d;this[n]=G(b.headers,L);this[x]=b.url||"";if(a&&-1<ra.indexOf(this[q]))throw new g("Response body is not allowed with a null body status");
-this[z]=b.is_aborted||!1;this._initBody(a)}if(!c.fetch){var F=c.Array,S=c.ArrayBuffer,ea=c.Object.create,P=c.Object.defineProperties,f=c.Symbol,sa=f.iterator,I=c.Map,T=c.RangeError,g=c.TypeError,u=c.Uint8Array,t=c.Promise,O=c.ReadableStream,V=c.ReadableStreamTee,ja=c.IsReadableStreamDisturbed,fa=c.IsReadableStreamLocked,m=f("body"),N=f("bodyUsed"),B=f("cache"),C=f("credentials"),v=f("guardCallback"),n=f("headers"),D=f("integrity"),l=f("map"),y=f("method"),p=f("mode"),U=f("ok"),H=f("redirect"),q=f("status"),
-K=f("statusText"),J=f("type"),x=f("url"),z=f("is_aborted"),A=f("signal"),Z="accept-charset accept-encoding access-control-request-headers access-control-request-method connection content-length cookie cookie2 date dnt expect host keep-alive origin referer te trailer transfer-encoding upgrade via".split(" "),da=["set-cookie","set-cookie2"],ba=["accept","accept-language","content-language"],ca=["application/x-www-form-urlencoded","multipart/form-data","text/plain"],ka="default no-store reload no-cache force-cache only-if-cached".split(" "),
-la=["omit","same-origin","include"],ma="DELETE GET HEAD OPTIONS POST PUT".split(" "),oa=["GET","HEAD","POST"],na=["same-origin","no-cors","cors"],pa=["follow","error","manual"],ra=[101,204,205,304],ta=[301,302,303,307,308],ua="[object Int8Array];[object Uint8Array];[object Uint8ClampedArray];[object Int16Array];[object Uint16Array];[object Int32Array];[object Uint32Array];[object Float32Array];[object Float64Array]".split(";"),ia=S.isView||function(a){return a&&-1<ua.indexOf(Object.prototype.toString.call(a))};
-h.prototype.append=function(a,b){if(2!==arguments.length)throw g("Invalid parameters to append");a=E(a);b=Q(b);this[v](a,b)||(this[l].has(a)?this[l].set(a,this[l].get(a)+", "+b):this[l].set(a,b))};h.prototype["delete"]=function(a){if(1!==arguments.length)throw g("Invalid parameters to delete");this[v](a,"invalid")||this[l].delete(E(a))};h.prototype.get=function(a){if(1!==arguments.length)throw g("Invalid parameters to get");a=E(a);var b=this[l].get(a);return void 0!==b?b:null};h.prototype.has=function(a){if(1!==
-arguments.length)throw g("Invalid parameters to has");return this[l].has(E(a))};h.prototype.set=function(a,b){if(2!==arguments.length)throw g("Invalid parameters to set");a=E(a);b=Q(b);this[v](a,b)||this[l].set(a,b)};h.prototype.forEach=function(a,b){var d=this;F.from(this[l].entries()).sort().forEach(function(e){a.call(b,e[1],e[0],d)})};h.prototype.keys=function(){return(new I(F.from(this[l].entries()).sort())).keys()};h.prototype.values=function(){return(new I(F.from(this[l].entries()).sort())).values()};
-h.prototype.entries=function(){return(new I(F.from(this[l].entries()).sort())).entries()};h.prototype[sa]=h.prototype.entries;w.prototype.clone=function(){var a=null;null!==this[m]&&(a=V(this[m],!0),this[m]=a[0],a=a[1]);return new w(this,{cloneBody:a,signal:this[A]})};P(w.prototype,{cache:{get:function(){return this[B]}},credentials:{get:function(){return this[C]}},headers:{get:function(){return this[n]}},integrity:{get:function(){return this[D]}},method:{get:function(){return this[y]}},mode:{get:function(){return this[p]}},
-redirect:{get:function(){return this[H]}},url:{get:function(){return this[x]}},signal:{get:function(){return this[A]}}});R.call(w.prototype);R.call(r.prototype);r.prototype.clone=function(){var a=null;null!==this[m]&&(a=V(this[m],!0),this[m]=a[0],a=a[1]);return new r(a,{status:this[q],statusText:this[K],headers:G(this[n],L),url:this[x],is_aborted:this[z]})};P(r.prototype,{headers:{get:function(){return this[n]}},ok:{get:function(){return this[U]}},status:{get:function(){return this[q]}},statusText:{get:function(){return this[K]}},
-type:{get:function(){return this[J]}},url:{get:function(){return this[x]}}});r.error=function(){var a=new r(null);a[n][v]=W;a[J]="error";a[q]=0;a[K]="";return a};r.redirect=function(a,b){if(!FetchInternal.isUrlValid(a,!0))throw new g("Invalid URL for response redirect");void 0===b&&(b=302);if(-1===ta.indexOf(b))throw new T("Invalid status code for response redirect");return new r(null,{status:b,headers:{location:a}})};c.Headers=h;c.Request=w;c.Response=r;c.fetch=function(a,b){return new t(function(d,
-e){var c=!1,f=!1,h=new w(a,b),k=new XMLHttpRequest,l=null;if(h.signal.aborted)return e(new DOMException("Aborted","AbortError"));var m=new O({start:function(a){l=a},cancel:function(a){c=!0;k.abort()}}),p=function(){if(!c){c=!0;m.cancel();if(l)try{ReadableStreamDefaultControllerError(l,new DOMException("Aborted","AbortError"))}catch(va){}setTimeout(function(){try{k.abort()}catch(va){}},0)}};k.onload=function(){l.close()};k.onreadystatechange=function(){if(k.readyState===k.HEADERS_RECEIVED){var a={status:k.status,
-statusText:k.statusText,headers:qa(k.getAllResponseHeaders()||"",L)};a.url="responseURL"in k?k.responseURL:a.headers.get("X-Request-URL");try{var b=new r(m,a);h[A].addEventListener("abort",function(){b[z]=!0;p();e(new DOMException("Aborted","AbortError"))});b[J]=f?"cors":"basic";d(b)}catch(wa){e(wa)}}};k.onerror=function(){l.error(new g("Network request failed"));e(new g("Network request failed"))};k.ontimeout=function(){l.error(new g("Network request failed"));e(new g("Network request failed"))};
-k.open(h.method,h.url,!0);"include"===h.credentials&&(k.withCredentials=!0);h.headers.forEach(function(a,b){k.setRequestHeader(b,a)});var n=function(a){c||l.enqueue(a)},q=function(a){f=a};null===h.body?k.fetch(n,q,null):M(h).then(function(a){k.fetch(n,q,a)})})};c.fetch.polyfill=!0}})(this);
\ No newline at end of file
+'use strict';(function(h){function J(a){"string"!==typeof a&&(a=String(a));if(/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(a))throw new e("Invalid character in header field name");return a.toLowerCase()}function X(a){"string"!==typeof a&&(a=String(a));var b;var c=0;for(b=a.length;c<b;c++){var d=a.charCodeAt(c);if(9!==d&&10!==d&&13!==d&&32!==d)break}for(b=a.length-1;b>c&&(d=a.charCodeAt(b),9===d||10===d||13===d||32===d);b--);a=a.substring(c,b+1);c=0;for(b=a.length;c<b;c++)if(d=a.charCodeAt(c),256<=d||0===d||
+10===d||13===d)throw new e("Invalid character in header field value");return a}function fa(a,b){throw new e("Immutable header cannot be modified");}function ha(a,b){return!1}function ia(a,b){a=a.toLowerCase();return-1<ja.indexOf(a)||a.startsWith("proxy-")||a.startsWith("sec-")?!0:!1}function ka(a,b){a=a.toLowerCase();return-1<la.indexOf(a)||"content-type"===a&&(b=b.split(";")[0].toLowerCase(),-1<ma.indexOf(b))?!1:!0}function S(a,b){return-1<na.indexOf(a.toLowerCase())?!0:!1}function n(a){this[p]=
+new P;void 0===this[A]&&(this[A]=ha);if(void 0!==a){if(null===a||"object"!==typeof a)throw new e("Constructing Headers with invalid parameters");a instanceof n?a.forEach(function(b,c){this.append(c,b)},this):K.isArray(a)?a.forEach(function(b){if(2!==b.length)throw new e("Constructing Headers with invalid parameters");this.append(b[0],b[1])},this):Object.getOwnPropertyNames(a).forEach(function(b){this.append(b,a[b])},this)}}function L(a,b){var c=oa(n.prototype);c[A]=b;n.call(c,a);return c}function T(a){if(a.bodyUsed)return z.reject(new e("Body was already read"));
+if(null===a.body)return z.resolve(new v(0));if(pa(a.body))return z.reject(new e("ReadableStream was already locked"));var b=a.body.getReader(),c=[],d=0;return b.read().then(function q(f){if(f.done){if(0===c.length)f=new v(0);else if(1===c.length)f=new v(c[0].buffer);else{f=new v(d);for(var g=0,w=c.length,M=0;g<w;g++)f.set(c[g],M),M+=c[g].length}return f}return f.value instanceof v?(d+=f.value.length,c.push(f.value),b.read().then(q)):z.reject(new e("Invalid stream data type"))})}function Y(){this._initBody=
+function(a){this[U]=!1;this[r]=null===a||void 0===a?null:a instanceof V?a:new V({start:function(b){if(a)if("string"===typeof a)b.enqueue(FetchInternal.encodeToUTF8(a));else if(Z.prototype.isPrototypeOf(a))b.enqueue(new v(a.slice(0)));else if(qa(a)){var c=new v(a.buffer);c=v.from(c.slice(a.byteOffset,a.byteLength+1));b.enqueue(c)}else if(a instanceof Blob)b.enqueue(new v(FetchInternal.blobToArrayBuffer(a)));else throw new e("Unsupported BodyInit type");b.close()}});this[x].get("content-type")||("string"===
+typeof a?this[x].set("content-type","text/plain;charset=UTF-8"):a instanceof Blob&&""!==a.type&&this[x].set("content-type",a.type))};W(this,{body:{get:function(){return this[r]}},bodyUsed:{get:function(){return this[U]?!0:this[r]?!!ra(this[r]):!1}}});this.arrayBuffer=function(){return this[E]?z.reject(new DOMException("Aborted","AbortError")):T(this).then(function(a){return a.buffer})};this.text=function(){return this[E]?z.reject(new DOMException("Aborted","AbortError")):T(this).then(function(a){return FetchInternal.decodeFromUTF8(a)})};
+this.json=function(){return this[E]?z.reject(new DOMException("Aborted","AbortError")):this.text().then(JSON.parse)};return this}function B(a,b){var c=void 0!==b&&null!==b&&void 0===b.cloneBody;b=b||{};var d=b.body||b.cloneBody;""===b.body&&(d="");var l=b.headers,f=new AbortController;this[F]=f.signal;f=null;if(a instanceof B)this[C]=a.url,this[G]=a.cache,this[H]=a.credentials,void 0===l&&(l=a.headers),this[I]=a.integrity,this[D]=a.method,this[t]=a.mode,c&&"navigate"===this[t]&&(this[t]="same-origin"),
+this[N]=a.redirect,d||null===a.body||(d=a.body,a[U]=!0),f=a[F];else{this[C]=String(a);if(!FetchInternal.isUrlValid(this[C],!1))throw new e("Invalid request URL");this[t]="cors";this[H]="same-origin"}if(void 0!==b.window&&null!==b.window)throw new e("Invalid request window");this[G]=b.cache||this[G]||"default";if(-1===sa.indexOf(this[G]))throw new e("Invalid request cache mode");this[H]=b.credentials||this[H]||"same-origin";if(-1===ta.indexOf(this[H]))throw new e("Invalid request credentials");void 0!==
+b.integrity?this[I]=b.integrity:void 0===this[I]&&(this[I]="");a=(b.method||this[D]||"GET").toUpperCase();if(-1===ua.indexOf(a))throw new e("Invalid request method");this[D]=a;if(b.mode&&-1===va.indexOf(b.mode))throw new e("Invalid request mode");this[t]=b.mode||this[t]||"no-cors";if("no-cors"===this[t]){if(-1===wa.indexOf(this[D]))throw new e("Invalid request method for no-cors");if(""!==this[I])throw new e("Request integrity data is not allowed with no-cors");}if("same-origin"!==this[t]&&"only-if-cached"===
+this[G])throw new e("Request mode must be same-origin for only-if-cached");this[N]=b.redirect||this[N]||"follow";if(-1===xa.indexOf(this[N]))throw new e("Invalid request redirect mode");this[x]="no-cors"===this[t]?L(l,ka):L(l,ia);if(("GET"===this[D]||"HEAD"===this[D])&&d)throw new e("Request body is not allowed for GET or HEAD");"signal"in b&&(f=b.signal);f&&this[F].follow(f);this._initBody(d)}function ya(a,b){var c=L(void 0,b);a.replace(/\r?\n[\t ]+/g," ").split(/\r?\n/).forEach(function(d){var l=
+d.split(":");if(d=l.shift().trim())l=l.join(":").trim(),c.append(d,l)});return c}function u(a,b){b||(b={});this[Q]="default";this[y]="status"in b?b.status:200;if(200>this[y]||599<this[y])throw new aa("Invalid response status");this[ba]=200<=this[y]&&300>this[y];if("statusText"in b){var c=b.statusText;for(var d=0,l=c.length,f;d<l;d++)if(f=c.charCodeAt(d),9!==f&&(32>f||255<f||127===f))throw e("Invalid response status text");}else c="OK";this[R]=c;this[x]=L(b.headers,S);this[C]=b.url||"";if(a&&-1<za.indexOf(this[y]))throw new e("Response body is not allowed with a null body status");
+this[E]=b.is_aborted||!1;this._initBody(a)}if(!h.fetch){var K=h.Array,Z=h.ArrayBuffer,oa=h.Object.create,W=h.Object.defineProperties,k=h.Symbol,Aa=k.iterator,P=h.Map,aa=h.RangeError,e=h.TypeError,v=h.Uint8Array,z=h.Promise,V=h.ReadableStream,ca=h.ReadableStreamTee,ra=h.IsReadableStreamDisturbed,pa=h.IsReadableStreamLocked,r=k("body"),U=k("bodyUsed"),G=k("cache"),H=k("credentials"),A=k("guardCallback"),x=k("headers"),I=k("integrity"),p=k("map"),D=k("method"),t=k("mode"),ba=k("ok"),N=k("redirect"),
+y=k("status"),R=k("statusText"),Q=k("type"),C=k("url"),E=k("is_aborted"),F=k("signal"),ja="accept-charset accept-encoding access-control-request-headers access-control-request-method connection content-length cookie cookie2 date dnt expect host keep-alive origin referer te trailer transfer-encoding upgrade via".split(" "),na=["set-cookie","set-cookie2"],la=["accept","accept-language","content-language"],ma=["application/x-www-form-urlencoded","multipart/form-data","text/plain"],sa="default no-store reload no-cache force-cache only-if-cached".split(" "),
+ta=["omit","same-origin","include"],ua="DELETE GET HEAD OPTIONS POST PUT".split(" "),wa=["GET","HEAD","POST"],va=["same-origin","no-cors","cors"],xa=["follow","error","manual"],za=[101,204,205,304],Ba=[301,302,303,307,308],Ca="[object Int8Array];[object Uint8Array];[object Uint8ClampedArray];[object Int16Array];[object Uint16Array];[object Int32Array];[object Uint32Array];[object Float32Array];[object Float64Array]".split(";"),qa=Z.isView||function(a){return a&&-1<Ca.indexOf(Object.prototype.toString.call(a))};
+n.prototype.append=function(a,b){if(2!==arguments.length)throw e("Invalid parameters to append");a=J(a);b=X(b);this[A](a,b)||(this[p].has(a)?this[p].set(a,this[p].get(a)+", "+b):this[p].set(a,b))};n.prototype["delete"]=function(a){if(1!==arguments.length)throw e("Invalid parameters to delete");this[A](a,"invalid")||this[p].delete(J(a))};n.prototype.get=function(a){if(1!==arguments.length)throw e("Invalid parameters to get");a=J(a);var b=this[p].get(a);return void 0!==b?b:null};n.prototype.has=function(a){if(1!==
+arguments.length)throw e("Invalid parameters to has");return this[p].has(J(a))};n.prototype.set=function(a,b){if(2!==arguments.length)throw e("Invalid parameters to set");a=J(a);b=X(b);this[A](a,b)||this[p].set(a,b)};n.prototype.forEach=function(a,b){var c=this;K.from(this[p].entries()).sort().forEach(function(d){a.call(b,d[1],d[0],c)})};n.prototype.keys=function(){return(new P(K.from(this[p].entries()).sort())).keys()};n.prototype.values=function(){return(new P(K.from(this[p].entries()).sort())).values()};
+n.prototype.entries=function(){return(new P(K.from(this[p].entries()).sort())).entries()};n.prototype[Aa]=n.prototype.entries;B.prototype.clone=function(){var a=null;null!==this[r]&&(a=ca(this[r],!0),this[r]=a[0],a=a[1]);return new B(this,{cloneBody:a,signal:this[F]})};W(B.prototype,{cache:{get:function(){return this[G]}},credentials:{get:function(){return this[H]}},headers:{get:function(){return this[x]}},integrity:{get:function(){return this[I]}},method:{get:function(){return this[D]}},mode:{get:function(){return this[t]}},
+redirect:{get:function(){return this[N]}},url:{get:function(){return this[C]}},signal:{get:function(){return this[F]}}});Y.call(B.prototype);Y.call(u.prototype);u.prototype.clone=function(){var a=null;null!==this[r]&&(a=ca(this[r],!0),this[r]=a[0],a=a[1]);return new u(a,{status:this[y],statusText:this[R],headers:L(this[x],S),url:this[C],is_aborted:this[E]})};W(u.prototype,{headers:{get:function(){return this[x]}},ok:{get:function(){return this[ba]}},status:{get:function(){return this[y]}},statusText:{get:function(){return this[R]}},
+type:{get:function(){return this[Q]}},url:{get:function(){return this[C]}}});u.error=function(){var a=new u(null);a[x][A]=fa;a[Q]="error";a[y]=0;a[R]="";return a};u.redirect=function(a,b){if(!FetchInternal.isUrlValid(a,!0))throw new e("Invalid URL for response redirect");void 0===b&&(b=302);if(-1===Ba.indexOf(b))throw new aa("Invalid status code for response redirect");return new u(null,{status:b,headers:{location:a}})};h.Headers=n;h.Request=B;h.Response=u;h.fetch=function(a,b){return new z(function(c,
+d){var l=!1,f=!1,q=new B(a,b),g=new XMLHttpRequest,w=null;if(q.signal.aborted)return d(new DOMException("Aborted","AbortError"));var M=new V({start:function(m){w=m},cancel:function(m){l=!0;g.abort()}}),Da=function(){if(!l){l=!0;M.cancel();if(w)try{ReadableStreamDefaultControllerError(w,new DOMException("Aborted","AbortError"))}catch(m){}setTimeout(function(){try{g.abort()}catch(m){}},0)}};g.onload=function(){w.close()};g.onreadystatechange=function(){if(g.readyState===g.HEADERS_RECEIVED){var m={status:g.status,
+statusText:g.statusText,headers:ya(g.getAllResponseHeaders()||"",S)};m.url="responseURL"in g?g.responseURL:m.headers.get("X-Request-URL");try{var O=new u(M,m);q[F].addEventListener("abort",function(){O[E]=!0;Da();d(new DOMException("Aborted","AbortError"))});O[Q]=f?"cors":"basic";c(O)}catch(Ea){d(Ea)}}};g.onerror=function(){w.error(new e("Network request failed"));d(new e("Network request failed"))};g.ontimeout=function(){w.error(new e("Network request failed"));d(new e("Network request failed"))};
+g.open(q.method,q.url,!0);"include"===q.credentials&&(g.withCredentials=!0);q.headers.forEach(function(m,O){g.setRequestHeader(O,m)});var da=function(m){l||w.enqueue(m)},ea=function(m){f=m};null===q.body?g.fetch(da,ea,null):T(q).then(function(m){g.fetch(da,ea,m)})})};h.fetch.polyfill=!0}})(this);
\ No newline at end of file
diff --git a/src/cobalt/fetch/fetch.js b/src/cobalt/fetch/fetch.js
index b5de929..8c8162b 100644
--- a/src/cobalt/fetch/fetch.js
+++ b/src/cobalt/fetch/fetch.js
@@ -434,7 +434,11 @@
} else if (ArrayBuffer.prototype.isPrototypeOf(data)) {
controller.enqueue(new Uint8Array(data.slice(0)))
} else if (isArrayBufferView(data)) {
- controller.enqueue(new Uint8Array(data.buffer.slice(0)))
+ // View as bytes
+ const asBytes = new Uint8Array(data.buffer);
+ // slice and copy
+ var byteSlice = Uint8Array.from(asBytes.slice(data.byteOffset, data.byteLength + 1));
+ controller.enqueue(byteSlice);
} else if (data instanceof Blob) {
controller.enqueue(new Uint8Array(FetchInternal.blobToArrayBuffer(data)))
} else {
@@ -529,6 +533,7 @@
init.cloneBody === undefined
init = init || {}
var body = init.body || init.cloneBody
+ if(init.body === '') body = '';
var headersInit = init.headers
// AbortSignal cannot be constructed directly, so create a temporary
diff --git a/src/cobalt/h5vcc/h5vcc_updater.cc b/src/cobalt/h5vcc/h5vcc_updater.cc
index 4b7a171..bebd3b0 100644
--- a/src/cobalt/h5vcc/h5vcc_updater.cc
+++ b/src/cobalt/h5vcc/h5vcc_updater.cc
@@ -33,7 +33,7 @@
if (updater_module_->GetUpdaterChannel().compare(channel) != 0 &&
updater_module_->IsChannelValid(channel)) {
updater_module_->SetUpdaterChannel(channel);
- updater_module_->MarkChannelChanged();
+ updater_module_->CompareAndSwapChannelChanged(0, 1);
updater_module_->RunUpdateCheck();
}
}
diff --git a/src/cobalt/layout/paragraph.cc b/src/cobalt/layout/paragraph.cc
index 55ccd1e..a18aecb 100644
--- a/src/cobalt/layout/paragraph.cc
+++ b/src/cobalt/layout/paragraph.cc
@@ -125,17 +125,22 @@
return start_position;
}
-bool Paragraph::FindBreakPosition(const scoped_refptr<dom::FontList>& used_font,
- int32 start_position, int32 end_position,
- LayoutUnit available_width,
- bool should_collapse_trailing_white_space,
- bool allow_overflow,
- Paragraph::BreakPolicy break_policy,
- int32* break_position,
- LayoutUnit* break_width) {
+bool Paragraph::FindBreakPosition(
+ BaseDirection direction, bool should_attempt_to_wrap,
+ const scoped_refptr<dom::FontList>& used_font, int32 start_position,
+ int32 end_position, LayoutUnit available_width,
+ bool should_collapse_trailing_white_space, bool allow_overflow,
+ Paragraph::BreakPolicy break_policy, int32* break_position,
+ LayoutUnit* break_width) {
DCHECK(is_closed_);
- *break_position = start_position;
+ DCHECK(direction == base_direction_);
+ if (AreInlineAndScriptDirectionsTheSame(direction, start_position) ||
+ should_attempt_to_wrap) {
+ *break_position = start_position;
+ } else {
+ *break_position = end_position;
+ }
*break_width = LayoutUnit();
// If overflow isn't allowed and there is no available width, then there is
@@ -165,9 +170,10 @@
// |break_width| will be updated with the position of the last available
// break position.
FindIteratorBreakPosition(
- used_font, line_break_iterator_, start_position, end_position,
- available_width, should_collapse_trailing_white_space,
- allow_normal_overflow, break_position, break_width);
+ direction, should_attempt_to_wrap, used_font, line_break_iterator_,
+ start_position, end_position, available_width,
+ should_collapse_trailing_white_space, allow_normal_overflow,
+ break_position, break_width);
}
// If break word is the break policy, attempt to break unbreakable "words" at
@@ -177,20 +183,39 @@
if (break_policy == kBreakPolicyBreakWord) {
// Only continue allowing overflow if the break position has not moved from
// start, meaning that no normal break positions were found.
- allow_overflow = allow_overflow && (*break_position == start_position);
+ if (AreInlineAndScriptDirectionsTheSame(direction, start_position) ||
+ should_attempt_to_wrap) {
+ allow_overflow = allow_overflow && (*break_position == start_position);
+ } else {
+ allow_overflow = allow_overflow && (*break_position == end_position);
+ }
// Find the last available break-word break position. |break_position| and
// |break_width| will be updated with the position of the last available
// break position. The search begins at the location of the last normal
// break position that fit within the available width.
- FindIteratorBreakPosition(
- used_font, character_break_iterator_, *break_position, end_position,
- available_width, false, allow_overflow, break_position, break_width);
+ if (AreInlineAndScriptDirectionsTheSame(direction, start_position) ||
+ should_attempt_to_wrap) {
+ FindIteratorBreakPosition(direction, should_attempt_to_wrap, used_font,
+ character_break_iterator_, *break_position,
+ end_position, available_width, false,
+ allow_overflow, break_position, break_width);
+ } else {
+ FindIteratorBreakPosition(direction, should_attempt_to_wrap, used_font,
+ character_break_iterator_, start_position,
+ *break_position, available_width, false,
+ allow_overflow, break_position, break_width);
+ }
}
// No usable break position was found if the break position has not moved
// from the start position.
- return *break_position > start_position;
+ if (AreInlineAndScriptDirectionsTheSame(direction, start_position) ||
+ should_attempt_to_wrap) {
+ return *break_position > start_position;
+ } else {
+ return *break_position < end_position;
+ }
}
int32 Paragraph::GetNextBreakPosition(int32 position,
@@ -268,6 +293,12 @@
return (GetBidiLevel(position) % 2) == 1;
}
+bool Paragraph::AreInlineAndScriptDirectionsTheSame(BaseDirection direction,
+ int32 position) const {
+ return ((direction == kLeftToRightBaseDirection && !IsRTL(position)) ||
+ (direction == kRightToLeftBaseDirection && IsRTL(position)));
+}
+
bool Paragraph::IsCollapsibleWhiteSpace(int32 position) const {
// Only check for the space character. Other collapsible white space
// characters will have already been converted into the space characters and
@@ -338,6 +369,7 @@
}
void Paragraph::FindIteratorBreakPosition(
+ BaseDirection direction, bool should_attempt_to_wrap,
const scoped_refptr<dom::FontList>& used_font,
icu::BreakIterator* const break_iterator, int32 start_position,
int32 end_position, LayoutUnit available_width,
@@ -347,19 +379,37 @@
// position. Continue until TryIncludeSegmentWithinAvailableWidth() returns
// false, indicating that no more segments can be included.
break_iterator->setText(unicode_text_);
- for (int32 segment_end = break_iterator->following(start_position);
- segment_end != icu::BreakIterator::DONE && segment_end < end_position;
- segment_end = break_iterator->next()) {
- if (!TryIncludeSegmentWithinAvailableWidth(
- used_font, *break_position, segment_end, available_width,
- should_collapse_trailing_white_space, &allow_overflow,
- break_position, break_width)) {
- break;
+ if (AreInlineAndScriptDirectionsTheSame(direction, start_position) ||
+ should_attempt_to_wrap) {
+ for (int32 segment_end = break_iterator->following(start_position);
+ segment_end != icu::BreakIterator::DONE && segment_end < end_position;
+ segment_end = break_iterator->next()) {
+ if (!TryIncludeSegmentWithinAvailableWidth(
+ direction, should_attempt_to_wrap, used_font, *break_position,
+ segment_end, available_width,
+ should_collapse_trailing_white_space, &allow_overflow,
+ break_position, break_width)) {
+ break;
+ }
+ }
+ } else {
+ for (int32 segment_begin = break_iterator->preceding(end_position);
+ segment_begin != icu::BreakIterator::DONE &&
+ segment_begin > start_position;
+ segment_begin = break_iterator->previous()) {
+ if (!TryIncludeSegmentWithinAvailableWidth(
+ direction, should_attempt_to_wrap, used_font, segment_begin,
+ *break_position, available_width,
+ should_collapse_trailing_white_space, &allow_overflow,
+ break_position, break_width)) {
+ break;
+ }
}
}
}
bool Paragraph::TryIncludeSegmentWithinAvailableWidth(
+ BaseDirection direction, bool should_attempt_to_wrap,
const scoped_refptr<dom::FontList>& used_font, int32 segment_start,
int32 segment_end, LayoutUnit available_width,
bool should_collapse_trailing_white_space, bool* allow_overflow,
@@ -388,7 +438,12 @@
return false;
}
- *break_position = segment_end;
+ if (AreInlineAndScriptDirectionsTheSame(direction, segment_start) ||
+ should_attempt_to_wrap) {
+ *break_position = segment_end;
+ } else {
+ *break_position = segment_start;
+ }
*break_width += segment_width;
if (*allow_overflow) {
diff --git a/src/cobalt/layout/paragraph.h b/src/cobalt/layout/paragraph.h
index 3feb5d8..d64233c 100644
--- a/src/cobalt/layout/paragraph.h
+++ b/src/cobalt/layout/paragraph.h
@@ -111,7 +111,8 @@
// substring coming before |break_position|.
//
// Returns false if no usable break position was found.
- bool FindBreakPosition(const scoped_refptr<dom::FontList>& used_font,
+ bool FindBreakPosition(BaseDirection direction, bool should_attempt_to_wrap,
+ const scoped_refptr<dom::FontList>& used_font,
int32 start_position, int32 end_position,
LayoutUnit available_width,
bool should_collapse_trailing_white_space,
@@ -136,6 +137,8 @@
int GetBidiLevel(int32 position) const;
bool IsRTL(int32 position) const;
+ bool AreInlineAndScriptDirectionsTheSame(BaseDirection direction,
+ int32 position) const;
bool IsCollapsibleWhiteSpace(int32 position) const;
bool GetNextRunPosition(int32 position, int32* next_run_position) const;
int32 GetTextEndPosition() const;
@@ -174,7 +177,9 @@
// that first overflowing segment will be included. The parameter
// |break_width| indicates the width of the portion of the substring coming
// before |break_position|.
- void FindIteratorBreakPosition(const scoped_refptr<dom::FontList>& used_font,
+ void FindIteratorBreakPosition(BaseDirection direction,
+ bool should_attempt_to_wrap,
+ const scoped_refptr<dom::FontList>& used_font,
icu::BreakIterator* const break_iterator,
int32 start_position, int32 end_position,
LayoutUnit available_width,
@@ -197,6 +202,7 @@
// of false does not guarantee that the segment was not included, but simply
// that no additional segments can be included.
bool TryIncludeSegmentWithinAvailableWidth(
+ BaseDirection direction, bool should_attempt_to_wrap,
const scoped_refptr<dom::FontList>& used_font, int32 start_position,
int32 end_position, LayoutUnit available_width,
bool should_collapse_trailing_white_space, bool* allow_overflow,
diff --git a/src/cobalt/layout/text_box.cc b/src/cobalt/layout/text_box.cc
index 4507080b..f1bd926 100644
--- a/src/cobalt/layout/text_box.cc
+++ b/src/cobalt/layout/text_box.cc
@@ -42,7 +42,9 @@
paragraph_(paragraph),
text_start_position_(text_start_position),
text_end_position_(text_end_position),
+ truncated_text_start_position_(text_start_position),
truncated_text_end_position_(text_end_position),
+ previous_truncated_text_start_position_(text_start_position),
previous_truncated_text_end_position_(text_end_position),
truncated_text_offset_from_left_(0),
used_font_(used_style_provider->GetUsedFontList(
@@ -237,12 +239,16 @@
}
void TextBox::DoPreEllipsisPlacementProcessing() {
+ previous_truncated_text_start_position_ = truncated_text_start_position_;
previous_truncated_text_end_position_ = truncated_text_end_position_;
+ truncated_text_start_position_ = text_start_position_;
truncated_text_end_position_ = text_end_position_;
}
void TextBox::DoPostEllipsisPlacementProcessing() {
- if (previous_truncated_text_end_position_ != truncated_text_end_position_) {
+ if (previous_truncated_text_start_position_ !=
+ truncated_text_start_position_ ||
+ previous_truncated_text_end_position_ != truncated_text_end_position_) {
InvalidateRenderTreeNodesOfBoxAndAncestors();
}
}
@@ -397,7 +403,7 @@
// color is animated, in which case it could become non-transparent.
if (used_color.a() > 0.0f || is_color_animated ||
text_shadow != cssom::KeywordValue::GetNone()) {
- int32 text_start_position = GetNonCollapsedTextStartPosition();
+ int32 text_start_position = GetVisibleTextStartPosition();
int32 text_length = GetVisibleTextLength();
scoped_refptr<render_tree::GlyphBuffer> glyph_buffer =
@@ -481,7 +487,12 @@
// If the ellipsis has already been placed, then the text is fully truncated
// by the ellipsis.
if (*is_placed) {
- truncated_text_end_position_ = text_start_position_;
+ if (paragraph_->AreInlineAndScriptDirectionsTheSame(base_direction,
+ text_start_position_)) {
+ truncated_text_end_position_ = text_start_position_;
+ } else {
+ truncated_text_start_position_ = text_end_position_;
+ }
return;
}
@@ -510,8 +521,8 @@
// text box. Otherwise, it can only appear after the first character
// (https://www.w3.org/TR/css3-ui/#propdef-text-overflow).
if (paragraph_->FindBreakPosition(
- used_font_, start_position, end_position, desired_content_offset,
- false, !(*is_placement_requirement_met),
+ base_direction, false, used_font_, start_position, end_position,
+ desired_content_offset, false, !(*is_placement_requirement_met),
Paragraph::kBreakPolicyBreakWord, &found_position, &found_offset)) {
// A usable break position was found. Calculate the placed offset using the
// the break position's distance from the content box's start edge. In the
@@ -525,7 +536,12 @@
} else {
*placed_offset = content_box_start_offset + found_offset;
}
- truncated_text_end_position_ = found_position;
+ if (paragraph_->AreInlineAndScriptDirectionsTheSame(base_direction,
+ start_position)) {
+ truncated_text_end_position_ = found_position;
+ } else {
+ truncated_text_start_position_ = found_position;
+ }
// An acceptable break position was not found. If the placement requirement
// was already met prior to this box, then the ellipsis doesn't require a
// character from this box to appear prior to its position, so simply place
@@ -533,7 +549,12 @@
} else if (is_placement_requirement_met) {
*placed_offset =
GetMarginBoxStartEdgeOffsetFromContainingBlock(base_direction);
- truncated_text_end_position_ = text_start_position_;
+ if (paragraph_->AreInlineAndScriptDirectionsTheSame(base_direction,
+ start_position)) {
+ truncated_text_end_position_ = text_start_position_;
+ } else {
+ truncated_text_start_position_ = text_end_position_;
+ }
// The placement requirement has not already been met. Given that an
// acceptable break position was not found within the text, the ellipsis can
// only be placed at the end edge of the box.
@@ -603,7 +624,8 @@
// fits within the available width. Overflow is never allowed.
LayoutUnit wrap_width;
if (!paragraph_->FindBreakPosition(
- used_font_, start_position, text_end_position_, available_width,
+ paragraph_->base_direction(), true, used_font_, start_position,
+ text_end_position_, available_width,
should_collapse_trailing_white_space, false, break_policy,
&wrap_position, &wrap_width)) {
// If no break position is found, but the line existence is already
@@ -720,19 +742,24 @@
Paragraph::kVisualTextOrder);
}
+int32 TextBox::GetVisibleTextStartPosition() const {
+ return std::max(GetNonCollapsedTextStartPosition(),
+ truncated_text_start_position_);
+}
+
int32 TextBox::GetVisibleTextEndPosition() const {
return std::min(GetNonCollapsedTextEndPosition(),
truncated_text_end_position_);
}
int32 TextBox::GetVisibleTextLength() const {
- return GetVisibleTextEndPosition() - GetNonCollapsedTextStartPosition();
+ return GetVisibleTextEndPosition() - GetVisibleTextStartPosition();
}
bool TextBox::HasVisibleText() const { return GetVisibleTextLength() > 0; }
std::string TextBox::GetVisibleText() const {
- return paragraph_->RetrieveUtf8SubString(GetNonCollapsedTextStartPosition(),
+ return paragraph_->RetrieveUtf8SubString(GetVisibleTextStartPosition(),
GetVisibleTextEndPosition(),
Paragraph::kVisualTextOrder);
}
diff --git a/src/cobalt/layout/text_box.h b/src/cobalt/layout/text_box.h
index c2edcc6..855a0a2 100644
--- a/src/cobalt/layout/text_box.h
+++ b/src/cobalt/layout/text_box.h
@@ -133,6 +133,7 @@
int32 GetNonCollapsibleTextLength() const;
std::string GetNonCollapsibleText() const;
+ int32 GetVisibleTextStartPosition() const;
int32 GetVisibleTextEndPosition() const;
int32 GetVisibleTextLength() const;
bool HasVisibleText() const;
@@ -145,7 +146,7 @@
const scoped_refptr<Paragraph> paragraph_;
// The position within the paragraph where the text contained in this box
// begins.
- const int32 text_start_position_;
+ int32 text_start_position_;
// The position within the paragraph where the text contained in this box
// ends.
int32 text_end_position_;
@@ -154,11 +155,13 @@
// "Implementations must hide characters and atomic inline-level elements at
// the applicable edge(s) of the line as necessary to fit the ellipsis."
// https://www.w3.org/TR/css3-ui/#propdef-text-overflow
+ int32 truncated_text_start_position_;
int32 truncated_text_end_position_;
- // Tracking of the previous value of |truncated_text_end_position_|, which
+ // Tracking of the previous value of the truncated text position, which
// allows for determination of whether or not the value changed during
// ellipsis placement. When this occurs, the cached render tree nodes of this
// box and its ancestors are invalidated.
+ int32 previous_truncated_text_start_position_;
int32 previous_truncated_text_end_position_;
// The horizontal offset to apply to rendered text as a result of an ellipsis
// truncating the text. This value can be non-zero when the text box is in a
diff --git a/src/cobalt/layout/topmost_event_target.cc b/src/cobalt/layout/topmost_event_target.cc
index 6316a6b..df2cd6a 100644
--- a/src/cobalt/layout/topmost_event_target.cc
+++ b/src/cobalt/layout/topmost_event_target.cc
@@ -130,18 +130,45 @@
}
namespace {
+// Return the nearest common ancestor of previous_element and target_element
+scoped_refptr<dom::Element> GetNearestCommonAncestor(
+ scoped_refptr<dom::HTMLElement> previous_element,
+ scoped_refptr<dom::HTMLElement> target_element) {
+ scoped_refptr<dom::Element> nearest_common_ancestor;
+ if (previous_element == target_element) {
+ nearest_common_ancestor = target_element;
+ } else {
+ if (previous_element && target_element) {
+ // Find the nearest common ancestor, if there is any.
+ dom::Document* previous_document = previous_element->node_document();
+ // The elements only have a common ancestor if they are both in the same
+ // document.
+ if (previous_document &&
+ previous_document == target_element->node_document()) {
+ // The nearest ancestor of the target element that is already
+ // designated is the nearest common ancestor of it and the previous
+ // element.
+ nearest_common_ancestor = target_element;
+ while (nearest_common_ancestor &&
+ nearest_common_ancestor->AsHTMLElement() &&
+ !nearest_common_ancestor->AsHTMLElement()->IsDesignated()) {
+ nearest_common_ancestor = nearest_common_ancestor->parent_element();
+ }
+ }
+ }
+ }
+ return nearest_common_ancestor;
+}
+
void SendStateChangeLeaveEvents(
bool is_pointer_event, scoped_refptr<dom::HTMLElement> previous_element,
scoped_refptr<dom::HTMLElement> target_element,
+ scoped_refptr<dom::Element> nearest_common_ancestor,
dom::PointerEventInit* event_init) {
// Send enter/leave/over/out (status change) events when needed.
if (previous_element != target_element) {
const scoped_refptr<dom::Window>& view = event_init->view();
- // The enter/leave status change events apply to all ancestors up to the
- // nearest common ancestor between the previous and current element.
- scoped_refptr<dom::Element> nearest_common_ancestor;
-
// Send out and leave events.
if (previous_element) {
// LottiePlayer elements may change playback state.
@@ -149,24 +176,9 @@
previous_element->AsLottiePlayer()->OnUnHover();
}
- event_init->set_related_target(target_element);
- // Find the nearest common ancestor, if there is any.
dom::Document* previous_document = previous_element->node_document();
- if (previous_document) {
- if (target_element &&
- previous_document == target_element->node_document()) {
- // The nearest ancestor of the current element that is already
- // designated is the nearest common ancestor of it and the previous
- // element.
- nearest_common_ancestor = target_element;
- while (nearest_common_ancestor &&
- nearest_common_ancestor->AsHTMLElement() &&
- !nearest_common_ancestor->AsHTMLElement()->IsDesignated()) {
- nearest_common_ancestor = nearest_common_ancestor->parent_element();
- }
- }
- }
+ event_init->set_related_target(target_element);
if (is_pointer_event) {
previous_element->DispatchEvent(new dom::PointerEvent(
base::Tokens::pointerout(), view, *event_init));
@@ -209,15 +221,12 @@
void SendStateChangeEnterEvents(
bool is_pointer_event, scoped_refptr<dom::HTMLElement> previous_element,
scoped_refptr<dom::HTMLElement> target_element,
+ scoped_refptr<dom::Element> nearest_common_ancestor,
dom::PointerEventInit* event_init) {
// Send enter/leave/over/out (status change) events when needed.
if (previous_element != target_element) {
const scoped_refptr<dom::Window>& view = event_init->view();
- // The enter/leave status change events apply to all ancestors up to the
- // nearest common ancestor between the previous and current element.
- scoped_refptr<dom::Element> nearest_common_ancestor;
-
// Send over and enter events.
if (target_element) {
// LottiePlayer elements may change playback state.
@@ -399,8 +408,14 @@
scoped_refptr<dom::HTMLElement> previous_html_element(
previous_html_element_weak_);
+ // The enter/leave status change events apply to all ancestors up to the
+ // nearest common ancestor between the previous and current element.
+ scoped_refptr<dom::Element> nearest_common_ancestor(
+ GetNearestCommonAncestor(previous_html_element, target_element));
+
SendStateChangeLeaveEvents(pointer_event, previous_html_element,
- target_element, &event_init);
+ target_element, nearest_common_ancestor,
+ &event_init);
if (target_element) {
target_element->DispatchEvent(event);
@@ -424,26 +439,41 @@
}
}
- if (target_element && !is_touchpad_event) {
- // Send the click event if needed, which is not prevented by canceling the
- // pointerdown event.
- // https://www.w3.org/TR/uievents/#event-type-click
- // https://www.w3.org/TR/pointerevents/#compatibility-mapping-with-mouse-events
- if (event_init.button() == 0 &&
- ((mouse_event->type() == base::Tokens::pointerup()) ||
- (mouse_event->type() == base::Tokens::mouseup()))) {
+ if (event_init.button() == 0 &&
+ ((mouse_event->type() == base::Tokens::pointerup()) ||
+ (mouse_event->type() == base::Tokens::mouseup()))) {
+ // This is an 'up' event for the last pressed button indicating that no
+ // more buttons are pressed.
+ if (target_element && !is_touchpad_event) {
+ // Send the click event if needed, which is not prevented by canceling
+ // the pointerdown event.
+ // https://www.w3.org/TR/uievents/#event-type-click
+ // https://www.w3.org/TR/pointerevents/#compatibility-mapping-with-mouse-events
target_element->DispatchEvent(
new dom::MouseEvent(base::Tokens::click(), view, event_init));
}
+ if (target_element && (pointer_event->pointer_type() != "mouse")) {
+ // If it's not a mouse event, then releasing the last button means
+ // that there is no longer an indicated element.
+ dom::Document* document = target_element->node_document();
+ if (document) {
+ document->SetIndicatedElement(NULL);
+ target_element = NULL;
+ }
+ }
}
SendStateChangeEnterEvents(pointer_event, previous_html_element,
- target_element, &event_init);
+ target_element, nearest_common_ancestor,
+ &event_init);
if (target_element) {
- dom::Document* document = target_element->node_document();
- if (document) {
- document->SetIndicatedElement(target_element);
+ // Touchpad input never indicates document elements.
+ if (!is_touchpad_event) {
+ dom::Document* document = target_element->node_document();
+ if (document) {
+ document->SetIndicatedElement(target_element);
+ }
}
previous_html_element_weak_ = base::AsWeakPtr(target_element.get());
} else {
diff --git a/src/cobalt/layout_tests/testdata/bidi/bidi-paragraphs-should-maintain-proper-ordering-when-split-across-multiple-lines-expected.png b/src/cobalt/layout_tests/testdata/bidi/bidi-paragraphs-should-maintain-proper-ordering-when-split-across-multiple-lines-expected.png
index d0f9074..7e86a49 100644
--- a/src/cobalt/layout_tests/testdata/bidi/bidi-paragraphs-should-maintain-proper-ordering-when-split-across-multiple-lines-expected.png
+++ b/src/cobalt/layout_tests/testdata/bidi/bidi-paragraphs-should-maintain-proper-ordering-when-split-across-multiple-lines-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/bidi/bidi-paragraphs-should-maintain-proper-ordering-when-split-across-multiple-lines.html b/src/cobalt/layout_tests/testdata/bidi/bidi-paragraphs-should-maintain-proper-ordering-when-split-across-multiple-lines.html
index 71a614f..463fedd 100644
--- a/src/cobalt/layout_tests/testdata/bidi/bidi-paragraphs-should-maintain-proper-ordering-when-split-across-multiple-lines.html
+++ b/src/cobalt/layout_tests/testdata/bidi/bidi-paragraphs-should-maintain-proper-ordering-when-split-across-multiple-lines.html
@@ -30,8 +30,12 @@
لتد2ل3تت4دل5ت6د ط1لتدلنش 123456789 745 ط1لت
987 لتد 654</span>
</div>
+ <div class="containing-block" dir="rtl">
+ <span>12لتدل3ت dدلت4دلتد5ل6تد يabطا32ل Single Word
+ 1234 ط1لتدلنش ab12دلتد34cd ط1aلتد2ل 3تت489
+ 12 ل5ت6745 ط1لتدلنش ط1لaتدلتدتد ط11246 ط1abcd
+ لتد2ل3تت4دل5ت6د ط1لتدلنش 123456789 745 ط1لت
+ 987 لتد 654</span>
+ </div>
</body>
</html>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-fonts/5-2-use-system-fallback-if-no-matching-family-is-found-expected.png b/src/cobalt/layout_tests/testdata/css3-fonts/5-2-use-system-fallback-if-no-matching-family-is-found-expected.png
index 5f2548e..bf339a6 100644
--- a/src/cobalt/layout_tests/testdata/css3-fonts/5-2-use-system-fallback-if-no-matching-family-is-found-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-fonts/5-2-use-system-fallback-if-no-matching-family-is-found-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-fonts/color-emojis-should-render-properly-expected.png b/src/cobalt/layout_tests/testdata/css3-fonts/color-emojis-should-render-properly-expected.png
index 30e5ac4..e509aaa 100644
--- a/src/cobalt/layout_tests/testdata/css3-fonts/color-emojis-should-render-properly-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-fonts/color-emojis-should-render-properly-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-fonts/color-emojis-should-render-properly.html b/src/cobalt/layout_tests/testdata/css3-fonts/color-emojis-should-render-properly.html
index 22e2cab..e1e8f5b 100644
--- a/src/cobalt/layout_tests/testdata/css3-fonts/color-emojis-should-render-properly.html
+++ b/src/cobalt/layout_tests/testdata/css3-fonts/color-emojis-should-render-properly.html
@@ -29,7 +29,7 @@
<span>🙈🙉🙊👨👩🏃🐌</span>
<span>🐜💐🌲🍇🥝🍄🍔</span>
<span>🍟🍞🥞🌮🍣🍡🍨</span>
- <span class="bold-span">🌎🌚</span>
+ <span class="bold-span">🌎🌚🥰</span>
</div>
</body>
</html>
diff --git a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-clip-when-it-overflows-expected.png b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-clip-when-it-overflows-expected.png
index 27b72da..0bbe59c 100644
--- a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-clip-when-it-overflows-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-clip-when-it-overflows-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-ellipsize-each-line-that-overflows-expected.png b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-ellipsize-each-line-that-overflows-expected.png
index 164d112..2e89634 100644
--- a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-ellipsize-each-line-that-overflows-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-ellipsize-each-line-that-overflows-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-ellipsize-overflowing-first-word-expected.png b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-ellipsize-overflowing-first-word-expected.png
index 59aa7b9..4db6e7b 100644
--- a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-ellipsize-overflowing-first-word-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-ellipsize-overflowing-first-word-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-handle-transform-functions-via-matrix-expected.png b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-handle-transform-functions-via-matrix-expected.png
index 7c2215c..21d31da 100644
--- a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-handle-transform-functions-via-matrix-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-handle-transform-functions-via-matrix-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-handle-transform-functions-via-rotation-expected.png b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-handle-transform-functions-via-rotation-expected.png
index 4cfa868..85a1acb 100644
--- a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-handle-transform-functions-via-rotation-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-handle-transform-functions-via-rotation-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-not-ellipsize-first-character-on-line-expected.png b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-not-ellipsize-first-character-on-line-expected.png
index 27b72da..0bbe59c 100644
--- a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-not-ellipsize-first-character-on-line-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-not-ellipsize-first-character-on-line-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-properly-position-ellipsis-in-spans-with-margins-expected.png b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-properly-position-ellipsis-in-spans-with-margins-expected.png
index a69a33a..f71519f 100644
--- a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-properly-position-ellipsis-in-spans-with-margins-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-properly-position-ellipsis-in-spans-with-margins-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-retain-background-color-of-ellipsized-span-expected.png b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-retain-background-color-of-ellipsized-span-expected.png
index 1c4e931..ac84ae0 100644
--- a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-retain-background-color-of-ellipsized-span-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-retain-background-color-of-ellipsized-span-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-use-style-of-containing-block-expected.png b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-use-style-of-containing-block-expected.png
index 5d56a8b..e059ac1 100644
--- a/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-use-style-of-containing-block-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-ui/5-2-ellipsis-should-use-style-of-containing-block-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-ui/5-2-shaped-text-should-accurately-calculate-width-before-ellipsis-expected.png b/src/cobalt/layout_tests/testdata/css3-ui/5-2-shaped-text-should-accurately-calculate-width-before-ellipsis-expected.png
index 7b2d801..8b20b2a 100644
--- a/src/cobalt/layout_tests/testdata/css3-ui/5-2-shaped-text-should-accurately-calculate-width-before-ellipsis-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-ui/5-2-shaped-text-should-accurately-calculate-width-before-ellipsis-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-ui/5-2-text-overflow-ellipsis-should-display-ellipsis-on-overflow-when-overflow-is-hidden-expected.png b/src/cobalt/layout_tests/testdata/css3-ui/5-2-text-overflow-ellipsis-should-display-ellipsis-on-overflow-when-overflow-is-hidden-expected.png
index bf2da54..7fecf85 100644
--- a/src/cobalt/layout_tests/testdata/css3-ui/5-2-text-overflow-ellipsis-should-display-ellipsis-on-overflow-when-overflow-is-hidden-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-ui/5-2-text-overflow-ellipsis-should-display-ellipsis-on-overflow-when-overflow-is-hidden-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-ui/5-2-text-overflow-ellipsis-should-not-be-inherited-expected.png b/src/cobalt/layout_tests/testdata/css3-ui/5-2-text-overflow-ellipsis-should-not-be-inherited-expected.png
index bb3987f..a264063 100644
--- a/src/cobalt/layout_tests/testdata/css3-ui/5-2-text-overflow-ellipsis-should-not-be-inherited-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-ui/5-2-text-overflow-ellipsis-should-not-be-inherited-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/web-platform-tests/fetch/web_platform_tests.txt b/src/cobalt/layout_tests/testdata/web-platform-tests/fetch/web_platform_tests.txt
index 5c11ed1..72ab7d8 100644
--- a/src/cobalt/layout_tests/testdata/web-platform-tests/fetch/web_platform_tests.txt
+++ b/src/cobalt/layout_tests/testdata/web-platform-tests/fetch/web_platform_tests.txt
@@ -97,12 +97,8 @@
api/request/request-cache-only-if-cached.html,DISABLE
api/request/request-cache-reload.html,DISABLE
api/request/request-clone.sub.html,PASS
-# Fails because Body only supports text, json, and arrayBuffer. See the
-# corresponding tests for Response which have been customized to test only
-# those types.
-api/request/request-consume.html,DISABLE
-# Fails because blob and formData are not supported.
-api/request/request-consume-empty.html,DISABLE
+api/request/request-consume.html,PASS
+api/request/request-consume-empty.html,PASS
# Disabled due to failing test fixture
api/request/request-disturbed.html,DISABLE
api/request/request-error.html,PASS
diff --git a/src/cobalt/media/base/shell_audio_bus.cc b/src/cobalt/media/base/audio_bus.cc
similarity index 87%
rename from src/cobalt/media/base/shell_audio_bus.cc
rename to src/cobalt/media/base/audio_bus.cc
index 5140d01..ea63e7a 100644
--- a/src/cobalt/media/base/shell_audio_bus.cc
+++ b/src/cobalt/media/base/audio_bus.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
#include <algorithm>
#include <limits>
@@ -24,20 +24,17 @@
namespace {
-typedef ShellAudioBus::StorageType StorageType;
-typedef ShellAudioBus::SampleType SampleType;
+typedef AudioBus::StorageType StorageType;
+typedef AudioBus::SampleType SampleType;
const float kFloat32ToInt16Factor = 32768.f;
-inline void ConvertSample(ShellAudioBus::SampleType src_type,
- const uint8* src_ptr,
- ShellAudioBus::SampleType dest_type,
- uint8* dest_ptr) {
+inline void ConvertSample(AudioBus::SampleType src_type, const uint8* src_ptr,
+ AudioBus::SampleType dest_type, uint8* dest_ptr) {
if (src_type == dest_type) {
- SbMemoryCopy(
- dest_ptr, src_ptr,
- src_type == ShellAudioBus::kInt16 ? sizeof(int16) : sizeof(float));
- } else if (src_type == ShellAudioBus::kFloat32) {
+ SbMemoryCopy(dest_ptr, src_ptr,
+ src_type == AudioBus::kInt16 ? sizeof(int16) : sizeof(float));
+ } else if (src_type == AudioBus::kFloat32) {
float sample_in_float = *reinterpret_cast<const float*>(src_ptr);
int32 sample_in_int32 =
static_cast<int32>(sample_in_float * kFloat32ToInt16Factor);
@@ -78,8 +75,8 @@
} // namespace
-ShellAudioBus::ShellAudioBus(size_t channels, size_t frames,
- SampleType sample_type, StorageType storage_type)
+AudioBus::AudioBus(size_t channels, size_t frames, SampleType sample_type,
+ StorageType storage_type)
: channels_(channels),
frames_(frames),
sample_type_(sample_type),
@@ -106,7 +103,7 @@
}
}
-ShellAudioBus::ShellAudioBus(size_t frames, const std::vector<float*>& samples)
+AudioBus::AudioBus(size_t frames, const std::vector<float*>& samples)
: channels_(samples.size()),
frames_(frames),
sample_type_(kFloat32),
@@ -119,7 +116,7 @@
}
}
-ShellAudioBus::ShellAudioBus(size_t channels, size_t frames, float* samples)
+AudioBus::AudioBus(size_t channels, size_t frames, float* samples)
: channels_(channels),
frames_(frames),
sample_type_(kFloat32),
@@ -129,7 +126,7 @@
channel_data_.push_back(reinterpret_cast<uint8*>(samples));
}
-ShellAudioBus::ShellAudioBus(size_t frames, const std::vector<int16*>& samples)
+AudioBus::AudioBus(size_t frames, const std::vector<int16*>& samples)
: channels_(samples.size()),
frames_(frames),
sample_type_(kInt16),
@@ -142,7 +139,7 @@
}
}
-ShellAudioBus::ShellAudioBus(size_t channels, size_t frames, int16* samples)
+AudioBus::AudioBus(size_t channels, size_t frames, int16* samples)
: channels_(channels),
frames_(frames),
sample_type_(kInt16),
@@ -152,7 +149,7 @@
channel_data_.push_back(reinterpret_cast<uint8*>(samples));
}
-size_t ShellAudioBus::GetSampleSizeInBytes() const {
+size_t AudioBus::GetSampleSizeInBytes() const {
if (sample_type_ == kInt16) {
return sizeof(int16);
}
@@ -160,29 +157,29 @@
return sizeof(float);
}
-const uint8* ShellAudioBus::interleaved_data() const {
+const uint8* AudioBus::interleaved_data() const {
DCHECK_EQ(storage_type_, kInterleaved);
return channel_data_[0];
}
-const uint8* ShellAudioBus::planar_data(size_t channel) const {
+const uint8* AudioBus::planar_data(size_t channel) const {
DCHECK_LT(channel, channels_);
DCHECK_EQ(storage_type_, kPlanar);
return channel_data_[channel];
}
-uint8* ShellAudioBus::interleaved_data() {
+uint8* AudioBus::interleaved_data() {
DCHECK_EQ(storage_type_, kInterleaved);
return channel_data_[0];
}
-uint8* ShellAudioBus::planar_data(size_t channel) {
+uint8* AudioBus::planar_data(size_t channel) {
DCHECK_LT(channel, channels_);
DCHECK_EQ(storage_type_, kPlanar);
return channel_data_[channel];
}
-void ShellAudioBus::ZeroFrames(size_t start_frame, size_t end_frame) {
+void AudioBus::ZeroFrames(size_t start_frame, size_t end_frame) {
DCHECK_LE(start_frame, end_frame);
DCHECK_LE(end_frame, frames_);
end_frame = std::min(end_frame, frames_);
@@ -201,7 +198,7 @@
}
}
-void ShellAudioBus::Assign(const ShellAudioBus& source) {
+void AudioBus::Assign(const AudioBus& source) {
DCHECK_EQ(channels_, source.channels_);
if (channels_ != source.channels_) {
ZeroAllFrames();
@@ -232,8 +229,8 @@
}
}
-void ShellAudioBus::Assign(const ShellAudioBus& source,
- const std::vector<float>& matrix) {
+void AudioBus::Assign(const AudioBus& source,
+ const std::vector<float>& matrix) {
DCHECK_EQ(channels() * source.channels(), matrix.size());
DCHECK_EQ(sample_type_, kFloat32);
DCHECK_EQ(source.sample_type_, kFloat32);
@@ -258,7 +255,7 @@
}
template <StorageType SourceStorageType, StorageType DestStorageType>
-void ShellAudioBus::MixFloatSamples(const ShellAudioBus& source) {
+void AudioBus::MixFloatSamples(const AudioBus& source) {
const size_t frames = std::min(frames_, source.frames_);
if (SourceStorageType == DestStorageType) {
@@ -284,7 +281,7 @@
}
template <StorageType SourceStorageType, StorageType DestStorageType>
-void ShellAudioBus::MixInt16Samples(const ShellAudioBus& source) {
+void AudioBus::MixInt16Samples(const AudioBus& source) {
const size_t frames = std::min(frames_, source.frames_);
if (SourceStorageType == DestStorageType) {
@@ -318,7 +315,7 @@
}
}
-void ShellAudioBus::Mix(const ShellAudioBus& source) {
+void AudioBus::Mix(const AudioBus& source) {
DCHECK_EQ(channels_, source.channels_);
DCHECK_EQ(sample_type_, source.sample_type_);
@@ -359,8 +356,7 @@
}
}
-void ShellAudioBus::Mix(const ShellAudioBus& source,
- const std::vector<float>& matrix) {
+void AudioBus::Mix(const AudioBus& source, const std::vector<float>& matrix) {
DCHECK_EQ(channels() * source.channels(), matrix.size());
DCHECK_EQ(sample_type_, source.sample_type_);
@@ -411,7 +407,7 @@
}
}
-uint8* ShellAudioBus::GetSamplePtr(size_t channel, size_t frame) {
+uint8* AudioBus::GetSamplePtr(size_t channel, size_t frame) {
DCHECK_LT(channel, channels_);
DCHECK_LT(frame, frames_);
@@ -423,7 +419,7 @@
}
}
-const uint8* ShellAudioBus::GetSamplePtr(size_t channel, size_t frame) const {
+const uint8* AudioBus::GetSamplePtr(size_t channel, size_t frame) const {
DCHECK_LT(channel, channels_);
DCHECK_LT(frame, frames_);
diff --git a/src/cobalt/media/base/shell_audio_bus.h b/src/cobalt/media/base/audio_bus.h
similarity index 85%
rename from src/cobalt/media/base/shell_audio_bus.h
rename to src/cobalt/media/base/audio_bus.h
index cdd4668..2b4c369 100644
--- a/src/cobalt/media/base/shell_audio_bus.h
+++ b/src/cobalt/media/base/audio_bus.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_MEDIA_BASE_SHELL_AUDIO_BUS_H_
-#define COBALT_MEDIA_BASE_SHELL_AUDIO_BUS_H_
+#ifndef COBALT_MEDIA_BASE_AUDIO_BUS_H_
+#define COBALT_MEDIA_BASE_AUDIO_BUS_H_
#include <memory>
#include <vector>
@@ -37,11 +37,11 @@
// second of such audio contains 48000 frames (96000 samples).
// Note: This class doesn't do endianness conversions. It assumes that all data
// is in the correct endianness.
-class COBALT_EXPORT ShellAudioBus {
+class COBALT_EXPORT AudioBus {
public:
// Guaranteed alignment of each channel's data; use 64-byte alignment so it
// satisfies all our current platforms. Note that this is only used for
- // buffers that are allocated and owned by the ShellAudioBus. We don't
+ // buffers that are allocated and owned by the AudioBus. We don't
// enforce alignment for the buffers passed in and extra caution should be
// taken if they are used as hardware buffer.
static const size_t kChannelAlignmentInBytes = 64;
@@ -50,12 +50,12 @@
enum StorageType { kInterleaved, kPlanar };
- ShellAudioBus(size_t channels, size_t frames, SampleType sample_type,
- StorageType storage_type);
- ShellAudioBus(size_t frames, const std::vector<float*>& samples);
- ShellAudioBus(size_t channels, size_t frames, float* samples);
- ShellAudioBus(size_t frames, const std::vector<int16*>& samples);
- ShellAudioBus(size_t channels, size_t frames, int16* samples);
+ AudioBus(size_t channels, size_t frames, SampleType sample_type,
+ StorageType storage_type);
+ AudioBus(size_t frames, const std::vector<float*>& samples);
+ AudioBus(size_t channels, size_t frames, float* samples);
+ AudioBus(size_t frames, const std::vector<int16*>& samples);
+ AudioBus(size_t channels, size_t frames, int16* samples);
size_t channels() const { return channels_; }
size_t frames() const { return frames_; }
@@ -84,7 +84,7 @@
// conversion between different sample types and storage types. When source
// has less frames than the destination object, it will only copy these frames
// and will not fill the rest frames in our buffer with 0.
- void Assign(const ShellAudioBus& source);
+ void Assign(const AudioBus& source);
// The same as the above function except that this function also does mixing.
// |matrix| is a |dest.channels()| row * |source.channels()| column matrix in
@@ -96,14 +96,14 @@
// + source.sample[source.channels() - 1][frame] *
// matrix[channels() * source.channels() + source.channels() - 1];
// Note: Both objects must have storage type of kFloat32.
- void Assign(const ShellAudioBus& source, const std::vector<float>& matrix);
+ void Assign(const AudioBus& source, const std::vector<float>& matrix);
// The following functions are the same as the Assign() functions except that
// they add the calculated samples to the target samples instead of replacing
// the target samples with the calculated samples.
// Note: Both objects must have storage type of kFloat32.
- void Mix(const ShellAudioBus& source);
- void Mix(const ShellAudioBus& source, const std::vector<float>& matrix);
+ void Mix(const AudioBus& source);
+ void Mix(const AudioBus& source, const std::vector<float>& matrix);
public:
// The .*ForTypes? functions below are optimized versions that assume what
@@ -134,10 +134,10 @@
}
template <StorageType SourceStorageType, StorageType DestStorageType>
- void MixFloatSamples(const ShellAudioBus& source);
+ void MixFloatSamples(const AudioBus& source);
template <StorageType SourceStorageType, StorageType DestStorageType>
- void MixInt16Samples(const ShellAudioBus& source);
+ void MixInt16Samples(const AudioBus& source);
private:
void SetFloat32Sample(size_t channel, size_t frame, float sample) {
@@ -160,10 +160,10 @@
SampleType sample_type_;
StorageType storage_type_;
- DISALLOW_COPY_AND_ASSIGN(ShellAudioBus);
+ DISALLOW_COPY_AND_ASSIGN(AudioBus);
};
} // namespace media
} // namespace cobalt
-#endif // COBALT_MEDIA_BASE_SHELL_AUDIO_BUS_H_
+#endif // COBALT_MEDIA_BASE_AUDIO_BUS_H_
diff --git a/src/cobalt/media/can_play_type_handler.h b/src/cobalt/media/can_play_type_handler.h
index 40d1ea6..00b94f1 100644
--- a/src/cobalt/media/can_play_type_handler.h
+++ b/src/cobalt/media/can_play_type_handler.h
@@ -25,9 +25,10 @@
class CanPlayTypeHandler {
public:
virtual ~CanPlayTypeHandler() {}
- virtual SbMediaSupportType CanPlayType(const std::string& mime_type,
- const std::string& key_system,
- bool is_progressive) const = 0;
+ virtual SbMediaSupportType CanPlayProgressive(
+ const std::string& mime_type) const = 0;
+ virtual SbMediaSupportType CanPlayAdaptive(
+ const std::string& mime_type, const std::string& key_system) const = 0;
virtual void SetDisabledMediaCodecs(const std::string& codecs) = 0;
protected:
diff --git a/src/cobalt/media/fetcher_buffered_data_source.cc b/src/cobalt/media/fetcher_buffered_data_source.cc
index 2409eb8..9eb25be 100644
--- a/src/cobalt/media/fetcher_buffered_data_source.cc
+++ b/src/cobalt/media/fetcher_buffered_data_source.cc
@@ -407,7 +407,7 @@
read_cb.Run(static_cast<int>(bytes_peeked));
// If we have a large buffer size, it could be ideal if we can keep sending
// small requests when the read offset is far from the beginning of the
- // buffer. However as the ShellDemuxer will cache many frames and the
+ // buffer. However as the ProgressiveDemuxer will cache many frames and the
// buffer we are using is usually small, we will just avoid sending requests
// here to make code simple.
return;
diff --git a/src/cobalt/media/filters/source_buffer_stream.cc b/src/cobalt/media/filters/source_buffer_stream.cc
index c4208ba..0d30352 100644
--- a/src/cobalt/media/filters/source_buffer_stream.cc
+++ b/src/cobalt/media/filters/source_buffer_stream.cc
@@ -736,7 +736,7 @@
size_t bytes_to_free = 0;
- int garbage_collection_duration_threshold_in_seconds =
+ int64_t garbage_collection_duration_threshold_in_seconds =
SbMediaGetBufferGarbageCollectionDurationThreshold() / kSbTimeSecond;
// Check if we're under or at the memory/duration limit.
const auto kGcDurationThresholdInMilliseconds =
diff --git a/src/cobalt/media/media.gyp b/src/cobalt/media/media.gyp
index bc1e422..4b31fc0 100644
--- a/src/cobalt/media/media.gyp
+++ b/src/cobalt/media/media.gyp
@@ -29,6 +29,8 @@
'media_module.cc',
'media_module.h',
+ 'base/audio_bus.cc',
+ 'base/audio_bus.h',
'base/audio_codecs.cc',
'base/audio_codecs.h',
'base/audio_decoder_config.cc',
@@ -90,10 +92,6 @@
'base/sbplayer_pipeline.cc',
'base/sbplayer_set_bounds_helper.cc',
'base/sbplayer_set_bounds_helper.h',
- 'base/shell_audio_bus.cc',
- 'base/shell_audio_bus.h',
- 'base/shell_data_source_reader.cc',
- 'base/shell_data_source_reader.h',
'base/starboard_player.cc',
'base/starboard_player.h',
'base/starboard_utils.cc',
@@ -125,20 +123,6 @@
'filters/h264_to_annex_b_bitstream_converter.h',
'filters/h265_parser.cc',
'filters/h265_parser.h',
- 'filters/shell_au.cc',
- 'filters/shell_au.h',
- 'filters/shell_avc_parser.cc',
- 'filters/shell_avc_parser.h',
- 'filters/shell_demuxer.cc',
- 'filters/shell_demuxer.h',
- 'filters/shell_mp4_map.cc',
- 'filters/shell_mp4_map.h',
- 'filters/shell_mp4_parser.cc',
- 'filters/shell_mp4_parser.h',
- 'filters/shell_parser.cc',
- 'filters/shell_parser.h',
- 'filters/shell_rbsp_stream.cc',
- 'filters/shell_rbsp_stream.h',
'filters/source_buffer_range.cc',
'filters/source_buffer_range.h',
'filters/source_buffer_state.cc',
@@ -216,6 +200,22 @@
'player/web_media_player_impl.h',
'player/web_media_player_proxy.cc',
'player/web_media_player_proxy.h',
+ 'progressive/avc_access_unit.cc',
+ 'progressive/avc_access_unit.h',
+ 'progressive/avc_parser.cc',
+ 'progressive/avc_parser.h',
+ 'progressive/data_source_reader.cc',
+ 'progressive/data_source_reader.h',
+ 'progressive/mp4_map.cc',
+ 'progressive/mp4_map.h',
+ 'progressive/mp4_parser.cc',
+ 'progressive/mp4_parser.h',
+ 'progressive/progressive_demuxer.cc',
+ 'progressive/progressive_demuxer.h',
+ 'progressive/progressive_parser.cc',
+ 'progressive/progressive_parser.h',
+ 'progressive/rbsp_stream.cc',
+ 'progressive/rbsp_stream.h',
],
'direct_dependent_settings': {
'include_dirs': [
@@ -240,9 +240,9 @@
'<(DEPTH)/testing/gtest.gyp:gtest',
],
'sources': [
- 'base/mock_shell_data_source_reader.h',
- 'filters/shell_mp4_map_unittest.cc',
- 'filters/shell_rbsp_stream_unittest.cc',
+ 'progressive/mock_data_source_reader.h',
+ 'progressive/mp4_map_unittest.cc',
+ 'progressive/rbsp_stream_unittest.cc',
],
'includes': [ '<(DEPTH)/cobalt/test/test.gypi' ],
},
diff --git a/src/cobalt/media/media_module.cc b/src/cobalt/media/media_module.cc
index e476a6f..82ba5c2 100644
--- a/src/cobalt/media/media_module.cc
+++ b/src/cobalt/media/media_module.cc
@@ -48,37 +48,27 @@
<< "\" from console/command line.";
}
- SbMediaSupportType CanPlayType(const std::string& mime_type,
- const std::string& key_system,
- bool is_progressive) const override {
- if (is_progressive) {
- // |mime_type| is something like:
- // video/mp4
- // video/webm
- // video/mp4; codecs="avc1.4d401e"
- // video/webm; codecs="vp9"
- // We do a rough pre-filter to ensure that only video/mp4 is supported as
- // progressive.
- if (SbStringFindString(mime_type.c_str(), "video/mp4") == 0 &&
- SbStringFindString(mime_type.c_str(), "application/x-mpegURL") == 0) {
- return kSbMediaSupportTypeNotSupported;
- }
+ SbMediaSupportType CanPlayProgressive(
+ const std::string& mime_type) const override {
+ // |mime_type| is something like:
+ // video/mp4
+ // video/webm
+ // video/mp4; codecs="avc1.4d401e"
+ // video/webm; codecs="vp9"
+ // We do a rough pre-filter to ensure that only video/mp4 is supported as
+ // progressive.
+ if (SbStringFindString(mime_type.c_str(), "video/mp4") == 0 &&
+ SbStringFindString(mime_type.c_str(), "application/x-mpegURL") == 0) {
+ return kSbMediaSupportTypeNotSupported;
}
- if (!disabled_media_codecs_.empty()) {
- auto mime_codecs = ExtractCodecs(mime_type);
- for (auto& disabled_codec : disabled_media_codecs_) {
- for (auto& mime_codec : mime_codecs) {
- if (mime_codec.find(disabled_codec) != std::string::npos) {
- LOG(INFO) << "Codec (" << mime_codec
- << ") is disabled via console/command line.";
- return kSbMediaSupportTypeNotSupported;
- }
- }
- }
- }
- SbMediaSupportType type =
- SbMediaCanPlayMimeAndKeySystem(mime_type.c_str(), key_system.c_str());
- return type;
+
+ return CanPlayType(mime_type, "");
+ }
+
+ SbMediaSupportType CanPlayAdaptive(
+ const std::string& mime_type,
+ const std::string& key_system) const override {
+ return CanPlayType(mime_type, key_system);
}
private:
@@ -107,6 +97,25 @@
return codecs;
}
+ SbMediaSupportType CanPlayType(const std::string& mime_type,
+ const std::string& key_system) const {
+ if (!disabled_media_codecs_.empty()) {
+ auto mime_codecs = ExtractCodecs(mime_type);
+ for (auto& disabled_codec : disabled_media_codecs_) {
+ for (auto& mime_codec : mime_codecs) {
+ if (mime_codec.find(disabled_codec) != std::string::npos) {
+ LOG(INFO) << "Codec (" << mime_codec
+ << ") is disabled via console/command line.";
+ return kSbMediaSupportTypeNotSupported;
+ }
+ }
+ }
+ }
+ SbMediaSupportType type =
+ SbMediaCanPlayMimeAndKeySystem(mime_type.c_str(), key_system.c_str());
+ return type;
+ }
+
// List of disabled media codecs that will be treated as unsupported.
std::vector<std::string> disabled_media_codecs_;
};
diff --git a/src/cobalt/media/player/web_media_player_impl.cc b/src/cobalt/media/player/web_media_player_impl.cc
index 6f18dc7..d5cfa6f 100644
--- a/src/cobalt/media/player/web_media_player_impl.cc
+++ b/src/cobalt/media/player/web_media_player_impl.cc
@@ -24,8 +24,8 @@
#include "cobalt/media/base/limits.h"
#include "cobalt/media/base/media_log.h"
#include "cobalt/media/filters/chunk_demuxer.h"
-#include "cobalt/media/filters/shell_demuxer.h"
#include "cobalt/media/player/web_media_player_proxy.h"
+#include "cobalt/media/progressive/progressive_demuxer.h"
#include "starboard/double.h"
#include "starboard/types.h"
@@ -292,8 +292,8 @@
is_local_source_ = !url.SchemeIs("http") && !url.SchemeIs("https");
progressive_demuxer_.reset(
- new ShellDemuxer(pipeline_thread_.task_runner(), buffer_allocator_,
- proxy_->data_source(), media_log_));
+ new ProgressiveDemuxer(pipeline_thread_.task_runner(), buffer_allocator_,
+ proxy_->data_source(), media_log_));
state_.is_progressive = true;
StartPipeline(progressive_demuxer_.get());
diff --git a/src/cobalt/media/filters/shell_au.cc b/src/cobalt/media/progressive/avc_access_unit.cc
similarity index 74%
rename from src/cobalt/media/filters/shell_au.cc
rename to src/cobalt/media/progressive/avc_access_unit.cc
index fadfadb..25ad24e 100644
--- a/src/cobalt/media/filters/shell_au.cc
+++ b/src/cobalt/media/progressive/avc_access_unit.cc
@@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "cobalt/media/filters/shell_au.h"
+#include "cobalt/media/progressive/avc_access_unit.h"
#include <algorithm>
#include "cobalt/media/base/decoder_buffer.h"
#include "cobalt/media/base/endian_util.h"
#include "cobalt/media/base/timestamp_constants.h"
-#include "cobalt/media/filters/shell_parser.h"
+#include "cobalt/media/progressive/progressive_parser.h"
namespace cobalt {
namespace media {
@@ -27,7 +27,7 @@
namespace {
bool ReadBytes(uint64 offset, size_t size, uint8* buffer,
- ShellDataSourceReader* reader) {
+ DataSourceReader* reader) {
if (reader->BlockingRead(offset, size, buffer) != size) {
DLOG(ERROR) << "unable to download AU";
return false;
@@ -36,7 +36,7 @@
}
bool ReadBytes(uint64 offset, size_t size, DecoderBuffer* decoder_buffer,
- uint64 decoder_buffer_offset, ShellDataSourceReader* reader) {
+ uint64 decoder_buffer_offset, DataSourceReader* reader) {
size_t buffer_index = 0;
auto& allocations = decoder_buffer->allocations();
while (size > 0) {
@@ -67,17 +67,17 @@
return true;
}
-// ==== ShellEndOfStreamAU ==================================================
+// ==== EndOfStreamAU ==================================================
-class ShellEndOfStreamAU : public ShellAU {
+class EndOfStreamAU : public AvcAccessUnit {
public:
- ShellEndOfStreamAU(Type type, TimeDelta timestamp)
+ EndOfStreamAU(Type type, TimeDelta timestamp)
: type_(type), timestamp_(timestamp), duration_(kInfiniteDuration) {}
private:
bool IsEndOfStream() const override { return true; }
bool IsValid() const override { return true; }
- bool Read(ShellDataSourceReader* reader, DecoderBuffer* buffer) override {
+ bool Read(DataSourceReader* reader, DecoderBuffer* buffer) override {
NOTREACHED();
return false;
}
@@ -102,20 +102,19 @@
TimeDelta duration_;
};
-// ==== ShellAudioAU =======================================================
+// ==== AudioAU =======================================================
-class ShellAudioAU : public ShellAU {
+class AudioAU : public AvcAccessUnit {
public:
- ShellAudioAU(uint64 offset, size_t size, size_t prepend_size,
- bool is_keyframe, TimeDelta timestamp, TimeDelta duration,
- ShellParser* parser);
+ AudioAU(uint64 offset, size_t size, size_t prepend_size, bool is_keyframe,
+ TimeDelta timestamp, TimeDelta duration, ProgressiveParser* parser);
private:
bool IsEndOfStream() const override { return false; }
bool IsValid() const override {
return offset_ != 0 && size_ != 0 && timestamp_ != kNoTimestamp;
}
- bool Read(ShellDataSourceReader* reader, DecoderBuffer* buffer) override;
+ bool Read(DataSourceReader* reader, DecoderBuffer* buffer) override;
Type GetType() const override { return DemuxerStream::AUDIO; }
bool IsKeyframe() const override { return is_keyframe_; }
bool AddPrepend() const override { return true; }
@@ -132,12 +131,12 @@
bool is_keyframe_;
TimeDelta timestamp_;
TimeDelta duration_;
- ShellParser* parser_;
+ ProgressiveParser* parser_;
};
-ShellAudioAU::ShellAudioAU(uint64 offset, size_t size, size_t prepend_size,
- bool is_keyframe, TimeDelta timestamp,
- TimeDelta duration, ShellParser* parser)
+AudioAU::AudioAU(uint64 offset, size_t size, size_t prepend_size,
+ bool is_keyframe, TimeDelta timestamp, TimeDelta duration,
+ ProgressiveParser* parser)
: offset_(offset),
size_(size),
prepend_size_(prepend_size),
@@ -146,7 +145,7 @@
duration_(duration),
parser_(parser) {}
-bool ShellAudioAU::Read(ShellDataSourceReader* reader, DecoderBuffer* buffer) {
+bool AudioAU::Read(DataSourceReader* reader, DecoderBuffer* buffer) {
DCHECK_LE(size_ + prepend_size_, buffer->data_size());
if (!ReadBytes(offset_, size_, buffer, prepend_size_, reader)) return false;
@@ -158,20 +157,20 @@
return true;
}
-// ==== ShellVideoAU =======================================================
+// ==== VideoAU =======================================================
-class ShellVideoAU : public ShellAU {
+class VideoAU : public AvcAccessUnit {
public:
- ShellVideoAU(uint64 offset, size_t size, size_t prepend_size,
- uint8 length_of_nalu_size, bool is_keyframe, TimeDelta timestamp,
- TimeDelta duration, ShellParser* parser);
+ VideoAU(uint64 offset, size_t size, size_t prepend_size,
+ uint8 length_of_nalu_size, bool is_keyframe, TimeDelta timestamp,
+ TimeDelta duration, ProgressiveParser* parser);
private:
bool IsEndOfStream() const override { return false; }
bool IsValid() const override {
return offset_ != 0 && size_ != 0 && timestamp_ != kNoTimestamp;
}
- bool Read(ShellDataSourceReader* reader, DecoderBuffer* buffer) override;
+ bool Read(DataSourceReader* reader, DecoderBuffer* buffer) override;
Type GetType() const override { return DemuxerStream::VIDEO; }
bool IsKeyframe() const override { return is_keyframe_; }
bool AddPrepend() const override { return is_keyframe_; }
@@ -193,13 +192,13 @@
bool is_keyframe_;
TimeDelta timestamp_;
TimeDelta duration_;
- ShellParser* parser_;
+ ProgressiveParser* parser_;
};
-ShellVideoAU::ShellVideoAU(uint64 offset, size_t size, size_t prepend_size,
- uint8 length_of_nalu_size, bool is_keyframe,
- TimeDelta timestamp, TimeDelta duration,
- ShellParser* parser)
+VideoAU::VideoAU(uint64 offset, size_t size, size_t prepend_size,
+ uint8 length_of_nalu_size, bool is_keyframe,
+ TimeDelta timestamp, TimeDelta duration,
+ ProgressiveParser* parser)
: offset_(offset),
size_(size),
prepend_size_(prepend_size),
@@ -212,7 +211,7 @@
CHECK_NE(length_of_nalu_size_, 3);
}
-bool ShellVideoAU::Read(ShellDataSourceReader* reader, DecoderBuffer* buffer) {
+bool VideoAU::Read(DataSourceReader* reader, DecoderBuffer* buffer) {
size_t au_left = size_; // bytes left in the AU
uint64 au_offset = offset_; // offset to read in the reader
size_t buf_left = buffer->data_size(); // bytes left in the buffer
@@ -280,33 +279,34 @@
} // namespace
-// ==== ShellAU ================================================================
+// ==== AvcAccessUnit
+// ================================================================
-ShellAU::ShellAU() {}
+AvcAccessUnit::AvcAccessUnit() {}
-ShellAU::~ShellAU() {}
+AvcAccessUnit::~AvcAccessUnit() {}
// static
-scoped_refptr<ShellAU> ShellAU::CreateEndOfStreamAU(DemuxerStream::Type type,
- TimeDelta timestamp) {
- return new ShellEndOfStreamAU(type, timestamp);
+scoped_refptr<AvcAccessUnit> AvcAccessUnit::CreateEndOfStreamAU(
+ DemuxerStream::Type type, TimeDelta timestamp) {
+ return new EndOfStreamAU(type, timestamp);
}
// static
-scoped_refptr<ShellAU> ShellAU::CreateAudioAU(
+scoped_refptr<AvcAccessUnit> AvcAccessUnit::CreateAudioAU(
uint64 offset, size_t size, size_t prepend_size, bool is_keyframe,
- TimeDelta timestamp, TimeDelta duration, ShellParser* parser) {
- return new ShellAudioAU(offset, size, prepend_size, is_keyframe, timestamp,
- duration, parser);
+ TimeDelta timestamp, TimeDelta duration, ProgressiveParser* parser) {
+ return new AudioAU(offset, size, prepend_size, is_keyframe, timestamp,
+ duration, parser);
}
// static
-scoped_refptr<ShellAU> ShellAU::CreateVideoAU(
+scoped_refptr<AvcAccessUnit> AvcAccessUnit::CreateVideoAU(
uint64 offset, size_t size, size_t prepend_size, uint8 length_of_nalu_size,
bool is_keyframe, TimeDelta timestamp, TimeDelta duration,
- ShellParser* parser) {
- return new ShellVideoAU(offset, size, prepend_size, length_of_nalu_size,
- is_keyframe, timestamp, duration, parser);
+ ProgressiveParser* parser) {
+ return new VideoAU(offset, size, prepend_size, length_of_nalu_size,
+ is_keyframe, timestamp, duration, parser);
}
} // namespace media
diff --git a/src/cobalt/media/filters/shell_au.h b/src/cobalt/media/progressive/avc_access_unit.h
similarity index 63%
rename from src/cobalt/media/filters/shell_au.h
rename to src/cobalt/media/progressive/avc_access_unit.h
index d6254e4..7c283e9 100644
--- a/src/cobalt/media/filters/shell_au.h
+++ b/src/cobalt/media/progressive/avc_access_unit.h
@@ -12,44 +12,44 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_MEDIA_FILTERS_SHELL_AU_H_
-#define COBALT_MEDIA_FILTERS_SHELL_AU_H_
+#ifndef COBALT_MEDIA_PROGRESSIVE_ACCESS_UNIT_H_
+#define COBALT_MEDIA_PROGRESSIVE_ACCESS_UNIT_H_
#include "base/memory/ref_counted.h"
#include "cobalt/media/base/demuxer_stream.h"
-#include "cobalt/media/base/shell_data_source_reader.h"
+#include "cobalt/media/progressive/data_source_reader.h"
namespace cobalt {
namespace media {
-class ShellParser;
+class ProgressiveParser;
static const int kAnnexBStartCodeSize = 4;
static const uint8_t kAnnexBStartCode[] = {0, 0, 0, 1};
-// The basic unit of currency between ShellDemuxer and ShellParser, the ShellAU
-// defines all needed information for a given AccessUnit (Frame) of encoded
-// media data.
-class ShellAU : public base::RefCountedThreadSafe<ShellAU> {
+// The basic unit of currency between ProgressiveDemuxer and ProgressiveParser,
+// the AvcAccessUnit defines all needed information for a given AvcAccessUnit
+// (Frame) of encoded media data.
+class AvcAccessUnit : public base::RefCountedThreadSafe<AvcAccessUnit> {
public:
typedef base::TimeDelta TimeDelta;
typedef DemuxerStream::Type Type;
- static scoped_refptr<ShellAU> CreateEndOfStreamAU(Type type,
- TimeDelta timestamp);
- static scoped_refptr<ShellAU> CreateAudioAU(
+ static scoped_refptr<AvcAccessUnit> CreateEndOfStreamAU(Type type,
+ TimeDelta timestamp);
+ static scoped_refptr<AvcAccessUnit> CreateAudioAU(
uint64 offset, size_t size, size_t prepend_size, bool is_keyframe,
- TimeDelta timestamp, TimeDelta duration, ShellParser* parser);
- static scoped_refptr<ShellAU> CreateVideoAU(
+ TimeDelta timestamp, TimeDelta duration, ProgressiveParser* parser);
+ static scoped_refptr<AvcAccessUnit> CreateVideoAU(
uint64 offset, size_t size, size_t prepend_size,
uint8 length_of_nalu_size, bool is_keyframe, TimeDelta timestamp,
- TimeDelta duration, ShellParser* parser);
+ TimeDelta duration, ProgressiveParser* parser);
virtual bool IsEndOfStream() const = 0;
virtual bool IsValid() const = 0;
// Read an AU from reader to buffer and also do all the necessary operations
// like prepending head to make it ready to decode.
- virtual bool Read(ShellDataSourceReader* reader, DecoderBuffer* buffer) = 0;
+ virtual bool Read(DataSourceReader* reader, DecoderBuffer* buffer) = 0;
virtual Type GetType() const = 0;
virtual bool IsKeyframe() const = 0;
virtual bool AddPrepend() const = 0;
@@ -63,13 +63,13 @@
virtual void SetTimestamp(TimeDelta timestamp) = 0;
protected:
- friend class base::RefCountedThreadSafe<ShellAU>;
+ friend class base::RefCountedThreadSafe<AvcAccessUnit>;
- ShellAU();
- virtual ~ShellAU();
+ AvcAccessUnit();
+ virtual ~AvcAccessUnit();
};
} // namespace media
} // namespace cobalt
-#endif // COBALT_MEDIA_FILTERS_SHELL_AU_H_
+#endif // COBALT_MEDIA_PROGRESSIVE_ACCESS_UNIT_H_
diff --git a/src/cobalt/media/filters/shell_avc_parser.cc b/src/cobalt/media/progressive/avc_parser.cc
similarity index 92%
rename from src/cobalt/media/filters/shell_avc_parser.cc
rename to src/cobalt/media/progressive/avc_parser.cc
index baca931..e08141a 100644
--- a/src/cobalt/media/filters/shell_avc_parser.cc
+++ b/src/cobalt/media/progressive/avc_parser.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "cobalt/media/filters/shell_avc_parser.h"
+#include "cobalt/media/progressive/avc_parser.h"
#include <limits>
#include <vector>
@@ -23,9 +23,9 @@
#include "cobalt/media/base/endian_util.h"
#include "cobalt/media/base/media_util.h"
#include "cobalt/media/base/video_types.h"
-#include "cobalt/media/filters/shell_au.h"
-#include "cobalt/media/filters/shell_rbsp_stream.h"
#include "cobalt/media/formats/mp4/aac.h"
+#include "cobalt/media/progressive/avc_access_unit.h"
+#include "cobalt/media/progressive/rbsp_stream.h"
#include "starboard/memory.h"
namespace cobalt {
@@ -36,19 +36,19 @@
// lower five bits of first byte in SPS should be 7
static const uint8 kSPSNALType = 7;
-ShellAVCParser::ShellAVCParser(scoped_refptr<ShellDataSourceReader> reader,
- const scoped_refptr<MediaLog>& media_log)
- : ShellParser(reader),
+AVCParser::AVCParser(scoped_refptr<DataSourceReader> reader,
+ const scoped_refptr<MediaLog>& media_log)
+ : ProgressiveParser(reader),
media_log_(media_log),
nal_header_size_(0),
video_prepend_size_(0) {
DCHECK(media_log);
}
-ShellAVCParser::~ShellAVCParser() {}
+AVCParser::~AVCParser() {}
-bool ShellAVCParser::Prepend(scoped_refptr<ShellAU> au,
- scoped_refptr<DecoderBuffer> buffer) {
+bool AVCParser::Prepend(scoped_refptr<AvcAccessUnit> au,
+ scoped_refptr<DecoderBuffer> buffer) {
// sanity-check inputs
if (!au || !buffer) {
NOTREACHED() << "bad input to Prepend()";
@@ -93,8 +93,7 @@
return true;
}
-bool ShellAVCParser::DownloadAndParseAVCConfigRecord(uint64 offset,
- uint32 size) {
+bool AVCParser::DownloadAndParseAVCConfigRecord(uint64 offset, uint32 size) {
if (size == 0) {
return false;
}
@@ -109,8 +108,8 @@
}
// static
-bool ShellAVCParser::ParseSPS(const uint8* sps, size_t sps_size,
- ShellSPSRecord* record_out) {
+bool AVCParser::ParseSPS(const uint8* sps, size_t sps_size,
+ SPSRecord* record_out) {
DCHECK(sps) << "no sps provided";
DCHECK(record_out) << "no output structure provided";
// first byte is NAL type id, check that it is SPS
@@ -119,7 +118,7 @@
return false;
}
// convert SPS NALU to RBSP stream
- ShellRBSPStream sps_rbsp(sps + 1, sps_size - 1);
+ RBSPStream sps_rbsp(sps + 1, sps_size - 1);
uint8 profile_idc = 0;
if (!sps_rbsp.ReadByte(&profile_idc)) {
DLOG(ERROR) << "failure reading profile_idc from sps RBSP";
@@ -294,7 +293,7 @@
return true;
}
-bool ShellAVCParser::ParseAVCConfigRecord(uint8* buffer, uint32 size) {
+bool AVCParser::ParseAVCConfigRecord(uint8* buffer, uint32 size) {
if (size < kAVCConfigMinSize) {
DLOG(ERROR) << base::StringPrintf("AVC config record bad size: %d", size);
return false;
@@ -392,7 +391,7 @@
}
}
// now we parse the valid SPS we extracted from byte stream earlier.
- ShellSPSRecord sps_record;
+ SPSRecord sps_record;
if (!ParseSPS(buffer + usable_sps_offset, usable_sps_size, &sps_record)) {
DLOG(WARNING) << "error parsing SPS";
return false;
@@ -409,8 +408,8 @@
buffer + usable_pps_offset, usable_pps_size);
}
-bool ShellAVCParser::BuildAnnexBPrepend(uint8* sps, uint32 sps_size, uint8* pps,
- uint32 pps_size) {
+bool AVCParser::BuildAnnexBPrepend(uint8* sps, uint32 sps_size, uint8* pps,
+ uint32 pps_size) {
// We will need to attach the sps and pps (if provided) to each keyframe
// video packet, with the AnnexB start code in front of each. Start with
// sps size and start code
@@ -445,7 +444,7 @@
return true;
}
-void ShellAVCParser::ParseAudioSpecificConfig(uint8 b0, uint8 b1) {
+void AVCParser::ParseAudioSpecificConfig(uint8 b0, uint8 b1) {
media::mp4::AAC aac;
std::vector<uint8> aac_config(2);
@@ -472,8 +471,8 @@
Unencrypted(), base::TimeDelta(), 0);
}
-size_t ShellAVCParser::CalculatePrependSize(DemuxerStream::Type type,
- bool is_keyframe) {
+size_t AVCParser::CalculatePrependSize(DemuxerStream::Type type,
+ bool is_keyframe) {
size_t prepend_size = 0;
if (type == DemuxerStream::VIDEO) {
bool needs_prepend = is_keyframe;
diff --git a/src/cobalt/media/filters/shell_avc_parser.h b/src/cobalt/media/progressive/avc_parser.h
similarity index 77%
rename from src/cobalt/media/filters/shell_avc_parser.h
rename to src/cobalt/media/progressive/avc_parser.h
index 758a7a2..e383bdf 100644
--- a/src/cobalt/media/filters/shell_avc_parser.h
+++ b/src/cobalt/media/progressive/avc_parser.h
@@ -12,13 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_MEDIA_FILTERS_SHELL_AVC_PARSER_H_
-#define COBALT_MEDIA_FILTERS_SHELL_AVC_PARSER_H_
+#ifndef COBALT_MEDIA_PROGRESSIVE_AVC_PARSER_H_
+#define COBALT_MEDIA_PROGRESSIVE_AVC_PARSER_H_
#include <vector>
#include "cobalt/media/base/media_log.h"
-#include "cobalt/media/filters/shell_parser.h"
+#include "cobalt/media/progressive/progressive_parser.h"
namespace cobalt {
namespace media {
@@ -29,27 +29,27 @@
static const int kAnnexBPrependMaxSize = 1024;
// while not an actual parser, provides shared functionality to both the
-// mp4 and flv parsers which derive from it. Implements part of ShellParser
-// while leaving the rest for its children.
-class ShellAVCParser : public ShellParser {
+// mp4 and flv parsers which derive from it. Implements part of
+// ProgressiveParser while leaving the rest for its children.
+class AVCParser : public ProgressiveParser {
public:
- explicit ShellAVCParser(scoped_refptr<ShellDataSourceReader> reader,
- const scoped_refptr<MediaLog>& media_log);
- virtual ~ShellAVCParser();
+ explicit AVCParser(scoped_refptr<DataSourceReader> reader,
+ const scoped_refptr<MediaLog>& media_log);
+ virtual ~AVCParser();
- struct ShellSPSRecord {
+ struct SPSRecord {
math::Size coded_size;
math::Rect visible_rect;
math::Size natural_size;
uint32 num_ref_frames;
};
static bool ParseSPS(const uint8* sps, size_t sps_size,
- ShellSPSRecord* record_out);
+ SPSRecord* record_out);
// GetNextAU we must pass on to FLV or MP4 children.
- virtual scoped_refptr<ShellAU> GetNextAU(DemuxerStream::Type type) = 0;
+ virtual scoped_refptr<AvcAccessUnit> GetNextAU(DemuxerStream::Type type) = 0;
// Prepends are common to all AVC/AAC containers so we can do this one here.
- bool Prepend(scoped_refptr<ShellAU> au,
+ bool Prepend(scoped_refptr<AvcAccessUnit> au,
scoped_refptr<DecoderBuffer> buffer) override;
protected:
@@ -77,4 +77,4 @@
} // namespace media
} // namespace cobalt
-#endif // COBALT_MEDIA_FILTERS_SHELL_AVC_PARSER_H_
+#endif // COBALT_MEDIA_PROGRESSIVE_AVC_PARSER_H_
diff --git a/src/cobalt/media/base/shell_data_source_reader.cc b/src/cobalt/media/progressive/data_source_reader.cc
similarity index 81%
rename from src/cobalt/media/base/shell_data_source_reader.cc
rename to src/cobalt/media/progressive/data_source_reader.cc
index 2c7c38f..fd4ff71 100644
--- a/src/cobalt/media/base/shell_data_source_reader.cc
+++ b/src/cobalt/media/progressive/data_source_reader.cc
@@ -12,16 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "cobalt/media/base/shell_data_source_reader.h"
+#include "cobalt/media/progressive/data_source_reader.h"
#include "starboard/types.h"
namespace cobalt {
namespace media {
-const int ShellDataSourceReader::kReadError = DataSource::kReadError;
+const int DataSourceReader::kReadError = DataSource::kReadError;
-ShellDataSourceReader::ShellDataSourceReader()
+DataSourceReader::DataSourceReader()
: data_source_(NULL),
blocking_read_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED),
@@ -29,15 +29,15 @@
read_has_failed_(false),
last_bytes_read_(0) {}
-ShellDataSourceReader::~ShellDataSourceReader() {}
+DataSourceReader::~DataSourceReader() {}
-void ShellDataSourceReader::SetDataSource(DataSource* data_source) {
+void DataSourceReader::SetDataSource(DataSource* data_source) {
DCHECK(data_source);
data_source_ = data_source;
}
// currently only single-threaded reads supported
-int ShellDataSourceReader::BlockingRead(int64 position, int size, uint8* data) {
+int DataSourceReader::BlockingRead(int64 position, int size, uint8* data) {
// read failures are unrecoverable, all subsequent reads will also fail
if (read_has_failed_) {
return kReadError;
@@ -57,7 +57,7 @@
}
data_source_->Read(
position, size, data,
- base::Bind(&ShellDataSourceReader::BlockingReadCompleted, this));
+ base::Bind(&DataSourceReader::BlockingReadCompleted, this));
}
// wait for callback on read completion
@@ -91,7 +91,7 @@
return total_bytes_read;
}
-void ShellDataSourceReader::Stop() {
+void DataSourceReader::Stop() {
if (data_source_) {
data_source_->Stop();
@@ -100,13 +100,13 @@
}
}
-void ShellDataSourceReader::BlockingReadCompleted(int bytes_read) {
+void DataSourceReader::BlockingReadCompleted(int bytes_read) {
last_bytes_read_ = bytes_read;
// wake up blocked thread
blocking_read_event_.Signal();
}
-int64 ShellDataSourceReader::FileSize() {
+int64 DataSourceReader::FileSize() {
if (file_size_ == -1) {
base::AutoLock auto_lock(lock_);
if (data_source_ && !data_source_->GetSize(&file_size_)) {
diff --git a/src/cobalt/media/base/shell_data_source_reader.h b/src/cobalt/media/progressive/data_source_reader.h
similarity index 85%
rename from src/cobalt/media/base/shell_data_source_reader.h
rename to src/cobalt/media/progressive/data_source_reader.h
index 2049a9d..c773083 100644
--- a/src/cobalt/media/base/shell_data_source_reader.h
+++ b/src/cobalt/media/progressive/data_source_reader.h
@@ -12,9 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_MEDIA_BASE_SHELL_DATA_SOURCE_READER_H_
-#define COBALT_MEDIA_BASE_SHELL_DATA_SOURCE_READER_H_
-
+#ifndef COBALT_MEDIA_PROGRESSIVE_DATA_SOURCE_READER_H_
+#define COBALT_MEDIA_PROGRESSIVE_DATA_SOURCE_READER_H_
#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/ref_counted.h"
@@ -32,12 +31,11 @@
// object is also the sole owner of a pointer to DataSource. If we want to add
// asynchronous reading to this object it will need its own thread and a
// callback queue.
-class ShellDataSourceReader
- : public base::RefCountedThreadSafe<ShellDataSourceReader> {
+class DataSourceReader : public base::RefCountedThreadSafe<DataSourceReader> {
public:
static const int kReadError;
- ShellDataSourceReader();
+ DataSourceReader();
virtual void SetDataSource(DataSource* data_source);
// Block the calling thread's message loop until read is complete.
@@ -53,8 +51,8 @@
virtual void Stop();
protected:
- friend class base::RefCountedThreadSafe<ShellDataSourceReader>;
- virtual ~ShellDataSourceReader();
+ friend class base::RefCountedThreadSafe<DataSourceReader>;
+ virtual ~DataSourceReader();
// blocking read callback
virtual void BlockingReadCompleted(int bytes_read);
@@ -69,4 +67,4 @@
} // namespace media
} // namespace cobalt
-#endif // COBALT_MEDIA_BASE_SHELL_DATA_SOURCE_READER_H_
+#endif // COBALT_MEDIA_PROGRESSIVE_DATA_SOURCE_READER_H_
diff --git a/src/cobalt/media/sandbox/shell_demuxer_fuzzer.cc b/src/cobalt/media/progressive/demuxer_fuzzer.cc
similarity index 78%
rename from src/cobalt/media/sandbox/shell_demuxer_fuzzer.cc
rename to src/cobalt/media/progressive/demuxer_fuzzer.cc
index 74d1e7e..ebd2766 100644
--- a/src/cobalt/media/sandbox/shell_demuxer_fuzzer.cc
+++ b/src/cobalt/media/progressive/demuxer_fuzzer.cc
@@ -25,7 +25,7 @@
#include "cobalt/media/sandbox/media_sandbox.h"
#include "media/base/bind_to_loop.h"
#include "media/base/pipeline_status.h"
-#include "media/filters/shell_demuxer.h"
+#include "media/progressive/progressive_demuxer.h"
namespace cobalt {
namespace media {
@@ -39,19 +39,20 @@
using ::media::DemuxerHost;
using ::media::DemuxerStream;
using ::media::PipelineStatus;
-using ::media::ShellDemuxer;
+using ::media::ProgressiveDemuxer;
-class ShellDemuxerFuzzer : DemuxerHost {
+class DemuxerFuzzer : DemuxerHost {
public:
- explicit ShellDemuxerFuzzer(const std::vector<uint8>& content)
+ explicit DemuxerFuzzer(const std::vector<uint8>& content)
: error_occurred_(false), eos_count_(0), stopped_(false) {
- demuxer_ = new ShellDemuxer(base::MessageLoop::current()->task_runner(),
- new InMemoryDataSource(content));
+ demuxer_ =
+ new ProgressiveDemuxer(base::MessageLoop::current()->task_runner(),
+ new InMemoryDataSource(content));
}
void Fuzz() {
demuxer_->Initialize(
- this, Bind(&ShellDemuxerFuzzer::InitializeCB, base::Unretained(this)));
+ this, Bind(&DemuxerFuzzer::InitializeCB, base::Unretained(this)));
// Check if there is any error or if both of the audio and video streams
// have reached eos.
@@ -59,7 +60,7 @@
base::RunLoop().RunUntilIdle();
}
- demuxer_->Stop(Bind(&ShellDemuxerFuzzer::StopCB, base::Unretained(this)));
+ demuxer_->Stop(Bind(&DemuxerFuzzer::StopCB, base::Unretained(this)));
while (!stopped_) {
base::RunLoop().RunUntilIdle();
@@ -101,10 +102,10 @@
error_occurred_ = true;
return;
}
- audio_stream->Read(BindToCurrentLoop(Bind(
- &ShellDemuxerFuzzer::ReadCB, base::Unretained(this), audio_stream)));
- video_stream->Read(BindToCurrentLoop(Bind(
- &ShellDemuxerFuzzer::ReadCB, base::Unretained(this), video_stream)));
+ audio_stream->Read(BindToCurrentLoop(
+ Bind(&DemuxerFuzzer::ReadCB, base::Unretained(this), audio_stream)));
+ video_stream->Read(BindToCurrentLoop(
+ Bind(&DemuxerFuzzer::ReadCB, base::Unretained(this), video_stream)));
}
void StopCB() { stopped_ = true; }
@@ -122,18 +123,18 @@
}
DCHECK(!error_occurred_);
stream->Read(BindToCurrentLoop(
- Bind(&ShellDemuxerFuzzer::ReadCB, base::Unretained(this), stream)));
+ Bind(&DemuxerFuzzer::ReadCB, base::Unretained(this), stream)));
}
bool error_occurred_;
int eos_count_;
bool stopped_;
- scoped_refptr<ShellDemuxer> demuxer_;
+ scoped_refptr<ProgressiveDemuxer> demuxer_;
};
-class ShellDemuxerFuzzerApp : public FuzzerApp {
+class DemuxerFuzzerApp : public FuzzerApp {
public:
- explicit ShellDemuxerFuzzerApp(MediaSandbox* media_sandbox)
+ explicit DemuxerFuzzerApp(MediaSandbox* media_sandbox)
: media_sandbox_(media_sandbox) {}
std::vector<uint8> ParseFileContent(
@@ -149,7 +150,7 @@
void Fuzz(const std::string& file_name,
const std::vector<uint8>& fuzzing_content) override {
- ShellDemuxerFuzzer demuxer_fuzzer(fuzzing_content);
+ DemuxerFuzzer demuxer_fuzzer(fuzzing_content);
demuxer_fuzzer.Fuzz();
}
@@ -159,9 +160,8 @@
int SandboxMain(int argc, char** argv) {
MediaSandbox media_sandbox(
- argc, argv,
- base::FilePath(FILE_PATH_LITERAL("shell_demuxer_fuzzer.json")));
- ShellDemuxerFuzzerApp fuzzer_app(&media_sandbox);
+ argc, argv, base::FilePath(FILE_PATH_LITERAL("demuxer_fuzzer.json")));
+ DemuxerFuzzerApp fuzzer_app(&media_sandbox);
if (fuzzer_app.Init(argc, argv)) {
fuzzer_app.RunFuzzingLoop();
diff --git a/src/cobalt/media/base/mock_shell_data_source_reader.h b/src/cobalt/media/progressive/mock_data_source_reader.h
similarity index 71%
rename from src/cobalt/media/base/mock_shell_data_source_reader.h
rename to src/cobalt/media/progressive/mock_data_source_reader.h
index 08935b2..cf3ddab 100644
--- a/src/cobalt/media/base/mock_shell_data_source_reader.h
+++ b/src/cobalt/media/progressive/mock_data_source_reader.h
@@ -14,20 +14,20 @@
* limitations under the License.
*/
-#ifndef COBALT_MEDIA_BASE_MOCK_SHELL_DATA_SOURCE_READER_H_
-#define COBALT_MEDIA_BASE_MOCK_SHELL_DATA_SOURCE_READER_H_
+#ifndef COBALT_MEDIA_PROGRESSIVE_MOCK_DATA_SOURCE_READER_H_
+#define COBALT_MEDIA_PROGRESSIVE_MOCK_DATA_SOURCE_READER_H_
-#include "media/base/shell_data_source_reader.h"
+#include "media/progressive/data_source_reader.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace cobalt {
namespace media {
-class MockShellDataSourceReader : public ShellDataSourceReader {
+class MockDataSourceReader : public DataSourceReader {
public:
- MockShellDataSourceReader() {}
+ MockDataSourceReader() {}
- // ShellDataSourceReader implementation
+ // DataSourceReader implementation
MOCK_METHOD1(SetDataSource, void(DataSource*));
MOCK_METHOD3(BlockingRead, int(int64, int, uint8*));
MOCK_METHOD0(FileSize, int64());
@@ -37,4 +37,4 @@
} // namespace media
} // namespace cobalt
-#endif // COBALT_MEDIA_BASE_MOCK_SHELL_DATA_SOURCE_READER_H_
+#endif // COBALT_MEDIA_PROGRESSIVE_MOCK_DATA_SOURCE_READER_H_
diff --git a/src/cobalt/media/filters/shell_mp4_map.cc b/src/cobalt/media/progressive/mp4_map.cc
similarity index 92%
rename from src/cobalt/media/filters/shell_mp4_map.cc
rename to src/cobalt/media/progressive/mp4_map.cc
index 3a5189e..3a65467 100644
--- a/src/cobalt/media/filters/shell_mp4_map.cc
+++ b/src/cobalt/media/progressive/mp4_map.cc
@@ -12,23 +12,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "cobalt/media/filters/shell_mp4_map.h"
+#include "cobalt/media/progressive/mp4_map.h"
#include <algorithm>
#include "base/strings/stringprintf.h"
#include "cobalt/media/base/endian_util.h"
-#include "cobalt/media/filters/shell_mp4_parser.h"
+#include "cobalt/media/progressive/mp4_parser.h"
namespace cobalt {
namespace media {
// ==== TableCache =============================================================
-ShellMP4Map::TableCache::TableCache(uint64 table_offset, uint32 entry_count,
- uint32 entry_size,
- uint32 cache_size_entries,
- scoped_refptr<ShellDataSourceReader> reader)
+MP4Map::TableCache::TableCache(uint64 table_offset, uint32 entry_count,
+ uint32 entry_size, uint32 cache_size_entries,
+ scoped_refptr<DataSourceReader> reader)
: entry_size_(entry_size),
entry_count_(entry_count),
cache_size_entries_(cache_size_entries),
@@ -37,7 +36,7 @@
cache_first_entry_number_(-1),
cache_entry_count_(0) {}
-uint8* ShellMP4Map::TableCache::GetBytesAtEntry(uint32 entry_number) {
+uint8* MP4Map::TableCache::GetBytesAtEntry(uint32 entry_number) {
// don't fetch the unfetchable
if (entry_number >= entry_count_) {
return NULL;
@@ -77,7 +76,7 @@
return &cache_[0] + (cache_offset * entry_size_);
}
-bool ShellMP4Map::TableCache::ReadU32Entry(uint32 entry_number, uint32* entry) {
+bool MP4Map::TableCache::ReadU32Entry(uint32 entry_number, uint32* entry) {
if (uint8* data = GetBytesAtEntry(entry_number)) {
*entry = endian_util::load_uint32_big_endian(data);
return true;
@@ -86,8 +85,8 @@
return false;
}
-bool ShellMP4Map::TableCache::ReadU32PairEntry(uint32 entry_number,
- uint32* first, uint32* second) {
+bool MP4Map::TableCache::ReadU32PairEntry(uint32 entry_number, uint32* first,
+ uint32* second) {
if (uint8* data = GetBytesAtEntry(entry_number)) {
if (first) *first = endian_util::load_uint32_big_endian(data);
if (second) *second = endian_util::load_uint32_big_endian(data + 4);
@@ -97,8 +96,8 @@
return false;
}
-bool ShellMP4Map::TableCache::ReadU32EntryIntoU64(uint32 entry_number,
- uint64* entry) {
+bool MP4Map::TableCache::ReadU32EntryIntoU64(uint32 entry_number,
+ uint64* entry) {
if (uint8* data = GetBytesAtEntry(entry_number)) {
*entry = endian_util::load_uint32_big_endian(data);
return true;
@@ -107,7 +106,7 @@
return false;
}
-bool ShellMP4Map::TableCache::ReadU64Entry(uint32 entry_number, uint64* entry) {
+bool MP4Map::TableCache::ReadU64Entry(uint32 entry_number, uint64* entry) {
if (uint8* data = GetBytesAtEntry(entry_number)) {
*entry = endian_util::load_uint64_big_endian(data);
return true;
@@ -116,7 +115,7 @@
return false;
}
-// ==== ShellMP4Map ============================================================
+// ==== MP4Map ============================================================
// atom | name | size | description, (*) means optional table
// -----+-----------------------+------+----------------------------------------
@@ -128,7 +127,7 @@
// stts | time-to-sample | 8 | run-length sample number to duration
// stsz | sample size | 4 | per-sample list of sample sizes
-ShellMP4Map::ShellMP4Map(scoped_refptr<ShellDataSourceReader> reader)
+MP4Map::MP4Map(scoped_refptr<DataSourceReader> reader)
: reader_(reader),
current_chunk_sample_(0),
next_chunk_sample_(0),
@@ -155,14 +154,14 @@
stts_table_index_(0),
stsz_default_size_(0) {}
-bool ShellMP4Map::IsComplete() {
+bool MP4Map::IsComplete() {
// all required table pointers must be valid for map to function
return (co64_ || stco_) && stsc_ && stts_ && (stsz_ || stsz_default_size_);
}
// The sample size is a lookup in the stsz table, which is indexed per sample
// number.
-bool ShellMP4Map::GetSize(uint32 sample_number, uint32* size_out) {
+bool MP4Map::GetSize(uint32 sample_number, uint32* size_out) {
DCHECK(size_out);
DCHECK(stsz_ || stsz_default_size_);
@@ -184,7 +183,7 @@
// then use the stsz to sum samples to the byte offset with that chunk. The sum
// of the chunk offset and the byte offset within the chunk is the offset of
// the sample.
-bool ShellMP4Map::GetOffset(uint32 sample_number, uint64* offset_out) {
+bool MP4Map::GetOffset(uint32 sample_number, uint64* offset_out) {
DCHECK(offset_out);
DCHECK(stsc_);
DCHECK(stco_ || co64_);
@@ -255,7 +254,7 @@
// durations to find the dts of that sample number. We then integrate sample
// numbers through the ctts to find the composition time offset, which we add to
// the dts to return the pts.
-bool ShellMP4Map::GetTimestamp(uint32 sample_number, uint64* timestamp_out) {
+bool MP4Map::GetTimestamp(uint32 sample_number, uint64* timestamp_out) {
DCHECK(timestamp_out);
if (sample_number > highest_valid_sample_number_) {
return false;
@@ -280,7 +279,7 @@
}
// Sum through the stts to find the duration of the given sample_number.
-bool ShellMP4Map::GetDuration(uint32 sample_number, uint32* duration_out) {
+bool MP4Map::GetDuration(uint32 sample_number, uint32* duration_out) {
DCHECK(duration_out);
if (sample_number > highest_valid_sample_number_) {
return false;
@@ -295,7 +294,7 @@
return true;
}
-bool ShellMP4Map::GetIsKeyframe(uint32 sample_number, bool* is_keyframe_out) {
+bool MP4Map::GetIsKeyframe(uint32 sample_number, bool* is_keyframe_out) {
DCHECK(is_keyframe_out);
if (sample_number > highest_valid_sample_number_) {
return false;
@@ -336,14 +335,14 @@
return true;
}
-bool ShellMP4Map::IsEOS(uint32 sample_number) {
+bool MP4Map::IsEOS(uint32 sample_number) {
return (sample_number > highest_valid_sample_number_);
}
// First look up the sample number for the provided timestamp by integrating
// timestamps through the stts. Then do a binary search on the stss to find the
// keyframe nearest that sample number.
-bool ShellMP4Map::GetKeyframe(uint64 timestamp, uint32* sample_out) {
+bool MP4Map::GetKeyframe(uint64 timestamp, uint32* sample_out) {
DCHECK(sample_out);
// Advance stts to the provided timestamp range
if (!stts_AdvanceToTime(timestamp)) {
@@ -375,8 +374,8 @@
// Set up map state and load first part of table, or entire table if it is small
// enough, for each of the supporated atoms.
-bool ShellMP4Map::SetAtom(uint32 four_cc, uint64 offset, uint64 size,
- uint32 cache_size_entries, const uint8* atom) {
+bool MP4Map::SetAtom(uint32 four_cc, uint64 offset, uint64 size,
+ uint32 cache_size_entries, const uint8* atom) {
// All map atoms are variable-length tables starting with 4 bytes of
// version/flag info followed by a uint32 indicating the number of items in
// table. The stsz atom bucks tradition by putting an optional default value
@@ -463,7 +462,7 @@
return atom_init;
}
-bool ShellMP4Map::co64_Init() {
+bool MP4Map::co64_Init() {
DCHECK(co64_);
// load offset of first chunk into current_chunk_offset_
if (co64_->GetEntryCount() > 0) {
@@ -482,7 +481,7 @@
// uint32 sample count
// uint32 composition offset in ticks
//
-bool ShellMP4Map::ctts_Init() {
+bool MP4Map::ctts_Init() {
DCHECK(ctts_);
// get cache segment vector to reserve table entries in advance
int cache_segments =
@@ -506,7 +505,7 @@
// To find the composition offset of a given sample number we must integrate
// through the ctts to find the range of samples containing sample_number. Note
// that the ctts is an optional table.
-bool ShellMP4Map::ctts_AdvanceToSample(uint32 sample_number) {
+bool MP4Map::ctts_AdvanceToSample(uint32 sample_number) {
// ctts table is optional, so treat not having one as non-fatal
if (!ctts_) {
return true;
@@ -573,8 +572,8 @@
return true;
}
-bool ShellMP4Map::ctts_SlipCacheToSample(uint32 sample_number,
- int starting_cache_index) {
+bool MP4Map::ctts_SlipCacheToSample(uint32 sample_number,
+ int starting_cache_index) {
DCHECK_LT(starting_cache_index, ctts_samples_.size());
int cache_index = starting_cache_index;
for (; cache_index + 1 < ctts_samples_.size(); cache_index++) {
@@ -593,7 +592,7 @@
return true;
}
-bool ShellMP4Map::stco_Init() {
+bool MP4Map::stco_Init() {
DCHECK(stco_);
// load offset of first chunk into current_chunk_offset_
if (stco_->GetEntryCount() > 0) {
@@ -610,7 +609,7 @@
// uint32 first chunk number with this sample count
// uint32 samples-per-chunk
// uint32 sample description id (unused)
-bool ShellMP4Map::stsc_Init() {
+bool MP4Map::stsc_Init() {
DCHECK(stsc_);
// set up vector to correct final size
int cache_segments =
@@ -660,7 +659,7 @@
// to be consumed incrementally and with minimal memory consumption we calculate
// this integration step only when needed, and save results for each cached
// piece of the table, to avoid having to recalculate needed data.
-bool ShellMP4Map::stsc_AdvanceToSample(uint32 sample_number) {
+bool MP4Map::stsc_AdvanceToSample(uint32 sample_number) {
DCHECK(stsc_);
// sample_number could be before first chunk, meaning that we are seeking
// backwards and have left the current chunk. Find the closest part of the
@@ -736,8 +735,8 @@
return true;
}
-bool ShellMP4Map::stsc_SlipCacheToSample(uint32 sample_number,
- int starting_cache_index) {
+bool MP4Map::stsc_SlipCacheToSample(uint32 sample_number,
+ int starting_cache_index) {
DCHECK_LT(starting_cache_index, stsc_sample_sums_.size());
// look through old sample sums for the first entry that exceeds sample
// sample_number, we want the entry right before that
@@ -776,7 +775,7 @@
}
// stss is a list of sample numbers that are keyframes.
-bool ShellMP4Map::stss_Init() {
+bool MP4Map::stss_Init() {
int cache_segments =
(stss_->GetEntryCount() / stss_->GetCacheSizeEntries()) + 1;
stss_keyframes_.reserve(cache_segments);
@@ -800,7 +799,7 @@
}
// advance by one table entry through stss, updating cache if necessary
-bool ShellMP4Map::stss_AdvanceStep() {
+bool MP4Map::stss_AdvanceStep() {
DCHECK(stss_);
stss_last_keyframe_ = stss_next_keyframe_;
stss_table_index_++;
@@ -823,7 +822,7 @@
return true;
}
-bool ShellMP4Map::stss_FindNearestKeyframe(uint32 sample_number) {
+bool MP4Map::stss_FindNearestKeyframe(uint32 sample_number) {
DCHECK(stss_);
// it is assumed that there's at least one cache entry created by
// stss_Init();
@@ -955,7 +954,7 @@
// The stts table has the following per-entry layout:
// uint32 sample count - number of sequential samples with this duration
// uint32 sample duration - duration in ticks of this sample range
-bool ShellMP4Map::stts_Init() {
+bool MP4Map::stts_Init() {
int cache_segments =
(stts_->GetEntryCount() / stts_->GetCacheSizeEntries()) + 1;
stts_samples_.reserve(cache_segments);
@@ -982,7 +981,7 @@
return true;
}
-bool ShellMP4Map::stts_AdvanceToSample(uint32 sample_number) {
+bool MP4Map::stts_AdvanceToSample(uint32 sample_number) {
DCHECK(stts_);
// sample_number could be before our current sample range, in which case
// we skip to the nearest table entry before sample_number and integrate
@@ -1015,8 +1014,8 @@
// Move our integration steps to a previously saved entry in the cache tables.
// Searches linearly through the vector of old cached values, so can accept a
// starting index to do the search from.
-bool ShellMP4Map::stts_SlipCacheToSample(uint32 sample_number,
- int starting_cache_index) {
+bool MP4Map::stts_SlipCacheToSample(uint32 sample_number,
+ int starting_cache_index) {
DCHECK_LT(starting_cache_index, stts_samples_.size());
int cache_index = starting_cache_index;
for (; cache_index + 1 < stts_samples_.size(); cache_index++) {
@@ -1039,7 +1038,7 @@
return true;
}
-bool ShellMP4Map::stts_AdvanceToTime(uint64 timestamp) {
+bool MP4Map::stts_AdvanceToTime(uint64 timestamp) {
DCHECK(stts_);
if (timestamp < stts_first_sample_time_) {
@@ -1067,7 +1066,7 @@
return true;
}
-bool ShellMP4Map::stts_IntegrateStep() {
+bool MP4Map::stts_IntegrateStep() {
// advance time to next sample range
uint32 range_size = stts_next_first_sample_ - stts_first_sample_;
stts_first_sample_time_ += (range_size * stts_sample_duration_);
@@ -1111,8 +1110,7 @@
return true;
}
-bool ShellMP4Map::stts_SlipCacheToTime(uint64 timestamp,
- int starting_cache_index) {
+bool MP4Map::stts_SlipCacheToTime(uint64 timestamp, int starting_cache_index) {
DCHECK_LT(starting_cache_index, stts_timestamps_.size());
int cache_index = starting_cache_index;
for (; cache_index + 1 < stts_timestamps_.size(); cache_index++) {
@@ -1135,7 +1133,7 @@
return true;
}
-bool ShellMP4Map::stsz_Init() { return stsz_->GetBytesAtEntry(0) != NULL; }
+bool MP4Map::stsz_Init() { return stsz_->GetBytesAtEntry(0) != NULL; }
} // namespace media
} // namespace cobalt
diff --git a/src/cobalt/media/filters/shell_mp4_map.h b/src/cobalt/media/progressive/mp4_map.h
similarity index 93%
rename from src/cobalt/media/filters/shell_mp4_map.h
rename to src/cobalt/media/progressive/mp4_map.h
index 88e1319..93bc08f 100644
--- a/src/cobalt/media/filters/shell_mp4_map.h
+++ b/src/cobalt/media/progressive/mp4_map.h
@@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_MEDIA_FILTERS_SHELL_MP4_MAP_H_
-#define COBALT_MEDIA_FILTERS_SHELL_MP4_MAP_H_
+#ifndef COBALT_MEDIA_PROGRESSIVE_MP4_MAP_H_
+#define COBALT_MEDIA_PROGRESSIVE_MP4_MAP_H_
#include <vector>
#include "base/callback.h"
#include "base/memory/ref_counted.h"
-#include "cobalt/media/base/shell_data_source_reader.h"
+#include "cobalt/media/progressive/data_source_reader.h"
namespace cobalt {
namespace media {
@@ -37,9 +37,9 @@
// them to provide byte offsets, sizes, and timestamps of a mp4 atom. The
// caching design benefits from, but does not require, sequential access
// in sample numbers.
-class ShellMP4Map : public base::RefCountedThreadSafe<ShellMP4Map> {
+class MP4Map : public base::RefCountedThreadSafe<MP4Map> {
public:
- explicit ShellMP4Map(scoped_refptr<ShellDataSourceReader> reader);
+ explicit MP4Map(scoped_refptr<DataSourceReader> reader);
bool IsComplete();
@@ -117,7 +117,7 @@
uint32 entry_count, // number of entries in table
uint32 entry_size, // size in bytes of each entry in table
uint32 cache_size_entries, // number of entries to cache in mem
- scoped_refptr<ShellDataSourceReader> reader); // reader to use
+ scoped_refptr<DataSourceReader> reader); // reader to use
// The following Read* functions all read values in big endian.
bool ReadU32Entry(uint32 entry_number, uint32* entry);
@@ -138,7 +138,7 @@
uint32 entry_count_; // size of table in entries
uint32 cache_size_entries_; // max number of entries to fit in memory
uint64 table_offset_; // offset of table in stream
- scoped_refptr<ShellDataSourceReader> reader_; // means to read more table
+ scoped_refptr<DataSourceReader> reader_; // means to read more table
// current cache state
std::vector<uint8> cache_; // the cached part of the table
@@ -146,7 +146,7 @@
uint32 cache_entry_count_; // number of valid entries in cache
};
- scoped_refptr<ShellDataSourceReader> reader_;
+ scoped_refptr<DataSourceReader> reader_;
// current integration state for GetOffset(), we save the sum of sample sizes
// within the current chunk.
@@ -211,4 +211,4 @@
} // namespace media
} // namespace cobalt
-#endif // COBALT_MEDIA_FILTERS_SHELL_MP4_MAP_H_
+#endif // COBALT_MEDIA_PROGRESSIVE_MP4_MAP_H_
diff --git a/src/cobalt/media/filters/shell_mp4_map_unittest.cc b/src/cobalt/media/progressive/mp4_map_unittest.cc
similarity index 95%
rename from src/cobalt/media/filters/shell_mp4_map_unittest.cc
rename to src/cobalt/media/progressive/mp4_map_unittest.cc
index 1fa0a73..347b7bb 100644
--- a/src/cobalt/media/filters/shell_mp4_map_unittest.cc
+++ b/src/cobalt/media/progressive/mp4_map_unittest.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "cobalt/media/filters/shell_mp4_map.h"
+#include "cobalt/media/progressive/mp4_map.h"
#include <stdlib.h> // for rand and srand
@@ -23,8 +23,8 @@
#include <vector>
#include "cobalt/media/base/endian_util.h"
-#include "cobalt/media/base/mock_shell_data_source_reader.h"
-#include "cobalt/media/filters/shell_mp4_parser.h"
+#include "cobalt/media/progressive/mock_data_source_reader.h"
+#include "cobalt/media/progressive/mp4_parser.h"
#include "starboard/memory.h"
#include "starboard/types.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -48,8 +48,8 @@
using cobalt::media::kEntrySize_stss;
using cobalt::media::kEntrySize_stsz;
using cobalt::media::kEntrySize_stts;
-using cobalt::media::MockShellDataSourceReader;
-using cobalt::media::ShellMP4Map;
+using cobalt::media::MockDataSourceReader;
+using cobalt::media::MP4Map;
using ::testing::_;
using ::testing::AllOf;
@@ -403,16 +403,16 @@
}
};
-class ShellMP4MapTest : public testing::Test {
+class MP4MapTest : public testing::Test {
protected:
- ShellMP4MapTest() {
+ MP4MapTest() {
// make a new mock reader
- reader_ = new ::testing::NiceMock<MockShellDataSourceReader>();
+ reader_ = new ::testing::NiceMock<MockDataSourceReader>();
// make a new map with a mock reader.
- map_ = new ShellMP4Map(reader_);
+ map_ = new MP4Map(reader_);
}
- virtual ~ShellMP4MapTest() {
+ virtual ~MP4MapTest() {
DCHECK(map_->HasOneRef());
map_ = NULL;
@@ -421,7 +421,7 @@
reader_ = NULL;
}
- void ResetMap() { map_ = new ShellMP4Map(reader_); }
+ void ResetMap() { map_ = new MP4Map(reader_); }
void CreateTestSampleTable(unsigned int seed, int num_of_samples,
int min_sample_size, int max_sample_size,
@@ -454,21 +454,21 @@
}
// ==== Test Fixture Members
- scoped_refptr<ShellMP4Map> map_;
- scoped_refptr<MockShellDataSourceReader> reader_;
+ scoped_refptr<MP4Map> map_;
+ scoped_refptr<MockDataSourceReader> reader_;
std::unique_ptr<SampleTable> sample_table_;
};
// ==== SetAtom() Tests ========================================================
/*
-TEST_F(ShellMP4MapTest, SetAtomWithZeroDefaultSize) {
+TEST_F(MP4MapTest, SetAtomWithZeroDefaultSize) {
// SetAtom() should fail with a zero default size on an stsc.
NOTIMPLEMENTED();
}
*/
// ==== GetSize() Tests ========================================================
-TEST_F(ShellMP4MapTest, GetSizeWithDefaultSize) {
+TEST_F(MP4MapTest, GetSizeWithDefaultSize) {
CreateTestSampleTable(100, 1000, 0xb0df00d, 0xb0df00d, 5, 10, 5, 10, 10, 20,
10, 20);
sample_table_->ClearReadStatistics();
@@ -490,7 +490,7 @@
ASSERT_EQ(sample_table_->read_count(), 0);
}
-TEST_F(ShellMP4MapTest, GetSizeIterationWithHugeCache) {
+TEST_F(MP4MapTest, GetSizeIterationWithHugeCache) {
for (int max_sample_size = 10; max_sample_size < 20; ++max_sample_size) {
CreateTestSampleTable(200 + max_sample_size, 1000, 10, max_sample_size, 5,
10, 5, 10, 10, 20, 10, 20);
@@ -517,7 +517,7 @@
}
}
-TEST_F(ShellMP4MapTest, GetSizeIterationTinyCache) {
+TEST_F(MP4MapTest, GetSizeIterationTinyCache) {
for (int max_sample_size = 10; max_sample_size < 20; ++max_sample_size) {
CreateTestSampleTable(300 + max_sample_size, 1000, 10, max_sample_size, 5,
10, 5, 10, 10, 20, 10, 20);
@@ -543,7 +543,7 @@
}
}
-TEST_F(ShellMP4MapTest, GetSizeRandomAccess) {
+TEST_F(MP4MapTest, GetSizeRandomAccess) {
CreateTestSampleTable(101, 2000, 20, 24, 5, 10, 5, 10, 10, 20, 10, 20);
for (int i = 24; i < 27; ++i) {
ResetMap();
@@ -593,7 +593,7 @@
// ==== GetOffset() Tests ======================================================
-TEST_F(ShellMP4MapTest, GetOffsetIterationHugeCache) {
+TEST_F(MP4MapTest, GetOffsetIterationHugeCache) {
for (int coindex = 0; coindex < 2; ++coindex) {
CreateTestSampleTable(102 + coindex, 1000, 20, 25, 5, 10, 5, 10, 10, 20, 10,
20);
@@ -617,7 +617,7 @@
}
}
-TEST_F(ShellMP4MapTest, GetOffsetIterationTinyCache) {
+TEST_F(MP4MapTest, GetOffsetIterationTinyCache) {
for (int coindex = 0; coindex < 2; ++coindex) {
CreateTestSampleTable(103, 30, 20, 25, 5, 10, 5, 10, 10, 20, 10, 20);
for (int i = 1; i < 12; ++i) {
@@ -644,7 +644,7 @@
// Random access within cache should just result in correct re-integration
// through the stsc.
-TEST_F(ShellMP4MapTest, GetOffsetRandomAccessHugeCache) {
+TEST_F(MP4MapTest, GetOffsetRandomAccessHugeCache) {
for (int coindex = 0; coindex < 2; ++coindex) {
CreateTestSampleTable(104, 300, 20, 25, 5, 10, 5, 10, 10, 20, 10, 20);
ResetMap();
@@ -664,7 +664,7 @@
// Random access across cache boundaries should not break computation of
// offsets.
-TEST_F(ShellMP4MapTest, GetOffsetRandomAccessTinyCache) {
+TEST_F(MP4MapTest, GetOffsetRandomAccessTinyCache) {
for (int coindex = 0; coindex < 2; ++coindex) {
CreateTestSampleTable(105, 300, 20, 25, 5, 10, 5, 10, 10, 20, 10, 20);
ResetMap();
@@ -718,7 +718,7 @@
}
}
-TEST_F(ShellMP4MapTest, GetOffsetRandomAccessWithDefaultSize) {
+TEST_F(MP4MapTest, GetOffsetRandomAccessWithDefaultSize) {
for (int coindex = 0; coindex < 2; ++coindex) {
CreateTestSampleTable(106, 300, 20, 20, 5, 10, 5, 10, 10, 20, 10, 20);
ResetMap();
@@ -755,7 +755,7 @@
// ==== GetDuration() Tests ====================================================
-TEST_F(ShellMP4MapTest, GetDurationIteration) {
+TEST_F(MP4MapTest, GetDurationIteration) {
CreateTestSampleTable(107, 60, 20, 25, 5, 10, 5, 10, 10, 20, 10, 20);
ResetMap();
SetTestTable(kAtomType_stts, 2);
@@ -773,7 +773,7 @@
map_->GetDuration(sample_table_->sample_count(), &failed_duration));
}
-TEST_F(ShellMP4MapTest, GetDurationRandomAccess) {
+TEST_F(MP4MapTest, GetDurationRandomAccess) {
CreateTestSampleTable(108, 60, 20, 25, 5, 10, 5, 10, 10, 20, 10, 20);
ResetMap();
SetTestTable(kAtomType_stts, 3);
@@ -810,7 +810,7 @@
// ==== GetTimestamp() Tests ===================================================
-TEST_F(ShellMP4MapTest, GetTimestampIterationNoCompositionTime) {
+TEST_F(MP4MapTest, GetTimestampIterationNoCompositionTime) {
CreateTestSampleTable(109, 60, 20, 25, 5, 10, 5, 10, 10, 20, 10, 20);
ResetMap();
SetTestTable(kAtomType_stts, 7);
@@ -828,7 +828,7 @@
map_->GetTimestamp(sample_table_->sample_count(), &failed_timestamp));
}
-TEST_F(ShellMP4MapTest, GetTimestampRandomAccessNoCompositionTime) {
+TEST_F(MP4MapTest, GetTimestampRandomAccessNoCompositionTime) {
CreateTestSampleTable(110, 60, 20, 25, 5, 10, 5, 10, 10, 20, 10, 20);
ResetMap();
SetTestTable(kAtomType_stts, 10);
@@ -858,7 +858,7 @@
}
}
-TEST_F(ShellMP4MapTest, GetTimestampIteration) {
+TEST_F(MP4MapTest, GetTimestampIteration) {
CreateTestSampleTable(111, 300, 20, 25, 5, 10, 5, 10, 10, 20, 10, 20);
for (int i = 1; i < 20; ++i) {
ResetMap();
@@ -879,7 +879,7 @@
}
}
-TEST_F(ShellMP4MapTest, GetTimestampRandomAccess) {
+TEST_F(MP4MapTest, GetTimestampRandomAccess) {
CreateTestSampleTable(112, 300, 20, 25, 5, 10, 5, 10, 10, 20, 10, 20);
for (int i = 1; i < 20; ++i) {
ResetMap();
@@ -904,7 +904,7 @@
// ==== GetIsKeyframe() Tests ==================================================
// the map should consider every valid sample number a keyframe without an stss
-TEST_F(ShellMP4MapTest, GetIsKeyframeNoKeyframeTable) {
+TEST_F(MP4MapTest, GetIsKeyframeNoKeyframeTable) {
ResetMap();
bool is_keyframe_out = false;
ASSERT_TRUE(map_->GetIsKeyframe(100, &is_keyframe_out));
@@ -921,7 +921,7 @@
}
}
-TEST_F(ShellMP4MapTest, GetIsKeyframeIteration) {
+TEST_F(MP4MapTest, GetIsKeyframeIteration) {
CreateTestSampleTable(113, 1000, 0xb0df00d, 0xb0df00d, 5, 10, 5, 10, 10, 20,
10, 20);
ResetMap();
@@ -936,7 +936,7 @@
}
}
-TEST_F(ShellMP4MapTest, GetIsKeyframeRandomAccess) {
+TEST_F(MP4MapTest, GetIsKeyframeRandomAccess) {
CreateTestSampleTable(114, 1000, 0xb0df00d, 0xb0df00d, 5, 10, 5, 10, 10, 20,
10, 20);
ResetMap();
@@ -1005,7 +1005,7 @@
// every frame should be returned as a keyframe. This tests if our computation
// of timestamps => sample numbers is equivalent to sample numbers => timestamps
-TEST_F(ShellMP4MapTest, GetKeyframeNoKeyframeTableIteration) {
+TEST_F(MP4MapTest, GetKeyframeNoKeyframeTableIteration) {
CreateTestSampleTable(115, 30, 20, 25, 5, 10, 5, 10, 10, 20, 10, 20);
ResetMap();
SetTestTable(kAtomType_stts, 7);
@@ -1022,7 +1022,7 @@
}
}
-TEST_F(ShellMP4MapTest, GetKeyframeNoKeyframeTableRandomAccess) {
+TEST_F(MP4MapTest, GetKeyframeNoKeyframeTableRandomAccess) {
CreateTestSampleTable(116, 30, 20, 25, 5, 10, 5, 10, 10, 20, 10, 20);
ResetMap();
SetTestTable(kAtomType_stts, 5);
@@ -1056,7 +1056,7 @@
}
// GetKeyframe is not normally called iteratively, so we test random access
-TEST_F(ShellMP4MapTest, GetKeyframe) {
+TEST_F(MP4MapTest, GetKeyframe) {
CreateTestSampleTable(117, 60, 20, 25, 5, 10, 5, 10, 10, 20, 10, 20);
ResetMap();
SetTestTable(kAtomType_stss, 3);
diff --git a/src/cobalt/media/filters/shell_mp4_parser.cc b/src/cobalt/media/progressive/mp4_parser.cc
similarity index 91%
rename from src/cobalt/media/filters/shell_mp4_parser.cc
rename to src/cobalt/media/progressive/mp4_parser.cc
index 7d9efb1..957395d 100644
--- a/src/cobalt/media/filters/shell_mp4_parser.cc
+++ b/src/cobalt/media/progressive/mp4_parser.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "cobalt/media/filters/shell_mp4_parser.h"
+#include "cobalt/media/progressive/mp4_parser.h"
#include <inttypes.h>
#include <limits>
@@ -67,10 +67,10 @@
static const int kMapTableAtomCacheEntries_ctts = 51543 / kEntrySize_ctts;
// static
-PipelineStatus ShellMP4Parser::Construct(
- scoped_refptr<ShellDataSourceReader> reader,
- const uint8* construction_header, scoped_refptr<ShellParser>* parser,
- const scoped_refptr<MediaLog>& media_log) {
+PipelineStatus MP4Parser::Construct(scoped_refptr<DataSourceReader> reader,
+ const uint8* construction_header,
+ scoped_refptr<ProgressiveParser>* parser,
+ const scoped_refptr<MediaLog>& media_log) {
DCHECK(parser);
DCHECK(media_log);
*parser = NULL;
@@ -90,28 +90,28 @@
}
// construct new mp4 parser
- *parser = new ShellMP4Parser(reader, ftyp_atom_size, media_log);
+ *parser = new MP4Parser(reader, ftyp_atom_size, media_log);
return PIPELINE_OK;
}
-ShellMP4Parser::ShellMP4Parser(scoped_refptr<ShellDataSourceReader> reader,
- uint32 ftyp_atom_size,
- const scoped_refptr<MediaLog>& media_log)
- : ShellAVCParser(reader, media_log),
+MP4Parser::MP4Parser(scoped_refptr<DataSourceReader> reader,
+ uint32 ftyp_atom_size,
+ const scoped_refptr<MediaLog>& media_log)
+ : AVCParser(reader, media_log),
atom_offset_(ftyp_atom_size), // start at next atom, skipping over ftyp
current_trak_is_video_(false),
current_trak_is_audio_(false),
current_trak_time_scale_(0),
video_time_scale_hz_(0),
audio_time_scale_hz_(0),
- audio_map_(new ShellMP4Map(reader)),
- video_map_(new ShellMP4Map(reader)),
+ audio_map_(new MP4Map(reader)),
+ video_map_(new MP4Map(reader)),
audio_sample_(0),
video_sample_(0),
first_audio_hole_ticks_(0),
first_audio_hole_(base::TimeDelta::FromSeconds(0)) {}
-ShellMP4Parser::~ShellMP4Parser() {}
+MP4Parser::~MP4Parser() {}
// For MP4 we traverse the file's atom structure attempting to find the audio
// and video configuration information and the locations in the file of the
@@ -119,7 +119,7 @@
// NALUs in the file. As some of the stbl subatoms can be quite large we cache
// a fixed maximum quantity of each stbl subatom and update the cache only on
// miss.
-bool ShellMP4Parser::ParseConfig() {
+bool MP4Parser::ParseConfig() {
while (!IsConfigComplete() || !audio_map_->IsComplete() ||
!video_map_->IsComplete()) {
if (!ParseNextAtom()) {
@@ -129,7 +129,7 @@
return true;
}
-scoped_refptr<ShellAU> ShellMP4Parser::GetNextAU(DemuxerStream::Type type) {
+scoped_refptr<AvcAccessUnit> MP4Parser::GetNextAU(DemuxerStream::Type type) {
uint32 size = 0;
uint32 duration_ticks = 0;
uint64 timestamp_ticks = 0;
@@ -148,8 +148,8 @@
!audio_map_->GetTimestamp(audio_sample_, ×tamp_ticks)) {
// determine if EOS or error
if (audio_map_->IsEOS(audio_sample_)) {
- return ShellAU::CreateEndOfStreamAU(DemuxerStream::AUDIO,
- audio_track_duration_);
+ return AvcAccessUnit::CreateEndOfStreamAU(DemuxerStream::AUDIO,
+ audio_track_duration_);
} else {
DLOG(ERROR) << "parsed bad audio AU";
return NULL;
@@ -195,8 +195,8 @@
!video_map_->GetTimestamp(video_sample_, ×tamp_ticks) ||
!video_map_->GetIsKeyframe(video_sample_, &is_keyframe)) {
if (video_map_->IsEOS(video_sample_)) {
- return ShellAU::CreateEndOfStreamAU(DemuxerStream::VIDEO,
- video_track_duration_);
+ return AvcAccessUnit::CreateEndOfStreamAU(DemuxerStream::VIDEO,
+ video_track_duration_);
} else {
DLOG(ERROR) << "parsed bad video AU";
return NULL;
@@ -219,13 +219,14 @@
size_t prepend_size = CalculatePrependSize(type, is_keyframe);
if (type == DemuxerStream::AUDIO)
- return ShellAU::CreateAudioAU(offset, size, prepend_size, is_keyframe,
- timestamp, duration, this);
- return ShellAU::CreateVideoAU(offset, size, prepend_size, nal_header_size_,
- is_keyframe, timestamp, duration, this);
+ return AvcAccessUnit::CreateAudioAU(offset, size, prepend_size, is_keyframe,
+ timestamp, duration, this);
+ return AvcAccessUnit::CreateVideoAU(offset, size, prepend_size,
+ nal_header_size_, is_keyframe, timestamp,
+ duration, this);
}
-bool ShellMP4Parser::SeekTo(base::TimeDelta timestamp) {
+bool MP4Parser::SeekTo(base::TimeDelta timestamp) {
if (audio_time_scale_hz_ == 0 || video_time_scale_hz_ == 0) {
DLOG_IF(ERROR, audio_time_scale_hz_ == 0)
<< "|audio_time_scale_hz_| cannot be 0.";
@@ -272,7 +273,7 @@
// fourCC code | ASCII | four-byte ASCII code we treat as uint32
// extended size | uint64 | optional size field, only here if atom size is 1
// <--- rest of atom body starts here
-bool ShellMP4Parser::ParseNextAtom() {
+bool MP4Parser::ParseNextAtom() {
uint8 atom[kAtomDownload];
int bytes_read = reader_->BlockingRead(atom_offset_, kAtomDownload, atom);
if (bytes_read < kAtomDownload) {
@@ -461,7 +462,7 @@
return atom_parse_success;
}
-bool ShellMP4Parser::ParseMP4_esds(uint64 atom_data_size) {
+bool MP4Parser::ParseMP4_esds(uint64 atom_data_size) {
if (atom_data_size < kFullBoxHeaderAndFlagSize) {
DLOG(WARNING) << base::StringPrintf(
"esds box should at least be %d bytes but now it is %" PRId64 " bytes",
@@ -501,7 +502,7 @@
return false;
}
-bool ShellMP4Parser::ParseMP4_hdlr(uint64 atom_data_size, uint8* hdlr) {
+bool MP4Parser::ParseMP4_hdlr(uint64 atom_data_size, uint8* hdlr) {
// ensure we're downloading enough of the hdlr to parse
DCHECK_LE(kDesiredBytes_hdlr + 16, kAtomDownload);
// sanity-check for minimum size
@@ -534,7 +535,7 @@
return true;
}
-bool ShellMP4Parser::ParseMP4_mdhd(uint64 atom_data_size, uint8* mdhd) {
+bool MP4Parser::ParseMP4_mdhd(uint64 atom_data_size, uint8* mdhd) {
DCHECK_LE(kDesiredBytes_mdhd + 16, kAtomDownload);
if (atom_data_size < kDesiredBytes_mdhd) {
DLOG(WARNING) << base::StringPrintf("bad size %" PRId64 " on mdhd",
@@ -577,7 +578,7 @@
return true;
}
-bool ShellMP4Parser::ParseMP4_mp4a(uint64 atom_data_size, uint8* mp4a) {
+bool MP4Parser::ParseMP4_mp4a(uint64 atom_data_size, uint8* mp4a) {
DCHECK_LE(kDesiredBytes_mp4a + 16, kAtomDownload);
// we only need the first two bytes of the header, which details the version
// number of this atom, which tells us the size of the rest of the header,
@@ -619,7 +620,7 @@
// 12 | time scale | 4
// 16 | duration: | 4
//
-bool ShellMP4Parser::ParseMP4_mvhd(uint64 atom_data_size, uint8* mvhd) {
+bool MP4Parser::ParseMP4_mvhd(uint64 atom_data_size, uint8* mvhd) {
DCHECK_LE(kDesiredBytes_mvhd + 16, kAtomDownload);
// it should be at least long enough for us to extract the parts we want
if (atom_data_size < kDesiredBytes_mvhd) {
@@ -641,8 +642,7 @@
return true;
}
-base::TimeDelta ShellMP4Parser::TicksToTime(uint64 ticks,
- uint32 time_scale_hz) {
+base::TimeDelta MP4Parser::TicksToTime(uint64 ticks, uint32 time_scale_hz) {
DCHECK_NE(time_scale_hz, 0);
if (time_scale_hz == 0) {
@@ -652,7 +652,7 @@
time_scale_hz);
}
-uint64 ShellMP4Parser::TimeToTicks(base::TimeDelta time, uint32 time_scale_hz) {
+uint64 MP4Parser::TimeToTicks(base::TimeDelta time, uint32 time_scale_hz) {
DCHECK_NE(time_scale_hz, 0);
if (time_scale_hz == 0) {
diff --git a/src/cobalt/media/filters/shell_mp4_parser.h b/src/cobalt/media/progressive/mp4_parser.h
similarity index 82%
rename from src/cobalt/media/filters/shell_mp4_parser.h
rename to src/cobalt/media/progressive/mp4_parser.h
index 6a16b9f..6d0d617 100644
--- a/src/cobalt/media/filters/shell_mp4_parser.h
+++ b/src/cobalt/media/progressive/mp4_parser.h
@@ -12,12 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_MEDIA_FILTERS_SHELL_MP4_PARSER_H_
-#define COBALT_MEDIA_FILTERS_SHELL_MP4_PARSER_H_
+#ifndef COBALT_MEDIA_PROGRESSIVE_MP4_PARSER_H_
+#define COBALT_MEDIA_PROGRESSIVE_MP4_PARSER_H_
#include "cobalt/media/base/media_log.h"
-#include "cobalt/media/filters/shell_avc_parser.h"
-#include "cobalt/media/filters/shell_mp4_map.h"
+#include "cobalt/media/progressive/avc_parser.h"
+#include "cobalt/media/progressive/mp4_map.h"
namespace cobalt {
namespace media {
@@ -27,7 +27,7 @@
// second download (typically), but no larger. This is currently set at 16
// bytes for the 8 byte header + optional 8 byte size extension plus 20 bytes
// for the needed values within an mvhd header. We leave this is the header so
-// that ShellMP4Map can re-use,
+// that MP4Map can re-use,
static const int kAtomDownload = 36;
// mp4 atom fourCC codes as big-endian unsigned ints
@@ -59,24 +59,23 @@
static const uint32 kAtomType_vmhd = 0x766d6864; // skip whole atom
// TODO: mp4v!!
-class ShellMP4Parser : public ShellAVCParser {
+class MP4Parser : public AVCParser {
public:
// Attempts to make sense of the provided bytes of the top of a file as an
// flv, and if it does make sense returns PIPELINE_OK and |*parser| contains a
- // ShellMP4Parser initialized with some basic state. If it doesn't make sense
+ // MP4Parser initialized with some basic state. If it doesn't make sense
// this returns an error status and |*parser| contains NULL.
- static PipelineStatus Construct(scoped_refptr<ShellDataSourceReader> reader,
+ static PipelineStatus Construct(scoped_refptr<DataSourceReader> reader,
const uint8* construction_header,
- scoped_refptr<ShellParser>* parser,
+ scoped_refptr<ProgressiveParser>* parser,
const scoped_refptr<MediaLog>& media_log);
- ShellMP4Parser(scoped_refptr<ShellDataSourceReader> reader,
- uint32 ftyp_atom_size,
- const scoped_refptr<MediaLog>& media_log);
- ~ShellMP4Parser() override;
+ MP4Parser(scoped_refptr<DataSourceReader> reader, uint32 ftyp_atom_size,
+ const scoped_refptr<MediaLog>& media_log);
+ ~MP4Parser() override;
- // === ShellParser implementation
+ // === ProgressiveParser implementation
bool ParseConfig() override;
- scoped_refptr<ShellAU> GetNextAU(DemuxerStream::Type type) override;
+ scoped_refptr<AvcAccessUnit> GetNextAU(DemuxerStream::Type type) override;
bool SeekTo(base::TimeDelta timestamp) override;
private:
@@ -99,8 +98,8 @@
uint32 audio_time_scale_hz_;
base::TimeDelta audio_track_duration_;
base::TimeDelta video_track_duration_;
- scoped_refptr<ShellMP4Map> audio_map_;
- scoped_refptr<ShellMP4Map> video_map_;
+ scoped_refptr<MP4Map> audio_map_;
+ scoped_refptr<MP4Map> video_map_;
uint32 audio_sample_;
uint32 video_sample_;
// for keeping buffers continuous across time scales
@@ -111,4 +110,4 @@
} // namespace media
} // namespace cobalt
-#endif // COBALT_MEDIA_FILTERS_SHELL_MP4_PARSER_H_
+#endif // COBALT_MEDIA_PROGRESSIVE_MP4_PARSER_H_
diff --git a/src/cobalt/media/filters/shell_demuxer.cc b/src/cobalt/media/progressive/progressive_demuxer.cc
similarity index 77%
rename from src/cobalt/media/filters/shell_demuxer.cc
rename to src/cobalt/media/progressive/progressive_demuxer.cc
index 3d0a8cf..a396825 100644
--- a/src/cobalt/media/filters/shell_demuxer.cc
+++ b/src/cobalt/media/progressive/progressive_demuxer.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "cobalt/media/filters/shell_demuxer.h"
+#include "cobalt/media/progressive/progressive_demuxer.h"
#include <inttypes.h>
@@ -33,14 +33,16 @@
namespace cobalt {
namespace media {
-ShellDemuxerStream::ShellDemuxerStream(ShellDemuxer* demuxer, Type type)
+ProgressiveDemuxerStream::ProgressiveDemuxerStream(ProgressiveDemuxer* demuxer,
+ Type type)
: demuxer_(demuxer), type_(type) {
- TRACE_EVENT0("media_stack", "ShellDemuxerStream::ShellDemuxerStream()");
+ TRACE_EVENT0("media_stack",
+ "ProgressiveDemuxerStream::ProgressiveDemuxerStream()");
DCHECK(demuxer_);
}
-void ShellDemuxerStream::Read(const ReadCB& read_cb) {
- TRACE_EVENT0("media_stack", "ShellDemuxerStream::Read()");
+void ProgressiveDemuxerStream::Read(const ReadCB& read_cb) {
+ TRACE_EVENT0("media_stack", "ProgressiveDemuxerStream::Read()");
DCHECK(!read_cb.is_null());
base::AutoLock auto_lock(lock_);
@@ -48,7 +50,7 @@
// Don't accept any additional reads if we've been told to stop.
// The demuxer_ may have been destroyed in the pipleine thread.
if (stopped_) {
- TRACE_EVENT0("media_stack", "ShellDemuxerStream::Read() EOS sent.");
+ TRACE_EVENT0("media_stack", "ProgressiveDemuxerStream::Read() EOS sent.");
read_cb.Run(DemuxerStream::kOk,
scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer()));
return;
@@ -61,7 +63,7 @@
// Send the oldest buffer back.
scoped_refptr<DecoderBuffer> buffer = buffer_queue_.front();
if (buffer->end_of_stream()) {
- TRACE_EVENT0("media_stack", "ShellDemuxerStream::Read() EOS sent.");
+ TRACE_EVENT0("media_stack", "ProgressiveDemuxerStream::Read() EOS sent.");
} else {
// Do not pop EOS buffers, so that subsequent read requests also get EOS
total_buffer_size_ -= buffer->data_size();
@@ -70,31 +72,33 @@
}
read_cb.Run(DemuxerStream::kOk, buffer);
} else {
- TRACE_EVENT0("media_stack", "ShellDemuxerStream::Read() request queued.");
+ TRACE_EVENT0("media_stack",
+ "ProgressiveDemuxerStream::Read() request queued.");
read_queue_.push_back(read_cb);
}
}
-AudioDecoderConfig ShellDemuxerStream::audio_decoder_config() {
+AudioDecoderConfig ProgressiveDemuxerStream::audio_decoder_config() {
return demuxer_->AudioConfig();
}
-VideoDecoderConfig ShellDemuxerStream::video_decoder_config() {
+VideoDecoderConfig ProgressiveDemuxerStream::video_decoder_config() {
return demuxer_->VideoConfig();
}
-Ranges<base::TimeDelta> ShellDemuxerStream::GetBufferedRanges() {
+Ranges<base::TimeDelta> ProgressiveDemuxerStream::GetBufferedRanges() {
base::AutoLock auto_lock(lock_);
return buffered_ranges_;
}
-DemuxerStream::Type ShellDemuxerStream::type() const { return type_; }
+DemuxerStream::Type ProgressiveDemuxerStream::type() const { return type_; }
-void ShellDemuxerStream::EnableBitstreamConverter() { NOTIMPLEMENTED(); }
+void ProgressiveDemuxerStream::EnableBitstreamConverter() { NOTIMPLEMENTED(); }
-void ShellDemuxerStream::EnqueueBuffer(scoped_refptr<DecoderBuffer> buffer) {
+void ProgressiveDemuxerStream::EnqueueBuffer(
+ scoped_refptr<DecoderBuffer> buffer) {
TRACE_EVENT1(
- "media_stack", "ShellDemuxerStream::EnqueueBuffer()", "timestamp",
+ "media_stack", "ProgressiveDemuxerStream::EnqueueBuffer()", "timestamp",
buffer->end_of_stream() ? -1 : buffer->timestamp().InMicroseconds());
base::AutoLock auto_lock(lock_);
if (stopped_) {
@@ -107,7 +111,7 @@
if (buffer->end_of_stream()) {
TRACE_EVENT0("media_stack",
- "ShellDemuxerStream::EnqueueBuffer() EOS received.");
+ "ProgressiveDemuxerStream::EnqueueBuffer() EOS received.");
} else if (buffer->timestamp() != kNoTimestamp) {
if (last_buffer_timestamp_ != kNoTimestamp &&
last_buffer_timestamp_ < buffer->timestamp()) {
@@ -135,23 +139,23 @@
}
}
-base::TimeDelta ShellDemuxerStream::GetLastBufferTimestamp() const {
+base::TimeDelta ProgressiveDemuxerStream::GetLastBufferTimestamp() const {
base::AutoLock auto_lock(lock_);
return last_buffer_timestamp_;
}
-size_t ShellDemuxerStream::GetTotalBufferSize() const {
+size_t ProgressiveDemuxerStream::GetTotalBufferSize() const {
base::AutoLock auto_lock(lock_);
return total_buffer_size_;
}
-size_t ShellDemuxerStream::GetTotalBufferCount() const {
+size_t ProgressiveDemuxerStream::GetTotalBufferCount() const {
base::AutoLock auto_lock(lock_);
return total_buffer_count_;
}
-void ShellDemuxerStream::FlushBuffers() {
- TRACE_EVENT0("media_stack", "ShellDemuxerStream::FlushBuffers()");
+void ProgressiveDemuxerStream::FlushBuffers() {
+ TRACE_EVENT0("media_stack", "ProgressiveDemuxerStream::FlushBuffers()");
base::AutoLock auto_lock(lock_);
// TODO: Investigate if the following warning is valid.
DLOG_IF(WARNING, !read_queue_.empty()) << "Read requests should be empty";
@@ -161,8 +165,8 @@
last_buffer_timestamp_ = kNoTimestamp;
}
-void ShellDemuxerStream::Stop() {
- TRACE_EVENT0("media_stack", "ShellDemuxerStream::Stop()");
+void ProgressiveDemuxerStream::Stop() {
+ TRACE_EVENT0("media_stack", "ProgressiveDemuxerStream::Stop()");
DCHECK(demuxer_->MessageLoopBelongsToCurrentThread());
base::AutoLock auto_lock(lock_);
buffer_queue_.clear();
@@ -172,7 +176,7 @@
// fulfill any pending callbacks with EOS buffers set to end timestamp
for (ReadQueue::iterator it = read_queue_.begin(); it != read_queue_.end();
++it) {
- TRACE_EVENT0("media_stack", "ShellDemuxerStream::Stop() EOS sent.");
+ TRACE_EVENT0("media_stack", "ProgressiveDemuxerStream::Stop() EOS sent.");
it->Run(DemuxerStream::kOk,
scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer()));
}
@@ -181,16 +185,16 @@
}
//
-// ShellDemuxer
+// ProgressiveDemuxer
//
-ShellDemuxer::ShellDemuxer(
+ProgressiveDemuxer::ProgressiveDemuxer(
const scoped_refptr<base::SingleThreadTaskRunner>& message_loop,
DecoderBuffer::Allocator* buffer_allocator, DataSource* data_source,
const scoped_refptr<MediaLog>& media_log)
: message_loop_(message_loop),
buffer_allocator_(buffer_allocator),
host_(NULL),
- blocking_thread_("ShellDemuxerBlk"),
+ blocking_thread_("ProgDemuxerBlk"),
data_source_(data_source),
media_log_(media_log),
stopped_(false),
@@ -201,20 +205,20 @@
DCHECK(buffer_allocator_);
DCHECK(data_source_);
DCHECK(media_log_);
- reader_ = new ShellDataSourceReader();
+ reader_ = new DataSourceReader();
reader_->SetDataSource(data_source_);
}
-ShellDemuxer::~ShellDemuxer() {
+ProgressiveDemuxer::~ProgressiveDemuxer() {
// Explicitly stop |blocking_thread_| to ensure that it stops before the
// destructiing of any other members.
blocking_thread_.Stop();
}
-void ShellDemuxer::Initialize(DemuxerHost* host,
- const PipelineStatusCB& status_cb,
- bool enable_text_tracks) {
- TRACE_EVENT0("media_stack", "ShellDemuxer::Initialize()");
+void ProgressiveDemuxer::Initialize(DemuxerHost* host,
+ const PipelineStatusCB& status_cb,
+ bool enable_text_tracks) {
+ TRACE_EVENT0("media_stack", "ProgressiveDemuxer::Initialize()");
DCHECK(!enable_text_tracks);
DCHECK(MessageLoopBelongsToCurrentThread());
DCHECK(reader_);
@@ -226,9 +230,9 @@
// create audio and video demuxer stream objects
audio_demuxer_stream_.reset(
- new ShellDemuxerStream(this, DemuxerStream::AUDIO));
+ new ProgressiveDemuxerStream(this, DemuxerStream::AUDIO));
video_demuxer_stream_.reset(
- new ShellDemuxerStream(this, DemuxerStream::VIDEO));
+ new ProgressiveDemuxerStream(this, DemuxerStream::VIDEO));
// start the blocking thread and have it download and parse the media config
if (!blocking_thread_.Start()) {
@@ -237,16 +241,18 @@
}
blocking_thread_.task_runner()->PostTask(
- FROM_HERE, base::Bind(&ShellDemuxer::ParseConfigBlocking,
+ FROM_HERE, base::Bind(&ProgressiveDemuxer::ParseConfigBlocking,
base::Unretained(this), status_cb));
}
-void ShellDemuxer::ParseConfigBlocking(const PipelineStatusCB& status_cb) {
+void ProgressiveDemuxer::ParseConfigBlocking(
+ const PipelineStatusCB& status_cb) {
DCHECK(blocking_thread_.task_runner()->BelongsToCurrentThread());
DCHECK(!parser_);
// construct stream parser with error callback
- PipelineStatus status = ShellParser::Construct(reader_, &parser_, media_log_);
+ PipelineStatus status =
+ ProgressiveParser::Construct(reader_, &parser_, media_log_);
// if we can't construct a parser for this stream it's a fatal error, return
// false so ParseConfigDone will notify the caller to Initialize() via
// status_cb.
@@ -286,8 +292,8 @@
ParseConfigDone(status_cb, PIPELINE_OK);
}
-void ShellDemuxer::ParseConfigDone(const PipelineStatusCB& status_cb,
- PipelineStatus status) {
+void ProgressiveDemuxer::ParseConfigDone(const PipelineStatusCB& status_cb,
+ PipelineStatus status) {
DCHECK(blocking_thread_.task_runner()->BelongsToCurrentThread());
if (HasStopCalled()) {
@@ -306,18 +312,18 @@
status_cb.Run(PIPELINE_OK);
}
-void ShellDemuxer::Request(DemuxerStream::Type type) {
+void ProgressiveDemuxer::Request(DemuxerStream::Type type) {
if (!blocking_thread_.task_runner()->BelongsToCurrentThread()) {
blocking_thread_.task_runner()->PostTask(
FROM_HERE,
- base::Bind(&ShellDemuxer::Request, base::Unretained(this), type));
+ base::Bind(&ProgressiveDemuxer::Request, base::Unretained(this), type));
return;
}
DCHECK(!requested_au_) << "overlapping requests not supported!";
flushing_ = false;
// Ask parser for next AU
- scoped_refptr<ShellAU> au = parser_->GetNextAU(type);
+ scoped_refptr<AvcAccessUnit> au = parser_->GetNextAU(type);
// fatal parsing error returns NULL or malformed AU
if (!au || !au->IsValid()) {
if (!HasStopCalled()) {
@@ -332,12 +338,12 @@
const char* ALLOW_UNUSED_TYPE event_type =
type == DemuxerStream::AUDIO ? "audio" : "video";
- TRACE_EVENT2("media_stack", "ShellDemuxer::RequestTask()", "type", event_type,
- "timestamp", au->GetTimestamp().InMicroseconds());
+ TRACE_EVENT2("media_stack", "ProgressiveDemuxer::RequestTask()", "type",
+ event_type, "timestamp", au->GetTimestamp().InMicroseconds());
// don't issue allocation requests for EOS AUs
if (au->IsEndOfStream()) {
- TRACE_EVENT0("media_stack", "ShellDemuxer::RequestTask() EOS sent");
+ TRACE_EVENT0("media_stack", "ProgressiveDemuxer::RequestTask() EOS sent");
// enqueue EOS buffer with correct stream
scoped_refptr<DecoderBuffer> eos_buffer = DecoderBuffer::CreateEOSBuffer();
if (type == DemuxerStream::AUDIO) {
@@ -357,7 +363,7 @@
AllocateBuffer();
}
-void ShellDemuxer::AllocateBuffer() {
+void ProgressiveDemuxer::AllocateBuffer() {
DCHECK(requested_au_);
if (HasStopCalled()) {
@@ -385,7 +391,8 @@
const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(100);
blocking_thread_.message_loop()->task_runner()->PostDelayedTask(
FROM_HERE,
- base::Bind(&ShellDemuxer::AllocateBuffer, base::Unretained(this)),
+ base::Bind(&ProgressiveDemuxer::AllocateBuffer,
+ base::Unretained(this)),
kDelay);
return;
}
@@ -404,13 +411,14 @@
const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(100);
blocking_thread_.message_loop()->task_runner()->PostDelayedTask(
FROM_HERE,
- base::Bind(&ShellDemuxer::AllocateBuffer, base::Unretained(this)),
+ base::Bind(&ProgressiveDemuxer::AllocateBuffer,
+ base::Unretained(this)),
kDelay);
}
}
}
-void ShellDemuxer::Download(scoped_refptr<DecoderBuffer> buffer) {
+void ProgressiveDemuxer::Download(scoped_refptr<DecoderBuffer> buffer) {
DCHECK(blocking_thread_.task_runner()->BelongsToCurrentThread());
// We need a requested_au_ or to have canceled this request and
// are buffering to a new location for this to make sense
@@ -418,8 +426,9 @@
const char* ALLOW_UNUSED_TYPE event_type =
requested_au_->GetType() == DemuxerStream::AUDIO ? "audio" : "video";
- TRACE_EVENT2("media_stack", "ShellDemuxer::Download()", "type", event_type,
- "timestamp", requested_au_->GetTimestamp().InMicroseconds());
+ TRACE_EVENT2("media_stack", "ProgressiveDemuxer::Download()", "type",
+ event_type, "timestamp",
+ requested_au_->GetTimestamp().InMicroseconds());
// do nothing if stopped
if (HasStopCalled()) {
DLOG(INFO) << "aborting download task, stopped";
@@ -466,11 +475,11 @@
host_->OnBufferedTimeRangesChanged(buffered);
blocking_thread_.task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&ShellDemuxer::IssueNextRequest, base::Unretained(this)));
+ FROM_HERE, base::Bind(&ProgressiveDemuxer::IssueNextRequest,
+ base::Unretained(this)));
}
-void ShellDemuxer::IssueNextRequest() {
+void ProgressiveDemuxer::IssueNextRequest() {
DCHECK(!requested_au_);
// if we're stopped don't download anymore
if (HasStopCalled()) {
@@ -519,10 +528,10 @@
// running in a tight loop and seek or stop request has no chance to kick in.
blocking_thread_.task_runner()->PostTask(
FROM_HERE,
- base::Bind(&ShellDemuxer::Request, base::Unretained(this), type));
+ base::Bind(&ProgressiveDemuxer::Request, base::Unretained(this), type));
}
-void ShellDemuxer::Stop() {
+void ProgressiveDemuxer::Stop() {
DCHECK(MessageLoopBelongsToCurrentThread());
// set our internal stop flag, to not treat read failures as
// errors anymore but as a natural part of stopping
@@ -535,8 +544,8 @@
reader_->Stop();
}
-void ShellDemuxer::DataSourceStopped(const base::Closure& callback) {
- TRACE_EVENT0("media_stack", "ShellDemuxer::DataSourceStopped()");
+void ProgressiveDemuxer::DataSourceStopped(const base::Closure& callback) {
+ TRACE_EVENT0("media_stack", "ProgressiveDemuxer::DataSourceStopped()");
DCHECK(MessageLoopBelongsToCurrentThread());
// stop the download thread
blocking_thread_.Stop();
@@ -548,20 +557,23 @@
callback.Run();
}
-bool ShellDemuxer::HasStopCalled() {
+bool ProgressiveDemuxer::HasStopCalled() {
base::AutoLock auto_lock(lock_for_stopped_);
return stopped_;
}
-void ShellDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) {
+void ProgressiveDemuxer::Seek(base::TimeDelta time,
+ const PipelineStatusCB& cb) {
blocking_thread_.message_loop()->task_runner()->PostTask(
- FROM_HERE, base::Bind(&ShellDemuxer::SeekTask, base::Unretained(this),
- time, BindToCurrentLoop(cb)));
+ FROM_HERE,
+ base::Bind(&ProgressiveDemuxer::SeekTask, base::Unretained(this), time,
+ BindToCurrentLoop(cb)));
}
// runs on blocking thread
-void ShellDemuxer::SeekTask(base::TimeDelta time, const PipelineStatusCB& cb) {
- TRACE_EVENT1("media_stack", "ShellDemuxer::SeekTask()", "timestamp",
+void ProgressiveDemuxer::SeekTask(base::TimeDelta time,
+ const PipelineStatusCB& cb) {
+ TRACE_EVENT1("media_stack", "ProgressiveDemuxer::SeekTask()", "timestamp",
time.InMicroseconds());
DLOG(INFO) << base::StringPrintf("seek to: %" PRId64 " ms",
time.InMilliseconds());
@@ -586,7 +598,7 @@
}
}
-DemuxerStream* ShellDemuxer::GetStream(media::DemuxerStream::Type type) {
+DemuxerStream* ProgressiveDemuxer::GetStream(media::DemuxerStream::Type type) {
if (type == DemuxerStream::AUDIO) {
return audio_demuxer_stream_.get();
} else if (type == DemuxerStream::VIDEO) {
@@ -597,20 +609,20 @@
return NULL;
}
-base::TimeDelta ShellDemuxer::GetStartTime() const {
+base::TimeDelta ProgressiveDemuxer::GetStartTime() const {
// we always assume a start time of 0
return base::TimeDelta();
}
-const AudioDecoderConfig& ShellDemuxer::AudioConfig() {
+const AudioDecoderConfig& ProgressiveDemuxer::AudioConfig() {
return parser_->AudioConfig();
}
-const VideoDecoderConfig& ShellDemuxer::VideoConfig() {
+const VideoDecoderConfig& ProgressiveDemuxer::VideoConfig() {
return parser_->VideoConfig();
}
-bool ShellDemuxer::MessageLoopBelongsToCurrentThread() const {
+bool ProgressiveDemuxer::MessageLoopBelongsToCurrentThread() const {
return message_loop_->BelongsToCurrentThread();
}
diff --git a/src/cobalt/media/filters/shell_demuxer.h b/src/cobalt/media/progressive/progressive_demuxer.h
similarity index 81%
rename from src/cobalt/media/filters/shell_demuxer.h
rename to src/cobalt/media/progressive/progressive_demuxer.h
index 38f3dde..6ecb323 100644
--- a/src/cobalt/media/filters/shell_demuxer.h
+++ b/src/cobalt/media/progressive/progressive_demuxer.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_MEDIA_FILTERS_SHELL_DEMUXER_H_
-#define COBALT_MEDIA_FILTERS_SHELL_DEMUXER_H_
+#ifndef COBALT_MEDIA_PROGRESSIVE_PROGRESSIVE_DEMUXER_H_
+#define COBALT_MEDIA_PROGRESSIVE_PROGRESSIVE_DEMUXER_H_
#include <deque>
#include <memory>
@@ -28,17 +28,17 @@
#include "cobalt/media/base/demuxer_stream.h"
#include "cobalt/media/base/media_log.h"
#include "cobalt/media/base/ranges.h"
-#include "cobalt/media/filters/shell_parser.h"
+#include "cobalt/media/progressive/progressive_parser.h"
namespace cobalt {
namespace media {
class DecoderBuffer;
-class ShellDemuxer;
+class ProgressiveDemuxer;
-class ShellDemuxerStream : public DemuxerStream {
+class ProgressiveDemuxerStream : public DemuxerStream {
public:
- ShellDemuxerStream(ShellDemuxer* demuxer, Type type);
+ ProgressiveDemuxerStream(ProgressiveDemuxer* demuxer, Type type);
// DemuxerStream implementation
void Read(const ReadCB& read_cb) override;
@@ -56,7 +56,7 @@
NOTREACHED();
}
- // Functions used by ShellDemuxer
+ // Functions used by ProgressiveDemuxer
Ranges<base::TimeDelta> GetBufferedRanges();
void EnqueueBuffer(scoped_refptr<DecoderBuffer> buffer);
void FlushBuffers();
@@ -72,7 +72,7 @@
void RebuildEnqueuedRanges_Locked();
// non-owning pointer to avoid circular reference
- ShellDemuxer* demuxer_;
+ ProgressiveDemuxer* demuxer_;
Type type_;
// Used to protect everything below.
@@ -97,19 +97,19 @@
size_t total_buffer_size_ = 0;
size_t total_buffer_count_ = 0;
- DISALLOW_COPY_AND_ASSIGN(ShellDemuxerStream);
+ DISALLOW_COPY_AND_ASSIGN(ProgressiveDemuxerStream);
};
-class MEDIA_EXPORT ShellDemuxer : public Demuxer {
+class MEDIA_EXPORT ProgressiveDemuxer : public Demuxer {
public:
- ShellDemuxer(const scoped_refptr<base::SingleThreadTaskRunner>& message_loop,
- DecoderBuffer::Allocator* buffer_allocator,
- DataSource* data_source,
- const scoped_refptr<MediaLog>& media_log);
- ~ShellDemuxer() override;
+ ProgressiveDemuxer(
+ const scoped_refptr<base::SingleThreadTaskRunner>& message_loop,
+ DecoderBuffer::Allocator* buffer_allocator, DataSource* data_source,
+ const scoped_refptr<MediaLog>& media_log);
+ ~ProgressiveDemuxer() override;
// Demuxer implementation.
- std::string GetDisplayName() const override { return "ShellDemuxer"; }
+ std::string GetDisplayName() const override { return "ProgressiveDemuxer"; }
void Initialize(DemuxerHost* host, const PipelineStatusCB& status_cb,
bool enable_text_tracks) override;
void AbortPendingReads() override {}
@@ -140,12 +140,12 @@
// in to it, and enqueue the data in the appropriate demuxer stream.
void Request(DemuxerStream::Type type);
- // The DemuxerStream objects ask their parent ShellDemuxer stream class
+ // The DemuxerStream objects ask their parent ProgressiveDemuxer stream class
// for these configuration data rather than duplicating in the child classes
const AudioDecoderConfig& AudioConfig();
const VideoDecoderConfig& VideoConfig();
- // Provide access to ShellDemuxerStream.
+ // Provide access to ProgressiveDemuxerStream.
bool MessageLoopBelongsToCurrentThread() const;
private:
@@ -170,17 +170,17 @@
base::Thread blocking_thread_;
DataSource* data_source_;
scoped_refptr<MediaLog> media_log_;
- scoped_refptr<ShellDataSourceReader> reader_;
+ scoped_refptr<DataSourceReader> reader_;
base::Lock lock_for_stopped_;
bool stopped_;
bool flushing_;
- std::unique_ptr<ShellDemuxerStream> audio_demuxer_stream_;
- std::unique_ptr<ShellDemuxerStream> video_demuxer_stream_;
- scoped_refptr<ShellParser> parser_;
+ std::unique_ptr<ProgressiveDemuxerStream> audio_demuxer_stream_;
+ std::unique_ptr<ProgressiveDemuxerStream> video_demuxer_stream_;
+ scoped_refptr<ProgressiveParser> parser_;
- scoped_refptr<ShellAU> requested_au_;
+ scoped_refptr<AvcAccessUnit> requested_au_;
bool audio_reached_eos_;
bool video_reached_eos_;
};
@@ -188,4 +188,4 @@
} // namespace media
} // namespace cobalt
-#endif // COBALT_MEDIA_FILTERS_SHELL_DEMUXER_H_
+#endif // COBALT_MEDIA_PROGRESSIVE_PROGRESSIVE_DEMUXER_H_
diff --git a/src/cobalt/media/filters/shell_parser.cc b/src/cobalt/media/progressive/progressive_parser.cc
similarity index 71%
rename from src/cobalt/media/filters/shell_parser.cc
rename to src/cobalt/media/progressive/progressive_parser.cc
index 3ff978e..f9ffb84 100644
--- a/src/cobalt/media/filters/shell_parser.cc
+++ b/src/cobalt/media/progressive/progressive_parser.cc
@@ -12,24 +12,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "cobalt/media/filters/shell_parser.h"
+#include "cobalt/media/progressive/progressive_parser.h"
#include "base/logging.h"
#include "cobalt/media/base/timestamp_constants.h"
-#include "cobalt/media/filters/shell_mp4_parser.h"
+#include "cobalt/media/progressive/mp4_parser.h"
namespace cobalt {
namespace media {
-// ==== ShellParser ============================================================
+// ==== ProgressiveParser
+// ============================================================
// how many bytes to download of the file to determine type?
-const int ShellParser::kInitialHeaderSize = 9;
+const int ProgressiveParser::kInitialHeaderSize = 9;
// static
-PipelineStatus ShellParser::Construct(
- scoped_refptr<ShellDataSourceReader> reader,
- scoped_refptr<ShellParser>* parser,
+PipelineStatus ProgressiveParser::Construct(
+ scoped_refptr<DataSourceReader> reader,
+ scoped_refptr<ProgressiveParser>* parser,
const scoped_refptr<MediaLog>& media_log) {
DCHECK(parser);
DCHECK(media_log);
@@ -44,15 +45,15 @@
}
// attempt to construct mp4 parser from this header
- return ShellMP4Parser::Construct(reader, header, parser, media_log);
+ return MP4Parser::Construct(reader, header, parser, media_log);
}
-ShellParser::ShellParser(scoped_refptr<ShellDataSourceReader> reader)
+ProgressiveParser::ProgressiveParser(scoped_refptr<DataSourceReader> reader)
: reader_(reader), duration_(kInfiniteDuration), bits_per_second_(0) {}
-ShellParser::~ShellParser() {}
+ProgressiveParser::~ProgressiveParser() {}
-bool ShellParser::IsConfigComplete() {
+bool ProgressiveParser::IsConfigComplete() {
return video_config_.IsValidConfig() && audio_config_.IsValidConfig() &&
duration_ != kInfiniteDuration;
}
diff --git a/src/cobalt/media/filters/shell_parser.h b/src/cobalt/media/progressive/progressive_parser.h
similarity index 77%
rename from src/cobalt/media/filters/shell_parser.h
rename to src/cobalt/media/progressive/progressive_parser.h
index 119a20c..a0e6f41 100644
--- a/src/cobalt/media/filters/shell_parser.h
+++ b/src/cobalt/media/progressive/progressive_parser.h
@@ -12,31 +12,31 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_MEDIA_FILTERS_SHELL_PARSER_H_
-#define COBALT_MEDIA_FILTERS_SHELL_PARSER_H_
-
+#ifndef COBALT_MEDIA_PROGRESSIVE_PARSER_H_
+#define COBALT_MEDIA_PROGRESSIVE_PARSER_H_
#include "base/memory/ref_counted.h"
#include "cobalt/media/base/audio_decoder_config.h"
#include "cobalt/media/base/demuxer_stream.h"
#include "cobalt/media/base/media_log.h"
#include "cobalt/media/base/pipeline.h"
-#include "cobalt/media/base/shell_data_source_reader.h"
#include "cobalt/media/base/video_decoder_config.h"
-#include "cobalt/media/filters/shell_au.h"
+#include "cobalt/media/progressive/avc_access_unit.h"
+#include "cobalt/media/progressive/data_source_reader.h"
namespace cobalt {
namespace media {
-// abstract base class to define a stream parser interface used by ShellDemuxer.
-class ShellParser : public base::RefCountedThreadSafe<ShellParser> {
+// abstract base class to define a stream parser interface used by
+// ProgressiveDemuxer.
+class ProgressiveParser : public base::RefCountedThreadSafe<ProgressiveParser> {
public:
static const int kInitialHeaderSize;
// Determine stream type, construct appropriate parser object, and returns
// PIPELINE_OK on success or error code.
- static PipelineStatus Construct(scoped_refptr<ShellDataSourceReader> reader,
- scoped_refptr<ShellParser>* parser,
+ static PipelineStatus Construct(scoped_refptr<DataSourceReader> reader,
+ scoped_refptr<ProgressiveParser>* parser,
const scoped_refptr<MediaLog>& media_log);
- explicit ShellParser(scoped_refptr<ShellDataSourceReader> reader);
+ explicit ProgressiveParser(scoped_refptr<DataSourceReader> reader);
// Seek through the file looking for audio and video configuration info,
// saving as much config state as is possible. Should try to be fast but this
@@ -47,10 +47,10 @@
// downloding and decoding the next access unit in the stream, or NULL on
// fatal error. On success this advances the respective audio or video cursor
// to the next AU.
- virtual scoped_refptr<ShellAU> GetNextAU(DemuxerStream::Type type) = 0;
+ virtual scoped_refptr<AvcAccessUnit> GetNextAU(DemuxerStream::Type type) = 0;
// Write the appropriate prepend header for the supplied au into the supplied
// buffer. Return false on error.
- virtual bool Prepend(scoped_refptr<ShellAU> au,
+ virtual bool Prepend(scoped_refptr<AvcAccessUnit> au,
scoped_refptr<DecoderBuffer> buffer) = 0;
// Advance internal state to provided timestamp. Return false on error.
virtual bool SeekTo(base::TimeDelta timestamp) = 0;
@@ -68,9 +68,9 @@
protected:
// only allow RefCountedThreadSafe to delete us
- friend class base::RefCountedThreadSafe<ShellParser>;
- virtual ~ShellParser();
- scoped_refptr<ShellDataSourceReader> reader_;
+ friend class base::RefCountedThreadSafe<ProgressiveParser>;
+ virtual ~ProgressiveParser();
+ scoped_refptr<DataSourceReader> reader_;
AudioDecoderConfig audio_config_;
VideoDecoderConfig video_config_;
base::TimeDelta duration_;
@@ -80,4 +80,4 @@
} // namespace media
} // namespace cobalt
-#endif // COBALT_MEDIA_FILTERS_SHELL_PARSER_H_
+#endif // COBALT_MEDIA_PROGRESSIVE_PARSER_H_
diff --git a/src/cobalt/media/filters/shell_rbsp_stream.cc b/src/cobalt/media/progressive/rbsp_stream.cc
similarity index 90%
rename from src/cobalt/media/filters/shell_rbsp_stream.cc
rename to src/cobalt/media/progressive/rbsp_stream.cc
index 6a3fb50..ea90f7a 100644
--- a/src/cobalt/media/filters/shell_rbsp_stream.cc
+++ b/src/cobalt/media/progressive/rbsp_stream.cc
@@ -12,15 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "cobalt/media/filters/shell_rbsp_stream.h"
+#include "cobalt/media/progressive/rbsp_stream.h"
#include "base/logging.h"
namespace cobalt {
namespace media {
-ShellRBSPStream::ShellRBSPStream(const uint8* nalu_buffer,
- size_t nalu_buffer_size)
+RBSPStream::RBSPStream(const uint8* nalu_buffer, size_t nalu_buffer_size)
: nalu_buffer_(nalu_buffer),
nalu_buffer_size_(nalu_buffer_size),
nalu_buffer_byte_offset_(0),
@@ -29,7 +28,7 @@
rbsp_bit_offset_(0) {}
// read unsigned Exp-Golomb coded integer, ISO 14496-10 Section 9.1
-bool ShellRBSPStream::ReadUEV(uint32* uev_out) {
+bool RBSPStream::ReadUEV(uint32* uev_out) {
DCHECK(uev_out);
int leading_zero_bits = -1;
for (uint8 b = 0; b == 0; leading_zero_bits++) {
@@ -52,7 +51,7 @@
}
// read signed Exp-Golomb coded integer, ISO 14496-10 Section 9.1
-bool ShellRBSPStream::ReadSEV(int32* sev_out) {
+bool RBSPStream::ReadSEV(int32* sev_out) {
DCHECK(sev_out);
// we start off by reading an unsigned Exp-Golomb coded number
uint32 uev = 0;
@@ -71,7 +70,7 @@
// read and return up to 32 bits, filling from the right, meaning that
// ReadBits(17) on a stream of all 1s would return 0x01ffff
-bool ShellRBSPStream::ReadBits(size_t bits, uint32* bits_out) {
+bool RBSPStream::ReadBits(size_t bits, uint32* bits_out) {
DCHECK(bits_out);
if (bits > 32) {
return false;
@@ -105,7 +104,7 @@
}
// jump over bytes in the RBSP stream
-bool ShellRBSPStream::SkipBytes(size_t bytes) {
+bool RBSPStream::SkipBytes(size_t bytes) {
for (int i = 0; i < bytes; ++i) {
if (!ConsumeNALUByte()) {
return false;
@@ -115,7 +114,7 @@
}
// jump over bits in the RBSP stream
-bool ShellRBSPStream::SkipBits(size_t bits) {
+bool RBSPStream::SkipBits(size_t bits) {
// skip bytes first
size_t bytes = bits >> 3;
if (bytes > 0) {
@@ -152,7 +151,7 @@
// advance by one byte through the NALU buffer, respecting the encoding of
// 00 00 03 => 00 00. Updates the state of current_nalu_byte_ to the new value.
-bool ShellRBSPStream::ConsumeNALUByte() {
+bool RBSPStream::ConsumeNALUByte() {
if (nalu_buffer_byte_offset_ >= nalu_buffer_size_) {
return false;
}
@@ -174,7 +173,7 @@
// return single bit in the LSb from the RBSP stream. Bits are read from MSb
// to LSb in the stream.
-bool ShellRBSPStream::ReadRBSPBit(uint8* bit_out) {
+bool RBSPStream::ReadRBSPBit(uint8* bit_out) {
DCHECK(bit_out);
// check to see if we need to consume a fresh byte
if (rbsp_bit_offset_ == 0) {
@@ -190,7 +189,7 @@
return true;
}
-bool ShellRBSPStream::ReadRBSPByte(uint8* byte_out) {
+bool RBSPStream::ReadRBSPByte(uint8* byte_out) {
DCHECK(byte_out);
// fast path for byte-aligned access
if (rbsp_bit_offset_ == 0) {
diff --git a/src/cobalt/media/filters/shell_rbsp_stream.h b/src/cobalt/media/progressive/rbsp_stream.h
similarity index 91%
rename from src/cobalt/media/filters/shell_rbsp_stream.h
rename to src/cobalt/media/progressive/rbsp_stream.h
index 5a46499..0c8d8bc 100644
--- a/src/cobalt/media/filters/shell_rbsp_stream.h
+++ b/src/cobalt/media/progressive/rbsp_stream.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef COBALT_MEDIA_FILTERS_SHELL_RBSP_STREAM_H_
-#define COBALT_MEDIA_FILTERS_SHELL_RBSP_STREAM_H_
+#ifndef COBALT_MEDIA_PROGRESSIVE_RBSP_STREAM_H_
+#define COBALT_MEDIA_PROGRESSIVE_RBSP_STREAM_H_
#include "base/basictypes.h"
@@ -25,11 +25,11 @@
// that some other atoms are defined. This class takes a non-owning reference
// to a buffer and extract various types from the stream while silently
// consuming the extra encoding bytes and advancing a bit stream pointer.
-class ShellRBSPStream {
+class RBSPStream {
public:
// NON-OWNING pointer to buffer. It is assumed the client will dispose of
// this buffer.
- ShellRBSPStream(const uint8* nalu_buffer, size_t nalu_buffer_size);
+ RBSPStream(const uint8* nalu_buffer, size_t nalu_buffer_size);
// all Read/Skip methods return the value by reference and return true
// on success, false on read error/EOB. Once the object has returned
// false the consistency of the data is not guaranteed.
@@ -70,4 +70,4 @@
} // namespace media
} // namespace cobalt
-#endif // COBALT_MEDIA_FILTERS_SHELL_RBSP_STREAM_H_
+#endif // COBALT_MEDIA_PROGRESSIVE_RBSP_STREAM_H_
diff --git a/src/cobalt/media/filters/shell_rbsp_stream_unittest.cc b/src/cobalt/media/progressive/rbsp_stream_unittest.cc
similarity index 89%
rename from src/cobalt/media/filters/shell_rbsp_stream_unittest.cc
rename to src/cobalt/media/progressive/rbsp_stream_unittest.cc
index 472639b..33669ed 100644
--- a/src/cobalt/media/filters/shell_rbsp_stream_unittest.cc
+++ b/src/cobalt/media/progressive/rbsp_stream_unittest.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "cobalt/media/filters/shell_rbsp_stream.h"
+#include "cobalt/media/progressive/rbsp_stream.h"
#include <list>
#include <memory>
@@ -24,11 +24,11 @@
namespace cobalt {
namespace media {
-class ShellRBSPStreamTest : public testing::Test {
+class RBSPStreamTest : public testing::Test {
protected:
- ShellRBSPStreamTest() {}
+ RBSPStreamTest() {}
- virtual ~ShellRBSPStreamTest() {}
+ virtual ~RBSPStreamTest() {}
// Given num encode the value in signed exp-golomb syntax and push
// the value on the provided bitlist
@@ -76,7 +76,7 @@
}
// after building a bitlist in various fun ways call this method to
- // create a buffer on the heap that can be passed to ShellRBSPStream
+ // create a buffer on the heap that can be passed to RBSPStream
// for deserialization.
std::unique_ptr<uint8[]> SerializeToBuffer(const std::list<bool>& bitlist,
bool add_sequence_bytes,
@@ -150,7 +150,7 @@
}
};
-TEST_F(ShellRBSPStreamTest, ReadUEV) {
+TEST_F(RBSPStreamTest, ReadUEV) {
std::list<bool> fibbits;
// encode first 47 Fibonacci numbers
uint32 f_n_minus_2 = 0;
@@ -171,9 +171,9 @@
size_t fib_buffer_no_sequence_size;
std::unique_ptr<uint8[]> fib_buffer_no_sequence =
SerializeToBuffer(fibbits, false, fib_buffer_no_sequence_size);
- ShellRBSPStream fib_stream(fib_buffer.get(), fib_buffer_size);
- ShellRBSPStream fib_stream_no_sequence(fib_buffer_no_sequence.get(),
- fib_buffer_no_sequence_size);
+ RBSPStream fib_stream(fib_buffer.get(), fib_buffer_size);
+ RBSPStream fib_stream_no_sequence(fib_buffer_no_sequence.get(),
+ fib_buffer_no_sequence_size);
// deserialize the same sequence from both buffers
uint32 uev = 0;
uint32 uev_n = 0;
@@ -203,7 +203,7 @@
ASSERT_FALSE(fib_stream_no_sequence.ReadUEV(&uev_n));
}
-TEST_F(ShellRBSPStreamTest, ReadSEV) {
+TEST_F(RBSPStreamTest, ReadSEV) {
std::list<bool> lucasbits;
// encode first 44 Lucas numbers with alternating sign
int32 l_n_minus_2 = 1;
@@ -227,10 +227,9 @@
size_t lucas_deseq_buffer_size = 0;
std::unique_ptr<uint8[]> lucas_deseq_buffer =
SerializeToBuffer(lucasbits, false, lucas_deseq_buffer_size);
- ShellRBSPStream lucas_seq_stream(lucas_seq_buffer.get(),
- lucas_seq_buffer_size);
- ShellRBSPStream lucas_deseq_stream(lucas_deseq_buffer.get(),
- lucas_deseq_buffer_size);
+ RBSPStream lucas_seq_stream(lucas_seq_buffer.get(), lucas_seq_buffer_size);
+ RBSPStream lucas_deseq_stream(lucas_deseq_buffer.get(),
+ lucas_deseq_buffer_size);
l_n_minus_2 = 1;
l_n_minus_1 = 2;
int32 sev = 0;
@@ -286,10 +285,10 @@
// 1111 111+0 (to complete the byte)
0xfe};
-TEST_F(ShellRBSPStreamTest, ReadUEVTooLarge) {
+TEST_F(RBSPStreamTest, ReadUEVTooLarge) {
// construct a stream from the supplied test data
- ShellRBSPStream uev_too_big(kTestRBSPExpGolombTooBig,
- sizeof(kTestRBSPExpGolombTooBig));
+ RBSPStream uev_too_big(kTestRBSPExpGolombTooBig,
+ sizeof(kTestRBSPExpGolombTooBig));
// first call should succeed
uint32 uev = 0;
ASSERT_TRUE(uev_too_big.ReadUEV(&uev));
@@ -301,10 +300,10 @@
ASSERT_FALSE(uev_too_big.ReadUEV(&uev));
}
-TEST_F(ShellRBSPStreamTest, ReadSEVTooLarge) {
+TEST_F(RBSPStreamTest, ReadSEVTooLarge) {
// construct a stream from the supplied test data
- ShellRBSPStream sev_too_big(kTestRBSPExpGolombTooBig,
- sizeof(kTestRBSPExpGolombTooBig));
+ RBSPStream sev_too_big(kTestRBSPExpGolombTooBig,
+ sizeof(kTestRBSPExpGolombTooBig));
// first call should succeed
int32 sev = 0;
ASSERT_TRUE(sev_too_big.ReadSEV(&sev));
@@ -316,7 +315,7 @@
ASSERT_FALSE(sev_too_big.ReadSEV(&sev));
}
-TEST_F(ShellRBSPStreamTest, ReadBit) {
+TEST_F(RBSPStreamTest, ReadBit) {
std::list<bool> padded_ones;
// build a bitfield of 1 padded by n zeros, for n in range[0, 1024]
for (int i = 0; i < 1024; i++) {
@@ -329,12 +328,12 @@
size_t sequence_buff_size = 0;
std::unique_ptr<uint8[]> sequence_buff =
SerializeToBuffer(padded_ones, true, sequence_buff_size);
- ShellRBSPStream seq_stream(sequence_buff.get(), sequence_buff_size);
+ RBSPStream seq_stream(sequence_buff.get(), sequence_buff_size);
size_t desequence_buff_size = 0;
std::unique_ptr<uint8[]> desequence_buff =
SerializeToBuffer(padded_ones, false, desequence_buff_size);
- ShellRBSPStream deseq_stream(desequence_buff.get(), desequence_buff_size);
+ RBSPStream deseq_stream(desequence_buff.get(), desequence_buff_size);
for (std::list<bool>::iterator it = padded_ones.begin();
it != padded_ones.end(); ++it) {
uint8 bit = 0;
@@ -351,7 +350,7 @@
ASSERT_FALSE(deseq_stream.ReadByte(&fail_byte));
}
-TEST_F(ShellRBSPStreamTest, ReadByte) {
+TEST_F(RBSPStreamTest, ReadByte) {
// build a field of 16 x (0xaa byte followed by 0 bit)
std::list<bool> aa_field;
for (int i = 0; i < 16; ++i) {
@@ -364,7 +363,7 @@
size_t aabuff_size = 0;
std::unique_ptr<uint8[]> aabuff =
SerializeToBuffer(aa_field, true, aabuff_size);
- ShellRBSPStream aa_stream(aabuff.get(), aabuff_size);
+ RBSPStream aa_stream(aabuff.get(), aabuff_size);
for (int i = 0; i < 16; ++i) {
uint8 aa = 0;
ASSERT_TRUE(aa_stream.ReadByte(&aa));
@@ -397,11 +396,11 @@
size_t zseqbuff_size = 0;
std::unique_ptr<uint8[]> zseqbuff =
SerializeToBuffer(zero_field, true, zseqbuff_size);
- ShellRBSPStream zseq_stream(zseqbuff.get(), zseqbuff_size);
+ RBSPStream zseq_stream(zseqbuff.get(), zseqbuff_size);
size_t zdseqbuff_size = 0;
std::unique_ptr<uint8[]> zdseqbuff =
SerializeToBuffer(zero_field, false, zdseqbuff_size);
- ShellRBSPStream zdseq_stream(zdseqbuff.get(), zdseqbuff_size);
+ RBSPStream zdseq_stream(zdseqbuff.get(), zdseqbuff_size);
for (int i = 0; i < 24; ++i) {
// read the leading 1 bit
uint8 seq_bit = 0;
@@ -454,7 +453,7 @@
}
}
-TEST_F(ShellRBSPStreamTest, ReadBits) {
+TEST_F(RBSPStreamTest, ReadBits) {
// test the assertion in the ReadBits comment, as it had a bug :)
std::list<bool> seventeen_ones;
for (int i = 0; i < 17; ++i) {
@@ -463,8 +462,8 @@
size_t seventeen_ones_size = 0;
std::unique_ptr<uint8[]> seventeen_ones_buff =
SerializeToBuffer(seventeen_ones, false, seventeen_ones_size);
- ShellRBSPStream seventeen_ones_stream(seventeen_ones_buff.get(),
- seventeen_ones_size);
+ RBSPStream seventeen_ones_stream(seventeen_ones_buff.get(),
+ seventeen_ones_size);
uint32 seventeen_ones_word = 0;
ASSERT_TRUE(seventeen_ones_stream.ReadBits(17, &seventeen_ones_word));
ASSERT_EQ(seventeen_ones_word, 0x0001ffff);
@@ -479,7 +478,7 @@
}
size_t pows_size = 0;
std::unique_ptr<uint8[]> pows_buff = SerializeToBuffer(pows, true, pows_size);
- ShellRBSPStream pows_stream(pows_buff.get(), pows_size);
+ RBSPStream pows_stream(pows_buff.get(), pows_size);
// ReadBits(0) should succeed and not modify the value of the ref output or
// internal bit iterator
uint32 dont_touch = 0xfeedfeed;
@@ -493,7 +492,7 @@
}
}
-TEST_F(ShellRBSPStreamTest, SkipBytes) {
+TEST_F(RBSPStreamTest, SkipBytes) {
// serialize all nine-bit values from zero to 512
std::list<bool> nines;
for (int i = 0; i < 512; ++i) {
@@ -507,8 +506,8 @@
size_t nines_deseq_size = 0;
std::unique_ptr<uint8[]> nines_deseq_buff =
SerializeToBuffer(nines, false, nines_deseq_size);
- ShellRBSPStream nines_stream(nines_buff.get(), nines_size);
- ShellRBSPStream nines_deseq_stream(nines_deseq_buff.get(), nines_deseq_size);
+ RBSPStream nines_stream(nines_buff.get(), nines_size);
+ RBSPStream nines_deseq_stream(nines_deseq_buff.get(), nines_deseq_size);
// iterate through streams, skipping in one and reading in the other, always
// comparing values.
for (int i = 0; i < 512; ++i) {
@@ -547,9 +546,9 @@
size_t run_length_deseq_size = 0;
std::unique_ptr<uint8[]> run_length_deseq_buff =
SerializeToBuffer(run_length, false, run_length_deseq_size);
- ShellRBSPStream run_length_stream(run_length_buff.get(), run_length_size);
- ShellRBSPStream run_length_deseq_stream(run_length_deseq_buff.get(),
- run_length_deseq_size);
+ RBSPStream run_length_stream(run_length_buff.get(), run_length_size);
+ RBSPStream run_length_deseq_stream(run_length_deseq_buff.get(),
+ run_length_deseq_size);
// read first bit, skip first byte from each stream, read next bit
uint8 bit = 0;
ASSERT_TRUE(run_length_stream.ReadBit(&bit));
@@ -593,7 +592,7 @@
ASSERT_FALSE(run_length_deseq_stream.SkipBytes(1));
}
-TEST_F(ShellRBSPStreamTest, SkipBits) {
+TEST_F(RBSPStreamTest, SkipBits) {
std::list<bool> one_ohs;
// encode one 1, followed by one zero, followed by 2 1s, followed by 2 zeros,
// etc
@@ -611,8 +610,8 @@
size_t skip_ohs_size = 0;
std::unique_ptr<uint8[]> skip_ohs_buff =
SerializeToBuffer(one_ohs, false, skip_ohs_size);
- ShellRBSPStream skip_ones(skip_ones_buff.get(), skip_ones_size);
- ShellRBSPStream skip_ohs(skip_ohs_buff.get(), skip_ohs_size);
+ RBSPStream skip_ones(skip_ones_buff.get(), skip_ones_size);
+ RBSPStream skip_ohs(skip_ohs_buff.get(), skip_ohs_size);
for (int i = 1; i < 64; ++i) {
// skip the ones
ASSERT_TRUE(skip_ones.SkipBits(i));
diff --git a/src/cobalt/media/sandbox/demuxer_helper.cc b/src/cobalt/media/sandbox/demuxer_helper.cc
index fa343fa..c5b2991 100644
--- a/src/cobalt/media/sandbox/demuxer_helper.cc
+++ b/src/cobalt/media/sandbox/demuxer_helper.cc
@@ -24,7 +24,7 @@
#include "media/base/bind_to_loop.h"
#include "media/base/decoder_buffer.h"
#include "media/base/video_decoder_config.h"
-#include "media/filters/shell_demuxer.h"
+#include "media/progressive/progressive_demuxer.h"
namespace cobalt {
namespace media {
@@ -263,7 +263,7 @@
fetcher_factory->network_module(),
loader::kNoCORSMode, loader::Origin()));
scoped_refptr<Demuxer> demuxer =
- new ::media::ShellDemuxer(media_message_loop, data_source);
+ new ::media::ProgressiveDemuxer(media_message_loop, data_source);
demuxer->Initialize(
host_, base::Bind(&DemuxerHelper::OnDemuxerReady, base::Unretained(this),
demuxer, demuxer_ready_cb, bytes_to_cache));
diff --git a/src/cobalt/media_capture/encoders/audio_encoder.h b/src/cobalt/media_capture/encoders/audio_encoder.h
index 63134e0..0efe09b 100644
--- a/src/cobalt/media_capture/encoders/audio_encoder.h
+++ b/src/cobalt/media_capture/encoders/audio_encoder.h
@@ -20,10 +20,10 @@
#include "base/basictypes.h"
#include "base/strings/string_piece.h"
#include "base/time/time.h"
+#include "cobalt/media/base/audio_bus.h"
#include "cobalt/media_stream/audio_parameters.h"
#include "starboard/common/mutex.h"
-#include "cobalt/media/base/shell_audio_bus.h"
namespace cobalt {
namespace media_capture {
@@ -31,7 +31,7 @@
class AudioEncoder {
public:
- typedef media::ShellAudioBus ShellAudioBus;
+ typedef media::AudioBus AudioBus;
class Listener {
public:
@@ -44,7 +44,7 @@
virtual ~AudioEncoder() = default;
// Encode raw audio data.
- virtual void Encode(const ShellAudioBus& audio_bus,
+ virtual void Encode(const AudioBus& audio_bus,
base::TimeTicks reference_time) = 0;
// Finish encoding.
virtual void Finish(base::TimeTicks timecode) = 0;
diff --git a/src/cobalt/media_capture/encoders/flac_audio_encoder.cc b/src/cobalt/media_capture/encoders/flac_audio_encoder.cc
index 0e45933..7c57c69 100644
--- a/src/cobalt/media_capture/encoders/flac_audio_encoder.cc
+++ b/src/cobalt/media_capture/encoders/flac_audio_encoder.cc
@@ -59,11 +59,11 @@
base::Bind(&FlacAudioEncoder::DestroyEncoder, base::Unretained(this)));
}
-void FlacAudioEncoder::Encode(const ShellAudioBus& audio_bus,
+void FlacAudioEncoder::Encode(const AudioBus& audio_bus,
base::TimeTicks reference_time) {
- std::unique_ptr<ShellAudioBus> audio_bus_copy(
- new ShellAudioBus(audio_bus.channels(), audio_bus.frames(),
- audio_bus.sample_type(), audio_bus.storage_type()));
+ std::unique_ptr<AudioBus> audio_bus_copy(
+ new AudioBus(audio_bus.channels(), audio_bus.frames(),
+ audio_bus.sample_type(), audio_bus.storage_type()));
audio_bus_copy->Assign(audio_bus);
// base::Unretained usage is safe here, since we're posting to a thread that
@@ -107,7 +107,7 @@
void FlacAudioEncoder::DestroyEncoder() { flac_encoder_.reset(); }
-void FlacAudioEncoder::DoEncode(std::unique_ptr<ShellAudioBus> audio_bus,
+void FlacAudioEncoder::DoEncode(std::unique_ptr<AudioBus> audio_bus,
base::TimeTicks reference_time) {
DCHECK(flac_encoder_);
flac_encoder_->Encode(audio_bus.get());
diff --git a/src/cobalt/media_capture/encoders/flac_audio_encoder.h b/src/cobalt/media_capture/encoders/flac_audio_encoder.h
index 90d4bd4..a982eaf 100644
--- a/src/cobalt/media_capture/encoders/flac_audio_encoder.h
+++ b/src/cobalt/media_capture/encoders/flac_audio_encoder.h
@@ -36,7 +36,7 @@
// Called from the thread the object is constructed on (usually
// a dedicated audio thread).
- void Encode(const ShellAudioBus& audio_bus,
+ void Encode(const AudioBus& audio_bus,
base::TimeTicks reference_time) override;
// This can be called from any thread
@@ -54,7 +54,7 @@
// These functions are called on the encoder thread.
void CreateEncoder(const media_stream::AudioParameters& params);
void DestroyEncoder();
- void DoEncode(std::unique_ptr<ShellAudioBus> audio_bus,
+ void DoEncode(std::unique_ptr<AudioBus> audio_bus,
base::TimeTicks reference_time);
void DoFinish(base::TimeTicks reference_time);
diff --git a/src/cobalt/media_capture/encoders/linear16_audio_encoder.cc b/src/cobalt/media_capture/encoders/linear16_audio_encoder.cc
index f18f035..c5148ac 100644
--- a/src/cobalt/media_capture/encoders/linear16_audio_encoder.cc
+++ b/src/cobalt/media_capture/encoders/linear16_audio_encoder.cc
@@ -43,9 +43,9 @@
return match_iterator == mime_type_container.begin();
}
-void Linear16AudioEncoder::Encode(const ShellAudioBus& audio_bus,
+void Linear16AudioEncoder::Encode(const AudioBus& audio_bus,
base::TimeTicks reference_time) {
- DCHECK_EQ(audio_bus.sample_type(), ShellAudioBus::kInt16);
+ DCHECK_EQ(audio_bus.sample_type(), AudioBus::kInt16);
DCHECK_EQ(audio_bus.channels(), size_t(1));
auto data = audio_bus.interleaved_data();
size_t data_size = audio_bus.GetSampleSizeInBytes() * audio_bus.frames();
diff --git a/src/cobalt/media_capture/encoders/linear16_audio_encoder.h b/src/cobalt/media_capture/encoders/linear16_audio_encoder.h
index bb5f5d7..75040f4 100644
--- a/src/cobalt/media_capture/encoders/linear16_audio_encoder.h
+++ b/src/cobalt/media_capture/encoders/linear16_audio_encoder.h
@@ -29,7 +29,7 @@
static bool IsLinear16MIMEType(const base::StringPiece& mime_type);
Linear16AudioEncoder() = default;
- void Encode(const ShellAudioBus& audio_bus,
+ void Encode(const AudioBus& audio_bus,
base::TimeTicks reference_time) override;
void Finish(base::TimeTicks reference_time) override;
std::string GetMimeType() const override;
diff --git a/src/cobalt/media_capture/media_recorder.cc b/src/cobalt/media_capture/media_recorder.cc
index 3a015f0..6642bfc 100644
--- a/src/cobalt/media_capture/media_recorder.cc
+++ b/src/cobalt/media_capture/media_recorder.cc
@@ -161,10 +161,10 @@
StopRecording();
}
-void MediaRecorder::OnData(const ShellAudioBus& audio_bus,
+void MediaRecorder::OnData(const AudioBus& audio_bus,
base::TimeTicks reference_time) {
// The source is always int16 data from the microphone.
- DCHECK_EQ(audio_bus.sample_type(), ShellAudioBus::kInt16);
+ DCHECK_EQ(audio_bus.sample_type(), AudioBus::kInt16);
DCHECK_EQ(audio_bus.channels(), size_t(1));
DCHECK(audio_encoder_);
audio_encoder_->Encode(audio_bus, reference_time);
diff --git a/src/cobalt/media_capture/media_recorder.h b/src/cobalt/media_capture/media_recorder.h
index a7b1c9d..5883af8 100644
--- a/src/cobalt/media_capture/media_recorder.h
+++ b/src/cobalt/media_capture/media_recorder.h
@@ -118,7 +118,7 @@
RecordingState state() { return recording_state_; }
// MediaStreamAudioSink overrides.
- void OnData(const ShellAudioBus& audio_bus,
+ void OnData(const AudioBus& audio_bus,
base::TimeTicks reference_time) override;
void OnSetFormat(const media_stream::AudioParameters& params) override;
void OnReadyStateChanged(
diff --git a/src/cobalt/media_capture/media_recorder_test.cc b/src/cobalt/media_capture/media_recorder_test.cc
index cfc5e3c..46fab4a 100644
--- a/src/cobalt/media_capture/media_recorder_test.cc
+++ b/src/cobalt/media_capture/media_recorder_test.cc
@@ -52,7 +52,7 @@
frames.push_back(32767);
frames.push_back(1000);
frames.push_back(0);
- cobalt::media_stream::MediaStreamAudioTrack::ShellAudioBus audio_bus(
+ cobalt::media_stream::MediaStreamAudioTrack::AudioBus audio_bus(
1, frames.size(), frames.data());
base::TimeTicks current_time = base::TimeTicks::Now();
media_recorder->OnData(audio_bus, current_time);
@@ -68,9 +68,8 @@
MOCK_METHOD0(EnsureSourceIsStarted, bool());
MOCK_METHOD0(EnsureSourceIsStopped, void());
- void DeliverDataToTracks(
- const MediaStreamAudioTrack::ShellAudioBus& audio_bus,
- base::TimeTicks reference_time) {
+ void DeliverDataToTracks(const MediaStreamAudioTrack::AudioBus& audio_bus,
+ base::TimeTicks reference_time) {
MediaStreamAudioSource::DeliverDataToTracks(audio_bus, reference_time);
}
@@ -191,8 +190,8 @@
frames.push_back(32767);
frames.push_back(1000);
frames.push_back(0);
- media_stream::MediaStreamAudioTrack::ShellAudioBus audio_bus(1, frames.size(),
- frames.data());
+ media_stream::MediaStreamAudioTrack::AudioBus audio_bus(1, frames.size(),
+ frames.data());
base::TimeTicks current_time = base::TimeTicks::Now();
media_recorder_->OnData(audio_bus, current_time);
current_time += base::TimeDelta::FromSecondsD(frames.size() / kSampleRate);
diff --git a/src/cobalt/media_stream/media_stream_audio_deliverer.h b/src/cobalt/media_stream/media_stream_audio_deliverer.h
index 40628d4..b942bdd 100644
--- a/src/cobalt/media_stream/media_stream_audio_deliverer.h
+++ b/src/cobalt/media_stream/media_stream_audio_deliverer.h
@@ -26,9 +26,10 @@
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
+
+#include "cobalt/media/base/audio_bus.h"
#include "cobalt/media_stream/audio_parameters.h"
-#include "cobalt/media/base/shell_audio_bus.h"
namespace cobalt {
namespace media_stream {
@@ -119,7 +120,7 @@
// Deliver data to all consumers. This method may be called on any thread.
- void OnData(const media::ShellAudioBus& audio_bus,
+ void OnData(const media::AudioBus& audio_bus,
base::TimeTicks reference_time) {
TRACE_EVENT1("media_stream", "MediaStreamAudioDeliverer::OnData",
"reference time (ms)",
diff --git a/src/cobalt/media_stream/media_stream_audio_sink.h b/src/cobalt/media_stream/media_stream_audio_sink.h
index 680bbd3..034dbec 100644
--- a/src/cobalt/media_stream/media_stream_audio_sink.h
+++ b/src/cobalt/media_stream/media_stream_audio_sink.h
@@ -15,12 +15,13 @@
#ifndef COBALT_MEDIA_STREAM_MEDIA_STREAM_AUDIO_SINK_H_
#define COBALT_MEDIA_STREAM_MEDIA_STREAM_AUDIO_SINK_H_
+#include "cobalt/media/base/audio_bus.h"
+
#include "cobalt/media_stream/audio_parameters.h"
#include "cobalt/media_stream/media_stream_source.h"
#include "cobalt/media_stream/media_stream_track.h"
-#include "cobalt/media/base/shell_audio_bus.h"
namespace cobalt {
namespace media_stream {
@@ -29,11 +30,11 @@
// Note: users of this class will call OnSetFormat is before OnData.
class MediaStreamAudioSink {
public:
- typedef media::ShellAudioBus ShellAudioBus;
+ typedef media::AudioBus AudioBus;
MediaStreamAudioSink() = default;
// These are called on the same thread.
- virtual void OnData(const ShellAudioBus& audio_bus,
+ virtual void OnData(const AudioBus& audio_bus,
base::TimeTicks reference_time) = 0;
virtual void OnSetFormat(const media_stream::AudioParameters& params) = 0;
virtual void OnReadyStateChanged(
diff --git a/src/cobalt/media_stream/media_stream_audio_source.cc b/src/cobalt/media_stream/media_stream_audio_source.cc
index 6c20d49..2d15393 100644
--- a/src/cobalt/media_stream/media_stream_audio_source.cc
+++ b/src/cobalt/media_stream/media_stream_audio_source.cc
@@ -60,7 +60,7 @@
}
void MediaStreamAudioSource::DeliverDataToTracks(
- const MediaStreamAudioTrack::ShellAudioBus& audio_bus,
+ const MediaStreamAudioTrack::AudioBus& audio_bus,
base::TimeTicks reference_time) {
deliverer_.OnData(audio_bus, reference_time);
}
diff --git a/src/cobalt/media_stream/media_stream_audio_source.h b/src/cobalt/media_stream/media_stream_audio_source.h
index 77c00d7..69d789c 100644
--- a/src/cobalt/media_stream/media_stream_audio_source.h
+++ b/src/cobalt/media_stream/media_stream_audio_source.h
@@ -58,9 +58,8 @@
// Subclasses should call these methods. |DeliverDataToTracks| can be
// called from a different thread than where MediaStreamAudioSource
// was created.
- void DeliverDataToTracks(
- const MediaStreamAudioTrack::ShellAudioBus& audio_bus,
- base::TimeTicks reference_time);
+ void DeliverDataToTracks(const MediaStreamAudioTrack::AudioBus& audio_bus,
+ base::TimeTicks reference_time);
void SetFormat(const media_stream::AudioParameters& params) {
DLOG(INFO) << "MediaStreamAudioSource@" << this << "::SetFormat("
diff --git a/src/cobalt/media_stream/media_stream_audio_source_test.cc b/src/cobalt/media_stream/media_stream_audio_source_test.cc
index f526bba..4157d3d 100644
--- a/src/cobalt/media_stream/media_stream_audio_source_test.cc
+++ b/src/cobalt/media_stream/media_stream_audio_source_test.cc
@@ -17,7 +17,7 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "cobalt/dom/testing/stub_environment_settings.h"
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
#include "cobalt/media_stream/media_stream_audio_track.h"
#include "cobalt/media_stream/testing/mock_media_stream_audio_source.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -35,7 +35,7 @@
namespace cobalt {
namespace media_stream {
-typedef media::ShellAudioBus ShellAudioBus;
+typedef media::AudioBus AudioBus;
class MediaStreamAudioSourceTest : public testing::Test {
public:
diff --git a/src/cobalt/media_stream/media_stream_audio_track.cc b/src/cobalt/media_stream/media_stream_audio_track.cc
index c6deb82..0823274 100644
--- a/src/cobalt/media_stream/media_stream_audio_track.cc
+++ b/src/cobalt/media_stream/media_stream_audio_track.cc
@@ -69,7 +69,7 @@
stop_callback_ = stop_callback;
}
-void MediaStreamAudioTrack::OnData(const ShellAudioBus& audio_bus,
+void MediaStreamAudioTrack::OnData(const AudioBus& audio_bus,
base::TimeTicks reference_time) {
deliverer_.OnData(audio_bus, reference_time);
}
diff --git a/src/cobalt/media_stream/media_stream_audio_track.h b/src/cobalt/media_stream/media_stream_audio_track.h
index b7d7708..f1b9b7d 100644
--- a/src/cobalt/media_stream/media_stream_audio_track.h
+++ b/src/cobalt/media_stream/media_stream_audio_track.h
@@ -19,7 +19,7 @@
#include "base/strings/string_piece.h"
#include "base/threading/thread_checker.h"
#include "cobalt/dom/event_target.h"
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
#include "cobalt/media_stream/audio_parameters.h"
#include "cobalt/media_stream/media_stream_audio_deliverer.h"
#include "cobalt/media_stream/media_stream_audio_sink.h"
@@ -50,7 +50,7 @@
settings.set_sample_size(parameters.bits_per_sample());
return settings;
}
- typedef media::ShellAudioBus ShellAudioBus;
+ typedef media::AudioBus AudioBus;
explicit MediaStreamAudioTrack(script::EnvironmentSettings* settings)
: MediaStreamTrack(settings) {}
@@ -81,7 +81,7 @@
void Start(const base::Closure& stop_callback);
// Called by MediaStreamAudioDeliverer.
- void OnData(const ShellAudioBus& audio_bus, base::TimeTicks reference_time);
+ void OnData(const AudioBus& audio_bus, base::TimeTicks reference_time);
void OnSetFormat(const media_stream::AudioParameters& params);
THREAD_CHECKER(thread_checker_);
diff --git a/src/cobalt/media_stream/media_stream_audio_track_test.cc b/src/cobalt/media_stream/media_stream_audio_track_test.cc
index 8fc542a..5512ae2 100644
--- a/src/cobalt/media_stream/media_stream_audio_track_test.cc
+++ b/src/cobalt/media_stream/media_stream_audio_track_test.cc
@@ -16,7 +16,7 @@
#include "base/bind_helpers.h"
#include "cobalt/dom/testing/stub_environment_settings.h"
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
#include "cobalt/media_stream/media_stream_audio_deliverer.h"
#include "cobalt/media_stream/testing/mock_media_stream_audio_sink.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -36,7 +36,7 @@
namespace cobalt {
namespace media_stream {
-typedef media::ShellAudioBus ShellAudioBus;
+typedef media::AudioBus AudioBus;
// This fixture is created, so it can be added as a friend to
// |MediaStreamAudioTrack|. This enables calling a private method
@@ -71,8 +71,8 @@
deliverer.OnSetFormat(expected_params);
- ShellAudioBus audio_bus(kChannelCount, kFrameCount, ShellAudioBus::kInt16,
- ShellAudioBus::kInterleaved);
+ AudioBus audio_bus(kChannelCount, kFrameCount, AudioBus::kInt16,
+ AudioBus::kInterleaved);
deliverer.OnData(audio_bus, expected_time);
}
@@ -104,8 +104,8 @@
deliverer.OnSetFormat(expected_params);
- ShellAudioBus audio_bus(kChannelCount, kFrameCount, ShellAudioBus::kInt16,
- ShellAudioBus::kInterleaved);
+ AudioBus audio_bus(kChannelCount, kFrameCount, AudioBus::kInt16,
+ AudioBus::kInterleaved);
deliverer.OnData(audio_bus, expected_time);
}
@@ -141,8 +141,8 @@
deliverer.OnSetFormat(expected_params);
- ShellAudioBus audio_bus(kChannelCount, kFrameCount, ShellAudioBus::kInt16,
- ShellAudioBus::kInterleaved);
+ AudioBus audio_bus(kChannelCount, kFrameCount, AudioBus::kInt16,
+ AudioBus::kInterleaved);
deliverer.OnData(audio_bus, expected_time);
}
@@ -166,8 +166,8 @@
deliverer.OnSetFormat(expected_params);
- ShellAudioBus audio_bus(kChannelCount, kFrameCount, ShellAudioBus::kInt16,
- ShellAudioBus::kInterleaved);
+ AudioBus audio_bus(kChannelCount, kFrameCount, AudioBus::kInt16,
+ AudioBus::kInterleaved);
track->RemoveSink(&mock_sink);
deliverer.OnData(audio_bus, expected_time);
diff --git a/src/cobalt/media_stream/microphone_audio_source.cc b/src/cobalt/media_stream/microphone_audio_source.cc
index 778223e..74eff37 100644
--- a/src/cobalt/media_stream/microphone_audio_source.cc
+++ b/src/cobalt/media_stream/microphone_audio_source.cc
@@ -100,7 +100,7 @@
base::Unretained(this), options))) {}
void MicrophoneAudioSource::OnDataReceived(
- std::unique_ptr<MediaStreamAudioTrack::ShellAudioBus> audio_bus) {
+ std::unique_ptr<MediaStreamAudioTrack::AudioBus> audio_bus) {
base::TimeTicks now = base::TimeTicks::Now();
DeliverDataToTracks(*audio_bus, now);
}
diff --git a/src/cobalt/media_stream/microphone_audio_source.h b/src/cobalt/media_stream/microphone_audio_source.h
index d3049d7..c930298 100644
--- a/src/cobalt/media_stream/microphone_audio_source.h
+++ b/src/cobalt/media_stream/microphone_audio_source.h
@@ -70,7 +70,7 @@
int buffer_size_bytes);
void OnDataReceived(
- std::unique_ptr<MediaStreamAudioTrack::ShellAudioBus> audio_bus);
+ std::unique_ptr<MediaStreamAudioTrack::AudioBus> audio_bus);
void OnDataCompletion();
void OnMicrophoneOpen();
diff --git a/src/cobalt/media_stream/testing/mock_media_stream_audio_sink.h b/src/cobalt/media_stream/testing/mock_media_stream_audio_sink.h
index bd11714..7fa06b6 100644
--- a/src/cobalt/media_stream/testing/mock_media_stream_audio_sink.h
+++ b/src/cobalt/media_stream/testing/mock_media_stream_audio_sink.h
@@ -24,8 +24,8 @@
class MockMediaStreamAudioSink : public MediaStreamAudioSink {
public:
- MOCK_METHOD2(OnData, void(const ShellAudioBus& audio_bus,
- base::TimeTicks reference_time));
+ MOCK_METHOD2(OnData,
+ void(const AudioBus& audio_bus, base::TimeTicks reference_time));
MOCK_METHOD1(OnSetFormat, void(const media_stream::AudioParameters& params));
MOCK_METHOD1(OnReadyStateChanged,
void(media_stream::MediaStreamTrack::ReadyState new_state));
diff --git a/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc b/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc
index 09ce038..9ba721f 100644
--- a/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc
+++ b/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc
@@ -96,6 +96,16 @@
SelectAtlasCache(&offscreen_atlases_, &offscreen_cache_);
SelectAtlasCache(&offscreen_atlases_1d_, &offscreen_cache_1d_);
+ // Delete skottie targets that were not used in the previous render frame.
+ for (size_t index = 0; index < skottie_targets_.size();) {
+ if (skottie_targets_[index]->allocations_used == 0) {
+ skottie_targets_.erase(skottie_targets_.begin() + index);
+ } else {
+ skottie_targets_[index]->allocations_used = 0;
+ ++index;
+ }
+ }
+
// Delete uncached targets that were not used in the previous render frame.
for (size_t index = 0; index < uncached_targets_.size();) {
if (uncached_targets_[index]->allocations_used == 0) {
@@ -215,6 +225,33 @@
return false;
}
+bool OffscreenTargetManager::GetCachedTarget(
+ const skia::SkottieAnimation* skottie_animation, const math::SizeF& size,
+ TargetInfo* out_target_info) {
+ // Each SkottieAnimation uses its own render target cache. The cache is keyed
+ // off the SkottieAnimation's size and pointer value. Using the pointer can
+ // be risky as an object may be destroyed and a new one created with the same
+ // pointer value. However, since each SkottieAnimation is created assuming
+ // the render cache is dirty, it is safe to accidentally use the render cache
+ // of an old SkottieAnimation with a new one.
+ int64_t id = reinterpret_cast<int64_t>(skottie_animation);
+ math::RectF target_size(std::ceil(size.width()), std::ceil(size.height()));
+ for (size_t i = 0; i < skottie_targets_.size(); ++i) {
+ OffscreenAtlas* target = skottie_targets_[i].get();
+ auto iter = target->allocation_map.find(id);
+ if (iter != target->allocation_map.end() &&
+ iter->second.error_data == target_size) {
+ target->allocations_used += 1;
+ out_target_info->framebuffer = target->framebuffer.get();
+ out_target_info->skia_canvas = target->skia_surface->getCanvas();
+ out_target_info->region = iter->second.target_region;
+ return true;
+ }
+ }
+
+ return false;
+}
+
void OffscreenTargetManager::AllocateCachedTarget(const render_tree::Node* node,
const math::SizeF& size,
const ErrorData& error_data,
@@ -325,6 +362,34 @@
}
}
+void OffscreenTargetManager::AllocateCachedTarget(
+ const skia::SkottieAnimation* skottie_animation, const math::SizeF& size,
+ TargetInfo* out_target_info) {
+ // Each SkottieAnimation has its own offscreen atlas.
+ math::Size target_size(static_cast<int>(std::ceil(size.width())),
+ static_cast<int>(std::ceil(size.height())));
+ OffscreenAtlas* atlas = CreateOffscreenAtlas(target_size, true).release();
+ if (!atlas) {
+ // If there was an error allocating the offscreen atlas, indicate by
+ // marking framebuffer and skia canvas as null and returning early.
+ out_target_info->framebuffer = nullptr;
+ out_target_info->skia_canvas = nullptr;
+ return;
+ }
+
+ int64_t id = reinterpret_cast<int64_t>(skottie_animation);
+ // |target_rect| must be calculated the same way as in GetCachedTarget().
+ math::RectF target_rect(std::ceil(size.width()), std::ceil(size.height()));
+ atlas->allocation_map.insert(AllocationMap::value_type(
+ id, AllocationMapValue(target_rect, target_rect)));
+ skottie_targets_.emplace_back(atlas);
+
+ atlas->allocations_used = 1;
+ out_target_info->framebuffer = atlas->framebuffer.get();
+ out_target_info->skia_canvas = atlas->skia_surface->getCanvas();
+ out_target_info->region = target_rect;
+}
+
void OffscreenTargetManager::AllocateUncachedTarget(
const math::SizeF& size, TargetInfo* out_target_info) {
// Align up the requested target size to increase the chances that it can
diff --git a/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.h b/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.h
index ec64a19..69e4bde 100644
--- a/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.h
+++ b/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.h
@@ -23,6 +23,7 @@
#include "cobalt/render_tree/node.h"
#include "cobalt/renderer/backend/egl/framebuffer_render_target.h"
#include "cobalt/renderer/backend/egl/graphics_context.h"
+#include "cobalt/renderer/rasterizer/skia/skottie_animation.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
@@ -85,6 +86,9 @@
bool GetCachedTarget(const render_tree::Node* node,
const CacheErrorFunction1D& error_function,
TargetInfo* out_target_info);
+ bool GetCachedTarget(const skia::SkottieAnimation* skottie_animation,
+ const math::SizeF& size,
+ TargetInfo* out_target_info);
// Allocate a cached offscreen target of the specified size.
// The returned values are only valid until the next call to Update().
@@ -95,6 +99,9 @@
void AllocateCachedTarget(const render_tree::Node* node, float size,
const ErrorData1D& error_data,
TargetInfo* out_target_info);
+ void AllocateCachedTarget(const skia::SkottieAnimation* skottie_animation,
+ const math::SizeF& size,
+ TargetInfo* out_target_info);
// Allocate an uncached render target. The contents of the target cannot be
// reused in subsequent frames. If there was an error allocating the
@@ -122,6 +129,7 @@
std::unique_ptr<OffscreenAtlas> offscreen_cache_1d_;
std::vector<std::unique_ptr<OffscreenAtlas>> uncached_targets_;
+ std::vector<std::unique_ptr<OffscreenAtlas>> skottie_targets_;
// Align offscreen targets to a particular size to more efficiently use the
// offscreen target atlas. Use a power of 2 for the alignment so that a bit
diff --git a/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
index 9ed9a55..7d73e88 100644
--- a/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
@@ -44,6 +44,7 @@
#include "cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.h"
#include "cobalt/renderer/rasterizer/skia/hardware_image.h"
#include "cobalt/renderer/rasterizer/skia/image.h"
+#include "cobalt/renderer/rasterizer/skia/skottie_animation.h"
namespace cobalt {
namespace renderer {
@@ -111,6 +112,17 @@
0, 1);
}
+math::SizeF GetTransformScale(const math::Matrix3F& transform) {
+ math::PointF mapped_origin = transform * math::PointF(0, 0);
+ math::PointF mapped_x = transform * math::PointF(1, 0);
+ math::PointF mapped_y = transform * math::PointF(0, 1);
+ math::Vector2dF mapped_vecx(mapped_x.x() - mapped_origin.x(),
+ mapped_x.y() - mapped_origin.y());
+ math::Vector2dF mapped_vecy(mapped_y.x() - mapped_origin.x(),
+ mapped_y.y() - mapped_origin.y());
+ return math::SizeF(mapped_vecx.Length(), mapped_vecy.Length());
+}
+
bool ImageNodeSupportedNatively(render_tree::ImageNode* image_node) {
// The image node may contain nothing. For example, when it represents a video
// element before any frame is decoded.
@@ -407,17 +419,9 @@
}
draw_state_.opacity = 1.0f;
- math::PointF mapped_origin = draw_state_.transform * math::PointF(0, 0);
- math::PointF mapped_x = draw_state_.transform * math::PointF(1, 0);
- math::PointF mapped_y = draw_state_.transform * math::PointF(0, 1);
- math::Vector2dF mapped_vecx(mapped_x.x() - mapped_origin.x(),
- mapped_x.y() - mapped_origin.y());
- math::Vector2dF mapped_vecy(mapped_y.x() - mapped_origin.x(),
- mapped_y.y() - mapped_origin.y());
- float scale_x = mapped_vecx.Length();
- float scale_y = mapped_vecy.Length();
- draw_state_.transform = math::ScaleMatrix(std::max(1.0f, scale_x),
- std::max(1.0f, scale_y));
+ math::SizeF scale = GetTransformScale(draw_state_.transform);
+ draw_state_.transform = math::ScaleMatrix(
+ std::max(1.0f, scale.width()), std::max(1.0f, scale.height()));
// Don't clip the source since it is in its own local space.
bool limit_to_screen_size = false;
@@ -672,12 +676,63 @@
}
void RenderTreeNodeVisitor::Visit(render_tree::LottieNode* lottie_node) {
- if (!IsVisible(lottie_node->GetBounds())) {
+ const render_tree::LottieNode::Builder& data = lottie_node->data();
+ math::RectF content_rect = data.destination_rect;
+ if (!IsVisible(content_rect)) {
return;
}
- // Use Skottie to render Lottie animations.
- FallbackRasterize(lottie_node);
+ skia::SkottieAnimation* animation =
+ base::polymorphic_downcast<skia::SkottieAnimation*>(data.animation.get());
+ if (animation->GetSize().GetArea() == 0) {
+ return;
+ }
+ animation->SetAnimationTime(data.animation_time);
+
+ // Get an offscreen target to cache the animation. Make the target big enough
+ // to avoid scaling artifacts.
+ math::SizeF scale = GetTransformScale(draw_state_.transform);
+ math::SizeF mapped_size = content_rect.size();
+ // Use a uniform scale to avoid impacting aspect ratio calculations.
+ mapped_size.Scale(std::max(scale.width(), scale.height()));
+
+ OffscreenTargetManager::TargetInfo target_info;
+ if (!offscreen_target_manager_->GetCachedTarget(
+ animation, mapped_size, &target_info)) {
+ // No pre-existing target was found. Allocate a new target.
+ animation->ResetRenderCache();
+ offscreen_target_manager_->AllocateCachedTarget(
+ animation, mapped_size, &target_info);
+ }
+ if (target_info.framebuffer == nullptr) {
+ // Unable to allocate the render target for the animation cache.
+ return;
+ }
+
+ // Add a draw call to update the cache.
+ std::unique_ptr<DrawObject> update_cache(new DrawCallback(
+ base::Bind(&skia::SkottieAnimation::UpdateRenderCache,
+ base::Unretained(animation),
+ base::Unretained(target_info.skia_canvas),
+ target_info.region.size())));
+ draw_object_manager_->AddBatchedExternalDraw(
+ std::move(update_cache), lottie_node->GetTypeId(),
+ target_info.framebuffer, target_info.region);
+
+ // Add a draw call to render the cached animation to the current target.
+ backend::TextureEGL* texture = target_info.framebuffer->GetColorTexture();
+ math::Matrix3F texcoord_transform = GetTexcoordTransform(target_info);
+ if (IsOpaque(draw_state_.opacity)) {
+ std::unique_ptr<DrawObject> draw(
+ new DrawRectTexture(graphics_state_, draw_state_, content_rect, texture,
+ texcoord_transform));
+ AddDraw(std::move(draw), content_rect, DrawObjectManager::kBlendSrcAlpha);
+ } else {
+ std::unique_ptr<DrawObject> draw(new DrawRectColorTexture(
+ graphics_state_, draw_state_, content_rect, kOpaqueWhite, texture,
+ texcoord_transform, false /* clamp_texcoords */));
+ AddDraw(std::move(draw), content_rect, DrawObjectManager::kBlendSrcAlpha);
+ }
}
void RenderTreeNodeVisitor::Visit(
diff --git a/src/cobalt/renderer/rasterizer/pixel_test.cc b/src/cobalt/renderer/rasterizer/pixel_test.cc
index 464ef3d..a751832 100644
--- a/src/cobalt/renderer/rasterizer/pixel_test.cc
+++ b/src/cobalt/renderer/rasterizer/pixel_test.cc
@@ -4538,6 +4538,61 @@
TestTree(lottie_node);
}
+TEST_F(PixelTest, LottiePreserveAspectRatioTooShortAnimationTest) {
+ std::vector<uint8> animation_data =
+ GetFileData(GetTestFilePath("white_material_wave_loading.json"));
+ scoped_refptr<LottieAnimation> animation =
+ GetResourceProvider()->CreateLottieAnimation(
+ reinterpret_cast<char*>(&animation_data[0]), animation_data.size());
+ LottieAnimation::LottieProperties lottie_properties;
+ lottie_properties.UpdateState(LottieAnimation::LottieState::kPlaying);
+ animation->BeginRenderFrame(lottie_properties);
+
+ LottieNode::Builder node_builder =
+ LottieNode::Builder(animation, RectF(output_surface_size().width(),
+ 100.0f));
+ node_builder.animation_time = base::TimeDelta::FromSecondsD(0);
+ scoped_refptr<LottieNode> lottie_node = new LottieNode(node_builder);
+ TestTree(lottie_node);
+}
+
+TEST_F(PixelTest, LottiePreserveAspectRatioTooNarrowAnimationTest) {
+ std::vector<uint8> animation_data =
+ GetFileData(GetTestFilePath("white_material_wave_loading.json"));
+ scoped_refptr<LottieAnimation> animation =
+ GetResourceProvider()->CreateLottieAnimation(
+ reinterpret_cast<char*>(&animation_data[0]), animation_data.size());
+ LottieAnimation::LottieProperties lottie_properties;
+ lottie_properties.UpdateState(LottieAnimation::LottieState::kPlaying);
+ animation->BeginRenderFrame(lottie_properties);
+
+ LottieNode::Builder node_builder =
+ LottieNode::Builder(animation, RectF(100.0f,
+ output_surface_size().height()));
+ node_builder.animation_time = base::TimeDelta::FromSecondsD(0);
+ scoped_refptr<LottieNode> lottie_node = new LottieNode(node_builder);
+ TestTree(lottie_node);
+}
+
+TEST_F(PixelTest, LottieScaledWideAnimationTest) {
+ std::vector<uint8> animation_data =
+ GetFileData(GetTestFilePath("white_material_wave_loading.json"));
+ scoped_refptr<LottieAnimation> animation =
+ GetResourceProvider()->CreateLottieAnimation(
+ reinterpret_cast<char*>(&animation_data[0]), animation_data.size());
+ LottieAnimation::LottieProperties lottie_properties;
+ lottie_properties.UpdateState(LottieAnimation::LottieState::kPlaying);
+ animation->BeginRenderFrame(lottie_properties);
+
+ LottieNode::Builder node_builder =
+ LottieNode::Builder(animation, RectF(output_surface_size()));
+ node_builder.animation_time = base::TimeDelta::FromSecondsD(0);
+ scoped_refptr<LottieNode> lottie_node = new LottieNode(node_builder);
+ TestTree(new MatrixTransformNode(lottie_node,
+ ScaleMatrix(4.0f, 1.0f) *
+ TranslateMatrix(output_surface_size().width() * -0.5f, 0.0f)));
+}
+
#endif // !SB_HAS(BLITTER)
} // namespace rasterizer
diff --git a/src/cobalt/renderer/rasterizer/skia/skottie_animation.cc b/src/cobalt/renderer/rasterizer/skia/skottie_animation.cc
index 4fae87f..224b4a9 100644
--- a/src/cobalt/renderer/rasterizer/skia/skottie_animation.cc
+++ b/src/cobalt/renderer/rasterizer/skia/skottie_animation.cc
@@ -15,6 +15,7 @@
#include "cobalt/renderer/rasterizer/skia/skottie_animation.h"
#include "base/bind.h"
+#include "third_party/skia/include/core/SkRect.h"
namespace cobalt {
namespace renderer {
@@ -23,6 +24,7 @@
SkottieAnimation::SkottieAnimation(const char* data, size_t length)
: last_updated_animation_time_(base::TimeDelta()) {
+ ResetRenderCache();
skottie::Animation::Builder builder;
skottie_animation_ = builder.make(data, length);
animation_size_ = math::Size(skottie_animation_->size().width(),
@@ -72,6 +74,11 @@
return;
}
+ // Do not update the animation time if it has already reached the last frame.
+ if (is_complete_) {
+ return;
+ }
+
base::TimeDelta current_animation_time = last_updated_animation_time_;
base::TimeDelta time_elapsed =
animate_function_time - last_updated_animate_function_time_;
@@ -124,6 +131,21 @@
animate_function_time);
}
+void SkottieAnimation::UpdateRenderCache(SkCanvas* render_target,
+ const math::SizeF& size) {
+ DCHECK(render_target);
+ if (cached_animation_time_ == last_updated_animation_time_) {
+ // The render cache is already up-to-date.
+ return;
+ }
+
+ cached_animation_time_ = last_updated_animation_time_;
+ SkRect bounding_rect = SkRect::MakeWH(size.width(), size.height());
+ render_target->clear(SK_ColorTRANSPARENT);
+ skottie_animation_->render(render_target, &bounding_rect);
+ render_target->flush();
+}
+
void SkottieAnimation::UpdateAnimationFrameAndAnimateFunctionTimes(
base::TimeDelta current_animation_time,
base::TimeDelta current_animate_function_time) {
diff --git a/src/cobalt/renderer/rasterizer/skia/skottie_animation.h b/src/cobalt/renderer/rasterizer/skia/skottie_animation.h
index 3d5531c..0acb854 100644
--- a/src/cobalt/renderer/rasterizer/skia/skottie_animation.h
+++ b/src/cobalt/renderer/rasterizer/skia/skottie_animation.h
@@ -15,7 +15,9 @@
#ifndef COBALT_RENDERER_RASTERIZER_SKIA_SKOTTIE_ANIMATION_H_
#define COBALT_RENDERER_RASTERIZER_SKIA_SKOTTIE_ANIMATION_H_
+#include "cobalt/math/size_f.h"
#include "cobalt/render_tree/lottie_animation.h"
+#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/modules/skottie/include/Skottie.h"
namespace cobalt {
@@ -41,6 +43,12 @@
sk_sp<skottie::Animation> GetSkottieAnimation() { return skottie_animation_; }
+ // Rendering the lottie animation can be CPU-intensive. To minimize the cost,
+ // the animation can be updated in an offscreen render target only as needed,
+ // then the offscreen target rendered to the screen.
+ void ResetRenderCache() { cached_animation_time_ = base::TimeDelta::Min(); }
+ void UpdateRenderCache(SkCanvas* render_target, const math::SizeF& size);
+
private:
void UpdateAnimationFrameAndAnimateFunctionTimes(
base::TimeDelta current_animation_time,
@@ -79,6 +87,9 @@
// The most recently updated frame time for |skottie_animation_|.
base::TimeDelta last_updated_animation_time_;
+
+ // This is the animation time used for the last cache update.
+ base::TimeDelta cached_animation_time_;
};
} // namespace skia
diff --git a/src/cobalt/renderer/rasterizer/testdata/LottiePreserveAspectRatioTooNarrowAnimationTest-expected.png b/src/cobalt/renderer/rasterizer/testdata/LottiePreserveAspectRatioTooNarrowAnimationTest-expected.png
new file mode 100644
index 0000000..803f356
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/LottiePreserveAspectRatioTooNarrowAnimationTest-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/LottiePreserveAspectRatioTooShortAnimationTest-expected.png b/src/cobalt/renderer/rasterizer/testdata/LottiePreserveAspectRatioTooShortAnimationTest-expected.png
new file mode 100644
index 0000000..804797d
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/LottiePreserveAspectRatioTooShortAnimationTest-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/LottieScaledWideAnimationTest-expected.png b/src/cobalt/renderer/rasterizer/testdata/LottieScaledWideAnimationTest-expected.png
new file mode 100644
index 0000000..86784fd
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/LottieScaledWideAnimationTest-expected.png
Binary files differ
diff --git a/src/cobalt/site/docs/development/setup-android.md b/src/cobalt/site/docs/development/setup-android.md
index 1e570e4..4a6f2b0 100644
--- a/src/cobalt/site/docs/development/setup-android.md
+++ b/src/cobalt/site/docs/development/setup-android.md
@@ -24,6 +24,32 @@
PATH=${PATH}:/path/to/depot_tools
```
+1. Additional build dependencies may need to be installed:
+ ```
+ sudo apt-get install python python-pip
+ ```
+
+ If `python-pip` is not available via your package mangaer, you can install `pip` following [recommended instructions](https://pip.pypa.io/en/stable/installing/) from the official Python guide.
+
+ There are also some Python module requirements:
+
+ ```
+ python -m pip install requests
+ ```
+
+1. Install ccache to support build acceleration. ccache is automatically used
+ when available, otherwise defaults to unaccelerated building:
+
+ ```
+ $ sudo apt-get install ccache
+ ```
+
+ We recommend adjusting the cache size as needed to increase cache hits:
+
+ ```
+ $ ccache --max-size=20G
+ ```
+
1. Download and install [Android Studio](https://developer.android.com/studio/).
1. Run `cobalt/build/gyp_cobalt android-x86` to configure the Cobalt build,
which also installs the SDK and NDK. (This step will have to be repeated
diff --git a/src/cobalt/site/docs/development/setup-linux.md b/src/cobalt/site/docs/development/setup-linux.md
index e67b94c..3c4d49f 100644
--- a/src/cobalt/site/docs/development/setup-linux.md
+++ b/src/cobalt/site/docs/development/setup-linux.md
@@ -9,6 +9,8 @@
on the machine that you are using to view the client. For example, you cannot
SSH into another machine and run the binary on that machine.
+## Set up your workstation
+
1. Choose where you want to put the `depot_tools` directory, which is used
by the Cobalt code. An easy option is to put them in `~/depot_tools`.
Clone the tools by running the following command:
@@ -30,19 +32,35 @@
Cobalt on Linux:
```
- $ sudo apt-get install bison build-essential coreutils git gperf \
- libaom-dev libasound2-dev libavformat-dev libavresample-dev \
- libdirectfb-dev libdirectfb-extra libpulse-dev \
- libgl1-mesa-dev libgles2-mesa-dev libvpx-dev libx11-dev \
- libxcomposite-dev libxcomposite1 libxrender-dev libxrender1 \
- libxpm-dev m4 python ruby tar xserver-xephyr xz-utils yasm
+ $ sudo apt install -qqy --no-install-recommends pkgconf ninja-build bison \
+ yasm binutils clang libgles2-mesa-dev mesa-common-dev libpulse-dev \
+ libavresample-dev libasound2-dev libxrender-dev libxcomposite-dev
```
-1. Install the latest version of the standard C++ header files (`libstdc++`).
- For example:
+1. Install Node.js via `nvm`:
+ ```
+ $ export NVM_DIR=~/.nvm
+ $ export NODE_VERSION=12.17.0
+
+ $ curl --silent -o- https://raw.githubusercontent.com/creationix/nvm/v0.35.3/install.sh | bash
+
+ $ . $NVM_DIR/nvm.sh \
+ && nvm install --lts \
+ && nvm alias default lts/* \
+ && nvm use default
+ ```
+
+1. Install ccache to support build acceleration. ccache is automatically used
+ when available, otherwise defaults to unaccelerated building:
```
- sudo apt-get install libstdc++-4.8-dev
+ $ sudo apt install -qqy --no-install-recommends ccache
+ ```
+
+ We recommend adjusting the cache size as needed to increase cache hits:
+
+ ```
+ $ ccache --max-size=20G
```
1. Clone the Cobalt code repository. The following `git` command creates a
@@ -52,13 +70,7 @@
$ git clone https://cobalt.googlesource.com/cobalt
```
-1. Modify your path to include the version of Clang that is downloaded
- in the next step of the instructions. The next step will return an
- error if this version of Clang is not in your path before it runs.
-
- ```
- $PATH="/path/to/cobalt/src/third_party/llvm-build/Release+Asserts/bin:${PATH}"
- ```
+## Build and Run Cobalt
1. Build the code by navigating to the `src` directory in your new
`cobalt` directory and running the following command. You must
diff --git a/src/cobalt/site/docs/development/setup-raspi.md b/src/cobalt/site/docs/development/setup-raspi.md
index 13936bb..3e88d8c 100644
--- a/src/cobalt/site/docs/development/setup-raspi.md
+++ b/src/cobalt/site/docs/development/setup-raspi.md
@@ -48,15 +48,27 @@
$ apt-get remove -y --purge --auto-remove libgl1-mesa-dev \
libegl1-mesa-dev libgles2-mesa libgles2-mesa-dev
$ apt-get install -y libpulse-dev libasound2-dev libavformat-dev \
- libavresample-dev
+ libavresample-dev rsync
```
## Set up your workstation
+<aside class="note">
+<b>Note:</b> Before proceeding further, refer to the documentation for ["Set up your environment - Linux"](setup-linux.md). Complete the section **Set up your workstation**, then return and complete the following steps.
+</aside>
+
The following steps install the cross-compiling toolchain on your workstation.
The toolchain runs on an x86 workstation and compiles binaries for your ARM
Raspberry Pi.
+1. Run the following command to install packages needed to build and run
+ Cobalt for Raspberry Pi:
+
+ ```
+ $ sudo apt install -qqy --no-install-recommends g++-multilib \
+ python-requests wget xz-utils
+ ```
+
1. Choose a location for the installed toolchain – e.g. `raspi-tools`
– and set `$RASPI_HOME` to that location.
@@ -94,10 +106,16 @@
## Build, install, and run Cobalt for Raspberry Pi
-1. Run the following commands to build Cobalt:
+1. Build the code by navigating to the src directory in your cobalt directory and run the
+ following command :
```
- $ gyp_cobalt raspi-2
+ $ cobalt/build/gyp_cobalt raspi-2
+ ```
+
+1. Compile the code from the `src/` directory:
+
+ ```
$ ninja -C out/raspi-2_debug cobalt
```
@@ -105,7 +123,7 @@
on the device:
```
- rsync -avzh --exclude="obj*" \
+ rsync -avzLPh --exclude="obj*" --exclude="gen/" \
$COBALT_SRC/out/raspi-2_debug pi@$RASPI_ADDR:~/
```
@@ -129,3 +147,21 @@
Note that you can also exit YouTube on Cobalt by hitting the `[Esc]` key
enough times to bring up the "Do you want to quit YouTube?" dialog and
selecting "yes".
+
+### Improving Cobalt performance on Raspberry Pi
+
+1. You will find that there are some processes installed by default that run on the
+ Raspberry Pi and can take away CPU time from Cobalt. You may wish to consider
+ disabling these processes for maximum (and more consistent) performance, as they
+ have been found to occasionally take >10% of the CPU according to `top`.
+ You can do this by typing:
+
+ ```
+ apt-get remove -y --auto-remove [PACKAGE_NAME, ...]
+ ```
+
+ For example:
+
+ ```
+ apt-get remove -y --auto-remove avahi-daemon
+ ```
diff --git a/src/cobalt/site/docs/reference/starboard/modules/10/file.md b/src/cobalt/site/docs/reference/starboard/modules/10/file.md
index b115501..b9c0e36 100644
--- a/src/cobalt/site/docs/reference/starboard/modules/10/file.md
+++ b/src/cobalt/site/docs/reference/starboard/modules/10/file.md
@@ -169,7 +169,7 @@
is used primarily to clean up after unit tests. On some platforms, this function
fails if the file in question is being held open.
-`path`: The absolute path fo the file, symlink, or directory to be deleted.
+`path`: The absolute path of the file, symlink, or directory to be deleted.
#### Declaration ####
diff --git a/src/cobalt/site/docs/reference/starboard/modules/10/media.md b/src/cobalt/site/docs/reference/starboard/modules/10/media.md
index 9b83d06..7271b29 100644
--- a/src/cobalt/site/docs/reference/starboard/modules/10/media.md
+++ b/src/cobalt/site/docs/reference/starboard/modules/10/media.md
@@ -665,6 +665,8 @@
outputs. If `true`, then non-protection-capable outputs are expected to be
blanked.
+presubmit: allow sb_export mismatch
+
#### Declaration ####
```
@@ -700,6 +702,8 @@
`enabled`: Indicates whether output protection is enabled (`true`) or disabled.
+presubmit: allow sb_export mismatch
+
#### Declaration ####
```
diff --git a/src/cobalt/site/docs/reference/starboard/modules/11/file.md b/src/cobalt/site/docs/reference/starboard/modules/11/file.md
index ad890dc..f910cb0 100644
--- a/src/cobalt/site/docs/reference/starboard/modules/11/file.md
+++ b/src/cobalt/site/docs/reference/starboard/modules/11/file.md
@@ -168,7 +168,7 @@
is used primarily to clean up after unit tests. On some platforms, this function
fails if the file in question is being held open.
-`path`: The absolute path fo the file, symlink, or directory to be deleted.
+`path`: The absolute path of the file, symlink, or directory to be deleted.
#### Declaration ####
diff --git a/src/cobalt/site/docs/reference/starboard/modules/11/media.md b/src/cobalt/site/docs/reference/starboard/modules/11/media.md
index 8d94612..377cb2b 100644
--- a/src/cobalt/site/docs/reference/starboard/modules/11/media.md
+++ b/src/cobalt/site/docs/reference/starboard/modules/11/media.md
@@ -659,6 +659,8 @@
outputs. If `true`, then non-protection-capable outputs are expected to be
blanked.
+presubmit: allow sb_export mismatch
+
#### Declaration ####
```
@@ -712,6 +714,8 @@
`enabled`: Indicates whether output protection is enabled (`true`) or disabled.
+presubmit: allow sb_export mismatch
+
#### Declaration ####
```
diff --git a/src/cobalt/site/docs/reference/starboard/modules/12/condition_variable.md b/src/cobalt/site/docs/reference/starboard/modules/12/condition_variable.md
index 836c4b8..22c2b79 100644
--- a/src/cobalt/site/docs/reference/starboard/modules/12/condition_variable.md
+++ b/src/cobalt/site/docs/reference/starboard/modules/12/condition_variable.md
@@ -40,7 +40,7 @@
#### Definition ####
```
-typedef union SbConditionVariable SbConditionVariable
+typedef union SbConditionVariable SbConditionVariable
```
## Functions ##
diff --git a/src/cobalt/site/docs/reference/starboard/modules/12/file.md b/src/cobalt/site/docs/reference/starboard/modules/12/file.md
index c3ba551..e22edeb 100644
--- a/src/cobalt/site/docs/reference/starboard/modules/12/file.md
+++ b/src/cobalt/site/docs/reference/starboard/modules/12/file.md
@@ -184,7 +184,7 @@
is used primarily to clean up after unit tests. On some platforms, this function
fails if the file in question is being held open.
-`path`: The absolute path fo the file, symlink, or directory to be deleted.
+`path`: The absolute path of the file, symlink, or directory to be deleted.
#### Declaration ####
diff --git a/src/cobalt/site/docs/reference/starboard/modules/12/mutex.md b/src/cobalt/site/docs/reference/starboard/modules/12/mutex.md
index 58f1907..a9d2a9a 100644
--- a/src/cobalt/site/docs/reference/starboard/modules/12/mutex.md
+++ b/src/cobalt/site/docs/reference/starboard/modules/12/mutex.md
@@ -40,7 +40,7 @@
#### Definition ####
```
-typedef union SbMutex SbMutex
+typedef union SbMutex SbMutex
```
## Functions ##
diff --git a/src/cobalt/site/docs/reference/starboard/modules/12/once.md b/src/cobalt/site/docs/reference/starboard/modules/12/once.md
index ce3c4d6..61aad5d 100644
--- a/src/cobalt/site/docs/reference/starboard/modules/12/once.md
+++ b/src/cobalt/site/docs/reference/starboard/modules/12/once.md
@@ -22,7 +22,7 @@
#### Definition ####
```
-typedef union SbOnceControl SbOnceControl
+typedef union SbOnceControl SbOnceControl
```
### SbOnceInitRoutine ###
diff --git a/src/cobalt/site/docs/reference/starboard/modules/condition_variable.md b/src/cobalt/site/docs/reference/starboard/modules/condition_variable.md
index 836c4b8..22c2b79 100644
--- a/src/cobalt/site/docs/reference/starboard/modules/condition_variable.md
+++ b/src/cobalt/site/docs/reference/starboard/modules/condition_variable.md
@@ -40,7 +40,7 @@
#### Definition ####
```
-typedef union SbConditionVariable SbConditionVariable
+typedef union SbConditionVariable SbConditionVariable
```
## Functions ##
diff --git a/src/cobalt/site/docs/reference/starboard/modules/file.md b/src/cobalt/site/docs/reference/starboard/modules/file.md
index c3ba551..e22edeb 100644
--- a/src/cobalt/site/docs/reference/starboard/modules/file.md
+++ b/src/cobalt/site/docs/reference/starboard/modules/file.md
@@ -184,7 +184,7 @@
is used primarily to clean up after unit tests. On some platforms, this function
fails if the file in question is being held open.
-`path`: The absolute path fo the file, symlink, or directory to be deleted.
+`path`: The absolute path of the file, symlink, or directory to be deleted.
#### Declaration ####
diff --git a/src/cobalt/site/docs/reference/starboard/modules/mutex.md b/src/cobalt/site/docs/reference/starboard/modules/mutex.md
index 58f1907..a9d2a9a 100644
--- a/src/cobalt/site/docs/reference/starboard/modules/mutex.md
+++ b/src/cobalt/site/docs/reference/starboard/modules/mutex.md
@@ -40,7 +40,7 @@
#### Definition ####
```
-typedef union SbMutex SbMutex
+typedef union SbMutex SbMutex
```
## Functions ##
diff --git a/src/cobalt/site/docs/reference/starboard/modules/once.md b/src/cobalt/site/docs/reference/starboard/modules/once.md
index ce3c4d6..61aad5d 100644
--- a/src/cobalt/site/docs/reference/starboard/modules/once.md
+++ b/src/cobalt/site/docs/reference/starboard/modules/once.md
@@ -22,7 +22,7 @@
#### Definition ####
```
-typedef union SbOnceControl SbOnceControl
+typedef union SbOnceControl SbOnceControl
```
### SbOnceInitRoutine ###
diff --git a/src/cobalt/speech/audio_encoder_flac.cc b/src/cobalt/speech/audio_encoder_flac.cc
index c6899de..279b5fe 100644
--- a/src/cobalt/speech/audio_encoder_flac.cc
+++ b/src/cobalt/speech/audio_encoder_flac.cc
@@ -56,18 +56,18 @@
FLAC__stream_encoder_delete(encoder_);
}
-void AudioEncoderFlac::Encode(const ShellAudioBus* audio_bus) {
+void AudioEncoderFlac::Encode(const AudioBus* audio_bus) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK_EQ(audio_bus->channels(), size_t(1));
uint32 frames = static_cast<uint32>(audio_bus->frames());
std::unique_ptr<FLAC__int32[]> flac_samples(new FLAC__int32[frames]);
for (uint32 i = 0; i < frames; ++i) {
- if (audio_bus->sample_type() == ShellAudioBus::kFloat32) {
+ if (audio_bus->sample_type() == AudioBus::kFloat32) {
flac_samples[i] = static_cast<FLAC__int32>(
audio_bus->GetFloat32Sample(0, i) * kMaxInt16AsFloat32);
} else {
- DCHECK_EQ(audio_bus->sample_type(), ShellAudioBus::kInt16);
+ DCHECK_EQ(audio_bus->sample_type(), AudioBus::kInt16);
flac_samples[i] =
static_cast<FLAC__int32>(audio_bus->GetInt16Sample(0, i));
}
diff --git a/src/cobalt/speech/audio_encoder_flac.h b/src/cobalt/speech/audio_encoder_flac.h
index 71b1822..3317af9 100644
--- a/src/cobalt/speech/audio_encoder_flac.h
+++ b/src/cobalt/speech/audio_encoder_flac.h
@@ -20,7 +20,7 @@
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/threading/thread_checker.h"
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
#include "third_party/flac/include/FLAC/stream_encoder.h"
namespace cobalt {
@@ -29,13 +29,13 @@
// Encode raw audio to using FLAC codec.
class AudioEncoderFlac {
public:
- typedef media::ShellAudioBus ShellAudioBus;
+ typedef media::AudioBus AudioBus;
explicit AudioEncoderFlac(int sample_rate);
~AudioEncoderFlac();
// Encode raw audio data.
- void Encode(const ShellAudioBus* audio_bus);
+ void Encode(const AudioBus* audio_bus);
// Finish encoding.
void Finish();
diff --git a/src/cobalt/speech/cobalt_speech_recognizer.cc b/src/cobalt/speech/cobalt_speech_recognizer.cc
index eb9fd8d..0d61e70 100644
--- a/src/cobalt/speech/cobalt_speech_recognizer.cc
+++ b/src/cobalt/speech/cobalt_speech_recognizer.cc
@@ -123,7 +123,7 @@
}
void CobaltSpeechRecognizer::OnDataReceived(
- std::unique_ptr<ShellAudioBus> audio_bus) {
+ std::unique_ptr<AudioBus> audio_bus) {
if (endpointer_delegate_.IsFirstTimeSoundStarted(*audio_bus)) {
RunEventCallback(new dom::Event(base::Tokens::soundstart()));
}
@@ -135,8 +135,8 @@
// silence at the end in case encoder had no data already.
size_t dummy_frames =
static_cast<size_t>(kSampleRate * kAudioPacketDurationInSeconds);
- std::unique_ptr<ShellAudioBus> dummy_audio_bus(new ShellAudioBus(
- 1, dummy_frames, ShellAudioBus::kInt16, ShellAudioBus::kInterleaved));
+ std::unique_ptr<AudioBus> dummy_audio_bus(
+ new AudioBus(1, dummy_frames, AudioBus::kInt16, AudioBus::kInterleaved));
dummy_audio_bus->ZeroAllFrames();
service_->RecognizeAudio(std::move(dummy_audio_bus), true);
}
diff --git a/src/cobalt/speech/cobalt_speech_recognizer.h b/src/cobalt/speech/cobalt_speech_recognizer.h
index f9ca9d4..d67ab5e 100644
--- a/src/cobalt/speech/cobalt_speech_recognizer.h
+++ b/src/cobalt/speech/cobalt_speech_recognizer.h
@@ -18,7 +18,7 @@
#include <memory>
#include <string>
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
#include "cobalt/network/network_module.h"
#include "cobalt/speech/endpointer_delegate.h"
#include "cobalt/speech/google_speech_service.h"
@@ -39,7 +39,7 @@
// from there.
class CobaltSpeechRecognizer : public SpeechRecognizer {
public:
- typedef media::ShellAudioBus ShellAudioBus;
+ typedef media::AudioBus AudioBus;
CobaltSpeechRecognizer(network::NetworkModule* network_module,
const Microphone::Options& microphone_options,
@@ -51,7 +51,7 @@
private:
// Callbacks from mic.
- void OnDataReceived(std::unique_ptr<ShellAudioBus> audio_bus);
+ void OnDataReceived(std::unique_ptr<AudioBus> audio_bus);
void OnDataCompletion();
void OnMicrophoneError(MicrophoneManager::MicrophoneError error,
std::string error_message);
diff --git a/src/cobalt/speech/endpointer_delegate.cc b/src/cobalt/speech/endpointer_delegate.cc
index 6340eea..1fc2658 100644
--- a/src/cobalt/speech/endpointer_delegate.cc
+++ b/src/cobalt/speech/endpointer_delegate.cc
@@ -45,8 +45,7 @@
void EndPointerDelegate::Stop() { endpointer_.EndSession(); }
-bool EndPointerDelegate::IsFirstTimeSoundStarted(
- const ShellAudioBus& audio_bus) {
+bool EndPointerDelegate::IsFirstTimeSoundStarted(const AudioBus& audio_bus) {
if (is_first_time_sound_started_) {
return false;
}
diff --git a/src/cobalt/speech/endpointer_delegate.h b/src/cobalt/speech/endpointer_delegate.h
index fe2f18b..e222f02 100644
--- a/src/cobalt/speech/endpointer_delegate.h
+++ b/src/cobalt/speech/endpointer_delegate.h
@@ -15,8 +15,8 @@
#ifndef COBALT_SPEECH_ENDPOINTER_DELEGATE_H_
#define COBALT_SPEECH_ENDPOINTER_DELEGATE_H_
+#include "cobalt/media/base/audio_bus.h"
#include "content/browser/speech/endpointer/endpointer.h"
-#include "cobalt/media/base/shell_audio_bus.h"
namespace cobalt {
namespace speech {
@@ -25,7 +25,7 @@
// speech session (from start speaking to end of speaking).
class EndPointerDelegate {
public:
- typedef media::ShellAudioBus ShellAudioBus;
+ typedef media::AudioBus AudioBus;
explicit EndPointerDelegate(int sample_rate);
~EndPointerDelegate();
@@ -36,7 +36,7 @@
void Stop();
// Return true if it is the first time that the sound started.
- bool IsFirstTimeSoundStarted(const ShellAudioBus& audio_bus);
+ bool IsFirstTimeSoundStarted(const AudioBus& audio_bus);
private:
// Used for detecting sound start event.
diff --git a/src/cobalt/speech/google_speech_service.cc b/src/cobalt/speech/google_speech_service.cc
index 83ef7ec..0bd11ac 100644
--- a/src/cobalt/speech/google_speech_service.cc
+++ b/src/cobalt/speech/google_speech_service.cc
@@ -220,8 +220,8 @@
base::Bind(&GoogleSpeechService::StopInternal, base::Unretained(this)));
}
-void GoogleSpeechService::RecognizeAudio(
- std::unique_ptr<ShellAudioBus> audio_bus, bool is_last_chunk) {
+void GoogleSpeechService::RecognizeAudio(std::unique_ptr<AudioBus> audio_bus,
+ bool is_last_chunk) {
// Called by the speech recognition manager thread.
thread_.message_loop()->task_runner()->PostTask(
FROM_HERE, base::Bind(&GoogleSpeechService::UploadAudioDataInternal,
@@ -393,7 +393,7 @@
}
void GoogleSpeechService::UploadAudioDataInternal(
- std::unique_ptr<ShellAudioBus> audio_bus, bool is_last_chunk) {
+ std::unique_ptr<AudioBus> audio_bus, bool is_last_chunk) {
DCHECK_EQ(thread_.message_loop(), base::MessageLoop::current());
DCHECK(audio_bus);
diff --git a/src/cobalt/speech/google_speech_service.h b/src/cobalt/speech/google_speech_service.h
index b0002ae..a1ea1e5 100644
--- a/src/cobalt/speech/google_speech_service.h
+++ b/src/cobalt/speech/google_speech_service.h
@@ -21,7 +21,7 @@
#include "base/threading/thread.h"
#include "cobalt/loader/url_fetcher_string_writer.h"
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
#include "cobalt/network/network_module.h"
#include "cobalt/speech/audio_encoder_flac.h"
#include "cobalt/speech/google_streaming_api.pb.h"
@@ -43,7 +43,7 @@
// manager.
class GoogleSpeechService : public net::URLFetcherDelegate {
public:
- typedef media::ShellAudioBus ShellAudioBus;
+ typedef media::AudioBus AudioBus;
typedef base::Callback<void(const scoped_refptr<dom::Event>&)> EventCallback;
typedef SpeechRecognitionResultList::SpeechRecognitionResults
SpeechRecognitionResults;
@@ -63,8 +63,7 @@
// Stop speech recognizer.
void Stop();
// An encoded audio data is available and ready to be recognized.
- void RecognizeAudio(std::unique_ptr<ShellAudioBus> audio_bus,
- bool is_last_chunk);
+ void RecognizeAudio(std::unique_ptr<AudioBus> audio_bus, bool is_last_chunk);
// net::URLFetcherDelegate interface
void OnURLFetchDownloadProgress(const net::URLFetcher* source,
@@ -81,7 +80,7 @@
void StopInternal();
// This method handles wrappables and should run on the MainWebModule thread.
void ClearFinalResults();
- void UploadAudioDataInternal(std::unique_ptr<ShellAudioBus> audio_bus,
+ void UploadAudioDataInternal(std::unique_ptr<AudioBus> audio_bus,
bool is_last_chunk);
// This method handles wrappables, and so it must run on the MainWebModule.
void ProcessAndFireSuccessEvent(proto::SpeechRecognitionEvent event);
diff --git a/src/cobalt/speech/microphone_fake.cc b/src/cobalt/speech/microphone_fake.cc
index 15c955a..29a86a4 100644
--- a/src/cobalt/speech/microphone_fake.cc
+++ b/src/cobalt/speech/microphone_fake.cc
@@ -31,7 +31,7 @@
namespace cobalt {
namespace speech {
-typedef audio::ShellAudioBus ShellAudioBus;
+typedef audio::AudioBus AudioBus;
namespace {
@@ -89,10 +89,10 @@
} else {
file_length_ = std::min(options.audio_data_size, kMaxBufferSize);
DCHECK_GT(file_length_, 0);
- audio_bus_.reset(new ShellAudioBus(
- kSupportedMonoChannel,
- file_length_ / audio::GetSampleTypeSize(ShellAudioBus::kInt16),
- ShellAudioBus::kInt16, ShellAudioBus::kInterleaved));
+ audio_bus_.reset(
+ new AudioBus(kSupportedMonoChannel,
+ file_length_ / audio::GetSampleTypeSize(AudioBus::kInt16),
+ AudioBus::kInt16, AudioBus::kInterleaved));
SbMemoryCopy(audio_bus_->interleaved_data(), options.external_audio_data,
file_length_);
}
@@ -131,14 +131,14 @@
const float kSupportedSampleRate = 16000.0f;
if (!reader) {
// If it is not a WAV file, read audio data as raw audio.
- audio_bus_.reset(new ShellAudioBus(
+ audio_bus_.reset(new AudioBus(
kSupportedMonoChannel,
- file_buffer_size / audio::GetSampleTypeSize(ShellAudioBus::kInt16),
- ShellAudioBus::kInt16, ShellAudioBus::kInterleaved));
+ file_buffer_size / audio::GetSampleTypeSize(AudioBus::kInt16),
+ AudioBus::kInt16, AudioBus::kInterleaved));
SbMemoryCopy(audio_bus_->interleaved_data(), audio_input.get(),
file_buffer_size);
file_length_ = file_buffer_size;
- } else if (reader->sample_type() != ShellAudioBus::kInt16 ||
+ } else if (reader->sample_type() != AudioBus::kInt16 ||
reader->sample_rate() != kSupportedSampleRate ||
reader->number_of_channels() != kSupportedMonoChannel) {
// If it is a WAV file but it doesn't meet the audio input criteria, treat
diff --git a/src/cobalt/speech/microphone_fake.h b/src/cobalt/speech/microphone_fake.h
index ac4cf8b..3f6cbbc 100644
--- a/src/cobalt/speech/microphone_fake.h
+++ b/src/cobalt/speech/microphone_fake.h
@@ -52,7 +52,7 @@
bool read_data_from_file_;
std::vector<base::FilePath> file_paths_;
- std::unique_ptr<audio::ShellAudioBus> audio_bus_;
+ std::unique_ptr<audio::AudioBus> audio_bus_;
int file_length_;
int read_index_;
bool is_valid_;
diff --git a/src/cobalt/speech/microphone_manager.cc b/src/cobalt/speech/microphone_manager.cc
index a957f2d..cddf31e 100644
--- a/src/cobalt/speech/microphone_manager.cc
+++ b/src/cobalt/speech/microphone_manager.cc
@@ -145,9 +145,9 @@
// If |read_bytes| is zero, nothing should happen.
if (read_bytes > 0 && read_bytes % sizeof(int16_t) == 0) {
size_t frames = read_bytes / sizeof(int16_t);
- std::unique_ptr<ShellAudioBus> output_audio_bus(new ShellAudioBus(
- 1, frames, ShellAudioBus::kInt16, ShellAudioBus::kInterleaved));
- ShellAudioBus source(1, frames, samples);
+ std::unique_ptr<AudioBus> output_audio_bus(
+ new AudioBus(1, frames, AudioBus::kInt16, AudioBus::kInterleaved));
+ AudioBus source(1, frames, samples);
output_audio_bus->Assign(source);
data_received_callback_.Run(std::move(output_audio_bus));
} else if (read_bytes != 0) {
diff --git a/src/cobalt/speech/microphone_manager.h b/src/cobalt/speech/microphone_manager.h
index 765d2b6..602f6bf 100644
--- a/src/cobalt/speech/microphone_manager.h
+++ b/src/cobalt/speech/microphone_manager.h
@@ -25,7 +25,7 @@
#include "base/threading/thread.h"
#include "base/timer/timer.h"
#include "cobalt/dom/event.h"
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
#include "cobalt/speech/microphone.h"
namespace cobalt {
@@ -39,9 +39,8 @@
kAudioCapture,
kAborted,
};
- typedef media::ShellAudioBus ShellAudioBus;
- typedef base::Callback<void(std::unique_ptr<ShellAudioBus>)>
- DataReceivedCallback;
+ typedef media::AudioBus AudioBus;
+ typedef base::Callback<void(std::unique_ptr<AudioBus>)> DataReceivedCallback;
typedef base::Closure CompletionCallback;
typedef base::Closure SuccessfulOpenCallback;
typedef base::Callback<void(MicrophoneError, std::string)> ErrorCallback;
diff --git a/src/cobalt/updater/configurator.cc b/src/cobalt/updater/configurator.cc
index d626083..210f088 100644
--- a/src/cobalt/updater/configurator.cc
+++ b/src/cobalt/updater/configurator.cc
@@ -31,6 +31,7 @@
#if defined(COBALT_BUILD_TYPE_DEBUG) || defined(COBALT_BUILD_TYPE_DEVEL)
const std::set<std::string> valid_channels = {"dev"};
+const std::string kDefaultUpdaterChannel = "dev";
#elif defined(COBALT_BUILD_TYPE_QA)
// Find more information about these test channels in the Evergreen test plan.
const std::set<std::string> valid_channels = {
@@ -51,8 +52,10 @@
// Test an update that's larger than the available storage on the device
"tistore",
};
+const std::string kDefaultUpdaterChannel = "qa";
#elif defined(COBALT_BUILD_TYPE_GOLD)
const std::set<std::string> valid_channels = {"prod", "dogfood"};
+const std::string kDefaultUpdaterChannel = "prod";
#endif
std::string GetDeviceProperty(SbSystemPropertyId id) {
@@ -74,10 +77,21 @@
Configurator::Configurator(network::NetworkModule* network_module)
: pref_service_(CreatePrefService()),
+ persisted_data_(std::make_unique<update_client::PersistedData>(
+ pref_service_.get(), nullptr)),
+ is_channel_changed_(0),
unzip_factory_(base::MakeRefCounted<UnzipperFactory>()),
network_fetcher_factory_(
base::MakeRefCounted<NetworkFetcherFactoryCobalt>(network_module)),
- patch_factory_(base::MakeRefCounted<PatcherFactory>()) {}
+ patch_factory_(base::MakeRefCounted<PatcherFactory>()) {
+ const std::string persisted_channel =
+ persisted_data_->GetUpdaterChannel(GetAppGuid());
+ if (persisted_channel.empty()) {
+ SetChannel(kDefaultUpdaterChannel);
+ } else {
+ SetChannel(persisted_channel);
+ }
+}
Configurator::~Configurator() = default;
int Configurator::InitialDelay() const { return 0; }
@@ -134,9 +148,9 @@
params.insert(std::make_pair("sbversion", std::to_string(SB_API_VERSION)));
params.insert(std::make_pair(
"jsengine", script::GetJavaScriptEngineNameAndVersion()));
- params.insert(std::make_pair("updaterchannelchanged",
- IsChannelChanged() ? "True" : "False"));
-
+ params.insert(std::make_pair(
+ "updaterchannelchanged",
+ SbAtomicNoBarrier_Load(&is_channel_changed_) == 1 ? "True" : "False"));
// Brand name
params.insert(
std::make_pair("brand", GetDeviceProperty(kSbSystemPropertyBrandName)));
@@ -200,6 +214,10 @@
return {};
}
+void Configurator::CompareAndSwapChannelChanged(int old_value, int new_value) {
+ SbAtomicNoBarrier_CompareAndSwap(&is_channel_changed_, old_value, new_value);
+}
+
// The updater channel is get and set by main web module thread and update
// client thread. The getter and set use a lock to prevent synchronization
// issue.
@@ -211,6 +229,7 @@
void Configurator::SetChannel(const std::string& updater_channel) {
base::AutoLock auto_lock(updater_channel_lock_);
updater_channel_ = updater_channel;
+ persisted_data_->SetUpdaterChannel(GetAppGuid(), updater_channel);
}
bool Configurator::IsChannelValid(const std::string& channel) {
diff --git a/src/cobalt/updater/configurator.h b/src/cobalt/updater/configurator.h
index 8012b2f..e335b4f 100644
--- a/src/cobalt/updater/configurator.h
+++ b/src/cobalt/updater/configurator.h
@@ -17,6 +17,7 @@
#include "base/synchronization/lock.h"
#include "cobalt/network/network_module.h"
#include "components/update_client/configurator.h"
+#include "components/update_client/persisted_data.h"
class GURL;
class PrefService;
@@ -76,8 +77,8 @@
void SetChannel(const std::string& updater_channel) override;
- void MarkChannelChanged() { is_channel_changed = true; }
- bool IsChannelChanged() const override { return is_channel_changed; }
+ void CompareAndSwapChannelChanged(int old_value, int new_value) override;
+
bool IsChannelValid(const std::string& channel);
std::string GetUpdaterStatus() const;
@@ -88,12 +89,13 @@
~Configurator() override;
std::unique_ptr<PrefService> pref_service_;
+ std::unique_ptr<update_client::PersistedData> persisted_data_;
scoped_refptr<update_client::NetworkFetcherFactory> network_fetcher_factory_;
scoped_refptr<update_client::UnzipperFactory> unzip_factory_;
scoped_refptr<update_client::PatcherFactory> patch_factory_;
std::string updater_channel_;
base::Lock updater_channel_lock_;
- bool is_channel_changed = false;
+ SbAtomic32 is_channel_changed_;
std::string updater_status_;
base::Lock updater_status_lock_;
diff --git a/src/cobalt/updater/crash_sandbox.cc b/src/cobalt/updater/crash_sandbox.cc
index 8f69c81..869c589 100644
--- a/src/cobalt/updater/crash_sandbox.cc
+++ b/src/cobalt/updater/crash_sandbox.cc
@@ -18,5 +18,6 @@
#include "starboard/event.h"
void SbEventHandle(const SbEvent* event) {
- SB_CHECK(false);
+ volatile int* a = (int*)(NULL);
+ *a = 1;
}
diff --git a/src/cobalt/updater/updater_module.cc b/src/cobalt/updater/updater_module.cc
index 0a7904e..2f0452b 100644
--- a/src/cobalt/updater/updater_module.cc
+++ b/src/cobalt/updater/updater_module.cc
@@ -246,6 +246,10 @@
base::TimeDelta::FromHours(kNextUpdateCheckHours));
}
+void UpdaterModule::CompareAndSwapChannelChanged(int old_value, int new_value) {
+ updater_configurator_->CompareAndSwapChannelChanged(old_value, new_value);
+}
+
// The following three methods all called by the main web module thread.
std::string UpdaterModule::GetUpdaterChannel() const {
return updater_configurator_->GetChannel();
diff --git a/src/cobalt/updater/updater_module.h b/src/cobalt/updater/updater_module.h
index c441d1d..d275556 100644
--- a/src/cobalt/updater/updater_module.h
+++ b/src/cobalt/updater/updater_module.h
@@ -65,8 +65,7 @@
std::string GetUpdaterChannel() const;
void SetUpdaterChannel(const std::string& updater_channel);
- void MarkChannelChanged() { updater_configurator_->MarkChannelChanged(); }
- bool IsChannelChanged() { return updater_configurator_->IsChannelChanged(); }
+ void CompareAndSwapChannelChanged(int old_value, int new_value);
bool IsChannelValid(const std::string& channel) {
return updater_configurator_->IsChannelValid(channel);
}
diff --git a/src/cobalt/updater/utils.cc b/src/cobalt/updater/utils.cc
index 17f0822..dab4b92 100644
--- a/src/cobalt/updater/utils.cc
+++ b/src/cobalt/updater/utils.cc
@@ -22,6 +22,12 @@
namespace cobalt {
namespace updater {
+namespace {
+// The default manifest version to assume when the actual manifest cannot be
+// parsed for any reason. This should not be used for installation manager
+// errors, or any other error unrelated to parsing the manifest.
+const std::string kDefaultManifestVersion = "1.0.0";
+} // namespace
bool CreateProductDirectory(base::FilePath* path) {
if (!GetProductDirectoryPath(path)) {
@@ -112,6 +118,12 @@
std::string(installation_path.begin(), installation_path.end())));
if (!version.IsValid()) {
+ if (!index) {
+ SB_LOG(ERROR) << "Failed to get the Everegreen version. Defaulting to "
+ << kDefaultManifestVersion << ".";
+ return kDefaultManifestVersion;
+ }
+
SB_LOG(ERROR) << "Failed to get the Everegreen version.";
return "";
}
diff --git a/src/cobalt/xhr/url_fetcher_buffer_writer.cc b/src/cobalt/xhr/url_fetcher_buffer_writer.cc
index a01a9a8..3b43b8a 100644
--- a/src/cobalt/xhr/url_fetcher_buffer_writer.cc
+++ b/src/cobalt/xhr/url_fetcher_buffer_writer.cc
@@ -103,7 +103,8 @@
return copy_of_data_as_string_;
}
-void URLFetcherResponseWriter::Buffer::GetAndReset(std::string* str) {
+void URLFetcherResponseWriter::Buffer::GetAndResetDataAndDownloadProgress(
+ std::string* str) {
DCHECK(str);
ReleaseMemory(str);
@@ -119,9 +120,15 @@
}
data_as_string_.swap(*str);
+
+ // It is important to reset the |download_progress_| and return the data in
+ // one function to avoid potential race condition that may prevent the last
+ // bit of data of Fetcher from being downloaded, because the data download is
+ // guarded by HasProgressSinceLastGetAndReset().
+ download_progress_ = 0;
}
-void URLFetcherResponseWriter::Buffer::GetAndReset(
+void URLFetcherResponseWriter::Buffer::GetAndResetData(
PreallocatedArrayBufferData* data) {
DCHECK(data);
diff --git a/src/cobalt/xhr/url_fetcher_buffer_writer.h b/src/cobalt/xhr/url_fetcher_buffer_writer.h
index c82ce32..8eb9736 100644
--- a/src/cobalt/xhr/url_fetcher_buffer_writer.h
+++ b/src/cobalt/xhr/url_fetcher_buffer_writer.h
@@ -57,8 +57,8 @@
// public member function is called on this object.
const std::string& GetTemporaryReferenceOfString();
- void GetAndReset(std::string* str);
- void GetAndReset(PreallocatedArrayBufferData* data);
+ void GetAndResetDataAndDownloadProgress(std::string* str);
+ void GetAndResetData(PreallocatedArrayBufferData* data);
void MaybePreallocate(int64_t capacity);
void Write(const void* buffer, int num_bytes);
diff --git a/src/cobalt/xhr/xml_http_request.cc b/src/cobalt/xhr/xml_http_request.cc
index 27408e2..0ea3345 100644
--- a/src/cobalt/xhr/xml_http_request.cc
+++ b/src/cobalt/xhr/xml_http_request.cc
@@ -717,7 +717,7 @@
if (fetch_callback_) {
std::string downloaded_data;
- response_body_->GetAndReset(&downloaded_data);
+ response_body_->GetAndResetDataAndDownloadProgress(&downloaded_data);
script::Handle<script::Uint8Array> data =
script::Uint8Array::New(settings_->global_environment(),
downloaded_data.data(), downloaded_data.size());
@@ -729,9 +729,13 @@
const base::TimeDelta elapsed(now - last_progress_time_);
if (elapsed > base::TimeDelta::FromMilliseconds(kProgressPeriodMs)) {
last_progress_time_ = now;
- // TODO: Investigate if we have to fire progress event with 0 loaded bytes
- // when used as Fetch API.
- UpdateProgress(response_body_->GetAndResetDownloadProgress());
+ if (fetch_callback_) {
+ // TODO: Investigate if we have to fire progress event with 0 loaded bytes
+ // when used as Fetch API.
+ UpdateProgress(0);
+ } else {
+ UpdateProgress(response_body_->GetAndResetDownloadProgress());
+ }
}
}
@@ -1025,7 +1029,7 @@
// request is re-opened.
std::unique_ptr<script::PreallocatedArrayBufferData> downloaded_data(
new script::PreallocatedArrayBufferData());
- response_body_->GetAndReset(downloaded_data.get());
+ response_body_->GetAndResetData(downloaded_data.get());
auto array_buffer = script::ArrayBuffer::New(
settings_->global_environment(), std::move(downloaded_data));
response_array_buffer_reference_.reset(
diff --git a/src/components/update_client/component.cc b/src/components/update_client/component.cc
index df190d0..50ec274 100644
--- a/src/components/update_client/component.cc
+++ b/src/components/update_client/component.cc
@@ -195,6 +195,14 @@
#endif
if (result.error != UnpackerError::kNone) {
+#if defined(OS_STARBOARD)
+ // When there is an error unpacking the downloaded CRX, such as a failure to
+ // verify the package, we should remember to clear out any drain files.
+ if (base::DirectoryExists(crx_path.DirName())) {
+ CobaltSlotManagement cobalt_slot_management;
+ cobalt_slot_management.CleanupAllDrainFiles(crx_path.DirName());
+ }
+#endif
main_task_runner->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), ErrorCategory::kUnpack,
diff --git a/src/components/update_client/configurator.h b/src/components/update_client/configurator.h
index 5baa3cc..ab7e01e 100644
--- a/src/components/update_client/configurator.h
+++ b/src/components/update_client/configurator.h
@@ -171,7 +171,9 @@
// parameters.
virtual void SetChannel(const std::string& channel) = 0;
- virtual bool IsChannelChanged() const = 0;
+ // Compare and swap the is_channel_changed flag.
+ virtual void CompareAndSwapChannelChanged(int old_value, int new_value) = 0;
+
#endif
protected:
diff --git a/src/components/update_client/test_configurator.h b/src/components/update_client/test_configurator.h
index f6ede80..c3fbda1 100644
--- a/src/components/update_client/test_configurator.h
+++ b/src/components/update_client/test_configurator.h
@@ -128,7 +128,7 @@
#if defined(STARBOARD)
void SetChannel(const std::string& channel) override {}
- bool IsChannelChanged() const override { return false; }
+ void CompareAndSwapChannelChanged(int old_value, int new_value) override {}
#else
network::TestURLLoaderFactory* test_url_loader_factory() {
return &test_url_loader_factory_;
diff --git a/src/components/update_client/update_checker.cc b/src/components/update_client/update_checker.cc
index c4045f0..3cfa2d5 100644
--- a/src/components/update_client/update_checker.cc
+++ b/src/components/update_client/update_checker.cc
@@ -44,14 +44,6 @@
namespace {
-#if defined(COBALT_BUILD_TYPE_DEBUG) || defined(COBALT_BUILD_TYPE_DEVEL)
-const std::string kDefaultUpdaterChannel = "dev";
-#elif defined(COBALT_BUILD_TYPE_QA)
-const std::string kDefaultUpdaterChannel = "qa";
-#elif defined(COBALT_BUILD_TYPE_GOLD)
-const std::string kDefaultUpdaterChannel = "prod";
-#endif
-
// Returns a sanitized version of the brand or an empty string otherwise.
std::string SanitizeBrand(const std::string& brand) {
return IsValidBrand(brand) ? brand : std::string("");
@@ -249,22 +241,6 @@
MakeProtocolPing(app_id, metadata_)));
}
std::string updater_channel = config_->GetChannel();
-#if defined(OS_STARBOARD)
- // If the updater channel is not set, read from pref store instead.
- if (updater_channel.empty()) {
- // All apps of the update use the same channel.
- updater_channel = GetPersistedData()->GetUpdaterChannel(ids_checked_[0]);
- if (updater_channel.empty()) {
- updater_channel = kDefaultUpdaterChannel;
- }
- // Set the updater channel from the persistent store or to default channel,
- // if it's not set already.
- config_->SetChannel(updater_channel);
- } else {
- // Update the record of updater channel in pref store.
- GetPersistedData()->SetUpdaterChannel(ids_checked_[0], updater_channel);
- }
-#endif
const auto request = MakeProtocolRequest(
session_id, config_->GetProdId(),
@@ -284,6 +260,10 @@
config_->EnabledCupSigning(),
base::BindOnce(&UpdateCheckerImpl::OnRequestSenderComplete,
base::Unretained(this)));
+#if defined(OS_STARBOARD)
+ // Reset is_channel_changed flag to false if it is true
+ config_->CompareAndSwapChannelChanged(1, 0);
+#endif
}
void UpdateCheckerImpl::OnRequestSenderComplete(int error,
diff --git a/src/content/browser/speech/endpointer/endpointer.cc b/src/content/browser/speech/endpointer/endpointer.cc
index 5c19c4a..96d8e6c 100644
--- a/src/content/browser/speech/endpointer/endpointer.cc
+++ b/src/content/browser/speech/endpointer/endpointer.cc
@@ -89,7 +89,7 @@
}
#if defined(STARBOARD)
-EpStatus Endpointer::ProcessAudio(const ShellAudioBus& audio_bus, float* rms_out) {
+EpStatus Endpointer::ProcessAudio(const AudioBus& audio_bus, float* rms_out) {
// TODO[Cobalt]: replace ShellAudioData with AudioChunk and deprecate
// ShellAudioData.
DCHECK_EQ(audio_bus.channels(), 1);
@@ -97,16 +97,16 @@
const size_t num_samples = audio_bus.frames();
const int16_t* audio_data = NULL;
- ShellAudioBus int16_audio_bus(1, num_samples, ShellAudioBus::kInt16,
- ShellAudioBus::kInterleaved);
+ AudioBus int16_audio_bus(1, num_samples, AudioBus::kInt16,
+ AudioBus::kInterleaved);
- if (audio_bus.sample_type() == ShellAudioBus::kFloat32) {
+ if (audio_bus.sample_type() == AudioBus::kFloat32) {
int16_audio_bus.Assign(audio_bus);
- DCHECK_EQ(int16_audio_bus.sample_type(), ShellAudioBus::kInt16);
+ DCHECK_EQ(int16_audio_bus.sample_type(), AudioBus::kInt16);
audio_data =
reinterpret_cast<const int16_t*>(int16_audio_bus.interleaved_data());
} else {
- DCHECK_EQ(audio_bus.sample_type(), ShellAudioBus::kInt16);
+ DCHECK_EQ(audio_bus.sample_type(), AudioBus::kInt16);
audio_data =
reinterpret_cast<const int16_t*>(audio_bus.interleaved_data());
}
diff --git a/src/content/browser/speech/endpointer/endpointer.h b/src/content/browser/speech/endpointer/endpointer.h
index 16bfed6..2264842 100644
--- a/src/content/browser/speech/endpointer/endpointer.h
+++ b/src/content/browser/speech/endpointer/endpointer.h
@@ -7,7 +7,7 @@
#include <stdint.h>
-#include "cobalt/media/base/shell_audio_bus.h"
+#include "cobalt/media/base/audio_bus.h"
#include "content/browser/speech/endpointer/energy_endpointer.h"
#include "content/common/content_export.h"
@@ -47,7 +47,7 @@
// long_speech_input_complete_silence_length.
class CONTENT_EXPORT Endpointer {
public:
- typedef cobalt::media::ShellAudioBus ShellAudioBus;
+ typedef cobalt::media::AudioBus AudioBus;
explicit Endpointer(int sample_rate);
@@ -68,7 +68,7 @@
// Process a segment of audio, which may be more than one frame.
// The status of the last frame will be returned.
#if defined(STARBOARD)
- EpStatus ProcessAudio(const ShellAudioBus& audio_bus, float* rms_out);
+ EpStatus ProcessAudio(const AudioBus& audio_bus, float* rms_out);
#else
EpStatus ProcessAudio(const AudioChunk& raw_audio, float* rms_out);
#endif
diff --git a/src/content/browser/speech/endpointer/endpointer_unittest.cc b/src/content/browser/speech/endpointer/endpointer_unittest.cc
index 632cc37..4b3cbb5 100644
--- a/src/content/browser/speech/endpointer/endpointer_unittest.cc
+++ b/src/content/browser/speech/endpointer/endpointer_unittest.cc
@@ -120,7 +120,7 @@
class EndpointerFrameProcessor : public FrameProcessor {
public:
#if defined(STARBOARD)
- typedef Endpointer::ShellAudioBus ShellAudioBus;
+ typedef Endpointer::AudioBus AudioBus;
#endif
explicit EndpointerFrameProcessor(Endpointer* endpointer)
: endpointer_(endpointer) {}
@@ -129,7 +129,7 @@
int16_t* samples,
int frame_size) override {
#if defined(STARBOARD)
- auto frame = std::make_unique<ShellAudioBus>(1, kFrameSize, samples);
+ auto frame = std::make_unique<AudioBus>(1, kFrameSize, samples);
endpointer_->ProcessAudio(*frame.get(), NULL);
#else
scoped_refptr<AudioChunk> frame(
diff --git a/src/docker-compose.yml b/src/docker-compose.yml
index 5d3f3a7..749a24a 100644
--- a/src/docker-compose.yml
+++ b/src/docker-compose.yml
@@ -1,27 +1,66 @@
version: '2.4'
+volumes:
+ android-debug-keystore:
+ container-ccache:
+ container-starboard-toolchains:
+
x-common-definitions: &common-definitions
stdin_open: true
tty: true
+
+x-build-volumes: &build-volumes
volumes:
- ${COBALT_SRC:-.}:/code/
- - ./docker/linux/scripts:/scripts
- - ${COBALT_SRC:-.}/out/ccache:/root/ccache
+ - android-debug-keystore:/root/.android/
+ - ${CCACHE_DIR:-container-ccache}:/root/ccache
+ - ${STARBOARD_TOOLCHAINS_DIR:-container-starboard-toolchains}:/root/starboard-toolchains
+
+x-build-common-definitions: &build-common-definitions
+ <<: *common-definitions
+ <<: *build-volumes
depends_on:
- - base
+ - build-base
services:
- # Define common build container for Linux
base:
build:
args:
- BASE_OS
context: ./docker/linux
dockerfile: base/Dockerfile
+ image: cobalt-base
+
+ base-xenial:
+ build:
+ args:
+ - BASE_OS=ubuntu
+ - BASE_OS_TAG=xenial
+ context: ./docker/linux
+ dockerfile: base/Dockerfile
+ image: base-xenial
+
+ # Define common build container for Linux
+ build-base:
+ build:
+ context: ./docker/linux
+ dockerfile: base/build/Dockerfile
image: cobalt-build-base
+ depends_on:
+ - base
+
+ build-base-xenial:
+ build:
+ context: ./docker/linux
+ dockerfile: base/build/Dockerfile
+ args:
+ - FROM_IMAGE=base-xenial
+ image: build-base-xenial
+ depends_on:
+ - base-xenial
stub:
- <<: *common-definitions
+ <<: *build-common-definitions
build:
context: ./docker/linux
dockerfile: stub/Dockerfile
@@ -31,18 +70,89 @@
- CONFIG=${CONFIG:-debug}
linux-x64x11:
- <<: *common-definitions
+ <<: *build-common-definitions
build:
context: ./docker/linux
dockerfile: linux-x64x11/Dockerfile
image: cobalt-build-linux
+ depends_on: [ build-base ]
environment:
- PLATFORM=linux-x64x11
- CONFIG=${CONFIG:-debug}
+ linux-x64x11-xenial:
+ <<: *common-definitions
+ <<: *build-volumes
+ build:
+ context: ./docker/linux
+ dockerfile: linux-x64x11/Dockerfile
+ args:
+ - FROM_IMAGE=build-base-xenial
+ image: linux-x64x11-xenial
+ depends_on:
+ - build-base-xenial
+
+ linux-x64x11-clang-3-6:
+ <<: *common-definitions
+ <<: *build-volumes
+ build:
+ context: ./docker/linux/
+ dockerfile: clang-3-6/Dockerfile
+ image: cobalt-build-linux-clang-3-6
+ environment:
+ - PLATFORM=linux-x64x11-clang-3-6
+ - CONFIG=${CONFIG:-debug}
+ depends_on:
+ - linux-x64x11-xenial
+
+ # Define common build container for Android
+ build-android:
+ <<: *build-common-definitions
+ build:
+ context: ./docker/linux/android
+ dockerfile: ./Dockerfile
+ image: cobalt-build-android
+
+ android-x86:
+ <<: *build-common-definitions
+ image: cobalt-build-android
+ depends_on: [ build-android ]
+ environment:
+ - IS_DOCKER=1
+ - PLATFORM=android-x86
+ - CONFIG=${CONFIG:-debug}
+
+ android-arm:
+ <<: *build-common-definitions
+ image: cobalt-build-android
+ depends_on: [ build-android ]
+ environment:
+ - IS_DOCKER=1
+ - PLATFORM=android-arm
+ - CONFIG=${CONFIG:-debug}
+
+ android-arm64:
+ <<: *build-common-definitions
+ image: cobalt-build-android
+ depends_on: [ build-android ]
+ environment:
+ - IS_DOCKER=1
+ - PLATFORM=android-arm64
+ - CONFIG=${CONFIG:-debug}
+
+ raspi:
+ <<: *build-common-definitions
+ build:
+ context: ./docker/linux/raspi
+ dockerfile: ./Dockerfile
+ image: cobalt-build-raspi
+ environment:
+ - PLATFORM
+ - CONFIG=${CONFIG:-debug}
+
# Define common build container for Evergreen
build-evergreen:
- <<: *common-definitions
+ <<: *build-common-definitions
build:
context: ./docker/linux
dockerfile: evergreen/Dockerfile
@@ -52,36 +162,51 @@
- CONFIG
evergreen-x64-sbversion-12:
- <<: *common-definitions
+ <<: *build-common-definitions
image: cobalt-build-evergreen
depends_on: [ build-evergreen ]
environment:
- PLATFORM=evergreen-x64-sbversion-12
evergreen-x86-sbversion-12:
- <<: *common-definitions
+ <<: *build-common-definitions
image: cobalt-build-evergreen
depends_on: [ build-evergreen ]
environment:
- PLATFORM=evergreen-x86-sbversion-12
evergreen-arm64-sbversion-12:
- <<: *common-definitions
+ <<: *build-common-definitions
image: cobalt-build-evergreen
depends_on: [ build-evergreen ]
environment:
- PLATFORM=evergreen-arm64-sbversion-12
evergreen-arm-hardfp-sbversion-12:
- <<: *common-definitions
+ <<: *build-common-definitions
image: cobalt-build-evergreen
depends_on: [ build-evergreen ]
environment:
- PLATFORM=evergreen-arm-hardfp-sbversion-12
evergreen-arm-softfp-sbversion-12:
- <<: *common-definitions
+ <<: *build-common-definitions
image: cobalt-build-evergreen
depends_on: [ build-evergreen ]
environment:
- PLATFORM=evergreen-arm-softfp-sbversion-12
+
+ unittest:
+ <<: *common-definitions
+ build:
+ context: ./docker/linux
+ dockerfile: unittest/Dockerfile
+ image: cobalt-unittest
+ environment:
+ - PLATFORM=${PLATFORM:-linux-x64x11}
+ - CONFIG=${CONFIG:-debug}
+ volumes:
+ - ${COBALT_SRC:-.}/out/${PLATFORM:-linux-x64x11}_${CONFIG:-debug}:/out
+ # TODO: Get NPLB unittests to run with IPv6 without using the host network.
+ network_mode: "host"
+ depends_on: [ base ]
diff --git a/src/docker/linux/android/Dockerfile b/src/docker/linux/android/Dockerfile
new file mode 100644
index 0000000..ad34732
--- /dev/null
+++ b/src/docker/linux/android/Dockerfile
@@ -0,0 +1,34 @@
+FROM cobalt-build-base
+
+RUN apt update -qqy \
+ && apt install -qqy --no-install-recommends \
+ binutils \
+ bison \
+ default-jdk \
+ g++-multilib \
+ ninja-build \
+ pkgconf \
+ python-requests \
+ yasm \
+ && apt-get clean autoclean \
+ && apt-get autoremove -y --purge \
+ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
+ && rm -rf /var/lib/{apt,dpkg,cache,log} \
+ && echo "Done"
+
+RUN mkdir -p /root/.android
+
+CMD (test -f /root/.android/debug.keystore \
+ && echo "Android debug keystore exists." \
+ || (keytool -genkey -v \
+ -keystore /root/.android/debug.keystore \
+ -dname "cn=Android Docker, ou=YouTube, o=Google, c=US" \
+ -storepass android \
+ -alias androiddebugkey \
+ -keypass android \
+ -keyalg RSA \
+ -keysize 2048 \
+ -validity 10000 \
+ && echo "Generated Android Debug keystore.")) \
+ && /code/cobalt/build/gyp_cobalt -v -C ${CONFIG} ${PLATFORM} \
+ && ninja -C ${OUTDIR}/${PLATFORM}_${CONFIG} ${TARGET:-cobalt_deploy}
diff --git a/src/docker/linux/base/Dockerfile b/src/docker/linux/base/Dockerfile
index 59e3da8..2746def 100644
--- a/src/docker/linux/base/Dockerfile
+++ b/src/docker/linux/base/Dockerfile
@@ -1,5 +1,6 @@
ARG BASE_OS
-FROM ${BASE_OS:-gcr.io/cloud-marketplace-containers/google/debian9}
+ARG BASE_OS_TAG
+FROM ${BASE_OS:-gcr.io/cloud-marketplace-containers/google/debian9}:${BASE_OS_TAG:-latest}
ENV PYTHONUNBUFFERED 1
@@ -15,36 +16,4 @@
&& rm -rf /var/lib/{apt,dpkg,cache,log} \
&& echo "Done"
-# === Get Nodejs pinned LTS version via NVM
-ENV NVM_DIR /root/.nvm
-ENV NODE_VERSION 12.17.0
-
-RUN curl --silent -o- https://raw.githubusercontent.com/creationix/nvm/v0.35.3/install.sh | bash
-
-RUN . $NVM_DIR/nvm.sh \
- && nvm install --lts \
- && nvm alias default lts/* \
- && nvm use default
-
-ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
-ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
-
-# === Install depot_tools
-RUN git clone https://cobalt.googlesource.com/depot_tools /depot_tools
-
-# === Configure common env vars
-ENV PATH="${PATH}:/depot_tools:/root/fake_goma" \
- OUTDIR=out \
- DEPOT_TOOLS_UPDATE=0 \
- NINJA_STATUS="[%f/%t %c/sec] " \
- CCACHE_DIR=/root/ccache \
- CCACHE_MAXSIZE=30G
-
-# == Set up gclient and fake Goma with ccache
-COPY ./files/fake_goma /root/fake_goma
-RUN cd /tmp && gclient verify || true \
- && chmod +x /root/fake_goma/gomacc /root/fake_goma/goma_ctl.py \
- && mkdir /root/ccache
-
-WORKDIR /code
CMD ["/usr/bin/python","--version"]
diff --git a/src/docker/linux/base/build/Dockerfile b/src/docker/linux/base/build/Dockerfile
new file mode 100644
index 0000000..545908d
--- /dev/null
+++ b/src/docker/linux/base/build/Dockerfile
@@ -0,0 +1,34 @@
+ARG FROM_IMAGE
+FROM ${FROM_IMAGE:-cobalt-base}
+
+# === Get Nodejs pinned LTS version via NVM
+ENV NVM_DIR /root/.nvm
+ENV NODE_VERSION 12.17.0
+
+RUN curl --silent -o- https://raw.githubusercontent.com/creationix/nvm/v0.35.3/install.sh | bash
+
+RUN . $NVM_DIR/nvm.sh \
+ && nvm install --lts \
+ && nvm alias default lts/* \
+ && nvm use default
+
+ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
+ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
+
+# === Install depot_tools
+RUN git clone https://cobalt.googlesource.com/depot_tools /depot_tools
+
+# === Configure common env vars
+ENV PATH="${PATH}:/depot_tools" \
+ OUTDIR=out \
+ DEPOT_TOOLS_UPDATE=0 \
+ NINJA_STATUS="[%f/%t %c/sec] " \
+ CCACHE_DIR=/root/ccache \
+ CCACHE_MAXSIZE=30G
+
+# == Set up gclient and ccache
+RUN cd /tmp && gclient verify || true \
+ && mkdir /root/ccache
+
+WORKDIR /code
+CMD ["/usr/bin/python","--version"]
diff --git a/src/docker/linux/clang-3-6/Dockerfile b/src/docker/linux/clang-3-6/Dockerfile
new file mode 100644
index 0000000..0bf3926
--- /dev/null
+++ b/src/docker/linux/clang-3-6/Dockerfile
@@ -0,0 +1,14 @@
+FROM linux-x64x11-xenial
+
+ARG DEBIAN_FRONTEND=noninteractive
+
+RUN apt update -qqy \
+ && apt install -qqy --no-install-recommends clang-3.6 \
+ && apt-get clean autoclean \
+ && apt-get autoremove -y --purge \
+ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
+ && rm -rf /var/lib/{apt,dpkg,cache,log} \
+ && echo "Done"
+
+CMD /code/cobalt/build/gyp_cobalt -v -C ${CONFIG} ${PLATFORM} && \
+ ninja -C ${OUTDIR}/${PLATFORM}_${CONFIG} ${TARGET:-cobalt_deploy}
diff --git a/src/docker/linux/files/fake_goma/goma_ctl.py b/src/docker/linux/files/fake_goma/goma_ctl.py
deleted file mode 100755
index 2f2ceb9..0000000
--- a/src/docker/linux/files/fake_goma/goma_ctl.py
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env python
-
-print("Faking Goma via ccache")
diff --git a/src/docker/linux/files/fake_goma/gomacc b/src/docker/linux/files/fake_goma/gomacc
deleted file mode 100755
index d64f812..0000000
--- a/src/docker/linux/files/fake_goma/gomacc
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-ccache "$@"
diff --git a/src/docker/linux/linux-x64x11/Dockerfile b/src/docker/linux/linux-x64x11/Dockerfile
index 524f320..29f7d8d 100644
--- a/src/docker/linux/linux-x64x11/Dockerfile
+++ b/src/docker/linux/linux-x64x11/Dockerfile
@@ -1,4 +1,5 @@
-FROM cobalt-build-base
+ARG FROM_IMAGE
+FROM ${FROM_IMAGE:-cobalt-build-base}
RUN apt update -qqy \
&& apt install -qqy --no-install-recommends \
diff --git a/src/docker/linux/raspi/Dockerfile b/src/docker/linux/raspi/Dockerfile
new file mode 100644
index 0000000..7ed69d0
--- /dev/null
+++ b/src/docker/linux/raspi/Dockerfile
@@ -0,0 +1,36 @@
+FROM cobalt-build-base
+
+ARG raspi_home=/root/raspi-home
+ARG raspi_sysroot=raspbian_lite_2017-07-05_sysroot.tar.xz
+
+# Required by the gyp build system.
+ENV RASPI_HOME=${raspi_home}
+
+RUN apt update -qqy \
+ && apt install -qqy --no-install-recommends \
+ binutils \
+ bison \
+ g++-multilib \
+ ninja-build \
+ pkgconf \
+ python-requests \
+ wget \
+ xz-utils \
+ yasm \
+ && apt-get clean autoclean \
+ && apt-get autoremove -y --purge \
+ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
+ && rm -rf /var/lib/{apt,dpkg,cache,log} \
+ && echo "Done"
+
+RUN mkdir -p ${raspi_home}/tools \
+ && git clone https://github.com/raspberrypi/tools.git ${raspi_home}/tools
+
+RUN cd ${raspi_home} \
+ && wget -q \
+ "https://storage.googleapis.com/cobalt-static-storage/${raspi_sysroot}"
+
+RUN cd ${raspi_home} && tar Jxpvf ${raspi_sysroot}
+
+CMD /code/cobalt/build/gyp_cobalt -v -C ${CONFIG} ${PLATFORM} \
+ && ninja -C ${OUTDIR}/${PLATFORM}_${CONFIG} ${TARGET:-cobalt_deploy}
diff --git a/src/docker/linux/unittest/Dockerfile b/src/docker/linux/unittest/Dockerfile
new file mode 100644
index 0000000..e876c8d
--- /dev/null
+++ b/src/docker/linux/unittest/Dockerfile
@@ -0,0 +1,35 @@
+FROM cobalt-base
+
+RUN apt update -qqy \
+ && apt install -qqy --no-install-recommends \
+ libasound2 \
+ libavcodec57 \
+ libavformat57 \
+ libavresample3 \
+ libavutil55 \
+ libegl1-mesa \
+ libgl1-mesa-dri \
+ libgles2-mesa \
+ libx11-6 \
+ libxcomposite1 \
+ libxrender1 \
+ unzip \
+ xauth \
+ xvfb \
+ && apt-get clean autoclean \
+ && apt-get autoremove -y --purge \
+ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
+ && rm -rf /var/lib/{apt,dpkg,cache,log} \
+ && echo "Done"
+
+WORKDIR /out
+
+# Sets the locale in the environment. This is needed for NPLB unit tests.
+ENV LANG en_US.UTF-8
+
+RUN mkdir -p /app_launcher_out
+
+CMD unzip -q /out/app_launcher -d /app_launcher_out && \
+ xvfb-run --server-args="-screen 0 1920x1080x24 +render +extension GLX -noreset" \
+ python /app_launcher_out/starboard/tools/testing/test_runner.py --run \
+ -o /out --platform $PLATFORM --config $CONFIG
diff --git a/src/starboard/CHANGELOG.md b/src/starboard/CHANGELOG.md
index cdd706c..40aab86 100644
--- a/src/starboard/CHANGELOG.md
+++ b/src/starboard/CHANGELOG.md
@@ -261,6 +261,23 @@
when those settings change. For older starboard versions, use
kSbEventTypeAccessiblitySettingsChanged instead.
+### Add extension to SbMediaCanPlayMimeAndKeySystem() for encryptionScheme.
+
+Now the Starboard implementation may choose to support |key_system| with extra
+attributes, in order to selectively support encryption schemes on particular
+containers or codecs.
+The Starboard implementation needn't support |key_system| with extra attributes
+if it meets the requirements for the default implementation of
+`Navigator.requestMediaKeySystemAccess()`, which assumes that:
+1. When the Widevine DRM system is used, all the encryption schemes ('cenc',
+ 'cbcs', 'cbcs-1-9') should be supported across all containers and codecs
+ supported by the platform.
+2. When the PlayReady DRM system is used, only 'cenc' is supported across all
+ containers and codecs supported by the platform.
+
+Please see the comment of `SbMediaCanPlayMimeAndKeySystem()` in `media.h` for
+more details.
+
## Version 11
### Add arguments to `SbMediaIsVideoSupported`.
diff --git a/src/starboard/android/apk/app/build.gradle b/src/starboard/android/apk/app/build.gradle
index fdf3b29..5ab0feb 100644
--- a/src/starboard/android/apk/app/build.gradle
+++ b/src/starboard/android/apk/app/build.gradle
@@ -66,7 +66,7 @@
defaultConfig {
applicationId "dev.cobalt.coat"
minSdkVersion 21
- targetSdkVersion 30
+ targetSdkVersion 29
versionCode 1
versionName "${buildId}"
manifestPlaceholders = [applicationName: "CoAT: ${cobaltTarget}"]
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java
index fe988bb..9cee635 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java
@@ -30,7 +30,7 @@
import android.os.Build;
import android.util.Size;
import android.util.SizeF;
-import android.view.Display;
+import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.CaptioningManager;
import androidx.annotation.RequiresApi;
@@ -155,13 +155,17 @@
@SuppressWarnings("unused")
@UsedByNative
protected void beforeSuspend() {
- Log.i(TAG, "Prepare to suspend");
- // We want the MediaSession to be deactivated immediately before suspending so that by the time
- // the launcher is visible our "Now Playing" card is already gone. Then Cobalt and the web app
- // can take their time suspending after that.
- cobaltMediaSession.suspend();
- for (CobaltService service : cobaltServices.values()) {
- service.beforeSuspend();
+ try {
+ Log.i(TAG, "Prepare to suspend");
+ // We want the MediaSession to be deactivated immediately before suspending so that by the time
+ // the launcher is visible our "Now Playing" card is already gone. Then Cobalt and the web app
+ // can take their time suspending after that.
+ cobaltMediaSession.suspend();
+ for (CobaltService service : cobaltServices.values()) {
+ service.beforeSuspend();
+ }
+ } catch (Throwable e) {
+ Log.i(TAG, "Caught exception in beforeSuspend: " + e.getMessage());
}
}
@@ -521,12 +525,18 @@
return false;
}
- Display defaultDisplay = DisplayUtil.getDefaultDisplay(activityHolder.get());
- if (defaultDisplay == null) {
+ Activity activity = activityHolder.get();
+ if (activity == null) {
return false;
}
- int[] supportedHdrTypes = defaultDisplay.getHdrCapabilities().getSupportedHdrTypes();
+ WindowManager windowManager = activity.getWindowManager();
+ if (windowManager == null) {
+ return false;
+ }
+
+ int[] supportedHdrTypes =
+ windowManager.getDefaultDisplay().getHdrCapabilities().getSupportedHdrTypes();
for (int supportedType : supportedHdrTypes) {
if (supportedType == hdrType) {
return true;
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java
index 42c4e98..faa8742 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java
@@ -69,7 +69,6 @@
private static final String KEY_CROP_TOP = "crop-top";
private static final int BITRATE_ADJUSTMENT_FPS = 30;
- private static final int MAXIMUM_INITIAL_FPS = 30;
private long mNativeMediaCodecBridge;
private MediaCodec mMediaCodec;
@@ -78,6 +77,8 @@
private long mLastPresentationTimeUs;
private final String mMime;
private boolean mAdaptivePlaybackSupported;
+ private double mPlaybackRate = 1.0;
+ private int mFps = 30;
// Functions that require this will be called frequently in a tight loop.
// Only create one of these and reuse it to avoid excessive allocations,
@@ -104,6 +105,45 @@
public static final String VIDEO_AV1 = "video/av01";
}
+ private class FrameRateEstimator {
+ private static final int INVALID_FRAME_RATE = -1;
+ private static final long INVALID_FRAME_TIMESTAMP = -1;
+ private static final int MINIMUN_REQUIRED_FRAMES = 4;
+ private long mLastFrameTimestampUs = INVALID_FRAME_TIMESTAMP;
+ private long mNumberOfFrames = 0;
+ private long mTotalDurationUs = 0;
+
+ public int getEstimatedFrameRate() {
+ if (mTotalDurationUs <= 0 || mNumberOfFrames < MINIMUN_REQUIRED_FRAMES) {
+ return INVALID_FRAME_RATE;
+ }
+ return Math.round((mNumberOfFrames - 1) * 1000000.0f / mTotalDurationUs);
+ }
+
+ public void reset() {
+ mLastFrameTimestampUs = INVALID_FRAME_TIMESTAMP;
+ mNumberOfFrames = 0;
+ mTotalDurationUs = 0;
+ }
+
+ public void onNewFrame(long presentationTimeUs) {
+ mNumberOfFrames++;
+
+ if (mLastFrameTimestampUs == INVALID_FRAME_TIMESTAMP) {
+ mLastFrameTimestampUs = presentationTimeUs;
+ return;
+ }
+ if (presentationTimeUs <= mLastFrameTimestampUs) {
+ Log.v(TAG, String.format("Invalid output presentation timestamp."));
+ return;
+ }
+
+ mTotalDurationUs += presentationTimeUs - mLastFrameTimestampUs;
+ mLastFrameTimestampUs = presentationTimeUs;
+ }
+ }
+
+ private FrameRateEstimator mFrameRateEstimator = null;
private BitrateAdjustmentTypes mBitrateAdjustmentType = BitrateAdjustmentTypes.NO_ADJUSTMENT;
@SuppressWarnings("unused")
@@ -415,6 +455,14 @@
info.offset,
info.presentationTimeUs,
info.size);
+ if (mFrameRateEstimator != null) {
+ mFrameRateEstimator.onNewFrame(info.presentationTimeUs);
+ int fps = mFrameRateEstimator.getEstimatedFrameRate();
+ if (fps != FrameRateEstimator.INVALID_FRAME_RATE && mFps != fps) {
+ mFps = fps;
+ updateOperatingRate();
+ }
+ }
}
}
@@ -599,6 +647,40 @@
@SuppressWarnings("unused")
@UsedByNative
+ private void setPlaybackRate(double playbackRate) {
+ if (mPlaybackRate == playbackRate) {
+ return;
+ }
+ mPlaybackRate = playbackRate;
+ if (mFrameRateEstimator != null) {
+ updateOperatingRate();
+ }
+ }
+
+ private void updateOperatingRate() {
+ // We needn't set operation rate if playback rate is 0 or less.
+ if (Double.compare(mPlaybackRate, 0.0) <= 0) {
+ return;
+ }
+ if (mFps == FrameRateEstimator.INVALID_FRAME_RATE) {
+ return;
+ }
+ if (mFps <= 0) {
+ Log.e(TAG, "Failed to set operating rate with invalid fps " + mFps);
+ return;
+ }
+ double operatingRate = mPlaybackRate * mFps;
+ Bundle b = new Bundle();
+ b.putFloat(MediaFormat.KEY_OPERATING_RATE, (float) operatingRate);
+ try {
+ mMediaCodec.setParameters(b);
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "Failed to set MediaCodec operating rate", e);
+ }
+ }
+
+ @SuppressWarnings("unused")
+ @UsedByNative
private int flush() {
try {
mFlushed = true;
@@ -830,17 +912,23 @@
if (mAdaptivePlaybackSupported) {
// Since we haven't passed the properties of the stream we're playing
// down to this level, from our perspective, we could potentially
- // adapt up to 8k at any point. We thus request 8k buffers up front,
+ // adapt up to 8k at any point. We thus request 8k buffers up front,
// unless the decoder claims to not be able to do 8k, in which case
// we're ok, since we would've rejected a 8k stream when canPlayType
// was called, and then use those decoder values instead.
- int maxWidth = Math.min(7680, maxSupportedWidth);
- int maxHeight = Math.min(4320, maxSupportedHeight);
- format.setInteger(MediaFormat.KEY_MAX_WIDTH, maxWidth);
- format.setInteger(MediaFormat.KEY_MAX_HEIGHT, maxHeight);
+ if (Build.VERSION.SDK_INT > 22) {
+ format.setInteger(MediaFormat.KEY_MAX_WIDTH, Math.min(7680, maxSupportedWidth));
+ format.setInteger(MediaFormat.KEY_MAX_HEIGHT, Math.min(4320, maxSupportedHeight));
+ } else {
+ // Android 5.0/5.1 seems not support 8K. Fallback to 4K until we get a
+ // better way to get maximum supported resolution.
+ format.setInteger(MediaFormat.KEY_MAX_WIDTH, Math.min(3840, maxSupportedWidth));
+ format.setInteger(MediaFormat.KEY_MAX_HEIGHT, Math.min(2160, maxSupportedHeight));
+ }
}
maybeSetMaxInputSize(format);
mMediaCodec.configure(format, surface, crypto, flags);
+ mFrameRateEstimator = new FrameRateEstimator();
return true;
} catch (IllegalArgumentException e) {
Log.e(TAG, "Cannot configure the video codec with IllegalArgumentException: ", e);
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/VideoFrameReleaseTimeHelper.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/VideoFrameReleaseTimeHelper.java
index 1e39d63..0274811 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/VideoFrameReleaseTimeHelper.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/VideoFrameReleaseTimeHelper.java
@@ -35,9 +35,8 @@
import android.os.Message;
import android.view.Choreographer;
import android.view.Choreographer.FrameCallback;
-import android.view.Display;
+import android.view.WindowManager;
import androidx.annotation.RequiresApi;
-import dev.cobalt.util.DisplayUtil;
import dev.cobalt.util.UsedByNative;
/** Makes a best effort to adjust frame release timestamps for a smoother visual result. */
@@ -222,9 +221,9 @@
}
private static double getDefaultDisplayRefreshRate(Context context) {
- Display defaultDisplay = DisplayUtil.getDefaultDisplay(context);
- return defaultDisplay != null
- ? defaultDisplay.getRefreshRate()
+ WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ return manager.getDefaultDisplay() != null
+ ? manager.getDefaultDisplay().getRefreshRate()
: DISPLAY_REFRESH_RATE_UNKNOWN;
}
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/util/DisplayUtil.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/util/DisplayUtil.java
index c7c2208..4b23394 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/util/DisplayUtil.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/util/DisplayUtil.java
@@ -15,14 +15,10 @@
package dev.cobalt.util;
import android.content.Context;
-import android.content.res.Resources;
import android.util.DisplayMetrics;
import android.util.Size;
import android.util.SizeF;
-import android.view.Display;
import android.view.WindowManager;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
/** Utility functions for querying display attributes. */
public class DisplayUtil {
@@ -30,34 +26,6 @@
private DisplayUtil() {}
/**
- * Returns the default display associated with a context.
- */
- @Nullable
- public static Display getDefaultDisplay(Context context) {
- if (context == null) {
- return null;
- }
- if (android.os.Build.VERSION.SDK_INT >= 30) {
- return getDefaultDisplayV30(context);
- } else {
- return getDefaultDisplayDeprecated(context);
- }
- }
-
- @Nullable
- @SuppressWarnings("deprecation")
- private static Display getDefaultDisplayDeprecated(Context context) {
- WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- return (wm == null) ? null : wm.getDefaultDisplay();
- }
-
- @Nullable
- @RequiresApi(30)
- private static Display getDefaultDisplayV30(Context context) {
- return context.getDisplay();
- }
-
- /**
* Returns the physical pixels per inch of the screen in the X and Y
* dimensions.
*/
@@ -114,10 +82,10 @@
private static DisplayMetrics cachedDisplayMetrics = null;
private static DisplayMetrics getDisplayMetrics(Context context) {
- Resources.getSystem().getDisplayMetrics();
if (cachedDisplayMetrics == null) {
cachedDisplayMetrics = new DisplayMetrics();
- getDefaultDisplay(context).getRealMetrics(cachedDisplayMetrics);
+ ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
+ .getDefaultDisplay().getRealMetrics(cachedDisplayMetrics);
}
return cachedDisplayMetrics;
}
diff --git a/src/starboard/android/apk/build.id b/src/starboard/android/apk/build.id
deleted file mode 100644
index 20ae2c6..0000000
--- a/src/starboard/android/apk/build.id
+++ /dev/null
@@ -1 +0,0 @@
-277473
\ No newline at end of file
diff --git a/src/starboard/android/shared/android_main.cc b/src/starboard/android/shared/android_main.cc
index 1f6513d..a44497e 100644
--- a/src/starboard/android/shared/android_main.cc
+++ b/src/starboard/android/shared/android_main.cc
@@ -67,6 +67,7 @@
if (j_url) {
start_url = env->GetStringStandardUTFOrAbort(j_url.Get());
}
+ SB_LOG(INFO) << "GetStartDeepLink: " << start_url;
return start_url;
}
diff --git a/src/starboard/android/shared/application_android.cc b/src/starboard/android/shared/application_android.cc
index e8fab42..1352a26 100644
--- a/src/starboard/android/shared/application_android.cc
+++ b/src/starboard/android/shared/application_android.cc
@@ -69,6 +69,8 @@
return "WindowFocusGained";
case ApplicationAndroid::AndroidCommand::kWindowFocusLost:
return "WindowFocusLost";
+ case ApplicationAndroid::AndroidCommand::kDeepLink:
+ return "DeepLink";
default:
return "unknown";
}
@@ -298,6 +300,21 @@
case AndroidCommand::kStop:
sync_state = activity_state_ = cmd.type;
break;
+ case AndroidCommand::kDeepLink:
+ char* deep_link = static_cast<char*>(cmd.data);
+ SB_LOG(INFO) << "AndroidCommand::kDeepLink: deep_link=" << deep_link
+ << " state=" << state();
+ if (deep_link != NULL) {
+ if (state() == kStateUnstarted) {
+ SetStartLink(deep_link);
+ SB_LOG(INFO) << "ApplicationAndroid SetStartLink";
+ SbMemoryDeallocate(static_cast<void*>(deep_link));
+ } else {
+ SB_LOG(INFO) << "ApplicationAndroid Inject: kSbEventTypeLink";
+ Inject(new Event(kSbEventTypeLink, deep_link, SbMemoryDeallocate));
+ }
+ }
+ break;
}
// If there's a window, sync the app state to the Activity lifecycle, letting
@@ -337,7 +354,7 @@
// Android main thread. This lets the MediaSession get released now without
// having to wait to bounce between threads.
JniEnvExt* env = JniEnvExt::Get();
- env->CallStarboardVoidMethodOrAbort("beforeSuspend", "()V");
+ env->CallStarboardVoidMethod("beforeSuspend", "()V");
}
AndroidCommand cmd {type, data};
ScopedLock lock(android_command_mutex_);
@@ -538,12 +555,14 @@
}
void ApplicationAndroid::HandleDeepLink(const char* link_url) {
+ SB_LOG(INFO) << "ApplicationAndroid::HandleDeepLink link_url=" << link_url;
if (link_url == NULL || link_url[0] == '\0') {
return;
}
char* deep_link = SbStringDuplicate(link_url);
SB_DCHECK(deep_link);
- Inject(new Event(kSbEventTypeLink, deep_link, SbMemoryDeallocate));
+
+ SendAndroidCommand(AndroidCommand::kDeepLink, deep_link);
}
extern "C" SB_EXPORT_PLATFORM
diff --git a/src/starboard/android/shared/application_android.h b/src/starboard/android/shared/application_android.h
index 3ad4820..6dad099 100644
--- a/src/starboard/android/shared/application_android.h
+++ b/src/starboard/android/shared/application_android.h
@@ -51,6 +51,7 @@
kNativeWindowDestroyed,
kWindowFocusGained,
kWindowFocusLost,
+ kDeepLink,
} CommandType;
CommandType type;
diff --git a/src/starboard/android/shared/audio_track_audio_sink_type.h b/src/starboard/android/shared/audio_track_audio_sink_type.h
index 1a8cb37..43b0c86 100644
--- a/src/starboard/android/shared/audio_track_audio_sink_type.h
+++ b/src/starboard/android/shared/audio_track_audio_sink_type.h
@@ -74,10 +74,10 @@
SbMediaAudioSampleType sample_type,
int sampling_frequency_hz);
- MinRequiredFramesTester min_required_frames_tester_;
Mutex min_required_frames_map_mutex_;
// The minimum frames required to avoid underruns of different frequencies.
std::map<int, int> min_required_frames_map_;
+ MinRequiredFramesTester min_required_frames_tester_;
};
class AudioTrackAudioSink : public SbAudioSinkPrivate {
diff --git a/src/starboard/android/shared/cobalt/configuration.py b/src/starboard/android/shared/cobalt/configuration.py
index 96c11fe..f9cf7d7 100644
--- a/src/starboard/android/shared/cobalt/configuration.py
+++ b/src/starboard/android/shared/cobalt/configuration.py
@@ -66,6 +66,11 @@
# A map of failing or crashing tests per target.
__FILTERED_TESTS = {
+ 'layout_tests': [
+ # Android relies of system fonts and some older Android builds do not
+ # have the update (Emoji 11.0) NotoColorEmoji.ttf installed.
+ 'CSS3FontsLayoutTests/Layout.Test/color_emojis_should_render_properly'
+ ],
'renderer_test': [
# Instead of returning an error when allocating too much texture
# memory, Android instead just terminates the process. Since this
diff --git a/src/starboard/android/shared/gyp_configuration.py b/src/starboard/android/shared/gyp_configuration.py
index ce072b3..04d5372 100644
--- a/src/starboard/android/shared/gyp_configuration.py
+++ b/src/starboard/android/shared/gyp_configuration.py
@@ -146,7 +146,7 @@
if not self._target_toolchain:
tool_prefix = os.path.join(sdk_utils.GetNdkPath(), 'toolchains', 'llvm',
'prebuilt', 'linux-x86_64', 'bin', '')
- cc_path = tool_prefix + _ABI_TOOL_NAMES[self.android_abi][0]
+ cc_path = self.build_accelerator + ' ' + tool_prefix + _ABI_TOOL_NAMES[self.android_abi][0]
cxx_path = cc_path + '++'
ar_path = tool_prefix + _ABI_TOOL_NAMES[self.android_abi][1]
clang_flags = [
@@ -243,7 +243,7 @@
if not self._host_toolchain:
if not hasattr(self, 'host_compiler_environment'):
self.host_compiler_environment = build.GetHostCompilerEnvironment(
- clang_build.GetClangSpecification(), False)
+ clang_build.GetClangSpecification(), self.build_accelerator)
cc_path = self.host_compiler_environment['CC_host'],
cxx_path = self.host_compiler_environment['CXX_host']
self._host_toolchain = [
@@ -327,6 +327,18 @@
'SbDirectoryGetNextTest.SunnyDayStaticContent',
'SbDirectoryOpenTest.SunnyDayStaticContent',
'SbFileGetPathInfoTest.WorksOnStaticContentDirectories',
+ # Android doesn't currently support specifying a bitrate under 8000
+ 'SbMediaCanPlayMimeAndKeySystem.MinimumSupport',
+ # There are issues with playback of heeac format files where the input
+ # |frames_per_channel| is 6912, instead of 12544 (as with other
+ # formats).
+ 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.NoInput/6',
+ # These tests are disabled due to not receiving the kEndOfStream
+ # player state update within the specified timeout.
+ 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.NoInput/7',
+ 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.NoInput/8',
+ 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.NoInput/9',
+ 'SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.NoInput/10',
],
}
diff --git a/src/starboard/android/shared/media_codec_bridge.cc b/src/starboard/android/shared/media_codec_bridge.cc
index b39a61d..f78c347 100644
--- a/src/starboard/android/shared/media_codec_bridge.cc
+++ b/src/starboard/android/shared/media_codec_bridge.cc
@@ -344,6 +344,11 @@
render_timestamp_ns);
}
+void MediaCodecBridge::SetPlaybackRate(double playback_rate) {
+ JniEnvExt::Get()->CallVoidMethodOrAbort(
+ j_media_codec_bridge_, "setPlaybackRate", "(D)V", playback_rate);
+}
+
jint MediaCodecBridge::Flush() {
return JniEnvExt::Get()->CallIntMethodOrAbort(j_media_codec_bridge_, "flush",
"()I");
diff --git a/src/starboard/android/shared/media_codec_bridge.h b/src/starboard/android/shared/media_codec_bridge.h
index 1fc6618..77452c1 100644
--- a/src/starboard/android/shared/media_codec_bridge.h
+++ b/src/starboard/android/shared/media_codec_bridge.h
@@ -131,6 +131,7 @@
void ReleaseOutputBuffer(jint index, jboolean render);
void ReleaseOutputBufferAtTimestamp(jint index, jlong render_timestamp_ns);
+ void SetPlaybackRate(double playback_rate);
jint Flush();
SurfaceDimensions GetOutputDimensions();
AudioOutputFormatResult GetAudioOutputFormat();
diff --git a/src/starboard/android/shared/media_decoder.cc b/src/starboard/android/shared/media_decoder.cc
index d5668d0..fc5fa0d 100644
--- a/src/starboard/android/shared/media_decoder.cc
+++ b/src/starboard/android/shared/media_decoder.cc
@@ -177,6 +177,12 @@
}
}
+void MediaDecoder::SetPlaybackRate(double playback_rate) {
+ SB_DCHECK(media_type_ == kSbMediaTypeVideo);
+ SB_DCHECK(media_codec_bridge_);
+ media_codec_bridge_->SetPlaybackRate(playback_rate);
+}
+
// static
void* MediaDecoder::DecoderThreadEntryPoint(void* context) {
SB_DCHECK(context);
diff --git a/src/starboard/android/shared/media_decoder.h b/src/starboard/android/shared/media_decoder.h
index 41a7a11..80d0b7e 100644
--- a/src/starboard/android/shared/media_decoder.h
+++ b/src/starboard/android/shared/media_decoder.h
@@ -86,6 +86,8 @@
void WriteInputBuffer(const scoped_refptr<InputBuffer>& input_buffer);
void WriteEndOfStream();
+ void SetPlaybackRate(double playback_rate);
+
size_t GetNumberOfPendingTasks() const {
return number_of_pending_tasks_.load();
}
diff --git a/src/starboard/android/shared/media_is_supported.cc b/src/starboard/android/shared/media_is_supported.cc
index 26d1e19..42aa227 100644
--- a/src/starboard/android/shared/media_is_supported.cc
+++ b/src/starboard/android/shared/media_is_supported.cc
@@ -16,12 +16,19 @@
#include "starboard/android/shared/jni_env_ext.h"
#include "starboard/android/shared/media_common.h"
+#include "starboard/string.h"
bool SbMediaIsSupported(SbMediaVideoCodec video_codec,
SbMediaAudioCodec audio_codec,
const char* key_system) {
using starboard::android::shared::IsWidevineL1;
using starboard::android::shared::JniEnvExt;
+
+ if (SbStringFindCharacter(key_system, ';')) {
+ // TODO: Remove this check and enable key system with attributes support.
+ return false;
+ }
+
// Filter anything other then aac as we only support paid content on aac.
// TODO: Add support of Opus if we are going to support software based drm
// systems.
diff --git a/src/starboard/android/shared/player_components_factory.cc b/src/starboard/android/shared/player_components_factory.cc
index 948b85a..6ac984a 100644
--- a/src/starboard/android/shared/player_components_factory.cc
+++ b/src/starboard/android/shared/player_components_factory.cc
@@ -38,6 +38,15 @@
namespace {
+const int kAudioSinkFramesAlignment = 256;
+const int kDefaultAudioSinkMinFramesPerAppend = 1024;
+const int kDefaultAudioSinkMaxCachedFrames =
+ 8 * kDefaultAudioSinkMinFramesPerAppend;
+
+int AlignUp(int value, int alignment) {
+ return (value + alignment - 1) / alignment * alignment;
+}
+
class PlayerComponentsFactory : public PlayerComponents::Factory {
bool CreateSubComponents(
const CreationParameters& creation_parameters,
@@ -94,6 +103,8 @@
creation_parameters.decode_target_graphics_context_provider(),
creation_parameters.max_video_capabilities(), error_message));
if (video_decoder_impl->is_valid()) {
+ video_render_algorithm->reset(new android::shared::VideoRenderAlgorithm(
+ video_decoder_impl.get()));
*video_renderer_sink = video_decoder_impl->GetSink();
video_decoder->reset(video_decoder_impl.release());
} else {
@@ -103,12 +114,35 @@
"Failed to create video decoder with error: " + *error_message;
return false;
}
-
- video_render_algorithm->reset(new android::shared::VideoRenderAlgorithm);
}
return true;
}
+
+ void GetAudioRendererParams(const CreationParameters& creation_parameters,
+ int* max_cached_frames,
+ int* min_frames_per_append) const override {
+ SB_DCHECK(max_cached_frames);
+ SB_DCHECK(min_frames_per_append);
+ SB_DCHECK(kDefaultAudioSinkMinFramesPerAppend % kAudioSinkFramesAlignment ==
+ 0);
+ *min_frames_per_append = kDefaultAudioSinkMinFramesPerAppend;
+
+ // AudioRenderer prefers to use kSbMediaAudioSampleTypeFloat32 and only uses
+ // kSbMediaAudioSampleTypeInt16Deprecated when float32 is not supported.
+ int min_frames_required = SbAudioSinkGetMinBufferSizeInFrames(
+ creation_parameters.audio_sample_info().number_of_channels,
+ SbAudioSinkIsAudioSampleTypeSupported(kSbMediaAudioSampleTypeFloat32)
+ ? kSbMediaAudioSampleTypeFloat32
+ : kSbMediaAudioSampleTypeInt16Deprecated,
+ creation_parameters.audio_sample_info().samples_per_second);
+ // On Android 5.0, the size of audio renderer sink buffer need to be two
+ // times larger than AudioTrack minBufferSize. Otherwise, AudioTrack may
+ // stop working after pause.
+ *max_cached_frames =
+ min_frames_required * 2 + kDefaultAudioSinkMinFramesPerAppend;
+ *max_cached_frames = AlignUp(*max_cached_frames, kAudioSinkFramesAlignment);
+ }
};
} // namespace
diff --git a/src/starboard/android/shared/video_decoder.cc b/src/starboard/android/shared/video_decoder.cc
index 5a5030e..96a490a 100644
--- a/src/starboard/android/shared/video_decoder.cc
+++ b/src/starboard/android/shared/video_decoder.cc
@@ -377,6 +377,7 @@
media_decoder_->Initialize(
std::bind(&VideoDecoder::ReportError, this, _1, _2));
}
+ media_decoder_->SetPlaybackRate(playback_rate_);
return true;
}
media_decoder_.reset();
@@ -577,6 +578,13 @@
return kSbDecodeTargetInvalid;
}
+void VideoDecoder::SetPlaybackRate(double playback_rate) {
+ playback_rate_ = playback_rate;
+ if (media_decoder_) {
+ media_decoder_->SetPlaybackRate(playback_rate);
+ }
+}
+
void VideoDecoder::OnNewTextureAvailable() {
has_new_texture_available_.store(true);
}
diff --git a/src/starboard/android/shared/video_decoder.h b/src/starboard/android/shared/video_decoder.h
index 8202f57..508817f 100644
--- a/src/starboard/android/shared/video_decoder.h
+++ b/src/starboard/android/shared/video_decoder.h
@@ -83,6 +83,8 @@
void Reset() override;
SbDecodeTarget GetCurrentDecodeTarget() override;
+ void SetPlaybackRate(double playback_rate);
+
bool is_valid() const { return media_decoder_ != NULL; }
void OnNewTextureAvailable();
@@ -133,6 +135,8 @@
int32_t frame_width_ = 0;
int32_t frame_height_ = 0;
+ double playback_rate_ = 1.0;
+
// The last enqueued |SbMediaColorMetadata|.
optional<SbMediaColorMetadata> color_metadata_;
diff --git a/src/starboard/android/shared/video_render_algorithm.cc b/src/starboard/android/shared/video_render_algorithm.cc
index 1b7e9aa..b234937 100644
--- a/src/starboard/android/shared/video_render_algorithm.cc
+++ b/src/starboard/android/shared/video_render_algorithm.cc
@@ -18,6 +18,7 @@
#include "starboard/android/shared/jni_utils.h"
#include "starboard/android/shared/media_common.h"
+#include "starboard/common/log.h"
namespace starboard {
namespace android {
@@ -36,6 +37,12 @@
} // namespace
+VideoRenderAlgorithm::VideoRenderAlgorithm(VideoDecoder* video_decoder)
+ : video_decoder_(video_decoder) {
+ SB_DCHECK(video_decoder_);
+ video_decoder_->SetPlaybackRate(playback_rate_);
+}
+
void VideoRenderAlgorithm::Render(
MediaTimeProvider* media_time_provider,
std::list<scoped_refptr<VideoFrame>>* frames,
@@ -61,6 +68,10 @@
if (!is_audio_playing) {
break;
}
+ if (playback_rate != playback_rate_) {
+ playback_rate_ = playback_rate;
+ video_decoder_->SetPlaybackRate(playback_rate);
+ }
jlong early_us = frames->front()->timestamp() - playback_time;
diff --git a/src/starboard/android/shared/video_render_algorithm.h b/src/starboard/android/shared/video_render_algorithm.h
index 187a1ca..132e871 100644
--- a/src/starboard/android/shared/video_render_algorithm.h
+++ b/src/starboard/android/shared/video_render_algorithm.h
@@ -18,6 +18,7 @@
#include <list>
#include "starboard/android/shared/jni_env_ext.h"
+#include "starboard/android/shared/video_decoder.h"
#include "starboard/shared/starboard/player/filter/video_render_algorithm.h"
namespace starboard {
@@ -27,6 +28,8 @@
class VideoRenderAlgorithm : public ::starboard::shared::starboard::player::
filter::VideoRenderAlgorithm {
public:
+ explicit VideoRenderAlgorithm(VideoDecoder* video_decoder);
+
void Render(MediaTimeProvider* media_time_provider,
std::list<scoped_refptr<VideoFrame>>* frames,
VideoRendererSink::DrawFrameCB draw_frame_cb) override;
@@ -45,6 +48,8 @@
jobject j_video_frame_release_time_helper_ = nullptr;
};
+ VideoDecoder* video_decoder_ = nullptr;
+ double playback_rate_ = 1.0;
VideoFrameReleaseTimeHelper video_frame_release_time_helper_;
int dropped_frames_ = 0;
};
diff --git a/src/starboard/android/shared/video_window.cc b/src/starboard/android/shared/video_window.cc
index 8329a85..88b7037 100644
--- a/src/starboard/android/shared/video_window.cc
+++ b/src/starboard/android/shared/video_window.cc
@@ -123,6 +123,11 @@
// during painting.
ScopedLock lock(*GetViewSurfaceMutex());
+ if (!g_native_video_window) {
+ SB_LOG(INFO) << "Tried to clear video window when it was null.";
+ return;
+ }
+
if (g_reset_surface_on_clear_window) {
int width = ANativeWindow_getWidth(g_native_video_window);
int height = ANativeWindow_getHeight(g_native_video_window);
@@ -133,11 +138,6 @@
}
}
- if (!g_native_video_window) {
- SB_LOG(INFO) << "Tried to clear video window when it was null.";
- return;
- }
-
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, NULL, NULL);
if (display == EGL_NO_DISPLAY) {
diff --git a/src/starboard/build/platform_configuration.py b/src/starboard/build/platform_configuration.py
index 44f7155..ebb054e 100644
--- a/src/starboard/build/platform_configuration.py
+++ b/src/starboard/build/platform_configuration.py
@@ -22,6 +22,7 @@
from starboard.build.application_configuration import ApplicationConfiguration
from starboard.optional import get_optional_tests
from starboard.sabi import sabi
+from starboard.tools import ccache
from starboard.tools import environment
from starboard.tools import paths
from starboard.tools import platform
@@ -62,14 +63,23 @@
asan_enabled_by_default=False,
directory=None):
self._platform_name = platform_name
+ self._asan_default = 1 if asan_enabled_by_default else 0
if directory:
self._directory = directory
else:
self._directory = os.path.realpath(os.path.dirname(__file__))
- self._asan_default = 1 if asan_enabled_by_default else 0
self._application_configuration = None
self._application_configuration_search_path = [self._directory]
+ # Specifies the build accelerator to be used. Default is ccache.
+ build_accelerator = ccache.Ccache()
+ if build_accelerator.Use():
+ self.build_accelerator = build_accelerator.GetName()
+ logging.info('Using %sbuild accelerator.', self.build_accelerator)
+ else:
+ self.build_accelerator = ''
+ logging.info('Not using a build accelerator.')
+
def GetBuildFormat(self):
"""Returns the desired build format."""
return 'ninja'
diff --git a/src/starboard/build/toolchain/gcc_toolchain.gni b/src/starboard/build/toolchain/gcc_toolchain.gni
index ef3d025..6fab1ae 100644
--- a/src/starboard/build/toolchain/gcc_toolchain.gni
+++ b/src/starboard/build/toolchain/gcc_toolchain.gni
@@ -17,7 +17,6 @@
# limitations under the License.
import("//starboard/build/toolchain/clang.gni")
-import("//starboard/build/toolchain/goma.gni")
# This template defines a toolchain for something that works like gcc
# (including clang).
@@ -111,29 +110,8 @@
forward_variables_from(invoker_toolchain_args, "*")
}
- # When the invoker has explicitly overridden use_goma or cc_wrapper in the
- # toolchain args, use those values, otherwise default to the global one.
- # This works because the only reasonable override that toolchains might
- # supply for these values are to force-disable them.
- if (defined(toolchain_args.use_goma)) {
- toolchain_uses_goma = toolchain_args.use_goma
- } else {
- toolchain_uses_goma = use_goma
- }
-
- # When the invoker has explicitly overridden use_goma in the
- # toolchain args, use those values, otherwise default to the global one.
- # This works because the only reasonable override that toolchains might
- # supply for these values are to force-disable them.
- if (toolchain_uses_goma) {
- goma_path = "$goma_dir/gomacc"
- compiler_prefix = "${goma_path} "
- } else {
- compiler_prefix = ""
- }
-
- cc = compiler_prefix + invoker.cc
- cxx = compiler_prefix + invoker.cxx
+ cc = invoker.cc
+ cxx = invoker.cxx
ar = invoker.ar
ld = invoker.ld
if (!defined(asm)) {
diff --git a/src/starboard/build/toolchain/goma.gni b/src/starboard/build/toolchain/goma.gni
deleted file mode 100644
index 84914b2..0000000
--- a/src/starboard/build/toolchain/goma.gni
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (c) 2013 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.
-
-# Modifications Copyright 2017 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Defines the configuration of Goma.
-
-# Allow ports to set an alternate default for use_goma
-import("//$starboard_path/configuration.gni")
-
-declare_args() {
- if (!defined(use_goma)) {
- # Set to true to enable distributed compilation using Goma. By default we
- # use Goma for stub and linux.
- use_goma = false
- }
-
- # Set the default value based on the platform.
- if (host_os == "win" || host_os == "winrt_81" ||
- host_os == "winrt_81_phone" || host_os == "winrt_10") {
- # Absolute directory containing the gomacc.exe binary.
- goma_dir = "C:\goma\goma-win64"
- } else {
- # Absolute directory containing the gomacc binary.
- goma_dir = getenv("HOME") + "/goma"
- }
-}
diff --git a/src/starboard/client_porting/eztime/test_constants.h b/src/starboard/client_porting/eztime/test_constants.h
index 92e0e59..0561ea1 100644
--- a/src/starboard/client_porting/eztime/test_constants.h
+++ b/src/starboard/client_porting/eztime/test_constants.h
@@ -48,16 +48,16 @@
// agree.
static const EzTimeT kTestTimeWindowsNegative = SB_INT64_C(-12212553600);
-// 1443473373 in POSIX time is
-// Monday, 9/28/2015 20:49:33 UTC
-// NOTE: Update this value once every 5 or so years.
-static const EzTimeT kTestTimeWritten = SB_INT64_C(1443473373);
+// 1600970155 in POSIX time is
+// Thursday, 9/24/2020 17:55:55 UTC
+// NOTE: Update this value once every 25 or so years.
+static const EzTimeT kTestTimeWritten = SB_INT64_C(1600970155);
-// 5 years after the time this test was written.
+// 25 years after the time this test was written.
static const EzTimeT kTestTimePastWritten =
- (kTestTimeWritten + (5 * kTestEzTimeTYear));
+ (kTestTimeWritten + (25 * kTestEzTimeTYear));
-// 1443473373 in POSIX time is
+// 4133980800 in POSIX time is
// Saturday, 01 Jan 2101 00:00:00 UTC
// NOTE: Update this value once every 100 or so years.
static const EzTimeT kTestTimeNextCentury = SB_INT64_C(4133980800);
diff --git a/src/starboard/contrib/linux/x64wl/gyp_configuration.py b/src/starboard/contrib/linux/x64wl/gyp_configuration.py
index 3d6687a..64a2c4b 100644
--- a/src/starboard/contrib/linux/x64wl/gyp_configuration.py
+++ b/src/starboard/contrib/linux/x64wl/gyp_configuration.py
@@ -26,11 +26,13 @@
"""Starboard Linux X64 Wayland platform configuration."""
def __init__(self,
- platform_name='linux-x64wl',
+ platform='linux-x64wl',
asan_enabled_by_default=False,
- goma_supports_compiler=True):
- super(LinuxX64WaylandConfiguration, self).__init__(
- platform_name, asan_enabled_by_default, goma_supports_compiler)
+ sabi_json_path='starboard/sabi/default/sabi.json'):
+ # pylint: disable=useless-super-delegation
+ super(LinuxX64WaylandConfiguration, self).__init__(platform,
+ asan_enabled_by_default,
+ sabi_json_path)
def GetTargetToolchain(self, **kwargs):
return self.GetHostToolchain(**kwargs)
diff --git a/src/starboard/doc/evergreen/symbolizing_minidumps.md b/src/starboard/doc/evergreen/symbolizing_minidumps.md
new file mode 100644
index 0000000..4931300
--- /dev/null
+++ b/src/starboard/doc/evergreen/symbolizing_minidumps.md
@@ -0,0 +1,129 @@
+# How to Symbolize Dumps
+
+Evergreen will store the minidumps (`.dmp` files) from the 2 most recent
+crashes on the disk. They are stored under `kSbSystemPathCacheDirectory` in the
+subdirectory `crashpad_database/`. These files can be used along with
+Breakpad's tools to get a full stacktrace of the past crashes. This can help in
+debugging, as these minidumps have the information for the dynamic
+`libcobalt.so` module correctly mapped, which a out-of-the-box dumper could not
+manage.
+
+## Obtaining the Tools to Symbolize Minidumps
+
+Tools for symbolizing these dumps are available through
+[Breakpad](https://chromium.googlesource.com/breakpad/breakpad/). Breakpad is
+an open source crash reporting library that we use to obtain symbol files
+(`.sym`) from unstripped binaries, and to process the symbol files with the
+minidumps to produce human-readable stacktraces.
+
+
+### Building Breakpad
+
+[Breakpad](https://chromium.googlesource.com/breakpad/breakpad/) provides
+instructions for building these tools yourself. The
+[Getting Started with Breakpad](https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/getting_started_with_breakpad.md)
+guide is a good place to start if you want to go through the docs yourself, but
+below is a brief overview of how to get and build the tools.
+
+Download depot_tools:
+```
+$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
+$ export PATH=/path/to/depot_tools:$PATH
+```
+
+Get breakpad:
+```
+$ mkdir breakpad && cd breakpad
+$ fetch breakpad
+$ cd src
+```
+
+Build breakpad:
+```
+$ ./configure && make
+```
+
+This will build the processor (`src/processor/minidump_stackwalk`), and when
+building on Linux it will also build the `dump_syms` tool
+(`src/tools/linux/dump_syms/dump_syms`).
+
+**IMPORTANT:** Once you have fetched Breakpad, you should remove the path to
+depot_tools from your `$PATH` environment variable, as it can conflict with
+Cobalt's depot_tools.
+
+## Symbolizing Minidumps
+
+Now that you have all the tools you need, we can symbolize the dumps. To be
+able to symbolize Cobalt using Evergreen, you need to be get the unstripped
+`libcobalt.so` binary. These will be available as assets in GitHub releases
+[on Cobalt's public GitHub repo](https://github.com/youtube/cobalt/releases).
+
+libcobalt releases will be labeled by the Evergreen version, the architecture,
+the config, and the ELF build id, for example
+"libcobalt_1.0.10_unstripped_armeabi_softfp_qa_ac3132014007df0e.tgz". Here, we
+have:
+* Evergreen Version: 1.0.10
+* Architecture: armeabi_softfp
+* Config: qa
+* ELF Build Id: ac3132014007df0e
+
+Knowing the architecture and config you want, you'll just have to know which
+version of Evergreen you're on or obtain the build id of the library. If you
+need to obtain the ELF build id, you can do so easily by running
+`readelf -n /path/to/libcobalt.so` and look at the hash displayed after "Build
+ID:".
+
+Now you can get the debug symbols from the library using the tools we
+downloaded previously. Unpack libcobalt and dump its symbols into a file:
+
+```
+$ tar xzf /path/to/libcobalt.tgz
+$ /path/to/dump_syms /path/to/unzipped/libcobalt > libcobalt.so.sym
+$ head -n1 libcobalt.so.sym
+MODULE Linux x86_64 6462A5D44C0843D100000000000000000 libcobalt.so
+```
+
+We run `head` on the symbol file to get the debug identifier, the hash
+displayed above (in this case, it's `6462A5D44C0843D100000000000000000`). Now
+we can create the file structure that `minidump_stackwalker` expects and run
+the stackwalker against the minidump:
+
+```
+$ mkdir -p symbols/libcobalt.so/<debug identifier>/
+$ mv libcobalt.so.sym symbols/libcobalt.so/<debug identifier>/
+$ /path/to/minidump_stackwalk /path/to/your/minidump.dmp symbols/
+```
+
+`minidump_stackwalk` produces verbose output on stderr, and the stacktrace on
+stdout, so you may want to redirect stderr.
+
+### Addendum: Adding Other Symbols
+
+We can use the process above to add symbols for any library or executable you
+use, not just `libcobalt.so`. To do this, all you have to do is run the
+`dump_syms` tools on the binary you want symbolized and put that in the
+"symbols/" folder.
+
+```
+$ /path/to/dump_syms /path/to/<your-binary> > <your-binary>.sym
+$ head -n1 <your-binary.sym>
+MODULE Linux x86_64 <debug-identifier> <your-binary>
+$ mkdir -p symbols/<your-binary>/<debug-identifier>
+$ mv <your-binary>.sym symbols/<your-binary>/<debug-identifier>/
+```
+
+Now, `minidump_stackwalk` should symbolize sections within `<your-binary>`. For
+example, if you decided to symbolize the `loader_app`, it would transform the
+stacktrace output from `minidump_stackwalk` from:
+
+```
+9 loader_app + 0x3a31130
+```
+
+to:
+
+```
+9 loader_app!SbEventHandle [sandbox.cc : 44 + 0x8]
+```
+
+Note that the addresses will vary.
diff --git a/src/starboard/elf_loader/evergreen_info.h b/src/starboard/elf_loader/evergreen_info.h
index fecd079..2adfe29 100644
--- a/src/starboard/elf_loader/evergreen_info.h
+++ b/src/starboard/elf_loader/evergreen_info.h
@@ -26,6 +26,7 @@
// the starboard implementation.
#define EVERGREEN_FILE_PATH_MAX_SIZE 4096
#define EVERGREEN_BUILD_ID_MAX_SIZE 128
+#define EVERGREEN_USER_AGENT_MAX_SIZE 2048
#define IS_EVERGREEN_ADDRESS(address, evergreen_info) \
(evergreen_info.base_address != 0 && \
@@ -62,6 +63,12 @@
size_t build_id_length;
} EvergreenInfo;
+// Annotations that Evergreen will add to Crashpad for more detailed crash
+// reports.
+typedef struct EvergreenAnnotations {
+ char user_agent_string[EVERGREEN_USER_AGENT_MAX_SIZE];
+} EvergreenAnnotations;
+
// Set the Evergreen information. Should be called only from the
// elf_loader module. Passing NULL clears the currently stored
// information.
diff --git a/src/starboard/elf_loader/sandbox.cc b/src/starboard/elf_loader/sandbox.cc
index 857ab89..9dd2f73 100644
--- a/src/starboard/elf_loader/sandbox.cc
+++ b/src/starboard/elf_loader/sandbox.cc
@@ -21,6 +21,7 @@
#include "starboard/event.h"
#include "starboard/mutex.h"
#include "starboard/shared/starboard/command_line.h"
+#include "starboard/string.h"
#include "starboard/thread_types.h"
#include "third_party/crashpad/wrapper/wrapper.h"
@@ -63,6 +64,20 @@
g_sb_event_func = reinterpret_cast<void (*)(const SbEvent*)>(
g_elf_loader.LookupSymbol("SbEventHandle"));
+ auto get_user_agent_func = reinterpret_cast<const char* (*)()>(
+ g_elf_loader.LookupSymbol("GetCobaltUserAgentString"));
+ if (!get_user_agent_func) {
+ SB_LOG(ERROR) << "Failed to get user agent string";
+ } else {
+ EvergreenAnnotations cobalt_version_info;
+ SbMemorySet(&cobalt_version_info, sizeof(EvergreenAnnotations), 0);
+ SbStringCopy(cobalt_version_info.user_agent_string, get_user_agent_func(),
+ EVERGREEN_USER_AGENT_MAX_SIZE);
+ third_party::crashpad::wrapper::AddAnnotationsToCrashpad(
+ cobalt_version_info);
+ SB_DLOG(INFO) << "Added user agent string to Crashpad.";
+ }
+
if (!g_sb_event_func) {
SB_LOG(ERROR) << "Failed to find SbEventHandle.";
return;
diff --git a/src/starboard/evergreen/arm/shared/gyp_configuration.gypi b/src/starboard/evergreen/arm/shared/gyp_configuration.gypi
index 404d3a3..4192b6c 100644
--- a/src/starboard/evergreen/arm/shared/gyp_configuration.gypi
+++ b/src/starboard/evergreen/arm/shared/gyp_configuration.gypi
@@ -24,6 +24,8 @@
# Force char to be signed.
'-fsigned-char',
+ '-ffunction-sections',
+ '-fdata-sections',
],
'linker_flags': [
diff --git a/src/starboard/evergreen/arm/shared/gyp_configuration.py b/src/starboard/evergreen/arm/shared/gyp_configuration.py
index c6c67ed..33a2284 100644
--- a/src/starboard/evergreen/arm/shared/gyp_configuration.py
+++ b/src/starboard/evergreen/arm/shared/gyp_configuration.py
@@ -17,7 +17,6 @@
from starboard.build import clang as clang_build
from starboard.evergreen.shared import gyp_configuration as shared_configuration
-from starboard.tools import build
from starboard.tools.testing import test_filter
from starboard.tools.toolchain import ar
from starboard.tools.toolchain import bash
@@ -32,34 +31,29 @@
"""Starboard Evergreen ARM platform configuration."""
def __init__(self,
- platform_name='evergreen-arm',
+ platform='evergreen-arm',
asan_enabled_by_default=False,
- goma_supports_compiler=True,
sabi_json_path='starboard/sabi/default/sabi.json'):
- # pylint: disable=useless-super-delegation
- super(EvergreenArmConfiguration,
- self).__init__(platform_name, asan_enabled_by_default,
- goma_supports_compiler, sabi_json_path)
+ super(EvergreenArmConfiguration, self).__init__(platform,
+ asan_enabled_by_default,
+ sabi_json_path)
+
self.AppendApplicationConfigurationPath(os.path.dirname(__file__))
- self._host_toolchain = None
def GetTargetToolchain(self, **kwargs):
return self.GetHostToolchain(**kwargs)
def GetHostToolchain(self, **kwargs):
- if not self._host_toolchain:
- if not hasattr(self, 'host_compiler_environment'):
- self.host_compiler_environment = build.GetHostCompilerEnvironment(
- clang_build.GetClangSpecification(), False)
- cc_path = self.host_compiler_environment['CC_host']
- cxx_path = self.host_compiler_environment['CXX_host']
+ if not hasattr(self, '_host_toolchain'):
+ env_variables = self.GetEnvironmentVariables()
+ cc_path = env_variables['CC_host']
+ cxx_path = env_variables['CXX_host']
- # Takes the provided value of CXX_HOST with a prepended 'gomacc' and an
+ # Takes the provided value of CXX_HOST with a prepended 'ccache' and an
# appended 'bin/clang++' and strips them off, leaving us with an absolute
# path to the root directory of our toolchain.
begin_path_index = cxx_path.find('/')
end_path_index = cxx_path.rfind('/', 0, cxx_path.rfind('/')) + 1
-
cxx_path_root = cxx_path[begin_path_index:end_path_index]
self._host_toolchain = [
@@ -93,7 +87,8 @@
return variables
__FILTERED_TESTS = { # pylint: disable=invalid-name
- 'nplb': ['SbSystemGetStackTest.SunnyDayStackDirection',
+ 'nplb': ['SbPlayerWriteSampleTests/SbPlayerWriteSampleTest.NoInput/4',
+ 'SbSystemGetStackTest.SunnyDayStackDirection',
'SbSystemGetStackTest.SunnyDay',
'SbSystemGetStackTest.SunnyDayShortStack',
'SbSystemSymbolizeTest.SunnyDay'],
diff --git a/src/starboard/evergreen/arm64/gyp_configuration.gypi b/src/starboard/evergreen/arm64/gyp_configuration.gypi
index b2a0525..f8843b2 100644
--- a/src/starboard/evergreen/arm64/gyp_configuration.gypi
+++ b/src/starboard/evergreen/arm64/gyp_configuration.gypi
@@ -22,6 +22,8 @@
'compiler_flags': [
'-isystem<(cobalt_repo_root)/third_party/musl/arch/aarch64',
+ '-ffunction-sections',
+ '-fdata-sections',
],
},
diff --git a/src/starboard/evergreen/arm64/gyp_configuration.py b/src/starboard/evergreen/arm64/gyp_configuration.py
index fc09a0d..e8b282a 100644
--- a/src/starboard/evergreen/arm64/gyp_configuration.py
+++ b/src/starboard/evergreen/arm64/gyp_configuration.py
@@ -15,7 +15,6 @@
from starboard.build import clang as clang_build
from starboard.evergreen.shared import gyp_configuration as shared_configuration
-from starboard.tools import build
from starboard.tools.toolchain import ar
from starboard.tools.toolchain import bash
from starboard.tools.toolchain import clang
@@ -29,33 +28,28 @@
"""Starboard Evergreen 64-bit ARM platform configuration."""
def __init__(self,
- platform_name='evergreen-arm64',
+ platform='evergreen-arm64',
asan_enabled_by_default=False,
- goma_supports_compiler=True,
sabi_json_path='starboard/sabi/default/sabi.json'):
# pylint: disable=useless-super-delegation
- super(EvergreenArm64Configuration,
- self).__init__(platform_name, asan_enabled_by_default,
- goma_supports_compiler, sabi_json_path)
- self._host_toolchain = None
+ super(EvergreenArm64Configuration, self).__init__(platform,
+ asan_enabled_by_default,
+ sabi_json_path)
def GetTargetToolchain(self, **kwargs):
return self.GetHostToolchain(**kwargs)
def GetHostToolchain(self, **kwargs):
- if not self._host_toolchain:
- if not hasattr(self, 'host_compiler_environment'):
- self.host_compiler_environment = build.GetHostCompilerEnvironment(
- clang_build.GetClangSpecification(), False)
- cc_path = self.host_compiler_environment['CC_host']
- cxx_path = self.host_compiler_environment['CXX_host']
+ if not hasattr(self, '_host_toolchain'):
+ env_variables = self.GetEnvironmentVariables()
+ cc_path = env_variables['CC_host']
+ cxx_path = env_variables['CXX_host']
- # Takes the provided value of CXX_HOST with a prepended 'gomacc' and an
+ # Takes the provided value of CXX_HOST with a prepended 'ccache' and an
# appended 'bin/clang++' and strips them off, leaving us with an absolute
# path to the root directory of our toolchain.
begin_path_index = cxx_path.find('/')
end_path_index = cxx_path.rfind('/', 0, cxx_path.rfind('/')) + 1
-
cxx_path_root = cxx_path[begin_path_index:end_path_index]
self._host_toolchain = [
diff --git a/src/starboard/evergreen/arm64/sbversion/12/gyp_configuration.py b/src/starboard/evergreen/arm64/sbversion/12/gyp_configuration.py
index f0b21ba..d2a4708 100644
--- a/src/starboard/evergreen/arm64/sbversion/12/gyp_configuration.py
+++ b/src/starboard/evergreen/arm64/sbversion/12/gyp_configuration.py
@@ -18,5 +18,5 @@
def CreatePlatformConfig():
return parent_configuration.EvergreenArm64Configuration(
- platform_name='evergreen-arm64-sbversion-12',
+ 'evergreen-arm64-sbversion-12',
sabi_json_path='starboard/sabi/arm64/sabi-v12.json')
diff --git a/src/starboard/evergreen/shared/gyp_configuration.py b/src/starboard/evergreen/shared/gyp_configuration.py
index 71c24c4..526b209 100644
--- a/src/starboard/evergreen/shared/gyp_configuration.py
+++ b/src/starboard/evergreen/shared/gyp_configuration.py
@@ -28,13 +28,12 @@
def __init__(self,
platform,
asan_enabled_by_default=True,
- goma_supports_compiler=True,
sabi_json_path='starboard/sabi/default/sabi.json'):
- self.goma_supports_compiler = goma_supports_compiler
- self.sabi_json_path = sabi_json_path
super(EvergreenConfiguration, self).__init__(platform,
asan_enabled_by_default)
+ self.sabi_json_path = sabi_json_path
+
def GetBuildFormat(self):
"""Returns the desired build format."""
# The comma means that ninja and qtcreator_ninja will be chained and use the
@@ -67,14 +66,14 @@
return generator_variables
def GetEnvironmentVariables(self):
- if not hasattr(self, 'host_compiler_environment'):
- self.host_compiler_environment = build.GetHostCompilerEnvironment(
- clang.GetClangSpecification(), self.goma_supports_compiler)
+ if not hasattr(self, '_host_compiler_environment'):
+ self._host_compiler_environment = build.GetHostCompilerEnvironment(
+ clang.GetClangSpecification(), self.build_accelerator)
- env_variables = self.host_compiler_environment
+ env_variables = self._host_compiler_environment
env_variables.update({
- 'CC': self.host_compiler_environment['CC_host'],
- 'CXX': self.host_compiler_environment['CXX_host'],
+ 'CC': self._host_compiler_environment['CC_host'],
+ 'CXX': self._host_compiler_environment['CXX_host'],
})
return env_variables
diff --git a/src/starboard/evergreen/x64/gyp_configuration.gypi b/src/starboard/evergreen/x64/gyp_configuration.gypi
index dcb689e..a9f3eaa 100644
--- a/src/starboard/evergreen/x64/gyp_configuration.gypi
+++ b/src/starboard/evergreen/x64/gyp_configuration.gypi
@@ -22,6 +22,8 @@
'compiler_flags': [
'-isystem<(cobalt_repo_root)/third_party/musl/arch/x86_64',
+ '-ffunction-sections',
+ '-fdata-sections',
],
},
diff --git a/src/starboard/evergreen/x64/gyp_configuration.py b/src/starboard/evergreen/x64/gyp_configuration.py
index 86174cd..dbb32d6 100644
--- a/src/starboard/evergreen/x64/gyp_configuration.py
+++ b/src/starboard/evergreen/x64/gyp_configuration.py
@@ -17,7 +17,6 @@
from starboard.build import clang as clang_build
from starboard.evergreen.shared import gyp_configuration as shared_configuration
-from starboard.tools import build
from starboard.tools import paths
from starboard.tools.toolchain import ar
from starboard.tools.toolchain import bash
@@ -32,34 +31,29 @@
"""Starboard Evergreen x64 platform configuration."""
def __init__(self,
- platform_name='evergreen-x64',
+ platform='evergreen-x64',
asan_enabled_by_default=False,
- goma_supports_compiler=True,
sabi_json_path='starboard/sabi/default/sabi.json'):
- # pylint: disable=useless-super-delegation
- super(EvergreenX64Configuration,
- self).__init__(platform_name, asan_enabled_by_default,
- goma_supports_compiler, sabi_json_path)
+ super(EvergreenX64Configuration, self).__init__(platform,
+ asan_enabled_by_default,
+ sabi_json_path)
+
self.AppendApplicationConfigurationPath(os.path.dirname(__file__))
- self._host_toolchain = None
def GetTargetToolchain(self, **kwargs):
return self.GetHostToolchain(**kwargs)
def GetHostToolchain(self, **kwargs):
- if not self._host_toolchain:
- if not hasattr(self, 'host_compiler_environment'):
- self.host_compiler_environment = build.GetHostCompilerEnvironment(
- clang_build.GetClangSpecification(), False)
- cc_path = self.host_compiler_environment['CC_host']
- cxx_path = self.host_compiler_environment['CXX_host']
+ if not hasattr(self, '_host_toolchain'):
+ env_variables = self.GetEnvironmentVariables()
+ cc_path = env_variables['CC_host']
+ cxx_path = env_variables['CXX_host']
- # Takes the provided value of CXX_HOST with a prepended 'gomacc' and an
+ # Takes the provided value of CXX_HOST with a prepended 'ccache' and an
# appended 'bin/clang++' and strips them off, leaving us with an absolute
# path to the root directory of our toolchain.
begin_path_index = cxx_path.find('/')
end_path_index = cxx_path.rfind('/', 0, cxx_path.rfind('/')) + 1
-
cxx_path_root = cxx_path[begin_path_index:end_path_index]
self._host_toolchain = [
diff --git a/src/starboard/evergreen/x64/sbversion/12/gyp_configuration.py b/src/starboard/evergreen/x64/sbversion/12/gyp_configuration.py
index a5ce04a..f03e574 100644
--- a/src/starboard/evergreen/x64/sbversion/12/gyp_configuration.py
+++ b/src/starboard/evergreen/x64/sbversion/12/gyp_configuration.py
@@ -18,5 +18,5 @@
def CreatePlatformConfig():
return parent_configuration.EvergreenX64Configuration(
- platform_name='evergreen-x64-sbversion-12',
+ 'evergreen-x64-sbversion-12',
sabi_json_path='starboard/sabi/x64/sysv/sabi-v12.json')
diff --git a/src/starboard/evergreen/x86/gyp_configuration.gypi b/src/starboard/evergreen/x86/gyp_configuration.gypi
index f8a868f..58ebaca 100644
--- a/src/starboard/evergreen/x86/gyp_configuration.gypi
+++ b/src/starboard/evergreen/x86/gyp_configuration.gypi
@@ -22,6 +22,8 @@
'compiler_flags': [
'-isystem<(cobalt_repo_root)/third_party/musl/arch/i386',
+ '-ffunction-sections',
+ '-fdata-sections',
],
},
diff --git a/src/starboard/evergreen/x86/gyp_configuration.py b/src/starboard/evergreen/x86/gyp_configuration.py
index 5ac4c8e..441c4e3 100644
--- a/src/starboard/evergreen/x86/gyp_configuration.py
+++ b/src/starboard/evergreen/x86/gyp_configuration.py
@@ -17,7 +17,6 @@
from starboard.build import clang as clang_build
from starboard.evergreen.shared import gyp_configuration as shared_configuration
-from starboard.tools import build
from starboard.tools import paths
from starboard.tools.toolchain import ar
from starboard.tools.toolchain import bash
@@ -32,33 +31,28 @@
"""Starboard Evergreen x86 platform configuration."""
def __init__(self,
- platform_name='evergreen-x86',
+ platform='evergreen-x86',
asan_enabled_by_default=False,
- goma_supports_compiler=True,
sabi_json_path='starboard/sabi/default/sabi.json'):
# pylint: disable=useless-super-delegation
- super(EvergreenX86Configuration,
- self).__init__(platform_name, asan_enabled_by_default,
- goma_supports_compiler, sabi_json_path)
- self._host_toolchain = None
+ super(EvergreenX86Configuration, self).__init__(platform,
+ asan_enabled_by_default,
+ sabi_json_path)
def GetTargetToolchain(self, **kwargs):
return self.GetHostToolchain(**kwargs)
def GetHostToolchain(self, **kwargs):
- if not self._host_toolchain:
- if not hasattr(self, 'host_compiler_environment'):
- self.host_compiler_environment = build.GetHostCompilerEnvironment(
- clang_build.GetClangSpecification(), False)
- cc_path = self.host_compiler_environment['CC_host']
- cxx_path = self.host_compiler_environment['CXX_host']
+ if not hasattr(self, '_host_toolchain'):
+ env_variables = self.GetEnvironmentVariables()
+ cc_path = env_variables['CC_host']
+ cxx_path = env_variables['CXX_host']
- # Takes the provided value of CXX_HOST with a prepended 'gomacc' and an
+ # Takes the provided value of CXX_HOST with a prepended 'ccache' and an
# appended 'bin/clang++' and strips them off, leaving us with an absolute
# path to the root directory of our toolchain.
begin_path_index = cxx_path.find('/')
end_path_index = cxx_path.rfind('/', 0, cxx_path.rfind('/')) + 1
-
cxx_path_root = cxx_path[begin_path_index:end_path_index]
self._host_toolchain = [
diff --git a/src/starboard/evergreen/x86/sbversion/12/gyp_configuration.py b/src/starboard/evergreen/x86/sbversion/12/gyp_configuration.py
index 0b040a4..4de44be 100644
--- a/src/starboard/evergreen/x86/sbversion/12/gyp_configuration.py
+++ b/src/starboard/evergreen/x86/sbversion/12/gyp_configuration.py
@@ -18,5 +18,5 @@
def CreatePlatformConfig():
return parent_configuration.EvergreenX86Configuration(
- platform_name='evergreen-x86-sbversion-12',
+ 'evergreen-x86-sbversion-12',
sabi_json_path='starboard/sabi/x86/sabi-v12.json')
diff --git a/src/starboard/linux/shared/compiler_flags.gypi b/src/starboard/linux/shared/compiler_flags.gypi
index 53b3229..af40c10 100644
--- a/src/starboard/linux/shared/compiler_flags.gypi
+++ b/src/starboard/linux/shared/compiler_flags.gypi
@@ -36,9 +36,15 @@
],
'compiler_flags_qa_size': [
'-Os',
+ # Compile symbols in separate sections
+ '-ffunction-sections',
+ '-fdata-sections',
],
'compiler_flags_qa_speed': [
'-O2',
+ # Compile symbols in separate sections
+ '-ffunction-sections',
+ '-fdata-sections',
],
'compiler_flags_gold': [
'-fno-rtti',
@@ -46,9 +52,15 @@
],
'compiler_flags_gold_size': [
'-Os',
+ # Compile symbols in separate sections
+ '-ffunction-sections',
+ '-fdata-sections',
],
'compiler_flags_gold_speed': [
'-O2',
+ # Compile symbols in separate sections
+ '-ffunction-sections',
+ '-fdata-sections',
],
'conditions': [
['clang==1', {
@@ -135,6 +147,8 @@
],
'ldflags': [
'-Wl,-rpath=$ORIGIN/lib',
+ # Cleanup unused sections
+ '-Wl,-gc-sections',
],
'target_conditions': [
['sb_pedantic_warnings==1', {
diff --git a/src/starboard/linux/shared/configuration.gni b/src/starboard/linux/shared/configuration.gni
index c4562c3..49d1b21 100644
--- a/src/starboard/linux/shared/configuration.gni
+++ b/src/starboard/linux/shared/configuration.gni
@@ -39,9 +39,3 @@
# Use ASAN by default when building with Clang.
use_asan_by_default = true
-
-declare_args() {
- # Set to true to enable distributed compilation using Goma. By default we
- # use Goma for stub and linux.
- use_goma = true
-}
diff --git a/src/starboard/linux/shared/gyp_configuration.py b/src/starboard/linux/shared/gyp_configuration.py
index a635fda..0cb799e 100644
--- a/src/starboard/linux/shared/gyp_configuration.py
+++ b/src/starboard/linux/shared/gyp_configuration.py
@@ -18,6 +18,7 @@
from starboard.build import clang
from starboard.build import platform_configuration
from starboard.tools import build
+from starboard.tools import paths
from starboard.tools.testing import test_filter
@@ -27,11 +28,10 @@
def __init__(self,
platform,
asan_enabled_by_default=True,
- goma_supports_compiler=True,
sabi_json_path='starboard/sabi/default/sabi.json'):
- self.goma_supports_compiler = goma_supports_compiler
- self.sabi_json_path = sabi_json_path
super(LinuxConfiguration, self).__init__(platform, asan_enabled_by_default)
+
+ self.sabi_json_path = sabi_json_path
self.AppendApplicationConfigurationPath(os.path.dirname(__file__))
def GetBuildFormat(self):
@@ -64,14 +64,14 @@
return generator_variables
def GetEnvironmentVariables(self):
- if not hasattr(self, 'host_compiler_environment'):
- self.host_compiler_environment = build.GetHostCompilerEnvironment(
- clang.GetClangSpecification(), self.goma_supports_compiler)
+ if not hasattr(self, '_host_compiler_environment'):
+ self._host_compiler_environment = build.GetHostCompilerEnvironment(
+ clang.GetClangSpecification(), self.build_accelerator)
- env_variables = self.host_compiler_environment
+ env_variables = self._host_compiler_environment
env_variables.update({
- 'CC': self.host_compiler_environment['CC_host'],
- 'CXX': self.host_compiler_environment['CXX_host'],
+ 'CC': self._host_compiler_environment['CC_host'],
+ 'CXX': self._host_compiler_environment['CXX_host'],
})
return env_variables
@@ -89,13 +89,25 @@
def GetTestFilters(self):
filters = super(LinuxConfiguration, self).GetTestFilters()
- for target, tests in self.__FILTERED_TESTS.iteritems():
+
+ has_cdm = os.path.isfile(
+ os.path.join(paths.REPOSITORY_ROOT, 'third_party', 'ce_cdm', 'cdm',
+ 'include', 'cdm.h'))
+
+ if has_cdm:
+ return filters
+
+ # Filter the drm related tests, as ce_cdm is not present.
+ for target, tests in self.__DRM_RELATED_TESTS.iteritems():
filters.extend(test_filter.TestFilter(target, test) for test in tests)
return filters
def GetPathToSabiJsonFile(self):
return self.sabi_json_path
- __FILTERED_TESTS = { # pylint: disable=invalid-name
- 'nplb': ['SbDrmTest.AnySupportedKeySystems',],
+ __DRM_RELATED_TESTS = { # pylint: disable=invalid-name
+ 'nplb': [
+ 'SbDrmTest.AnySupportedKeySystems',
+ 'SbMediaCanPlayMimeAndKeySystem.AnySupportedKeySystems',
+ ],
}
diff --git a/src/starboard/linux/x64x11/clang/3.6/compiler_flags.gypi b/src/starboard/linux/x64x11/clang/3.6/compiler_flags.gypi
index b5368e1..7ff50f5 100644
--- a/src/starboard/linux/x64x11/clang/3.6/compiler_flags.gypi
+++ b/src/starboard/linux/x64x11/clang/3.6/compiler_flags.gypi
@@ -50,8 +50,6 @@
'common_clang_flags': [
'-Werror',
'-fcolor-diagnostics',
- # Point to a gcc toolchain that works with this compiler.
- '--gcc-toolchain=<(GCC_TOOLCHAIN_FOLDER)',
# Default visibility to hidden, to enable dead stripping.
'-fvisibility=hidden',
# Warn for implicit type conversions that may change a value.
@@ -107,6 +105,16 @@
'-Wno-unused-parameter',
# Suppress warnings about unknown pragmas.
'-Wno-unknown-pragmas',
+ # Suppress warnings about equality checks within double parentheses.
+ '-Wno-parentheses-equality',
+ # Suppress warnings about unreachable code due to constexpr conditions
+ '-Wno-unreachable-code',
+ # Suppress warnings about values being written but not read before the next write.
+ '-Wno-unused-value',
+ # Suppress warnings related to unused compilation flags in clang.
+ '-Wno-unused-command-line-argument',
+ # Suppress warnings related to tautological comparisons.
+ '-Wno-tautological-compare',
],
}],
['cobalt_fastbuild==0', {
diff --git a/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py b/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py
index 0266fbc..8bb0020 100644
--- a/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py
@@ -18,7 +18,6 @@
import subprocess
from starboard.linux.shared import gyp_configuration as shared_configuration
-from starboard.tools import build
from starboard.tools.toolchain import ar
from starboard.tools.toolchain import bash
from starboard.tools.toolchain import clang
@@ -31,45 +30,37 @@
"""Starboard Linux X64 X11 Clang 3.6 platform configuration."""
def __init__(self,
- platform,
+ platform='linux-x64x11-clang-3-6',
asan_enabled_by_default=False,
sabi_json_path='starboard/sabi/default/sabi.json'):
- super(LinuxX64X11Clang36Configuration, self).__init__(
- platform,
- asan_enabled_by_default,
- goma_supports_compiler=False,
- sabi_json_path=sabi_json_path)
+ super(LinuxX64X11Clang36Configuration,
+ self).__init__(platform, asan_enabled_by_default, sabi_json_path)
- self.toolchain_top_dir = os.path.join(build.GetToolchainsDir(),
- 'x86_64-linux-gnu-clang-3.6')
- self.toolchain_dir = os.path.join(self.toolchain_top_dir, 'llvm',
- 'Release+Asserts')
+ self.toolchain_dir = '/usr/lib/llvm-3.6'
def SetupPlatformTools(self, build_number):
- script_path = os.path.dirname(os.path.realpath(__file__))
- # Run the script that ensures clang 3.6 is installed.
- subprocess.call(
- os.path.join(script_path, 'download_clang.sh'), cwd=script_path)
+ ret = subprocess.call('/usr/bin/clang-3.6 --version', shell=True)
+ if ret != 0:
+ raise Exception('clang-3.6 is not installed.')
def GetEnvironmentVariables(self):
+ toolchain_bin_dir = os.path.join(self.toolchain_dir, 'bin')
+
env_variables = super(LinuxX64X11Clang36Configuration,
self).GetEnvironmentVariables()
- toolchain_bin_dir = os.path.join(self.toolchain_dir, 'bin')
env_variables.update({
- 'CC': os.path.join(toolchain_bin_dir, 'clang'),
- 'CXX': os.path.join(toolchain_bin_dir, 'clang++'),
+ 'CC':
+ self.build_accelerator + ' ' +
+ os.path.join(toolchain_bin_dir, 'clang'),
+ 'CXX':
+ self.build_accelerator + ' ' +
+ os.path.join(toolchain_bin_dir, 'clang++'),
})
return env_variables
def GetVariables(self, config_name):
- # A significant amount of code in V8 fails to compile on clang 3.6 using
- # the debug config, due to an internal error in clang.
variables = super(LinuxX64X11Clang36Configuration,
self).GetVariables(config_name)
- variables.update({
- 'GCC_TOOLCHAIN_FOLDER':
- '\"%s\"' % os.path.join(self.toolchain_top_dir, 'libstdc++-7'),
- })
return variables
def GetTargetToolchain(self, **kwargs):
@@ -112,7 +103,6 @@
def CreatePlatformConfig():
try:
return LinuxX64X11Clang36Configuration(
- 'linux-x64x11-clang-3-6',
sabi_json_path='starboard/sabi/x64/sysv/sabi-v{sb_api_version}.json')
except RuntimeError as e:
logging.critical(e)
diff --git a/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.py b/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.py
index 2fbd354..df1a163 100644
--- a/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/gcc/6.3/gyp_configuration.py
@@ -30,14 +30,13 @@
"""Starboard Linux platform configuration."""
def __init__(self,
- platform,
+ platform='linux-x64x11-gcc-6-3',
asan_enabled_by_default=False,
sabi_json_path='starboard/sabi/default/sabi.json'):
super(LinuxX64X11Gcc63Configuration, self).__init__(
platform,
asan_enabled_by_default,
- goma_supports_compiler=False,
- sabi_json_path=sabi_json_path)
+ sabi_json_path)
self.toolchain_dir = os.path.join(build.GetToolchainsDir(),
'x86_64-linux-gnu-gcc-6.3.0', 'gcc')
@@ -62,11 +61,16 @@
def GetEnvironmentVariables(self):
toolchain_bin_dir = os.path.join(self.toolchain_dir, 'bin')
+
env_variables = {
- 'CC': os.path.join(toolchain_bin_dir, 'gcc'),
- 'CXX': os.path.join(toolchain_bin_dir, 'g++'),
- 'CC_HOST': os.path.join(toolchain_bin_dir, 'gcc'),
- 'CXX_HOST': os.path.join(toolchain_bin_dir, 'g++'),
+ 'CC': self.build_accelerator + ' ' + os.path.join(toolchain_bin_dir,
+ 'gcc'),
+ 'CXX': self.build_accelerator + ' ' + os.path.join(toolchain_bin_dir,
+ 'g++'),
+ 'CC_HOST': self.build_accelerator + ' ' + os.path.join(
+ toolchain_bin_dir, 'gcc'),
+ 'CXX_HOST': self.build_accelerator + ' ' + os.path.join(
+ toolchain_bin_dir, 'g++'),
}
return env_variables
@@ -109,5 +113,4 @@
def CreatePlatformConfig():
return LinuxX64X11Gcc63Configuration(
- 'linux-x64x11-gcc-6-3',
sabi_json_path='starboard/sabi/x64/sysv/sabi-v{sb_api_version}.json')
diff --git a/src/starboard/linux/x64x11/gyp_configuration.py b/src/starboard/linux/x64x11/gyp_configuration.py
index f62c9ea..5f8069a 100644
--- a/src/starboard/linux/x64x11/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/gyp_configuration.py
@@ -13,8 +13,6 @@
# limitations under the License.
"""Starboard Linux X64 X11 platform configuration."""
-import os.path
-
from starboard.linux.shared import gyp_configuration as shared_configuration
from starboard.tools.toolchain import ar
from starboard.tools.toolchain import bash
@@ -22,22 +20,17 @@
from starboard.tools.toolchain import clangxx
from starboard.tools.toolchain import cp
from starboard.tools.toolchain import touch
-from starboard.tools import paths
class LinuxX64X11Configuration(shared_configuration.LinuxConfiguration):
"""Starboard Linux X64 X11 platform configuration."""
def __init__(self,
- platform_name='linux-x64x11',
+ platform='linux-x64x11',
asan_enabled_by_default=True,
- goma_supports_compiler=True,
sabi_json_path='starboard/sabi/default/sabi.json'):
- super(LinuxX64X11Configuration, self).__init__(
- platform_name,
- asan_enabled_by_default,
- goma_supports_compiler,
- sabi_json_path=sabi_json_path)
+ super(LinuxX64X11Configuration,
+ self).__init__(platform, asan_enabled_by_default, sabi_json_path)
def GetTargetToolchain(self, **kwargs):
return self.GetHostToolchain(**kwargs)
@@ -60,25 +53,6 @@
bash.Shell(),
]
- def GetTestFilters(self):
- filters = super(LinuxX64X11Configuration, self).GetTestFilters()
- # Remove the exclusion filter on SbDrmTest.AnySupportedKeySystems.
- # Generally, children of linux/shared do not support widevine, but children
- # of linux/x64x11 do, if the content decryption module is present.
-
- has_cdm = os.path.isfile(
- os.path.join(paths.REPOSITORY_ROOT, 'third_party', 'cdm', 'cdm',
- 'include', 'content_decryption_module.h'))
-
- if not has_cdm:
- return filters
-
- for test_filter in filters:
- if (test_filter.target_name == 'nplb' and
- test_filter.test_name == 'SbDrmTest.AnySupportedKeySystems'):
- filters.remove(test_filter)
- return filters
-
def CreatePlatformConfig():
return LinuxX64X11Configuration(
diff --git a/src/starboard/linux/x64x11/sbversion/12/gyp_configuration.py b/src/starboard/linux/x64x11/sbversion/12/gyp_configuration.py
index 6dd53b0..a85e677 100644
--- a/src/starboard/linux/x64x11/sbversion/12/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/sbversion/12/gyp_configuration.py
@@ -18,5 +18,5 @@
def CreatePlatformConfig():
return parent_configuration.LinuxX64X11Configuration(
- platform_name='linux-x64x11-sbversion-12',
+ 'linux-x64x11-sbversion-12',
sabi_json_path='starboard/sabi/x64/sysv/sabi-v12.json')
diff --git a/src/starboard/loader_app/loader_app.cc b/src/starboard/loader_app/loader_app.cc
index c74437f..1c661af 100644
--- a/src/starboard/loader_app/loader_app.cc
+++ b/src/starboard/loader_app/loader_app.cc
@@ -25,6 +25,7 @@
#include "starboard/loader_app/loader_app_switches.h"
#include "starboard/loader_app/slot_management.h"
#include "starboard/loader_app/system_get_extension_shim.h"
+#include "starboard/memory.h"
#include "starboard/mutex.h"
#include "starboard/shared/starboard/command_line.h"
#include "starboard/string.h"
@@ -109,6 +110,20 @@
SB_LOG(INFO) << "Loaded Cobalt library information into Crashpad.";
}
+ auto get_user_agent_func = reinterpret_cast<const char* (*)()>(
+ g_elf_loader.LookupSymbol("GetCobaltUserAgentString"));
+ if (!get_user_agent_func) {
+ SB_LOG(ERROR) << "Failed to get user agent string";
+ } else {
+ EvergreenAnnotations cobalt_version_info;
+ SbMemorySet(&cobalt_version_info, sizeof(EvergreenAnnotations), 0);
+ SbStringCopy(cobalt_version_info.user_agent_string, get_user_agent_func(),
+ EVERGREEN_USER_AGENT_MAX_SIZE);
+ third_party::crashpad::wrapper::AddAnnotationsToCrashpad(
+ cobalt_version_info);
+ SB_DLOG(INFO) << "Added user agent string to Crashpad.";
+ }
+
g_sb_event_func = reinterpret_cast<void (*)(const SbEvent*)>(
g_elf_loader.LookupSymbol("SbEventHandle"));
diff --git a/src/starboard/loader_app/slot_management.cc b/src/starboard/loader_app/slot_management.cc
index 9e1eadd..5dc1212 100644
--- a/src/starboard/loader_app/slot_management.cc
+++ b/src/starboard/loader_app/slot_management.cc
@@ -23,6 +23,7 @@
#include "starboard/loader_app/app_key_files.h"
#include "starboard/loader_app/drain_file.h"
#include "starboard/loader_app/installation_manager.h"
+#include "starboard/memory.h"
#include "starboard/string.h"
#include "third_party/crashpad/wrapper/wrapper.h"
@@ -243,6 +244,20 @@
SB_LOG(INFO) << "Loaded Cobalt library information into Crashpad.";
}
+ auto get_user_agent_func = reinterpret_cast<const char* (*)()>(
+ library_loader->Resolve("GetCobaltUserAgentString"));
+ if (!get_user_agent_func) {
+ SB_LOG(ERROR) << "Failed to get user agent string";
+ } else {
+ EvergreenAnnotations cobalt_version_info;
+ SbMemorySet(&cobalt_version_info, sizeof(EvergreenAnnotations), 0);
+ SbStringCopy(cobalt_version_info.user_agent_string, get_user_agent_func(),
+ EVERGREEN_USER_AGENT_MAX_SIZE);
+ third_party::crashpad::wrapper::AddAnnotationsToCrashpad(
+ cobalt_version_info);
+ SB_DLOG(INFO) << "Added user agent string to Crashpad.";
+ }
+
SB_DLOG(INFO) << "Successfully loaded Cobalt!\n";
void* p = library_loader->Resolve("SbEventHandle");
if (p != NULL) {
diff --git a/src/starboard/loader_app/slot_management_test.cc b/src/starboard/loader_app/slot_management_test.cc
index 0eeb83c..5ff9e20 100644
--- a/src/starboard/loader_app/slot_management_test.cc
+++ b/src/starboard/loader_app/slot_management_test.cc
@@ -37,6 +37,10 @@
void SbEventFake(const SbEvent*) {}
+const char* GetCobaltUserAgentStringFake() {
+ return "";
+}
+
class MockLibraryLoader : public LibraryLoader {
public:
MOCK_METHOD2(Load,
@@ -132,6 +136,10 @@
Load(testing::EndsWith(lib), testing::EndsWith(content)))
.Times(1)
.WillOnce(testing::Return(true));
+ EXPECT_CALL(library_loader, Resolve("GetCobaltUserAgentString"))
+ .Times(1)
+ .WillOnce(testing::Return(
+ reinterpret_cast<void*>(&GetCobaltUserAgentStringFake)));
EXPECT_CALL(library_loader, Resolve("SbEventHandle"))
.Times(1)
.WillOnce(testing::Return(reinterpret_cast<void*>(&SbEventFake)));
@@ -261,6 +269,10 @@
testing::EndsWith("/foo")))
.Times(1)
.WillOnce(testing::Return(true));
+ EXPECT_CALL(library_loader, Resolve("GetCobaltUserAgentString"))
+ .Times(1)
+ .WillOnce(testing::Return(
+ reinterpret_cast<void*>(&GetCobaltUserAgentStringFake)));
EXPECT_CALL(library_loader, Resolve("SbEventHandle"))
.Times(1)
.WillOnce(testing::Return(reinterpret_cast<void*>(&SbEventFake)));
diff --git a/src/starboard/media.h b/src/starboard/media.h
index bdafbe4..05aaf0d 100644
--- a/src/starboard/media.h
+++ b/src/starboard/media.h
@@ -544,11 +544,44 @@
// or |video/mp4; codecs="avc1.42001E"|. It may include arbitrary parameters
// like "codecs", "channels", etc. Note that the "codecs" parameter may
// contain more than one codec, delimited by comma.
-// |key_system|: A lowercase value in fhe form of "com.example.somesystem"
+// |key_system|: A lowercase value in the form of "com.example.somesystem"
// as suggested by https://w3c.github.io/encrypted-media/#key-system
// that can be matched exactly with known DRM key systems of the platform.
// When |key_system| is an empty string, the return value is an indication for
// non-encrypted media.
+//
+// An implementation may choose to support |key_system| with extra attributes,
+// separated by ';', like
+// |com.example.somesystem; attribute_name1="value1"; attribute_name2=value1|.
+// If |key_system| with attributes is not supported by an implementation, it
+// should treat |key_system| as if it contains only the key system, and reject
+// any input containing extra attributes, i.e. it can keep using its existing
+// implementation.
+// When an implementation supports |key_system| with attributes, it has to
+// support all attributes defined by the Starboard version the implementation
+// uses.
+// An implementation should ignore any unknown attributes, and make a decision
+// solely based on the key system and the known attributes. For example, if
+// an implementation supports "com.widevine.alpha", it should also return
+// `kSbMediaSupportTypeProbably` when |key_system| is
+// |com.widevine.alpha; invalid_attribute="invalid_value"|.
+// Currently the only attribute has to be supported is |encryptionscheme|. It
+// reflects the value passed to `encryptionScheme` of
+// MediaKeySystemMediaCapability, as defined in
+// https://wicg.github.io/encrypted-media-encryption-scheme/, which can take
+// value "cenc", "cbcs", or "cbcs-1-9".
+// Empty string is not a valid value for |encryptionscheme| and the
+// implementation should return `kSbMediaSupportTypeNotSupported` when
+// |encryptionscheme| is set to "".
+// The implementation should return `kSbMediaSupportTypeNotSupported` for
+// unknown values of known attributes. For example, if an implementation
+// supports "encryptionscheme" with value "cenc", "cbcs", or "cbcs-1-9", then
+// it should return `kSbMediaSupportTypeProbably` when |key_system| is
+// |com.widevine.alpha; encryptionscheme="cenc"|, and return
+// `kSbMediaSupportTypeNotSupported` when |key_system| is
+// |com.widevine.alpha; encryptionscheme="invalid"|.
+// If an implementation supports key system with attributes on one key system,
+// it has to support key system with attributes on all key systems supported.
SB_EXPORT SbMediaSupportType
SbMediaCanPlayMimeAndKeySystem(const char* mime, const char* key_system);
diff --git a/src/starboard/nplb/drm_helpers.h b/src/starboard/nplb/drm_helpers.h
index c24b696..e6b0972 100644
--- a/src/starboard/nplb/drm_helpers.h
+++ b/src/starboard/nplb/drm_helpers.h
@@ -68,6 +68,10 @@
"com.youtube.fairplay",
};
+static const char* kEncryptionSchemes[] = {
+ "cenc", "cbcs", "cbcs-1-9",
+};
+
} // namespace nplb
} // namespace starboard
diff --git a/src/starboard/nplb/media_can_play_mime_and_key_system_test.cc b/src/starboard/nplb/media_can_play_mime_and_key_system_test.cc
index 2e38c86..3003a56 100644
--- a/src/starboard/nplb/media_can_play_mime_and_key_system_test.cc
+++ b/src/starboard/nplb/media_can_play_mime_and_key_system_test.cc
@@ -14,14 +14,38 @@
#include "starboard/media.h"
+#include "starboard/common/string.h"
+#include "starboard/nplb/drm_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace starboard {
-namespace shared {
-namespace starboard {
-namespace media {
+namespace nplb {
namespace {
+bool IsKeySystemWithAttributesSupported() {
+ for (auto key_system : kKeySystems) {
+ if (!SbMediaCanPlayMimeAndKeySystem("video/mp4; codecs=\"avc1.4d4015\"",
+ key_system)) {
+ continue;
+ }
+
+ // The key system is supported, let's check if the implementation supports
+ // attributes. By definition, when an implementation supports key system
+ // with attributes, it should make the decision without any unknown
+ // attributes. So the following |key_system_with_invalid_attribute| should
+ // be supported on such implementation.
+ std::string key_system_with_invalid_attribute = key_system;
+ key_system_with_invalid_attribute += "; invalid_attribute=\"some_value\"";
+ if (SbMediaCanPlayMimeAndKeySystem(
+ "video/mp4; codecs=\"avc1.4d4015\"",
+ key_system_with_invalid_attribute.c_str())) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
TEST(SbMediaCanPlayMimeAndKeySystem, SunnyDay) {
// Vp9
SbMediaCanPlayMimeAndKeySystem(
@@ -89,14 +113,121 @@
"audio/mp4; codecs=\"mp4a.40.2\"; channels=99", "");
ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
- // Invalid keysystem
- result = SbMediaCanPlayMimeAndKeySystem(
- "video/mp4; codecs=\"avc1.4d4015\"; width=1920; height=1080;", "abc");
+ // Invalid key system
+ result = SbMediaCanPlayMimeAndKeySystem("video/mp4; codecs=\"avc1.4d4015\"",
+ "abc");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+ result = SbMediaCanPlayMimeAndKeySystem("video/mp4; codecs=\"avc1.4d4015\"",
+ "widevine");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+ result = SbMediaCanPlayMimeAndKeySystem("video/mp4; codecs=\"avc1.4d4015\"",
+ "com.widevine.alpha.invalid");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+ result = SbMediaCanPlayMimeAndKeySystem("video/mp4; codecs=\"avc1.4d4015\"",
+ "playready");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+ result = SbMediaCanPlayMimeAndKeySystem("video/mp4; codecs=\"avc1.4d4015\"",
+ "com.youtube.playready.invalid");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+ result = SbMediaCanPlayMimeAndKeySystem("video/mp4; codecs=\"avc1.4d4015\"",
+ "fairplay");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+ result = SbMediaCanPlayMimeAndKeySystem("video/mp4; codecs=\"avc1.4d4015\"",
+ "com.youtube.fairplay.invalid");
ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
}
+TEST(SbMediaCanPlayMimeAndKeySystem, MinimumSupport) {
+ // H.264 Main Profile Level 4.2
+ SbMediaSupportType result = SbMediaCanPlayMimeAndKeySystem(
+ "video/mp4; codecs=\"avc1.4d402a\"; width=1920; height=1080; "
+ "framerate=30;",
+ "");
+ ASSERT_EQ(result, kSbMediaSupportTypeProbably);
+
+ result = SbMediaCanPlayMimeAndKeySystem(
+ "video/mp4; codecs=\"avc1.4d402a\"; width=1920; height=1080; "
+ "framerate=60;",
+ "");
+ ASSERT_EQ(result, kSbMediaSupportTypeProbably);
+
+ // H.264 Main Profile Level 2.1
+ result = SbMediaCanPlayMimeAndKeySystem(
+ "video/mp4; codecs=\"avc1.4d4015\"; width=432; height=240; "
+ "framerate=15;",
+ "");
+ ASSERT_EQ(result, kSbMediaSupportTypeProbably);
+
+ // AAC-LC
+ result = SbMediaCanPlayMimeAndKeySystem(
+ "audio/mp4; codecs=\"mp4a.40.2\"; channels=2; bitrate=256;", "");
+ ASSERT_EQ(result, kSbMediaSupportTypeProbably);
+
+ // HE-AAC
+ result = SbMediaCanPlayMimeAndKeySystem(
+ "audio/mp4; codecs=\"mp4a.40.5\"; channels=2; bitrate=48;", "");
+ ASSERT_EQ(result, kSbMediaSupportTypeProbably);
+}
+
+TEST(SbMediaCanPlayMimeAndKeySystem, AnySupportedKeySystems) {
+ bool any_supported_key_systems = false;
+ for (auto key_system : kKeySystems) {
+ if (SbMediaCanPlayMimeAndKeySystem("video/mp4; codecs=\"avc1.4d4015\"",
+ key_system)) {
+ any_supported_key_systems = true;
+ break;
+ }
+ }
+ ASSERT_TRUE(any_supported_key_systems);
+}
+
+TEST(SbMediaCanPlayMimeAndKeySystem, KeySystemWithAttributes) {
+ if (!IsKeySystemWithAttributesSupported()) {
+ SB_LOG(INFO) << "KeySystemWithAttributes test skipped because key system"
+ << " with attribute is not supported.";
+ return;
+ }
+
+ for (auto key_system : kKeySystems) {
+ if (!SbMediaCanPlayMimeAndKeySystem("video/mp4; codecs=\"avc1.4d4015\"",
+ key_system)) {
+ continue;
+ }
+
+ EXPECT_TRUE(SbMediaCanPlayMimeAndKeySystem(
+ "video/mp4; codecs=\"avc1.4d4015\"",
+ FormatString("%s; %s=\"%s\"", key_system, "invalid_attribute",
+ "some_value")
+ .c_str()));
+
+ // "" is not a valid value for "encryptionscheme".
+ EXPECT_FALSE(SbMediaCanPlayMimeAndKeySystem(
+ "video/mp4; codecs=\"avc1.4d4015\"",
+ FormatString("%s; %s=\"%s\"", key_system, "encryptionscheme", "")
+ .c_str()));
+
+ bool has_supported_encryption_scheme = false;
+ for (auto encryption_scheme : kEncryptionSchemes) {
+ if (!SbMediaCanPlayMimeAndKeySystem(
+ "video/mp4; codecs=\"avc1.4d4015\"",
+ FormatString("%s; %s=\"%s\"", key_system, "encryptionscheme",
+ encryption_scheme)
+ .c_str())) {
+ continue;
+ }
+ has_supported_encryption_scheme = true;
+ EXPECT_TRUE(SbMediaCanPlayMimeAndKeySystem(
+ "video/mp4; codecs=\"avc1.4d4015\"",
+ FormatString("%s; %s=\"%s\"; %s=\"%s\"", key_system,
+ "encryptionscheme", encryption_scheme,
+ "invalid_attribute", "some_value")
+ .c_str()));
+ }
+
+ ASSERT_TRUE(has_supported_encryption_scheme);
+ }
+}
+
} // namespace
-} // namespace media
-} // namespace starboard
-} // namespace shared
+} // namespace nplb
} // namespace starboard
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp
index 8407b1de..24563cf 100644
--- a/src/starboard/nplb/nplb.gyp
+++ b/src/starboard/nplb/nplb.gyp
@@ -191,6 +191,7 @@
'player_output_mode_supported_test.cc',
'player_test_util.cc',
'player_test_util.h',
+ 'player_write_sample_test.cc',
'random_helpers.cc',
'recursive_mutex_test.cc',
'rwlock_test.cc',
diff --git a/src/starboard/nplb/player_test_util.cc b/src/starboard/nplb/player_test_util.cc
index 88f8233..151cbdf 100644
--- a/src/starboard/nplb/player_test_util.cc
+++ b/src/starboard/nplb/player_test_util.cc
@@ -14,12 +14,92 @@
#include "starboard/nplb/player_test_util.h"
+#include <functional>
+
+#include "starboard/audio_sink.h"
+#include "starboard/common/string.h"
#include "starboard/directory.h"
#include "starboard/nplb/player_creation_param_helpers.h"
+#include "starboard/shared/starboard/player/video_dmp_reader.h"
+#include "starboard/testing/fake_graphics_context_provider.h"
namespace starboard {
namespace nplb {
+namespace {
+
+using shared::starboard::player::video_dmp::VideoDmpReader;
+using std::placeholders::_1;
+using std::placeholders::_2;
+using std::placeholders::_3;
+using std::placeholders::_4;
+using testing::FakeGraphicsContextProvider;
+
+void ErrorFunc(SbPlayer player,
+ void* context,
+ SbPlayerError error,
+ const char* message) {
+ atomic_bool* error_occurred = static_cast<atomic_bool*>(context);
+ error_occurred->exchange(true);
+}
+
+} // namespace
+
+std::vector<SbPlayerTestConfig> GetSupportedSbPlayerTestConfigs() {
+ const char* kAudioTestFiles[] = {"beneath_the_canopy_aac_stereo.dmp",
+ "beneath_the_canopy_aac_5_1.dmp",
+ "beneath_the_canopy_aac_mono.dmp",
+ "beneath_the_canopy_opus_5_1.dmp",
+ "beneath_the_canopy_opus_stereo.dmp",
+ "beneath_the_canopy_opus_mono.dmp",
+ "sintel_329_ec3.dmp",
+ "sintel_381_ac3.dmp",
+ "heaac.dmp"};
+
+ const char* kVideoTestFiles[] = {"beneath_the_canopy_137_avc.dmp",
+ "beneath_the_canopy_248_vp9.dmp",
+ "sintel_399_av1.dmp"};
+
+ const SbPlayerOutputMode kOutputModes[] = {kSbPlayerOutputModeDecodeToTexture,
+ kSbPlayerOutputModePunchOut};
+
+ std::vector<SbPlayerTestConfig> test_configs;
+
+ const char* kEmptyName = NULL;
+
+ for (auto audio_filename : kAudioTestFiles) {
+ VideoDmpReader dmp_reader(ResolveTestFileName(audio_filename).c_str());
+ SB_DCHECK(dmp_reader.number_of_audio_buffers() > 0);
+
+ const auto* audio_sample_info = &dmp_reader.audio_sample_info();
+ if (IsMediaConfigSupported(kSbMediaVideoCodecNone, dmp_reader.audio_codec(),
+ kSbDrmSystemInvalid, audio_sample_info,
+ "", /* max_video_capabilities */
+ kSbPlayerOutputModePunchOut)) {
+ test_configs.push_back(std::make_tuple(audio_filename, kEmptyName,
+ kSbPlayerOutputModePunchOut));
+ }
+ }
+
+ for (auto video_filename : kVideoTestFiles) {
+ VideoDmpReader dmp_reader(ResolveTestFileName(video_filename).c_str());
+ SB_DCHECK(dmp_reader.number_of_video_buffers() > 0);
+
+ for (auto output_mode : kOutputModes) {
+ if (IsMediaConfigSupported(dmp_reader.video_codec(),
+ kSbMediaAudioCodecNone, kSbDrmSystemInvalid,
+ NULL, /* audio_sample_info */
+ "", /* max_video_capabilities */
+ output_mode)) {
+ test_configs.push_back(
+ std::make_tuple(kEmptyName, video_filename, output_mode));
+ }
+ }
+ }
+
+ return test_configs;
+}
+
std::string ResolveTestFileName(const char* filename) {
std::vector<char> content_path(kSbFileMaxPath);
SB_CHECK(SbSystemGetPath(kSbSystemPathContentDirectory, content_path.data(),
@@ -45,10 +125,10 @@
SbPlayerDecoderState state,
int ticket) {}
-void DummyStatusFunc(SbPlayer player,
- void* context,
- SbPlayerState state,
- int ticket) {}
+void DummyPlayerStatusFunc(SbPlayer player,
+ void* context,
+ SbPlayerState state,
+ int ticket) {}
void DummyErrorFunc(SbPlayer player,
void* context,
@@ -116,5 +196,30 @@
#endif // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
}
+bool IsMediaConfigSupported(SbMediaVideoCodec video_codec,
+ SbMediaAudioCodec audio_codec,
+ SbDrmSystem drm_system,
+ const SbMediaAudioSampleInfo* audio_sample_info,
+ const char* max_video_capabilities,
+ SbPlayerOutputMode output_mode) {
+ if (audio_codec != kSbMediaAudioCodecNone &&
+ audio_sample_info->number_of_channels > SbAudioSinkGetMaxChannels()) {
+ return false;
+ }
+
+ atomic_bool error_occurred;
+ FakeGraphicsContextProvider fake_graphics_context_provider;
+ SbPlayer player = CallSbPlayerCreate(
+ fake_graphics_context_provider.window(), video_codec, audio_codec,
+ drm_system, audio_sample_info, max_video_capabilities,
+ DummyDeallocateSampleFunc, DummyDecoderStatusFunc, DummyPlayerStatusFunc,
+ ErrorFunc, &error_occurred, output_mode,
+ fake_graphics_context_provider.decoder_target_provider());
+ bool is_valid_player = SbPlayerIsValid(player);
+ SbPlayerDestroy(player);
+
+ return is_valid_player && !error_occurred.load();
+}
+
} // namespace nplb
} // namespace starboard
diff --git a/src/starboard/nplb/player_test_util.h b/src/starboard/nplb/player_test_util.h
index 335e414..ece5faf 100644
--- a/src/starboard/nplb/player_test_util.h
+++ b/src/starboard/nplb/player_test_util.h
@@ -16,6 +16,7 @@
#define STARBOARD_NPLB_PLAYER_TEST_UTIL_H_
#include <string>
+#include <tuple>
#include <vector>
#include "starboard/configuration_constants.h"
@@ -24,6 +25,13 @@
namespace starboard {
namespace nplb {
+typedef std::tuple<const char* /* audio_filename */,
+ const char* /* video_filename */,
+ SbPlayerOutputMode /* output_mode */>
+ SbPlayerTestConfig;
+
+std::vector<SbPlayerTestConfig> GetSupportedSbPlayerTestConfigs();
+
std::string ResolveTestFileName(const char* filename);
void DummyDeallocateSampleFunc(SbPlayer player,
@@ -64,6 +72,13 @@
bool IsOutputModeSupported(SbPlayerOutputMode output_mode,
SbMediaVideoCodec codec);
+bool IsMediaConfigSupported(SbMediaVideoCodec video_codec,
+ SbMediaAudioCodec audio_codec,
+ SbDrmSystem drm_system,
+ const SbMediaAudioSampleInfo* audio_sample_info,
+ const char* max_video_capabilities,
+ SbPlayerOutputMode output_mode);
+
} // namespace nplb
} // namespace starboard
diff --git a/src/starboard/nplb/player_write_sample_test.cc b/src/starboard/nplb/player_write_sample_test.cc
new file mode 100644
index 0000000..13977ee
--- /dev/null
+++ b/src/starboard/nplb/player_write_sample_test.cc
@@ -0,0 +1,520 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <algorithm>
+#include <deque>
+#include <functional>
+
+#include "starboard/atomic.h"
+#include "starboard/common/optional.h"
+#include "starboard/common/queue.h"
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/common/string.h"
+#include "starboard/nplb/player_test_util.h"
+#include "starboard/shared/starboard/player/video_dmp_reader.h"
+#include "starboard/string.h"
+#include "starboard/testing/fake_graphics_context_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace nplb {
+namespace {
+
+using shared::starboard::player::video_dmp::VideoDmpReader;
+using testing::FakeGraphicsContextProvider;
+using ::testing::ValuesIn;
+
+const SbTimeMonotonic kDefaultWaitForDecoderStateNeedsDataTimeout =
+ 5 * kSbTimeSecond;
+const SbTimeMonotonic kDefaultWaitForPlayerStateTimeout = 5 * kSbTimeSecond;
+const SbTimeMonotonic kDefaultWaitForCallbackEventTimeout =
+ 15 * kSbTimeMillisecond;
+
+class SbPlayerWriteSampleTest
+ : public ::testing::TestWithParam<SbPlayerTestConfig> {
+ public:
+ SbPlayerWriteSampleTest();
+
+ void SetUp() override;
+ void TearDown() override;
+
+ protected:
+ struct CallbackEvent {
+ CallbackEvent() {}
+
+ CallbackEvent(SbPlayer player, SbPlayerState state, int ticket)
+ : player(player), player_state(state), ticket(ticket) {}
+
+ CallbackEvent(SbPlayer player, SbPlayerDecoderState state, int ticket)
+ : player(player), decoder_state(state), ticket(ticket) {}
+
+ bool HasStateUpdate() const {
+ return player_state.has_engaged() || decoder_state.has_engaged();
+ }
+
+ SbPlayer player = kSbPlayerInvalid;
+ optional<SbPlayerState> player_state;
+ optional<SbPlayerDecoderState> decoder_state;
+ int ticket = SB_PLAYER_INITIAL_TICKET;
+ };
+
+ static void DecoderStatusCallback(SbPlayer player,
+ void* context,
+ SbMediaType type,
+ SbPlayerDecoderState state,
+ int ticket);
+
+ static void PlayerStatusCallback(SbPlayer player,
+ void* context,
+ SbPlayerState state,
+ int ticket);
+
+ static void ErrorCallback(SbPlayer player,
+ void* context,
+ SbPlayerError error,
+ const char* message);
+
+ void InitializePlayer();
+
+ void PrepareForSeek();
+
+ void Seek(const SbTime time);
+
+ // When the |output_mode| is decoding to texture, then this method is used to
+ // advance the decoded frames.
+ void GetDecodeTargetWhenSupported();
+
+ // Callback methods from the underlying player.
+ void OnDecoderState(SbPlayer player,
+ SbMediaType media_type,
+ SbPlayerDecoderState state,
+ int ticket);
+ void OnPlayerState(SbPlayer player, SbPlayerState state, int ticket);
+ void OnError(SbPlayer player, SbPlayerError error, const char* message);
+
+ // Waits for |kSbPlayerDecoderStateNeedsData| to be sent.
+ void WaitForDecoderStateNeedsData(
+ const SbTime timeout = kDefaultWaitForDecoderStateNeedsDataTimeout);
+
+ // Waits for desired player state update to be sent.
+ void WaitForPlayerState(
+ const SbPlayerState desired_state,
+ const SbTime timeout = kDefaultWaitForPlayerStateTimeout);
+
+ // Player and Decoder methods for driving input and output.
+ void WriteSingleInput(size_t index);
+ void WriteEndOfStream();
+ void WriteMultipleInputs(size_t start_index, size_t num_inputs_to_write);
+ void DrainOutputs();
+
+ int GetNumBuffers() const;
+
+ SbMediaType GetTestMediaType() const { return test_media_type_; }
+
+ // Determine if the the current event is valid based on previously received
+ // player state updates, or other inputs to the player.
+ void AssertPlayerStateIsValid(SbPlayerState state) const;
+
+ bool HasReceivedPlayerState(SbPlayerState state) const {
+ return player_state_set_.find(state) != player_state_set_.end();
+ }
+
+ // Checks if there are pending callback events and, if so, logs the received
+ // state update in the appropriate tracking container:
+ // * |decoder_state_queue_| for SbPlayerDecoderState updates.
+ // * |player_state_set_| for SbPlayerState updates.
+ // Executes a blocking wait for any new CallbackEvents to be enqueued.
+ void TryProcessCallbackEvents(SbTime timeout);
+
+ // Queue of events from the underlying player.
+ Queue<CallbackEvent> callback_event_queue_;
+
+ // Ordered queue of pending decoder state updates.
+ std::deque<SbPlayerDecoderState> decoder_state_queue_;
+
+ // Set of received player state updates from the underlying player. This is
+ // used to check that the state updates occur in a valid order during normal
+ // playback.
+ std::set<SbPlayerState> player_state_set_;
+
+ // Test instance specific configuration.
+ std::string dmp_filename_;
+ SbMediaType test_media_type_;
+ SbPlayerOutputMode output_mode_;
+ scoped_ptr<VideoDmpReader> dmp_reader_;
+
+ FakeGraphicsContextProvider fake_graphics_context_provider_;
+ SbPlayer player_ = kSbPlayerInvalid;
+
+ bool destroy_player_called_ = false;
+ bool end_of_stream_written_ = false;
+ atomic_bool error_occurred_;
+ int ticket_ = SB_PLAYER_INITIAL_TICKET;
+};
+
+SbPlayerWriteSampleTest::SbPlayerWriteSampleTest() {
+ const char* audio_filename = std::get<0>(GetParam());
+ const char* video_filename = std::get<1>(GetParam());
+ output_mode_ = std::get<2>(GetParam());
+
+ SB_DCHECK(output_mode_ != kSbPlayerOutputModeInvalid);
+
+ if (audio_filename != NULL) {
+ SB_DCHECK(video_filename == NULL);
+
+ dmp_filename_ = audio_filename;
+ test_media_type_ = kSbMediaTypeAudio;
+ } else {
+ SB_DCHECK(video_filename != NULL);
+
+ dmp_filename_ = video_filename;
+ test_media_type_ = kSbMediaTypeVideo;
+ }
+ dmp_reader_.reset(
+ new VideoDmpReader(ResolveTestFileName(dmp_filename_.c_str()).c_str()));
+
+ SB_LOG(INFO) << FormatString(
+ "Initialize SbPlayerWriteSampleTest with dmp file '%s' and with output "
+ "mode '%s'.",
+ dmp_filename_.c_str(),
+ output_mode_ == kSbPlayerOutputModeDecodeToTexture ? "Decode To Texture"
+ : "Punchout");
+}
+
+void SbPlayerWriteSampleTest::SetUp() {
+ SbMediaVideoCodec video_codec = dmp_reader_->video_codec();
+ SbMediaAudioCodec audio_codec = dmp_reader_->audio_codec();
+ const SbMediaAudioSampleInfo* audio_sample_info = NULL;
+
+ if (test_media_type_ == kSbMediaTypeAudio) {
+ SB_DCHECK(audio_codec != kSbMediaAudioCodecNone);
+
+ audio_sample_info = &dmp_reader_->audio_sample_info();
+ video_codec = kSbMediaVideoCodecNone;
+ } else {
+ SB_DCHECK(video_codec != kSbMediaVideoCodecNone);
+
+ audio_codec = kSbMediaAudioCodecNone;
+ }
+
+ player_ = CallSbPlayerCreate(
+ fake_graphics_context_provider_.window(), video_codec, audio_codec,
+ kSbDrmSystemInvalid, audio_sample_info, "", DummyDeallocateSampleFunc,
+ DecoderStatusCallback, PlayerStatusCallback, ErrorCallback, this,
+ output_mode_, fake_graphics_context_provider_.decoder_target_provider());
+
+ ASSERT_TRUE(SbPlayerIsValid(player_));
+
+ InitializePlayer();
+}
+
+void SbPlayerWriteSampleTest::TearDown() {
+ SB_DCHECK(SbPlayerIsValid(player_));
+
+ ASSERT_FALSE(destroy_player_called_);
+ destroy_player_called_ = true;
+ SbPlayerDestroy(player_);
+
+ // We expect the event to be sent already.
+ ASSERT_NO_FATAL_FAILURE(WaitForPlayerState(kSbPlayerStateDestroyed, 0));
+ ASSERT_FALSE(error_occurred_.load());
+}
+
+// static
+void SbPlayerWriteSampleTest::DecoderStatusCallback(SbPlayer player,
+ void* context,
+ SbMediaType type,
+ SbPlayerDecoderState state,
+ int ticket) {
+ SbPlayerWriteSampleTest* sb_player_write_sample_test =
+ static_cast<SbPlayerWriteSampleTest*>(context);
+ sb_player_write_sample_test->OnDecoderState(player, type, state, ticket);
+}
+
+// static
+void SbPlayerWriteSampleTest::PlayerStatusCallback(SbPlayer player,
+ void* context,
+ SbPlayerState state,
+ int ticket) {
+ SbPlayerWriteSampleTest* sb_player_write_sample_test =
+ static_cast<SbPlayerWriteSampleTest*>(context);
+ sb_player_write_sample_test->OnPlayerState(player, state, ticket);
+}
+
+// static
+void SbPlayerWriteSampleTest::ErrorCallback(SbPlayer player,
+ void* context,
+ SbPlayerError error,
+ const char* message) {
+ SbPlayerWriteSampleTest* sb_player_write_sample_test =
+ static_cast<SbPlayerWriteSampleTest*>(context);
+ sb_player_write_sample_test->OnError(player, error, message);
+}
+
+void SbPlayerWriteSampleTest::InitializePlayer() {
+ ASSERT_FALSE(destroy_player_called_);
+ ASSERT_NO_FATAL_FAILURE(WaitForPlayerState(kSbPlayerStateInitialized));
+ Seek(0);
+ SbPlayerSetPlaybackRate(player_, 1.0);
+ SbPlayerSetVolume(player_, 1.0);
+}
+
+void SbPlayerWriteSampleTest::PrepareForSeek() {
+ ASSERT_FALSE(destroy_player_called_);
+ ASSERT_FALSE(HasReceivedPlayerState(kSbPlayerStateDestroyed));
+ ASSERT_TRUE(HasReceivedPlayerState(kSbPlayerStateInitialized));
+ player_state_set_.clear();
+ player_state_set_.insert(kSbPlayerStateInitialized);
+ ticket_++;
+}
+
+void SbPlayerWriteSampleTest::Seek(const SbTime time) {
+ PrepareForSeek();
+ SbPlayerSeek2(player_, time, ticket_);
+ ASSERT_NO_FATAL_FAILURE(WaitForDecoderStateNeedsData());
+ ASSERT_TRUE(decoder_state_queue_.empty());
+}
+
+void SbPlayerWriteSampleTest::GetDecodeTargetWhenSupported() {
+ if (destroy_player_called_) {
+ return;
+ }
+#if SB_HAS(GLES2)
+ fake_graphics_context_provider_.RunOnGlesContextThread([&]() {
+ ASSERT_TRUE(SbPlayerIsValid(player_));
+ if (output_mode_ != kSbPlayerOutputModeDecodeToTexture) {
+#if SB_API_VERSION >= 12
+ ASSERT_EQ(SbPlayerGetCurrentFrame(player_), kSbDecodeTargetInvalid);
+#endif // SB_API_VERSION >= 12
+ return;
+ }
+ ASSERT_EQ(output_mode_, kSbPlayerOutputModeDecodeToTexture);
+ SbDecodeTarget frame = SbPlayerGetCurrentFrame(player_);
+ if (SbDecodeTargetIsValid(frame)) {
+ SbDecodeTargetRelease(frame);
+ }
+ });
+#endif // SB_HAS(GLES2)
+}
+
+void SbPlayerWriteSampleTest::OnDecoderState(SbPlayer player,
+ SbMediaType type,
+ SbPlayerDecoderState state,
+ int ticket) {
+ switch (state) {
+ case kSbPlayerDecoderStateNeedsData:
+ callback_event_queue_.Put(CallbackEvent(player, state, ticket));
+ break;
+#if SB_API_VERSION < 12
+ // Note: we do not add these events to the queue since these states are not
+ // used in Cobalt and are being deprecated.
+ case kSbPlayerDecoderStateBufferFull:
+ case kSbPlayerDecoderStateDestroyed:
+ break;
+#endif // SB_API_VERSION < 12
+ }
+}
+
+void SbPlayerWriteSampleTest::OnPlayerState(SbPlayer player,
+ SbPlayerState state,
+ int ticket) {
+ callback_event_queue_.Put(CallbackEvent(player, state, ticket));
+}
+
+void SbPlayerWriteSampleTest::OnError(SbPlayer player,
+ SbPlayerError error,
+ const char* message) {
+ SB_LOG(ERROR) << FormatString("Got SbPlayerError %d with message '%s'", error,
+ message != NULL ? message : "");
+ error_occurred_.exchange(true);
+}
+
+void SbPlayerWriteSampleTest::WaitForDecoderStateNeedsData(
+ const SbTime timeout) {
+ optional<SbPlayerDecoderState> received_state;
+ SbTimeMonotonic start = SbTimeGetMonotonicNow();
+ do {
+ ASSERT_FALSE(error_occurred_.load());
+ GetDecodeTargetWhenSupported();
+ ASSERT_NO_FATAL_FAILURE(TryProcessCallbackEvents(
+ std::min(timeout, kDefaultWaitForCallbackEventTimeout)));
+ if (decoder_state_queue_.empty()) {
+ continue;
+ }
+ received_state = decoder_state_queue_.front();
+ decoder_state_queue_.pop_front();
+ if (received_state.value() == kSbPlayerDecoderStateNeedsData) {
+ break;
+ }
+ } while (SbTimeGetMonotonicNow() - start < timeout);
+
+ ASSERT_TRUE(received_state.has_engaged()) << "Did not receive any states.";
+ ASSERT_EQ(kSbPlayerDecoderStateNeedsData, received_state.value())
+ << "Did not receive expected state.";
+}
+
+void SbPlayerWriteSampleTest::WaitForPlayerState(
+ const SbPlayerState desired_state,
+ const SbTime timeout) {
+ SbTimeMonotonic start = SbTimeGetMonotonicNow();
+ do {
+ ASSERT_FALSE(error_occurred_.load());
+ GetDecodeTargetWhenSupported();
+ ASSERT_NO_FATAL_FAILURE(TryProcessCallbackEvents(
+ std::min(timeout, kDefaultWaitForCallbackEventTimeout)));
+ if (HasReceivedPlayerState(desired_state)) {
+ break;
+ }
+ } while (SbTimeGetMonotonicNow() - start < timeout);
+ ASSERT_TRUE(HasReceivedPlayerState(desired_state))
+ << "Did not received expected state.";
+}
+
+void SbPlayerWriteSampleTest::WriteSingleInput(size_t index) {
+ ASSERT_FALSE(destroy_player_called_);
+ ASSERT_LT(index, GetNumBuffers());
+ SbPlayerSampleInfo sample_info =
+ dmp_reader_->GetPlayerSampleInfo(test_media_type_, index);
+ SbPlayerWriteSample2(player_, test_media_type_, &sample_info, 1);
+}
+
+void SbPlayerWriteSampleTest::WriteEndOfStream() {
+ ASSERT_FALSE(destroy_player_called_);
+ ASSERT_FALSE(end_of_stream_written_);
+ end_of_stream_written_ = true;
+ SbPlayerWriteEndOfStream(player_, test_media_type_);
+}
+
+void SbPlayerWriteSampleTest::WriteMultipleInputs(size_t start_index,
+ size_t num_inputs_to_write) {
+ SB_DCHECK(num_inputs_to_write > 0);
+ SB_DCHECK(start_index < GetNumBuffers());
+
+ ASSERT_NO_FATAL_FAILURE(WriteSingleInput(start_index));
+ ++start_index;
+ --num_inputs_to_write;
+
+ while (num_inputs_to_write > 0 && start_index < GetNumBuffers()) {
+ ASSERT_NO_FATAL_FAILURE(WaitForDecoderStateNeedsData());
+ ASSERT_NO_FATAL_FAILURE(WriteSingleInput(start_index));
+ ++start_index;
+ --num_inputs_to_write;
+ }
+}
+
+void SbPlayerWriteSampleTest::DrainOutputs() {
+ ASSERT_TRUE(end_of_stream_written_);
+ ASSERT_NO_FATAL_FAILURE(WaitForPlayerState(kSbPlayerStateEndOfStream));
+ // We should not get any new decoder events after end of stream.
+ ASSERT_TRUE(decoder_state_queue_.empty());
+}
+
+int SbPlayerWriteSampleTest::GetNumBuffers() const {
+ return test_media_type_ == kSbMediaTypeAudio
+ ? dmp_reader_->number_of_audio_buffers()
+ : dmp_reader_->number_of_video_buffers();
+}
+
+void SbPlayerWriteSampleTest::AssertPlayerStateIsValid(
+ SbPlayerState state) const {
+ // Note: it is possible to receive the same state that has been previously
+ // received in the case of multiple Seek() calls. Prior to any Seek commands
+ // issued in this test, we should reset the |player_state_set_| member.
+ ASSERT_FALSE(HasReceivedPlayerState(state));
+
+ switch (state) {
+ case kSbPlayerStateInitialized:
+ // No other states have been received before getting Initialized.
+ ASSERT_TRUE(player_state_set_.empty());
+ break;
+ case kSbPlayerStatePrerolling:
+ ASSERT_TRUE(HasReceivedPlayerState(kSbPlayerStateInitialized));
+ ASSERT_FALSE(HasReceivedPlayerState(kSbPlayerStateDestroyed));
+ break;
+ case kSbPlayerStatePresenting:
+ ASSERT_TRUE(HasReceivedPlayerState(kSbPlayerStatePrerolling));
+ ASSERT_FALSE(HasReceivedPlayerState(kSbPlayerStateDestroyed));
+ break;
+ case kSbPlayerStateEndOfStream:
+ ASSERT_TRUE(HasReceivedPlayerState(kSbPlayerStateInitialized));
+ ASSERT_TRUE(HasReceivedPlayerState(kSbPlayerStatePrerolling));
+ ASSERT_FALSE(HasReceivedPlayerState(kSbPlayerStateDestroyed));
+ break;
+ case kSbPlayerStateDestroyed:
+ // Nothing stops the user of the player from destroying the player during
+ // any of the previous states.
+ ASSERT_TRUE(destroy_player_called_);
+ break;
+ }
+}
+
+void SbPlayerWriteSampleTest::TryProcessCallbackEvents(SbTime timeout) {
+ for (;;) {
+ auto event = callback_event_queue_.GetTimed(timeout);
+ if (!event.HasStateUpdate()) {
+ break;
+ }
+ if (event.ticket != ticket_) {
+ continue;
+ }
+ ASSERT_EQ(event.player, player_);
+ SB_DCHECK(event.decoder_state.has_engaged() ^
+ event.player_state.has_engaged());
+ if (event.decoder_state.has_engaged()) {
+ // Callbacks may be in-flight at the time that the player is destroyed by
+ // a call to |SbPlayerDestroy|. In this case, the callbacks are ignored.
+ // However no new callbacks are expected after receiving the player status
+ // |kSbPlayerStateDestroyed|.
+ ASSERT_FALSE(HasReceivedPlayerState(kSbPlayerStateDestroyed));
+ decoder_state_queue_.push_back(event.decoder_state.value());
+ continue;
+ }
+ ASSERT_NO_FATAL_FAILURE(
+ AssertPlayerStateIsValid(event.player_state.value()));
+ player_state_set_.insert(event.player_state.value());
+ }
+}
+
+TEST_P(SbPlayerWriteSampleTest, SeekAndDestroy) {
+ PrepareForSeek();
+ SbPlayerSeek2(player_, 1 * kSbTimeSecond, ticket_);
+}
+
+TEST_P(SbPlayerWriteSampleTest, NoInput) {
+ WriteEndOfStream();
+ DrainOutputs();
+}
+
+TEST_P(SbPlayerWriteSampleTest, SingleInput) {
+ ASSERT_NO_FATAL_FAILURE(WriteSingleInput(0));
+ ASSERT_NO_FATAL_FAILURE(WaitForDecoderStateNeedsData());
+ WriteEndOfStream();
+ DrainOutputs();
+}
+
+TEST_P(SbPlayerWriteSampleTest, MultipleInputs) {
+ ASSERT_NO_FATAL_FAILURE(
+ WriteMultipleInputs(0, std::min<size_t>(10, GetNumBuffers())));
+ ASSERT_NO_FATAL_FAILURE(WaitForDecoderStateNeedsData());
+ WriteEndOfStream();
+ DrainOutputs();
+}
+
+INSTANTIATE_TEST_CASE_P(SbPlayerWriteSampleTests,
+ SbPlayerWriteSampleTest,
+ ValuesIn(GetSupportedSbPlayerTestConfigs()));
+
+} // namespace
+} // namespace nplb
+} // namespace starboard
diff --git a/src/starboard/nplb/time_constants.h b/src/starboard/nplb/time_constants.h
index 2b87459..e816429 100644
--- a/src/starboard/nplb/time_constants.h
+++ b/src/starboard/nplb/time_constants.h
@@ -47,15 +47,15 @@
static const SbTime kTestTimeWindowsNegative =
SbTimeFromPosix(SB_INT64_C(-15065654400) * kSbTimeSecond);
-// 1443473373 in POSIX time is
-// Monday, 9/28/2015 20:49:33 UTC
-// NOTE: Update this value once every 5 or so years.
+// 1600970155 in POSIX time is
+// Thursday, 9/24/2020 17:55:55 UTC
+// NOTE: Update this value once every 25 or so years.
static const SbTime kTestTimeWritten =
- SbTimeFromPosix(SB_INT64_C(1443473373) * kSbTimeSecond);
+ SbTimeFromPosix(SB_INT64_C(1600970155) * kSbTimeSecond);
-// 5 years after the time this test was written.
+// 25 years after the time this test was written.
static const SbTime kTestTimePastWritten =
- SbTimeFromPosix(kTestTimeWritten + (5 * kTestSbTimeYear));
+ SbTimeFromPosix(kTestTimeWritten + (25 * kTestSbTimeYear));
} // namespace nplb
} // namespace starboard
diff --git a/src/starboard/raspi/2/sbversion/12/gyp_configuration.py b/src/starboard/raspi/2/sbversion/12/gyp_configuration.py
index 622f13c..995e684 100644
--- a/src/starboard/raspi/2/sbversion/12/gyp_configuration.py
+++ b/src/starboard/raspi/2/sbversion/12/gyp_configuration.py
@@ -22,5 +22,5 @@
def CreatePlatformConfig():
return _PARENT_CONFIGURATION.Raspi2PlatformConfig(
- platform='raspi-2-sbversion-12',
+ 'raspi-2-sbversion-12',
sabi_json_path='starboard/sabi/arm/hardfp/sabi-v12.json')
diff --git a/src/starboard/raspi/shared/gyp_configuration.gypi b/src/starboard/raspi/shared/gyp_configuration.gypi
index deb191c..d2dd46b 100644
--- a/src/starboard/raspi/shared/gyp_configuration.gypi
+++ b/src/starboard/raspi/shared/gyp_configuration.gypi
@@ -76,7 +76,8 @@
# libraries.
'-L<(sysroot)/opt/vc/lib',
'-Wl,-rpath=<(sysroot)/opt/vc/lib',
-
+ # Cleanup unused sections
+ '-Wl,-gc-sections',
# We don't wrap these symbols, but this ensures that they aren't
# linked in.
'-Wl,--wrap=malloc',
@@ -107,9 +108,15 @@
],
'compiler_flags_qa_size': [
'-Os',
+ # Compile symbols in separate sections
+ '-ffunction-sections',
+ '-fdata-sections',
],
'compiler_flags_qa_speed': [
'-O2',
+ # Compile symbols in separate sections
+ '-ffunction-sections',
+ '-fdata-sections',
],
'compiler_flags_cc_qa': [
'-fno-rtti',
@@ -119,9 +126,15 @@
],
'compiler_flags_gold_size': [
'-Os',
+ # Compile symbols in separate sections
+ '-ffunction-sections',
+ '-fdata-sections',
],
'compiler_flags_gold_speed': [
'-O2',
+ # Compile symbols in separate sections
+ '-ffunction-sections',
+ '-fdata-sections',
],
'compiler_flags_cc_gold': [
'-fno-rtti',
diff --git a/src/starboard/raspi/shared/gyp_configuration.py b/src/starboard/raspi/shared/gyp_configuration.py
index 65e4796..faacb40 100644
--- a/src/starboard/raspi/shared/gyp_configuration.py
+++ b/src/starboard/raspi/shared/gyp_configuration.py
@@ -39,9 +39,10 @@
platform,
sabi_json_path='starboard/sabi/default/sabi.json'):
super(RaspiPlatformConfig, self).__init__(platform)
+
+ self.sabi_json_path = sabi_json_path
self.AppendApplicationConfigurationPath(os.path.dirname(__file__))
self.raspi_home = os.environ.get('RASPI_HOME', _UNDEFINED_RASPI_HOME)
- self.sabi_json_path = sabi_json_path
self.sysroot = os.path.realpath(os.path.join(self.raspi_home, 'sysroot'))
def GetBuildFormat(self):
@@ -69,18 +70,24 @@
def GetEnvironmentVariables(self):
if not hasattr(self, 'host_compiler_environment'):
self.host_compiler_environment = build.GetHostCompilerEnvironment(
- clang_specification.GetClangSpecification(), False)
+ clang_specification.GetClangSpecification(), self.build_accelerator)
- env_variables = self.host_compiler_environment
toolchain = os.path.realpath(
os.path.join(
self.raspi_home,
'tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64'))
toolchain_bin_dir = os.path.join(toolchain, 'bin')
+
+ env_variables = self.host_compiler_environment
env_variables.update({
- 'CC': os.path.join(toolchain_bin_dir, 'arm-linux-gnueabihf-gcc'),
- 'CXX': os.path.join(toolchain_bin_dir, 'arm-linux-gnueabihf-g++'),
- 'STRIP': os.path.join(toolchain_bin_dir, 'arm-linux-gnueabihf-strip'),
+ 'CC':
+ self.build_accelerator + ' ' +
+ os.path.join(toolchain_bin_dir, 'arm-linux-gnueabihf-gcc'),
+ 'CXX':
+ self.build_accelerator + ' ' +
+ os.path.join(toolchain_bin_dir, 'arm-linux-gnueabihf-g++'),
+ 'STRIP':
+ os.path.join(toolchain_bin_dir, 'arm-linux-gnueabihf-strip'),
})
return env_variables
@@ -149,6 +156,9 @@
__FILTERED_TESTS = { # pylint: disable=invalid-name
'nplb': [
'SbDrmTest.AnySupportedKeySystems',
+ 'SbMediaCanPlayMimeAndKeySystem.AnySupportedKeySystems',
+ 'SbMediaCanPlayMimeAndKeySystem.KeySystemWithAttributes',
+ 'SbMediaCanPlayMimeAndKeySystem.MinimumSupport',
],
'player_filter_tests': [
# The implementations for the raspberry pi (0 and 2) are incomplete
diff --git a/src/starboard/shared/starboard/media/codec_util.cc b/src/starboard/shared/starboard/media/codec_util.cc
index 64a649b..7d192fd 100644
--- a/src/starboard/shared/starboard/media/codec_util.cc
+++ b/src/starboard/shared/starboard/media/codec_util.cc
@@ -499,10 +499,10 @@
return true;
}
- // 6. Parse chroma subsampling, which we only support 01.
+ // 6. Parse chroma subsampling, which we only support 00 and 01.
// Note that this value is not returned.
int chroma;
- if (!ReadTwoDigitDecimal(codec + 14, &chroma) || chroma != 1) {
+ if (!ReadTwoDigitDecimal(codec + 14, &chroma) || (chroma != 0 && chroma != 1)) {
return false;
}
diff --git a/src/starboard/shared/starboard/media/media_util.cc b/src/starboard/shared/starboard/media/media_util.cc
index 9b721cb..3269d04 100644
--- a/src/starboard/shared/starboard/media/media_util.cc
+++ b/src/starboard/shared/starboard/media/media_util.cc
@@ -373,8 +373,11 @@
}
if (codecs.size() == 0) {
- // This is a progressive query. We only support "video/mp4" in this case.
- if (mime_type.type() == "video" && mime_type.subtype() == "mp4") {
+ // This happens when the H5 player is either querying for progressive
+ // playback support, or probing for generic mp4 support without specific
+ // codecs. We only support "audio/mp4" and "video/mp4" for these cases.
+ if ((mime_type.type() == "audio" || mime_type.type() == "video") &&
+ mime_type.subtype() == "mp4") {
return kSbMediaSupportTypeMaybe;
}
return kSbMediaSupportTypeNotSupported;
diff --git a/src/starboard/shared/starboard/player/filter/player_components.h b/src/starboard/shared/starboard/player/filter/player_components.h
index 567c4a1..e4c0eef 100644
--- a/src/starboard/shared/starboard/player/filter/player_components.h
+++ b/src/starboard/shared/starboard/player/filter/player_components.h
@@ -197,9 +197,10 @@
scoped_refptr<VideoRendererSink>* video_renderer_sink);
// Check AudioRenderer ctor for more details on the parameters.
- void GetAudioRendererParams(const CreationParameters& creation_parameters,
- int* max_cached_frames,
- int* min_frames_per_append) const;
+ virtual void GetAudioRendererParams(
+ const CreationParameters& creation_parameters,
+ int* max_cached_frames,
+ int* min_frames_per_append) const;
private:
SB_DISALLOW_COPY_AND_ASSIGN(Factory);
diff --git a/src/starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.h b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.h
index 1450b58..49dbd09 100644
--- a/src/starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.h
+++ b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test_fixture.h
@@ -86,7 +86,11 @@
SbPlayerOutputMode output_mode,
bool using_stub_decoder);
- ~VideoDecoderTestFixture() { video_decoder_->Reset(); }
+ ~VideoDecoderTestFixture() {
+ if (video_decoder_) {
+ video_decoder_->Reset();
+ }
+ }
void Initialize();
diff --git a/src/starboard/shared/widevine/drm_system_widevine.cc b/src/starboard/shared/widevine/drm_system_widevine.cc
index c3910d3..4a8eaf1 100644
--- a/src/starboard/shared/widevine/drm_system_widevine.cc
+++ b/src/starboard/shared/widevine/drm_system_widevine.cc
@@ -26,6 +26,7 @@
#include "starboard/memory.h"
#include "starboard/once.h"
#include "starboard/shared/starboard/application.h"
+#include "starboard/shared/starboard/media/mime_type.h"
#include "starboard/shared/widevine/widevine_storage.h"
#include "starboard/shared/widevine/widevine_timer.h"
#include "starboard/time.h"
@@ -40,7 +41,7 @@
namespace {
const int kInitializationVectorSize = 16;
-const char* kWidevineKeySystem[] = {"com.widevine", "com.widevine.alpha"};
+const char* kWidevineKeySystems[] = {"com.widevine", "com.widevine.alpha"};
const char kWidevineStorageFileName[] = "wvcdm.dat";
// Key usage may be blocked due to incomplete HDCP authentication which could
@@ -264,8 +265,28 @@
// static
bool DrmSystemWidevine::IsKeySystemSupported(const char* key_system) {
- for (auto wv_key_system : kWidevineKeySystem) {
- if (SbStringCompareAll(key_system, wv_key_system) == 0) {
+ SB_DCHECK(key_system);
+
+ // It is possible that the |key_system| comes with extra attributes, like
+ // `com.widevine.alpha; encryptionscheme="cenc"`. We prepend "key_system/"
+ // to it, so it can be parsed by MimeType.
+ starboard::media::MimeType mime_type(std::string("key_system/") + key_system);
+
+ if (!mime_type.is_valid()) {
+ return false;
+ }
+ SB_DCHECK(mime_type.type() == "key_system");
+
+ for (auto wv_key_system : kWidevineKeySystems) {
+ if (mime_type.subtype() == wv_key_system) {
+ for (int i = 0; i < mime_type.GetParamCount(); ++i) {
+ if (mime_type.GetParamName(i) == "encryptionscheme") {
+ auto value = mime_type.GetParamStringValue(i);
+ if (value != "cenc" && value != "cbcs" && value != "cbcs-1-9") {
+ return false;
+ }
+ }
+ }
return true;
}
}
diff --git a/src/starboard/shared/x11/application_x11.cc b/src/starboard/shared/x11/application_x11.cc
index 07cfc1f..b206794 100644
--- a/src/starboard/shared/x11/application_x11.cc
+++ b/src/starboard/shared/x11/application_x11.cc
@@ -41,6 +41,10 @@
#include "starboard/shared/x11/window_internal.h"
#include "starboard/time.h"
+namespace {
+const char kTouchscreenPointerSwitch[] = "touchscreen_pointer";
+}
+
namespace starboard {
namespace shared {
namespace x11 {
@@ -715,6 +719,7 @@
// evdev input will be sent to the first created window only.
dev_input_.reset(DevInput::Create(window, ConnectionNumber(display_)));
}
+ touchscreen_pointer_ = GetCommandLine()->HasSwitch(kTouchscreenPointerSwitch);
return window;
}
@@ -1242,7 +1247,8 @@
data->key = XButtonEventToSbKey(x_button_event);
data->type =
is_press_event ? kSbInputEventTypePress : kSbInputEventTypeUnpress;
- data->device_type = kSbInputDeviceTypeMouse;
+ data->device_type = touchscreen_pointer_ ? kSbInputDeviceTypeTouchScreen
+ : kSbInputDeviceTypeMouse;
if (is_wheel_event) {
data->pressure = NAN;
data->size = {NAN, NAN};
@@ -1268,11 +1274,17 @@
data->size = {NAN, NAN};
data->tilt = {NAN, NAN};
data->type = kSbInputEventTypeMove;
- data->device_type = kSbInputDeviceTypeMouse;
+ data->device_type = touchscreen_pointer_ ? kSbInputDeviceTypeTouchScreen
+ : kSbInputDeviceTypeMouse;
data->device_id = kMouseDeviceId;
data->key_modifiers = XEventStateToSbKeyModifiers(x_motion_event->state);
data->position.x = x_motion_event->x;
data->position.y = x_motion_event->y;
+ if (touchscreen_pointer_ && !data->key_modifiers) {
+ // For touch screens, only report motion events when a button is
+ // pressed.
+ return NULL;
+ }
return new Event(kSbEventTypeInput, data.release(),
&DeleteDestructor<SbInputData>);
}
diff --git a/src/starboard/shared/x11/application_x11.h b/src/starboard/shared/x11/application_x11.h
index e63cd91..6b1ade7 100644
--- a/src/starboard/shared/x11/application_x11.h
+++ b/src/starboard/shared/x11/application_x11.h
@@ -150,6 +150,9 @@
// The /dev/input input handler. Only set when there is an open window.
scoped_ptr<::starboard::shared::dev_input::DevInput> dev_input_;
+
+ // Indicates whether pointer input is from a touchscreen.
+ bool touchscreen_pointer_;
};
} // namespace x11
diff --git a/src/starboard/stub/configuration.gni b/src/starboard/stub/configuration.gni
index 9babbcb..774ab8a 100644
--- a/src/starboard/stub/configuration.gni
+++ b/src/starboard/stub/configuration.gni
@@ -18,9 +18,3 @@
# Use media source extension implementation that is conformed to the
# Candidate Recommendation of July 5th 2016.
cobalt_use_media_source_2016 = true
-
-declare_args() {
- # Set to true to enable distributed compilation using Goma. By default we
- # use Goma for stub and linux.
- use_goma = true
-}
diff --git a/src/starboard/stub/gyp_configuration.py b/src/starboard/stub/gyp_configuration.py
index 2d97119..4f0285f 100644
--- a/src/starboard/stub/gyp_configuration.py
+++ b/src/starboard/stub/gyp_configuration.py
@@ -52,9 +52,8 @@
def GetEnvironmentVariables(self):
if not hasattr(self, 'host_compiler_environment'):
- goma_supports_compiler = True
self.host_compiler_environment = build.GetHostCompilerEnvironment(
- clang_specification.GetClangSpecification(), goma_supports_compiler)
+ clang_specification.GetClangSpecification(), 'ccache')
env_variables = self.host_compiler_environment
env_variables.update({
diff --git a/src/starboard/tools/build.py b/src/starboard/tools/build.py
index 7a071e3..7652a4c 100644
--- a/src/starboard/tools/build.py
+++ b/src/starboard/tools/build.py
@@ -26,7 +26,6 @@
from starboard.tools import config
from starboard.tools import paths
from starboard.tools import platform
-import starboard.tools.goma
_STARBOARD_TOOLCHAINS_DIR_KEY = 'STARBOARD_TOOLCHAINS_DIR'
_STARBOARD_TOOLCHAINS_DIR_NAME = 'starboard-toolchains'
@@ -190,27 +189,20 @@
return _GetClangBasePath(clang_spec)
-def GetHostCompilerEnvironment(clang_spec, goma_supports_compiler):
+def GetHostCompilerEnvironment(clang_spec, build_accelerator):
"""Return the host compiler toolchain environment."""
-
toolchain_dir = EnsureClangAvailable(clang_spec)
toolchain_bin_dir = os.path.join(toolchain_dir, 'bin')
cc_clang = os.path.join(toolchain_bin_dir, 'clang')
cxx_clang = os.path.join(toolchain_bin_dir, 'clang++')
host_clang_environment = {
- 'CC_host': cc_clang,
- 'CXX_host': cxx_clang,
+ 'CC_host': build_accelerator + ' ' + cc_clang,
+ 'CXX_host': build_accelerator + ' ' + cxx_clang,
'LD_host': cxx_clang,
'ARFLAGS_host': 'rcs',
'ARTHINFLAGS_host': 'rcsT',
}
- # Check if goma is installed. Initialize if needed and use if possible.
- if goma_supports_compiler and starboard.tools.goma.FindAndStartGoma():
- host_clang_environment.update({
- 'CC_host': 'gomacc ' + cc_clang,
- 'CXX_host': 'gomacc ' + cxx_clang,
- })
return host_clang_environment
diff --git a/src/starboard/tools/build_accelerator.py b/src/starboard/tools/build_accelerator.py
new file mode 100644
index 0000000..5c4a39f
--- /dev/null
+++ b/src/starboard/tools/build_accelerator.py
@@ -0,0 +1,34 @@
+#
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Defines abstract build accelerators."""
+
+import abc
+
+
+class BuildAccelerator(object):
+ """A base class for all build accelerators."""
+
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def GetName(self):
+ """Returns name of build accelerator to be called."""
+ pass
+
+ @abc.abstractmethod
+ def Use(self):
+ """Returns boolean of whether the build accelerator should be used."""
+ pass
diff --git a/src/starboard/tools/ccache.py b/src/starboard/tools/ccache.py
new file mode 100644
index 0000000..5f1928c
--- /dev/null
+++ b/src/starboard/tools/ccache.py
@@ -0,0 +1,57 @@
+#
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Ccache specific definitions and helper functions.
+
+Override settings using environment variables.
+USE_CCACHE To enable/disable ccache. Default is None.
+"""
+
+import logging
+import os
+import util
+
+from starboard.tools import build_accelerator
+
+
+class Ccache(build_accelerator.BuildAccelerator):
+ """Ccache is a cache based build accelerator."""
+
+ def GetName(self):
+ return 'ccache'
+
+ def Use(self):
+ return CcacheEnvOverride() and CcacheInstalled()
+
+
+def CcacheEnvOverride():
+ """Checks USE_CCACHE to enable/disable ccache.
+
+ Returns:
+ USE_CCACHE boolean if exists, defaults to True.
+ """
+ if 'USE_CCACHE' in os.environ:
+ return os.environ['USE_CCACHE'] == '1'
+ return True
+
+
+def CcacheInstalled():
+ """Returns True if ccache is installed, otherwise is False."""
+ ccache_path = util.Which('ccache')
+ if ccache_path is not None:
+ logging.info('Using ccache installed at: %s', ccache_path)
+ return True
+ logging.error('Unable to find ccache.')
+ return False
diff --git a/src/starboard/tools/goma.py b/src/starboard/tools/goma.py
deleted file mode 100644
index deec990..0000000
--- a/src/starboard/tools/goma.py
+++ /dev/null
@@ -1,118 +0,0 @@
-#
-# Copyright 2019 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-"""Goma specific definitions and helper functions.
-
-Goma is used for faster builds. Install goma and add directory to PATH.
-Provides common functions to setup goma across platform builds.
-It checks that goma is enabled and installed, and starts the
-goma proxy.
-
-Override settings using environment variables.
-USE_GOMA To enable/disable goma. Default is None.
-"""
-
-import logging
-import os
-import subprocess
-import sys
-import util
-
-
-def _GomaEnabledFromEnv():
- """Enable goma if USE_GOMA is defined.
-
- Returns:
- True to enable goma, defaults to False.
- """
- if 'USE_GOMA' in os.environ:
- return os.environ['USE_GOMA'] == '1'
- return False
-
-
-def _GetGomaFromPath():
- """Returns goma directory from PATH, otherwise is None."""
- gomacc_path = util.Which('gomacc')
- if gomacc_path is not None:
- return os.path.dirname(gomacc_path)
- return None
-
-
-def _GomaInstalled(goma_dir):
- """Returns True if goma is installed, otherwise is False."""
- if goma_dir and os.path.isdir(goma_dir):
- if os.path.isfile(GomaControlFile(goma_dir)):
- logging.error('Using Goma installed at: %s', goma_dir)
- return True
- logging.error('Failed to find goma dir. Check PATH location: %s', goma_dir)
- return False
-
-
-def GomaControlFile(goma_dir):
- """Returns path to goma control script."""
- return os.path.join(goma_dir, 'goma_ctl.py')
-
-
-def _GomaEnsureStart(goma_dir):
- """Starts the goma proxy.
-
- Checks the proxy status and tries to start if not running.
-
- Args:
- goma_dir: goma install directory
-
- Returns:
- True if goma started, otherwise False.
- """
- if not _GomaInstalled(goma_dir):
- return False
-
- goma_ctl = GomaControlFile(goma_dir)
- command = [goma_ctl, 'ensure_start']
- logging.error('starting goma proxy...')
-
- try:
- subprocess.check_call(command)
- return True
- except subprocess.CalledProcessError as e:
- logging.error('Goma proxy failed to start.\nCommand: %s\n%s',
- ' '.join(e.cmd), e.output)
- return False
-
-
-def FindAndStartGoma(enable_in_path=True, exit_on_failed_start=False):
- """Uses goma if installed and proxy is running.
-
- Args:
- enable_in_path: If True, enable goma if found in PATH. Otherwise,
- it enables it when USE_GOMA=1 is set.
- exit_on_failed_start: Boolean to exit if goma is enabled, but wasn't
- started.
- Returns:
- True if goma is enabled and running, otherwise False.
- """
- if enable_in_path or _GomaEnabledFromEnv():
- goma_dir = _GetGomaFromPath()
- if _GomaEnsureStart(goma_dir):
- return True
- else:
- logging.critical('goma was enabled, but failed to start.')
- if exit_on_failed_start:
- sys.exit(1)
- return False
- else:
- logging.info('Goma is disabled. To enable, check for gomacc in PATH '
- 'and/or set USE_GOMA=1.')
- return False
diff --git a/src/starboard/tools/toolchain/evergreen_linker.py b/src/starboard/tools/toolchain/evergreen_linker.py
index a7bf4d7..04fdc19 100644
--- a/src/starboard/tools/toolchain/evergreen_linker.py
+++ b/src/starboard/tools/toolchain/evergreen_linker.py
@@ -28,6 +28,7 @@
return shell.And('{0} '
'--build-id '
+ '-gc-sections '
'-X '
'-v '
'--eh-frame-hdr '
diff --git a/src/third_party/aom_includes/METATDATA b/src/third_party/aom_includes/METADATA
similarity index 100%
rename from src/third_party/aom_includes/METATDATA
rename to src/third_party/aom_includes/METADATA
diff --git a/src/third_party/crashpad/client/crash_report_database.h b/src/third_party/crashpad/client/crash_report_database.h
index cc4b8df..0739a9c 100644
--- a/src/third_party/crashpad/client/crash_report_database.h
+++ b/src/third_party/crashpad/client/crash_report_database.h
@@ -404,6 +404,15 @@
//! \return The number of reports cleaned.
virtual int CleanDatabase(time_t lockfile_ttl) { return 0; }
+ //! \brief Deletes the oldest crash reports and their associated metadata,
+ //! leaving only num_reports_to_keep left in the database.
+ //!
+ //! \param[in] num_reports_to_keep To number of most recent reports to leave
+ //! in the database.
+ //!
+ //! \return The operation status code.
+ virtual OperationStatus RemoveOldReports(int num_reports_to_keep) = 0;
+
protected:
CrashReportDatabase() {}
diff --git a/src/third_party/crashpad/client/crash_report_database_generic.cc b/src/third_party/crashpad/client/crash_report_database_generic.cc
index e90bfa6..e807f17 100644
--- a/src/third_party/crashpad/client/crash_report_database_generic.cc
+++ b/src/third_party/crashpad/client/crash_report_database_generic.cc
@@ -18,7 +18,9 @@
#include <sys/stat.h>
#include <sys/types.h>
+#include <algorithm>
#include <utility>
+#include <vector>
#include "base/logging.h"
#include "build/build_config.h"
@@ -191,6 +193,11 @@
}
}
+bool WasCreatedSooner(CrashReportDatabase::Report a,
+ CrashReportDatabase::Report b) {
+ return a.creation_time < b.creation_time;
+}
+
} // namespace
class CrashReportDatabaseGeneric : public CrashReportDatabase {
@@ -218,6 +225,7 @@
OperationStatus DeleteReport(const UUID& uuid) override;
OperationStatus RequestUpload(const UUID& uuid) override;
int CleanDatabase(time_t lockfile_ttl) override;
+ OperationStatus RemoveOldReports(int num_reports_to_keep) override;
// Build a filepath for the directory for the report to hold attachments.
base::FilePath AttachmentsPath(const UUID& uuid);
@@ -640,6 +648,32 @@
return removed;
}
+OperationStatus CrashReportDatabaseGeneric::RemoveOldReports(
+ int num_reports_to_keep) {
+ std::vector<CrashReportDatabase::Report> pending_reports;
+ std::vector<CrashReportDatabase::Report> completed_reports;
+ std::vector<CrashReportDatabase::Report> all_reports;
+
+ GetPendingReports(&pending_reports);
+ GetCompletedReports(&completed_reports);
+
+ all_reports.insert(
+ all_reports.end(), pending_reports.begin(), pending_reports.end());
+ all_reports.insert(
+ all_reports.end(), completed_reports.begin(), completed_reports.end());
+ std::sort(all_reports.begin(), all_reports.end(), WasCreatedSooner);
+
+ while (all_reports.size() > num_reports_to_keep) {
+ OperationStatus os = DeleteReport((*all_reports.begin()).uuid);
+ if (os != kNoError) {
+ return os;
+ }
+ all_reports.erase(all_reports.begin());
+ }
+
+ return kNoError;
+}
+
OperationStatus CrashReportDatabaseGeneric::RecordUploadAttempt(
UploadReport* report,
bool successful,
diff --git a/src/third_party/crashpad/client/crashpad_client.h b/src/third_party/crashpad/client/crashpad_client.h
index e381b41..147b974 100644
--- a/src/third_party/crashpad/client/crashpad_client.h
+++ b/src/third_party/crashpad/client/crashpad_client.h
@@ -388,6 +388,15 @@
//!
//! \return `true` on success, `false` on failure with a message logged.
static bool SendEvergreenInfoToHandler(EvergreenInfo evergreen_info);
+
+ //! \brief Sends mapping info to the handler
+ //!
+ //! A handler must have already been installed before calling this method.
+ //! \param[in] annotations A EvergreenAnnotations struct, whose information
+ //! was created on Evergreen startup.
+ //!
+ //! \return `true` on success, `false` on failure with a message logged.
+ static bool SendAnnotationsToHandler(EvergreenAnnotations annotations);
#endif
//! \brief Requests that the handler capture a dump even though there hasn't
diff --git a/src/third_party/crashpad/client/crashpad_client_linux.cc b/src/third_party/crashpad/client/crashpad_client_linux.cc
index 02a4e57..2435153 100644
--- a/src/third_party/crashpad/client/crashpad_client_linux.cc
+++ b/src/third_party/crashpad/client/crashpad_client_linux.cc
@@ -141,6 +141,11 @@
evergreen_info_ = evergreen_info;
return SendEvergreenInfoImpl();
}
+
+ bool SendAnnotations(EvergreenAnnotations annotations) {
+ annotations_ = annotations;
+ return SendAnnotationsImpl();
+ }
#endif
// The base implementation for all signal handlers, suitable for calling
@@ -181,6 +186,7 @@
#if defined(STARBOARD)
const EvergreenInfo& GetEvergreenInfo() { return evergreen_info_; }
+ const EvergreenAnnotations& GetAnnotations() { return annotations_; }
#endif
const ExceptionInformation& GetExceptionInfo() {
@@ -189,6 +195,7 @@
#if defined(STARBOARD)
virtual bool SendEvergreenInfoImpl() = 0;
+ virtual bool SendAnnotationsImpl() = 0;
#endif
virtual void HandleCrashImpl() = 0;
@@ -211,6 +218,7 @@
#if defined(STARBOARD)
EvergreenInfo evergreen_info_;
+ EvergreenAnnotations annotations_;
#endif
static SignalHandler* handler_;
@@ -250,6 +258,7 @@
#if defined(STARBOARD)
bool SendEvergreenInfoImpl() override { return false; }
+ bool SendAnnotationsImpl() override { return false; }
#endif
void HandleCrashImpl() override {
@@ -353,6 +362,14 @@
client.SendEvergreenInfo(info);
return true;
}
+
+ bool SendAnnotationsImpl() override {
+ ExceptionHandlerClient client(sock_to_handler_.get(), true);
+ ExceptionHandlerProtocol::ClientInformation info = {};
+ info.annotations_address = FromPointerCast<VMAddress>(&GetAnnotations());
+ client.SendAnnotations(info);
+ return true;
+ }
#endif
void HandleCrashImpl() override {
@@ -576,6 +593,16 @@
return SignalHandler::Get()->SendEvergreenInfo(evergreen_info);
}
+
+bool CrashpadClient::SendAnnotationsToHandler(
+ EvergreenAnnotations annotations) {
+ if (!SignalHandler::Get()) {
+ DLOG(ERROR) << "Crashpad isn't enabled";
+ return false;
+ }
+
+ return SignalHandler::Get()->SendAnnotations(annotations);
+}
#endif
// static
diff --git a/src/third_party/crashpad/handler/crash_report_upload_thread.cc b/src/third_party/crashpad/handler/crash_report_upload_thread.cc
index ac0f7c1..db960b1 100644
--- a/src/third_party/crashpad/handler/crash_report_upload_thread.cc
+++ b/src/third_party/crashpad/handler/crash_report_upload_thread.cc
@@ -242,7 +242,7 @@
break;
}
#if defined(STARBOARD)
- database_->DeleteReport(report.uuid);
+ database_->RemoveOldReports(/*num_reports_to_save=*/2);
#endif
}
diff --git a/src/third_party/crashpad/handler/linux/capture_snapshot.cc b/src/third_party/crashpad/handler/linux/capture_snapshot.cc
index d792945..488bbba 100644
--- a/src/third_party/crashpad/handler/linux/capture_snapshot.cc
+++ b/src/third_party/crashpad/handler/linux/capture_snapshot.cc
@@ -34,14 +34,15 @@
std::unique_ptr<ProcessSnapshotSanitized>* sanitized_snapshot
#if defined(STARBOARD)
,
- VMAddress evergreen_information_address
+ VMAddress evergreen_information_address,
+ VMAddress annotations_address
#endif
) {
std::unique_ptr<ProcessSnapshotLinux> process_snapshot(
new ProcessSnapshotLinux());
#if defined(STARBOARD)
- if (!process_snapshot->Initialize(connection,
- evergreen_information_address)) {
+ if (!process_snapshot->Initialize(
+ connection, evergreen_information_address, annotations_address)) {
#else
if (!process_snapshot->Initialize(connection)) {
#endif
diff --git a/src/third_party/crashpad/handler/linux/capture_snapshot.h b/src/third_party/crashpad/handler/linux/capture_snapshot.h
index d191b8b..51eca35 100644
--- a/src/third_party/crashpad/handler/linux/capture_snapshot.h
+++ b/src/third_party/crashpad/handler/linux/capture_snapshot.h
@@ -67,7 +67,8 @@
std::unique_ptr<ProcessSnapshotSanitized>* sanitized_snapshot
#if defined(STARBOARD)
,
- VMAddress evergreen_information_address
+ VMAddress evergreen_information_address,
+ VMAddress annotations_address
#endif
);
diff --git a/src/third_party/crashpad/handler/linux/crash_report_exception_handler.cc b/src/third_party/crashpad/handler/linux/crash_report_exception_handler.cc
index 3a59dc7..b0f68ce 100644
--- a/src/third_party/crashpad/handler/linux/crash_report_exception_handler.cc
+++ b/src/third_party/crashpad/handler/linux/crash_report_exception_handler.cc
@@ -86,6 +86,12 @@
evergreen_info_ = info.evergreen_information_address;
return true;
}
+
+bool CrashReportExceptionHandler::AddAnnotations(
+ const ExceptionHandlerProtocol::ClientInformation& info) {
+ annotations_address_ = info.annotations_address;
+ return true;
+}
#endif
bool CrashReportExceptionHandler::HandleException(
@@ -150,7 +156,8 @@
&sanitized_snapshot
#if defined(STARBOARD)
,
- evergreen_info_
+ evergreen_info_,
+ annotations_address_
#endif
)) {
return false;
diff --git a/src/third_party/crashpad/handler/linux/crash_report_exception_handler.h b/src/third_party/crashpad/handler/linux/crash_report_exception_handler.h
index b5ea3f7..5cca2ad 100644
--- a/src/third_party/crashpad/handler/linux/crash_report_exception_handler.h
+++ b/src/third_party/crashpad/handler/linux/crash_report_exception_handler.h
@@ -87,6 +87,8 @@
#if defined(STARBOARD)
bool AddEvergreenInfo(
const ExceptionHandlerProtocol::ClientInformation& info) override;
+ bool AddAnnotations(
+ const ExceptionHandlerProtocol::ClientInformation& info) override;
#endif
bool HandleExceptionWithBroker(
@@ -120,6 +122,7 @@
const UserStreamDataSources* user_stream_data_sources_; // weak
#if defined(STARBOARD)
VMAddress evergreen_info_;
+ VMAddress annotations_address_;
#endif
DISALLOW_COPY_AND_ASSIGN(CrashReportExceptionHandler);
diff --git a/src/third_party/crashpad/handler/linux/exception_handler_server.cc b/src/third_party/crashpad/handler/linux/exception_handler_server.cc
index d49cc1c..63215d5 100644
--- a/src/third_party/crashpad/handler/linux/exception_handler_server.cc
+++ b/src/third_party/crashpad/handler/linux/exception_handler_server.cc
@@ -442,6 +442,8 @@
#if defined(STARBOARD)
case ExceptionHandlerProtocol::ClientToServerMessage::kTypeAddEvergreenInfo:
return HandleAddEvergreenInfoRequest(creds, message.client_info);
+ case ExceptionHandlerProtocol::ClientToServerMessage::kTypeAddAnnotations:
+ return HandleAddAnnotationsRequest(creds, message.client_info);
#endif
}
@@ -456,6 +458,12 @@
const ExceptionHandlerProtocol::ClientInformation& client_info) {
return delegate_->AddEvergreenInfo(client_info);
}
+
+bool ExceptionHandlerServer::HandleAddAnnotationsRequest(
+ const ucred& creds,
+ const ExceptionHandlerProtocol::ClientInformation& client_info) {
+ return delegate_->AddAnnotations(client_info);
+}
#endif
bool ExceptionHandlerServer::HandleCrashDumpRequest(
diff --git a/src/third_party/crashpad/handler/linux/exception_handler_server.h b/src/third_party/crashpad/handler/linux/exception_handler_server.h
index 0f0e73c..1e87157 100644
--- a/src/third_party/crashpad/handler/linux/exception_handler_server.h
+++ b/src/third_party/crashpad/handler/linux/exception_handler_server.h
@@ -102,6 +102,13 @@
//! \return `true` on success. `false` on failure with a message logged.
virtual bool AddEvergreenInfo(
const ExceptionHandlerProtocol::ClientInformation& info) = 0;
+
+ //! \brief Called on receipt of a request to add Evergreen Annotations.
+ //!
+ //! \param[in] info Information on the client.
+ //! \return `true` on success. `false` on failure with a message logged.
+ virtual bool AddAnnotations(
+ const ExceptionHandlerProtocol::ClientInformation& info) = 0;
#endif
//! \brief Called on the receipt of a crash dump request from a client for a
@@ -193,6 +200,9 @@
bool HandleAddEvergreenInfoRequest(
const ucred& creds,
const ExceptionHandlerProtocol::ClientInformation& client_info);
+ bool HandleAddAnnotationsRequest(
+ const ucred& creds,
+ const ExceptionHandlerProtocol::ClientInformation& client_info);
#endif
std::unordered_map<int, std::unique_ptr<Event>> clients_;
diff --git a/src/third_party/crashpad/snapshot/linux/process_snapshot_linux.cc b/src/third_party/crashpad/snapshot/linux/process_snapshot_linux.cc
index 32ee101..a731187 100644
--- a/src/third_party/crashpad/snapshot/linux/process_snapshot_linux.cc
+++ b/src/third_party/crashpad/snapshot/linux/process_snapshot_linux.cc
@@ -55,7 +55,8 @@
#if defined(STARBOARD)
bool ProcessSnapshotLinux::Initialize(PtraceConnection* connection,
- VMAddress evergreen_information_address) {
+ VMAddress evergreen_information_address,
+ VMAddress annotations_address) {
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
if (gettimeofday(&snapshot_time_, nullptr) != 0) {
@@ -69,6 +70,15 @@
return false;
}
+ EvergreenAnnotations annotations;
+ if (!memory_range_.Read(
+ annotations_address, sizeof(EvergreenAnnotations), &annotations)) {
+ LOG(ERROR) << "Could not read annotations";
+ } else {
+ AddAnnotation("user_agent_string",
+ std::string(annotations.user_agent_string));
+ }
+
system_.Initialize(&process_reader_, &snapshot_time_);
InitializeThreads();
diff --git a/src/third_party/crashpad/snapshot/linux/process_snapshot_linux.h b/src/third_party/crashpad/snapshot/linux/process_snapshot_linux.h
index 6c5d7a8..c78a709 100644
--- a/src/third_party/crashpad/snapshot/linux/process_snapshot_linux.h
+++ b/src/third_party/crashpad/snapshot/linux/process_snapshot_linux.h
@@ -70,11 +70,14 @@
//! \param[in] connection A connection to the process to snapshot.
//! \param[in] evergreen_information_address An address sent to the handler
//! server that points to a populated EvergreenInfo struct.
+ //! \param[in] annotations_address An address sent to the handler server that
+ //! that points to a populated EvergreenAnnotations struct.
//!
//! \return `true` if the snapshot could be created, `false` otherwise with
//! an appropriate message logged.
bool Initialize(PtraceConnection* connnection,
- VMAddress evergreen_information_address);
+ VMAddress evergreen_information_address,
+ VMAddress annotations_address);
#endif
//! \brief Finds the thread whose stack contains \a stack_address.
diff --git a/src/third_party/crashpad/util/linux/exception_handler_client.cc b/src/third_party/crashpad/util/linux/exception_handler_client.cc
index b1df219..de27275 100644
--- a/src/third_party/crashpad/util/linux/exception_handler_client.cc
+++ b/src/third_party/crashpad/util/linux/exception_handler_client.cc
@@ -89,6 +89,11 @@
const ExceptionHandlerProtocol::ClientInformation& info) {
return SendEvergreenInfoRequest(info);
}
+
+bool ExceptionHandlerClient::SendAnnotations(
+ const ExceptionHandlerProtocol::ClientInformation& info) {
+ return SendAddAnnotationsRequest(info);
+}
#endif
int ExceptionHandlerClient::RequestCrashDump(
@@ -161,6 +166,17 @@
UnixCredentialSocket::SendMsg(server_sock_, &message, sizeof(message));
return true;
}
+
+bool ExceptionHandlerClient::SendAddAnnotationsRequest(
+ const ExceptionHandlerProtocol::ClientInformation& info) {
+ ExceptionHandlerProtocol::ClientToServerMessage message;
+ message.type =
+ ExceptionHandlerProtocol::ClientToServerMessage::kTypeAddAnnotations;
+ message.client_info = info;
+
+ UnixCredentialSocket::SendMsg(server_sock_, &message, sizeof(message));
+ return true;
+}
#endif
int ExceptionHandlerClient::SendCrashDumpRequest(
diff --git a/src/third_party/crashpad/util/linux/exception_handler_client.h b/src/third_party/crashpad/util/linux/exception_handler_client.h
index 3a27739..e2f6398 100644
--- a/src/third_party/crashpad/util/linux/exception_handler_client.h
+++ b/src/third_party/crashpad/util/linux/exception_handler_client.h
@@ -57,6 +57,12 @@
//! \return `true` on success or `false` on failure.
bool SendEvergreenInfo(
const ExceptionHandlerProtocol::ClientInformation& info);
+
+ //! \brief Sends EvergreenAnnotations to the ExceptionHandlerServer.
+ //!
+ //! \param[in] info Information to about this client.
+ //! \return `true` on success or `false` on failure.
+ bool SendAnnotations(const ExceptionHandlerProtocol::ClientInformation& info);
#endif
//! \brief Request a crash dump from the ExceptionHandlerServer.
@@ -83,6 +89,9 @@
#if defined(STARBOARD)
bool SendEvergreenInfoRequest(
const ExceptionHandlerProtocol::ClientInformation& info);
+
+ bool SendAddAnnotationsRequest(
+ const ExceptionHandlerProtocol::ClientInformation& info);
#endif
int SendCrashDumpRequest(
const ExceptionHandlerProtocol::ClientInformation& info,
diff --git a/src/third_party/crashpad/util/linux/exception_handler_protocol.cc b/src/third_party/crashpad/util/linux/exception_handler_protocol.cc
index 2220ecf..b139017 100644
--- a/src/third_party/crashpad/util/linux/exception_handler_protocol.cc
+++ b/src/third_party/crashpad/util/linux/exception_handler_protocol.cc
@@ -25,7 +25,8 @@
#endif // OS_LINUX
#if defined(STARBOARD)
,
- evergreen_information_address(0)
+ evergreen_information_address(0),
+ annotations_address(0)
#endif
{
}
diff --git a/src/third_party/crashpad/util/linux/exception_handler_protocol.h b/src/third_party/crashpad/util/linux/exception_handler_protocol.h
index 9edd82a..dbfaeca 100644
--- a/src/third_party/crashpad/util/linux/exception_handler_protocol.h
+++ b/src/third_party/crashpad/util/linux/exception_handler_protocol.h
@@ -56,6 +56,10 @@
//! \brief The address in the client's address space of an EvergreenInfo
//! struct, or 0 if there is no such struct.
VMAddress evergreen_information_address;
+
+ //! \brief The address in the client's address space of an
+ //! EvergreenAnnotations struct, or 0 if there is no such struct.
+ VMAddress annotations_address;
#endif
#if defined(OS_LINUX)
@@ -93,7 +97,8 @@
#if defined(STARBOARD)
//! \brief Used to store Evergreen mapping info in the handler for use at
//! time of crash.
- kTypeAddEvergreenInfo
+ kTypeAddEvergreenInfo,
+ kTypeAddAnnotations,
#endif
};
diff --git a/src/third_party/crashpad/wrapper/wrapper.cc b/src/third_party/crashpad/wrapper/wrapper.cc
index 8b8a18d..0ab09e5 100644
--- a/src/third_party/crashpad/wrapper/wrapper.cc
+++ b/src/third_party/crashpad/wrapper/wrapper.cc
@@ -206,6 +206,11 @@
return client->SendEvergreenInfoToHandler(evergreen_info);
}
+bool AddAnnotationsToCrashpad(EvergreenAnnotations annotations) {
+ ::crashpad::CrashpadClient* client = GetCrashpadClient();
+ return client->SendAnnotationsToHandler(annotations);
+}
+
} // namespace wrapper
} // namespace crashpad
} // namespace third_party
diff --git a/src/third_party/crashpad/wrapper/wrapper.h b/src/third_party/crashpad/wrapper/wrapper.h
index c2b366f..57ab399 100644
--- a/src/third_party/crashpad/wrapper/wrapper.h
+++ b/src/third_party/crashpad/wrapper/wrapper.h
@@ -25,6 +25,8 @@
bool AddEvergreenInfoToCrashpad(EvergreenInfo evergreen_info);
+bool AddAnnotationsToCrashpad(EvergreenAnnotations annotations);
+
} // namespace wrapper
} // namespace crashpad
} // namespace third_party
diff --git a/src/third_party/crashpad/wrapper/wrapper_stub.cc b/src/third_party/crashpad/wrapper/wrapper_stub.cc
index 6158445..f2aeb8a 100644
--- a/src/third_party/crashpad/wrapper/wrapper_stub.cc
+++ b/src/third_party/crashpad/wrapper/wrapper_stub.cc
@@ -24,6 +24,10 @@
return false;
}
+bool AddAnnotationsToCrashpad(EvergreenAnnotations annotations) {
+ return false;
+}
+
} // namespace wrapper
} // namespace crashpad
} // namespace third_party
\ No newline at end of file
diff --git a/src/third_party/libdav1d/METATDATA b/src/third_party/libdav1d/METADATA
similarity index 100%
rename from src/third_party/libdav1d/METATDATA
rename to src/third_party/libdav1d/METADATA
diff --git a/src/third_party/libdav1d/include/config.asm b/src/third_party/libdav1d/include/config.asm
new file mode 100644
index 0000000..862e441
--- /dev/null
+++ b/src/third_party/libdav1d/include/config.asm
@@ -0,0 +1,21 @@
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# NOTE:
+# libdav1d's build process will generate this file and populate it with defines
+# that configure the project appropriately and set compilation flags. These
+# flags are migrated into Cobalt's gyp and ninja build process which makes this
+# file superfluous. However, we keep |config.asm| since the file is referenced
+# in the includes for several source files and to keep the overall code changes
+# low for ease of rebasing upstream changes from libdav1d.
diff --git a/src/third_party/libdav1d/include/config.h b/src/third_party/libdav1d/include/config.h
index e69de29..f0bbc12 100644
--- a/src/third_party/libdav1d/include/config.h
+++ b/src/third_party/libdav1d/include/config.h
@@ -0,0 +1,21 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// NOTE:
+// libdav1d's build process will generate this file and populate it with defines
+// that configure the project appropriately and set compilation flags. These
+// flags are migrated into Cobalt's gyp and ninja build process which makes this
+// file superfluous. However, we keep |config.h| since the file is referenced
+// in the includes for several source files and to keep the overall code changes
+// low for ease of rebasing upstream changes from libdav1d.
diff --git a/src/third_party/libdav1d/libdav1d.gyp b/src/third_party/libdav1d/libdav1d.gyp
index 862555d..db10ba0 100644
--- a/src/third_party/libdav1d/libdav1d.gyp
+++ b/src/third_party/libdav1d/libdav1d.gyp
@@ -1,13 +1,55 @@
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
{
+ 'conditions': [
+ ['sb_api_version >= 12', {
+ 'variables': {
+ 'DAV1D_ARCH_AARCH64': 'SB_IS(ARCH_ARM64)',
+ 'DAV1D_ARCH_ARM': 'SB_IS(ARCH_ARM)',
+ 'DAV1D_ARCH_PPC64LE': 'SB_IS(ARCH_PPC)',
+ 'DAV1D_ARCH_X86': '(SB_IS(ARCH_X86) || SB_IS(ARCH_X64))',
+ 'DAV1D_ARCH_X86_32': 'SB_IS(ARCH_X86)',
+ 'DAV1D_ARCH_X86_64': 'SB_IS(ARCH_X64)',
+ 'DAV1D_ENDIANNESS_BIG': 'SB_IS(BIG_ENDIAN)',
+ },
+ }, {
+ 'variables': {
+ 'DAV1D_ARCH_AARCH64': '(SB_IS_ARCH_ARM & SB_IS_64_BIT)',
+ 'DAV1D_ARCH_ARM': '(SB_IS_ARCH_ARM & SB_IS_32_BIT)',
+ 'DAV1D_ARCH_PPC64LE': 'SB_IS_ARCH_PPC',
+ 'DAV1D_ARCH_X86': 'SB_IS_ARCH_X86',
+ 'DAV1D_ARCH_X86_32': '(SB_IS_ARCH_X86 & SB_IS_32_BIT)',
+ 'DAV1D_ARCH_X86_64': '(SB_IS_ARCH_X86 & SB_IS_64_BIT)',
+ 'DAV1D_ENDIANNESS_BIG': 'SB_IS_BIG_ENDIAN',
+ },
+ }],
+ ],
+
'variables': {
+ 'enable_asm': 0,
+
'libdav1d_dir': '<(DEPTH)/third_party/libdav1d',
'libdav1d_include_dirs': [
- '<(libdav1d_dir)/',
- '<(libdav1d_dir)/include',
- '<(libdav1d_dir)/include/dav1d',
+ '<(libdav1d_dir)/',
+ '<(libdav1d_dir)/include',
+ '<(libdav1d_dir)/include/dav1d',
],
+ # BITDEPTH-specific sources
+ # Note: these files must be compiled with -DBITDEPTH=8 or 16
'libdav1d_bitdepth_sources': [
'src/cdef.h',
'src/cdef_apply.h',
@@ -36,6 +78,53 @@
'src/recon.h',
'src/recon_tmpl.c',
],
+
+ # ARCH-specific sources
+ 'libdav1d_arch_sources': [],
+ 'libdav1d_arch_bitdepth_sources': [],
+
+ # ASM-specific sources
+ 'libdav1d_base_asm_sources': [],
+ 'libdav1d_bitdepth8_asm_sources': [],
+ 'libdav1d_bitdepth16_asm_sources': [],
+
+ 'conditions': [
+ ['enable_asm == 1 and (target_arch == "x86" or target_arch == "x64")', {
+ 'libdav1d_arch_sources': [
+ 'src/x86/cpu.c',
+ 'src/x86/cpu.h',
+ 'src/x86/msac.h',
+ ],
+ 'libdav1d_arch_bitdepth_sources': [
+ 'src/x86/cdef_init_tmpl.c',
+ 'src/x86/film_grain_init_tmpl.c',
+ 'src/x86/ipred_init_tmpl.c',
+ 'src/x86/itx_init_tmpl.c',
+ 'src/x86/loopfilter_init_tmpl.c',
+ 'src/x86/looprestoration_init_tmpl.c',
+ 'src/x86/mc_init_tmpl.c',
+ ],
+ 'libdav1d_base_asm_sources': [
+ 'src/x86/cpuid.asm',
+ 'src/x86/msac.asm',
+ ],
+ 'libdav1d_bitdepth8_asm_sources': [
+ 'src/x86/cdef.asm',
+ 'src/x86/cdef_sse.asm',
+ 'src/x86/film_grain.asm',
+ 'src/x86/ipred.asm',
+ 'src/x86/ipred_ssse3.asm',
+ 'src/x86/itx.asm',
+ 'src/x86/itx_ssse3.asm',
+ 'src/x86/loopfilter.asm',
+ 'src/x86/loopfilter_ssse3.asm',
+ 'src/x86/looprestoration.asm',
+ 'src/x86/looprestoration_ssse3.asm',
+ 'src/x86/mc.asm',
+ 'src/x86/mc_ssse3.asm',
+ ],
+ }],
+ ],
},
'target_defaults': {
@@ -43,25 +132,64 @@
'<(DEPTH)/third_party/libdav1d/',
'<(DEPTH)/third_party/libdav1d/include',
'<(DEPTH)/third_party/libdav1d/include/dav1d',
+ '<(DEPTH)/third_party/libdav1d/src',
],
- # These values are determined by the configure script in the project,
- # and included via the |build/config.h| file however in this case we
- # determine these using gyp and inject them into the compilation.
'defines': [
- 'ARCH_AARCH64=SB_IS(ARCH_ARM64)',
- 'ARCH_ARM=SB_IS(ARCH_ARM)',
- 'ARCH_X86=(SB_IS(ARCH_X86) || SB_IS(ARCH_X64))',
- 'ARCH_X86_32=SB_IS(ARCH_X86)',
- 'ARCH_X86_64=SB_IS(ARCH_X64)',
+ 'ARCH_AARCH64=<(DAV1D_ARCH_AARCH64)',
+ 'ARCH_ARM=<(DAV1D_ARCH_ARM)',
+ 'ARCH_PPC64LE=<(DAV1D_ARCH_PPC64LE)',
+ 'ARCH_X86=<(DAV1D_ARCH_X86)',
+ 'ARCH_X86_32=<(DAV1D_ARCH_X86_32)',
+ 'ARCH_X86_64=<(DAV1D_ARCH_X86_64)',
'CONFIG_16BPC=1',
'CONFIG_8BPC=1',
'CONFIG_LOG=1',
- 'ENDIANNESS_BIG=SB_IS(BIG_ENDIAN)',
- 'HAVE_ASM=0',
- 'HAVE_CLOCK_GETTIME=1',
- 'HAVE_POSIX_MEMALIGN=1',
- 'HAVE_UNISTD_H=1',
- 'STACK_ALIGNMENT=32'
+ 'ENDIANNESS_BIG=<(DAV1D_ENDIANNESS_BIG)',
+ 'HAVE_ASM=<(enable_asm)',
+ ],
+
+ 'conditions': [
+ ['target_os == "linux"', {
+ 'defines':[
+ 'HAVE_CLOCK_GETTIME=1',
+ 'HAVE_POSIX_MEMALIGN=1',
+ 'HAVE_UNISTD_H=1',
+ 'STACK_ALIGNMENT=32',
+ ]
+ }],
+
+ ['target_os == "win"', {
+ 'include_dirs': [
+ # for stdatomic.h
+ '<(DEPTH)/third_party/libdav1d/include/compat/msvc',
+ ],
+ 'defines':[
+ 'HAVE_ALIGNED_MALLOC=1',
+ 'HAVE_IO_H=1',
+ 'UNICODE=1',
+ '_CRT_DECLARE_NONSTDC_NAMES=1',
+ '_UNICODE=1',
+ '_WIN32_WINNT=0x0601',
+ '__USE_MINGW_ANSI_STDIO=1',
+ 'fseeko=_fseeki64',
+ 'ftello=_ftelli64',
+ ],
+ 'cflags_cc': [
+ '-wd4028',
+ '-wd4996',
+ ],
+ 'conditions': [
+ ['target_arch == "x64"', {
+ 'defines': [
+ 'STACK_ALIGNMENT=16',
+ ],
+ }, {
+ 'defines': [
+ 'STACK_ALIGNMENT=4',
+ ],
+ }],
+ ],
+ }],
],
},
@@ -82,8 +210,22 @@
'BITDEPTH=16',
],
'sources': [
+ '<@(libdav1d_arch_bitdepth_sources)',
'<@(libdav1d_bitdepth_sources)',
- ]
+ ],
+ },
+ {
+ 'target_name': 'libdav1d_bitdepth16_asm',
+ 'type': 'static_library',
+ 'defines': [
+ 'BITDEPTH=16',
+ ],
+ 'includes': [
+ 'libdav1d_asm.gypi'
+ ],
+ 'sources': [
+ '<@(libdav1d_bitdepth16_asm_sources)',
+ ],
},
{
'target_name': 'libdav1d_bitdepth8',
@@ -92,18 +234,43 @@
'BITDEPTH=8',
],
'sources': [
+ '<@(libdav1d_arch_bitdepth_sources)',
'<@(libdav1d_bitdepth_sources)',
- ]
+ ],
},
{
- 'target_name': 'libdav1d_no_asm',
+ 'target_name': 'libdav1d_bitdepth8_asm',
+ 'type': 'static_library',
+ 'defines': [
+ 'BITDEPTH=8',
+ ],
+ 'includes': [
+ 'libdav1d_asm.gypi'
+ ],
+ 'sources': [
+ '<@(libdav1d_bitdepth8_asm_sources)',
+ ],
+ },
+ {
+ 'target_name': 'libdav1d_base',
'type': 'static_library',
'sources': [
'src/cpu.c',
'src/cpu.h',
'src/msac.c',
'src/msac.h',
- ]
+ ],
+ },
+ {
+ 'target_name': 'libdav1d_base_asm',
+ 'type': 'static_library',
+ 'includes': [
+ 'libdav1d_asm.gypi'
+ ],
+ 'sources': [
+ '<@(libdav1d_arch_sources)',
+ '<@(libdav1d_base_asm_sources)'
+ ],
},
{
'target_name': 'libdav1d',
@@ -151,18 +318,20 @@
'src/wedge.h',
],
'dependencies': [
+ '<(DEPTH)/starboard/common/common.gyp:common',
+ 'libdav1d_base',
+ 'libdav1d_base_asm',
'libdav1d_bitdepth16',
+ 'libdav1d_bitdepth16_asm',
'libdav1d_bitdepth8',
+ 'libdav1d_bitdepth8_asm',
'libdav1d_entrypoint',
- 'libdav1d_no_asm',
],
'direct_dependent_settings': {
'include_dirs': [
- '<(DEPTH)/third_party/libdav1d/',
- '<(DEPTH)/third_party/libdav1d/include',
- '<(DEPTH)/third_party/libdav1d/include/dav1d',
+ '<@(libdav1d_include_dirs)',
],
},
},
- ]
+ ],
}
diff --git a/src/third_party/libdav1d/libdav1d_asm.gypi b/src/third_party/libdav1d/libdav1d_asm.gypi
new file mode 100644
index 0000000..a52b895
--- /dev/null
+++ b/src/third_party/libdav1d/libdav1d_asm.gypi
@@ -0,0 +1,103 @@
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{
+ 'conditions': [
+ ['target_arch == "x64" or target_arch == "x86"', {
+ 'variables': {
+ 'DAV1D_IS_PIC': '1',
+ },
+ 'conditions': [
+ ['target_arch == "x64"', {
+ 'variables': {
+ 'DAV1D_ARCH_X86_32': '0',
+ 'DAV1D_ARCH_X86_64': '1',
+ }
+ }, {
+ 'variables': {
+ 'DAV1D_ARCH_X86_32': '1',
+ 'DAV1D_ARCH_X86_64': '0',
+ }
+ }]
+ ],
+ }],
+ ['target_os == "linux"', {
+ 'variables': {
+ 'DAV1D_STACK_ALIGNMENT': '32',
+ },
+ }],
+ ['target_os == "win"', {
+ 'conditions': [
+ ['target_arch == "x64"', {
+ 'variables': {
+ 'DAV1D_STACK_ALIGNMENT': '16',
+ }
+ }, {
+ 'variables': {
+ 'DAV1D_STACK_ALIGNMENT': '4',
+ }
+ }]
+ ],
+ }],
+ ],
+ 'rules': [{
+ 'rule_name': 'assemble',
+ 'extension': 'asm',
+ 'inputs': [],
+ 'outputs': [
+ '<(PRODUCT_DIR)/obj/third_party/libdav1d/<(RULE_INPUT_ROOT).asm.o',
+ ],
+
+ 'conditions': [
+ ['target_os == "win"', {
+ 'variables': {
+ 'NASM_EXECUTABLE': 'nasm.exe',
+ 'NASM_OUTPUT_FORMAT' : 'win',
+ },
+ }],
+ ['target_os == "linux"', {
+ 'variables': {
+ 'NASM_EXECUTABLE': '/usr/bin/nasm',
+ 'NASM_OUTPUT_FORMAT': 'elf',
+ },
+ }],
+ ['target_arch == "x86"', {
+ 'variables': {
+ 'NASM_OUTPUT_SIZE': '32'
+ },
+ }, {
+ 'variables': {
+ 'NASM_OUTPUT_SIZE': '64'
+ },
+ }],
+ ],
+
+ 'action': [
+ '<(NASM_EXECUTABLE)',
+ '-f<(NASM_OUTPUT_FORMAT)<(NASM_OUTPUT_SIZE)',
+ '-DSTACK_ALIGNMENT=<(DAV1D_STACK_ALIGNMENT)',
+ '-DARCH_X86_32=<(DAV1D_ARCH_X86_32)',
+ '-DARCH_X86_64=<(DAV1D_ARCH_X86_64)',
+ '-DPIC=<(DAV1D_IS_PIC)',
+ '-I<(DEPTH)/third_party/libdav1d/include',
+ '-I<(DEPTH)/third_party/libdav1d/src',
+ '-MQ<(PRODUCT_DIR)/$out',
+ '-MF<(PRODUCT_DIR)/$out.ndep',
+ '-o<(PRODUCT_DIR)/$out',
+ '<(RULE_INPUT_PATH)',
+ ],
+ 'process_outputs_as_sources': 1,
+ 'message': 'Building <(RULE_INPUT_ROOT).asm.o',
+ }],
+}
diff --git a/src/third_party/web_platform_tests/fetch/api/request/request-consume-empty.html b/src/third_party/web_platform_tests/fetch/api/request/request-consume-empty.html
index c3ca838..a5bc141 100644
--- a/src/third_party/web_platform_tests/fetch/api/request/request-consume-empty.html
+++ b/src/third_party/web_platform_tests/fetch/api/request/request-consume-empty.html
@@ -69,12 +69,18 @@
}, "Consume request's body as " + bodyType);
}
+/* Cobalt doesn't support FormData request body
var formData = new FormData();
+*/
checkRequestWithNoBody("text", checkBodyText);
+/* Cobalt doesn't support Blob request body
checkRequestWithNoBody("blob", checkBodyBlob);
+*/
checkRequestWithNoBody("arrayBuffer", checkBodyArrayBuffer);
checkRequestWithNoBody("json", checkBodyJSON);
+/* Cobalt doesn't support FormData request body
checkRequestWithNoBody("formData", checkBodyFormData);
+*/
function checkRequestWithEmptyBody(bodyType, body, asText) {
promise_test(function(test) {
@@ -98,9 +104,11 @@
checkRequestWithEmptyBody("text", "", false);
checkRequestWithEmptyBody("blob", new Blob([], { "type" : "text/plain" }), true);
checkRequestWithEmptyBody("text", "", true);
+/* Cobalt doesn't support URLSearchParams and FormData request body
checkRequestWithEmptyBody("URLSearchParams", new URLSearchParams(""), true);
// FIXME: This test assumes that the empty string be returned but it is not clear whether that is right. See https://github.com/w3c/web-platform-tests/pull/3950.
checkRequestWithEmptyBody("FormData", new FormData(), true);
+*/
checkRequestWithEmptyBody("ArrayBuffer", new ArrayBuffer(), true);
</script>
</body>
diff --git a/src/third_party/web_platform_tests/fetch/api/request/request-consume.html b/src/third_party/web_platform_tests/fetch/api/request/request-consume.html
index 9ac7041..880f471 100644
--- a/src/third_party/web_platform_tests/fetch/api/request/request-consume.html
+++ b/src/third_party/web_platform_tests/fetch/api/request/request-consume.html
@@ -69,11 +69,13 @@
assert_false(request.bodyUsed, "bodyUsed is false at init");
return checkBodyText(request, expected);
}, "Consume " + bodyType + " request's body as text");
+/* Cobalt doesn't support Blob request body
promise_test(function(test) {
var request = new Request("", {"method": "POST", "body": body });
assert_false(request.bodyUsed, "bodyUsed is false at init");
return checkBodyBlob(request, expected);
}, "Consume " + bodyType + " request's body as blob");
+*/
promise_test(function(test) {
var request = new Request("", {"method": "POST", "body": body });
assert_false(request.bodyUsed, "bodyUsed is false at init");
@@ -114,6 +116,7 @@
checkRequestBody(new Float32Array(getArrayBuffer()), string, "Float32Array");
checkRequestBody(new DataView(getArrayBufferWithZeros(), 1, 8), string, "DataView");
+/* Cobalt doesn't support FormData request body
promise_test(function(test) {
var formData = new FormData();
formData.append("name", "value")
@@ -121,6 +124,7 @@
assert_false(request.bodyUsed, "bodyUsed is false at init");
return checkBodyFormData(request, formData);
}, "Consume FormData request's body as FormData");
+*/
function checkBlobResponseBody(blobBody, blobData, bodyType, checkFunction) {
promise_test(function(test) {
@@ -130,11 +134,15 @@
}, "Consume blob response's body as " + bodyType);
}
+/* Cobalt doesn't support Blob request body
checkBlobResponseBody(blob, textData, "blob", checkBodyBlob);
+*/
checkBlobResponseBody(blob, textData, "text", checkBodyText);
checkBlobResponseBody(blob, textData, "json", checkBodyJSON);
checkBlobResponseBody(blob, textData, "arrayBuffer", checkBodyArrayBuffer);
+/* Cobalt doesn't support Blob request body
checkBlobResponseBody(new Blob([""]), "", "blob (empty blob as input)", checkBodyBlob);
+*/
var goodJSONValues = ["null", "1", "true", "\"string\""];
goodJSONValues.forEach(function(value) {
diff --git a/src/third_party/zlib/contrib/optimizations/chunkcopy.h b/src/third_party/zlib/contrib/optimizations/chunkcopy.h
index 38ba0ed..c856b6a 100644
--- a/src/third_party/zlib/contrib/optimizations/chunkcopy.h
+++ b/src/third_party/zlib/contrib/optimizations/chunkcopy.h
@@ -406,6 +406,26 @@
return chunkcopy_lapped_relaxed(out, dist, len);
}
+/* TODO(cavalcanti): see crbug.com/1110083. */
+static inline unsigned char FAR* chunkcopy_safe_ugly(unsigned char FAR* out,
+ unsigned dist,
+ unsigned len,
+ unsigned char FAR* limit) {
+#if defined(__GNUC__) && !defined(__clang__)
+ /* Speed is the same as using chunkcopy_safe
+ w/ GCC on ARM (tested gcc 6.3 and 7.5) and avoids
+ undefined behavior.
+ */
+ return chunkcopy_core_safe(out, out - dist, len, limit);
+#elif defined(__clang__) && defined(ARMV8_OS_ANDROID) && !defined(__aarch64__)
+ /* Seems to perform better on 32bit (i.e. Android). */
+ return chunkcopy_core_safe(out, out - dist, len, limit);
+#else
+ /* Seems to perform better on 64bit. */
+ return chunkcopy_lapped_safe(out, dist, len, limit);
+#endif
+}
+
/*
* The chunk-copy code above deals with writing the decoded DEFLATE data to
* the output with SIMD methods to increase decode speed. Reading the input
diff --git a/src/third_party/zlib/contrib/optimizations/inffast_chunk.c b/src/third_party/zlib/contrib/optimizations/inffast_chunk.c
index 4099edf..4bacbc4 100644
--- a/src/third_party/zlib/contrib/optimizations/inffast_chunk.c
+++ b/src/third_party/zlib/contrib/optimizations/inffast_chunk.c
@@ -276,7 +276,7 @@
the main copy is near the end.
*/
out = chunkunroll_relaxed(out, &dist, &len);
- out = chunkcopy_safe(out, out - dist, len, limit);
+ out = chunkcopy_safe_ugly(out, dist, len, limit);
} else {
/* from points to window, so there is no risk of
overlapping pointers requiring memset-like behaviour
diff --git a/src/v8/METADATA b/src/v8/METADATA
new file mode 100644
index 0000000..8522c17
--- /dev/null
+++ b/src/v8/METADATA
@@ -0,0 +1,22 @@
+name: "v8"
+description:
+ "Subtree at v8."
+ "v8 is Google's JavaScript engine developed for The Chromium Project. Cobalt "
+ "uses v8 as its primary JavaScript engine. v8 works closely with Cobalt's "
+ "script interface and templated bindings code."
+third_party {
+ url {
+ type: LOCAL_SOURCE
+ value: "/v8_mirror"
+ }
+ url {
+ type: GIT
+ value: "https://chromium.googlesource.com/v8/v8"
+ }
+ version: "1e6ebba9def991e536159fa658bf5564c054733f"
+ last_upgrade_date {
+ year: 2019
+ month: 8
+ day: 26
+ }
+}