Import Cobalt 6.16000
diff --git a/src/starboard/build/convert_i18n_data.py b/src/starboard/build/convert_i18n_data.py index a34916a..0f56a59 100644 --- a/src/starboard/build/convert_i18n_data.py +++ b/src/starboard/build/convert_i18n_data.py
@@ -51,7 +51,7 @@ messages = root[0] # Write each message to the output file on its own line. - with open(output_filename, 'w') as output_file: + with open(output_filename, 'wb') as output_file: for msg in messages: # Use ; as the separator. Which means it better not be in the name. assert not (';' in msg.attrib['name'])
diff --git a/src/starboard/client_porting/poem/getenv_stub_poem.h b/src/starboard/client_porting/poem/getenv_stub_poem.h new file mode 100644 index 0000000..8e4ab81 --- /dev/null +++ b/src/starboard/client_porting/poem/getenv_stub_poem.h
@@ -0,0 +1,28 @@ +// 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. + +// A poem (POsix EMulation) stub implementation for getenv. + +#ifndef STARBOARD_CLIENT_PORTING_POEM_GETENV_STUB_POEM_H_ +#define STARBOARD_CLIENT_PORTING_POEM_GETENV_STUB_POEM_H_ + +#include <stdlib.h> + +#include "starboard/configuration.h" + +static SB_C_INLINE const char* getenv(const char* unused) { + return NULL; +} + +#endif // STARBOARD_CLIENT_PORTING_POEM_GETENV_STUB_POEM_H_
diff --git a/src/starboard/client_porting/poem/inet_poem.h b/src/starboard/client_porting/poem/inet_poem.h new file mode 100644 index 0000000..55cf47a --- /dev/null +++ b/src/starboard/client_porting/poem/inet_poem.h
@@ -0,0 +1,27 @@ +// 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. + +// A poem (POsix EMulation) for functions usually declared in <arpa/inet.h> + +#ifndef STARBOARD_CLIENT_PORTING_POEM_INET_POEM_H_ +#define STARBOARD_CLIENT_PORTING_POEM_INET_POEM_H_ + +#include "starboard/byte_swap.h" + +#define htonl(x) SB_HOST_TO_NET_U32(x) +#define htons(x) SB_HOST_TO_NET_U16(x) +#define ntohl(x) SB_NET_TO_HOST_U32(x) +#define ntohs(x) SB_NET_TO_HOST_U16(x) + +#endif // STARBOARD_CLIENT_PORTING_POEM_INET_POEM_H_
diff --git a/src/starboard/client_porting/poem/poem.gyp b/src/starboard/client_porting/poem/poem.gyp index def3f4e..947cc36 100644 --- a/src/starboard/client_porting/poem/poem.gyp +++ b/src/starboard/client_porting/poem/poem.gyp
@@ -19,10 +19,13 @@ 'type': 'static_library', 'sources': [ 'eztime_poem.h', + 'getenv_stub_poem.h', + 'inet_poem.h', 'stdio_poem.h', 'stdlib_poem.h', 'string_poem.h', 'strings_poem.h', + 'strnlen_poem.h', 'wchar_poem.h', ], 'dependencies': [ @@ -44,5 +47,16 @@ '<(DEPTH)/starboard/starboard.gyp:starboard', ], }, + { + 'target_name': 'poem_unittests_deploy', + 'type': 'none', + 'dependencies': [ + 'poem_unittests', + ], + 'variables': { + 'executable_name': 'poem_unittests', + }, + 'includes': [ '../../build/deploy.gypi' ], + }, ], }
diff --git a/src/starboard/client_porting/poem/string_poem_test.cc b/src/starboard/client_porting/poem/string_poem_test.cc index 2243b48..1a3e899 100644 --- a/src/starboard/client_porting/poem/string_poem_test.cc +++ b/src/starboard/client_porting/poem/string_poem_test.cc
@@ -17,6 +17,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "starboard/client_porting/poem/string_poem.h" +#include "starboard/client_porting/poem/strnlen_poem.h" namespace starboard { namespace nplb { @@ -76,6 +77,20 @@ EXPECT_STREQ(a, "Wu"); } +TEST(StringPoemTest, PoemStringGetLengthFixed) { + char a[] = "abcdef"; + char b[] = "abc\0def"; + + EXPECT_EQ(strnlen(a, 0), 0); + EXPECT_EQ(strnlen(a, 3), 3); + EXPECT_EQ(strnlen(a, sizeof(a)), 6); + EXPECT_EQ(strnlen(a, 256), 6); + EXPECT_EQ(strnlen(b, 2), 2); + EXPECT_EQ(strnlen(b, 3), 3); + EXPECT_EQ(strnlen(b, sizeof(b)), 3); + EXPECT_EQ(strnlen(b, 256), 3); +} + } // namespace } // namespace nplb } // namespace starboard
diff --git a/src/starboard/client_porting/poem/strnlen_poem.h b/src/starboard/client_porting/poem/strnlen_poem.h new file mode 100644 index 0000000..fb2d674 --- /dev/null +++ b/src/starboard/client_porting/poem/strnlen_poem.h
@@ -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. + +// A poem (POsix EMulation) implementation for strnlen. Usually declared in +// <string.h>, but may be missing on some platforms (e.g. PS3). + +#ifndef STARBOARD_CLIENT_PORTING_POEM_STRNLEN_POEM_H_ +#define STARBOARD_CLIENT_PORTING_POEM_STRNLEN_POEM_H_ + +#include "starboard/configuration.h" + +static SB_C_INLINE size_t StringGetLengthFixed(const char* s, size_t maxlen) { + size_t i = 0; + while (i < maxlen && s[i]) { + ++i; + } + return i; +} + +#define strnlen(s, maxlen) StringGetLengthFixed(s, maxlen) + +#endif // STARBOARD_CLIENT_PORTING_POEM_STRNLEN_POEM_H_
diff --git a/src/starboard/client_porting/pr_starboard/pr_starboard.cc b/src/starboard/client_porting/pr_starboard/pr_starboard.cc new file mode 100644 index 0000000..732ea14 --- /dev/null +++ b/src/starboard/client_porting/pr_starboard/pr_starboard.cc
@@ -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. + +#include "starboard/client_porting/pr_starboard/pr_starboard.h" + +#include "starboard/condition_variable.h" +#include "starboard/log.h" +#include "starboard/memory.h" +#include "starboard/mutex.h" +#include "starboard/once.h" +#include "starboard/queue.h" +#include "starboard/thread.h" +#include "starboard/time.h" +#include "starboard/types.h" + +namespace { + +typedef starboard::Queue<bool> SetupSignalQueue; + +// Utility function to convert a PRInterval to signed 64 bit integer +// microseconds. +int64_t PR_IntervalToMicrosecondsInt64(PRIntervalTime ticks) { + uint32_t microseconds_as_uint32 = PR_IntervalToMicroseconds(ticks); + int64_t microseconds_as_int64 = static_cast<int64_t>(microseconds_as_uint32); + return microseconds_as_int64; +} + +// Struct to bundle up arguments to be passed into SbThreadCreate. +struct ThreadEntryPointWrapperContext { + ThreadEntryPointWrapperContext(void* pr_context, + PRThread* pr_thread, + PRThreadEntryPoint pr_entry_point, + SetupSignalQueue* setup_signal_queue) + : pr_context(pr_context), + pr_thread(pr_thread), + pr_entry_point(pr_entry_point), + setup_signal_queue(setup_signal_queue) {} + void* pr_context; + PRThread* pr_thread; + PRThreadEntryPoint pr_entry_point; + SetupSignalQueue* setup_signal_queue; +}; + +// The thread local key that corresponds to where local PRThread* data is held. +SbThreadLocalKey g_pr_thread_local_key = kSbThreadLocalKeyInvalid; +// The SbOnceControlStructure to to ensure that the local key is only created +// once. +SbOnceControl g_pr_thread_key_once_control = SB_ONCE_INITIALIZER; + +void PrThreadDtor(void* value) { + PRThread* pr_thread = reinterpret_cast<PRThread*>(value); + delete pr_thread; +} + +void InitPrThreadKey() { + g_pr_thread_local_key = SbThreadCreateLocalKey(PrThreadDtor); +} + +SbThreadLocalKey GetPrThreadKey() { + SB_CHECK(SbOnce(&g_pr_thread_key_once_control, InitPrThreadKey)); + return g_pr_thread_local_key; +} + +void* ThreadEntryPointWrapper(void* context_as_void_pointer) { + ThreadEntryPointWrapperContext* context = + reinterpret_cast<ThreadEntryPointWrapperContext*>( + context_as_void_pointer); + void* pr_context = context->pr_context; + PRThreadEntryPoint pr_entry_point = context->pr_entry_point; + PRThread* pr_thread = context->pr_thread; + SetupSignalQueue* setup_signal_queue = context->setup_signal_queue; + + delete context; + + pr_thread->sb_thread = SbThreadGetCurrent(); + SbThreadLocalKey key = GetPrThreadKey(); + SB_CHECK(SbThreadIsValidLocalKey(key)); + SbThreadSetLocalValue(key, pr_thread); + + setup_signal_queue->Put(true); + pr_entry_point(pr_context); + + return NULL; +} + +} // namespace + +PRLock* PR_NewLock() { + PRLock* lock = new PRLock(); + if (!SbMutexCreate(lock)) { + delete lock; + return NULL; + } + return lock; +} + +void PR_DestroyLock(PRLock* lock) { + SB_DCHECK(lock); + SbMutexDestroy(lock); + delete lock; +} + +PRCondVar* PR_NewCondVar(PRLock* lock) { + SB_DCHECK(lock); + PRCondVar* cvar = new PRCondVar(); + if (!SbConditionVariableCreate(&cvar->sb_condition_variable, lock)) { + delete cvar; + return NULL; + } + cvar->lock = lock; + return cvar; +} + +void PR_DestroyCondVar(PRCondVar* cvar) { + SbConditionVariableDestroy(&cvar->sb_condition_variable); + delete cvar; +} + +PRStatus PR_WaitCondVar(PRCondVar* cvar, PRIntervalTime timeout) { + SbConditionVariableResult result; + if (timeout == PR_INTERVAL_NO_WAIT) { + result = SbConditionVariableWaitTimed(&cvar->sb_condition_variable, + cvar->lock, 0); + } else if (timeout == PR_INTERVAL_NO_TIMEOUT) { + result = SbConditionVariableWait(&cvar->sb_condition_variable, cvar->lock); + } else { + int64_t microseconds = PR_IntervalToMicrosecondsInt64(timeout); + result = SbConditionVariableWaitTimed(&cvar->sb_condition_variable, + cvar->lock, microseconds); + } + return pr_starboard::ToPRStatus(result != kSbConditionVariableFailed); +} + +PRThread* PR_GetCurrentThread() { + SbThreadLocalKey key = GetPrThreadKey(); + SB_CHECK(SbThreadIsValidLocalKey(key)); + + PRThread* value = static_cast<PRThread*>(SbThreadGetLocalValue(key)); + // We could potentially be a thread that was not created through + // PR_CreateThread. In this case, we must allocate a PRThread and do the + // setup that would normally have been done in PR_CreateThread. + if (!value) { + PRThread* pr_thread = new PRThread(SbThreadGetCurrent()); + SbThreadSetLocalValue(key, pr_thread); + value = pr_thread; + } + + return value; +} + +uint32_t PR_snprintf(char* out, uint32_t outlen, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + uint32_t ret = PR_vsnprintf(out, outlen, fmt, args); + va_end(args); + return ret; +} + +PRThread* PR_CreateThread(PRThreadType type, + PRThreadEntryPoint start, + void* arg, + PRThreadPriority priority, + PRThreadScope scope, + PRThreadState state, + PRUint32 stackSize) { + int64_t sb_stack_size = static_cast<int64_t>(stackSize); + + SbThreadPriority sb_priority; + switch (priority) { + case PR_PRIORITY_LOW: + sb_priority = kSbThreadPriorityLow; + break; + case PR_PRIORITY_NORMAL: + sb_priority = kSbThreadPriorityNormal; + break; + case PR_PRIORITY_HIGH: + sb_priority = kSbThreadPriorityHigh; + break; + case PR_PRIORITY_LAST: + sb_priority = kSbThreadPriorityHighest; + break; + default: + sb_priority = kSbThreadNoPriority; + } + + SbThreadAffinity sb_affinity = kSbThreadNoAffinity; + + SB_DCHECK(state == PR_JOINABLE_THREAD || state == PR_UNJOINABLE_THREAD); + bool sb_joinable = (state == PR_JOINABLE_THREAD); + + // This heap allocated PRThread object will have a pointer to it stored in + // the newly created child thread's thread local storage. Once the newly + // created child thread finishes, it will be freed in the destructor + // associated with it through thread local storage. + PRThread* pr_thread = new PRThread(kSbThreadInvalid); + + // Utility queue for the ThreadEntryWrapper to signal us once it's done + // running its initial setup and we can safely exit. + SetupSignalQueue setup_signal_queue; + + // This heap allocated context object is freed after + // ThreadEntryPointWrapper's initial setup is complete, right before the + // nspr level entry point is run. + ThreadEntryPointWrapperContext* context = new ThreadEntryPointWrapperContext( + arg, pr_thread, start, &setup_signal_queue); + + // Note that pr_thread->sb_thread will be set to the correct value in the + // setup section of ThreadEntryPointWrapper. It is done there rather than + // here to account for the unlikely but possible case in which we enter the + // newly created child thread, and then the child thread passes references + // to itself off into its potential children or co-threads that interact + // with it before we can copy what SbThreadCreate returns into + // pr_thread->sb_thread from this current thread. + SbThreadCreate(sb_stack_size, sb_priority, sb_affinity, sb_joinable, NULL, + ThreadEntryPointWrapper, context); + + // Now we must wait for the setup section of ThreadEntryPointWrapper to run + // and initialize pr_thread (both the struct itself and the corresponding + // new thread's private data) before we can safely return. We expect to + // receive true rather than false by convention. + bool setup_signal = setup_signal_queue.Get(); + SB_DCHECK(setup_signal); + + return pr_thread; +} + +PRStatus PR_CallOnceWithArg(PRCallOnceType* once, + PRCallOnceWithArgFN func, + void* arg) { + SB_NOTREACHED() << "Not implemented"; + return PR_FAILURE; +} + +PRStatus PR_NewThreadPrivateIndex(PRTLSIndex* newIndex, + PRThreadPrivateDTOR destructor) { + SbThreadLocalKey key = SbThreadCreateLocalKey(destructor); + if (!SbThreadIsValidLocalKey(key)) { + return pr_starboard::ToPRStatus(false); + } + *newIndex = key; + return pr_starboard::ToPRStatus(true); +} + +PRIntervalTime PR_MillisecondsToInterval(PRUint32 milli) { + PRUint64 tock = static_cast<PRUint64>(milli); + PRUint64 msecPerSec = static_cast<PRInt64>(PR_MSEC_PER_SEC); + PRUint64 rounding = static_cast<PRInt64>(PR_MSEC_PER_SEC >> 1); + PRUint64 tps = static_cast<PRInt64>(PR_TicksPerSecond()); + + tock *= tps; + tock += rounding; + tock /= msecPerSec; + + PRUint64 ticks = static_cast<PRUint64>(tock); + return ticks; +} + +PRUint32 PR_IntervalToMicroseconds(PRIntervalTime ticks) { + PRUint64 tock = static_cast<PRInt64>(ticks); + PRUint64 usecPerSec = static_cast<PRInt64>(PR_USEC_PER_SEC); + PRUint64 tps = static_cast<PRInt64>(PR_TicksPerSecond()); + PRUint64 rounding = static_cast<PRUint64>(tps) >> 1; + + tock *= usecPerSec; + tock += rounding; + tock /= tps; + + PRUint32 micro = static_cast<PRUint32>(tock); + return micro; +}
diff --git a/src/starboard/client_porting/pr_starboard/pr_starboard.gyp b/src/starboard/client_porting/pr_starboard/pr_starboard.gyp new file mode 100644 index 0000000..0874b65 --- /dev/null +++ b/src/starboard/client_porting/pr_starboard/pr_starboard.gyp
@@ -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. + +{ + 'targets': [ + { + 'target_name': 'pr_starboard', + 'type': 'static_library', + 'sources': [ + 'pr_starboard.cc', + 'pr_starboard.h', + ], + 'dependencies': [ + '<(DEPTH)/starboard/starboard.gyp:starboard', + ], + }, + ], +}
diff --git a/src/starboard/client_porting/pr_starboard/pr_starboard.h b/src/starboard/client_porting/pr_starboard/pr_starboard.h new file mode 100644 index 0000000..63e5c4d --- /dev/null +++ b/src/starboard/client_porting/pr_starboard/pr_starboard.h
@@ -0,0 +1,189 @@ +// 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. + +// This header defines the interface for a starboard based implementation of +// the subset of nspr that SpiderMonkey depends on. It directly matches the +// NSPR API, with the exception that accessing thread local data should use +// PRTLSIndex, rather than PRUintn. + +#ifndef STARBOARD_CLIENT_PORTING_PR_STARBOARD_PR_STARBOARD_H_ +#define STARBOARD_CLIENT_PORTING_PR_STARBOARD_PR_STARBOARD_H_ + +#include "starboard/condition_variable.h" +#include "starboard/log.h" +#include "starboard/memory.h" +#include "starboard/mutex.h" +#include "starboard/string.h" +#include "starboard/thread.h" +#include "starboard/types.h" + +#define PR_CALLBACK + +#define PR_MSEC_PER_SEC 1000L +#define PR_USEC_PER_SEC 1000000L +#define PR_NSEC_PER_SEC 1000000000L +#define PR_USEC_PER_MSEC 1000L +#define PR_NSEC_PER_MSEC 1000000L + +typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus; + +namespace pr_starboard { + +// Utility function to map true to PR_SUCCESS and false to PR_FAILURE. +static inline PRStatus ToPRStatus(bool result) { + return result ? PR_SUCCESS : PR_FAILURE; +} + +} // namespace pr_starboard + +typedef enum PRThreadPriority { + PR_PRIORITY_FIRST = 0, + PR_PRIORITY_LOW = 0, + PR_PRIORITY_NORMAL = 1, + PR_PRIORITY_HIGH = 2, + PR_PRIORITY_URGENT = 3, + PR_PRIORITY_LAST = 3 +} PRThreadPriority; + +typedef enum PRThreadScope { + PR_LOCAL_THREAD, + PR_GLOBAL_THREAD, + PR_GLOBAL_BOUND_THREAD +} PRThreadScope; + +typedef enum PRThreadState { + PR_JOINABLE_THREAD, + PR_UNJOINABLE_THREAD +} PRThreadState; + +typedef enum PRThreadType { PR_USER_THREAD, PR_SYSTEM_THREAD } PRThreadType; + +typedef SbThreadLocalKey PRTLSIndex; +typedef uint32_t PRIntervalTime; + +typedef int32_t PRInt32; +typedef uint32_t PRUint32; + +typedef int64_t PRInt64; +typedef uint64_t PRUint64; + +typedef void(PR_CALLBACK* PRThreadPrivateDTOR)(void* priv); + +struct PRThread { + explicit PRThread(SbThread sb_thread) : sb_thread(sb_thread) {} + SbThread sb_thread; +}; + +typedef SbMutex PRLock; + +#define PR_INTERVAL_NO_WAIT 0UL +#define PR_INTERVAL_NO_TIMEOUT 0xffffffffUL + +struct PRCondVar { + SbConditionVariable sb_condition_variable; + SbMutex* lock; +}; + +PRLock* PR_NewLock(); + +static inline void PR_Lock(PRLock* lock) { + SbMutexAcquire(lock); +} + +static inline void PR_Unlock(PRLock* lock) { + SbMutexRelease(lock); +} + +void PR_DestroyLock(PRLock* lock); + +PRCondVar* PR_NewCondVar(PRLock* lock); + +void PR_DestroyCondVar(PRCondVar* cvar); + +PRStatus PR_WaitCondVar(PRCondVar* cvar, PRIntervalTime timeout); + +static inline PRStatus PR_NotifyCondVar(PRCondVar* cvar) { + return pr_starboard::ToPRStatus( + SbConditionVariableSignal(&cvar->sb_condition_variable)); +} + +static inline PRStatus PR_NotifyAllCondVar(PRCondVar* cvar) { + return pr_starboard::ToPRStatus( + SbConditionVariableBroadcast(&cvar->sb_condition_variable)); +} + +typedef void (*PRThreadEntryPoint)(void*); + +PRThread* PR_CreateThread(PRThreadType type, + PRThreadEntryPoint start, + void* arg, + PRThreadPriority priority, + PRThreadScope scope, + PRThreadState state, + PRUint32 stackSize); + +static inline PRStatus PR_JoinThread(PRThread* pr_thread) { + SB_DCHECK(pr_thread); + SB_DCHECK(SbThreadIsValid(pr_thread->sb_thread)); + return pr_starboard::ToPRStatus(SbThreadJoin(pr_thread->sb_thread, NULL)); +} + +PRThread* PR_GetCurrentThread(); + +void PR_DetachThread(); + +PRStatus PR_NewThreadPrivateIndex(PRTLSIndex* newIndex, + PRThreadPrivateDTOR destructor); + +static inline PRStatus PR_SetThreadPrivate(PRTLSIndex index, void* priv) { + return pr_starboard::ToPRStatus(SbThreadSetLocalValue(index, priv)); +} + +static inline void* PR_GetThreadPrivate(PRTLSIndex index) { + return SbThreadGetLocalValue(index); +} + +static inline void PR_SetCurrentThreadName(const char* name) { + SbThreadSetName(name); +} + +static inline PRUint32 PR_vsnprintf(char* out, + PRUint32 outlen, + const char* fmt, + va_list ap) { + return static_cast<PRUint32>(SbStringFormat(out, outlen, fmt, ap)); +} + +PRUint32 PR_snprintf(char* out, PRUint32 outlen, const char* fmt, ...); + +PRIntervalTime PR_MillisecondsToInterval(PRUint32 milli); + +static inline PRIntervalTime PR_MicrosecondsToInterval(PRUint32 micro) { + return (micro + 999) / 1000; +} + +PRUint32 PR_IntervalToMicroseconds(PRIntervalTime ticks); + +struct PRCallOnceType {}; +typedef PRStatus(PR_CALLBACK* PRCallOnceWithArgFN)(void* arg); + +PRStatus PR_CallOnceWithArg(PRCallOnceType* once, + PRCallOnceWithArgFN func, + void* arg); + +static inline PRUint32 PR_TicksPerSecond() { + return 1000; +} + +#endif // STARBOARD_CLIENT_PORTING_PR_STARBOARD_PR_STARBOARD_H_
diff --git a/src/starboard/client_porting/wrap_main/wrap_main.h b/src/starboard/client_porting/wrap_main/wrap_main.h index e4879d3..4734772 100644 --- a/src/starboard/client_porting/wrap_main/wrap_main.h +++ b/src/starboard/client_porting/wrap_main/wrap_main.h
@@ -50,6 +50,11 @@ } // namespace client_porting } // namespace starboard +#if defined(_WIN32) +// Today there is no Starboard win32. Make sure those who create it know +// the _CrtSet* functions below should be moved to starboard win32 main. +#error For starboard win32, please move _CrtSet* to main +#endif #define STARBOARD_WRAP_SIMPLE_MAIN(main_function) \ void SbEventHandle(const SbEvent* event) { \ ::starboard::client_porting::wrap_main::SimpleEventHandler< \ @@ -57,10 +62,26 @@ } #else +#if defined(_WIN32) +#include <windows.h> + +// TODO this case should be removed when win32 is starboardized +#define STARBOARD_WRAP_SIMPLE_MAIN(main_function) \ + int main(int argc, char** argv) { \ + if (!IsDebuggerPresent()) { \ + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); \ + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); \ + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); \ + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); \ + } \ + return main_function(argc, argv); \ + } +#else // defined(_WIN32) #define STARBOARD_WRAP_SIMPLE_MAIN(main_function) \ int main(int argc, char** argv) { \ return main_function(argc, argv); \ } +#endif #endif // STARBOARD #endif // STARBOARD_CLIENT_PORTING_WRAP_MAIN_WRAP_MAIN_H_
diff --git a/src/starboard/condition_variable.h b/src/starboard/condition_variable.h index 673b7d9..4c519ba 100644 --- a/src/starboard/condition_variable.h +++ b/src/starboard/condition_variable.h
@@ -56,10 +56,6 @@ // placing the newly created condition variable in |out_condition|. // // The return value indicates whether the condition variable could be created. -// -// TODO: It looks like WTF does not have the mutex available when creating -// the condition variable, and pthreads doesn't appear to require the mutex on -// condvar creation, so we should just remove the parameter. SB_EXPORT bool SbConditionVariableCreate(SbConditionVariable* out_condition, SbMutex* opt_mutex);
diff --git a/src/starboard/examples/window/main.cc b/src/starboard/examples/window/main.cc index 381d428..bb5bc83 100644 --- a/src/starboard/examples/window/main.cc +++ b/src/starboard/examples/window/main.cc
@@ -35,7 +35,7 @@ << ", window=" << data->window << ", device_type=" << data->device_type << ", device_id=" << data->device_id - << ", key=" << data->key + << ", key=0x" << std::hex << data->key << ", character=" << data->character << ", modifiers=0x" << std::hex << data->key_modifiers << ", location=" << std::dec << data->key_location;
diff --git a/src/starboard/linux/x64directfb/sanitizer_options.cc b/src/starboard/linux/x64directfb/sanitizer_options.cc new file mode 100644 index 0000000..e85d451 --- /dev/null +++ b/src/starboard/linux/x64directfb/sanitizer_options.cc
@@ -0,0 +1,42 @@ +// 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. + +// Removes gallium leak warnings from x11 GL code, but defines it as a weak +// symbol, so other code can override it if they want to. + +#if defined(ADDRESS_SANITIZER) + +// Functions returning default options are declared weak in the tools' runtime +// libraries. To make the linker pick the strong replacements for those +// functions from this module, we explicitly force its inclusion by passing +// -Wl,-u_sanitizer_options_link_helper +extern "C" void _sanitizer_options_link_helper() { } + +#define SANITIZER_HOOK_ATTRIBUTE \ + extern "C" \ + __attribute__((no_sanitize_address)) \ + __attribute__((no_sanitize_memory)) \ + __attribute__((no_sanitize_thread)) \ + __attribute__((visibility("default"))) \ + __attribute__((weak)) \ + __attribute__((used)) + +// Newline separated list of issues to suppress, see +// http://clang.llvm.org/docs/AddressSanitizer.html#issue-suppression +// http://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_suppressions.cc +SANITIZER_HOOK_ATTRIBUTE const char* __lsan_default_suppressions() { + return "leak:*eglibc-2.19*\n"; +} + +#endif // defined(ADDRESS_SANITIZER)
diff --git a/src/starboard/linux/x64directfb/starboard_platform.gypi b/src/starboard/linux/x64directfb/starboard_platform.gypi index f5d40ad..d38e23c 100644 --- a/src/starboard/linux/x64directfb/starboard_platform.gypi +++ b/src/starboard/linux/x64directfb/starboard_platform.gypi
@@ -17,6 +17,7 @@ 'variables': { 'starboard_platform_sources': [ '<(DEPTH)/starboard/linux/x64directfb/main.cc', + '<(DEPTH)/starboard/linux/x64directfb/sanitizer_options.cc', '<(DEPTH)/starboard/linux/x64directfb/system_get_property.cc', '<(DEPTH)/starboard/shared/directfb/application_directfb.cc', '<(DEPTH)/starboard/shared/directfb/blitter_blit_rect_to_rect.cc',
diff --git a/src/starboard/nplb/decode_target_create_test.cc b/src/starboard/nplb/decode_target_create_test.cc index e8f3ea4..287dc21 100644 --- a/src/starboard/nplb/decode_target_create_test.cc +++ b/src/starboard/nplb/decode_target_create_test.cc
@@ -44,7 +44,6 @@ SbDecodeTarget target = SbDecodeTargetCreate(kSbDecodeTargetFormat1PlaneRGBA, &surface); - EXPECT_TRUE(SbDecodeTargetIsValid(target)); if (SbDecodeTargetIsValid(target)) { SbBlitterSurface plane = SbDecodeTargetGetPlane(target, kSbDecodeTargetPlaneRGBA);
diff --git a/src/starboard/nplb/storage_helpers.h b/src/starboard/nplb/storage_helpers.h index 56b4fc2..efc422e 100644 --- a/src/starboard/nplb/storage_helpers.h +++ b/src/starboard/nplb/storage_helpers.h
@@ -27,12 +27,12 @@ const int64_t kStorageSize2 = kStorageSize * 2 + kStorageOffset; // Deletes the storage for the current user. -SB_C_INLINE void ClearStorageRecord() { +static SB_C_INLINE void ClearStorageRecord() { SbStorageDeleteRecord(SbUserGetCurrent()); } // Opens the storage record for the current user, validating that it is valid. -SB_C_INLINE SbStorageRecord OpenStorageRecord() { +static SB_C_INLINE SbStorageRecord OpenStorageRecord() { SbStorageRecord record = SbStorageOpenRecord(SbUserGetCurrent()); EXPECT_TRUE(SbStorageIsValidRecord(record)); return record; @@ -40,7 +40,8 @@ // Writes a standard pattern of |size| bytes into the given open storage // |record|. -SB_C_INLINE void WriteStorageRecord(SbStorageRecord record, int64_t size) { +static SB_C_INLINE void WriteStorageRecord(SbStorageRecord record, + int64_t size) { char* data = new char[size]; for (int64_t i = 0; i < size; ++i) { data[i] = static_cast<char>(i + 2 % 0xFF); @@ -52,7 +53,8 @@ // Ensures that the storage record for the current user is initialized with the // standard pattern for exactly |length| bytes. -SB_C_INLINE void InitializeStorageRecord(int64_t length) { + +static SB_C_INLINE void InitializeStorageRecord(int64_t length) { ClearStorageRecord(); SbStorageRecord record = OpenStorageRecord(); WriteStorageRecord(record, length); @@ -62,7 +64,7 @@ // Checks a buffer of |total| size for the expected pattern (written in // WriteStorageRecord) to start at |offset| and continue for |length|, and the // rest of the buffer, before and after, should be set to 0. -SB_C_INLINE void CheckStorageBuffer(char* data, +static SB_C_INLINE void CheckStorageBuffer(char* data, int64_t offset, int64_t length, int64_t total) { @@ -83,7 +85,7 @@ // |offset| and reporting the buffer size as |length|, checks that the number of // read bytes is |expected_length| and then checks the buffer for the expected // pattern written in WriteStorageRecord over the expected range of the buffer. -SB_C_INLINE void ReadAndCheckStorage(SbStorageRecord record, +static SB_C_INLINE void ReadAndCheckStorage(SbStorageRecord record, int64_t offset, int64_t expected_length, int64_t length,
diff --git a/src/starboard/player.h b/src/starboard/player.h index 6fbc381..cbd1ff3 100644 --- a/src/starboard/player.h +++ b/src/starboard/player.h
@@ -173,7 +173,7 @@ #define kSbPlayerInvalid ((SbPlayer)NULL) // Returns whether the given player handle is valid. -SB_C_INLINE bool SbPlayerIsValid(SbPlayer player) { +static SB_C_INLINE bool SbPlayerIsValid(SbPlayer player) { return player != kSbPlayerInvalid; }
diff --git a/src/starboard/raspi/1/gyp_configuration.gypi b/src/starboard/raspi/1/gyp_configuration.gypi index fbccc08..040ca1e 100644 --- a/src/starboard/raspi/1/gyp_configuration.gypi +++ b/src/starboard/raspi/1/gyp_configuration.gypi
@@ -32,7 +32,8 @@ # This should have a default value in cobalt/base.gypi. See the comment # there for acceptable values for this variable. 'javascript_engine': 'mozjs', - 'cobalt_enable_jit': 1, + 'cobalt_enable_jit': 0, + 'cobalt_minimum_frame_time_in_milliseconds': '33', # RasPi 1 is ARMv6 'arm_version': 6,
diff --git a/src/starboard/raspi/1/starboard_platform.gyp b/src/starboard/raspi/1/starboard_platform.gyp index fb203a6..c39d4e3 100644 --- a/src/starboard/raspi/1/starboard_platform.gyp +++ b/src/starboard/raspi/1/starboard_platform.gyp
@@ -39,6 +39,8 @@ '<(DEPTH)/starboard/raspi/shared/main.cc', '<(DEPTH)/starboard/raspi/shared/open_max/open_max_component.cc', '<(DEPTH)/starboard/raspi/shared/open_max/open_max_component.h', + '<(DEPTH)/starboard/raspi/shared/open_max/open_max_video_decode_component.cc', + '<(DEPTH)/starboard/raspi/shared/open_max/open_max_video_decode_component.h', '<(DEPTH)/starboard/raspi/shared/open_max/video_decoder.cc', '<(DEPTH)/starboard/raspi/shared/open_max/video_decoder.h', '<(DEPTH)/starboard/raspi/shared/thread_create_priority.cc',
diff --git a/src/starboard/raspi/shared/application_dispmanx.cc b/src/starboard/raspi/shared/application_dispmanx.cc index fcaf43f..4f9dddf 100644 --- a/src/starboard/raspi/shared/application_dispmanx.cc +++ b/src/starboard/raspi/shared/application_dispmanx.cc
@@ -51,9 +51,7 @@ window_ = new SbWindowPrivate(*display_, options); input_ = DevInput::Create(window_); - // Create the dispmanx element to display video frames. - int result = 0; - uint32_t vc_image_ptr; + video_renderer_.reset(new DispmanxVideoRenderer(*display_, kVideoLayer)); return window_; } @@ -86,14 +84,11 @@ } void ApplicationDispmanx::AcceptFrame(SbPlayer player, - const VideoFrame& frame, + const scoped_refptr<VideoFrame>& frame, int x, int y, int width, int height) { - if (!video_renderer_) { - video_renderer_.reset(new DispmanxVideoRenderer(*display_, kVideoLayer)); - } video_renderer_->Update(frame); }
diff --git a/src/starboard/raspi/shared/application_dispmanx.h b/src/starboard/raspi/shared/application_dispmanx.h index ba49ff5..d08c406 100644 --- a/src/starboard/raspi/shared/application_dispmanx.h +++ b/src/starboard/raspi/shared/application_dispmanx.h
@@ -49,7 +49,7 @@ void Initialize() SB_OVERRIDE; void Teardown() SB_OVERRIDE; void AcceptFrame(SbPlayer player, - const VideoFrame& frame, + const scoped_refptr<VideoFrame>& frame, int x, int y, int width,
diff --git a/src/starboard/raspi/shared/dispmanx_util.cc b/src/starboard/raspi/shared/dispmanx_util.cc index 88c7f52..f33a441 100644 --- a/src/starboard/raspi/shared/dispmanx_util.cc +++ b/src/starboard/raspi/shared/dispmanx_util.cc
@@ -23,6 +23,8 @@ namespace { +const int kElementChangeAttributesFlagSrcRect = 1 << 3; + class DispmanxAutoUpdate { public: DispmanxAutoUpdate() { @@ -52,10 +54,61 @@ } // namespace +DispmanxResource::DispmanxResource(VC_IMAGE_TYPE_T image_type, + uint32_t width, + uint32_t height, + uint32_t visible_width, + uint32_t visible_height) + : width_(width), + height_(height), + visible_width_(visible_width), + visible_height_(visible_height) { + static const uint32_t kMaxDimension = 1 << 16; + + SB_DCHECK(width_ > 0 && width_ < kMaxDimension); + SB_DCHECK(height_ > 0 && height_ < kMaxDimension); + SB_DCHECK(visible_width_ > 0 && visible_width_ < kMaxDimension); + SB_DCHECK(visible_height > 0 && visible_height < kMaxDimension); + SB_DCHECK(width_ >= visible_width_); + SB_DCHECK(height_ >= visible_height); + + uint32_t vc_image_ptr; + + handle_ = vc_dispmanx_resource_create( + image_type, visible_width_ | (width_ << 16), + visible_height | (height_ << 16), &vc_image_ptr); + SB_DCHECK(handle_ != DISPMANX_NO_HANDLE); +} + +void DispmanxYUV420Resource::WriteData(const void* data) { + SB_DCHECK(handle() != DISPMANX_NO_HANDLE); + + DispmanxRect dst_rect(0, 0, width(), height() * 3 / 2); + int32_t result = vc_dispmanx_resource_write_data( + handle(), VC_IMAGE_YUV420, width(), const_cast<void*>(data), &dst_rect); + SB_DCHECK(result == 0); +} + void DispmanxYUV420Resource::ClearWithBlack() { - scoped_array<uint8_t> data(new uint8_t[width_ * height_ * 3 / 2]); - SbMemorySet(data.get(), width_ * height_, 0); - SbMemorySet(data.get() + width_ * height_, width_ * height_ / 2, 0x80); + scoped_array<uint8_t> data(new uint8_t[width() * height() * 3 / 2]); + SbMemorySet(data.get(), width() * height(), 0); + SbMemorySet(data.get() + width() * height(), width() * height() / 2, 0x80); + WriteData(data.get()); +} + +void DispmanxRGB565Resource::WriteData(const void* data) { + SB_DCHECK(handle() != DISPMANX_NO_HANDLE); + + DispmanxRect dst_rect(0, 0, width(), height()); + int32_t result = + vc_dispmanx_resource_write_data(handle(), VC_IMAGE_RGB565, width() * 2, + const_cast<void*>(data), &dst_rect); + SB_DCHECK(result == 0); +} + +void DispmanxRGB565Resource::ClearWithBlack() { + scoped_array<uint8_t> data(new uint8_t[width() * height() * 2]); + SbMemorySet(data.get(), width() * height() * 2, 0); WriteData(data.get()); } @@ -78,26 +131,37 @@ SB_DCHECK(result == 0) << " result=" << result; } -void DispmanxVideoRenderer::Update(const VideoFrame& video_frame) { - if (video_frame.IsEndOfStream()) { - element_.reset(); - resource_.reset(); +void DispmanxElement::ChangeSource(const DispmanxResource& new_src) { + DispmanxAutoUpdate update; + vc_dispmanx_element_change_source(update.handle(), handle_, new_src.handle()); +} + +DispmanxVideoRenderer::DispmanxVideoRenderer(const DispmanxDisplay& display, + int32_t layer) + : black_frame_(256, 256, 256, 256) { + black_frame_.ClearWithBlack(); + element_.reset(new DispmanxElement(display, layer, DispmanxRect(), + black_frame_, DispmanxRect())); +} + +void DispmanxVideoRenderer::Update( + const scoped_refptr<VideoFrame>& video_frame) { + SB_DCHECK(video_frame); + + if (frame_ == video_frame) { return; } - if (!resource_ || resource_->width() != video_frame.width() || - resource_->height() != video_frame.height()) { - element_.reset(); - resource_.reset(); - DispmanxRect src_rect(0, 0, video_frame.width() << 16, - video_frame.height() << 16); - resource_.reset( - new DispmanxYUV420Resource(video_frame.width(), video_frame.height())); - element_.reset(new DispmanxElement(display_, layer_, DispmanxRect(), - *resource_, src_rect)); + if (video_frame->IsEndOfStream()) { + element_->ChangeSource(black_frame_); + frame_ = video_frame; + return; } - resource_->WriteData(video_frame.GetPlane(0).data); + DispmanxYUV420Resource* resource = + reinterpret_cast<DispmanxYUV420Resource*>(video_frame->native_texture()); + element_->ChangeSource(*resource); + frame_ = video_frame; } } // namespace shared
diff --git a/src/starboard/raspi/shared/dispmanx_util.h b/src/starboard/raspi/shared/dispmanx_util.h index c4b65f6..f051e86 100644 --- a/src/starboard/raspi/shared/dispmanx_util.h +++ b/src/starboard/raspi/shared/dispmanx_util.h
@@ -69,38 +69,57 @@ } DISPMANX_RESOURCE_HANDLE_T handle() const { return handle_; } + uint32_t visible_width() const { return visible_width_; } + uint32_t visible_height() const { return visible_height_; } uint32_t width() const { return width_; } uint32_t height() const { return height_; } protected: - DispmanxResource(VC_IMAGE_TYPE_T image_type, uint32_t width, uint32_t height) - : width_(width), height_(height) { - uint32_t vc_image_ptr; + DispmanxResource(VC_IMAGE_TYPE_T image_type, + uint32_t width, + uint32_t height, + uint32_t visible_width, + uint32_t visible_height); - handle_ = - vc_dispmanx_resource_create(image_type, width, height, &vc_image_ptr); - SB_DCHECK(handle_ != DISPMANX_NO_HANDLE); - } - + private: DISPMANX_RESOURCE_HANDLE_T handle_; uint32_t width_; uint32_t height_; + uint32_t visible_width_; + uint32_t visible_height_; SB_DISALLOW_COPY_AND_ASSIGN(DispmanxResource); }; class DispmanxYUV420Resource : public DispmanxResource { public: - DispmanxYUV420Resource(uint32_t width, uint32_t height) - : DispmanxResource(VC_IMAGE_YUV420, width, height) {} + DispmanxYUV420Resource(uint32_t width, + uint32_t height, + uint32_t visible_width, + uint32_t visible_height) + : DispmanxResource(VC_IMAGE_YUV420, + width, + height, + visible_width, + visible_height) {} - void WriteData(const void* data) { - SB_DCHECK(handle_ != DISPMANX_NO_HANDLE); - DispmanxRect dst_rect(0, 0, width(), height() * 3 / 2); - int32_t result = vc_dispmanx_resource_write_data( - handle_, VC_IMAGE_YUV420, width(), const_cast<void*>(data), &dst_rect); - SB_DCHECK(result == 0); - } + void WriteData(const void* data); + void ClearWithBlack(); +}; + +class DispmanxRGB565Resource : public DispmanxResource { + public: + DispmanxRGB565Resource(uint32_t width, + uint32_t height, + uint32_t visible_width, + uint32_t visible_height) + : DispmanxResource(VC_IMAGE_RGB565, + width, + height, + visible_width, + visible_height) {} + + void WriteData(const void* data); void ClearWithBlack(); }; @@ -114,6 +133,7 @@ ~DispmanxElement(); DISPMANX_ELEMENT_HANDLE_T handle() const { return handle_; } + void ChangeSource(const DispmanxResource& new_src); private: DISPMANX_ELEMENT_HANDLE_T handle_; @@ -124,16 +144,18 @@ class DispmanxVideoRenderer { public: typedef starboard::shared::starboard::player::VideoFrame VideoFrame; - DispmanxVideoRenderer(const DispmanxDisplay& display, int32_t layer) - : display_(display), layer_(layer) {} - void Update(const VideoFrame& video_frame); + DispmanxVideoRenderer(const DispmanxDisplay& display, int32_t layer); + + void Update(const scoped_refptr<VideoFrame>& video_frame); private: - const DispmanxDisplay& display_; - int32_t layer_; - scoped_ptr<DispmanxYUV420Resource> resource_; scoped_ptr<DispmanxElement> element_; + scoped_refptr<VideoFrame> frame_; + + // Used to fill the background with black if no video is playing so that the + // console does not show through. + DispmanxRGB565Resource black_frame_; SB_DISALLOW_COPY_AND_ASSIGN(DispmanxVideoRenderer); };
diff --git a/src/starboard/raspi/shared/open_max/open_max_component.cc b/src/starboard/raspi/shared/open_max/open_max_component.cc index eb05825..bb814f6c 100644 --- a/src/starboard/raspi/shared/open_max/open_max_component.cc +++ b/src/starboard/raspi/shared/open_max/open_max_component.cc
@@ -47,15 +47,13 @@ } // namespace -OpenMaxComponent::OpenMaxComponent(const char* name, size_t minimum_output_size) +OpenMaxComponent::OpenMaxComponent(const char* name) : condition_variable_(mutex_), - minimum_output_size_(minimum_output_size), handle_(NULL), input_port_(kInvalidPort), output_port_(kInvalidPort), output_setting_changed_(false), - output_buffer_(NULL), - output_buffer_filled_(false) { + output_port_enabled_(false) { InitializeOpenMax(); OMX_CALLBACKTYPE callbacks; @@ -99,18 +97,20 @@ SendCommandAndWaitForCompletion(OMX_CommandFlush, output_port_); SendCommand(OMX_CommandPortDisable, input_port_); - for (BufferHeaders::iterator iter = unused_buffers_.begin(); - iter != unused_buffers_.end(); ++iter) { - OMX_ERRORTYPE error = OMX_FreeBuffer(handle_, input_port_, *iter); + for (size_t i = 0; i < input_buffers_.size(); ++i) { + OMX_ERRORTYPE error = + OMX_FreeBuffer(handle_, input_port_, input_buffers_[i]); SB_DCHECK(error == OMX_ErrorNone); } WaitForCommandCompletion(); SendCommand(OMX_CommandPortDisable, output_port_); - if (output_buffer_) { - OMX_ERRORTYPE error = OMX_FreeBuffer(handle_, output_port_, output_buffer_); + for (size_t i = 0; i < output_buffers_.size(); ++i) { + OMX_ERRORTYPE error = + OMX_FreeBuffer(handle_, output_port_, output_buffers_[i]); SB_DCHECK(error == OMX_ErrorNone); } + output_buffers_.clear(); WaitForCommandCompletion(); SendCommandAndWaitForCompletion(OMX_CommandStateSet, OMX_StateLoaded); @@ -162,45 +162,34 @@ SB_DCHECK(error == OMX_ErrorNone); } -bool OpenMaxComponent::ReadVideoFrame(VideoFrame* frame) { +OMX_BUFFERHEADERTYPE* OpenMaxComponent::PeekNextOutputBuffer() { { ScopedLock scoped_lock(mutex_); - if (output_buffer_ && !output_buffer_filled_) { - return false; - } + if (!output_setting_changed_) { - return false; + return NULL; } } - SB_DCHECK(output_setting_changed_); - if (!output_buffer_) { - GetOutputPortParam(&output_port_definition_); - SB_DCHECK(output_port_definition_.format.video.eColorFormat == - OMX_COLOR_FormatYUV420PackedPlanar); - EnableOutputPortAndAllocateBuffer(); - return false; - } - if (output_buffer_->nFlags & OMX_BUFFERFLAG_EOS) { - *frame = VideoFrame(); - return true; + if (!output_port_enabled_) { + EnableOutputPortAndAllocateBuffer(); } - SbMediaTime timestamp = - ((output_buffer_->nTimeStamp.nHighPart * 0x100000000ull) + - output_buffer_->nTimeStamp.nLowPart) * - kSbMediaTimeSecond / kSbTimeSecond; - int width = output_port_definition_.format.video.nFrameWidth; - int height = output_port_definition_.format.video.nSliceHeight; - int pitch = output_port_definition_.format.video.nStride; - *frame = VideoFrame::CreateYV12Frame( - width, height, pitch, timestamp, output_buffer_->pBuffer, - output_buffer_->pBuffer + pitch * height, - output_buffer_->pBuffer + pitch * height * 5 / 4); - output_buffer_filled_ = false; - output_buffer_->nFilledLen = 0; - OMX_ERRORTYPE error = OMX_FillThisBuffer(handle_, output_buffer_); + + ScopedLock scoped_lock(mutex_); + return filled_output_buffers_.empty() ? NULL : filled_output_buffers_.front(); +} + +void OpenMaxComponent::DropNextOutputBuffer() { + OMX_BUFFERHEADERTYPE* buffer = NULL; + { + ScopedLock scoped_lock(mutex_); + SB_DCHECK(!filled_output_buffers_.empty()); + buffer = filled_output_buffers_.front(); + filled_output_buffers_.pop(); + } + buffer->nFilledLen = 0; + OMX_ERRORTYPE error = OMX_FillThisBuffer(handle_, buffer); SB_DCHECK(error == OMX_ErrorNone); - return true; } void OpenMaxComponent::SendCommand(OMX_COMMANDTYPE command, int param) { @@ -234,48 +223,68 @@ } void OpenMaxComponent::EnableInputPortAndAllocateBuffers() { - SB_DCHECK(unused_buffers_.empty()); + SB_DCHECK(input_buffers_.empty()); OMXParamPortDefinition port_definition; GetInputPortParam(&port_definition); + if (OnEnableInputPort(&port_definition)) { + SetPortParam(port_definition); + } SendCommand(OMX_CommandPortEnable, input_port_); - unused_buffers_.resize(port_definition.nBufferCountActual); - for (int i = 0; i != port_definition.nBufferCountActual; ++i) { - OMX_ERRORTYPE error = - OMX_AllocateBuffer(handle_, &unused_buffers_[i], input_port_, NULL, - port_definition.nBufferSize); + for (int i = 0; i < port_definition.nBufferCountActual; ++i) { + OMX_BUFFERHEADERTYPE* buffer; + OMX_ERRORTYPE error = OMX_AllocateBuffer(handle_, &buffer, input_port_, + NULL, port_definition.nBufferSize); SB_DCHECK(error == OMX_ErrorNone); + input_buffers_.push_back(buffer); + unused_input_buffers_.push(buffer); } WaitForCommandCompletion(); } void OpenMaxComponent::EnableOutputPortAndAllocateBuffer() { - if (output_buffer_ != NULL) { - return; + SB_DCHECK(!output_port_enabled_); + + GetOutputPortParam(&output_port_definition_); + if (OnEnableOutputPort(&output_port_definition_)) { + SetPortParam(output_port_definition_); } SendCommand(OMX_CommandPortEnable, output_port_); - OMX_ERRORTYPE error = OMX_AllocateBuffer( - handle_, &output_buffer_, output_port_, NULL, - std::max(output_port_definition_.nBufferSize, minimum_output_size_)); - SB_DCHECK(error == OMX_ErrorNone); + output_buffers_.reserve(output_port_definition_.nBufferCountActual); + for (int i = 0; i < output_port_definition_.nBufferCountActual; ++i) { + OMX_BUFFERHEADERTYPE* buffer; + OMX_ERRORTYPE error = + OMX_AllocateBuffer(handle_, &buffer, output_port_, NULL, + output_port_definition_.nBufferSize); + SB_DCHECK(error == OMX_ErrorNone); + output_buffers_.push_back(buffer); + } + WaitForCommandCompletion(); - error = OMX_FillThisBuffer(handle_, output_buffer_); - SB_DCHECK(error == OMX_ErrorNone); + output_port_enabled_ = true; + + for (size_t i = 0; i < output_buffers_.size(); ++i) { + output_buffers_[i]->nFilledLen = 0; + OMX_ERRORTYPE error = OMX_FillThisBuffer(handle_, output_buffers_[i]); + SB_DCHECK(error == OMX_ErrorNone); + } } OMX_BUFFERHEADERTYPE* OpenMaxComponent::GetUnusedInputBuffer() { for (;;) { - ScopedLock scoped_lock(mutex_); - if (!unused_buffers_.empty()) { - OMX_BUFFERHEADERTYPE* buffer_header = unused_buffers_.back(); - unused_buffers_.pop_back(); - return buffer_header; + { + ScopedLock scoped_lock(mutex_); + if (!unused_input_buffers_.empty()) { + OMX_BUFFERHEADERTYPE* buffer_header = unused_input_buffers_.front(); + unused_input_buffers_.pop(); + return buffer_header; + } } SbThreadSleep(kSbTimeMillisecond); } @@ -312,13 +321,12 @@ OMX_ERRORTYPE OpenMaxComponent::OnEmptyBufferDone( OMX_BUFFERHEADERTYPE* buffer) { ScopedLock scoped_lock(mutex_); - unused_buffers_.push_back(buffer); + unused_input_buffers_.push(buffer); } void OpenMaxComponent::OnFillBufferDone(OMX_BUFFERHEADERTYPE* buffer) { ScopedLock scoped_lock(mutex_); - SB_DCHECK(!output_buffer_filled_); - output_buffer_filled_ = true; + filled_output_buffers_.push(buffer); } // static
diff --git a/src/starboard/raspi/shared/open_max/open_max_component.h b/src/starboard/raspi/shared/open_max/open_max_component.h index 9085c1b..d9b5295 100644 --- a/src/starboard/raspi/shared/open_max/open_max_component.h +++ b/src/starboard/raspi/shared/open_max/open_max_component.h
@@ -22,13 +22,14 @@ #include <interface/vcos/vcos.h> #include <interface/vcos/vcos_logging.h> #include <interface/vmcs_host/vchost.h> + +#include <queue> #include <vector> #include "starboard/condition_variable.h" #include "starboard/log.h" #include "starboard/mutex.h" #include "starboard/shared/internal_only.h" -#include "starboard/shared/starboard/player/video_frame_internal.h" #include "starboard/time.h" namespace starboard { @@ -53,10 +54,8 @@ class OpenMaxComponent { public: - typedef starboard::shared::starboard::player::VideoFrame VideoFrame; - - explicit OpenMaxComponent(const char* name, size_t minimum_output_size = 0); - ~OpenMaxComponent(); + explicit OpenMaxComponent(const char* name); + virtual ~OpenMaxComponent(); void Start(); void Flush(); @@ -64,7 +63,8 @@ void WriteData(const void* data, size_t size, SbTime timestamp); void WriteEOS(); - bool ReadVideoFrame(VideoFrame* frame); + OMX_BUFFERHEADERTYPE* PeekNextOutputBuffer(); + void DropNextOutputBuffer(); template <typename ParamType> void GetInputPortParam(ParamType* param) const { @@ -94,8 +94,6 @@ } private: - typedef std::vector<OMX_BUFFERHEADERTYPE*> BufferHeaders; - struct EventDescription { OMX_EVENTTYPE event; OMX_U32 data1; @@ -105,6 +103,13 @@ typedef std::vector<EventDescription> EventDescriptions; + virtual bool OnEnableInputPort(OMXParamPortDefinition* port_definition) { + return false; + } + virtual bool OnEnableOutputPort(OMXParamPortDefinition* port_definition) { + return false; + } + void SendCommand(OMX_COMMANDTYPE command, int param); void WaitForCommandCompletion(); void SendCommandAndWaitForCompletion(OMX_COMMANDTYPE command, int param); @@ -134,16 +139,18 @@ Mutex mutex_; ConditionVariable condition_variable_; - const size_t minimum_output_size_; OMX_HANDLETYPE handle_; int input_port_; int output_port_; bool output_setting_changed_; EventDescriptions event_descriptions_; - BufferHeaders unused_buffers_; - OMX_BUFFERHEADERTYPE* output_buffer_; + std::vector<OMX_BUFFERHEADERTYPE*> input_buffers_; + std::queue<OMX_BUFFERHEADERTYPE*> unused_input_buffers_; + std::vector<OMX_BUFFERHEADERTYPE*> output_buffers_; + std::queue<OMX_BUFFERHEADERTYPE*> filled_output_buffers_; + OMXParamPortDefinition output_port_definition_; - bool output_buffer_filled_; + bool output_port_enabled_; }; } // namespace open_max
diff --git a/src/starboard/raspi/shared/open_max/open_max_video_decode_component.cc b/src/starboard/raspi/shared/open_max/open_max_video_decode_component.cc new file mode 100644 index 0000000..0520c36 --- /dev/null +++ b/src/starboard/raspi/shared/open_max/open_max_video_decode_component.cc
@@ -0,0 +1,165 @@ +// 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/raspi/shared/open_max/open_max_video_decode_component.h" + +#include <algorithm> + +#include "starboard/configuration.h" + +namespace starboard { +namespace raspi { +namespace shared { +namespace open_max { + +namespace { + +const char kVideoDecodeComponentName[] = "OMX.broadcom.video_decode"; +const size_t kResourcePoolSize = 12; +const size_t kOMXOutputBufferCount = 4; +const int kMaxFrameWidth = 1920; +const int kMaxFrameHeight = 1088; +const size_t kMaxVideoFrameSize = kMaxFrameWidth * kMaxFrameHeight * 3 / 2; + +} // namespace + +typedef OpenMaxVideoDecodeComponent::VideoFrame VideoFrame; + +VideoFrameResourcePool::VideoFrameResourcePool(size_t max_number_of_resources) + : max_number_of_resources_(max_number_of_resources), + number_of_resources_(0), + last_frame_height_(0) {} + +VideoFrameResourcePool::~VideoFrameResourcePool() { + for (ResourceMap::iterator iter = resource_map_.begin(); + iter != resource_map_.end(); ++iter) { + while (!iter->second.empty()) { + delete iter->second.front(); + iter->second.pop(); + --number_of_resources_; + } + } + SB_DCHECK(number_of_resources_ == 0) << number_of_resources_; +} + +DispmanxYUV420Resource* VideoFrameResourcePool::Alloc(int width, + int height, + int visible_width, + int visible_height) { + ScopedLock scoped_lock(mutex_); + + last_frame_height_ = height; + + ResourceMap::iterator iter = resource_map_.find(height); + if (iter != resource_map_.end() && !iter->second.empty()) { + DispmanxYUV420Resource* resource = iter->second.front(); + iter->second.pop(); + return resource; + } + + if (number_of_resources_ >= max_number_of_resources_) { + return NULL; + } + + ++number_of_resources_; + return new DispmanxYUV420Resource(width, height, visible_width, + visible_height); +} + +void VideoFrameResourcePool::Free(DispmanxYUV420Resource* resource) { + ScopedLock scoped_lock(mutex_); + if (resource->height() != last_frame_height_) { + // The video has adapted, free the resource as it won't be reused any soon. + delete resource; + --number_of_resources_; + return; + } + resource_map_[resource->height()].push(resource); +} + +// static +void VideoFrameResourcePool::DisposeDispmanxYUV420Resource( + void* context, + void* dispmanx_resource) { + SB_DCHECK(context != NULL); + SB_DCHECK(dispmanx_resource != NULL); + VideoFrameResourcePool* pool = + reinterpret_cast<VideoFrameResourcePool*>(context); + pool->Free(reinterpret_cast<DispmanxYUV420Resource*>(dispmanx_resource)); + pool->Release(); +} + +OpenMaxVideoDecodeComponent::OpenMaxVideoDecodeComponent() + : OpenMaxComponent(kVideoDecodeComponentName), + resource_pool_(new VideoFrameResourcePool(kResourcePoolSize)) {} + +scoped_refptr<VideoFrame> OpenMaxVideoDecodeComponent::ReadVideoFrame() { + if (OMX_BUFFERHEADERTYPE* buffer = PeekNextOutputBuffer()) { + if (scoped_refptr<VideoFrame> frame = CreateVideoFrame(buffer)) { + DropNextOutputBuffer(); + return frame; + } + } + return NULL; +} + +scoped_refptr<VideoFrame> OpenMaxVideoDecodeComponent::CreateVideoFrame( + OMX_BUFFERHEADERTYPE* buffer) { + scoped_refptr<VideoFrame> frame; + if (buffer->nFlags & OMX_BUFFERFLAG_EOS) { + frame = VideoFrame::CreateEOSFrame(); + } else { + OMX_VIDEO_PORTDEFINITIONTYPE& video_definition = + output_port_definition_.format.video; + DispmanxYUV420Resource* resource = resource_pool_->Alloc( + video_definition.nStride, video_definition.nSliceHeight, + video_definition.nFrameWidth, video_definition.nFrameHeight); + if (!resource) { + return NULL; + } + + resource->WriteData(buffer->pBuffer); + + SbMediaTime timestamp = ((buffer->nTimeStamp.nHighPart * 0x100000000ull) + + buffer->nTimeStamp.nLowPart) * + kSbMediaTimeSecond / kSbTimeSecond; + + resource_pool_->AddRef(); + frame = new VideoFrame( + video_definition.nFrameWidth, video_definition.nFrameHeight, timestamp, + resource, resource_pool_, + &VideoFrameResourcePool::DisposeDispmanxYUV420Resource); + } + return frame; +} + +bool OpenMaxVideoDecodeComponent::OnEnableOutputPort( + OMXParamPortDefinition* port_definition) { + SB_DCHECK(port_definition); + + output_port_definition_ = *port_definition; + SB_DCHECK(port_definition->format.video.eColorFormat == + OMX_COLOR_FormatYUV420PackedPlanar); + port_definition->format.video.eColorFormat = + OMX_COLOR_FormatYUV420PackedPlanar; + port_definition->nBufferCountActual = kOMXOutputBufferCount; + port_definition->nBufferSize = + std::max(port_definition->nBufferSize, kMaxVideoFrameSize); + return true; +} + +} // namespace open_max +} // namespace shared +} // namespace raspi +} // namespace starboard
diff --git a/src/starboard/raspi/shared/open_max/open_max_video_decode_component.h b/src/starboard/raspi/shared/open_max/open_max_video_decode_component.h new file mode 100644 index 0000000..94b9cda --- /dev/null +++ b/src/starboard/raspi/shared/open_max/open_max_video_decode_component.h
@@ -0,0 +1,84 @@ +// 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_RASPI_SHARED_OPEN_MAX_OPEN_MAX_VIDEO_DECODE_COMPONENT_H_ +#define STARBOARD_RASPI_SHARED_OPEN_MAX_OPEN_MAX_VIDEO_DECODE_COMPONENT_H_ + +#include <map> +#include <queue> + +#include "starboard/common/ref_counted.h" +#include "starboard/raspi/shared/dispmanx_util.h" +#include "starboard/raspi/shared/open_max/open_max_component.h" + +namespace starboard { +namespace raspi { +namespace shared { +namespace open_max { + +class VideoFrameResourcePool + : public RefCountedThreadSafe<VideoFrameResourcePool> { + public: + explicit VideoFrameResourcePool(size_t max_number_of_resources); + ~VideoFrameResourcePool(); + + DispmanxYUV420Resource* Alloc(int width, + int height, + int visible_width, + int visible_height); + void Free(DispmanxYUV420Resource* resource); + + static void DisposeDispmanxYUV420Resource(void* context, + void* dispmanx_resource); + + private: + typedef std::queue<DispmanxYUV420Resource*> ResourceQueue; + // Map frame height to resource handles. + typedef std::map<int, ResourceQueue> ResourceMap; + + const size_t max_number_of_resources_; + + Mutex mutex_; + size_t number_of_resources_; + int last_frame_height_; + ResourceMap resource_map_; +}; + +// Encapsulate a "OMX.broadcom.video_decode" component. Note that member +// functions of this class is expected to be called from ANY threads as this +// class works with the VideoDecoder filter, the OpenMAX component, and also +// manages the disposition of Dispmanx resource. +class OpenMaxVideoDecodeComponent : public OpenMaxComponent { + public: + typedef starboard::shared::starboard::player::VideoFrame VideoFrame; + + OpenMaxVideoDecodeComponent(); + + scoped_refptr<VideoFrame> ReadVideoFrame(); + + private: + scoped_refptr<VideoFrame> CreateVideoFrame(OMX_BUFFERHEADERTYPE* buffer); + + bool OnEnableOutputPort(OMXParamPortDefinition* port_definition) SB_OVERRIDE; + + scoped_refptr<VideoFrameResourcePool> resource_pool_; + OMXParamPortDefinition output_port_definition_; +}; + +} // namespace open_max +} // namespace shared +} // namespace raspi +} // namespace starboard + +#endif // STARBOARD_RASPI_SHARED_OPEN_MAX_OPEN_MAX_VIDEO_DECODE_COMPONENT_H_
diff --git a/src/starboard/raspi/shared/open_max/video_decoder.cc b/src/starboard/raspi/shared/open_max/video_decoder.cc index 702a9f8..a238db7 100644 --- a/src/starboard/raspi/shared/open_max/video_decoder.cc +++ b/src/starboard/raspi/shared/open_max/video_decoder.cc
@@ -23,17 +23,8 @@ using starboard::shared::starboard::player::VideoFrame; -namespace { - -const char kVideoDecodeComponentName[] = "OMX.broadcom.video_decode"; -const size_t kMaxVideoFrameSize = 1920 * 1088 * 3 / 2; - -} // namespace - VideoDecoder::VideoDecoder(SbMediaVideoCodec video_codec) - : component_(kVideoDecodeComponentName, kMaxVideoFrameSize), - host_(NULL), - stream_ended_(false) { + : host_(NULL), stream_ended_(false) { SB_DCHECK(video_codec == kSbMediaVideoCodecH264); OMXVideoParamPortFormat port_format; @@ -61,11 +52,11 @@ } component_.WriteData(input_buffer.data(), input_buffer.size(), input_buffer.pts() * kSbTimeSecond / kSbMediaTimeSecond); - - VideoFrame frame; - if (component_.ReadVideoFrame(&frame)) { - host_->OnDecoderStatusUpdate(kNeedMoreInput, &frame); + if (scoped_refptr<VideoFrame> frame = component_.ReadVideoFrame()) { + host_->OnDecoderStatusUpdate(kNeedMoreInput, frame); } else { + // Call the callback with NULL frame to ensure that the host know that more + // data is expected. host_->OnDecoderStatusUpdate(kNeedMoreInput, NULL); } }
diff --git a/src/starboard/raspi/shared/open_max/video_decoder.h b/src/starboard/raspi/shared/open_max/video_decoder.h index 92850da..de684af 100644 --- a/src/starboard/raspi/shared/open_max/video_decoder.h +++ b/src/starboard/raspi/shared/open_max/video_decoder.h
@@ -16,7 +16,7 @@ #define STARBOARD_RASPI_SHARED_OPEN_MAX_VIDEO_DECODER_H_ #include "starboard/media.h" -#include "starboard/raspi/shared/open_max/open_max_component.h" +#include "starboard/raspi/shared/open_max/open_max_video_decode_component.h" #include "starboard/shared/internal_only.h" #include "starboard/shared/starboard/player/filter/video_decoder_internal.h" @@ -39,7 +39,7 @@ void Reset() SB_OVERRIDE; private: - OpenMaxComponent component_; + OpenMaxVideoDecodeComponent component_; // These variables will be initialized inside ctor or SetHost() and will not // be changed during the life time of this class.
diff --git a/src/starboard/shared/directfb/blitter_destroy_swap_chain.cc b/src/starboard/shared/directfb/blitter_destroy_swap_chain.cc index ba9d317..2f9505b 100644 --- a/src/starboard/shared/directfb/blitter_destroy_swap_chain.cc +++ b/src/starboard/shared/directfb/blitter_destroy_swap_chain.cc
@@ -26,5 +26,7 @@ swap_chain->render_target.surface->Release(swap_chain->render_target.surface); + delete swap_chain; + return true; }
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc index 7b9efed..2e05ee8 100644 --- a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc +++ b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
@@ -197,8 +197,7 @@ packet.pts = 0; } while (DecodePacket(&packet)); - VideoFrame frame = VideoFrame::CreateEOSFrame(); - host_->OnDecoderStatusUpdate(kBufferFull, &frame); + host_->OnDecoderStatusUpdate(kBufferFull, VideoFrame::CreateEOSFrame()); } } } @@ -223,11 +222,11 @@ int pitch = AlignUp(av_frame_->width, kAlignment * 2); - VideoFrame frame = VideoFrame::CreateYV12Frame( + scoped_refptr<VideoFrame> frame = VideoFrame::CreateYV12Frame( av_frame_->width, av_frame_->height, pitch, codec_context_->reordered_opaque, av_frame_->data[0], av_frame_->data[1], av_frame_->data[2]); - host_->OnDecoderStatusUpdate(kBufferFull, &frame); + host_->OnDecoderStatusUpdate(kBufferFull, frame); return true; }
diff --git a/src/starboard/shared/posix/socket_receive_from.cc b/src/starboard/shared/posix/socket_receive_from.cc index c4819b6..ca0cb04 100644 --- a/src/starboard/shared/posix/socket_receive_from.cc +++ b/src/starboard/shared/posix/socket_receive_from.cc
@@ -27,11 +27,7 @@ char* out_data, int data_size, SbSocketAddress* out_source) { -#if defined(MSG_NOSIGNAL) - const int kRecvFlags = MSG_NOSIGNAL; -#else const int kRecvFlags = 0; -#endif if (!SbSocketIsValid(socket)) { errno = EBADF;
diff --git a/src/starboard/shared/signal/crash_signals.cc b/src/starboard/shared/signal/crash_signals.cc index 0d74011..78b3ab2 100644 --- a/src/starboard/shared/signal/crash_signals.cc +++ b/src/starboard/shared/signal/crash_signals.cc
@@ -32,7 +32,7 @@ }; const int kStopSignalsToTrap[] = { - SIGTERM, SIGINT, SIGHUP, + SIGHUP, }; void Crash(int signal_id) {
diff --git a/src/starboard/shared/signal/crash_signals_sigaction.cc b/src/starboard/shared/signal/crash_signals_sigaction.cc index 5273ab1..da318a8 100644 --- a/src/starboard/shared/signal/crash_signals_sigaction.cc +++ b/src/starboard/shared/signal/crash_signals_sigaction.cc
@@ -32,7 +32,7 @@ }; const int kStopSignalsToTrap[] = { - SIGTERM, SIGINT, SIGHUP, + SIGHUP, }; void SetSignalHandler(int signal_id, SignalHandlerFunction handler) {
diff --git a/src/starboard/shared/signal/suspend_signals.cc b/src/starboard/shared/signal/suspend_signals.cc index 6bb42d8..4048a3b 100644 --- a/src/starboard/shared/signal/suspend_signals.cc +++ b/src/starboard/shared/signal/suspend_signals.cc
@@ -15,6 +15,7 @@ #include "starboard/shared/signal/suspend_signals.h" #include <signal.h> +#include <sys/socket.h> #include "starboard/configuration.h" #include "starboard/log.h" @@ -71,19 +72,34 @@ } // namespace +#if !defined(MSG_NOSIGNAL) && defined(SO_NOSIGPIPE) +// See "#if !defined(MSG_NOSIGNAL)" below. +// OS X, which we do not build for today, has another mechanism which +// should be used. +#error On this platform, please use SO_NOSIGPIPE and leave the SIGPIPE \ + handler at default. +#endif + void InstallSuspendSignalHandlers() { SetSignalHandler(SIGTSTP, &Suspend); UnblockSignal(SIGTSTP); SetSignalHandler(SIGCONT, &Resume); - // We might receive SIGPIPE after resuming. We should not terminate. +#if !defined(MSG_NOSIGNAL) + // By default in POSIX, sending to a closed socket causes a SIGPIPE + // If we cannot disable that behavior, we must ignore SIGPIPE. + // Ignoring SIGPIPE means cases that use pipes to redirect the stdio + // log messages may behave in surprising ways, so it's not desirable. SetSignalHandler(SIGPIPE, &Ignore); +#endif } void UninstallSuspendSignalHandlers() { SetSignalHandler(SIGCONT, SIG_DFL); SetSignalHandler(SIGTSTP, SIG_DFL); +#if !defined(MSG_NOSIGNAL) SetSignalHandler(SIGPIPE, SIG_DFL); +#endif } } // namespace signal
diff --git a/src/starboard/shared/starboard/application.cc b/src/starboard/shared/starboard/application.cc index 96efbdb..4f2e850 100644 --- a/src/starboard/shared/starboard/application.cc +++ b/src/starboard/shared/starboard/application.cc
@@ -130,7 +130,7 @@ #if SB_HAS(PLAYER) && SB_IS(PLAYER_PUNCHED_OUT) void Application::HandleFrame(SbPlayer player, - const VideoFrame& frame, + const scoped_refptr<VideoFrame>& frame, int x, int y, int width,
diff --git a/src/starboard/shared/starboard/application.h b/src/starboard/shared/starboard/application.h index f8609ce..4387bed 100644 --- a/src/starboard/shared/starboard/application.h +++ b/src/starboard/shared/starboard/application.h
@@ -202,7 +202,7 @@ // used when the application needs to composite video frames with punch-out // video manually (should be rare). Will be called from an external thread. void HandleFrame(SbPlayer player, - const VideoFrame& frame, + const scoped_refptr<VideoFrame>& frame, int x, int y, int width, @@ -224,7 +224,7 @@ // Subclasses may override this method to accept video frames from the media // system. Will be called from an external thread. virtual void AcceptFrame(SbPlayer player, - const VideoFrame& frame, + const scoped_refptr<VideoFrame>& frame, int x, int y, int width,
diff --git a/src/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc b/src/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc index 3317806..8648663 100644 --- a/src/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc +++ b/src/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc
@@ -248,9 +248,11 @@ } } - return SbBlitterBlitRectsToRects(context, source_surface, src_rects, - dst_rects, num_tiles); + bool result = SbBlitterBlitRectsToRects(context, source_surface, src_rects, + dst_rects, num_tiles); delete[] src_rects; delete[] dst_rects; + + return result; }
diff --git a/src/starboard/shared/starboard/file_storage/storage_internal.h b/src/starboard/shared/starboard/file_storage/storage_internal.h index ea322b8..6bb3362 100644 --- a/src/starboard/shared/starboard/file_storage/storage_internal.h +++ b/src/starboard/shared/starboard/file_storage/storage_internal.h
@@ -33,9 +33,9 @@ namespace shared { namespace starboard { // Gets the path to the storage file for the given user. -SB_C_INLINE bool GetUserStorageFilePath(SbUser user, - char* out_path, - int path_size) { +static SB_C_INLINE bool GetUserStorageFilePath(SbUser user, + char* out_path, + int path_size) { bool success = SbUserGetProperty(user, kSbUserPropertyHomeDirectory, out_path, path_size); if (!success) {
diff --git a/src/starboard/shared/starboard/localized_strings.cc b/src/starboard/shared/starboard/localized_strings.cc index 2639c53..0f802e6 100644 --- a/src/starboard/shared/starboard/localized_strings.cc +++ b/src/starboard/shared/starboard/localized_strings.cc
@@ -116,7 +116,7 @@ return false; } SB_DCHECK(file_contents.length() > 0); - SB_DCHECK(file_contents.back() == '\n'); + SB_DCHECK(file_contents[file_contents.length() - 1] == '\n'); // Each line of the file corresponds to one message (key/value). size_t pos = 0;
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc index 54477cf..b73cbb2 100644 --- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc +++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
@@ -210,7 +210,7 @@ (*player_worker_.*update_player_state_cb_)(kSbPlayerStateEndOfStream); } - const VideoFrame& frame = + scoped_refptr<VideoFrame> frame = video_renderer_->GetCurrentFrame(audio_renderer_->GetCurrentTime()); #if SB_IS(PLAYER_PUNCHED_OUT) @@ -230,8 +230,8 @@ #if SB_IS(PLAYER_PUNCHED_OUT) // Clear the video frame as we terminate. - shared::starboard::Application::Get()->HandleFrame(player_, VideoFrame(), 0, - 0, 0, 0); + shared::starboard::Application::Get()->HandleFrame( + player_, VideoFrame::CreateEOSFrame(), 0, 0, 0, 0); #endif // SB_IS(PLAYER_PUNCHED_OUT) }
diff --git a/src/starboard/shared/starboard/player/filter/video_decoder_internal.h b/src/starboard/shared/starboard/player/filter/video_decoder_internal.h index fd32c9f..e55c685 100644 --- a/src/starboard/shared/starboard/player/filter/video_decoder_internal.h +++ b/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
@@ -37,7 +37,9 @@ // user should only call WriteInputFrame() when |status| is kNeedMoreInput // or when the instance is just created. Also note that calling Reset() or // dtor from this callback will result in deadlock. - virtual void OnDecoderStatusUpdate(Status status, VideoFrame* frame) = 0; + virtual void OnDecoderStatusUpdate( + Status status, + const scoped_refptr<VideoFrame>& frame) = 0; protected: ~Host() {}
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc b/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc index 65ee800..35b6bf0 100644 --- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc +++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
@@ -79,7 +79,8 @@ frames_.clear(); } -const VideoFrame& VideoRenderer::GetCurrentFrame(SbMediaTime media_time) { +scoped_refptr<VideoFrame> VideoRenderer::GetCurrentFrame( + SbMediaTime media_time) { SB_DCHECK(thread_checker_.CalledOnValidThread()); if (frames_.empty()) { @@ -87,7 +88,7 @@ } // Remove any frames with timestamps earlier than |media_time|, but always // keep at least one of the frames. - while (frames_.size() > 1 && frames_.front().pts() < media_time) { + while (frames_.size() > 1 && frames_.front()->pts() < media_time) { frames_.pop_front(); } @@ -101,6 +102,7 @@ bool VideoRenderer::CanAcceptMoreData() const { SB_DCHECK(thread_checker_.CalledOnValidThread()); + ScopedLock lock(mutex_); return frames_.size() < kMaxCachedFrames && !end_of_stream_written_ && need_more_input_; } @@ -110,8 +112,9 @@ return seeking_; } -void VideoRenderer::OnDecoderStatusUpdate(VideoDecoder::Status status, - VideoFrame* frame) { +void VideoRenderer::OnDecoderStatusUpdate( + VideoDecoder::Status status, + const scoped_refptr<VideoFrame>& frame) { ScopedLock lock(mutex_); if (frame) { @@ -124,7 +127,7 @@ } } if (!frame_too_early) { - frames_.push_back(*frame); + frames_.push_back(frame); } if (seeking_ && frames_.size() >= kPrerollFrames) {
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h index 8450e59..6cc4cad 100644 --- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h +++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
@@ -44,7 +44,7 @@ void Seek(SbMediaTime seek_to_pts); - const VideoFrame& GetCurrentFrame(SbMediaTime media_time); + scoped_refptr<VideoFrame> GetCurrentFrame(SbMediaTime media_time); bool IsEndOfStreamWritten() const { return end_of_stream_written_; } bool IsEndOfStreamPlayed() const; @@ -52,7 +52,7 @@ bool IsSeekingInProgress() const; private: - typedef std::list<VideoFrame> Frames; + typedef std::list<scoped_refptr<VideoFrame> > Frames; // Preroll considered finished after either kPrerollFrames is cached or EOS // is reached. @@ -65,7 +65,8 @@ // VideoDecoder::Host method. void OnDecoderStatusUpdate(VideoDecoder::Status status, - VideoFrame* frame) SB_OVERRIDE; + const scoped_refptr<VideoFrame>& frame) + SB_OVERRIDE; ThreadChecker thread_checker_; ::starboard::Mutex mutex_; @@ -77,7 +78,7 @@ // should still display the last frame it is rendering. This frame will be // kept inside |seeking_frame_|. It is an empty/black frame before the video // is started. - VideoFrame seeking_frame_; + scoped_refptr<VideoFrame> seeking_frame_; SbMediaTime seeking_to_pts_; bool end_of_stream_written_;
diff --git a/src/starboard/shared/starboard/player/video_frame_internal.cc b/src/starboard/shared/starboard/player/video_frame_internal.cc index 793066d..7bee2c4 100644 --- a/src/starboard/shared/starboard/player/video_frame_internal.cc +++ b/src/starboard/shared/starboard/player/video_frame_internal.cc
@@ -73,53 +73,76 @@ } // namespace -VideoFrame::VideoFrame(const VideoFrame& that) { - *this = that; +VideoFrame::VideoFrame() { + InitializeToInvalidFrame(); } -VideoFrame& VideoFrame::operator=(const VideoFrame& that) { - this->format_ = that.format_; +VideoFrame::VideoFrame(int width, + int height, + SbMediaTime pts, + void* native_texture, + void* native_texture_context, + FreeNativeTextureFunc free_native_texture_func) { + SB_DCHECK(native_texture != NULL); + SB_DCHECK(free_native_texture_func != NULL); - this->pts_ = that.pts_; - this->planes_ = that.planes_; - this->pixel_buffer_ = that.pixel_buffer_; + InitializeToInvalidFrame(); - for (int i = 0; i < GetPlaneCount(); ++i) { - const uint8_t* data = that.GetPlane(i).data; - const uint8_t* base = &that.pixel_buffer_[0]; - ptrdiff_t offset = data - base; - SB_DCHECK(offset >= 0); - SB_DCHECK(offset < static_cast<ptrdiff_t>(that.pixel_buffer_.size())); - planes_[i].data = &pixel_buffer_[0] + offset; + format_ = kNativeTexture; + width_ = width; + height_ = height; + pts_ = pts; + native_texture_ = native_texture; + native_texture_context_ = native_texture_context; + free_native_texture_func_ = free_native_texture_func; +} + +VideoFrame::~VideoFrame() { + if (format_ == kNativeTexture) { + free_native_texture_func_(native_texture_context_, native_texture_); } +} - return *this; +int VideoFrame::GetPlaneCount() const { + SB_DCHECK(format_ != kInvalid); + SB_DCHECK(format_ != kNativeTexture); + + return static_cast<int>(planes_.size()); } const VideoFrame::Plane& VideoFrame::GetPlane(int index) const { + SB_DCHECK(format_ != kInvalid); + SB_DCHECK(format_ != kNativeTexture); SB_DCHECK(index >= 0 && index < GetPlaneCount()) << "Invalid index: " << index; return planes_[index]; } -VideoFrame VideoFrame::ConvertTo(Format target_format) const { +void* VideoFrame::native_texture() const { + SB_DCHECK(format_ == kNativeTexture); + return native_texture_; +} + +scoped_refptr<VideoFrame> VideoFrame::ConvertTo(Format target_format) const { SB_DCHECK(format_ == kYV12); SB_DCHECK(target_format == kBGRA32); EnsureYUVToRGBLookupTableInitialized(); - VideoFrame target_frame; + scoped_refptr<VideoFrame> target_frame(new VideoFrame); - target_frame.format_ = target_format; - target_frame.pts_ = pts_; - target_frame.pixel_buffer_.resize(width() * height() * 4); - target_frame.planes_.push_back( - Plane(width(), height(), width() * 4, &target_frame.pixel_buffer_[0])); + target_frame->format_ = target_format; + target_frame->width_ = width(); + target_frame->height_ = height(); + target_frame->pts_ = pts_; + target_frame->pixel_buffer_.reset(new uint8_t[width() * height() * 4]); + target_frame->planes_.push_back( + Plane(width(), height(), width() * 4, target_frame->pixel_buffer_.get())); const uint8_t* y_data = GetPlane(0).data; const uint8_t* u_data = GetPlane(1).data; const uint8_t* v_data = GetPlane(2).data; - uint8_t* bgra_data = &target_frame.pixel_buffer_[0]; + uint8_t* bgra_data = target_frame->pixel_buffer_.get(); int height = this->height(); int width = this->width(); @@ -158,21 +181,23 @@ } // static -VideoFrame VideoFrame::CreateEOSFrame() { - return VideoFrame(); +scoped_refptr<VideoFrame> VideoFrame::CreateEOSFrame() { + return new VideoFrame; } // static -VideoFrame VideoFrame::CreateYV12Frame(int width, - int height, - int pitch_in_bytes, - SbMediaTime pts, - const uint8_t* y, - const uint8_t* u, - const uint8_t* v) { - VideoFrame frame; - frame.format_ = kYV12; - frame.pts_ = pts; +scoped_refptr<VideoFrame> VideoFrame::CreateYV12Frame(int width, + int height, + int pitch_in_bytes, + SbMediaTime pts, + const uint8_t* y, + const uint8_t* u, + const uint8_t* v) { + scoped_refptr<VideoFrame> frame(new VideoFrame); + frame->format_ = kYV12; + frame->width_ = width; + frame->height_ = height; + frame->pts_ = pts; // U/V planes generally have half resolution of the Y plane. However, in the // extreme case that any dimension of Y plane is odd, we want to have an @@ -183,26 +208,38 @@ int y_plane_size_in_bytes = height * pitch_in_bytes; int uv_plane_size_in_bytes = uv_height * uv_pitch_in_bytes; - frame.pixel_buffer_.reserve(y_plane_size_in_bytes + - uv_plane_size_in_bytes * 2); - frame.pixel_buffer_.assign(y, y + y_plane_size_in_bytes); - frame.pixel_buffer_.insert(frame.pixel_buffer_.end(), u, - u + uv_plane_size_in_bytes); - frame.pixel_buffer_.insert(frame.pixel_buffer_.end(), v, - v + uv_plane_size_in_bytes); + frame->pixel_buffer_.reset( + new uint8_t[y_plane_size_in_bytes + uv_plane_size_in_bytes * 2]); + SbMemoryCopy(frame->pixel_buffer_.get(), y, y_plane_size_in_bytes); + SbMemoryCopy(frame->pixel_buffer_.get() + y_plane_size_in_bytes, u, + uv_plane_size_in_bytes); + SbMemoryCopy(frame->pixel_buffer_.get() + y_plane_size_in_bytes + + uv_plane_size_in_bytes, + v, uv_plane_size_in_bytes); - frame.planes_.push_back( - Plane(width, height, pitch_in_bytes, &frame.pixel_buffer_[0])); - frame.planes_.push_back( + frame->planes_.push_back( + Plane(width, height, pitch_in_bytes, frame->pixel_buffer_.get())); + frame->planes_.push_back( Plane(uv_width, uv_height, uv_pitch_in_bytes, - &frame.pixel_buffer_[0] + y_plane_size_in_bytes)); - frame.planes_.push_back(Plane(uv_width, uv_height, uv_pitch_in_bytes, - &frame.pixel_buffer_[0] + - y_plane_size_in_bytes + - uv_plane_size_in_bytes)); + frame->pixel_buffer_.get() + y_plane_size_in_bytes)); + frame->planes_.push_back(Plane(uv_width, uv_height, uv_pitch_in_bytes, + frame->pixel_buffer_.get() + + y_plane_size_in_bytes + + uv_plane_size_in_bytes)); return frame; } +void VideoFrame::InitializeToInvalidFrame() { + format_ = kInvalid; + width_ = 0; + height_ = 0; + + pts_ = 0; + native_texture_ = NULL; + native_texture_context_ = NULL; + free_native_texture_func_ = NULL; +} + } // namespace player } // namespace starboard } // namespace shared
diff --git a/src/starboard/shared/starboard/player/video_frame_internal.h b/src/starboard/shared/starboard/player/video_frame_internal.h index 745ec31..c956e90 100644 --- a/src/starboard/shared/starboard/player/video_frame_internal.h +++ b/src/starboard/shared/starboard/player/video_frame_internal.h
@@ -17,6 +17,9 @@ #include <vector> +#include "starboard/common/ref_counted.h" +#include "starboard/common/scoped_ptr.h" +#include "starboard/configuration.h" #include "starboard/media.h" #include "starboard/shared/internal_only.h" @@ -26,10 +29,12 @@ namespace player { // A video frame produced by a video decoder. -class VideoFrame { +class VideoFrame : public RefCountedThreadSafe<VideoFrame> { public: + typedef void (*FreeNativeTextureFunc)(void* context, void* textue); + enum Format { - kInvalid, + kInvalid, // A VideoFrame in this format can be used to indicate EOS. // This is the native format supported by XComposite (PictStandardARGB32 // with bytes swapped). Remove this once we are able to pass out frames // as YV12 textures. @@ -50,37 +55,55 @@ const uint8_t* data; }; - VideoFrame() : format_(kInvalid) {} - VideoFrame(const VideoFrame& that); - - VideoFrame& operator=(const VideoFrame& that); + VideoFrame(); // Create an EOS frame. + VideoFrame(int width, + int height, + SbMediaTime pts, + void* native_texture, + void* native_texture_context, + FreeNativeTextureFunc free_native_texture_func); + ~VideoFrame(); Format format() const { return format_; } - int width() const { return GetPlaneCount() == 0 ? 0 : GetPlane(0).width; } - int height() const { return GetPlaneCount() == 0 ? 0 : GetPlane(0).height; } - bool IsEndOfStream() const { return format_ == kInvalid; } SbMediaTime pts() const { return pts_; } - int GetPlaneCount() const { return static_cast<int>(planes_.size()); } + int width() const { return width_; } + int height() const { return height_; } + + int GetPlaneCount() const; const Plane& GetPlane(int index) const; - VideoFrame ConvertTo(Format target_format) const; + void* native_texture() const; - static VideoFrame CreateEOSFrame(); - static VideoFrame CreateYV12Frame(int width, - int height, - int pitch_in_bytes, - SbMediaTime pts, - const uint8_t* y, - const uint8_t* u, - const uint8_t* v); + scoped_refptr<VideoFrame> ConvertTo(Format target_format) const; + + static scoped_refptr<VideoFrame> CreateEOSFrame(); + static scoped_refptr<VideoFrame> CreateYV12Frame(int width, + int height, + int pitch_in_bytes, + SbMediaTime pts, + const uint8_t* y, + const uint8_t* u, + const uint8_t* v); private: - Format format_; + void InitializeToInvalidFrame(); + Format format_; + int width_; + int height_; SbMediaTime pts_; + + // The following two variables are valid when the frame contains pixel data. std::vector<Plane> planes_; - std::vector<uint8_t> pixel_buffer_; + scoped_array<uint8_t> pixel_buffer_; + + // The following three variables are valid when |format_| is `kNativeTexture`. + void* native_texture_; + void* native_texture_context_; + FreeNativeTextureFunc free_native_texture_func_; + + SB_DISALLOW_COPY_AND_ASSIGN(VideoFrame); }; } // namespace player
diff --git a/src/starboard/shared/x11/application_x11.cc b/src/starboard/shared/x11/application_x11.cc index 1457e73..797c807 100644 --- a/src/starboard/shared/x11/application_x11.cc +++ b/src/starboard/shared/x11/application_x11.cc
@@ -679,7 +679,7 @@ ScopedLock lock(frame_mutex_); if (frame_written_) { // Clear the old frame, now that we are done with it. - frame_infos_[frame_read_index_].frame = VideoFrame(); + frame_infos_[frame_read_index_].frame = NULL; // Increment the index to the next frame, which has been written. frame_read_index_ = (frame_read_index_ + 1) % kNumFrames; @@ -692,12 +692,12 @@ } FrameInfo& frame_info = frame_infos_[frame_read_index_]; - if (!frame_info.frame.IsEndOfStream() && - frame_info.frame.format() != VideoFrame::kBGRA32) { - frame_info.frame = frame_info.frame.ConvertTo(VideoFrame::kBGRA32); + if (frame_info.frame && !frame_info.frame->IsEndOfStream() && + frame_info.frame->format() != VideoFrame::kBGRA32) { + frame_info.frame = frame_info.frame->ConvertTo(VideoFrame::kBGRA32); } window->Composite(frame_info.x, frame_info.y, frame_info.width, - frame_info.height, &frame_info.frame); + frame_info.height, frame_info.frame); } } composite_event_id_ = @@ -705,7 +705,7 @@ } void ApplicationX11::AcceptFrame(SbPlayer player, - const VideoFrame& frame, + const scoped_refptr<VideoFrame>& frame, int x, int y, int width,
diff --git a/src/starboard/shared/x11/application_x11.h b/src/starboard/shared/x11/application_x11.h index 8bd9940..efe2a24 100644 --- a/src/starboard/shared/x11/application_x11.h +++ b/src/starboard/shared/x11/application_x11.h
@@ -49,7 +49,7 @@ protected: void AcceptFrame(SbPlayer player, - const shared::starboard::player::VideoFrame& frame, + const scoped_refptr<VideoFrame>& frame, int x, int y, int width, @@ -71,7 +71,7 @@ #if SB_IS(PLAYER_PUNCHED_OUT) struct FrameInfo { - shared::starboard::player::VideoFrame frame; + scoped_refptr<VideoFrame> frame; int x; int y; int width;
diff --git a/src/starboard/shared/x11/window_internal.cc b/src/starboard/shared/x11/window_internal.cc index b17082a..70daeb3 100644 --- a/src/starboard/shared/x11/window_internal.cc +++ b/src/starboard/shared/x11/window_internal.cc
@@ -30,8 +30,6 @@ #include <X11/extensions/Xrender.h> #endif // SB_IS(PLAYER_PUNCHED_OUT) -using starboard::shared::starboard::player::VideoFrame; - namespace { const int kWindowWidth = 1920; @@ -148,11 +146,12 @@ } #if SB_IS(PLAYER_PUNCHED_OUT) -void SbWindowPrivate::Composite(int bounds_x, - int bounds_y, - int bounds_width, - int bounds_height, - VideoFrame* frame) { +void SbWindowPrivate::Composite( + int bounds_x, + int bounds_y, + int bounds_width, + int bounds_height, + const starboard::scoped_refptr<VideoFrame>& frame) { XSynchronize(display, True); XWindowAttributes window_attributes; XGetWindowAttributes(display, window, &window_attributes);
diff --git a/src/starboard/shared/x11/window_internal.h b/src/starboard/shared/x11/window_internal.h index 7c55cb3..e96ffdc 100644 --- a/src/starboard/shared/x11/window_internal.h +++ b/src/starboard/shared/x11/window_internal.h
@@ -33,6 +33,8 @@ Window window; #if SB_IS(PLAYER_PUNCHED_OUT) + typedef ::starboard::shared::starboard::player::VideoFrame VideoFrame; + // Composites graphics and the given video frame video for this window. In // PLAYER_PUNCHED_OUT mode, this is the only way any graphics or video is // presented in the window. The video frame will be rendered according to @@ -41,7 +43,7 @@ int bounds_y, int bounds_width, int bounds_height, - ::starboard::shared::starboard::player::VideoFrame* frame); + const starboard::scoped_refptr<VideoFrame>& frame); // The cached XRender Picture that represents the window that is the // destination of the composition.
diff --git a/src/starboard/thread.h b/src/starboard/thread.h index d2138e0..f642f28 100644 --- a/src/starboard/thread.h +++ b/src/starboard/thread.h
@@ -255,7 +255,7 @@ // Returns whether |thread| is the current thread. // // |thread|: The thread to check. -SB_C_INLINE bool SbThreadIsCurrent(SbThread thread) { +static SB_C_INLINE bool SbThreadIsCurrent(SbThread thread) { return SbThreadGetCurrent() == thread; }