Import Cobalt 4.16134 Change-Id: Ibd3aeff170baa0d15baae38e16a1dd59b5387c7a
diff --git a/src/base/atomicops.h b/src/base/atomicops.h index 230a601..6d04858 100644 --- a/src/base/atomicops.h +++ b/src/base/atomicops.h
@@ -31,6 +31,10 @@ #include "base/basictypes.h" #include "build/build_config.h" +#if defined(OS_STARBOARD) +#include "starboard/atomic.h" +#endif // defined(OS_STARBOARD) + #if (defined(OS_WIN) && defined(ARCH_CPU_64_BITS)) || defined(__LB_XB360__) || defined(__LB_XB1__) // windows.h #defines this (only on x64). This causes problems because the // public API also uses MemoryBarrier at the public name for this fence. So, on @@ -43,6 +47,12 @@ namespace base { namespace subtle { +#if defined(OS_STARBOARD) +typedef SbAtomic32 Atomic32; +#if defined(ARCH_CPU_64_BITS) +typedef SbAtomic64 Atomic64; +#endif // defined(ARCH_CPU_64_BITS) +#else typedef int32 Atomic32; #ifdef ARCH_CPU_64_BITS // We need to be able to go between Atomic64 and AtomicWord implicitly. This @@ -55,6 +65,7 @@ typedef intptr_t Atomic64; #endif #endif +#endif // defined(OS_STARBOARD) // Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or // Atomic64 routines below, depending on your architecture.
diff --git a/src/base/file_util_unittest.cc b/src/base/file_util_unittest.cc index 6f4e111..81fdcc7 100644 --- a/src/base/file_util_unittest.cc +++ b/src/base/file_util_unittest.cc
@@ -211,7 +211,16 @@ // Simple function to dump some text into a new file. void CreateTextFile(const FilePath& filename, const std::wstring& contents) { -#if defined(__LB_PS3__) +#if defined(OS_STARBOARD) + SbFile file = + SbFileOpen(filename.value().c_str(), kSbFileCreateAlways | kSbFileWrite, + NULL /*out_created*/, NULL /*out_error*/); + EXPECT_TRUE(file != kSbFileInvalid); + std::string utf8 = WideToUTF8(contents); + int bytes_written = SbFileWrite(file, utf8.c_str(), utf8.length()); + EXPECT_TRUE(bytes_written == utf8.length()); + SbFileClose(file); +#elif defined(__LB_PS3__) FILE *file = fopen(filename.value().c_str(), "w"); ASSERT_TRUE(file != NULL); fputws(contents.c_str(), file); @@ -232,18 +241,35 @@ ASSERT_TRUE(file.is_open()); file << contents; file.close(); -#endif +#endif // defined(OS_STARBOARD) } // Simple function to take out some text from a file. std::wstring ReadTextFile(const FilePath& filename) { +#if defined(OS_STARBOARD) + SbFile file = + SbFileOpen(filename.value().c_str(), kSbFileOpenOnly | kSbFileRead, + NULL /*out_created*/, NULL /*out_error*/); + EXPECT_TRUE(file != kSbFileInvalid); + char utf8_buffer[64] = {0}; + int bytes_read = + SbFileRead(file, utf8_buffer, SB_ARRAY_SIZE_INT(utf8_buffer)); + EXPECT_TRUE(bytes_read >= 0); + SbFileClose(file); + std::wstring result; + bool did_convert = + UTF8ToWide(utf8_buffer, SbStringGetLength(utf8_buffer), &result); + EXPECT_TRUE(did_convert); + return result; +#elif defined(__LB_PS3__) wchar_t contents[64]; -#if defined(__LB_PS3__) FILE *file = fopen(filename.value().c_str(), "r"); EXPECT_TRUE(file != NULL); fgetws(contents, arraysize(contents), file); fclose(file); + return std::wstring(contents); #elif defined(__LB_WIIU__) + wchar_t contents[64]; char mb_sequence_buffer[64]; int fd = open(filename.value().c_str(), O_RDONLY); EXPECT_TRUE(fd >= 0); @@ -253,14 +279,16 @@ const char * mb_sequence = mb_sequence_buffer; size_t nbytes = mbsrtowcs(contents, &mb_sequence, sizeof(contents), NULL); EXPECT_TRUE(mb_sequence == NULL); + return std::wstring(contents); #else + wchar_t contents[64]; std::wifstream file; file.open(filename.value().c_str()); EXPECT_TRUE(file.is_open()); file.getline(contents, arraysize(contents)); file.close(); -#endif return std::wstring(contents); +#endif } #if defined(OS_WIN)
diff --git a/src/base/i18n/file_util_icu.cc b/src/base/i18n/file_util_icu.cc index fc07d13..0dd1523 100644 --- a/src/base/i18n/file_util_icu.cc +++ b/src/base/i18n/file_util_icu.cc
@@ -159,7 +159,7 @@ // Windows uses UTF-16 encoding for filenames. U16_NEXT(file_name->data(), cursor, static_cast<int>(file_name->length()), code_point); -#elif defined(OS_POSIX) || defined(OS_STARBAORD) +#elif defined(OS_POSIX) || defined(OS_STARBOARD) // Linux doesn't actually define an encoding. It basically allows anything // except for a few special ASCII characters. unsigned char cur_char = static_cast<unsigned char>((*file_name)[cursor++]);
diff --git a/src/base/location.cc b/src/base/location.cc index b6ded2c..fe8581a 100644 --- a/src/base/location.cc +++ b/src/base/location.cc
@@ -92,9 +92,11 @@ BASE_EXPORT const void* GetProgramCounter() { #if defined(COMPILER_MSVC) return _ReturnAddress(); +#elif defined(COMPILER_SNC) + return __builtin_return_address(0); #elif defined(COMPILER_GCC) && !defined(__LB_PS3__) && !defined(__LB_WIIU__) return __builtin_extract_return_addr(__builtin_return_address(0)); -#endif // COMPILER_GCC +#endif // defined(COMPILER_MSVC) return NULL; }
diff --git a/src/base/stl_util.h b/src/base/stl_util.h index c612769..483fd53 100644 --- a/src/base/stl_util.h +++ b/src/base/stl_util.h
@@ -7,7 +7,7 @@ #include <algorithm> #include <functional> -#if defined(__LB_SHELL__) // TODO: Starboard? +#if defined(__LB_SHELL__) || defined(STARBOARD) #include <iterator> #endif #include <string>
diff --git a/src/base/test/test_file_util_starboard.cc b/src/base/test/test_file_util_starboard.cc index ef4cdad..f8127c6 100644 --- a/src/base/test/test_file_util_starboard.cc +++ b/src/base/test/test_file_util_starboard.cc
@@ -36,7 +36,7 @@ // Mostly a verbatim copy of CopyDirectory bool CopyRecursiveDirNoCache(const FilePath& source_dir, const FilePath& dest_dir) { - char top_dir[PATH_MAX]; + char top_dir[SB_FILE_MAX_PATH]; if (base::strlcpy(top_dir, source_dir.value().c_str(), arraysize(top_dir)) >= arraysize(top_dir)) { return false;
diff --git a/src/base/third_party/nspr/prcpucfg_starboard.h b/src/base/third_party/nspr/prcpucfg_starboard.h index 5bdf40d..3aaa298 100644 --- a/src/base/third_party/nspr/prcpucfg_starboard.h +++ b/src/base/third_party/nspr/prcpucfg_starboard.h
@@ -55,7 +55,7 @@ # define IS_64 #endif -#if SB_IS(ARCH_PPC) && SB_IS(32_BIT) +#if SB_IS(ARCH_PPC) #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc index 20bae1a..38699b2 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc
@@ -222,6 +222,15 @@ JSBool set_arbitraryProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<ArbitraryInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc index 67e7e5f..2599232 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc
@@ -220,6 +220,15 @@ JSBool set_booleanProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<BooleanTypeTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc index 8ebf68c..fce394f 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc
@@ -224,6 +224,15 @@ JSBool set_callbackAttribute( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<CallbackFunctionInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -277,6 +286,15 @@ JSBool set_nullableCallbackAttribute( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<CallbackFunctionInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc index e510b12..468faf3 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc
@@ -224,6 +224,15 @@ JSBool set_callbackAttribute( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<CallbackInterfaceInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc index 12fda2f..2610e00 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc
@@ -223,6 +223,15 @@ JSBool set_enabledAttribute( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<ConditionalInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -278,6 +287,15 @@ JSBool set_disabledAttribute( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<ConditionalInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc index 4524287..7092da5 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc
@@ -220,6 +220,15 @@ JSBool set_property( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<DOMStringTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -335,6 +344,15 @@ JSBool set_nullIsEmptyProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<DOMStringTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -388,6 +406,15 @@ JSBool set_undefinedIsEmptyProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<DOMStringTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -441,6 +468,15 @@ JSBool set_nullableUndefinedIsEmptyProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<DOMStringTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc index 647ef55..1c88411 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
@@ -436,6 +436,15 @@ JSBool set_propertyOnDerivedClass( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<DerivedGetterSetterInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc index 5fb88e5..5e3f995 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc
@@ -222,6 +222,15 @@ JSBool set_disabledProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<DisabledInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc index ea07296..38c99f1 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc
@@ -231,6 +231,15 @@ JSBool set_enumProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<EnumerationInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc index b23ae9f..6ab9aab 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc
@@ -222,6 +222,15 @@ JSBool set_attributeThrowsException( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<ExceptionsInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGarbageCollectionTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsGarbageCollectionTestInterface.cc index df1b224..9ba778e 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGarbageCollectionTestInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGarbageCollectionTestInterface.cc
@@ -233,6 +233,15 @@ JSBool set_previous( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<GarbageCollectionTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -286,6 +295,15 @@ JSBool set_next( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<GarbageCollectionTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc index 7f0e6b7..e027bc0 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
@@ -436,6 +436,15 @@ JSBool set_propertyOnBaseClass( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NamedIndexedGetterInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc index c7945ee..9b732fe 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc
@@ -224,6 +224,15 @@ JSBool set_nestedForwardingAttribute( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NestedPutForwardsInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc index a2d5622..e7533d8 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc
@@ -224,6 +224,15 @@ JSBool set_nullableBooleanProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NullableTypesTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -277,6 +286,15 @@ JSBool set_nullableNumericProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NullableTypesTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -330,6 +348,15 @@ JSBool set_nullableStringProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NullableTypesTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -383,6 +410,15 @@ JSBool set_nullableObjectProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NullableTypesTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc index c64b5d9..eb604d8 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc
@@ -220,6 +220,15 @@ JSBool set_byteProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NumericTypesTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -273,6 +282,15 @@ JSBool set_octetProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NumericTypesTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -326,6 +344,15 @@ JSBool set_shortProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NumericTypesTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -379,6 +406,15 @@ JSBool set_unsignedShortProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NumericTypesTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -432,6 +468,15 @@ JSBool set_longProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NumericTypesTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -485,6 +530,15 @@ JSBool set_unsignedLongProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NumericTypesTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -538,6 +592,15 @@ JSBool set_longLongProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NumericTypesTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -591,6 +654,15 @@ JSBool set_unsignedLongLongProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NumericTypesTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -644,6 +716,15 @@ JSBool set_doubleProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NumericTypesTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -697,6 +778,15 @@ JSBool set_unrestrictedDoubleProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<NumericTypesTestInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc index d25a5b1..77631f6 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc
@@ -232,6 +232,15 @@ JSBool set_arbitraryObject( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<ObjectTypeBindingsInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -316,6 +325,15 @@ JSBool set_derivedInterface( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<ObjectTypeBindingsInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -369,6 +387,15 @@ JSBool set_objectProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<ObjectTypeBindingsInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc index 325c6fd..dfc7ffa 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc
@@ -224,6 +224,15 @@ JSBool set_forwardingAttribute( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<PutForwardsInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc index 30cfd0a..428506c 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc
@@ -220,6 +220,15 @@ JSBool set_theStringifierAttribute( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<StringifierAttributeInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc index a81efa7..e6cf73b 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc
@@ -228,6 +228,15 @@ JSBool set_unionProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<UnionTypesInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -281,6 +290,15 @@ JSBool set_unionWithNullableMemberProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<UnionTypesInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -334,6 +352,15 @@ JSBool set_nullableUnionProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<UnionTypesInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context); @@ -387,6 +414,15 @@ JSBool set_unionBaseProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<UnionTypesInterface>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc index 673aed8..212ecca 100644 --- a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc +++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc
@@ -413,6 +413,15 @@ JSBool set_windowProperty( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { + MozjsGlobalEnvironment* global_environment = + static_cast<MozjsGlobalEnvironment*>(JS_GetContextPrivate(context)); + WrapperFactory* wrapper_factory = global_environment->wrapper_factory(); + if (!wrapper_factory->DoesObjectImplementInterface( + object, base::GetTypeId<Window>())) { + MozjsExceptionState exception(context); + exception.SetSimpleException(script::kDoesNotImplementInterface); + return false; + } MozjsExceptionState exception_state(context); JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/mozjs/templates/interface.cc.template b/src/cobalt/bindings/mozjs/templates/interface.cc.template index 2dfc9eb..3307b67 100644 --- a/src/cobalt/bindings/mozjs/templates/interface.cc.template +++ b/src/cobalt/bindings/mozjs/templates/interface.cc.template
@@ -485,6 +485,7 @@ JSBool set_{{attribute.idl_name}}( JSContext* context, JS::HandleObject object, JS::HandleId id, JSBool strict, JS::MutableHandleValue vp) { +{{ check_if_object_implements_interface() }} {{ nonstatic_function_prologue(impl_class)}} {% endif %} {#- attribute.is_static #} {{ set_attribute_implementation(attribute, impl_class) -}}
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc index 72f1dd8..f19023b 100644 --- a/src/cobalt/browser/browser_module.cc +++ b/src/cobalt/browser/browser_module.cc
@@ -21,11 +21,13 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/debug/trace_event.h" +#include "base/lazy_instance.h" #include "base/logging.h" #include "base/path_service.h" #include "base/stl_util.h" #include "base/string_number_conversions.h" #include "base/string_split.h" +#include "base/time.h" #include "cobalt/base/cobalt_paths.h" #include "cobalt/base/source_location.h" #include "cobalt/base/tokens.h" @@ -37,11 +39,70 @@ #include "cobalt/dom/keycode.h" #include "cobalt/h5vcc/h5vcc.h" #include "cobalt/input/input_device_manager_fuzzer.h" +#include "starboard/atomic.h" +#include "starboard/system.h" +#include "starboard/time.h" + +#if defined(OS_STARBOARD) +#include "starboard/configuration.h" +#if SB_HAS(CORE_DUMP_HANDLER_SUPPORT) +#define HANDLE_CORE_DUMP +#include "starboard/ps4/core_dump_handler.h" +#endif // SB_HAS(CORE_DUMP_HANDLER_SUPPORT) +#endif // OS_STARBOARD namespace cobalt { + +#if defined(COBALT_CHECK_SUBMITDONE_TIMEOUT) +namespace timestamp { +// This is a temporary workaround. +extern SbAtomic64 g_last_submit_done_timestamp; +} // namespace timestamp + +namespace { +struct NonTrivialGlobalVariables { + NonTrivialGlobalVariables(); + + SbAtomic64* last_submit_done_timestamp; +}; + +NonTrivialGlobalVariables::NonTrivialGlobalVariables() { + last_submit_done_timestamp = &cobalt::timestamp::g_last_submit_done_timestamp; + SbAtomicNoBarrier_Exchange64(last_submit_done_timestamp, + static_cast<SbAtomic64>(SbTimeGetNow())); +} + +base::LazyInstance<NonTrivialGlobalVariables> non_trivial_global_variables = + LAZY_INSTANCE_INITIALIZER; + +} // namespace +#endif + namespace browser { namespace { +#if defined(COBALT_CHECK_SUBMITDONE_TIMEOUT) +// Timeout for last submitDone(). +const int kLastSubmitDoneTimeoutSeconds = 15; + +// Polling interval for timeout_polling_thread_. +const int kRenderTimeOutPollingDelaySeconds = 1; + +// Minimum number of continuous times the timeout expirations. This is used to +// prevent unintended behavior in situations such as when returning from +// suspended state. Note that the timeout response trigger will be delayed +// after the actual timeout expiration by this value times the polling delay. +const int kMinimumContinuousRenderTimeoutExpirations = 2; + +// Name for timeout_polling_thread_. +const char* kTimeoutPollingThreadName = "TimeoutPolling"; + +// This specifies the percentage of calls to OnRenderTimeout() that result in a +// call to OnError(). +const int kRenderTimeoutErrorPercentage = 99; + +#endif + // This constant defines the maximum rate at which the layout engine will // refresh over time. Since there is little benefit in performing a layout // faster than the display's refresh rate, we set this to 60Hz. @@ -169,8 +230,25 @@ h5vcc_url_handler_(this, system_window, account_manager)), web_module_options_(options.web_module_options), has_resumed_(true, false), +#if defined(COBALT_CHECK_SUBMITDONE_TIMEOUT) + timeout_polling_thread_(kTimeoutPollingThreadName), + render_timeout_count_(0), +#endif will_quit_(false), suspended_(false) { +#if defined(HANDLE_CORE_DUMP) + on_error_triggered_count_ = 0; + recovery_mechanism_triggered_count_ = 0; + submit_done_timeout_count_ = 0; + SbCoreDumpRegisterHandler(BrowserModule::CoreDumpHandler, this); +#endif +#if defined(COBALT_CHECK_SUBMITDONE_TIMEOUT) + timeout_polling_thread_.Start(); + timeout_polling_thread_.message_loop()->PostDelayedTask( + FROM_HERE, base::Bind(&BrowserModule::OnPollForRenderTimeout, + base::Unretained(this), url), + base::TimeDelta::FromSeconds(kRenderTimeOutPollingDelaySeconds)); +#endif // Setup our main web module to have the H5VCC API injected into it. DCHECK(!ContainsKey(web_module_options_.injected_window_attributes, "h5vcc")); h5vcc::H5vcc::Settings h5vcc_settings; @@ -216,6 +294,9 @@ BrowserModule::~BrowserModule() { DCHECK_EQ(MessageLoop::current(), self_message_loop_); +#if defined(HANDLE_CORE_DUMP) + SbCoreDumpUnregisterHandler(BrowserModule::CoreDumpHandler, this); +#endif } void BrowserModule::Navigate(const GURL& url) { @@ -234,6 +315,20 @@ base::SourceLocation("[object BrowserModule]", 1, 1)); } +#if defined(HANDLE_CORE_DUMP) +// static +void BrowserModule::CoreDumpHandler(void* browser_module_as_void) { + BrowserModule* browser_module = + static_cast<BrowserModule*>(browser_module_as_void); + SbCoreDumpLogInteger("BrowserModule.on_error_triggered_count_", + browser_module->on_error_triggered_count_); + SbCoreDumpLogInteger("BrowserModule.recovery_mechanism_triggered_count_", + browser_module->recovery_mechanism_triggered_count_); + SbCoreDumpLogInteger("BrowserModule.submit_done_timeout_count_", + browser_module->submit_done_timeout_count_); +} +#endif + void BrowserModule::NavigateInternal(const GURL& url) { DCHECK_EQ(MessageLoop::current(), self_message_loop_); @@ -273,6 +368,13 @@ array_buffer_allocator_.get(); options.dom_settings_options.array_buffer_cache = array_buffer_cache_.get(); #endif // defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR) +#if defined(ENABLE_FAKE_MICROPHONE) + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kFakeMicrophone) || + CommandLine::ForCurrentProcess()->HasSwitch(switches::kInputFuzzer)) { + options.dom_settings_options.enable_fake_microphone = true; + } +#endif // defined(ENABLE_FAKE_MICROPHONE) + options.image_cache_capacity_multiplier_when_playing_video = COBALT_IMAGE_CACHE_CAPACITY_MULTIPLIER_WHEN_PLAYING_VIDEO; web_module_.reset(new WebModule( @@ -479,6 +581,9 @@ } void BrowserModule::OnError(const GURL& url, const std::string& error) { +#if defined(HANDLE_CORE_DUMP) + on_error_triggered_count_++; +#endif LOG(ERROR) << error; std::string url_string = "h5vcc://network-failure"; @@ -706,5 +811,52 @@ } #endif // OS_STARBOARD +#if defined(COBALT_CHECK_SUBMITDONE_TIMEOUT) +void BrowserModule::OnPollForRenderTimeout(const GURL& url) { + SbTime last_submitdone_timestamp = static_cast<SbTime>(SbAtomicAcquire_Load64( + non_trivial_global_variables.Get().last_submit_done_timestamp)); + base::Time last_submitdone = + base::Time::FromSbTime(last_submitdone_timestamp); + bool timeout_expiration = + base::Time::Now() - + base::TimeDelta::FromSeconds(kLastSubmitDoneTimeoutSeconds) > + last_submitdone; + bool timeout_response_trigger = false; + if (timeout_expiration) { + // The timeout only triggers if the timeout expiration has been detected + // without interruption at least kMinimumContinuousRenderTimeoutExpirations + // times. + ++render_timeout_count_; + timeout_response_trigger = + render_timeout_count_ >= kMinimumContinuousRenderTimeoutExpirations; + } else { + render_timeout_count_ = 0; + } + + if (timeout_response_trigger) { +#if defined(HANDLE_CORE_DUMP) + submit_done_timeout_count_++; +#endif + SbAtomicNoBarrier_Exchange64( + non_trivial_global_variables.Get().last_submit_done_timestamp, + static_cast<SbAtomic64>(kSbTimeMax)); + if (SbSystemGetRandomUInt64() < + kRenderTimeoutErrorPercentage * (UINT64_MAX / 100)) { + OnError(url, std::string("Rendering Timeout")); +#if defined(HANDLE_CORE_DUMP) + recovery_mechanism_triggered_count_++; +#endif + } else { + SB_DLOG(INFO) << "Received OnRenderTimeout, ignoring by random chance."; + } + } else { + timeout_polling_thread_.message_loop()->PostDelayedTask( + FROM_HERE, base::Bind(&BrowserModule::OnPollForRenderTimeout, + base::Unretained(this), url), + base::TimeDelta::FromSeconds(kRenderTimeOutPollingDelaySeconds)); + } +} +#endif + } // namespace browser } // namespace cobalt
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h index 82322b3..5adc43d 100644 --- a/src/cobalt/browser/browser_module.h +++ b/src/cobalt/browser/browser_module.h
@@ -23,6 +23,7 @@ #include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" +#include "base/threading/thread.h" #include "cobalt/account/account_manager.h" #include "cobalt/base/message_queue.h" #include "cobalt/browser/h5vcc_url_handler.h" @@ -48,6 +49,10 @@ #include "cobalt/debug/debug_server.h" #endif // ENABLE_DEBUG_CONSOLE +#if defined(OS_STARBOARD) +#include "starboard/configuration.h" +#endif + namespace cobalt { namespace browser { @@ -121,6 +126,15 @@ void Resume(); private: +#if defined(OS_STARBOARD) +#if SB_HAS(CORE_DUMP_HANDLER_SUPPORT) + static void CoreDumpHandler(void* browser_module_as_void); + int on_error_triggered_count_; + int recovery_mechanism_triggered_count_; + int submit_done_timeout_count_; +#endif +#endif + // Recreates web module with the given URL. void NavigateInternal(const GURL& url); @@ -210,6 +224,11 @@ // Process all messages queued into the |render_tree_submission_queue_|. void ProcessRenderTreeSubmissionQueue(); +#if defined(COBALT_CHECK_SUBMITDONE_TIMEOUT) + // Poll for render timeout. Called from timeout_polling_thread_. + void OnPollForRenderTimeout(const GURL& url); +#endif + // TODO: // WeakPtr usage here can be avoided if BrowserModule has a thread to // own where it can ensure that its tasks are all resolved when it is @@ -326,6 +345,14 @@ // Reset when the browser is paused, signalled to resume. base::WaitableEvent has_resumed_; +#if defined(COBALT_CHECK_SUBMITDONE_TIMEOUT) + base::Thread timeout_polling_thread_; + + // Counts the number of continuous render timeout expirations. This value is + // updated and used from OnPollForRenderTimeout. + int render_timeout_count_; +#endif + // Set when the application is about to quit. May be set from a thread other // than the one hosting this object, and read from another. bool will_quit_;
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc index 73b734a..f0315b7 100644 --- a/src/cobalt/browser/switches.cc +++ b/src/cobalt/browser/switches.cc
@@ -45,6 +45,10 @@ // Additional base directory for accessing web files via file://. const char kExtraWebFileDir[] = "web_file_path"; +// If this flag is set, fake microphone will be used to mock the user voice +// input. +const char kFakeMicrophone[] = "fake_microphone"; + // Setting this switch causes all certificate errors to be ignored. const char kIgnoreCertificateErrors[] = "ignore_certificate_errors";
diff --git a/src/cobalt/browser/switches.h b/src/cobalt/browser/switches.h index fe02027..70fe5cd 100644 --- a/src/cobalt/browser/switches.h +++ b/src/cobalt/browser/switches.h
@@ -29,6 +29,7 @@ extern const char kDisableWebmVp9[]; extern const char kEnableWebDriver[]; extern const char kExtraWebFileDir[]; +extern const char kFakeMicrophone[]; extern const char kIgnoreCertificateErrors[]; extern const char kInputFuzzer[]; extern const char kMinLogLevel[];
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id index d690671..6f60c5d 100644 --- a/src/cobalt/build/build.id +++ b/src/cobalt/build/build.id
@@ -1 +1 @@ -13403 \ No newline at end of file +16134 \ No newline at end of file
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi index 8ba37eb..31b8c5f 100644 --- a/src/cobalt/build/config/base.gypi +++ b/src/cobalt/build/config/base.gypi
@@ -95,9 +95,11 @@ 'lbshell_root%': '<(DEPTH)/lbshell', # The relative path from src/ to the directory containing the - # starboard_platform.gyp file, or the empty string if not an autodiscovered - # platform. - 'starboard_path%': '', + # starboard_platform.gyp file. It is currently set to + # 'starboard/<(target_arch)' to make semi-starboard platforms work. + # TODO: Set the default value to '' once all semi-starboard platforms are + # moved to starboard. + 'starboard_path%': 'starboard/<(target_arch)', # The source of EGL and GLES headers and libraries. # Valid values (case and everything sensitive!): @@ -449,6 +451,7 @@ 'cobalt_copy_debug_console': 1, 'cobalt_copy_test_data': 1, 'enable_about_scheme': 1, + 'enable_fake_microphone': 1, 'enable_file_scheme': 1, 'enable_network_logging': 1, 'enable_remote_debugging%': 1, @@ -461,6 +464,7 @@ 'cobalt_copy_debug_console': 0, 'cobalt_copy_test_data': 0, 'enable_about_scheme': 0, + 'enable_fake_microphone': 0, 'enable_file_scheme': 0, 'enable_network_logging': 0, 'enable_remote_debugging%': 0,
diff --git a/src/cobalt/build/gyp_cobalt b/src/cobalt/build/gyp_cobalt index 0e60bb9..030de0f 100755 --- a/src/cobalt/build/gyp_cobalt +++ b/src/cobalt/build/gyp_cobalt
@@ -218,6 +218,7 @@ full_starboard_path = platforms[platform] assert full_starboard_path[:len(source_tree_dir)] == source_tree_dir starboard_path = full_starboard_path[len(source_tree_dir) + 1:] + starboard_path.replace(os.sep, '/') assert starboard_path[0] not in [ os.sep, os.altsep ] variables['starboard_path'] = starboard_path _AppendVariables(variables, self.common_args)
diff --git a/src/cobalt/content/ssl/certs/0a775a30.0 b/src/cobalt/content/ssl/certs/0a775a30.0 new file mode 100644 index 0000000..7d540a4 --- /dev/null +++ b/src/cobalt/content/ssl/certs/0a775a30.0
@@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout +736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2A +DDL24CejQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFuk +fCPAlaUs3L6JbyO5o91lAFJekazInXJ0glMLfalAvWhgxeG4VDvBNhcl2MG9AjEA +njWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOaKaqW04MjyaR7YbPMAuhd +-----END CERTIFICATE-----
diff --git a/src/cobalt/content/ssl/certs/1001acf7.0 b/src/cobalt/content/ssl/certs/1001acf7.0 new file mode 100644 index 0000000..5496703 --- /dev/null +++ b/src/cobalt/content/ssl/certs/1001acf7.0
@@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy +MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl +cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM +f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vX +mX7wCl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7 +zUjwTcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0P +fyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtc +vfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4 +Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUsp +zBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOO +Rc92wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYW +k70paDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+ +DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgF +lQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBADiW +Cu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1 +d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6Z +XPYfcX3v73svfuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZR +gyFmxhE+885H7pwoHyXa/6xmld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3 +d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9bgsiG1eGZbYwE8na6SfZu6W0eX6Dv +J4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq4BjFbkerQUIpm/Zg +DdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWErtXvM ++SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyy +F62ARPBopY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9 +SQ98POyDGCBDTtWTurQ0sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdws +E3PYJ/HQcu51OyLemGhmW/HGY0dVHLqlCFF1pkgl +-----END CERTIFICATE-----
diff --git a/src/cobalt/content/ssl/certs/626dceaf.0 b/src/cobalt/content/ssl/certs/626dceaf.0 new file mode 100644 index 0000000..984f1d1 --- /dev/null +++ b/src/cobalt/content/ssl/certs/626dceaf.0
@@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy +MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl +cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv +CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3Kg +GjSY6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9Bu +XvAuMC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOd +re7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXu +PuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1 +mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K +8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqj +x5RWIr9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsR +nTKaG73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0 +kzCqgc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9Ok +twIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBALZp +8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT +vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiT +z9D2PGcDFWEJ+YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiA +pJiS4wGWAqoC7o87xdFtCjMwc3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvb +pxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3DaWsYDQvTtN6LwG1BUSw7YhN4ZKJmB +R64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5rn/WkhLx3+WuXrD5R +RaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56GtmwfuNmsk +0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC +5AwiWVIQ7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiF +izoHCBy69Y9Vmhh1fuXsgWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLn +yOd/xCxgXS/Dr55FBcOEArf9LAhST4Ldo/DUhgkC +-----END CERTIFICATE-----
diff --git a/src/cobalt/content/ssl/certs/a3418fda.0 b/src/cobalt/content/ssl/certs/a3418fda.0 new file mode 100644 index 0000000..07372d3 --- /dev/null +++ b/src/cobalt/content/ssl/certs/a3418fda.0
@@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu +hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/l +xKvRHYqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0 +CMRw3J5QdCHojXohw0+WbhXRIjVhLfoIN+4Zba3bssx9BzT1YBkstTTZbyACMANx +sbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11xzPKwTdb+mciUqXWi4w== +-----END CERTIFICATE-----
diff --git a/src/cobalt/dom/dom_settings.cc b/src/cobalt/dom/dom_settings.cc index 1eca2a2..dce0f0b 100644 --- a/src/cobalt/dom/dom_settings.cc +++ b/src/cobalt/dom/dom_settings.cc
@@ -31,6 +31,7 @@ script::GlobalEnvironment* global_environment, const Options& options) : max_dom_element_depth_(max_dom_element_depth), + enable_fake_microphone_(options.enable_fake_microphone), fetcher_factory_(fetcher_factory), network_module_(network_module), window_(window),
diff --git a/src/cobalt/dom/dom_settings.h b/src/cobalt/dom/dom_settings.h index 5bd39e1..0b99ea4 100644 --- a/src/cobalt/dom/dom_settings.h +++ b/src/cobalt/dom/dom_settings.h
@@ -45,7 +45,10 @@ public: // Hold optional settings for DOMSettings. struct Options { - Options() : array_buffer_allocator(NULL), array_buffer_cache(NULL) {} + Options() + : array_buffer_allocator(NULL), + array_buffer_cache(NULL), + enable_fake_microphone(false) {} // ArrayBuffer allocates its memory on the heap by default and ArrayBuffers // may occupy a lot of memory. It is possible to provide an allocator via @@ -56,6 +59,8 @@ // amount of ArrayBuffer inside main memory. So we have provide the // following cache to manage ArrayBuffer in main memory. ArrayBuffer::Cache* array_buffer_cache; + // Use fake microphone if this flag is set to true. + bool enable_fake_microphone; }; DOMSettings(const int max_dom_element_depth, @@ -70,6 +75,7 @@ ~DOMSettings() OVERRIDE; int max_dom_element_depth() { return max_dom_element_depth_; } + bool enable_fake_microphone() const { return enable_fake_microphone_; } void set_window(const scoped_refptr<Window>& window) { window_ = window; } scoped_refptr<Window> window() const { return window_; } @@ -106,6 +112,7 @@ private: const int max_dom_element_depth_; + const bool enable_fake_microphone_; loader::FetcherFactory* fetcher_factory_; network::NetworkModule* network_module_; scoped_refptr<Window> window_;
diff --git a/src/cobalt/dom_parser/html_decoder_test.cc b/src/cobalt/dom_parser/html_decoder_test.cc index 92736ea..70019a1 100644 --- a/src/cobalt/dom_parser/html_decoder_test.cc +++ b/src/cobalt/dom_parser/html_decoder_test.cc
@@ -382,6 +382,34 @@ EXPECT_EQ("💩", text->data()); } +TEST_F(HTMLDecoderTest, CanParseUTF8SplitInChunks) { + const std::string input = "<p>💩</p>"; + + for (size_t first_chunk_size = 0; first_chunk_size < input.length(); + first_chunk_size++) { + root_ = new dom::Element(document_, base::Token("element")); + html_decoder_.reset(new HTMLDecoder( + document_, root_, NULL, kDOMMaxElementDepth, source_location_, + base::Closure(), base::Bind(&MockErrorCallback::Run, + base::Unretained(&mock_error_callback_)), + true)); + + // This could cut the input in the middle of a UTF8 character. + html_decoder_->DecodeChunk(input.c_str(), first_chunk_size); + html_decoder_->DecodeChunk(input.c_str() + first_chunk_size, + input.length() - first_chunk_size); + html_decoder_->Finish(); + + dom::Element* element = root_->first_element_child(); + ASSERT_TRUE(element); + EXPECT_EQ("p", element->tag_name()); + + dom::Text* text = element->first_child()->AsText(); + ASSERT_TRUE(text); + EXPECT_EQ("💩", text->data()); + } +} + // Misnested tags: <b><i></b></i> // https://www.w3.org/TR/html5/syntax.html#misnested-tags:-b-i-/b-/i //
diff --git a/src/cobalt/dom_parser/libxml_html_parser_wrapper.cc b/src/cobalt/dom_parser/libxml_html_parser_wrapper.cc index 968dbe5..7a05cb8 100644 --- a/src/cobalt/dom_parser/libxml_html_parser_wrapper.cc +++ b/src/cobalt/dom_parser/libxml_html_parser_wrapper.cc
@@ -110,7 +110,10 @@ return; } - if (CheckInputAndUpdateSeverity(data, size) == kFatal) { + std::string current_chunk; + PreprocessChunk(data, size, ¤t_chunk); + + if (max_severity() == kFatal) { return; } @@ -120,9 +123,10 @@ // when used for setting an element's innerHTML. htmlEmitImpliedRootLevelParagraph(0); - html_parser_context_ = htmlCreatePushParserCtxt( - &html_sax_handler, this, data, static_cast<int>(size), - NULL /*filename*/, XML_CHAR_ENCODING_UTF8); + html_parser_context_ = + htmlCreatePushParserCtxt(&html_sax_handler, this, current_chunk.c_str(), + static_cast<int>(current_chunk.size()), + NULL /*filename*/, XML_CHAR_ENCODING_UTF8); if (!html_parser_context_) { static const char kErrorUnableCreateParser[] = @@ -135,7 +139,8 @@ } } else { DCHECK(html_parser_context_); - htmlParseChunk(html_parser_context_, data, static_cast<int>(size), + htmlParseChunk(html_parser_context_, current_chunk.c_str(), + static_cast<int>(current_chunk.size()), 0 /*do not terminate*/); } }
diff --git a/src/cobalt/dom_parser/libxml_parser_wrapper.cc b/src/cobalt/dom_parser/libxml_parser_wrapper.cc index ef19c762..a86753e 100644 --- a/src/cobalt/dom_parser/libxml_parser_wrapper.cc +++ b/src/cobalt/dom_parser/libxml_parser_wrapper.cc
@@ -19,6 +19,8 @@ #include "base/logging.h" #include "base/string_util.h" #include "base/stringprintf.h" +#include "base/third_party/icu/icu_utf.h" +#include "base/utf_string_conversion_utils.h" #include "cobalt/base/tokens.h" #include "cobalt/dom/cdata_section.h" #include "cobalt/dom/comment.h" @@ -314,34 +316,32 @@ node_stack_.top()->AppendChild(new dom::CDATASection(document_, value)); } -LibxmlParserWrapper::IssueSeverity -LibxmlParserWrapper::CheckInputAndUpdateSeverity(const char* data, - size_t size) { - if (max_severity_ == kFatal) { - return max_severity_; - } - +void LibxmlParserWrapper::PreprocessChunk(const char* data, size_t size, + std::string* current_chunk) { + DCHECK(current_chunk); // Check the total input size. total_input_size_ += size; if (total_input_size_ > kMaxTotalInputSize) { static const char kMessageInputTooLong[] = "Parser input is too long."; OnParsingIssue(kFatal, kMessageInputTooLong); - return max_severity_; + return; } // Check the encoding of the input. - if (!IsStringUTF8(std::string(data, size))) { + std::string input = next_chunk_start_ + std::string(data, size); + TruncateUTF8ToByteSize(input, input.size(), current_chunk); + next_chunk_start_ = input.substr(current_chunk->size()); + if (!IsStringUTF8(*current_chunk)) { + current_chunk->clear(); static const char kMessageInputNotUTF8[] = "Parser input contains non-UTF8 characters."; OnParsingIssue(kFatal, kMessageInputNotUTF8); - return max_severity_; + return; } #if defined(HANDLE_CORE_DUMP) libxml_parser_wrapper_log.Get().IncrementParsedBytes(static_cast<int>(size)); #endif - - return max_severity_; } } // namespace dom_parser
diff --git a/src/cobalt/dom_parser/libxml_parser_wrapper.h b/src/cobalt/dom_parser/libxml_parser_wrapper.h index 98d210e..4c5e233 100644 --- a/src/cobalt/dom_parser/libxml_parser_wrapper.h +++ b/src/cobalt/dom_parser/libxml_parser_wrapper.h
@@ -121,8 +121,10 @@ // Returns true when the input is a full document, false when it's a fragment. bool IsFullDocument() { return document_ == parent_node_; } - // Checks the input, updates and returns the maximum issue severity. - IssueSeverity CheckInputAndUpdateSeverity(const char* data, size_t size); + // Preprocesses the input chunk and updates the max error severity level. + // Sets current chunk if successful. + void PreprocessChunk(const char* data, size_t size, + std::string* current_chunk); const scoped_refptr<dom::Document>& document() { return document_; } const base::SourceLocation& first_chunk_location() { @@ -136,6 +138,8 @@ return node_stack_; } + IssueSeverity max_severity() const { return max_severity_; } + private: // Maximum total input size, as specified in Libxml's value // XML_MAX_TEXT_LENGTH in parserInternals.h. @@ -154,6 +158,7 @@ IssueSeverity max_severity_; size_t total_input_size_; + std::string next_chunk_start_; std::stack<scoped_refptr<dom::Node> > node_stack_; DISALLOW_COPY_AND_ASSIGN(LibxmlParserWrapper);
diff --git a/src/cobalt/dom_parser/libxml_xml_parser_wrapper.cc b/src/cobalt/dom_parser/libxml_xml_parser_wrapper.cc index 787970d..dfbb290 100644 --- a/src/cobalt/dom_parser/libxml_xml_parser_wrapper.cc +++ b/src/cobalt/dom_parser/libxml_xml_parser_wrapper.cc
@@ -79,14 +79,17 @@ return; } - if (CheckInputAndUpdateSeverity(data, size) == kFatal) { + std::string current_chunk; + PreprocessChunk(data, size, ¤t_chunk); + + if (max_severity() == kFatal) { return; } if (!xml_parser_context_) { - xml_parser_context_ = - xmlCreatePushParserCtxt(&xml_sax_handler, this, data, - static_cast<int>(size), NULL /*filename*/); + xml_parser_context_ = xmlCreatePushParserCtxt( + &xml_sax_handler, this, current_chunk.c_str(), + static_cast<int>(current_chunk.size()), NULL /*filename*/); if (!xml_parser_context_) { static const char kErrorUnableCreateParser[] = @@ -94,7 +97,8 @@ OnParsingIssue(kFatal, kErrorUnableCreateParser); } } else { - xmlParseChunk(xml_parser_context_, data, static_cast<int>(size), + xmlParseChunk(xml_parser_context_, current_chunk.c_str(), + static_cast<int>(current_chunk.size()), 0 /*do not terminate*/); } }
diff --git a/src/cobalt/speech/endpointer/endpointer.cc b/src/cobalt/speech/endpointer/endpointer.cc index b0c09e9..cabad1a 100644 --- a/src/cobalt/speech/endpointer/endpointer.cc +++ b/src/cobalt/speech/endpointer/endpointer.cc
@@ -9,7 +9,10 @@ using base::Time; namespace { -const int kFrameRate = 50; // 1 frame = 20ms of audio. +// Only send |kFrameSize| of audio data to energy endpointer each time. +// It should be smaller than the samples of audio bus which is passed in +// |ProcessAudio|. +const int kFrameSize = 160; } namespace cobalt { @@ -20,11 +23,9 @@ speech_input_complete_silence_length_us_(-1), audio_frame_time_us_(0), sample_rate_(sample_rate), - frame_size_(0) { + frame_rate_(sample_rate / kFrameSize) { Reset(); - frame_size_ = static_cast<int>(sample_rate / static_cast<float>(kFrameRate)); - speech_input_minimum_length_us_ = static_cast<int64_t>(1.7 * Time::kMicrosecondsPerSecond); speech_input_complete_silence_length_us_ = @@ -36,8 +37,8 @@ // Set the default configuration for Push To Talk mode. EnergyEndpointerParams ep_config; - ep_config.set_frame_period(1.0f / static_cast<float>(kFrameRate)); - ep_config.set_frame_duration(1.0f / static_cast<float>(kFrameRate)); + ep_config.set_frame_period(1.0f / static_cast<float>(frame_rate_)); + ep_config.set_frame_duration(1.0f / static_cast<float>(frame_rate_)); ep_config.set_endpoint_margin(0.2f); ep_config.set_onset_window(0.15f); ep_config.set_speech_on_window(0.4f); @@ -92,6 +93,7 @@ EpStatus Endpointer::ProcessAudio( const ShellAudioBus& audio_bus, float* rms_out) { DCHECK_EQ(audio_bus.channels(), 1); + const size_t num_samples = audio_bus.frames(); const int16_t* audio_data = NULL; @@ -111,19 +113,17 @@ EpStatus ep_status = EP_PRE_SPEECH; - // Process the input data in blocks of frame_size_, dropping any incomplete + // Process the input data in blocks of kFrameSize, dropping any incomplete // frames at the end (which is ok since typically the caller will be recording // audio in multiples of our frame size). int sample_index = 0; - while (static_cast<size_t>(sample_index + frame_size_) <= num_samples) { + while (static_cast<size_t>(sample_index + kFrameSize) <= num_samples) { // Have the endpointer process the frame. - energy_endpointer_.ProcessAudioFrame(audio_frame_time_us_, - audio_data + sample_index, - frame_size_, - rms_out); - sample_index += frame_size_; - audio_frame_time_us_ += (frame_size_ * Time::kMicrosecondsPerSecond) / - sample_rate_; + energy_endpointer_.ProcessAudioFrame( + audio_frame_time_us_, audio_data + sample_index, kFrameSize, rms_out); + sample_index += kFrameSize; + audio_frame_time_us_ += + (kFrameSize * Time::kMicrosecondsPerSecond) / sample_rate_; // Get the status of the endpointer. int64_t ep_time;
diff --git a/src/cobalt/speech/endpointer/endpointer.h b/src/cobalt/speech/endpointer/endpointer.h index b8d46f5..f6c818f 100644 --- a/src/cobalt/speech/endpointer/endpointer.h +++ b/src/cobalt/speech/endpointer/endpointer.h
@@ -100,6 +100,8 @@ return speech_input_complete_; } + int sample_rate() const { return sample_rate_; } + // RMS background noise level in dB. float NoiseLevelDb() const { return energy_endpointer_.GetNoiseLevelDb(); } @@ -147,7 +149,8 @@ bool speech_input_complete_; EnergyEndpointer energy_endpointer_; int sample_rate_; - int32_t frame_size_; + // 1 frame = (1 / frame_rate_) second of audio. + int frame_rate_; }; } // namespace speech
diff --git a/src/cobalt/speech/endpointer_delegate.cc b/src/cobalt/speech/endpointer_delegate.cc new file mode 100644 index 0000000..a3d0444 --- /dev/null +++ b/src/cobalt/speech/endpointer_delegate.cc
@@ -0,0 +1,75 @@ +/* + * Copyright 2016 Google Inc. 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 "cobalt/speech/endpointer_delegate.h" + +#include "base/time.h" + +namespace cobalt { +namespace speech { + +namespace { +const int kEndPointerEstimationTimeInMillisecond = 300; +// If used in noisy conditions, the endpointer should be started and run in the +// EnvironmentEstimation mode, for at least 200ms, before switching to +// UserInputMode. +COMPILE_ASSERT(kEndPointerEstimationTimeInMillisecond >= 200, + in_environment_estimation_mode_for_at_least_200ms); +} // namespace + +EndPointerDelegate::EndPointerDelegate(int sample_rate) + : endpointer_(sample_rate), + num_samples_recorded_(0), + is_first_time_sound_started_(false) {} + +EndPointerDelegate::~EndPointerDelegate() {} + +void EndPointerDelegate::Start() { + num_samples_recorded_ = 0; + is_first_time_sound_started_ = false; + + endpointer_.StartSession(); + endpointer_.SetEnvironmentEstimationMode(); +} + +void EndPointerDelegate::Stop() { endpointer_.EndSession(); } + +bool EndPointerDelegate::IsFirstTimeSoundStarted( + const ShellAudioBus& audio_bus) { + if (is_first_time_sound_started_) { + return false; + } + + num_samples_recorded_ += static_cast<int>(audio_bus.frames()); + if (endpointer_.IsEstimatingEnvironment() && + num_samples_recorded_ * 1000 / endpointer_.sample_rate() > + kEndPointerEstimationTimeInMillisecond) { + // Switch to user input mode. + endpointer_.SetUserInputMode(); + } + + endpointer_.ProcessAudio(audio_bus, NULL); + int64_t ep_time; + EpStatus status = endpointer_.Status(&ep_time); + if (status == EP_POSSIBLE_ONSET) { + is_first_time_sound_started_ = true; + } + + return is_first_time_sound_started_; +} + +} // namespace speech +} // namespace cobalt
diff --git a/src/cobalt/speech/endpointer_delegate.h b/src/cobalt/speech/endpointer_delegate.h new file mode 100644 index 0000000..8a3aafa --- /dev/null +++ b/src/cobalt/speech/endpointer_delegate.h
@@ -0,0 +1,59 @@ +/* + * Copyright 2016 Google Inc. 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. + */ + +#ifndef COBALT_SPEECH_ENDPOINTER_DELEGATE_H_ +#define COBALT_SPEECH_ENDPOINTER_DELEGATE_H_ + +#include "cobalt/speech/endpointer/endpointer.h" +#include "media/base/audio_bus.h" + +namespace cobalt { +namespace speech { + +// Delegate of endpointer for detecting the first time sound started in one +// speech session (from start speaking to end of speaking). +class EndPointerDelegate { + public: + typedef ::media::ShellAudioBus ShellAudioBus; + + explicit EndPointerDelegate(int sample_rate); + ~EndPointerDelegate(); + + // Start endpointer session for sound processing. + void Start(); + // Stop endpointer session. + void Stop(); + + // Return true if it is the first time that the sound started. + bool IsFirstTimeSoundStarted(const ShellAudioBus& audio_bus); + + private: + // Used for detecting sound start event. + Endpointer endpointer_; + // Used for recording the number of samples before notifying that it is the + // first time the sound started. The |endpointer_| should be started and run + // in the EnvironmentEstimation mode if used in noisy conditions for at least + // 200ms before switching to UserInputMode. + int num_samples_recorded_; + + // Record if it is the first time that the sound started. + bool is_first_time_sound_started_; +}; + +} // namespace speech +} // namespace cobalt + +#endif // COBALT_SPEECH_ENDPOINTER_DELEGATE_H_
diff --git a/src/cobalt/speech/mic.h b/src/cobalt/speech/mic.h deleted file mode 100644 index 506632a..0000000 --- a/src/cobalt/speech/mic.h +++ /dev/null
@@ -1,70 +0,0 @@ -/* - * Copyright 2016 Google Inc. 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. - */ - -#ifndef COBALT_SPEECH_MIC_H_ -#define COBALT_SPEECH_MIC_H_ - -#include <string> - -#include "base/callback.h" -#include "media/base/shell_audio_bus.h" - -namespace cobalt { -namespace speech { - -// An abstract class is used for interacting platform specific microphone. -class Mic { - public: - typedef ::media::ShellAudioBus ShellAudioBus; - typedef base::Callback<void(scoped_ptr<ShellAudioBus>)> DataReceivedCallback; - typedef base::Callback<void(void)> CompletionCallback; - typedef base::Callback<void(void)> ErrorCallback; - - virtual ~Mic() {} - - static scoped_ptr<Mic> Create(int sample_rate, - const DataReceivedCallback& data_received, - const CompletionCallback& completion, - const ErrorCallback& error); - - // Multiple calls to Start/Stop are allowed, the implementation should take - // care of multiple calls. The Start/Stop methods are required to be called in - // the same thread. - // Start microphone to receive voice. - virtual void Start() = 0; - // Stop microphone from receiving voice. - virtual void Stop() = 0; - - protected: - Mic(int sample_rate, const DataReceivedCallback& data_received, - const CompletionCallback& completion, const ErrorCallback& error) - : sample_rate_(sample_rate), - data_received_callback_(data_received), - completion_callback_(completion), - error_callback_(error) {} - - int sample_rate_; - const DataReceivedCallback data_received_callback_; - const CompletionCallback completion_callback_; - const ErrorCallback error_callback_; -}; - -std::string GetSpeechAPIKey(); - -} // namespace speech -} // namespace cobalt - -#endif // COBALT_SPEECH_MIC_H_
diff --git a/src/cobalt/speech/mic_linux.cc b/src/cobalt/speech/mic_linux.cc deleted file mode 100644 index d7f6809..0000000 --- a/src/cobalt/speech/mic_linux.cc +++ /dev/null
@@ -1,44 +0,0 @@ -/* - * Copyright 2016 Google Inc. 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 "cobalt/speech/mic.h" - -namespace cobalt { -namespace speech { - -class MicLinux : public Mic { - public: - MicLinux(int sample_rate, const DataReceivedCallback& data_received, - const CompletionCallback& completion, const ErrorCallback& error) - : Mic(sample_rate, data_received, completion, error) {} - - void Start() OVERRIDE { NOTIMPLEMENTED(); } - void Stop() OVERRIDE { NOTIMPLEMENTED(); } -}; - -// static -scoped_ptr<Mic> Mic::Create(int sample_rate, - const DataReceivedCallback& data_received, - const CompletionCallback& completion, - const ErrorCallback& error) { - return make_scoped_ptr<Mic>( - new MicLinux(sample_rate, data_received, completion, error)); -} - -std::string GetSpeechAPIKey() { return ""; } - -} // namespace speech -} // namespace cobalt
diff --git a/src/cobalt/speech/mic_starboard.cc b/src/cobalt/speech/mic_starboard.cc deleted file mode 100644 index c818dab..0000000 --- a/src/cobalt/speech/mic_starboard.cc +++ /dev/null
@@ -1,44 +0,0 @@ -/* - * Copyright 2016 Google Inc. 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 "cobalt/speech/mic.h" - -namespace cobalt { -namespace speech { - -class MicStarboard : public Mic { - public: - MicStarboard(int sample_rate, const DataReceivedCallback& data_received, - const CompletionCallback& completion, const ErrorCallback& error) - : Mic(sample_rate, data_received, completion, error) {} - - void Start() OVERRIDE { NOTIMPLEMENTED(); } - void Stop() OVERRIDE { NOTIMPLEMENTED(); } -}; - -// static -scoped_ptr<Mic> Mic::Create(int sample_rate, - const DataReceivedCallback& data_received, - const CompletionCallback& completion, - const ErrorCallback& error) { - return make_scoped_ptr<Mic>( - new MicStarboard(sample_rate, data_received, completion, error)); -} - -std::string GetSpeechAPIKey() { return ""; } - -} // namespace speech -} // namespace cobalt
diff --git a/src/cobalt/speech/mic_win.cc b/src/cobalt/speech/mic_win.cc deleted file mode 100644 index 80c49fc..0000000 --- a/src/cobalt/speech/mic_win.cc +++ /dev/null
@@ -1,44 +0,0 @@ -/* - * Copyright 2016 Google Inc. 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 "cobalt/speech/mic.h" - -namespace cobalt { -namespace speech { - -class MicWin : public Mic { - public: - MicWin(int sample_rate, const DataReceivedCallback& data_received, - const CompletionCallback& completion, const ErrorCallback& error) - : Mic(sample_rate, data_received, completion, error) {} - - void Start() OVERRIDE { NOTIMPLEMENTED(); } - void Stop() OVERRIDE { NOTIMPLEMENTED(); } -}; - -// static -scoped_ptr<Mic> Mic::Create(int sample_rate, - const DataReceivedCallback& data_received, - const CompletionCallback& completion, - const ErrorCallback& error) { - return make_scoped_ptr<Mic>( - new MicWin(sample_rate, data_received, completion, error)); -} - -std::string GetSpeechAPIKey() { return ""; } - -} // namespace speech -} // namespace cobalt
diff --git a/src/cobalt/speech/microphone.h b/src/cobalt/speech/microphone.h new file mode 100644 index 0000000..3b9e6ae --- /dev/null +++ b/src/cobalt/speech/microphone.h
@@ -0,0 +1,52 @@ +/* + * Copyright 2016 Google Inc. 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. + */ + +#ifndef COBALT_SPEECH_MICROPHONE_H_ +#define COBALT_SPEECH_MICROPHONE_H_ + +#include <string> + +#include "base/memory/scoped_ptr.h" + +namespace cobalt { +namespace speech { + +// An abstract class is used for interacting platform specific microphone. +class Microphone { + public: + virtual ~Microphone() {} + + // Opens microphone port and starts recording audio. + virtual bool Open() = 0; + // Reads audio data from microphone. The return value is the bytes that were + // read from microphone. Negative value indicates a read error. |data_size| is + // the requested read bytes. + virtual int Read(char* out_data, int data_size) = 0; + // Closes microphone port and stops recording audio. + virtual bool Close() = 0; + // Returns the minimum requested bytes per microphone read. + virtual int MinMicrophoneReadInBytes() = 0; + // Returns true if the microphone is valid. + virtual bool IsValid() = 0; + + protected: + Microphone() {} +}; + +} // namespace speech +} // namespace cobalt + +#endif // COBALT_SPEECH_MICROPHONE_H_
diff --git a/src/cobalt/speech/microphone_fake.cc b/src/cobalt/speech/microphone_fake.cc new file mode 100644 index 0000000..7ee601c --- /dev/null +++ b/src/cobalt/speech/microphone_fake.cc
@@ -0,0 +1,137 @@ +/* + * Copyright 2016 Google Inc. 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 "cobalt/speech/microphone_fake.h" + +#if defined(ENABLE_FAKE_MICROPHONE) + +#include <algorithm> + +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/rand_util.h" +#include "starboard/file.h" +#include "starboard/memory.h" +#include "starboard/time.h" + +namespace cobalt { +namespace speech { + +namespace { +const int kMaxBufferSize = 512 * 1024; +const int kMinMicrophoneReadInBytes = 1024; +// The possiblity of microphone creation failed is 1/20. +const int kCreationRange = 20; +// The possiblity of microphone open failed is 1/20. +const int kOpenRange = 20; +// The possiblity of microphone read failed is 1/200. +const int kReadRange = 200; +// The possiblity of microphone close failed is 1/20. +const int kCloseRange = 20; +const int kFailureNumber = 5; + +bool ShouldFail(int range) { + return base::RandGenerator(range) == kFailureNumber; +} + +} // namespace + +MicrophoneFake::MicrophoneFake() + : Microphone(), + file_length_(-1), + read_index_(0), + is_valid_(!ShouldFail(kCreationRange)) { + if (!is_valid_) { + SB_DLOG(WARNING) << "Mocking microphone creation failed."; + return; + } + + FilePath audio_files_path; + SB_CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &audio_files_path)); + audio_files_path = audio_files_path.Append(FILE_PATH_LITERAL("cobalt")) + .Append(FILE_PATH_LITERAL("speech")) + .Append(FILE_PATH_LITERAL("testdata")); + + file_util::FileEnumerator file_enumerator(audio_files_path, + false /* Not recursive */, + file_util::FileEnumerator::FILES); + for (FilePath next = file_enumerator.Next(); !next.empty(); + next = file_enumerator.Next()) { + file_paths_.push_back(next); + } +} + +bool MicrophoneFake::Open() { + if (ShouldFail(kOpenRange)) { + SB_DLOG(WARNING) << "Mocking microphone open failed."; + return false; + } + + SB_DCHECK(file_paths_.size() != 0); + uint64 random_index = base::RandGenerator(file_paths_.size()); + starboard::ScopedFile file(file_paths_[random_index].value().c_str(), + kSbFileOpenOnly | kSbFileRead, NULL, NULL); + SB_DCHECK(file.IsValid()); + int file_buffer_size = + std::min(static_cast<int>(file.GetSize()), kMaxBufferSize); + SB_DCHECK(file_buffer_size > 0); + file_buffer_.reset(new char[file_buffer_size]); + int read_bytes = file.ReadAll(file_buffer_.get(), file_buffer_size); + if (read_bytes < 0) { + return false; + } + + file_length_ = read_bytes; + return true; +} + +int MicrophoneFake::Read(char* out_data, int data_size) { + if (ShouldFail(kReadRange)) { + SB_DLOG(WARNING) << "Mocking microphone read failed."; + return -1; + } + + int copy_bytes = std::min(file_length_ - read_index_, data_size); + SbMemoryCopy(out_data, file_buffer_.get() + read_index_, copy_bytes); + read_index_ += copy_bytes; + if (read_index_ == file_length_) { + read_index_ = 0; + } + + return copy_bytes; +} + +bool MicrophoneFake::Close() { + file_buffer_.reset(); + file_length_ = -1; + read_index_ = 0; + + if (ShouldFail(kCloseRange)) { + SB_DLOG(WARNING) << "Mocking microphone close failed."; + return false; + } + + return true; +} + +int MicrophoneFake::MinMicrophoneReadInBytes() { + return kMinMicrophoneReadInBytes; +} + +} // namespace speech +} // namespace cobalt + +#endif // defined(ENABLE_FAKE_MICROPHONE)
diff --git a/src/cobalt/speech/microphone_fake.h b/src/cobalt/speech/microphone_fake.h new file mode 100644 index 0000000..dd17c1c --- /dev/null +++ b/src/cobalt/speech/microphone_fake.h
@@ -0,0 +1,59 @@ +/* + * Copyright 2016 Google Inc. 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. + */ + +#ifndef COBALT_SPEECH_MICROPHONE_FAKE_H_ +#define COBALT_SPEECH_MICROPHONE_FAKE_H_ + +#include "cobalt/speech/speech_configuration.h" + +#if defined(ENABLE_FAKE_MICROPHONE) + +#include <string> +#include <vector> + +#include "base/file_path.h" +#include "base/memory/scoped_ptr.h" +#include "cobalt/speech/microphone.h" + +namespace cobalt { +namespace speech { + +// Fake microphone to mock the speech input by reading from the pre-recorded +// audio. +class MicrophoneFake : public Microphone { + public: + MicrophoneFake(); + ~MicrophoneFake() SB_OVERRIDE {} + + bool Open() SB_OVERRIDE; + int Read(char* out_data, int data_size) SB_OVERRIDE; + bool Close() SB_OVERRIDE; + int MinMicrophoneReadInBytes() SB_OVERRIDE; + bool IsValid() SB_OVERRIDE { return is_valid_; } + + private: + std::vector<FilePath> file_paths_; + scoped_array<char> file_buffer_; + int file_length_; + int read_index_; + bool is_valid_; +}; + +} // namespace speech +} // namespace cobalt + +#endif // defined(ENABLE_FAKE_MICROPHONE) +#endif // COBALT_SPEECH_MICROPHONE_FAKE_H_
diff --git a/src/cobalt/speech/microphone_manager.cc b/src/cobalt/speech/microphone_manager.cc new file mode 100644 index 0000000..7b491d9 --- /dev/null +++ b/src/cobalt/speech/microphone_manager.cc
@@ -0,0 +1,191 @@ +/* + * Copyright 2016 Google Inc. 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 "cobalt/speech/microphone_manager.h" + +#if defined(ENABLE_FAKE_MICROPHONE) +#include "cobalt/speech/microphone_fake.h" +#endif // defined(ENABLE_FAKE_MICROPHONE) +#if defined(SB_USE_SB_MICROPHONE) +#include "cobalt/speech/microphone_starboard.h" +#endif // defined(SB_USE_SB_MICROPHONE) +#include "cobalt/speech/speech_recognition_error.h" + +namespace cobalt { +namespace speech { + +namespace { +// Size of an audio buffer. +const int kBufferSizeInBytes = 8 * 1024; +// The frequency which we read the data from devices. +const float kMicReadRateInHertz = 60.0f; +} // namespace + +MicrophoneManager::MicrophoneManager(int sample_rate, + const DataReceivedCallback& data_received, + const CompletionCallback& completion, + const ErrorCallback& error, + bool enable_fake_microphone) + : sample_rate_(sample_rate), + data_received_callback_(data_received), + completion_callback_(completion), + error_callback_(error), +#if defined(ENABLE_FAKE_MICROPHONE) + enable_fake_microphone_(enable_fake_microphone), +#endif // defined(ENABLE_FAKE_MICROPHONE) + state_(kStopped), + thread_("microphone_thread") { + UNREFERENCED_PARAMETER(sample_rate_); +#if defined(ENABLE_FAKE_MICROPHONE) + UNREFERENCED_PARAMETER(enable_fake_microphone_); +#else + UNREFERENCED_PARAMETER(enable_fake_microphone); +#endif // defined(ENABLE_FAKE_MICROPHONE) + thread_.StartWithOptions(base::Thread::Options(MessageLoop::TYPE_IO, 0)); +} + +MicrophoneManager::~MicrophoneManager() { + thread_.message_loop()->PostTask( + FROM_HERE, + base::Bind(&MicrophoneManager::DestroyInternal, base::Unretained(this))); +} + +void MicrophoneManager::Open() { + thread_.message_loop()->PostTask( + FROM_HERE, + base::Bind(&MicrophoneManager::OpenInternal, base::Unretained(this))); +} + +void MicrophoneManager::Close() { + thread_.message_loop()->PostTask( + FROM_HERE, + base::Bind(&MicrophoneManager::CloseInternal, base::Unretained(this))); +} + +bool MicrophoneManager::CreateIfNecessary() { + DCHECK(thread_.message_loop_proxy()->BelongsToCurrentThread()); + + if (microphone_) { + return true; + } + +#if defined(SB_USE_SB_MICROPHONE) +#if defined(ENABLE_FAKE_MICROPHONE) + if (enable_fake_microphone_) { + microphone_.reset(new MicrophoneFake()); + } else { + microphone_.reset( + new MicrophoneStarboard(sample_rate_, kBufferSizeInBytes)); + } +#else + microphone_.reset(new MicrophoneStarboard(sample_rate_, kBufferSizeInBytes)); +#endif // defined(ENABLE_FAKE_MICROPHONE) +#endif // defined(SB_USE_SB_MICROPHONE) + + if (microphone_ && microphone_->IsValid()) { + state_ = kStopped; + return true; + } else { + DLOG(WARNING) << "Microphone creation failed."; + microphone_.reset(); + state_ = kError; + error_callback_.Run(new SpeechRecognitionError( + SpeechRecognitionError::kAudioCapture, "No microphone available.")); + return false; + } +} + +void MicrophoneManager::OpenInternal() { + DCHECK(thread_.message_loop_proxy()->BelongsToCurrentThread()); + + // Try to create a valid microphone if necessary. + if (state_ == kStarted || !CreateIfNecessary()) { + return; + } + + DCHECK(microphone_); + if (!microphone_->Open()) { + state_ = kError; + error_callback_.Run(new SpeechRecognitionError( + SpeechRecognitionError::kAborted, "Microphone open failed.")); + return; + } + + poll_mic_events_timer_.emplace(); + // Setup a timer to poll for input events. + poll_mic_events_timer_->Start( + FROM_HERE, base::TimeDelta::FromMicroseconds(static_cast<int64>( + base::Time::kMicrosecondsPerSecond / kMicReadRateInHertz)), + this, &MicrophoneManager::Read); + state_ = kStarted; +} + +void MicrophoneManager::CloseInternal() { + DCHECK(thread_.message_loop_proxy()->BelongsToCurrentThread()); + + if (state_ == kStopped) { + return; + } + + if (poll_mic_events_timer_) { + poll_mic_events_timer_->Stop(); + } + + if (microphone_) { + if (!microphone_->Close()) { + state_ = kError; + error_callback_.Run(new SpeechRecognitionError( + SpeechRecognitionError::kAborted, "Microphone close failed.")); + return; + } + completion_callback_.Run(); + state_ = kStopped; + } +} + +void MicrophoneManager::Read() { + DCHECK(thread_.message_loop_proxy()->BelongsToCurrentThread()); + + DCHECK(state_ == kStarted); + DCHECK(microphone_); + DCHECK(microphone_->MinMicrophoneReadInBytes() <= kBufferSizeInBytes); + + static int16_t samples[kBufferSizeInBytes / sizeof(int16_t)]; + int read_bytes = + microphone_->Read(reinterpret_cast<char*>(samples), kBufferSizeInBytes); + if (read_bytes > 0) { + size_t frames = read_bytes / sizeof(int16_t); + scoped_ptr<ShellAudioBus> output_audio_bus(new ShellAudioBus( + 1, frames, ShellAudioBus::kInt16, ShellAudioBus::kInterleaved)); + output_audio_bus->Assign(ShellAudioBus(1, frames, samples)); + data_received_callback_.Run(output_audio_bus.Pass()); + } else if (read_bytes < 0) { + state_ = kError; + error_callback_.Run(new SpeechRecognitionError( + SpeechRecognitionError::kAborted, "Microphone read failed.")); + poll_mic_events_timer_->Stop(); + } +} + +void MicrophoneManager::DestroyInternal() { + DCHECK(thread_.message_loop_proxy()->BelongsToCurrentThread()); + + microphone_.reset(); + state_ = kStopped; +} + +} // namespace speech +} // namespace cobalt
diff --git a/src/cobalt/speech/microphone_manager.h b/src/cobalt/speech/microphone_manager.h new file mode 100644 index 0000000..e91ca8c --- /dev/null +++ b/src/cobalt/speech/microphone_manager.h
@@ -0,0 +1,89 @@ +/* + * Copyright 2016 Google Inc. 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. + */ + +#ifndef COBALT_SPEECH_MICROPHONE_MANAGER_H_ +#define COBALT_SPEECH_MICROPHONE_MANAGER_H_ + +#include "cobalt/speech/speech_configuration.h" + +#include "base/callback.h" +#include "base/optional.h" +#include "base/threading/thread.h" +#include "base/timer.h" +#include "cobalt/dom/event.h" +#include "cobalt/speech/microphone.h" +#include "media/base/shell_audio_bus.h" + +namespace cobalt { +namespace speech { + +// This class is used for microphone creation, control and destruction. It has +// a self-managed poller to fetch audio data from microphone. +class MicrophoneManager { + public: + typedef ::media::ShellAudioBus ShellAudioBus; + typedef base::Callback<void(scoped_ptr<ShellAudioBus>)> DataReceivedCallback; + typedef base::Callback<void(void)> CompletionCallback; + typedef base::Callback<void(const scoped_refptr<dom::Event>&)> ErrorCallback; + + MicrophoneManager(int sample_rate, const DataReceivedCallback& data_received, + const CompletionCallback& completion, + const ErrorCallback& error, bool enable_fake_microphone); + + ~MicrophoneManager(); + + // Open microphone to receive voice and start a timer to fetch audio data from + // microphone. + void Open(); + // Close microphone and stop the timer from receiving audio data. + void Close(); + + private: + enum State { kStarted, kStopped, kError }; + + // Returns true if the creation succeeded or the microphone is already a valid + // one. + bool CreateIfNecessary(); + void OpenInternal(); + void CloseInternal(); + void DestroyInternal(); + + // Timer callback for fetching audio data. + void Read(); + + int sample_rate_; + const DataReceivedCallback data_received_callback_; + const CompletionCallback completion_callback_; + const ErrorCallback error_callback_; + + scoped_ptr<Microphone> microphone_; +#if defined(ENABLE_FAKE_MICROPHONE) + bool enable_fake_microphone_; +#endif // defined(ENABLE_FAKE_MICROPHONE) + + // Microphone state. + State state_; + // Repeat timer to poll mic events. + base::optional<base::RepeatingTimer<MicrophoneManager> > + poll_mic_events_timer_; + // Microphone thread. + base::Thread thread_; +}; + +} // namespace speech +} // namespace cobalt + +#endif // COBALT_SPEECH_MICROPHONE_MANAGER_H_
diff --git a/src/cobalt/speech/microphone_starboard.cc b/src/cobalt/speech/microphone_starboard.cc new file mode 100644 index 0000000..676c0aa --- /dev/null +++ b/src/cobalt/speech/microphone_starboard.cc
@@ -0,0 +1,79 @@ +/* + * Copyright 2016 Google Inc. 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 "cobalt/speech/microphone_starboard.h" + +#if defined(SB_USE_SB_MICROPHONE) + +#include "starboard/log.h" + +namespace cobalt { +namespace speech { + +namespace { +// The maximum of microphones which can be supported. Currently only supports +// one microphone. +const int kNumberOfMicrophones = 1; +} // namespace + +MicrophoneStarboard::MicrophoneStarboard(int sample_rate, int buffer_size_bytes) + : Microphone(), + min_microphone_read_in_bytes_(-1), + microphone_(kSbMicrophoneInvalid) { + SbMicrophoneInfo info[kNumberOfMicrophones]; + int microphone_num = SbMicrophoneGetAvailable(info, kNumberOfMicrophones); + + // Loop all the available microphones and create a valid one. + for (int index = 0; index < microphone_num; ++index) { + if (!SbMicrophoneIsSampleRateSupported(info[index].id, sample_rate)) { + continue; + } + + microphone_ = + SbMicrophoneCreate(info[index].id, sample_rate, buffer_size_bytes); + if (!SbMicrophoneIsValid(microphone_)) { + continue; + } + + // Created a microphone successfully. + min_microphone_read_in_bytes_ = info[index].min_read_size; + return; + } +} + +MicrophoneStarboard::~MicrophoneStarboard() { + SbMicrophoneDestroy(microphone_); +} + +bool MicrophoneStarboard::Open() { + SB_DCHECK(SbMicrophoneIsValid(microphone_)); + return SbMicrophoneOpen(microphone_); +} + +int MicrophoneStarboard::Read(char* out_data, int data_size) { + SB_DCHECK(SbMicrophoneIsValid(microphone_)); + return SbMicrophoneRead(microphone_, out_data, data_size); +} + +bool MicrophoneStarboard::Close() { + SB_DCHECK(SbMicrophoneIsValid(microphone_)); + return SbMicrophoneClose(microphone_); +} + +} // namespace speech +} // namespace cobalt + +#endif // defined(SB_USE_SB_MICROPHONE)
diff --git a/src/cobalt/speech/microphone_starboard.h b/src/cobalt/speech/microphone_starboard.h new file mode 100644 index 0000000..9df841a --- /dev/null +++ b/src/cobalt/speech/microphone_starboard.h
@@ -0,0 +1,53 @@ +/* + * Copyright 2016 Google Inc. 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. + */ + +#ifndef COBALT_SPEECH_MICROPHONE_STARBOARD_H_ +#define COBALT_SPEECH_MICROPHONE_STARBOARD_H_ + +#include "cobalt/speech/speech_configuration.h" + +#if defined(SB_USE_SB_MICROPHONE) + +#include "cobalt/speech/microphone.h" +#include "starboard/microphone.h" + +namespace cobalt { +namespace speech { + +class MicrophoneStarboard : public Microphone { + public: + MicrophoneStarboard(int sample_rate, int buffer_size_bytes); + ~MicrophoneStarboard() OVERRIDE; + + bool Open() OVERRIDE; + int Read(char* out_data, int data_size) OVERRIDE; + bool Close() OVERRIDE; + int MinMicrophoneReadInBytes() OVERRIDE { + return min_microphone_read_in_bytes_; + } + bool IsValid() OVERRIDE { return SbMicrophoneIsValid(microphone_); } + + private: + // Minimum requested bytes per microphone read. + int min_microphone_read_in_bytes_; + SbMicrophone microphone_; +}; + +} // namespace speech +} // namespace cobalt + +#endif // defined(SB_USE_SB_MICROPHONE) +#endif // COBALT_SPEECH_MICROPHONE_STARBOARD_H_
diff --git a/src/cobalt/speech/speech.gyp b/src/cobalt/speech/speech.gyp index eb0ffcb..aa933d3 100644 --- a/src/cobalt/speech/speech.gyp +++ b/src/cobalt/speech/speech.gyp
@@ -30,6 +30,8 @@ 'audio_encoder_flac.h', 'chunked_byte_buffer.cc', 'chunked_byte_buffer.h', + 'endpointer_delegate.cc', + 'endpointer_delegate.h', 'endpointer/endpointer.cc', 'endpointer/endpointer.h', @@ -41,7 +43,10 @@ 'google_streaming_api.pb.cc', 'google_streaming_api.pb.h', 'google_streaming_api.pb.proto', - 'mic.h', + 'microphone.h', + 'microphone_manager.cc', + 'microphone_manager.h', + 'speech_configuration.h', 'speech_recognition.cc', 'speech_recognition.h', 'speech_recognition_alternative.cc', @@ -73,14 +78,38 @@ 'conditions': [ ['OS=="starboard"', { 'sources': [ - 'mic_starboard.cc', + 'microphone_starboard.cc', + 'microphone_starboard.h', ], }], - ['OS!="starboard" and actual_target_arch in ["linux", "ps3", "win"]', { + ['OS=="starboard" and enable_fake_microphone == 1', { 'sources': [ - 'mic_<(actual_target_arch).cc', + 'microphone_fake.cc', + 'microphone_fake.h', ], + 'defines': [ + 'ENABLE_FAKE_MICROPHONE', + ], + 'direct_dependent_settings': { + 'defines': [ 'ENABLE_FAKE_MICROPHONE', ], + }, }], + ['cobalt_copy_test_data == 1', { + 'actions': [ + { + 'action_name': 'speech_copy_test_data', + 'variables': { + 'input_files': [ + '<(DEPTH)/cobalt/speech/testdata/', + ], + 'output_dir': 'cobalt/speech/testdata/', + }, + 'includes': [ '../build/copy_test_data.gypi' ], + }, + ], + } + + ], ], }, {
diff --git a/src/cobalt/speech/speech_configuration.h b/src/cobalt/speech/speech_configuration.h new file mode 100644 index 0000000..97ab76f --- /dev/null +++ b/src/cobalt/speech/speech_configuration.h
@@ -0,0 +1,29 @@ +/* + * Copyright 2016 Google Inc. 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. + */ + +#ifndef COBALT_SPEECH_SPEECH_CONFIGURATION_H_ +#define COBALT_SPEECH_SPEECH_CONFIGURATION_H_ + +#include "build/build_config.h" + +#if defined(OS_STARBOARD) +#include "starboard/configuration.h" +#if SB_HAS(MICROPHONE) && SB_VERSION(2) +#define SB_USE_SB_MICROPHONE 1 +#endif // SB_HAS(MICROPHONE) && SB_VERSION(2) +#endif // defined(OS_STARBOARD) + +#endif // COBALT_SPEECH_SPEECH_CONFIGURATION_H_
diff --git a/src/cobalt/speech/speech_recognition.cc b/src/cobalt/speech/speech_recognition.cc index 761b2e5..8ea7c49 100644 --- a/src/cobalt/speech/speech_recognition.cc +++ b/src/cobalt/speech/speech_recognition.cc
@@ -31,7 +31,9 @@ ->fetcher_factory() ->network_module(), base::Bind(&SpeechRecognition::OnEventAvailable, - base::Unretained(this)))), + base::Unretained(this)), + base::polymorphic_downcast<dom::DOMSettings*>(settings) + ->enable_fake_microphone())), config_("" /*lang*/, false /*continuous*/, false /*interim_results*/, 1 /*max alternatives*/) {}
diff --git a/src/cobalt/speech/speech_recognition_manager.cc b/src/cobalt/speech/speech_recognition_manager.cc index e531a77..114d374 100644 --- a/src/cobalt/speech/speech_recognition_manager.cc +++ b/src/cobalt/speech/speech_recognition_manager.cc
@@ -17,6 +17,7 @@ #include "cobalt/speech/speech_recognition_manager.h" #include "base/bind.h" +#include "cobalt/base/tokens.h" #include "cobalt/dom/dom_exception.h" namespace cobalt { @@ -28,7 +29,8 @@ } // namespace SpeechRecognitionManager::SpeechRecognitionManager( - network::NetworkModule* network_module, const EventCallback& event_callback) + network::NetworkModule* network_module, const EventCallback& event_callback, + bool enable_fake_microphone) : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), weak_this_(weak_ptr_factory_.GetWeakPtr()), main_message_loop_(base::MessageLoopProxy::current()), @@ -37,13 +39,15 @@ recognizer_(network_module, base::Bind(&SpeechRecognitionManager::OnRecognizerEvent, base::Unretained(this)))), - ALLOW_THIS_IN_INITIALIZER_LIST(mic_(Mic::Create( + ALLOW_THIS_IN_INITIALIZER_LIST(microphone_manager_( kSampleRate, base::Bind(&SpeechRecognitionManager::OnDataReceived, base::Unretained(this)), base::Bind(&SpeechRecognitionManager::OnDataCompletion, base::Unretained(this)), base::Bind(&SpeechRecognitionManager::OnMicError, - base::Unretained(this))))), + base::Unretained(this)), + enable_fake_microphone)), + endpointer_delegate_(kSampleRate), state_(kStopped) {} SpeechRecognitionManager::~SpeechRecognitionManager() { Stop(); } @@ -61,7 +65,8 @@ } recognizer_.Start(config, kSampleRate); - mic_->Start(); + microphone_manager_.Open(); + endpointer_delegate_.Start(); state_ = kStarted; } @@ -74,9 +79,11 @@ return; } - mic_->Stop(); + endpointer_delegate_.Stop(); + microphone_manager_.Close(); recognizer_.Stop(); state_ = kStopped; + event_callback_.Run(new dom::Event(base::Tokens::soundend())); } void SpeechRecognitionManager::Abort() { @@ -88,9 +95,11 @@ return; } - mic_->Stop(); + endpointer_delegate_.Stop(); + microphone_manager_.Close(); recognizer_.Stop(); state_ = kAborted; + event_callback_.Run(new dom::Event(base::Tokens::soundend())); } void SpeechRecognitionManager::OnDataReceived( @@ -105,6 +114,9 @@ // Stop recognizing if in the abort state. if (state_ != kAborted) { + if (endpointer_delegate_.IsFirstTimeSoundStarted(*audio_bus)) { + event_callback_.Run(new dom::Event(base::Tokens::soundstart())); + } recognizer_.RecognizeAudio(audio_bus.Pass(), false); } } @@ -125,7 +137,7 @@ size_t dummy_frames = static_cast<size_t>(kSampleRate * kAudioPacketDurationInSeconds); scoped_ptr<ShellAudioBus> dummy_audio_bus(new ShellAudioBus( - 1, dummy_frames, ShellAudioBus::kInt16, ShellAudioBus::kPlanar)); + 1, dummy_frames, ShellAudioBus::kInt16, ShellAudioBus::kInterleaved)); dummy_audio_bus->ZeroAllFrames(); recognizer_.RecognizeAudio(dummy_audio_bus.Pass(), true); } @@ -147,22 +159,23 @@ } } -void SpeechRecognitionManager::OnMicError() { +void SpeechRecognitionManager::OnMicError( + const scoped_refptr<dom::Event>& event) { if (!main_message_loop_->BelongsToCurrentThread()) { // Called from mic thread. main_message_loop_->PostTask( FROM_HERE, - base::Bind(&SpeechRecognitionManager::OnMicError, weak_this_)); + base::Bind(&SpeechRecognitionManager::OnMicError, weak_this_, event)); return; } - event_callback_.Run( - scoped_refptr<SpeechRecognitionError>(new SpeechRecognitionError( - SpeechRecognitionError::kAborted, "Mic Disconnected."))); + event_callback_.Run(event); - // An error is occured in Mic, so stopping the recognizer. + // An error is occured in Mic, so stop the energy endpointer and recognizer. + endpointer_delegate_.Stop(); recognizer_.Stop(); state_ = kAborted; + event_callback_.Run(new dom::Event(base::Tokens::soundend())); } } // namespace speech
diff --git a/src/cobalt/speech/speech_recognition_manager.h b/src/cobalt/speech/speech_recognition_manager.h index 852ede2..9367a10 100644 --- a/src/cobalt/speech/speech_recognition_manager.h +++ b/src/cobalt/speech/speech_recognition_manager.h
@@ -21,7 +21,9 @@ #include "cobalt/network/network_module.h" #include "cobalt/script/exception_state.h" -#include "cobalt/speech/mic.h" +#include "cobalt/speech/endpointer_delegate.h" +#include "cobalt/speech/microphone_manager.h" +#include "cobalt/speech/speech_configuration.h" #include "cobalt/speech/speech_recognition_config.h" #include "cobalt/speech/speech_recognition_error.h" #include "cobalt/speech/speech_recognition_event.h" @@ -42,7 +44,8 @@ typedef base::Callback<bool(const scoped_refptr<dom::Event>&)> EventCallback; SpeechRecognitionManager(network::NetworkModule* network_module, - const EventCallback& event_callback); + const EventCallback& event_callback, + bool enable_fake_microphone); ~SpeechRecognitionManager(); // Start/Stop speech recognizer and microphone. Multiple calls would be @@ -62,7 +65,7 @@ // Callbacks from mic. void OnDataReceived(scoped_ptr<ShellAudioBus> audio_bus); void OnDataCompletion(); - void OnMicError(); + void OnMicError(const scoped_refptr<dom::Event>& event); // Callbacks from recognizer. void OnRecognizerEvent(const scoped_refptr<dom::Event>& event); @@ -76,7 +79,12 @@ // Callback for sending dom events if available. EventCallback event_callback_; SpeechRecognizer recognizer_; - scoped_ptr<Mic> mic_; + + MicrophoneManager microphone_manager_; + + // Delegate of endpointer which is used for detecting sound energy. + EndPointerDelegate endpointer_delegate_; + State state_; };
diff --git a/src/cobalt/speech/speech_recognizer.cc b/src/cobalt/speech/speech_recognizer.cc index d5c1ce1..bbb3049 100644 --- a/src/cobalt/speech/speech_recognizer.cc +++ b/src/cobalt/speech/speech_recognizer.cc
@@ -25,11 +25,16 @@ #include "cobalt/loader/fetcher_factory.h" #include "cobalt/network/network_module.h" #include "cobalt/speech/google_streaming_api.pb.h" -#include "cobalt/speech/mic.h" +#include "cobalt/speech/microphone.h" +#include "cobalt/speech/speech_configuration.h" #include "cobalt/speech/speech_recognition_error.h" #include "net/base/escape.h" #include "net/url_request/url_fetcher.h" +#if defined(SB_USE_SB_MICROPHONE) +#include "starboard/system.h" +#endif // defined(SB_USE_SB_MICROPHONE) + namespace cobalt { namespace speech { @@ -75,16 +80,23 @@ SpeechRecognitionResultList::SpeechRecognitionResults results; for (int i = 0; i < event.result_size(); ++i) { SpeechRecognitionResult::SpeechRecognitionAlternatives alternatives; - const proto::SpeechRecognitionResult& kProtoResult = event.result(i); - for (int j = 0; j < kProtoResult.alternative_size(); ++j) { - const proto::SpeechRecognitionAlternative& kAlternative = - kProtoResult.alternative(j); + const proto::SpeechRecognitionResult& proto_result = event.result(i); + for (int j = 0; j < proto_result.alternative_size(); ++j) { + const proto::SpeechRecognitionAlternative& proto_alternative = + proto_result.alternative(j); + float confidence = 0.0f; + if (proto_alternative.has_confidence()) { + confidence = proto_alternative.confidence(); + } else if (proto_result.has_stability()) { + confidence = proto_result.stability(); + } scoped_refptr<SpeechRecognitionAlternative> alternative( - new SpeechRecognitionAlternative(kAlternative.transcript(), - kAlternative.confidence())); + new SpeechRecognitionAlternative(proto_alternative.transcript(), + confidence)); alternatives.push_back(alternative); } - bool final = kProtoResult.has_final() && kProtoResult.final(); + + bool final = proto_result.has_final() && proto_result.final(); scoped_refptr<SpeechRecognitionResult> recognition_result( new SpeechRecognitionResult(alternatives, final)); results.push_back(recognition_result); @@ -139,19 +151,32 @@ event_callback.Run(error_event); } +bool IsResponseCodeSuccess(int response_code) { + // NetFetcher only considers success to be if the network request + // was successful *and* we get a 2xx response back. + // TODO: 304s are unexpected since we don't enable the HTTP cache, + // meaning we don't add the If-Modified-Since header to our request. + // However, it's unclear what would happen if we did, so DCHECK. + DCHECK_NE(response_code, 304) << "Unsupported status code"; + return response_code / 100 == 2; +} + } // namespace SpeechRecognizer::SpeechRecognizer(network::NetworkModule* network_module, const EventCallback& event_callback) : network_module_(network_module), - thread_("speech_recognizer"), started_(false), - event_callback_(event_callback) { + event_callback_(event_callback), + thread_("speech_recognizer") { thread_.StartWithOptions(base::Thread::Options(MessageLoop::TYPE_IO, 0)); } SpeechRecognizer::~SpeechRecognizer() { Stop(); + // Stopping the thread here to ensure that StopInternal has completed before + // we finish running the destructor. + thread_.Stop(); } void SpeechRecognizer::Start(const SpeechRecognitionConfig& config, @@ -182,23 +207,31 @@ const net::URLFetcher* source, scoped_ptr<std::string> download_data) { DCHECK_EQ(thread_.message_loop(), MessageLoop::current()); + const net::URLRequestStatus& status = source->GetStatus(); + const int response_code = source->GetResponseCode(); + if (source == downstream_fetcher_.get()) { - chunked_byte_buffer_.Append(*download_data); - while (chunked_byte_buffer_.HasChunks()) { - scoped_ptr<std::vector<uint8_t> > chunk = - chunked_byte_buffer_.PopChunk().Pass(); + if (status.is_success() && IsResponseCodeSuccess(response_code)) { + chunked_byte_buffer_.Append(*download_data); + while (chunked_byte_buffer_.HasChunks()) { + scoped_ptr<std::vector<uint8_t> > chunk = + chunked_byte_buffer_.PopChunk().Pass(); - proto::SpeechRecognitionEvent event; - if (!event.ParseFromString(std::string(chunk->begin(), chunk->end()))) { - DLOG(WARNING) << "Parse proto string error."; - return; - } + proto::SpeechRecognitionEvent event; + if (!event.ParseFromString(std::string(chunk->begin(), chunk->end()))) { + DLOG(WARNING) << "Parse proto string error."; + return; + } - if (event.status() == proto::SpeechRecognitionEvent::STATUS_SUCCESS) { - ProcessAndFireSuccessEvent(ProcessProtoSuccessResults(event)); - } else { - ProcessAndFireErrorEvent(event, event_callback_); + if (event.status() == proto::SpeechRecognitionEvent::STATUS_SUCCESS) { + ProcessAndFireSuccessEvent(ProcessProtoSuccessResults(event)); + } else { + ProcessAndFireErrorEvent(event, event_callback_); + } } + } else { + event_callback_.Run(new SpeechRecognitionError( + SpeechRecognitionError::kNetwork, "Network response failure.")); } } } @@ -206,7 +239,7 @@ void SpeechRecognizer::OnURLFetchComplete(const net::URLFetcher* source) { DCHECK_EQ(thread_.message_loop(), MessageLoop::current()); UNREFERENCED_PARAMETER(source); - started_ = false; + // no-op. } void SpeechRecognizer::StartInternal(const SpeechRecognitionConfig& config, @@ -243,7 +276,19 @@ up_url = AppendQueryParameter(up_url, "client", kClient); up_url = AppendQueryParameter(up_url, "pair", pair); up_url = AppendQueryParameter(up_url, "output", "pb"); - up_url = AppendQueryParameter(up_url, "key", GetSpeechAPIKey()); + + const char* speech_api_key = NULL; +#if defined(SB_USE_SB_MICROPHONE) + const int kSpeechApiKeyLength = 100; + char buffer[kSpeechApiKeyLength] = {0}; + bool result = SbSystemGetProperty(kSbSystemPropertySpeechApiKey, buffer, + SB_ARRAY_SIZE_INT(buffer)); + SB_DCHECK(result); + speech_api_key = result ? buffer : ""; +#else + speech_api_key = ""; +#endif + up_url = AppendQueryParameter(up_url, "key", speech_api_key); // Language is required. If no language is specified, use the system language. if (!config.lang.empty()) {
diff --git a/src/cobalt/speech/speech_recognizer.h b/src/cobalt/speech/speech_recognizer.h index 90e5dcd..1bff9f9 100644 --- a/src/cobalt/speech/speech_recognizer.h +++ b/src/cobalt/speech/speech_recognizer.h
@@ -77,8 +77,6 @@ // This is used for creating fetchers. network::NetworkModule* network_module_; - // Speech recognizer is operating in its own thread. - base::Thread thread_; // Track the start/stop state of speech recognizer. bool started_; @@ -93,6 +91,8 @@ ChunkedByteBuffer chunked_byte_buffer_; // Used for accumulating final results. SpeechRecognitionResults final_results_; + // Speech recognizer is operating in its own thread. + base::Thread thread_; }; } // namespace speech
diff --git a/src/cobalt/speech/testdata/audio1.raw b/src/cobalt/speech/testdata/audio1.raw new file mode 100644 index 0000000..5ebf79d --- /dev/null +++ b/src/cobalt/speech/testdata/audio1.raw Binary files differ
diff --git a/src/cobalt/speech/testdata/audio2.raw b/src/cobalt/speech/testdata/audio2.raw new file mode 100644 index 0000000..35413b7 --- /dev/null +++ b/src/cobalt/speech/testdata/audio2.raw Binary files differ
diff --git a/src/cobalt/speech/testdata/audio3.raw b/src/cobalt/speech/testdata/audio3.raw new file mode 100644 index 0000000..c503c9e --- /dev/null +++ b/src/cobalt/speech/testdata/audio3.raw Binary files differ
diff --git a/src/cobalt/speech/testdata/quit.raw b/src/cobalt/speech/testdata/quit.raw new file mode 100644 index 0000000..a01dfc4 --- /dev/null +++ b/src/cobalt/speech/testdata/quit.raw Binary files differ
diff --git a/src/cobalt/trace_event/json_file_outputter.cc b/src/cobalt/trace_event/json_file_outputter.cc index f17f2d3..c515057 100644 --- a/src/cobalt/trace_event/json_file_outputter.cc +++ b/src/cobalt/trace_event/json_file_outputter.cc
@@ -18,12 +18,38 @@ #include <string> +#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) +#include "base/command_line.h" +#endif #include "base/logging.h" #include "base/platform_file.h" +#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) +#include "base/string_piece.h" +#include "cobalt/trace_event/switches.h" +#endif namespace cobalt { namespace trace_event { +// Returns true if and only if log_timed_trace == "on", and +// ENABLE_DEBUG_COMMAND_LINE_SWITCHES is set. +bool ShouldLogTimedTrace() { + bool isTimedTraceSet = false; + +#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) + + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kLogTimedTrace) && + command_line->GetSwitchValueASCII(switches::kLogTimedTrace) == + "on") { + isTimedTraceSet = true; + } + +#endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES + + return isTimedTraceSet; +} + JSONFileOutputter::JSONFileOutputter(const FilePath& output_path) : output_path_(output_path), output_trace_event_call_count_(0), @@ -72,6 +98,13 @@ return; } + if (ShouldLogTimedTrace()) { + // These markers assist in locating the trace data in the log, and can be + // used by scripts to help extract the trace data. + LOG(INFO) << "BEGIN_TRACELOG_MARKER" << base::StringPiece(buffer, length) + << "END_TRACELOG_MARKER"; + } + int count = base::WritePlatformFileAtCurrentPos(file_, buffer, length); if (count < 0) { Close();
diff --git a/src/cobalt/trace_event/switches.cc b/src/cobalt/trace_event/switches.cc new file mode 100644 index 0000000..6cf65e6 --- /dev/null +++ b/src/cobalt/trace_event/switches.cc
@@ -0,0 +1,33 @@ +/* + * Copyright 2016 Google Inc. 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 "cobalt/trace_event/switches.h" + +namespace cobalt { +namespace trace_event { +namespace switches { + +#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) +// If this flag is set, then the contents of the timed_trace is sent to the log +// such that it can be collected by examining console output. This may be +// useful on devices where it is difficult to gain access to files written by +// Cobalt. log_timed_trace: on | off. +const char kLogTimedTrace[] = "log_timed_trace"; +#endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES + +} // namespace switches +} // namespace trace_event +} // namespace cobalt
diff --git a/src/cobalt/trace_event/switches.h b/src/cobalt/trace_event/switches.h new file mode 100644 index 0000000..98fc0ec --- /dev/null +++ b/src/cobalt/trace_event/switches.h
@@ -0,0 +1,32 @@ +/* + * Copyright 2016 Google Inc. 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. + */ + +#ifndef COBALT_TRACE_EVENT_SWITCHES_H_ +#define COBALT_TRACE_EVENT_SWITCHES_H_ + +namespace cobalt { +namespace trace_event { +namespace switches { + +#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES) +extern const char kLogTimedTrace[]; +#endif // ENABLE_DEBUG_COMMAND_LINE_SWITCHES + +} // namespace switches +} // namespace trace_event +} // namespace cobalt + +#endif // COBALT_TRACE_EVENT_SWITCHES_H_
diff --git a/src/cobalt/trace_event/trace_event.gyp b/src/cobalt/trace_event/trace_event.gyp index 75d5c82..4e4279e 100644 --- a/src/cobalt/trace_event/trace_event.gyp +++ b/src/cobalt/trace_event/trace_event.gyp
@@ -27,6 +27,8 @@ 'scoped_event_parser_trace.h', 'scoped_trace_to_file.cc', 'scoped_trace_to_file.h', + 'switches.cc', + 'switches.h', ], 'dependencies': [ '<(DEPTH)/base/base.gyp:base',
diff --git a/src/media/base/sbplayer_pipeline.cc b/src/media/base/sbplayer_pipeline.cc index b9d2262..64497b8 100644 --- a/src/media/base/sbplayer_pipeline.cc +++ b/src/media/base/sbplayer_pipeline.cc
@@ -201,8 +201,6 @@ scoped_refptr<SbPlayerSetBoundsHelper> set_bounds_helper_; - bool flushing_; - // The following member variables can be accessed from WMPI thread but all // modifications to them happens on the pipeline thread. So any access of // them from the WMPI thread and any modification to them on the pipeline @@ -232,7 +230,6 @@ has_video_(false), audio_read_in_progress_(false), video_read_in_progress_(false), - flushing_(false), set_bounds_helper_(new SbPlayerSetBoundsHelper), suspended_(false) {} @@ -327,19 +324,17 @@ seek_cb.Run(PIPELINE_ERROR_INVALID_STATE); } + player_->PrepareForSeek(); + DCHECK(seek_cb_.is_null()); DCHECK(!seek_cb.is_null()); - flushing_ = true; - if (audio_read_in_progress_ || video_read_in_progress_) { message_loop_->PostTask( FROM_HERE, base::Bind(&SbPlayerPipeline::Seek, this, time, seek_cb)); return; } - player_->PrepareForSeek(); - { base::AutoLock auto_lock(lock_); seek_cb_ = seek_cb; @@ -637,7 +632,6 @@ DCHECK(message_loop_->BelongsToCurrentThread()); if (status == PIPELINE_OK) { - flushing_ = false; player_->Seek(seek_time_); } } @@ -682,7 +676,6 @@ video_read_in_progress_ = false; } if (!seek_cb_.is_null()) { - buffering_state_cb_.Run(kPrerollCompleted); PipelineStatusCB seek_cb; { base::AutoLock auto_lock(lock_); @@ -718,10 +711,6 @@ return; } - if (flushing_) { - return; - } - if (type == DemuxerStream::AUDIO) { if (audio_read_in_progress_) { return;
diff --git a/src/media/base/starboard_player.cc b/src/media/base/starboard_player.cc index ce5197c..2708468 100644 --- a/src/media/base/starboard_player.cc +++ b/src/media/base/starboard_player.cc
@@ -40,6 +40,7 @@ ticket_(SB_PLAYER_INITIAL_TICKET), volume_(1.0), paused_(true), + seek_pending_(false), state_(kPlaying) { DCHECK(audio_config.IsValidConfig()); DCHECK(video_config.IsValidConfig()); @@ -131,6 +132,8 @@ void StarboardPlayer::PrepareForSeek() { DCHECK(message_loop_->BelongsToCurrentThread()); ++ticket_; + SbPlayerSetPause(player_, true); + seek_pending_ = true; } void StarboardPlayer::Seek(base::TimeDelta time) { @@ -154,6 +157,10 @@ ++ticket_; SbPlayerSeek(player_, TimeDeltaToSbMediaTime(time), ticket_); + seek_pending_ = false; + if (!paused_) { + SbPlayerSetPause(player_, false); + } } void StarboardPlayer::SetVolume(float volume) { @@ -174,8 +181,10 @@ DCHECK(message_loop_->BelongsToCurrentThread()); DCHECK(SbPlayerIsValid(player_)); - SbPlayerSetPause(player_, pause); paused_ = pause; + if (!seek_pending_) { + SbPlayerSetPause(player_, pause); + } } void StarboardPlayer::GetInfo(uint32* video_frames_decoded,
diff --git a/src/media/base/starboard_player.h b/src/media/base/starboard_player.h index 0f71acb..2d9dc58 100644 --- a/src/media/base/starboard_player.h +++ b/src/media/base/starboard_player.h
@@ -131,6 +131,7 @@ int ticket_; float volume_; bool paused_; + bool seek_pending_; DecoderBufferCache decoder_buffer_cache_; // The following variables can be accessed from GetInfo(), which can be called
diff --git a/src/nb/atomic.h b/src/nb/atomic.h new file mode 100644 index 0000000..9bd5c61 --- /dev/null +++ b/src/nb/atomic.h
@@ -0,0 +1,281 @@ +/* + * Copyright 2016 Google Inc. 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. + */ + +#ifndef NB_ATOMIC_H_ +#define NB_ATOMIC_H_ + +#include "starboard/mutex.h" +#include "starboard/types.h" + +namespace nb { + +// Provides atomic types like integer and float. Some types like atomic_int32_t +// are likely to be hardware accelerated for your platform. +// +// Never use the parent types like atomic<T>, atomic_number<T> or +// atomic_integral<T> and instead use the fully qualified classes like +// atomic_int32_t, atomic_pointer<T*>, etc. +// +// Note on template instantiation, avoid using the parent type and instead +// use the fully qualified type. +// BAD: +// template<typename T> +// void Foo(const atomic<T>& value); +// GOOD: +// template<typename atomic_t> +// void Foo(const atomic_t& vlaue); + +// Atomic Pointer class. Instantiate as atomic_pointer<void*> +// for void* pointer types. +template<typename T> +class atomic_pointer; + +// Atomic bool class. +class atomic_bool; + +// Atomic int32 class +class atomic_int32_t; + +// Atomic int64 class. +class atomic_int64_t; + +// Atomic float class. +class atomic_float; + +// Atomic double class. +class atomic_double; + +/////////////////////////////////////////////////////////////////////////////// +// Class hiearchy. +/////////////////////////////////////////////////////////////////////////////// + +// Base functionality for atomic types. Defines exchange(), load(), +// store(), compare_exhange_weak(), compare_exchange_strong() +template <typename T> +class atomic; + +// Subtype of atomic<T> for numbers likes float and integer types but not bool. +// Adds fetch_add() and fetch_sub(). +template <typename T> +class atomic_number; + +// Subtype of atomic_number<T> for integer types like int32 and int64. Adds +// increment and decrement. +template <typename T> +class atomic_integral; + +/////////////////////////////////////////////////////////////////////////////// +// Implimentation. +/////////////////////////////////////////////////////////////////////////////// + +// Similar to C++11 std::atomic<T>. +// atomic<T> may be instantiated with any TriviallyCopyable type T. +// atomic<T> is neither copyable nor movable. +template <typename T> +class atomic { + public: + typedef T ValueType; + + // C++11 forbids a copy constructor for std::atomic<T>, it also forbids + // a move operation. + atomic() : value_() {} + explicit atomic(T v) : value_(v) {} + + // Checks whether the atomic operations on all objects of this type + // are lock-free. + // Returns true if the atomic operations on the objects of this type + // are lock-free, false otherwise. + // + // All atomic types may be implemented using mutexes or other locking + // operations, rather than using the lock-free atomic CPU instructions. + // atomic types are also allowed to be sometimes lock-free, e.g. if only + // aligned memory accesses are naturally atomic on a given architecture, + // misaligned objects of the same type have to use locks. + // + // See also std::atomic<T>::is_lock_free(). + bool is_lock_free() const { return false; } + bool is_lock_free() const volatile { return false; } + + // Atomically replaces the value of the atomic object + // and returns the value held previously. + // See also std::atomic<T>::exchange(). + T exchange(T new_val) { + T old_value; + { + starboard::ScopedLock lock(mutex_); + old_value = value_; + value_ = new_val; + } + return old_value; + } + + // Atomically obtains the value of the atomic object. + // See also std::atomic<T>::load(). + T load() const { + starboard::ScopedLock lock(mutex_); + return value_; + } + + // Stores the value. See std::atomic<T>::store(...) + void store(T val) { + starboard::ScopedLock lock(mutex_); + value_ = val; + } + + // compare_exchange_strong(...) sets the new value if and only if + // *expected_value matches what is stored internally. + // If this succeeds then true is returned and *expected_value == new_value. + // Otherwise If there is a mismatch then false is returned and + // *expected_value is set to the internal value. + // Inputs: + // new_value: Attempt to set the value to this new value. + // expected_value: A test condition for success. If the actual value + // matches the expected_value then the swap will succeed. + // + // See also std::atomic<T>::compare_exchange_strong(...). + bool compare_exchange_strong(T* expected_value, T new_value) { + // Save original value so that its local. This hints to the compiler + // that test_val doesn't have aliasing issues and should result in + // more optimal code inside of the lock. + const T test_val = *expected_value; + starboard::ScopedLock lock(mutex_); + if (test_val == value_) { + value_ = new_value; + return true; + } else { + *expected_value = value_; + return false; + } + } + + // Weak version of this function is documented to be faster, but has allows + // weaker memory ordering and therefore will sometimes have a false negative: + // The value compared will actually be equal but the return value from this + // function indicates otherwise. + // By default, the function delegates to compare_exchange_strong(...). + // + // See also std::atomic<T>::compare_exchange_weak(...). + bool compare_exchange_weak(T* expected_value, T new_value) { + return compare_exchange_strong(expected_value, new_value); + } + + protected: + T value_; + starboard::Mutex mutex_; +}; + +// A subclass of atomic<T> that adds fetch_add(...) and fetch_sub(...). +template <typename T> +class atomic_number : public atomic<T> { + public: + typedef atomic<T> Super; + typedef T ValueType; + + atomic_number() : Super() {} + explicit atomic_number(T v) : Super(v) {} + + // Returns the previous value before the input value was added. + // See also std::atomic<T>::fetch_add(...). + T fetch_add(T val) { + T old_val; + { + starboard::ScopedLock lock(this->mutex_); + old_val = this->value_; + this->value_ += val; + } + return old_val; + } + + // Returns the value before the operation was applied. + // See also std::atomic<T>::fetch_sub(...). + T fetch_sub(T val) { + T old_val; + { + starboard::ScopedLock lock(this->mutex_); + old_val = this->value_; + this->value_ -= val; + } + return old_val; + } +}; + +// A subclass to classify Atomic Integers. Adds increment and decrement +// functions. +template <typename T> +class atomic_integral : public atomic_number<T> { + public: + typedef atomic_number<T> Super; + + atomic_integral() : Super() {} + explicit atomic_integral(T v) : Super(v) {} + + T increment() { return this->fetch_add(T(1)); } + T decrement() { return this->fetch_sub(T(1)); } +}; + +// atomic_pointer class. +template <typename T> +class atomic_pointer : public atomic<T> { + public: + typedef atomic<T> Super; + atomic_pointer() : Super() {} + explicit atomic_pointer(T initial_val) : Super(initial_val) {} +}; + +// Simple atomic bool class. This could be optimized for speed using +// compiler intrinsics for concurrent integer modification. +class atomic_bool : public atomic<bool> { + public: + typedef atomic<bool> Super; + atomic_bool() : Super() {} + explicit atomic_bool(bool initial_val) : Super(initial_val) {} +}; + +// Simple atomic int class. This could be optimized for speed using +// compiler intrinsics for concurrent integer modification. +class atomic_int32_t : public atomic_integral<int32_t> { + public: + typedef atomic_integral<int32_t> Super; + atomic_int32_t() : Super() {} + explicit atomic_int32_t(int32_t initial_val) : Super(initial_val) {} +}; + +// Simple atomic int class. This could be optimized for speed using +// compiler intrinsics for concurrent integer modification. +class atomic_int64_t : public atomic_integral<int64_t> { + public: + typedef atomic_integral<int64_t> Super; + atomic_int64_t() : Super() {} + explicit atomic_int64_t(int64_t initial_val) : Super(initial_val) {} +}; + +class atomic_float : public atomic_number<float> { + public: + typedef atomic_number<float> Super; + atomic_float() : Super() {} + explicit atomic_float(float initial_val) : Super(initial_val) {} +}; + +class atomic_double : public atomic_number<double> { + public: + typedef atomic_number<double> Super; + atomic_double() : Super() {} + explicit atomic_double(double initial_val) : Super(initial_val) {} +}; + +} // namespace nb + +#endif // NB_ATOMIC_H_
diff --git a/src/nb/atomic_test.cc b/src/nb/atomic_test.cc new file mode 100644 index 0000000..fc76703 --- /dev/null +++ b/src/nb/atomic_test.cc
@@ -0,0 +1,317 @@ +/* + * Copyright 2016 Google Inc. 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 "nb/atomic.h" + +#include <algorithm> +#include <vector> + +#include "nb/test_thread.h" +#include "starboard/configuration.h" +#include "starboard/mutex.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace nb { +namespace { + +/////////////////////////////////////////////////////////////////////////////// +// Boilerplate for test setup. +/////////////////////////////////////////////////////////////////////////////// + +// Defines a typelist for all atomic types. +typedef ::testing::Types<atomic_int32_t, atomic_int64_t, + atomic_float, atomic_double, + atomic_bool, + atomic_pointer<int*> > AllAtomicTypes; + +// Defines a typelist for just atomic number types. +typedef ::testing::Types<atomic_int32_t, atomic_int64_t, + atomic_float, atomic_double> AtomicNumberTypes; + +// Defines test type that will be instantiated using each type in +// AllAtomicTypes type list. +template <typename T> +class AtomicTest : public ::testing::Test {}; +TYPED_TEST_CASE(AtomicTest, AllAtomicTypes); // Registration. + +// Defines test type that will be instantiated using each type in +// AtomicNumberTypes type list. +template <typename T> +class AtomicNumberTest : public ::testing::Test {}; +TYPED_TEST_CASE(AtomicNumberTest, AtomicNumberTypes); // Registration. + + +/////////////////////////////////////////////////////////////////////////////// +// Singlethreaded tests. +/////////////////////////////////////////////////////////////////////////////// + +// Tests default constructor and single-argument constructor. +TYPED_TEST(AtomicTest, Constructors) { + typedef TypeParam AtomicT; + typedef typename AtomicT::ValueType T; + + const T zero(0); + const T one = zero + 1; // Allows AtomicPointer<T*>. + + AtomicT atomic_default; + + // Tests that default value is zero. + ASSERT_EQ(atomic_default.load(), zero); + AtomicT atomic_val(one); + ASSERT_EQ(one, atomic_val.load()); +} + +// Tests load() and exchange(). +TYPED_TEST(AtomicTest, Load_Exchange_SingleThread) { + typedef TypeParam AtomicT; + typedef typename AtomicT::ValueType T; + + const T zero(0); + const T one = zero + 1; // Allows AtomicPointer<T*>. + + AtomicT atomic; + ASSERT_EQ(atomic.load(), zero); // Default is 0. + ASSERT_EQ(zero, atomic.exchange(one)); // Old value was 0. + + // Tests that AtomicType has const get function. + const AtomicT& const_atomic = atomic; + ASSERT_EQ(one, const_atomic.load()); +} + +// Tests compare_exchange_strong(). +TYPED_TEST(AtomicNumberTest, CompareExchangeStrong_SingleThread) { + typedef TypeParam AtomicT; + typedef typename AtomicT::ValueType T; + + const T zero(0); + const T one = zero + 1; // Allows AtomicPointer<T*>. + + AtomicT atomic; + ASSERT_EQ(atomic.load(), zero); // Default is 0. + T expected_value = zero; + // Should succeed. + ASSERT_TRUE(atomic.compare_exchange_strong(&expected_value, + one)); // New value. + + ASSERT_EQ(zero, expected_value); + ASSERT_EQ(one, atomic.load()); // Expect that value was set. + + expected_value = zero; + // Asserts that when the expected and actual value is mismatched that the + // compare_exchange_strong() fails. + ASSERT_FALSE(atomic.compare_exchange_strong(&expected_value, // Mismatched. + zero)); // New value. + + // Failed and this means that expected_value should be set to what the + // internal value was. In this case, one. + ASSERT_EQ(expected_value, one); + ASSERT_EQ(one, atomic.load()); + + ASSERT_TRUE(atomic.compare_exchange_strong(&expected_value, // Matches. + zero)); + ASSERT_EQ(expected_value, one); +} + +// Tests atomic fetching and adding. +TYPED_TEST(AtomicNumberTest, FetchAdd_SingleThread) { + typedef TypeParam AtomicT; + typedef typename AtomicT::ValueType T; + + const T zero(0); + const T one = zero + 1; // Allows atomic_pointer<T*>. + const T two = zero + 2; + + AtomicT atomic; + ASSERT_EQ(atomic.load(), zero); // Default is 0. + ASSERT_EQ(zero, atomic.fetch_add(one)); // Prev value was 0. + ASSERT_EQ(one, atomic.load()); // Now value is this. + ASSERT_EQ(one, atomic.fetch_add(one)); // Prev value was 1. + ASSERT_EQ(two, atomic.exchange(one)); // Old value was 2. +} + +// Tests atomic fetching and subtracting. +TYPED_TEST(AtomicNumberTest, FetchSub_SingleThread) { + typedef TypeParam AtomicT; + typedef typename AtomicT::ValueType T; + + const T zero(0); + const T one = zero + 1; // Allows AtomicPointer<T*>. + const T two = zero + 2; + const T neg_two(zero-2); + + AtomicT atomic; + ASSERT_EQ(atomic.load(), zero); // Default is 0. + atomic.exchange(two); + ASSERT_EQ(two, atomic.fetch_sub(one)); // Prev value was 2. + ASSERT_EQ(one, atomic.load()); // New value. + ASSERT_EQ(one, atomic.fetch_sub(one)); // Prev value was one. + ASSERT_EQ(zero, atomic.load()); // New 0. + ASSERT_EQ(zero, atomic.fetch_sub(two)); + ASSERT_EQ(neg_two, atomic.load()); // 0-2 = -2 +} + +/////////////////////////////////////////////////////////////////////////////// +// Multithreaded tests. +/////////////////////////////////////////////////////////////////////////////// + +// A thread that will execute compare_exhange_strong() and write out a result +// to a shared output. +template <typename AtomicT> +class CompareExchangeThread : public TestThread { + public: + typedef typename AtomicT::ValueType T; + CompareExchangeThread(int start_num, + int end_num, + AtomicT* atomic_value, + std::vector<T>* output, + starboard::Mutex* output_mutex) + : start_num_(start_num), end_num_(end_num), + atomic_value_(atomic_value), output_(output), + output_mutex_(output_mutex) { + } + + virtual void Run() { + std::vector<T> output_buffer; + output_buffer.reserve(end_num_ - start_num_); + for (int i = start_num_; i < end_num_; ++i) { + T new_value = T(i); + while (true) { + if (std::rand() % 3 == 0) { + // 1 in 3 chance of yeilding. + // Attempt to cause more contention by giving other threads a chance + // to run. + SbThreadYield(); + } + + const T prev_value = atomic_value_->load(); + T expected_value = prev_value; + const bool success = + atomic_value_->compare_exchange_strong(&expected_value, + new_value); + if (success) { + output_buffer.push_back(prev_value); + break; + } + } + } + + // Lock the output to append this output buffer. + starboard::ScopedLock lock(*output_mutex_); + output_->insert(output_->end(), + output_buffer.begin(), + output_buffer.end()); + } + private: + const int start_num_; + const int end_num_; + AtomicT*const atomic_value_; + std::vector<T>*const output_; + starboard::Mutex*const output_mutex_; +}; + +// Tests Atomic<T>::compare_exchange_strong(). Each thread has a unique +// sequential range [0,1,2,3 ... ), [5,6,8, ...) that it will generate. +// The numbers are sequentially written to the shared Atomic type and then +// exposed to other threads: +// +// Generates [0,1,2,...,n/2) +// +------+ Thread A <--------+ (Write Exchanged Value) +// | | +// | compare_exchange() +---> exchanged? ---+ +// +----> +------------+ +----+ v +// | AtomicType | Output vector +// +----> +------------+ +----+ ^ +// | compare_exchange() +---> exchanged? ---+ +// | | +// +------+ Thread B <--------+ +// Generates [n/2,n/2+1,...,n) +// +// By repeatedly calling atomic<T>::compare_exchange_strong() by each of the +// threads, each will see the previous value of the shared variable when their +// exchange (atomic swap) operation is successful. If all of the swapped out +// values are recombined then it will form the original generated sequence from +// all threads. +// +// TEST PHASE +// sort( output vector ) AND TEST THAT +// output vector Contains [0,1,2,...,n) +// +// The test passes when the output array is tested that it contains every +// expected generated number from all threads. If compare_exchange_strong() is +// written incorrectly for an atomic type then the output array will have +// duplicates or otherwise not be equal to the expected natural number set. +TYPED_TEST(AtomicNumberTest, Test_CompareExchange_MultiThreaded) { + typedef TypeParam AtomicT; + typedef typename AtomicT::ValueType T; + + static const int kNumElements = 1000; + static const int kNumThreads = 4; + + AtomicT atomic_value(T(-1)); + std::vector<TestThread*> threads; + std::vector<T> output_values; + starboard::Mutex output_mutex; + + for (int i = 0; i < kNumThreads; ++i) { + const int start_num = (kNumElements * i) / kNumThreads; + const int end_num = (kNumElements * (i + 1)) / kNumThreads; + threads.push_back( + new CompareExchangeThread<AtomicT>( + start_num, // defines the number range to generate. + end_num, + &atomic_value, + &output_values, + &output_mutex)); + } + + // These threads will generate unique numbers in their range and then + // write them to the output array. + for (int i = 0; i < kNumThreads; ++i) { + threads[i]->Start(); + } + + for (int i = 0; i < kNumThreads; ++i) { + threads[i]->Join(); + } + // Cleanup threads. + for (int i = 0; i < kNumThreads; ++i) { + delete threads[i]; + } + threads.clear(); + + // Final value needs to be written out. The last thread to join doesn't + // know it's the last and therefore the final value in the shared + // has not be pushed to the output array. + output_values.push_back(atomic_value.load()); + std::sort(output_values.begin(), output_values.end()); + + // We expect the -1 value because it was the explicit initial value of the + // shared atomic. + ASSERT_EQ(T(-1), output_values[0]); + ASSERT_EQ(T(0), output_values[1]); + output_values.erase(output_values.begin()); // Chop off the -1 at the front. + + // Finally, assert that the output array is equal to the natural numbers + // after it has been sorted. + ASSERT_EQ(output_values.size(), kNumElements); + // All of the elements should be equal too. + for (int i = 0; i < output_values.size(); ++i) { + ASSERT_EQ(output_values[i], T(i)); + } +} + +} // namespace +} // namespace nb
diff --git a/src/nb/nb.gyp b/src/nb/nb.gyp index 3780eb9..f87d42a 100644 --- a/src/nb/nb.gyp +++ b/src/nb/nb.gyp
@@ -24,6 +24,7 @@ 'allocator.h', 'allocator_decorator.cc', 'allocator_decorator.h', + 'atomic.h', 'fixed_no_free_allocator.cc', 'fixed_no_free_allocator.h', 'memory_pool.cc', @@ -38,6 +39,7 @@ 'scoped_ptr.h', 'thread_collision_warner.cc', 'thread_collision_warner.h', + 'thread_local_object.h', ], 'dependencies': [ @@ -60,9 +62,11 @@ 'target_name': 'nb_test', 'type': '<(gtest_target_type)', 'sources': [ + 'atomic_test.cc', 'fixed_no_free_allocator_test.cc', 'reuse_allocator_test.cc', 'run_all_unittests.cc', + 'test_thread.h', 'thread_local_object_test.cc', ], 'dependencies': [
diff --git a/src/nb/test_thread.h b/src/nb/test_thread.h new file mode 100644 index 0000000..0ea5768 --- /dev/null +++ b/src/nb/test_thread.h
@@ -0,0 +1,73 @@ +// Copyright 2016 Google Inc. 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. + +#ifndef NB_TEST_THREAD_H_ +#define NB_TEST_THREAD_H_ + +#include "starboard/configuration.h" +#include "starboard/thread.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace nb { + +// TestThread that is a bare bones class wrapper around Starboard +// thread. Subclasses must override Run(). +class TestThread { + public: + TestThread() : thread_(kSbThreadInvalid) {} + virtual ~TestThread() {} + + // Subclasses should override the Run method. + virtual void Run() = 0; + + // Calls SbThreadCreate() with default parameters. + void Start() { + SbThreadEntryPoint entry_point = ThreadEntryPoint; + + thread_ = SbThreadCreate( + 0, // default stack_size. + kSbThreadNoPriority, // default priority. + kSbThreadNoAffinity, // default affinity. + true, // joinable. + "TestThread", + entry_point, + this); + + if (kSbThreadInvalid == thread_) { + ADD_FAILURE_AT(__FILE__, __LINE__) << "Invalid thread."; + } + return; + } + + void Join() { + if (!SbThreadJoin(thread_, NULL)) { + ADD_FAILURE_AT(__FILE__, __LINE__) << "Could not join thread."; + } + } + + private: + static void* ThreadEntryPoint(void* ptr) { + TestThread* this_ptr = static_cast<TestThread*>(ptr); + this_ptr->Run(); + return NULL; + } + + SbThread thread_; + + SB_DISALLOW_COPY_AND_ASSIGN(TestThread); +}; + +} // namespace nb. + +#endif // NB_TEST_THREAD_H_
diff --git a/src/nb/thread_local_object.h b/src/nb/thread_local_object.h index 4b6a7ab..a303f5a 100644 --- a/src/nb/thread_local_object.h +++ b/src/nb/thread_local_object.h
@@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef BASE_THREADING_THREAD_LOCAL_OBJECT_H_ -#define BASE_THREADING_THREAD_LOCAL_OBJECT_H_ +#ifndef NB_THREAD_LOCAL_OBJECT_H_ +#define NB_THREAD_LOCAL_OBJECT_H_ #include <set> @@ -24,7 +24,7 @@ #include "starboard/mutex.h" #include "starboard/thread.h" -namespace base { +namespace nb { // Like base::ThreadLocalPointer<T> but destroys objects. This is important // for using ThreadLocalObjects that aren't tied to a singleton, or for @@ -75,12 +75,14 @@ // Thread Local Objects are destroyed after this call. ~ThreadLocalObject() { CheckCurrentThreadAllowedToDestruct(); - SB_DCHECK(entry_set_.size() < 2) + if (SB_DLOG_IS_ON(FATAL)) { + SB_DCHECK(entry_set_.size() < 2) << "Logic error: Some threads may still be accessing the objects that " << "are about to be destroyed. Only one object is expected and that " << "should be for the main thread. The caller should ensure that " << "other threads that access this object are externally " << "synchronized."; + } // No locking is done because the entries should not be accessed by // different threads while this object is shutting down. If access is // occuring then the caller has a race condition, external to this class. @@ -209,6 +211,6 @@ SB_DISALLOW_COPY_AND_ASSIGN(ThreadLocalObject<Type>); }; -} // namespace base +} // namespace nb -#endif // BASE_THREADING_THREAD_LOCAL_H_ +#endif // NB_THREAD_LOCAL_OBJECT_H_
diff --git a/src/nb/thread_local_object_test.cc b/src/nb/thread_local_object_test.cc index 000c6f4..9fce6d6 100644 --- a/src/nb/thread_local_object_test.cc +++ b/src/nb/thread_local_object_test.cc
@@ -15,172 +15,31 @@ #include <map> #include <string> +#include "nb/test_thread.h" +#include "nb/atomic.h" #include "nb/thread_local_object.h" #include "nb/scoped_ptr.h" #include "starboard/mutex.h" #include "starboard/thread.h" - #include "testing/gtest/include/gtest/gtest.h" -namespace base { +namespace nb { namespace { -// Similar to C++11 std::atomic<T>. -// Atomic<T> may be instantiated with any TriviallyCopyable type T. -// Atomic<T> is neither copyable nor movable. -// TODO: Lift this class out into the library. -template <typename T> -class Atomic { - public: - // C++11 forbids a copy constructor for std::atomic<T>, it also forbids - // a move operation. - Atomic() : value_() {} - explicit Atomic(T v) : value_(v) {} - - // Checks whether the atomic operations on all objects of this type - // are lock-free. - // Returns true if the atomic operations on the objects of this type - // are lock-free, false otherwise. - // - // All atomic types may be implemented using mutexes or other locking - // operations, rather than using the lock-free atomic CPU instructions. - // Atomic types are also allowed to be sometimes lock-free, e.g. if only - // aligned memory accesses are naturally atomic on a given architecture, - // misaligned objects of the same type have to use locks. - bool is_lock_free() const { return false; } - bool is_lock_free() const volatile { return false; } - - // Atomically replaces the value of the atomic object - // and returns the value held previously. - T Swap(T new_val) { - int old_value = -1; - { - starboard::ScopedLock lock(mutex_); - old_value = value_; - value_ = new_val; - } - return old_value; - } - - // Atomically obtains the value of the atomic object. - T Get() const { - starboard::ScopedLock lock(mutex_); - return value_; - } - - // Returns the new updated value after the operation has been applied. - T Add(T val) { - starboard::ScopedLock lock(mutex_); - value_ += val; - return value_; - } - - // TrySwap(...) sets the new value if and only if "expected_old_value" - // matches the actual value during the atomic assignment operation. If this - // succeeds then true is returned. If there is a mismatch then the value is - // left unchanged and false is returned. - // Inputs: - // new_value: Attempt to set the value to this new value. - // expected_old_value: A test condition for success. If the actual value - // matches the expected_old_value then the swap will succeed. - // optional_actual_value: If non-null, then the actual value at the time - // of the attempted operation is set to this value. - bool TrySwap(T new_value, T expected_old_value, - T* optional_actual_value) { - starboard::ScopedLock lock(mutex_); - if (optional_actual_value) { - *optional_actual_value = value_; - } - if (expected_old_value == value_) { - value_ = new_value; - return true; - } - return false; - } - - private: - T value_; - starboard::Mutex mutex_; -}; - -// Simple atomic int class. This could be optimized for speed using -// compiler intrinsics for concurrent integer modification. -class AtomicInt : public Atomic<int> { - public: - AtomicInt() : Atomic<int>(0) {} - explicit AtomicInt(int initial_val) : Atomic<int>(initial_val) {} - void Increment() { Add(1); } - void Decrement() { Add(-1); } -}; - -// Simple atomic bool class. This could be optimized for speed using -// compiler intrinsics for concurrent integer modification. -class AtomicBool : public Atomic<bool> { - public: - AtomicBool() : Atomic<bool>(false) {} - explicit AtomicBool(bool initial_val) : Atomic<bool>(initial_val) {} -}; - -// AbstractTestThread that is a bare bones class wrapper around Starboard -// thread. Subclasses must override Run(). -// TODO: Move this to nplb/thread_helpers.h -class AbstractTestThread { - public: - explicit AbstractTestThread() : thread_(kSbThreadInvalid) {} - virtual ~AbstractTestThread() {} - - // Subclasses should override the Run method. - virtual void Run() = 0; - - // Calls SbThreadCreate() with default parameters. - void Start() { - SbThreadEntryPoint entry_point = ThreadEntryPoint; - - thread_ = SbThreadCreate( - 0, // default stack_size. - kSbThreadNoPriority, // default priority. - kSbThreadNoAffinity, // default affinity. - true, // joinable. - "AbstractTestThread", - entry_point, - this); - - if (kSbThreadInvalid == thread_) { - ADD_FAILURE_AT(__FILE__, __LINE__) << "Invalid thread."; - } - return; - } - - void Join() { - if (!SbThreadJoin(thread_, NULL)) { - ADD_FAILURE_AT(__FILE__, __LINE__) << "Could not join thread."; - } - } - - private: - static void* ThreadEntryPoint(void* ptr) { - AbstractTestThread* this_ptr = static_cast<AbstractTestThread*>(ptr); - this_ptr->Run(); - return NULL; - } - - SbThread thread_; -}; - // Simple class that counts the number of instances alive. struct CountsInstances { - CountsInstances() { s_instances_.Increment(); } - ~CountsInstances() { s_instances_.Decrement(); } - static AtomicInt s_instances_; - static int NumInstances() { return s_instances_.Get(); } - static void ResetNumInstances() { s_instances_.Swap(0); } + CountsInstances() { s_instances_.increment(); } + ~CountsInstances() { s_instances_.decrement(); } + static atomic_int32_t s_instances_; + static int NumInstances() { return s_instances_.load(); } + static void ResetNumInstances() { s_instances_.exchange(0); } }; -AtomicInt CountsInstances::s_instances_(0); +nb::atomic_int32_t CountsInstances::s_instances_(0); // A simple thread that just creates the an object from the supplied // ThreadLocalObject<T> and then exits. template <typename TYPE> -class CreateThreadLocalObjectThenExit : public AbstractTestThread { +class CreateThreadLocalObjectThenExit : public TestThread { public: explicit CreateThreadLocalObjectThenExit( ThreadLocalObject<TYPE>* tlo) : tlo_(tlo) {} @@ -196,7 +55,7 @@ // A simple thread that just deletes the object supplied on a thread and then // exists. template <typename TYPE> -class DestroyTypeOnThread : public AbstractTestThread { +class DestroyTypeOnThread : public TestThread { public: explicit DestroyTypeOnThread(TYPE* ptr) : ptr_(ptr) {} @@ -285,7 +144,7 @@ nb::scoped_ptr<TLO> tlo(new TLO); { - AbstractTestThread* thread = + TestThread* thread = new CreateThreadLocalObjectThenExit<CountsInstances>(tlo.get()); thread->Start(); thread->Join(); @@ -318,7 +177,7 @@ // Thread will simply create the thread local object (CountsInstances) // and then return. - nb::scoped_ptr<AbstractTestThread> thread_ptr( + nb::scoped_ptr<TestThread> thread_ptr( new CreateThreadLocalObjectThenExit<CountsInstances>(tlo)); thread_ptr->Start(); // Object is now created. thread_ptr->Join(); // ...then destroyed. @@ -342,5 +201,4 @@ } } // anonymous namespace -} // namespace base - +} // nb namespace
diff --git a/src/starboard/audio_sink.h b/src/starboard/audio_sink.h index 59f507b..790741a 100644 --- a/src/starboard/audio_sink.h +++ b/src/starboard/audio_sink.h
@@ -12,7 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -// An interface to output raw audio data. +// Module Overview: Starboard Audio Sink API +// +// Provides an interface to output raw audio data. #ifndef STARBOARD_AUDIO_SINK_H_ #define STARBOARD_AUDIO_SINK_H_ @@ -69,37 +71,49 @@ // --- Functions ------------------------------------------------------------- -// Returns whether the given audio sink handle is valid. +// Indicates whether the given audio sink handle is valid. +// +// |audio_sink|: The audio sink handle to check. SB_EXPORT bool SbAudioSinkIsValid(SbAudioSink audio_sink); // Creates an audio sink for the specified |channels| and -// |sampling_frequency_hz|, acquiring all resources needed to operate it, and -// returning an opaque handle to it. -// -// |frame_buffers| is an array of pointers to sample data. If the sink is -// operating in interleaved mode, the array contains only one element, which is -// an array containing |frames_per_channel| * |channels| samples. If the sink -// is operating in planar mode, the number of elements in the array will be the -// same as |channels|, each of the elements will be an array of -// |frames_per_channel| samples. The caller has to ensure that |frame_buffers| -// is valid until SbAudioSinkDestroy is called. -// -// |update_source_status_func| cannot be NULL. The audio sink will call it on -// an internal thread to query the status of the source. -// -// |consume_frames_func| cannot be NULL. The audio sink will call it on an -// internal thread to report consumed frames. -// -// |context| will be passed back into all callbacks, and is generally used to -// point at a class or struct that contains state associated with the audio -// sink. -// -// The audio sink will start to call |update_source_status_func| immediately -// after SbAudioSinkCreate is called, even before it returns. The caller has -// to ensure that the above callbacks returns meaningful values in this case. +// |sampling_frequency_hz|, acquires all resources needed to operate the +// audio sink, and returns an opaque handle to the audio sink. // // If the particular platform doesn't support the requested audio sink, the // function returns kSbAudioSinkInvalid without calling any of the callbacks. +// +// |channels|: The number of audio channels, such as left and right channels +// in stereo audio. +// |sampling_frequency_hz|: The sample frequency of the audio data being +// streamed. For example, 22,000 Hz means 22,000 sample elements represents +// one second of audio data. +// |audio_sample_type|: The type of each sample of the audio data -- +// |int16|, |float32|, etc. +// |audio_frame_storage_type|: Indicates whether frames are interleaved or +// planar. +// |frame_buffers|: An array of pointers to sample data. +// - If the sink is operating in interleaved mode, the array contains only +// one element, which is an array containing (|frames_per_channel| * +// |channels|) samples. +// - If the sink is operating in planar mode, the number of elements in the +// array is the same as |channels|, and each element is an array of +// |frames_per_channel| samples. The caller has to ensure that +// |frame_buffers| is valid until SbAudioSinkDestroy is called. +// |frames_per_channel|: The size of the frame buffers, in units of the +// number of samples per channel. The frame, in this case, represents a +// group of samples at the same media time, one for each channel. +// |update_source_status_func|: The audio sink calls this function on an +// internal thread to query the status of the source. The value cannot be NULL. +// |consume_frames_func|: The audio sink calls this function on an internal +// thread to report consumed frames. The value cannot be NULL. +// |context|: A value that is passed back to all callbacks and is generally +// used to point at a class or struct that contains state associated with the +// audio sink. +// |update_source_status_func|: A function that the audio sink starts to call +// immediately after SbAudioSinkCreate is called, even before it returns. +// The caller has to ensure that the callback functions above return +// meaningful values in this case. SB_EXPORT SbAudioSink SbAudioSinkCreate(int channels, int sampling_frequency_hz, @@ -111,32 +125,36 @@ SbAudioSinkConsumeFramesFunc consume_frames_func, void* context); -// Destroys |audio_sink|, freeing all associated resources. It will wait until -// all callbacks in progress is finished before returning. Upon returning of -// this function, no callbacks passed into SbAudioSinkCreate will be called -// further. This function can be called on any thread but cannot be called +// Destroys |audio_sink|, freeing all associated resources. Before +// returning, the function waits until all callbacks that are in progress +// have finished. After the function returns, no further calls are made +// callbacks passed into SbAudioSinkCreate. In addition, you can not pass +// |audio_sink| to any other SbAudioSink functions after SbAudioSinkDestroy +// has been called on it. +// +// This function can be called on any thread. However, it cannot be called // within any of the callbacks passed into SbAudioSinkCreate. -// It is not allowed to pass |audio_sink| into any other SbAudioSink function -// once SbAudioSinkDestroy has been called on it. +// +// |audio_sink|: The audio sink to destroy. SB_EXPORT void SbAudioSinkDestroy(SbAudioSink audio_sink); -// Returns the maximum channel supported on the platform. +// Returns the maximum number of channels supported on the platform. For +// example, the number would be |2| if the platform only supports stereo. SB_EXPORT int SbAudioSinkGetMaxChannels(); -// Returns the nearest supported sample rate of |sampling_frequency_hz|. On -// platforms that don't support all sample rates, it is the caller's +// Returns the supported sample rate closest to |sampling_frequency_hz|. +// On platforms that don't support all sample rates, it is the caller's // responsibility to resample the audio frames into the supported sample rate // returned by this function. SB_EXPORT int SbAudioSinkGetNearestSupportedSampleFrequency( int sampling_frequency_hz); -// Returns true if the particular SbMediaAudioSampleType is supported on this -// platform. +// Indicates whether |audio_sample_type| is supported on this platform. SB_EXPORT bool SbAudioSinkIsAudioSampleTypeSupported( SbMediaAudioSampleType audio_sample_type); -// Returns true if the particular SbMediaAudioFrameStorageType is supported on -// this platform. +// Indicates whether |audio_frame_storage_type| is supported on this +// platform. SB_EXPORT bool SbAudioSinkIsAudioFrameStorageTypeSupported( SbMediaAudioFrameStorageType audio_frame_storage_type);
diff --git a/src/starboard/client_porting/eztime/eztime.gyp b/src/starboard/client_porting/eztime/eztime.gyp index 009c29f..70f51e6 100644 --- a/src/starboard/client_porting/eztime/eztime.gyp +++ b/src/starboard/client_porting/eztime/eztime.gyp
@@ -32,9 +32,9 @@ 'target_name': 'eztime_test', 'type': '<(gtest_target_type)', 'sources': [ + '<(DEPTH)/starboard/common/test_main.cc', 'test_constants.h', 'eztime_test.cc', - '<(DEPTH)/starboard/nplb/main.cc', ], 'dependencies': [ '<(DEPTH)/testing/gmock.gyp:gmock',
diff --git a/src/starboard/nplb/main.cc b/src/starboard/common/test_main.cc similarity index 100% rename from src/starboard/nplb/main.cc rename to src/starboard/common/test_main.cc
diff --git a/src/starboard/creator/ci20/configuration_public.h b/src/starboard/creator/ci20/configuration_public.h deleted file mode 100644 index cd85a36..0000000 --- a/src/starboard/creator/ci20/configuration_public.h +++ /dev/null
@@ -1,95 +0,0 @@ -// Copyright 2016 Google Inc. 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. - -// The Starboard configuration for Creator Ci20 Debian. - -// Other source files should never include this header directly, but should -// include the generic "starboard/configuration.h" instead. - -#ifndef STARBOARD_CREATOR_CI20_CONFIGURATION_PUBLIC_H_ -#define STARBOARD_CREATOR_CI20_CONFIGURATION_PUBLIC_H_ - -// --- Architecture Configuration -------------------------------------------- - -// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be -// automatically set based on this. -#define SB_IS_BIG_ENDIAN 0 - -// Whether the current platform is an ARM architecture. -#define SB_IS_ARCH_ARM 0 - -// Whether the current platform is a MIPS architecture. -#define SB_IS_ARCH_MIPS 1 - -// Whether the current platform is a PPC architecture. -#define SB_IS_ARCH_PPC 0 - -// Whether the current platform is an x86 architecture. -#define SB_IS_ARCH_X86 0 - -// Whether the current platform is a 32-bit architecture. -#define SB_IS_32_BIT 1 - -// Whether the current platform is a 64-bit architecture. -#define SB_IS_64_BIT 0 - -// Whether the current platform's pointers are 32-bit. -// Whether the current platform's longs are 32-bit. -#if SB_IS(32_BIT) -#define SB_HAS_32_BIT_POINTERS 1 -#define SB_HAS_32_BIT_LONG 1 -#else -#define SB_HAS_32_BIT_POINTERS 0 -#define SB_HAS_32_BIT_LONG 0 -#endif - -// Whether the current platform's pointers are 64-bit. -// Whether the current platform's longs are 64-bit. -#if SB_IS(64_BIT) -#define SB_HAS_64_BIT_POINTERS 1 -#define SB_HAS_64_BIT_LONG 1 -#else -#define SB_HAS_64_BIT_POINTERS 0 -#define SB_HAS_64_BIT_LONG 0 -#endif - -// Configuration parameters that allow the application to make some general -// compile-time decisions with respect to the the number of cores likely to be -// available on this platform. For a definitive measure, the application should -// still call SbSystemGetNumberOfProcessors at runtime. - -// Whether the current platform is expected to have many cores (> 6), or a -// wildly varying number of cores. -#define SB_HAS_MANY_CORES 0 - -// Whether the current platform is expected to have exactly 1 core. -#define SB_HAS_1_CORE 0 - -// Whether the current platform is expected to have exactly 2 cores. -#define SB_HAS_2_CORES 1 - -// Whether the current platform is expected to have exactly 4 cores. -#define SB_HAS_4_CORES 0 - -// Whether the current platform is expected to have exactly 6 cores. -#define SB_HAS_6_CORES 0 - -// Whether the current platform's thread scheduler will automatically balance -// threads between cores, as opposed to systems where threads will only ever run -// on the specifically pinned core. -#define SB_HAS_CROSS_CORE_SCHEDULER 1 - -#include "starboard/creator/shared/configuration_public.h" - -#endif // STARBOARD_CREATOR_CI20_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/creator/ci20directfb/README.md b/src/starboard/creator/ci20directfb/README.md new file mode 100644 index 0000000..e0c1251 --- /dev/null +++ b/src/starboard/creator/ci20directfb/README.md
@@ -0,0 +1,4 @@ +# Setting up Starboard to use DirectFB on a Creator Ci20 + +See `starboard/raspi/directfb/README.md`. The steps for getting directfb +running on the Ci20 are identical.
diff --git a/src/starboard/creator/ci20/atomic_public.h b/src/starboard/creator/ci20directfb/atomic_public.h similarity index 79% copy from src/starboard/creator/ci20/atomic_public.h copy to src/starboard/creator/ci20directfb/atomic_public.h index 3b48d2e..2a182e7 100644 --- a/src/starboard/creator/ci20/atomic_public.h +++ b/src/starboard/creator/ci20directfb/atomic_public.h
@@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef STARBOARD_CREATOR_CI20_ATOMIC_PUBLIC_H_ -#define STARBOARD_CREATOR_CI20_ATOMIC_PUBLIC_H_ +#ifndef STARBOARD_CREATOR_CI20DIRECTFB_ATOMIC_PUBLIC_H_ +#define STARBOARD_CREATOR_CI20DIRECTFB_ATOMIC_PUBLIC_H_ #include "starboard/linux/shared/atomic_public.h" -#endif // STARBOARD_CREATOR_CI20_ATOMIC_PUBLIC_H_ +#endif // STARBOARD_CREATOR_CI20DIRECTFB_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/creator/ci20directfb/configuration_public.h b/src/starboard/creator/ci20directfb/configuration_public.h new file mode 100644 index 0000000..651c203 --- /dev/null +++ b/src/starboard/creator/ci20directfb/configuration_public.h
@@ -0,0 +1,46 @@ +// Copyright 2016 Google Inc. 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. + +#ifndef STARBOARD_CREATOR_CI20DIRECTFB_CONFIGURATION_PUBLIC_H_ +#define STARBOARD_CREATOR_CI20DIRECTFB_CONFIGURATION_PUBLIC_H_ + +#include "starboard/creator/shared/configuration_public.h" + +// Indicates whether or not the given platform supports rendering of NV12 +// textures. These textures typically originate from video decoders. +#undef SB_HAS_NV12_TEXTURE_SUPPORT +#define SB_HAS_NV12_TEXTURE_SUPPORT 0 + +// This configuration supports the blitter API (implemented via DirectFB). +#undef SB_HAS_BLITTER +#define SB_HAS_BLITTER 1 + +// Unfortunately, DirectFB does not support bilinear filtering. According to +// http://osdir.com/ml/graphics.directfb.user/2008-06/msg00028.html, "smooth +// scaling is not supported in conjunction with blending", and we need blending +// more. +#undef SB_HAS_BILINEAR_FILTERING_SUPPORT +#define SB_HAS_BILINEAR_FILTERING_SUPPORT 0 + +// DirectFB's only 32-bit RGBA color format is word-order ARGB. This translates +// to byte-order ARGB for big endian platforms and byte-order BGRA for +// little-endian platforms. +#undef SB_PREFERRED_RGBA_BYTE_ORDER +#if SB_IS(BIG_ENDIAN) +#define SB_PREFERRED_RGBA_BYTE_ORDER SB_PREFERRED_RGBA_BYTE_ORDER_ARGB +#else +#define SB_PREFERRED_RGBA_BYTE_ORDER SB_PREFERRED_RGBA_BYTE_ORDER_BGRA +#endif + +#endif // STARBOARD_CREATOR_CI20DIRECTFB_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/creator/ci20directfb/gyp_configuration.gypi b/src/starboard/creator/ci20directfb/gyp_configuration.gypi new file mode 100644 index 0000000..8d8c263 --- /dev/null +++ b/src/starboard/creator/ci20directfb/gyp_configuration.gypi
@@ -0,0 +1,45 @@ +# Copyright 2016 Google Inc. 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. + +{ + 'variables': { + 'platform_libraries': [ + '-ldirectfb', + '-ldirect', + ], + 'gl_type': 'none', + }, + + 'target_defaults': { + 'default_configuration': 'creator-ci20directfb_debug', + 'configurations': { + 'creator-ci20directfb_debug': { + 'inherit_from': ['debug_base'], + }, + 'creator-ci20directfb_devel': { + 'inherit_from': ['devel_base'], + }, + 'creator-ci20directfb_qa': { + 'inherit_from': ['qa_base'], + }, + 'creator-ci20directfb_gold': { + 'inherit_from': ['gold_base'], + }, + }, # end of configurations + }, + + 'includes': [ + '../shared/gyp_configuration.gypi', + ], +}
diff --git a/src/starboard/creator/ci20directfb/gyp_configuration.py b/src/starboard/creator/ci20directfb/gyp_configuration.py new file mode 100644 index 0000000..4e712f5 --- /dev/null +++ b/src/starboard/creator/ci20directfb/gyp_configuration.py
@@ -0,0 +1,32 @@ +# Copyright 2016 Google Inc. 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. +"""Starboard Creator Ci20 DirectFB platform configuration for gyp_cobalt.""" + +import logging +import os +import sys + +# Import the shared Creator platform configuration. +sys.path.append( + os.path.realpath( + os.path.join(os.path.dirname(__file__), os.pardir, 'shared'))) +import gyp_configuration # pylint: disable=import-self,g-import-not-at-top + + +def CreatePlatformConfig(): + try: + return gyp_configuration.PlatformConfig('creator-ci20directfb') + except RuntimeError as e: + logging.critical(e) + return None
diff --git a/src/starboard/creator/ci20directfb/main.cc b/src/starboard/creator/ci20directfb/main.cc new file mode 100644 index 0000000..68d7761 --- /dev/null +++ b/src/starboard/creator/ci20directfb/main.cc
@@ -0,0 +1,29 @@ +// Copyright 2016 Google Inc. 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 "starboard/configuration.h" +#include "starboard/shared/directfb/application_directfb.h" +#include "starboard/shared/signal/crash_signals.h" +#include "starboard/shared/signal/suspend_signals.h" + +int main(int argc, char** argv) { + tzset(); + starboard::shared::signal::InstallCrashSignalHandlers(); + starboard::shared::signal::InstallSuspendSignalHandlers(); + starboard::ApplicationDirectFB application; + int result = application.Run(argc, argv); + starboard::shared::signal::UninstallSuspendSignalHandlers(); + starboard::shared::signal::UninstallCrashSignalHandlers(); + return result; +}
diff --git a/src/starboard/creator/ci20/starboard_platform.gyp b/src/starboard/creator/ci20directfb/starboard_platform.gyp similarity index 84% copy from src/starboard/creator/ci20/starboard_platform.gyp copy to src/starboard/creator/ci20directfb/starboard_platform.gyp index c6a9f11..b695c91 100644 --- a/src/starboard/creator/ci20/starboard_platform.gyp +++ b/src/starboard/creator/ci20directfb/starboard_platform.gyp
@@ -25,14 +25,14 @@ 'target_name': 'starboard_platform', 'type': 'static_library', 'sources': [ - '<(DEPTH)/starboard/creator/ci20/configuration_public.h', - '<(DEPTH)/starboard/creator/ci20/system_get_property.cc', + '<(DEPTH)/starboard/creator/ci20directfb/configuration_public.h', + '<(DEPTH)/starboard/creator/ci20directfb/main.cc', + '<(DEPTH)/starboard/creator/ci20directfb/system_get_property.cc', '<(DEPTH)/starboard/linux/shared/atomic_public.h', '<(DEPTH)/starboard/linux/shared/system_get_connection_type.cc', '<(DEPTH)/starboard/linux/shared/system_get_device_type.cc', '<(DEPTH)/starboard/linux/shared/system_get_path.cc', '<(DEPTH)/starboard/linux/shared/system_has_capability.cc', - '<(DEPTH)/starboard/linux/x64x11/main.cc', '<(DEPTH)/starboard/shared/alsa/alsa_audio_sink_type.cc', '<(DEPTH)/starboard/shared/alsa/alsa_audio_sink_type.h', '<(DEPTH)/starboard/shared/alsa/alsa_util.cc', @@ -41,6 +41,43 @@ '<(DEPTH)/starboard/shared/alsa/audio_sink_get_nearest_supported_sample_frequency.cc', '<(DEPTH)/starboard/shared/alsa/audio_sink_is_audio_frame_storage_type_supported.cc', '<(DEPTH)/starboard/shared/alsa/audio_sink_is_audio_sample_type_supported.cc', + '<(DEPTH)/starboard/shared/directfb/application_directfb.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_blit_rect_to_rect.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_create_context.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_create_default_device.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_create_pixel_data.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_create_render_target_surface.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_create_surface_from_pixel_data.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_create_swap_chain_from_window.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_destroy_context.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_destroy_device.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_destroy_pixel_data.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_destroy_surface.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_destroy_swap_chain.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_download_surface_pixels.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_fill_rect.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_flip_swap_chain.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_flush_context.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_get_max_contexts.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_get_pixel_data_pitch_in_bytes.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_get_pixel_data_pointer.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_get_render_target_from_surface.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_get_render_target_from_swap_chain.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_get_surface_info.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_internal.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_is_pixel_format_supported_by_download_surface_pixels.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_is_pixel_format_supported_by_pixel_data.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_is_surface_format_supported_by_render_target_surface.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_set_blending.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_set_color.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_set_modulate_blits_with_color.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_set_render_target.cc', + '<(DEPTH)/starboard/shared/directfb/blitter_set_scissor.cc', + '<(DEPTH)/starboard/shared/directfb/window_create.cc', + '<(DEPTH)/starboard/shared/directfb/window_destroy.cc', + '<(DEPTH)/starboard/shared/directfb/window_get_platform_handle.cc', + '<(DEPTH)/starboard/shared/directfb/window_get_size.cc', + '<(DEPTH)/starboard/shared/directfb/window_internal.cc', '<(DEPTH)/starboard/shared/dlmalloc/memory_allocate_aligned_unchecked.cc', '<(DEPTH)/starboard/shared/dlmalloc/memory_allocate_unchecked.cc', '<(DEPTH)/starboard/shared/dlmalloc/memory_free.cc', @@ -210,6 +247,8 @@ '<(DEPTH)/starboard/shared/starboard/audio_sink/audio_sink_is_valid.cc', '<(DEPTH)/starboard/shared/starboard/audio_sink/stub_audio_sink_type.cc', '<(DEPTH)/starboard/shared/starboard/audio_sink/stub_audio_sink_type.h', + '<(DEPTH)/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc', + '<(DEPTH)/starboard/shared/starboard/blitter_blit_rects_to_rects.cc', '<(DEPTH)/starboard/shared/starboard/directory_can_open.cc', '<(DEPTH)/starboard/shared/starboard/event_cancel.cc', '<(DEPTH)/starboard/shared/starboard/event_schedule.cc', @@ -275,12 +314,9 @@ '<(DEPTH)/starboard/shared/stub/system_get_used_gpu_memory.cc', '<(DEPTH)/starboard/shared/stub/system_hide_splash_screen.cc', '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc', - '<(DEPTH)/starboard/shared/x11/application_x11.cc', - '<(DEPTH)/starboard/shared/x11/window_create.cc', - '<(DEPTH)/starboard/shared/x11/window_destroy.cc', - '<(DEPTH)/starboard/shared/x11/window_get_platform_handle.cc', - '<(DEPTH)/starboard/shared/x11/window_get_size.cc', - '<(DEPTH)/starboard/shared/x11/window_internal.cc', + ], + 'include_dirs': [ + '<(sysroot)/mipsel-r2-hard/usr/include/directfb', ], 'defines': [ # This must be defined when building Starboard, and must not when
diff --git a/src/starboard/creator/ci20/system_get_property.cc b/src/starboard/creator/ci20directfb/system_get_property.cc similarity index 95% copy from src/starboard/creator/ci20/system_get_property.cc copy to src/starboard/creator/ci20directfb/system_get_property.cc index 8a7a795..51ca55f 100644 --- a/src/starboard/creator/ci20/system_get_property.cc +++ b/src/starboard/creator/ci20directfb/system_get_property.cc
@@ -20,7 +20,7 @@ namespace { const char* kFriendlyName = "Creator Ci20"; -const char* kPlatformName = "Creator Ci20 JZ4780"; +const char* kPlatformName = "DirectFB; Creator Ci20 JZ4780"; bool CopyStringAndTestIfSuccess(char* out_value, int value_length, @@ -47,6 +47,7 @@ case kSbSystemPropertyModelName: case kSbSystemPropertyModelYear: case kSbSystemPropertyNetworkOperatorName: + case kSbSystemPropertySpeechApiKey: return false; case kSbSystemPropertyFriendlyName:
diff --git a/src/starboard/creator/ci20/thread_types_public.h b/src/starboard/creator/ci20directfb/thread_types_public.h similarity index 77% copy from src/starboard/creator/ci20/thread_types_public.h copy to src/starboard/creator/ci20directfb/thread_types_public.h index ec9eedf..b531032 100644 --- a/src/starboard/creator/ci20/thread_types_public.h +++ b/src/starboard/creator/ci20directfb/thread_types_public.h
@@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef STARBOARD_CREATOR_CI20_THREAD_TYPES_PUBLIC_H_ -#define STARBOARD_CREATOR_CI20_THREAD_TYPES_PUBLIC_H_ +#ifndef STARBOARD_CREATOR_CI20DIRECTFB_THREAD_TYPES_PUBLIC_H_ +#define STARBOARD_CREATOR_CI20DIRECTFB_THREAD_TYPES_PUBLIC_H_ #include "starboard/linux/shared/thread_types_public.h" -#endif // STARBOARD_CREATOR_CI20_THREAD_TYPES_PUBLIC_H_ +#endif // STARBOARD_CREATOR_CI20DIRECTFB_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/creator/ci20/atomic_public.h b/src/starboard/creator/ci20x11/atomic_public.h similarity index 80% rename from src/starboard/creator/ci20/atomic_public.h rename to src/starboard/creator/ci20x11/atomic_public.h index 3b48d2e..932fe9d 100644 --- a/src/starboard/creator/ci20/atomic_public.h +++ b/src/starboard/creator/ci20x11/atomic_public.h
@@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef STARBOARD_CREATOR_CI20_ATOMIC_PUBLIC_H_ -#define STARBOARD_CREATOR_CI20_ATOMIC_PUBLIC_H_ +#ifndef STARBOARD_CREATOR_CI20X11_ATOMIC_PUBLIC_H_ +#define STARBOARD_CREATOR_CI20X11_ATOMIC_PUBLIC_H_ #include "starboard/linux/shared/atomic_public.h" -#endif // STARBOARD_CREATOR_CI20_ATOMIC_PUBLIC_H_ +#endif // STARBOARD_CREATOR_CI20X11_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/shared/stub/microphone_get_speech_api_key.cc b/src/starboard/creator/ci20x11/configuration_public.h similarity index 71% rename from src/starboard/shared/stub/microphone_get_speech_api_key.cc rename to src/starboard/creator/ci20x11/configuration_public.h index 98038b4..4c00bad 100644 --- a/src/starboard/shared/stub/microphone_get_speech_api_key.cc +++ b/src/starboard/creator/ci20x11/configuration_public.h
@@ -12,12 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "starboard/microphone.h" +#ifndef STARBOARD_CREATOR_CI20X11_CONFIGURATION_PUBLIC_H_ +#define STARBOARD_CREATOR_CI20X11_CONFIGURATION_PUBLIC_H_ -#if SB_HAS(MICROPHONE) && SB_VERSION(2) +#include "starboard/creator/shared/configuration_public.h" -const char* SbMicrophoneGetSpeechApiKey() { - return ""; -} - -#endif // SB_HAS(MICROPHONE) && SB_VERSION(2) +#endif // STARBOARD_CREATOR_CI20X11_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/creator/ci20x11/gyp_configuration.gypi b/src/starboard/creator/ci20x11/gyp_configuration.gypi new file mode 100644 index 0000000..a2ea1b8 --- /dev/null +++ b/src/starboard/creator/ci20x11/gyp_configuration.gypi
@@ -0,0 +1,48 @@ +# Copyright 2016 Google Inc. 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. + +{ + 'variables': { + 'platform_libraries': [ + '-lEGL', + '-lGLESv2', + '-lX11', + '-lXcomposite', + '-lXext', + '-lXrender', + ], + }, + + 'target_defaults': { + 'default_configuration': 'creator-ci20x11_debug', + 'configurations': { + 'creator-ci20x11_debug': { + 'inherit_from': ['debug_base'], + }, + 'creator-ci20x11_devel': { + 'inherit_from': ['devel_base'], + }, + 'creator-ci20x11_qa': { + 'inherit_from': ['qa_base'], + }, + 'creator-ci20x11_gold': { + 'inherit_from': ['gold_base'], + }, + }, # end of configurations + }, + + 'includes': [ + '../shared/gyp_configuration.gypi', + ], +}
diff --git a/src/starboard/creator/ci20x11/gyp_configuration.py b/src/starboard/creator/ci20x11/gyp_configuration.py new file mode 100644 index 0000000..1c062df --- /dev/null +++ b/src/starboard/creator/ci20x11/gyp_configuration.py
@@ -0,0 +1,32 @@ +# Copyright 2016 Google Inc. 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. +"""Starboard Creator Ci20 X11 platform configuration for gyp_cobalt.""" + +import logging +import os +import sys + +# Import the shared Creator platform configuration. +sys.path.append( + os.path.realpath( + os.path.join(os.path.dirname(__file__), os.pardir, 'shared'))) +import gyp_configuration # pylint: disable=import-self,g-import-not-at-top + + +def CreatePlatformConfig(): + try: + return gyp_configuration.PlatformConfig('creator-ci20x11') + except RuntimeError as e: + logging.critical(e) + return None
diff --git a/src/starboard/creator/ci20/main.cc b/src/starboard/creator/ci20x11/main.cc similarity index 100% rename from src/starboard/creator/ci20/main.cc rename to src/starboard/creator/ci20x11/main.cc
diff --git a/src/starboard/creator/ci20/starboard_platform.gyp b/src/starboard/creator/ci20x11/starboard_platform.gyp similarity index 97% rename from src/starboard/creator/ci20/starboard_platform.gyp rename to src/starboard/creator/ci20x11/starboard_platform.gyp index c6a9f11..bab02c6 100644 --- a/src/starboard/creator/ci20/starboard_platform.gyp +++ b/src/starboard/creator/ci20x11/starboard_platform.gyp
@@ -25,14 +25,15 @@ 'target_name': 'starboard_platform', 'type': 'static_library', 'sources': [ - '<(DEPTH)/starboard/creator/ci20/configuration_public.h', - '<(DEPTH)/starboard/creator/ci20/system_get_property.cc', + '<(DEPTH)/starboard/creator/ci20x11/atomic_public.h', + '<(DEPTH)/starboard/creator/ci20x11/configuration_public.h', + '<(DEPTH)/starboard/creator/ci20x11/main.cc', + '<(DEPTH)/starboard/creator/ci20x11/system_get_property.cc', '<(DEPTH)/starboard/linux/shared/atomic_public.h', '<(DEPTH)/starboard/linux/shared/system_get_connection_type.cc', '<(DEPTH)/starboard/linux/shared/system_get_device_type.cc', '<(DEPTH)/starboard/linux/shared/system_get_path.cc', '<(DEPTH)/starboard/linux/shared/system_has_capability.cc', - '<(DEPTH)/starboard/linux/x64x11/main.cc', '<(DEPTH)/starboard/shared/alsa/alsa_audio_sink_type.cc', '<(DEPTH)/starboard/shared/alsa/alsa_audio_sink_type.h', '<(DEPTH)/starboard/shared/alsa/alsa_util.cc', @@ -226,8 +227,8 @@ '<(DEPTH)/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc', '<(DEPTH)/starboard/shared/starboard/media/media_is_output_protected.cc', '<(DEPTH)/starboard/shared/starboard/media/media_set_output_protection.cc', - '<(DEPTH)/starboard/shared/starboard/media/mime_parser.cc', - '<(DEPTH)/starboard/shared/starboard/media/mime_parser.h', + '<(DEPTH)/starboard/shared/starboard/media/mime_type.cc', + '<(DEPTH)/starboard/shared/starboard/media/mime_type.h', '<(DEPTH)/starboard/shared/starboard/new.cc', '<(DEPTH)/starboard/shared/starboard/player/filter/audio_decoder_internal.h', '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.cc',
diff --git a/src/starboard/creator/ci20/system_get_property.cc b/src/starboard/creator/ci20x11/system_get_property.cc similarity index 97% rename from src/starboard/creator/ci20/system_get_property.cc rename to src/starboard/creator/ci20x11/system_get_property.cc index 8a7a795..9d71165 100644 --- a/src/starboard/creator/ci20/system_get_property.cc +++ b/src/starboard/creator/ci20x11/system_get_property.cc
@@ -47,6 +47,7 @@ case kSbSystemPropertyModelName: case kSbSystemPropertyModelYear: case kSbSystemPropertyNetworkOperatorName: + case kSbSystemPropertySpeechApiKey: return false; case kSbSystemPropertyFriendlyName:
diff --git a/src/starboard/creator/ci20/thread_types_public.h b/src/starboard/creator/ci20x11/thread_types_public.h similarity index 79% rename from src/starboard/creator/ci20/thread_types_public.h rename to src/starboard/creator/ci20x11/thread_types_public.h index ec9eedf..7437a70 100644 --- a/src/starboard/creator/ci20/thread_types_public.h +++ b/src/starboard/creator/ci20x11/thread_types_public.h
@@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef STARBOARD_CREATOR_CI20_THREAD_TYPES_PUBLIC_H_ -#define STARBOARD_CREATOR_CI20_THREAD_TYPES_PUBLIC_H_ +#ifndef STARBOARD_CREATOR_CI20X11_THREAD_TYPES_PUBLIC_H_ +#define STARBOARD_CREATOR_CI20X11_THREAD_TYPES_PUBLIC_H_ #include "starboard/linux/shared/thread_types_public.h" -#endif // STARBOARD_CREATOR_CI20_THREAD_TYPES_PUBLIC_H_ +#endif // STARBOARD_CREATOR_CI20X11_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/creator/shared/configuration_public.h b/src/starboard/creator/shared/configuration_public.h index 8144c15..3574948 100644 --- a/src/starboard/creator/shared/configuration_public.h +++ b/src/starboard/creator/shared/configuration_public.h
@@ -17,8 +17,78 @@ #ifndef STARBOARD_CREATOR_SHARED_CONFIGURATION_PUBLIC_H_ #define STARBOARD_CREATOR_SHARED_CONFIGURATION_PUBLIC_H_ +// --- Architecture Configuration -------------------------------------------- + +// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be +// automatically set based on this. +#define SB_IS_BIG_ENDIAN 0 + +// Whether the current platform is an ARM architecture. +#define SB_IS_ARCH_ARM 0 + +// Whether the current platform is a MIPS architecture. +#define SB_IS_ARCH_MIPS 1 + +// Whether the current platform is a PPC architecture. +#define SB_IS_ARCH_PPC 0 + +// Whether the current platform is an x86 architecture. +#define SB_IS_ARCH_X86 0 + +// Whether the current platform is a 32-bit architecture. +#define SB_IS_32_BIT 1 + +// Whether the current platform is a 64-bit architecture. +#define SB_IS_64_BIT 0 + +// Whether the current platform's pointers are 32-bit. +// Whether the current platform's longs are 32-bit. +#if SB_IS(32_BIT) +#define SB_HAS_32_BIT_POINTERS 1 +#define SB_HAS_32_BIT_LONG 1 +#else +#define SB_HAS_32_BIT_POINTERS 0 +#define SB_HAS_32_BIT_LONG 0 +#endif + +// Whether the current platform's pointers are 64-bit. +// Whether the current platform's longs are 64-bit. +#if SB_IS(64_BIT) +#define SB_HAS_64_BIT_POINTERS 1 +#define SB_HAS_64_BIT_LONG 1 +#else +#define SB_HAS_64_BIT_POINTERS 0 +#define SB_HAS_64_BIT_LONG 0 +#endif + +// Configuration parameters that allow the application to make some general +// compile-time decisions with respect to the the number of cores likely to be +// available on this platform. For a definitive measure, the application should +// still call SbSystemGetNumberOfProcessors at runtime. + +// Whether the current platform is expected to have many cores (> 6), or a +// wildly varying number of cores. +#define SB_HAS_MANY_CORES 0 + +// Whether the current platform is expected to have exactly 1 core. +#define SB_HAS_1_CORE 0 + +// Whether the current platform is expected to have exactly 2 cores. +#define SB_HAS_2_CORES 1 + +// Whether the current platform is expected to have exactly 4 cores. +#define SB_HAS_4_CORES 0 + +// Whether the current platform is expected to have exactly 6 cores. +#define SB_HAS_6_CORES 0 + +// Whether the current platform's thread scheduler will automatically balance +// threads between cores, as opposed to systems where threads will only ever run +// on the specifically pinned core. +#define SB_HAS_CROSS_CORE_SCHEDULER 1 + // The API version implemented by this platform. -#define SB_API_VERSION 1 +#define SB_API_VERSION 2 // --- System Header Configuration ------------------------------------------- @@ -49,6 +119,9 @@ // Whether the current platform provides the standard header float.h. #define SB_HAS_FLOAT_H 1 +// Whether the current platform has microphone supported. +#define SB_HAS_MICROPHONE 0 + // Type detection for wchar_t. #if defined(__WCHAR_MAX__) && \ (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff) @@ -68,10 +141,8 @@ // --- Architecture Configuration -------------------------------------------- -// On the current version of Raspbian, real time thread scheduling seems to be -// broken in that higher priority threads do not always have priority over lower -// priority threads. It looks like the thread created last will always have the -// highest priority. +// On default Linux, you must be a superuser in order to set real time +// scheduling on threads. #define SB_HAS_THREAD_PRIORITY_SUPPORT 0 // --- Attribute Configuration -----------------------------------------------
diff --git a/src/starboard/creator/ci20/gyp_configuration.gypi b/src/starboard/creator/shared/gyp_configuration.gypi similarity index 86% rename from src/starboard/creator/ci20/gyp_configuration.gypi rename to src/starboard/creator/shared/gyp_configuration.gypi index 045e41c..c6cb2f2 100644 --- a/src/starboard/creator/ci20/gyp_configuration.gypi +++ b/src/starboard/creator/shared/gyp_configuration.gypi
@@ -19,7 +19,7 @@ 'enable_webdriver': 0, 'in_app_dial%': 0, - 'gl_type': 'system_gles2', + 'gl_type%': 'system_gles3', 'image_cache_size_in_bytes': 32 * 1024 * 1024, 'scratch_surface_cache_size_in_bytes' : 0, @@ -39,6 +39,16 @@ '-U__linux__', '--sysroot=<(sysroot)', '-EL', + + # Suppress some warnings that will be hard to fix. + '-Wno-unused-local-typedefs', + '-Wno-unused-result', + '-Wno-deprecated-declarations', + '-Wno-missing-field-initializers', + '-Wno-comment', + '-Wno-narrowing', + '-Wno-unknown-pragmas', + '-Wno-type-limits', # TODO: We should actually look into these. ], 'linker_flags': [ '--sysroot=<(sysroot)', @@ -87,16 +97,10 @@ '-lavformat', '-lavresample', '-lavutil', - '-lEGL', - '-lGLESv2', '-lm', '-lpthread', '-lpulse', '-lrt', - '-lX11', - '-lXcomposite', - '-lXext', - '-lXrender', ], 'conditions': [ ['cobalt_fastbuild==0', { @@ -129,21 +133,6 @@ '-std=gnu++11', '-Wno-literal-suffix', ], - 'default_configuration': 'creator-ci20_debug', - 'configurations': { - 'creator-ci20_debug': { - 'inherit_from': ['debug_base'], - }, - 'creator-ci20_devel': { - 'inherit_from': ['devel_base'], - }, - 'creator-ci20_qa': { - 'inherit_from': ['qa_base'], - }, - 'creator-ci20_gold': { - 'inherit_from': ['gold_base'], - }, - }, # end of configurations 'target_conditions': [ ['cobalt_code==1', { 'cflags': [
diff --git a/src/starboard/creator/ci20/gyp_configuration.py b/src/starboard/creator/shared/gyp_configuration.py similarity index 73% rename from src/starboard/creator/ci20/gyp_configuration.py rename to src/starboard/creator/shared/gyp_configuration.py index 10bb683..373a70e 100644 --- a/src/starboard/creator/ci20/gyp_configuration.py +++ b/src/starboard/creator/shared/gyp_configuration.py
@@ -11,7 +11,7 @@ # 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. -"""Starboard ci20 platform configuration for gyp_cobalt.""" +"""Starboard Creator Ci20 platform configuration for gyp_cobalt.""" import logging import os @@ -20,19 +20,11 @@ import config.starboard -def CreatePlatformConfig(): - try: - return _PlatformConfig('creator-ci20') - except RuntimeError as e: - logging.critical(e) - return None - - -class _PlatformConfig(config.starboard.PlatformConfigStarboard): +class PlatformConfig(config.starboard.PlatformConfigStarboard): """Starboard ci20 platform configuration.""" def __init__(self, platform): - super(_PlatformConfig, self).__init__(platform) + super(PlatformConfig, self).__init__(platform) def _GetCi20Home(self): try: @@ -46,16 +38,16 @@ def GetVariables(self, configuration): ci20_home = self._GetCi20Home() - sysroot = os.path.join(ci20_home, 'mips-mti-linux-gnu', '2016.05-03', - 'sysroot') + relative_sysroot = os.path.join('mips-mti-linux-gnu', '2016.05-03', + 'sysroot') + sysroot = os.path.join(ci20_home, relative_sysroot) if not os.path.isdir(sysroot): logging.critical( - 'ci20 builds require ' - '$CI20_HOME/mips-mti-linux-gnu/2016.05-03/sysroot to be a valid ' - 'directory.') + 'ci20 builds require $CI20_HOME/%s to be a valid directory.', + relative_sysroot) sys.exit(1) - variables = super(_PlatformConfig, self).GetVariables(configuration) + variables = super(PlatformConfig, self).GetVariables(configuration) variables.update({ 'clang': 0, 'sysroot': sysroot,
diff --git a/src/starboard/drm.h b/src/starboard/drm.h index 26d99a9..f7f4544 100644 --- a/src/starboard/drm.h +++ b/src/starboard/drm.h
@@ -12,8 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Definitions that allow for DRM support, common between Player and Decoder -// interfaces. +// Module Overview: Starboard DRM module +// +// Provides definitions that allow for DRM support, which are common +// between Player and Decoder interfaces. #ifndef STARBOARD_DRM_H_ #define STARBOARD_DRM_H_ @@ -104,26 +106,30 @@ // --- Functions ------------------------------------------------------------- -// Returns whether the |drm_system| is a valid SbDrmSystem. +// Indicates whether |drm_system| is a valid SbDrmSystem. static SB_C_FORCE_INLINE bool SbDrmSystemIsValid(SbDrmSystem drm) { return drm != kSbDrmSystemInvalid; } -// Creates a new |key_system| DRM system that can be used when constructing an -// SbPlayer or an SbDecoder. |key_system| should be in fhe form of -// "com.example.somesystem" as suggested by -// https://w3c.github.io/encrypted-media/#key-system. All letters in -// |key_system| should be in lower case and will be matched exactly with known -// DRM key systems of the platform. -// |context| will be passed when any callback parameters of this function are -// called. -// |update_request_callback| is a callback that will be called every time after -// SbDrmGenerateSessionUpdateRequest() is called. -// |session_updated_callback| is a callback that will be called every time -// after SbDrmUpdateSession() is called. -// Please refer to the document of SbDrmGenerateSessionUpdateRequest() and +// Creates a new DRM system that can be used when constructing an SbPlayer +// or an SbDecoder. +// +// This function returns kSbDrmSystemInvalid if |key_system| is unsupported. +// +// Also see the documentation of SbDrmGenerateSessionUpdateRequest() and // SbDrmUpdateSession() for more details. -// Returns kSbDrmSystemInvalid if the |key_system| is unsupported. +// +// |key_system|: The DRM key system to be created. The value should be in the +// form of "com.example.somesystem" as suggested by +// https://w3c.github.io/encrypted-media/#key-system. All letters in the value +// should be lowercase and will be matched exactly with known DRM key systems +// of the platform. +// |context|: A value passed when any of this function's callback parameters +// are called. +// |update_request_callback|: A function that is called every time after +// SbDrmGenerateSessionUpdateRequest() is called. +// |session_updated_callback|: A function that is called every time after +// SbDrmUpdateSession() is called. SB_EXPORT SbDrmSystem SbDrmCreateSystem(const char* key_system, void* context, @@ -132,15 +138,28 @@ // Asynchronously generates a session update request payload for // |initialization_data|, of |initialization_data_size|, in case sensitive -// |type|, extracted from the media stream, in |drm_system|'s key system. Calls -// |update_request_callback| with |context| and either a populated request, or -// NULL |session_id| if an error occured. |context| may be used to distinguish -// callbacks from multiple concurrent calls to -// SbDrmGenerateSessionUpdateRequest(), and/or to route callbacks back to an -// object instance. +// |type|, extracted from the media stream, in |drm_system|'s key system. // -// Callbacks may called from another thread or from the current thread before -// this function returns. +// This function calls |drm_system|'s |update_request_callback| function, +// which is defined when the DRM system is created by SbDrmCreateSystem. When +// calling that function, this function either sends |context| (also from +// |SbDrmCreateSystem|) and a populated request, or it sends NULL |session_id| +// if an error occurred. +// +// |drm_system|'s |context| may be used to distinguish callbacks from +// multiple concurrent calls to SbDrmGenerateSessionUpdateRequest(), and/or +// to route callbacks back to an object instance. +// +// Callbacks may be called either from the current thread before this function +// returns or from another thread. +// +// |drm_system|: The DRM system that defines the key system used for the +// session update request payload as well as the callback function that is +// called as a result of the function being called. +// |type|: The case-sensitive type of the session update request payload. +// |initialization_data|: The data for which the session update request payload +// is created. +// |initialization_data_size|: The size of the session update request payload. SB_EXPORT void SbDrmGenerateSessionUpdateRequest( SbDrmSystem drm_system, const char* type, @@ -155,26 +174,28 @@ // and/or to route callbacks back to an object instance. // // Once the session is successfully updated, an SbPlayer or SbDecoder associated -// with that system will be able to decrypt samples encrypted. +// with that DRM key system will be able to decrypt encrypted samples. // -// |session_updated_callback| may called from another thread or from the current -// thread before this function returns. +// |drm_system|'s |session_updated_callback| may called either from the +// current thread before this function returns or from another thread. SB_EXPORT void SbDrmUpdateSession(SbDrmSystem drm_system, const void* key, int key_size, const void* session_id, int session_id_size); -// Clear any internal states/resources related to the particular |session_id|. +// Clear any internal states/resources related to the specified |session_id|. SB_EXPORT void SbDrmCloseSession(SbDrmSystem drm_system, const void* session_id, int session_id_size); -// Gets the number of keys installed in the given |drm_system| system. +// Returns the number of keys installed in |drm_system|. +// +// |drm_system|: The system for which the number of installed keys is retrieved. SB_EXPORT int SbDrmGetKeyCount(SbDrmSystem drm_system); -// Gets the |out_key|, |out_key_size|, and |out_status| for key with |index| in -// the given |drm_system| system. Returns whether a key is installed at |index|. +// Gets |out_key|, |out_key_size|, and |out_status| for the key with |index| +// in |drm_system|. Returns whether a key is installed at |index|. // If not, the output parameters, which all must not be NULL, will not be // modified. SB_EXPORT bool SbDrmGetKeyStatus(SbDrmSystem drm_system, @@ -186,17 +207,21 @@ SbDrmKeyStatus* out_status); // Removes all installed keys for |drm_system|. Any outstanding session update -// requests will also be invalidated. +// requests are also invalidated. +// +// |drm_system|: The DRM system for which keys should be removed. SB_EXPORT void SbDrmRemoveAllKeys(SbDrmSystem drm_system); -// Destroys |drm_system|, which implicitly removes all keys installed in it, and +// Destroys |drm_system|, which implicitly removes all keys installed in it and // invalidates all outstanding session update requests. A DRM system cannot be // destroyed unless any associated SbPlayer or SbDecoder has first been // destroyed. // -// All callbacks are guaranteed to be finished when this function returns. So -// calling this function from a callback passed to SbDrmCreateSystem() will -// result in deadlock. +// All callbacks are guaranteed to be finished when this function returns. +// As a result, if this function is called from a callback that is passed +// to SbDrmCreateSystem(), a deadlock will occur. +// +// |drm_system|: The DRM system to be destroyed. SB_EXPORT void SbDrmDestroySystem(SbDrmSystem drm_system); #ifdef __cplusplus
diff --git a/src/starboard/linux/shared/configuration_public.h b/src/starboard/linux/shared/configuration_public.h index 20643e6..0e1efaa 100644 --- a/src/starboard/linux/shared/configuration_public.h +++ b/src/starboard/linux/shared/configuration_public.h
@@ -24,7 +24,7 @@ #define STARBOARD_LINUX_SHARED_CONFIGURATION_PUBLIC_H_ // The API version implemented by this platform. -#define SB_API_VERSION 1 +#define SB_API_VERSION 2 // --- System Header Configuration ------------------------------------------- @@ -55,6 +55,9 @@ // Whether the current platform provides the standard header float.h. #define SB_HAS_FLOAT_H 1 +// Whether the current platform has microphone supported. +#define SB_HAS_MICROPHONE 0 + // Type detection for wchar_t. #if defined(__WCHAR_MAX__) && \ (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
diff --git a/src/starboard/linux/x64directfb/starboard_platform.gyp b/src/starboard/linux/x64directfb/starboard_platform.gyp index f89ae85..2419586 100644 --- a/src/starboard/linux/x64directfb/starboard_platform.gyp +++ b/src/starboard/linux/x64directfb/starboard_platform.gyp
@@ -265,8 +265,8 @@ '<(DEPTH)/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc', '<(DEPTH)/starboard/shared/starboard/media/media_is_output_protected.cc', '<(DEPTH)/starboard/shared/starboard/media/media_set_output_protection.cc', - '<(DEPTH)/starboard/shared/starboard/media/mime_parser.cc', - '<(DEPTH)/starboard/shared/starboard/media/mime_parser.h', + '<(DEPTH)/starboard/shared/starboard/media/mime_type.cc', + '<(DEPTH)/starboard/shared/starboard/media/mime_type.h', '<(DEPTH)/starboard/shared/starboard/new.cc', '<(DEPTH)/starboard/shared/starboard/player/filter/audio_decoder_internal.h', '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.cc',
diff --git a/src/starboard/linux/x64directfb/system_get_property.cc b/src/starboard/linux/x64directfb/system_get_property.cc index b1529fe..1d20f7f 100644 --- a/src/starboard/linux/x64directfb/system_get_property.cc +++ b/src/starboard/linux/x64directfb/system_get_property.cc
@@ -47,6 +47,7 @@ case kSbSystemPropertyModelName: case kSbSystemPropertyModelYear: case kSbSystemPropertyNetworkOperatorName: + case kSbSystemPropertySpeechApiKey: return false; case kSbSystemPropertyFriendlyName:
diff --git a/src/starboard/linux/x64x11/starboard_platform.gyp b/src/starboard/linux/x64x11/starboard_platform.gyp index 6f9e3f8..a208bfc 100644 --- a/src/starboard/linux/x64x11/starboard_platform.gyp +++ b/src/starboard/linux/x64x11/starboard_platform.gyp
@@ -226,8 +226,8 @@ '<(DEPTH)/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc', '<(DEPTH)/starboard/shared/starboard/media/media_is_output_protected.cc', '<(DEPTH)/starboard/shared/starboard/media/media_set_output_protection.cc', - '<(DEPTH)/starboard/shared/starboard/media/mime_parser.cc', - '<(DEPTH)/starboard/shared/starboard/media/mime_parser.h', + '<(DEPTH)/starboard/shared/starboard/media/mime_type.cc', + '<(DEPTH)/starboard/shared/starboard/media/mime_type.h', '<(DEPTH)/starboard/shared/starboard/new.cc', '<(DEPTH)/starboard/shared/starboard/player/filter/audio_decoder_internal.h', '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.cc',
diff --git a/src/starboard/linux/x64x11/starboard_platform_tests.gyp b/src/starboard/linux/x64x11/starboard_platform_tests.gyp new file mode 100644 index 0000000..0250125 --- /dev/null +++ b/src/starboard/linux/x64x11/starboard_platform_tests.gyp
@@ -0,0 +1,41 @@ +# Copyright 2016 Google Inc. 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. +{ + 'targets': [ + { + 'target_name': 'starboard_platform_tests', + 'type': '<(gtest_target_type)', + 'sources': [ + '<(DEPTH)/starboard/common/test_main.cc', + '<(DEPTH)/starboard/shared/starboard/media/mime_type_test.cc', + ], + 'dependencies': [ + '<(DEPTH)/starboard/starboard.gyp:starboard', + '<(DEPTH)/testing/gmock.gyp:gmock', + '<(DEPTH)/testing/gtest.gyp:gtest', + ], + }, + { + 'target_name': 'starboard_platform_tests_deploy', + 'type': 'none', + 'dependencies': [ + '<(DEPTH)/<(starboard_path)/starboard_platform_tests.gyp:starboard_platform_tests', + ], + 'variables': { + 'executable_name': 'starboard_platform_tests', + }, + 'includes': [ '../../build/deploy.gypi' ], + }, + ], +}
diff --git a/src/starboard/linux/x64x11/system_get_property.cc b/src/starboard/linux/x64x11/system_get_property.cc index cffaa35..b72747d 100644 --- a/src/starboard/linux/x64x11/system_get_property.cc +++ b/src/starboard/linux/x64x11/system_get_property.cc
@@ -47,6 +47,7 @@ case kSbSystemPropertyModelName: case kSbSystemPropertyModelYear: case kSbSystemPropertyNetworkOperatorName: + case kSbSystemPropertySpeechApiKey: return false; case kSbSystemPropertyFriendlyName:
diff --git a/src/starboard/microphone.h b/src/starboard/microphone.h index 9ca8816..7e43451 100644 --- a/src/starboard/microphone.h +++ b/src/starboard/microphone.h
@@ -85,6 +85,9 @@ // Microphone max supported sampling rate. int max_sample_rate_hz; + + // The minimum read size required for each read from microphone. + int min_read_size; } SbMicrophoneInfo; // An opaque handle to an implementation-private structure representing a @@ -102,9 +105,11 @@ // Gets all currently-available microphone information and the results are // stored in |out_info_array|. |info_array_size| is the size of // |out_info_array|. -// Return value is the number of the available microphones. A negative return -// value indicates that either the |info_array_size| is too small or an internal -// error is occurred. +// Returns the number of the available microphones. A negative return +// value indicates that an internal error has occurred. If the number of +// available microphones is larger than |info_array_size|, |out_info_array| will +// be filled up with as many available microphones as possible and the actual +// number of available microphones will be returned. SB_EXPORT int SbMicrophoneGetAvailable(SbMicrophoneInfo* out_info_array, int info_array_size); @@ -153,7 +158,9 @@ // an error. This function should be called frequently, otherwise microphone // only buffers |buffer_size| bytes which is configured in |SbMicrophoneCreate| // and the new audio data will be thrown out. No audio data will be read from a -// stopped microphone. +// stopped microphone. If |audio_data_size| is smaller than |min_read_size| of +// |SbMicrophoneInfo|, the extra audio data which is already read from device +// will be discarded. SB_EXPORT int SbMicrophoneRead(SbMicrophone microphone, void* out_audio_data, int audio_data_size); @@ -163,12 +170,6 @@ // read will be thrown away. SB_EXPORT void SbMicrophoneDestroy(SbMicrophone microphone); -// Returns the Google Speech API key. The platform manufacturer is responsible -// for registering a Google Speech API key for their products. In the API -// Console (http://developers.google.com/console), you are able to enable the -// Speech APIs and generate a Speech API key. -SB_EXPORT const char* SbMicrophoneGetSpeechApiKey(); - #ifdef __cplusplus } // extern "C" #endif
diff --git a/src/starboard/nplb/microphone_get_available_test.cc b/src/starboard/nplb/microphone_get_available_test.cc index 14a7ed0..232995b 100644 --- a/src/starboard/nplb/microphone_get_available_test.cc +++ b/src/starboard/nplb/microphone_get_available_test.cc
@@ -32,14 +32,16 @@ SbMicrophoneInfo info_array[kMaxNumberOfMicrophone]; if (SbMicrophoneGetAvailable(info_array, kMaxNumberOfMicrophone) > 0) { int available_microphones = SbMicrophoneGetAvailable(info_array, 0); - EXPECT_LE(available_microphones, 0); + EXPECT_GT(available_microphones, 0); } } TEST(SbMicrophoneGetAvailableTest, RainyDayNegativeNumberOfMicrophone) { SbMicrophoneInfo info_array[kMaxNumberOfMicrophone]; - int available_microphones = SbMicrophoneGetAvailable(info_array, -10); - EXPECT_LT(available_microphones, 0); + if (SbMicrophoneGetAvailable(info_array, kMaxNumberOfMicrophone) > 0) { + int available_microphones = SbMicrophoneGetAvailable(info_array, -10); + EXPECT_GT(available_microphones, 0); + } } TEST(SbMicrophoneGetAvailableTest, RainyDayNULLInfoArray) { @@ -47,7 +49,7 @@ if (SbMicrophoneGetAvailable(info_array, kMaxNumberOfMicrophone) > 0) { int available_microphones = SbMicrophoneGetAvailable(NULL, kMaxNumberOfMicrophone); - EXPECT_LT(available_microphones, 0); + EXPECT_GT(available_microphones, 0); } }
diff --git a/src/starboard/nplb/microphone_get_speech_api_key_test.cc b/src/starboard/nplb/microphone_get_speech_api_key_test.cc deleted file mode 100644 index 67b5347..0000000 --- a/src/starboard/nplb/microphone_get_speech_api_key_test.cc +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2016 Google Inc. 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 "starboard/microphone.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace starboard { -namespace nplb { - -#if SB_HAS(MICROPHONE) && SB_VERSION(2) - -TEST(SbMicrophoneGetSpeechApiKeyTest, SunnyDay) { - const char* speech_api_key = SbMicrophoneGetSpeechApiKey(); - - ASSERT_NE(speech_api_key, static_cast<const char*>(NULL)); - EXPECT_NE(speech_api_key[0], '\0'); -} - -#endif // SB_HAS(MICROPHONE) && SB_VERSION(2) - -} // namespace nplb -} // namespace starboard
diff --git a/src/starboard/nplb/microphone_read_test.cc b/src/starboard/nplb/microphone_read_test.cc index 6f80656..7df0260 100644 --- a/src/starboard/nplb/microphone_read_test.cc +++ b/src/starboard/nplb/microphone_read_test.cc
@@ -35,16 +35,41 @@ info_array[0].id, info_array[0].max_sample_rate_hz, kBufferSize); ASSERT_TRUE(SbMicrophoneIsValid(microphone)); - bool success = SbMicrophoneOpen(microphone); - ASSERT_TRUE(success); + ASSERT_TRUE(SbMicrophoneOpen(microphone)); - void* audio_data[1024]; + int requested_bytes = info_array[0].min_read_size; + std::vector<uint8_t> audio_data(requested_bytes, 0); int read_bytes = - SbMicrophoneRead(microphone, audio_data, sizeof(audio_data)); + SbMicrophoneRead(microphone, &audio_data[0], audio_data.size()); EXPECT_GE(read_bytes, 0); - success = SbMicrophoneClose(microphone); - EXPECT_TRUE(success); + EXPECT_TRUE(SbMicrophoneClose(microphone)); + SbMicrophoneDestroy(microphone); + } +} + +TEST(SbMicrophoneReadTest, SunnyDayReadIsLargerThanMinReadSize) { + SbMicrophoneInfo info_array[kMaxNumberOfMicrophone]; + int available_microphones = + SbMicrophoneGetAvailable(info_array, kMaxNumberOfMicrophone); + EXPECT_GE(available_microphones, 0); + + if (available_microphones != 0) { + ASSERT_TRUE(SbMicrophoneIsSampleRateSupported( + info_array[0].id, info_array[0].max_sample_rate_hz)); + SbMicrophone microphone = SbMicrophoneCreate( + info_array[0].id, info_array[0].max_sample_rate_hz, kBufferSize); + ASSERT_TRUE(SbMicrophoneIsValid(microphone)); + + ASSERT_TRUE(SbMicrophoneOpen(microphone)); + + int requested_bytes = info_array[0].min_read_size; + std::vector<uint8_t> audio_data(requested_bytes * 2, 0); + int read_bytes = + SbMicrophoneRead(microphone, &audio_data[0], audio_data.size()); + EXPECT_GE(read_bytes, 0); + + EXPECT_TRUE(SbMicrophoneClose(microphone)); SbMicrophoneDestroy(microphone); } } @@ -62,22 +87,19 @@ info_array[0].id, info_array[0].max_sample_rate_hz, kBufferSize); ASSERT_TRUE(SbMicrophoneIsValid(microphone)); - bool success = SbMicrophoneOpen(microphone); - EXPECT_TRUE(success); + EXPECT_TRUE(SbMicrophoneOpen(microphone)); SbThreadSleep(50 * kSbTimeMillisecond); - success = SbMicrophoneClose(microphone); - EXPECT_TRUE(success); + EXPECT_TRUE(SbMicrophoneClose(microphone)); + EXPECT_TRUE(SbMicrophoneOpen(microphone)); - success = SbMicrophoneOpen(microphone); - EXPECT_TRUE(success); - - void* audio_data[16 * 1024]; + int requested_bytes = info_array[0].min_read_size; + std::vector<uint8_t> audio_data(requested_bytes, 0); int read_bytes = - SbMicrophoneRead(microphone, audio_data, sizeof(audio_data)); + SbMicrophoneRead(microphone, &audio_data[0], audio_data.size()); EXPECT_GE(read_bytes, 0); - EXPECT_LT(read_bytes, sizeof(audio_data)); + EXPECT_LT(read_bytes, audio_data.size()); SbMicrophoneDestroy(microphone); } @@ -96,14 +118,12 @@ info_array[0].id, info_array[0].max_sample_rate_hz, kBufferSize); ASSERT_TRUE(SbMicrophoneIsValid(microphone)); - bool success = SbMicrophoneOpen(microphone); - ASSERT_TRUE(success); + ASSERT_TRUE(SbMicrophoneOpen(microphone)); int read_bytes = SbMicrophoneRead(microphone, NULL, 0); EXPECT_EQ(read_bytes, 0); - success = SbMicrophoneClose(microphone); - EXPECT_TRUE(success); + EXPECT_TRUE(SbMicrophoneClose(microphone)); SbMicrophoneDestroy(microphone); } } @@ -121,14 +141,38 @@ info_array[0].id, info_array[0].max_sample_rate_hz, kBufferSize); ASSERT_TRUE(SbMicrophoneIsValid(microphone)); - bool success = SbMicrophoneOpen(microphone); - ASSERT_TRUE(success); + ASSERT_TRUE(SbMicrophoneOpen(microphone)); int read_bytes = SbMicrophoneRead(microphone, NULL, 1024); EXPECT_LE(read_bytes, 0); - success = SbMicrophoneClose(microphone); - EXPECT_TRUE(success); + EXPECT_TRUE(SbMicrophoneClose(microphone)); + SbMicrophoneDestroy(microphone); + } +} + +TEST(SbMicrophoneReadTest, RainyDayAudioBufferSizeIsSmallerThanMinReadSize) { + SbMicrophoneInfo info_array[kMaxNumberOfMicrophone]; + int available_microphones = + SbMicrophoneGetAvailable(info_array, kMaxNumberOfMicrophone); + EXPECT_GE(available_microphones, 0); + + if (available_microphones != 0) { + ASSERT_TRUE(SbMicrophoneIsSampleRateSupported( + info_array[0].id, info_array[0].max_sample_rate_hz)); + SbMicrophone microphone = SbMicrophoneCreate( + info_array[0].id, info_array[0].max_sample_rate_hz, kBufferSize); + ASSERT_TRUE(SbMicrophoneIsValid(microphone)); + + ASSERT_TRUE(SbMicrophoneOpen(microphone)); + + int requested_bytes = info_array[0].min_read_size; + std::vector<uint8_t> audio_data(requested_bytes / 2, 0); + int read_bytes = + SbMicrophoneRead(microphone, &audio_data[0], audio_data.size()); + EXPECT_GE(read_bytes, 0); + + EXPECT_TRUE(SbMicrophoneClose(microphone)); SbMicrophoneDestroy(microphone); } } @@ -146,10 +190,12 @@ info_array[0].id, info_array[0].max_sample_rate_hz, kBufferSize); ASSERT_TRUE(SbMicrophoneIsValid(microphone)); - void* audio_data[1024]; + int requested_bytes = info_array[0].min_read_size; + std::vector<uint8_t> audio_data(requested_bytes, 0); int read_bytes = - SbMicrophoneRead(microphone, audio_data, sizeof(audio_data)); - EXPECT_EQ(read_bytes, 0); + SbMicrophoneRead(microphone, &audio_data[0], audio_data.size()); + // An error should have occurred because open was not called. + EXPECT_LT(read_bytes, 0); SbMicrophoneDestroy(microphone); } @@ -168,26 +214,24 @@ info_array[0].id, info_array[0].max_sample_rate_hz, kBufferSize); ASSERT_TRUE(SbMicrophoneIsValid(microphone)); - bool success = SbMicrophoneOpen(microphone); - EXPECT_TRUE(success); + EXPECT_TRUE(SbMicrophoneOpen(microphone)); + EXPECT_TRUE(SbMicrophoneClose(microphone)); - success = SbMicrophoneClose(microphone); - EXPECT_TRUE(success); - - void* audio_data[1024]; + int requested_bytes = info_array[0].min_read_size; + std::vector<uint8_t> audio_data(requested_bytes, 0); int read_bytes = - SbMicrophoneRead(microphone, audio_data, sizeof(audio_data)); - // No data can be read. - EXPECT_EQ(read_bytes, 0); + SbMicrophoneRead(microphone, &audio_data[0], audio_data.size()); + // An error should have occurred because the microphone was closed. + EXPECT_LT(read_bytes, 0); SbMicrophoneDestroy(microphone); } } TEST(SbMicrophoneReadTest, RainyDayMicrophoneIsInvalid) { - void* audio_data[1024]; + std::vector<uint8_t> audio_data(1024, 0); int read_bytes = - SbMicrophoneRead(kSbMicrophoneInvalid, audio_data, sizeof(audio_data)); + SbMicrophoneRead(kSbMicrophoneInvalid, &audio_data[0], audio_data.size()); EXPECT_LT(read_bytes, 0); }
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp index 437cc92..43143c2 100644 --- a/src/starboard/nplb/nplb.gyp +++ b/src/starboard/nplb/nplb.gyp
@@ -21,6 +21,7 @@ 'target_name': 'nplb', 'type': '<(gtest_target_type)', 'sources': [ + '<(DEPTH)/starboard/common/test_main.cc', 'atomic_test.cc', 'audio_sink_create_test.cc', 'audio_sink_destroy_test.cc', @@ -107,7 +108,6 @@ 'log_raw_dump_stack_test.cc', 'log_raw_test.cc', 'log_test.cc', - 'main.cc', 'memory_align_to_page_size_test.cc', 'memory_allocate_aligned_test.cc', 'memory_allocate_test.cc', @@ -125,7 +125,6 @@ 'microphone_create_test.cc', 'microphone_destroy_test.cc', 'microphone_get_available_test.cc', - 'microphone_get_speech_api_key_test.cc', 'microphone_is_sample_rate_supported_test.cc', 'microphone_open_test.cc', 'microphone_read_test.cc',
diff --git a/src/starboard/nplb/system_get_property_test.cc b/src/starboard/nplb/system_get_property_test.cc index de94895..ef4078f 100644 --- a/src/starboard/nplb/system_get_property_test.cc +++ b/src/starboard/nplb/system_get_property_test.cc
@@ -70,6 +70,9 @@ BasicTest(kSbSystemPropertyChipsetModelNumber, false, true, __LINE__); BasicTest(kSbSystemPropertyFirmwareVersion, false, true, __LINE__); BasicTest(kSbSystemPropertyNetworkOperatorName, false, true, __LINE__); +#if SB_VERSION(2) + BasicTest(kSbSystemPropertySpeechApiKey, false, true, __LINE__); +#endif // SB_VERSION(2) if (IsCEDevice(SbSystemGetDeviceType())) { BasicTest(kSbSystemPropertyBrandName, true, true, __LINE__);
diff --git a/src/starboard/raspi/1/starboard_platform.gyp b/src/starboard/raspi/1/starboard_platform.gyp index b866ee7..7e51179 100644 --- a/src/starboard/raspi/1/starboard_platform.gyp +++ b/src/starboard/raspi/1/starboard_platform.gyp
@@ -233,8 +233,8 @@ '<(DEPTH)/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc', '<(DEPTH)/starboard/shared/starboard/media/media_is_output_protected.cc', '<(DEPTH)/starboard/shared/starboard/media/media_set_output_protection.cc', - '<(DEPTH)/starboard/shared/starboard/media/mime_parser.cc', - '<(DEPTH)/starboard/shared/starboard/media/mime_parser.h', + '<(DEPTH)/starboard/shared/starboard/media/mime_type.cc', + '<(DEPTH)/starboard/shared/starboard/media/mime_type.h', '<(DEPTH)/starboard/shared/starboard/new.cc', '<(DEPTH)/starboard/shared/starboard/player/filter/audio_decoder_internal.h', '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.cc',
diff --git a/src/starboard/raspi/1/system_get_property.cc b/src/starboard/raspi/1/system_get_property.cc index 6b5cee9..50f9d92 100644 --- a/src/starboard/raspi/1/system_get_property.cc +++ b/src/starboard/raspi/1/system_get_property.cc
@@ -47,6 +47,7 @@ case kSbSystemPropertyModelName: case kSbSystemPropertyModelYear: case kSbSystemPropertyNetworkOperatorName: + case kSbSystemPropertySpeechApiKey: return false; case kSbSystemPropertyFriendlyName:
diff --git a/src/starboard/raspi/directfb/README.md b/src/starboard/raspi/directfb/README.md index 4d9d9be..a4b4ec7 100644 --- a/src/starboard/raspi/directfb/README.md +++ b/src/starboard/raspi/directfb/README.md
@@ -31,7 +31,7 @@ ## Modifications to /etc/directfbrc -Open or create 'etc/directfbrc' (as root) and add the lines: +Open or create '/etc/directfbrc' (as root) and add the lines: graphics-vt hardware
diff --git a/src/starboard/raspi/shared/configuration_public.h b/src/starboard/raspi/shared/configuration_public.h index 15c18ca..0db1522 100644 --- a/src/starboard/raspi/shared/configuration_public.h +++ b/src/starboard/raspi/shared/configuration_public.h
@@ -18,7 +18,7 @@ #define STARBOARD_RASPI_SHARED_CONFIGURATION_PUBLIC_H_ // The API version implemented by this platform. -#define SB_API_VERSION 1 +#define SB_API_VERSION 2 // --- System Header Configuration ------------------------------------------- @@ -49,6 +49,9 @@ // Whether the current platform provides the standard header float.h. #define SB_HAS_FLOAT_H 1 +// Whether the current platform has microphone supported. +#define SB_HAS_MICROPHONE 0 + // Type detection for wchar_t. #if defined(__WCHAR_MAX__) && \ (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
diff --git a/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc b/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc index 9bfd9a7..0f417fd 100644 --- a/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc +++ b/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc
@@ -16,10 +16,10 @@ #include "starboard/character.h" #include "starboard/log.h" -#include "starboard/shared/starboard/media/mime_parser.h" +#include "starboard/shared/starboard/media/mime_type.h" #include "starboard/string.h" -using starboard::shared::starboard::media::MimeParser; +using starboard::shared::starboard::media::MimeType; SbMediaSupportType SbMediaCanPlayMimeAndKeySystem(const char* mime, const char* key_system) { @@ -37,27 +37,32 @@ return kSbMediaSupportTypeNotSupported; } } - MimeParser parser(mime); - if (!parser.is_valid()) { + MimeType mime_type(mime); + if (!mime_type.is_valid()) { SB_DLOG(WARNING) << mime << " is not a valid mime type"; return kSbMediaSupportTypeNotSupported; } - if (parser.mime() == "application/octet-stream") { + int codecs_index = mime_type.GetParamIndexByName("codecs"); + if (codecs_index != MimeType::kInvalidParamIndex && codecs_index != 0) { + SB_DLOG(WARNING) << mime << " is not a valid mime type"; + return kSbMediaSupportTypeNotSupported; + } + if (mime_type.type() == "application" && + mime_type.subtype() == "octet-stream") { return kSbMediaSupportTypeProbably; } - if (parser.mime() == "audio/mp4") { + if (mime_type.type() == "audio" && mime_type.subtype() == "mp4") { return kSbMediaSupportTypeProbably; } - if (parser.mime() == "video/mp4") { + if (mime_type.type() == "video" && mime_type.subtype() == "mp4") { return kSbMediaSupportTypeProbably; } #if SB_HAS(MEDIA_WEBM_VP9_SUPPORT) - if (parser.mime() == "video/webm") { - if (!parser.HasParam("codecs")) { + if (mime_type.type() == "video" && mime_type.subtype() == "webm") { + if (codecs_index == MimeType::kInvalidParamIndex) { return kSbMediaSupportTypeMaybe; } - std::string codecs = parser.GetParam("codecs"); - if (codecs == "vp9") { + if (mime_type.GetParamStringValue(0) == "vp9") { return kSbMediaSupportTypeProbably; } return kSbMediaSupportTypeNotSupported;
diff --git a/src/starboard/shared/starboard/media/mime_parser.cc b/src/starboard/shared/starboard/media/mime_parser.cc deleted file mode 100644 index 7db734a..0000000 --- a/src/starboard/shared/starboard/media/mime_parser.cc +++ /dev/null
@@ -1,141 +0,0 @@ -// Copyright 2016 Google Inc. 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 "starboard/shared/starboard/media/mime_parser.h" - -#include <vector> - -#include "starboard/character.h" -#include "starboard/log.h" -#include "starboard/string.h" - -namespace starboard { -namespace shared { -namespace starboard { -namespace media { - -namespace { - -void ToLower(std::string* string) { - SB_DCHECK(string); - for (size_t i = 0; i < string->size(); ++i) { - (*string)[i] = SbCharacterToLower((*string)[i]); - } -} - -void Trim(std::string* string) { - SB_DCHECK(string); - while (!string->empty() && SbCharacterIsSpace(*string->rbegin())) { - string->resize(string->size() - 1); - } - while (!string->empty() && SbCharacterIsSpace(*string->begin())) { - string->erase(string->begin()); - } -} - -bool IsSeparator(char ch, std::string separator) { - if (separator.empty()) { - return SbCharacterIsSpace(ch); - } - return separator.find(ch) != separator.npos; -} - -// For any given string, split it into substrings separated by any character in -// the |separator| string. If |separator| is empty string, treat any white -// space as separators. -std::vector<std::string> SplitString(std::string string, - std::string separator = "") { - std::vector<std::string> result; - while (!string.empty()) { - Trim(&string); - if (string.empty()) { - break; - } - bool added = false; - for (size_t i = 0; i < string.size(); ++i) { - if (IsSeparator(string[i], separator)) { - result.push_back(string.substr(0, i)); - Trim(&result.back()); - string = string.substr(i + 1); - added = true; - break; - } - } - if (!added) { - Trim(&string); - result.push_back(string); - break; - } - } - return result; -} - -} // namespace - -MimeParser::MimeParser(std::string mime_with_params) { - Trim(&mime_with_params); - ToLower(&mime_with_params); - - std::vector<std::string> splits = SplitString(mime_with_params, ";"); - if (splits.empty()) { - return; // It is invalid, leave |mime_| as empty. - } - mime_ = splits[0]; - // Mime is in the form of "video/mp4". - if (SplitString(mime_, "/").size() != 2) { - mime_.clear(); - return; - } - splits.erase(splits.begin()); - - while (!splits.empty()) { - std::string params = *splits.begin(); - splits.erase(splits.begin()); - - // Param is in the form of 'name=value' or 'name="value"'. - std::vector<std::string> name_and_value = SplitString(params, "="); - if (name_and_value.size() != 2) { - mime_.clear(); - return; - } - std::string name = name_and_value[0]; - std::string value = name_and_value[1]; - - if (value.size() >= 2 && value[0] == '\"' && - value[value.size() - 1] == '\"') { - value.erase(value.begin()); - value.resize(value.size() - 1); - Trim(&value); - } - - params_[name] = value; - } -} - -bool MimeParser::HasParam(const std::string& name) const { - return params_.find(name) != params_.end(); -} - -std::string MimeParser::GetParam(const std::string& name) const { - std::map<std::string, std::string>::const_iterator iter = params_.find(name); - if (iter == params_.end()) { - return ""; - } - return iter->second; -} - -} // namespace media -} // namespace starboard -} // namespace shared -} // namespace starboard
diff --git a/src/starboard/shared/starboard/media/mime_parser.h b/src/starboard/shared/starboard/media/mime_parser.h deleted file mode 100644 index b896b2d..0000000 --- a/src/starboard/shared/starboard/media/mime_parser.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2016 Google Inc. 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. - -#ifndef STARBOARD_SHARED_STARBOARD_MEDIA_MIME_PARSER_H_ -#define STARBOARD_SHARED_STARBOARD_MEDIA_MIME_PARSER_H_ - -#include <map> -#include <string> - -#include "starboard/shared/internal_only.h" - -namespace starboard { -namespace shared { -namespace starboard { -namespace media { - -// This class can be used to parse media mime types with params. For example, -// the following mime type 'video/mp4; codecs="avc1.4d401e"; width=640' will be -// parsed into: -// mime => video/mp4 -// param: codecs => avc1.4d401e -// param: width => 640 -class MimeParser { - public: - explicit MimeParser(std::string mime_with_params); - - bool is_valid() const { return !mime_.empty(); } - const std::string& mime() const { return mime_; } - - bool HasParam(const std::string& name) const; - std::string GetParam(const std::string& name) const; - - private: - std::string mime_; - std::map<std::string, std::string> params_; -}; - -} // namespace media -} // namespace starboard -} // namespace shared -} // namespace starboard - -#endif // STARBOARD_SHARED_STARBOARD_MEDIA_MIME_PARSER_H_
diff --git a/src/starboard/shared/starboard/media/mime_type.cc b/src/starboard/shared/starboard/media/mime_type.cc new file mode 100644 index 0000000..d77b2d5 --- /dev/null +++ b/src/starboard/shared/starboard/media/mime_type.cc
@@ -0,0 +1,217 @@ +// Copyright 2016 Google Inc. 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 "starboard/shared/starboard/media/mime_type.h" + +#include "starboard/character.h" +#include "starboard/log.h" +#include "starboard/string.h" + +namespace starboard { +namespace shared { +namespace starboard { +namespace media { + +namespace { + +typedef std::vector<std::string> Strings; + +MimeType::ParamType GetParamTypeByValue(const std::string& value) { + int count; + int i; + if (SbStringScanF(value.c_str(), "%d%n", &i, &count) == 1 && + count == value.size()) { + return MimeType::kParamTypeInteger; + } + float f; + if (SbStringScanF(value.c_str(), "%g%n", &f, &count) == 1 && + count == value.size()) { + return MimeType::kParamTypeFloat; + } + return MimeType::kParamTypeString; +} + +bool ContainsSpace(const std::string& str) { + for (size_t i = 0; i < str.size(); ++i) { + if (SbCharacterIsSpace(str[i])) { + return true; + } + } + + return false; +} + +void Trim(std::string* str) { + while (!str->empty() && SbCharacterIsSpace(*str->begin())) { + str->erase(str->begin()); + } + while (!str->empty() && SbCharacterIsSpace(*str->rbegin())) { + str->resize(str->size() - 1); + } +} + +Strings SplitAndTrim(const std::string& str, char ch) { + Strings result; + size_t pos = 0; + + for (;;) { + size_t next = str.find(ch, pos); + result.push_back(str.substr(pos, next - pos)); + Trim(&result.back()); + if (next == str.npos) { + break; + } + pos = next + 1; + } + + return result; +} + +} // namespace + +const int MimeType::kInvalidParamIndex = -1; + +MimeType::MimeType(const std::string& content_type) : is_valid_(false) { + Strings components = SplitAndTrim(content_type, ';'); + + SB_DCHECK(!components.empty()); + + // 1. Verify if there is a valid type/subtype in the very beginning. + if (ContainsSpace(components.front())) { + return; + } + + std::vector<std::string> type_and_container = + SplitAndTrim(components.front(), '/'); + if (type_and_container.size() != 2 || type_and_container[0].empty() || + type_and_container[1].empty()) { + return; + } + type_ = type_and_container[0]; + subtype_ = type_and_container[1]; + components.erase(components.begin()); + + // 2. Verify the parameters have valid formats, we want to be strict here. + for (Strings::iterator iter = components.begin(); iter != components.end(); + ++iter) { + std::vector<std::string> name_and_value = SplitAndTrim(*iter, '='); + if (name_and_value.size() != 2 || name_and_value[0].empty() || + name_and_value[1].empty()) { + return; + } + Param param; + if (name_and_value[1].size() > 2 && name_and_value[1][0] == '\"' && + *name_and_value[1].rbegin() == '\"') { + param.type = kParamTypeString; + param.value = name_and_value[1].substr(1, name_and_value[1].size() - 2); + } else { + param.type = GetParamTypeByValue(name_and_value[1]); + param.value = name_and_value[1]; + } + param.name = name_and_value[0]; + params_.push_back(param); + } + + is_valid_ = true; +} + +int MimeType::GetParamCount() const { + SB_DCHECK(is_valid()); + + return static_cast<int>(params_.size()); +} + +MimeType::ParamType MimeType::GetParamType(int index) const { + SB_DCHECK(is_valid()); + SB_DCHECK(index < GetParamCount()); + + return params_[index].type; +} + +const std::string& MimeType::GetParamName(int index) const { + SB_DCHECK(is_valid()); + SB_DCHECK(index < GetParamCount()); + + return params_[index].name; +} + +int MimeType::GetParamIntValue(int index) const { + SB_DCHECK(is_valid()); + SB_DCHECK(index < GetParamCount()); + SB_DCHECK(GetParamType(index) == kParamTypeInteger); + + int i; + SbStringScanF(params_[index].value.c_str(), "%d", &i); + return i; +} + +float MimeType::GetParamFloatValue(int index) const { + SB_DCHECK(is_valid()); + SB_DCHECK(index < GetParamCount()); + SB_DCHECK(GetParamType(index) == kParamTypeInteger || + GetParamType(index) == kParamTypeFloat); + + float f; + SbStringScanF(params_[index].value.c_str(), "%g", &f); + + return f; +} + +const std::string& MimeType::GetParamStringValue(int index) const { + SB_DCHECK(is_valid()); + SB_DCHECK(index < GetParamCount()); + + return params_[index].value; +} + +int MimeType::GetParamIntValue(const char* name, int default_value) const { + int index = GetParamIndexByName(name); + if (index != kInvalidParamIndex) { + return GetParamIntValue(index); + } + return default_value; +} + +float MimeType::GetParamFloatValue(const char* name, + float default_value) const { + int index = GetParamIndexByName(name); + if (index != kInvalidParamIndex) { + return GetParamFloatValue(index); + } + return default_value; +} + +const std::string& MimeType::GetParamStringValue( + const char* name, + const std::string& default_value) const { + int index = GetParamIndexByName(name); + if (index != kInvalidParamIndex) { + return GetParamStringValue(index); + } + return default_value; +} + +int MimeType::GetParamIndexByName(const char* name) const { + for (size_t i = 0; i < params_.size(); ++i) { + if (SbStringCompareNoCase(params_[i].name.c_str(), name) == 0) { + return static_cast<int>(i); + } + } + return kInvalidParamIndex; +} + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard
diff --git a/src/starboard/shared/starboard/media/mime_type.h b/src/starboard/shared/starboard/media/mime_type.h new file mode 100644 index 0000000..eb5b2f2 --- /dev/null +++ b/src/starboard/shared/starboard/media/mime_type.h
@@ -0,0 +1,95 @@ +// Copyright 2016 Google Inc. 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. + +#ifndef STARBOARD_SHARED_STARBOARD_MEDIA_MIME_TYPE_H_ +#define STARBOARD_SHARED_STARBOARD_MEDIA_MIME_TYPE_H_ + +#include <string> +#include <vector> + +namespace starboard { +namespace shared { +namespace starboard { +namespace media { + +// This class can be used to parse a content type for media in the form of +// "type/subtype; param1=value1; param2="value2". For example, the content type +// "video/webm; codecs="vp9"; width=1920; height=1080; framerate=59.96" will be +// parsed into: +// type: video +// subtype: webm +// codecs: vp9 +// width: 1920 +// height: 1080 +// framerate: 59.96 +// +// The following are the restrictions on the components: +// 1. Type/subtype has to be in the very beginning. +// 2. String values may be double quoted. +// 3. Numeric values cannot be double quoted. +class MimeType { + public: + enum ParamType { + kParamTypeInteger, + kParamTypeFloat, + kParamTypeString, + }; + + static const int kInvalidParamIndex; + + explicit MimeType(const std::string& content_type); + + bool is_valid() const { return is_valid_; } + + const std::string& type() const { return type_; } + const std::string& subtype() const { return subtype_; } + + int GetParamIndexByName(const char* name) const; + int GetParamCount() const; + ParamType GetParamType(int index) const; + const std::string& GetParamName(int index) const; + + int GetParamIntValue(int index) const; + float GetParamFloatValue(int index) const; + const std::string& GetParamStringValue(int index) const; + + int GetParamIntValue(const char* name, int default_value) const; + float GetParamFloatValue(const char* name, float default_value) const; + const std::string& GetParamStringValue( + const char* name, + const std::string& default_value) const; + + private: + struct Param { + ParamType type; + std::string name; + std::string value; + }; + + // Use std::vector as the number of components are usually small and we'd like + // to keep the order of components. + typedef std::vector<Param> Params; + + bool is_valid_; + std::string type_; + std::string subtype_; + Params params_; +}; + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard + +#endif // STARBOARD_SHARED_STARBOARD_MEDIA_MIME_TYPE_H_
diff --git a/src/starboard/shared/starboard/media/mime_type_test.cc b/src/starboard/shared/starboard/media/mime_type_test.cc new file mode 100644 index 0000000..44d0371 --- /dev/null +++ b/src/starboard/shared/starboard/media/mime_type_test.cc
@@ -0,0 +1,269 @@ +// Copyright 2016 Google Inc. 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 "starboard/shared/starboard/media/mime_type.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace starboard { +namespace shared { +namespace starboard { +namespace media { +namespace { + +TEST(MimeTypeTest, EmptyString) { + MimeType mime_type(""); + EXPECT_FALSE(mime_type.is_valid()); +} + +// Valid mime type must have a type/subtype without space in between. +TEST(MimeTypeTest, InvalidType) { + { + MimeType mime_type("video"); + EXPECT_FALSE(mime_type.is_valid()); + } + + { + MimeType mime_type("video/"); + EXPECT_FALSE(mime_type.is_valid()); + } + + { + MimeType mime_type("/mp4"); + EXPECT_FALSE(mime_type.is_valid()); + } + + { + MimeType mime_type("video /mp4"); + EXPECT_FALSE(mime_type.is_valid()); + } + + { + MimeType mime_type("video/ mp4"); + EXPECT_FALSE(mime_type.is_valid()); + } + + { + MimeType mime_type("video / mp4"); + EXPECT_FALSE(mime_type.is_valid()); + } +} + +TEST(MimeTypeTest, ValidContentTypeWithTypeAndSubtypeOnly) { + { + MimeType mime_type("video/mp4"); + EXPECT_TRUE(mime_type.is_valid()); + EXPECT_EQ("video", mime_type.type()); + EXPECT_EQ("mp4", mime_type.subtype()); + } + + { + MimeType mime_type("audio/mp4"); + EXPECT_TRUE(mime_type.is_valid()); + } + + { + MimeType mime_type("abc/xyz"); + EXPECT_TRUE(mime_type.is_valid()); + } +} + +TEST(MimeTypeTest, TypeNotAtBeginning) { + { + MimeType mime_type(";video/mp4"); + EXPECT_FALSE(mime_type.is_valid()); + } + + { + MimeType mime_type("codecs=\"abc\"; audio/mp4"); + EXPECT_FALSE(mime_type.is_valid()); + } +} + +TEST(MimeTypeTest, EmptyComponent) { + { + MimeType mime_type("video/mp4;"); + EXPECT_FALSE(mime_type.is_valid()); + } + + { + MimeType mime_type("video/mp4;;"); + EXPECT_FALSE(mime_type.is_valid()); + } + + { + MimeType mime_type("audio/mp4; codecs=\"abc\";"); + EXPECT_FALSE(mime_type.is_valid()); + } +} + +TEST(MimeTypeTest, ValidContentTypeWithParams) { + { + MimeType mime_type("video/mp4; name=123"); + EXPECT_TRUE(mime_type.is_valid()); + } + + { + MimeType mime_type("audio/mp4;codecs=\"abc\""); + EXPECT_TRUE(mime_type.is_valid()); + } + + { + MimeType mime_type(" audio/mp4 ; codecs = \"abc\" "); + EXPECT_TRUE(mime_type.is_valid()); + } +} + +TEST(MimeTypeTest, GetParamIndexByName) { + MimeType mime_type("video/mp4; name=123"); + EXPECT_EQ(MimeType::kInvalidParamIndex, + mime_type.GetParamIndexByName("video")); + EXPECT_EQ(MimeType::kInvalidParamIndex, mime_type.GetParamIndexByName("mp4")); + EXPECT_EQ(0, mime_type.GetParamIndexByName("name")); +} + +TEST(MimeTypeTest, ParamCount) { + { + MimeType mime_type("video/mp4"); + EXPECT_EQ(0, mime_type.GetParamCount()); + } + + { + MimeType mime_type("video/mp4; width=1920"); + EXPECT_EQ(1, mime_type.GetParamCount()); + } + + { + MimeType mime_type("video/mp4; width=1920; height=1080"); + EXPECT_EQ(2, mime_type.GetParamCount()); + } +} + +TEST(MimeTypeTest, GetParamType) { + { + MimeType mime_type("video/mp4; name0=123; name1=1.2; name2=xyz"); + EXPECT_EQ(MimeType::kParamTypeInteger, mime_type.GetParamType(0)); + EXPECT_EQ(MimeType::kParamTypeFloat, mime_type.GetParamType(1)); + EXPECT_EQ(MimeType::kParamTypeString, mime_type.GetParamType(2)); + } + + { + MimeType mime_type("video/mp4; name0=\"123\"; name1=\"abc\""); + EXPECT_EQ(MimeType::kParamTypeString, mime_type.GetParamType(0)); + EXPECT_EQ(MimeType::kParamTypeString, mime_type.GetParamType(1)); + } + + { + MimeType mime_type("video/mp4; name1=\" abc \""); + EXPECT_EQ(MimeType::kParamTypeString, mime_type.GetParamType(0)); + } +} + +TEST(MimeTypeTest, GetParamName) { + { + MimeType mime_type("video/mp4; name0=123; name1=1.2; name2=xyz"); + EXPECT_EQ("name0", mime_type.GetParamName(0)); + EXPECT_EQ("name1", mime_type.GetParamName(1)); + EXPECT_EQ("name2", mime_type.GetParamName(2)); + } +} + +TEST(MimeTypeTest, GetParamIntValueWithIndex) { + { + MimeType mime_type("video/mp4; name=123"); + EXPECT_EQ(123, mime_type.GetParamIntValue(0)); + } + + { + MimeType mime_type("video/mp4; width=1920; height=1080"); + EXPECT_EQ(1920, mime_type.GetParamIntValue(0)); + EXPECT_EQ(1080, mime_type.GetParamIntValue(1)); + } + + { + MimeType mime_type("audio/mp4; channels=6"); + EXPECT_EQ(6, mime_type.GetParamIntValue(0)); + } +} + +TEST(MimeTypeTest, GetParamFloatValueWithIndex) { + { + MimeType mime_type("video/mp4; name0=123; name1=123.4"); + EXPECT_FLOAT_EQ(123., mime_type.GetParamFloatValue(0)); + EXPECT_FLOAT_EQ(123.4, mime_type.GetParamFloatValue(1)); + } +} + +TEST(MimeTypeTest, GetParamStringValueWithIndex) { + { + MimeType mime_type("video/mp4; name0=123; name1=abc; name2=\"xyz\""); + EXPECT_EQ("123", mime_type.GetParamStringValue(0)); + EXPECT_EQ("abc", mime_type.GetParamStringValue(1)); + EXPECT_EQ("xyz", mime_type.GetParamStringValue(2)); + } + + { + MimeType mime_type("video/mp4; name=\" xyz \""); + EXPECT_EQ(" xyz ", mime_type.GetParamStringValue(0)); + } +} + +TEST(MimeTypeTest, GetParamIntValueWithName) { + { + MimeType mime_type("video/mp4; name=123"); + EXPECT_EQ(123, mime_type.GetParamIntValue("name", 0)); + EXPECT_EQ(6, mime_type.GetParamIntValue("channels", 6)); + } + + { + MimeType mime_type("video/mp4; width=1920; height=1080"); + EXPECT_EQ(1920, mime_type.GetParamIntValue("width", 0)); + EXPECT_EQ(1080, mime_type.GetParamIntValue("height", 0)); + } + + { + MimeType mime_type("audio/mp4; channels=6"); + EXPECT_EQ(6, mime_type.GetParamIntValue("channels", 0)); + } +} + +TEST(MimeTypeTest, GetParamFloatValueWithName) { + { + MimeType mime_type("video/mp4; name0=123; name1=123.4"); + EXPECT_FLOAT_EQ(123.f, mime_type.GetParamFloatValue("name0", 0.f)); + EXPECT_FLOAT_EQ(123.4f, mime_type.GetParamFloatValue("name1", 0.f)); + EXPECT_FLOAT_EQ(59.96f, mime_type.GetParamFloatValue("framerate", 59.96f)); + } +} + +TEST(MimeTypeTest, GetParamStringValueWithName) { + { + MimeType mime_type("video/mp4; name0=123; name1=abc; name2=\"xyz\""); + EXPECT_EQ("123", mime_type.GetParamStringValue("name0", "")); + EXPECT_EQ("abc", mime_type.GetParamStringValue("name1", "")); + EXPECT_EQ("xyz", mime_type.GetParamStringValue("name2", "")); + EXPECT_EQ("h263", mime_type.GetParamStringValue("codecs", "h263")); + } + + { + MimeType mime_type("video/mp4; name=\" xyz \""); + EXPECT_EQ(" xyz ", mime_type.GetParamStringValue("name", "")); + } +} + +} // namespace +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard
diff --git a/src/starboard/starboard.gyp b/src/starboard/starboard.gyp index 5677568..b89ff1a 100644 --- a/src/starboard/starboard.gyp +++ b/src/starboard/starboard.gyp
@@ -60,26 +60,13 @@ 'window.h', ], 'dependencies': [ + '<(DEPTH)/<(starboard_path)/starboard_platform.gyp:starboard_platform', 'common/common.gyp:common', ], + 'export_dependent_settings': [ + '<(DEPTH)/<(starboard_path)/starboard_platform.gyp:starboard_platform', + ], 'conditions': [ - ['starboard_path == ""', { - # TODO: Make starboard_path required. This legacy condition is only - # here to support semi-starboard platforms while they still exist. - 'dependencies': [ - '<(DEPTH)/starboard/<(target_arch)/starboard_platform.gyp:starboard_platform', - ], - 'export_dependent_settings': [ - '<(DEPTH)/starboard/<(target_arch)/starboard_platform.gyp:starboard_platform', - ], - }, { - 'dependencies': [ - '<(DEPTH)/<(starboard_path)/starboard_platform.gyp:starboard_platform', - ], - 'export_dependent_settings': [ - '<(DEPTH)/<(starboard_path)/starboard_platform.gyp:starboard_platform', - ], - }], ['final_executable_type=="shared_library"', { 'all_dependent_settings': { 'target_conditions': [
diff --git a/src/starboard/starboard_all.gyp b/src/starboard/starboard_all.gyp index b97230b..1eb3b02 100644 --- a/src/starboard/starboard_all.gyp +++ b/src/starboard/starboard_all.gyp
@@ -16,6 +16,9 @@ # Starboard project. { + 'variables': { + 'has_platform_tests%' : '<!(python -c "import os.path; print os.path.isfile(\'<(starboard_path)/starboard_platform_tests.gyp\') & 1 | 0")', + }, 'targets': [ { # Note that this target must be in a separate GYP file from starboard.gyp, @@ -31,6 +34,13 @@ '<(DEPTH)/starboard/nplb/nplb.gyp:*', '<(DEPTH)/starboard/starboard.gyp:*', ], + 'conditions': [ + ['has_platform_tests==1', { + 'dependencies': [ + '<(DEPTH)/<(starboard_path)/starboard_platform_tests.gyp:starboard_platform_tests', + ], + }], + ], }, ], }
diff --git a/src/starboard/stub/starboard_platform.gyp b/src/starboard/stub/starboard_platform.gyp index bfacb36..63ca705 100644 --- a/src/starboard/stub/starboard_platform.gyp +++ b/src/starboard/stub/starboard_platform.gyp
@@ -102,7 +102,6 @@ '<(DEPTH)/starboard/shared/stub/microphone_create.cc', '<(DEPTH)/starboard/shared/stub/microphone_destroy.cc', '<(DEPTH)/starboard/shared/stub/microphone_get_available.cc', - '<(DEPTH)/starboard/shared/stub/microphone_get_speech_api_key.cc', '<(DEPTH)/starboard/shared/stub/microphone_is_sample_rate_supported.cc', '<(DEPTH)/starboard/shared/stub/microphone_open.cc', '<(DEPTH)/starboard/shared/stub/microphone_read.cc',
diff --git a/src/starboard/system.h b/src/starboard/system.h index c52a4e1..667cd1a 100644 --- a/src/starboard/system.h +++ b/src/starboard/system.h
@@ -94,6 +94,14 @@ // A universally-unique ID for the current user. kSbSystemPropertyPlatformUuid, + +#if SB_VERSION(2) + // The Google Speech API key. The platform manufacturer is responsible + // for registering a Google Speech API key for their products. In the API + // Console (http://developers.google.com/console), you are able to enable the + // Speech APIs and generate a Speech API key. + kSbSystemPropertySpeechApiKey, +#endif // SB_VERSION(2) } SbSystemPropertyId; // Enumeration of device types.
diff --git a/src/starboard/time_zone.h b/src/starboard/time_zone.h index ce67d09..25ac711 100644 --- a/src/starboard/time_zone.h +++ b/src/starboard/time_zone.h
@@ -12,7 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Access to the system time zone information. +// Module Overview: Starboard Time Zone module +// +// Provides access to the system time zone information. #ifndef STARBOARD_TIME_ZONE_H_ #define STARBOARD_TIME_ZONE_H_ @@ -24,7 +26,7 @@ extern "C" { #endif -// The number of minutes west of the Greenwich Prime Meridian, NOT including any +// The number of minutes west of the Greenwich Prime Meridian, NOT including // Daylight Savings Time adjustments. // // For example: PST/PDT is 480 minutes (28800 seconds, 8 hours). @@ -34,7 +36,7 @@ SB_EXPORT SbTimeZone SbTimeZoneGetCurrent(); // Gets the three-letter code of the current timezone in standard time, -// regardless of current DST status. (e.g. "PST") +// regardless of current Daylight Savings Time status. (e.g. "PST") SB_EXPORT const char* SbTimeZoneGetName(); // Gets the three-letter code of the current timezone in Daylight Savings Time,
diff --git a/src/third_party/libjpeg/jmemnobs.c b/src/third_party/libjpeg/jmemnobs.c index a360de8..935ef6e 100644 --- a/src/third_party/libjpeg/jmemnobs.c +++ b/src/third_party/libjpeg/jmemnobs.c
@@ -23,7 +23,7 @@ #if defined(NEED_STARBOARD_MEMORY) #include "starboard/memory.h" #define malloc SbMemoryAllocate -#define free SbMemoryFree +#define free SbMemoryDeallocate #elif !defined(HAVE_STDLIB_H) /* <stdlib.h> should declare malloc(),free() */ extern void * malloc JPP((size_t size)); extern void free JPP((void *ptr));
diff --git a/src/third_party/libpng/pngmem.c b/src/third_party/libpng/pngmem.c index d19179d..1b4b88f 100644 --- a/src/third_party/libpng/pngmem.c +++ b/src/third_party/libpng/pngmem.c
@@ -24,7 +24,7 @@ #if defined(STARBOARD) # include "starboard/memory.h" # define malloc SbMemoryAllocate -# define free SbMemoryFree +# define free SbMemoryDeallocate #endif #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
diff --git a/src/third_party/openssl/openssl/crypto/LPdir_starboard.c b/src/third_party/openssl/openssl/crypto/LPdir_starboard.c index f663a95..5daa624 100644 --- a/src/third_party/openssl/openssl/crypto/LPdir_starboard.c +++ b/src/third_party/openssl/openssl/crypto/LPdir_starboard.c
@@ -52,7 +52,7 @@ (*ctx)->dir = SbDirectoryOpen(directory, NULL); if (!SbDirectoryIsValid((*ctx)->dir)) { - SbMemoryFree(*ctx); + SbMemoryDeallocate(*ctx); *ctx = NULL; return NULL; } @@ -70,7 +70,7 @@ { if (ctx != NULL && *ctx != NULL) { bool result = SbDirectoryClose((*ctx)->dir); - SbMemoryFree(*ctx); + SbMemoryDeallocate(*ctx); return (result ? 1 : 0); } return 0;
diff --git a/src/third_party/sqlite/amalgamation/sqlite3.c b/src/third_party/sqlite/amalgamation/sqlite3.c index 25aa93a..5a56cc5 100644 --- a/src/third_party/sqlite/amalgamation/sqlite3.c +++ b/src/third_party/sqlite/amalgamation/sqlite3.c
@@ -14473,7 +14473,7 @@ #if defined(STARBOARD) #include "starboard/memory.h" #define malloc SbMemoryAllocate -#define free SbMemoryFree +#define free SbMemoryDeallocate #define realloc SbMemoryReallocate #endif
diff --git a/src/third_party/zlib/zutil.c b/src/third_party/zlib/zutil.c index bf2e3cc..fd3a67b 100644 --- a/src/third_party/zlib/zutil.c +++ b/src/third_party/zlib/zutil.c
@@ -301,7 +301,7 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { SB_UNREFERENCED_PARAMETER(opaque); - SbMemoryFree(ptr); + SbMemoryDeallocate(ptr); } #endif /* STARBOARD */